1 /*
2  *
3  *  Copyright (C) 2016-2018, Open Connections GmbH
4  *  All rights reserved.  See COPYRIGHT file for details.
5  *
6  *  This software and supporting documentation are maintained by
7  *
8  *    OFFIS e.V.
9  *    R&D Division Health
10  *    Escherweg 2
11  *    D-26121 Oldenburg, Germany
12  *
13  *
14  *  Module:  dcmtract
15  *
16  *  Author:  Michael Onken
17  *
18  *  Purpose: Statistics from a Tractography Results IOD
19  *
20  */
21 #include "dcmtk/config/osconfig.h"
22 #include "dcmtk/dcmdata/dcuid.h"
23 #include "dcmtk/dcmiod/iodutil.h"
24 #include "dcmtk/dcmtract/trcstatistic.h"
25 
26 
27 // ------------------------------ class TrcTStatistic --------------------------
28 
29 // default constructor (protected, instance creation via create() function)
TrcStatistic()30 TrcStatistic::TrcStatistic()
31 : IODComponent(),
32   m_Type(),
33   m_TypeModifier(),
34   m_Units(),
35   m_Values()
36 {
37   // This is an abstract class so it is enough to call resetRules() is called
38   // from derived classes
39 }
40 
41 
resetRules()42 void TrcStatistic::resetRules()
43 {
44   // Set rules for the attributes within this component
45   getRules()->addRule(new IODRule(DCM_ConceptNameCodeSequence, "1","1",getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
46   getRules()->addRule(new IODRule(DCM_ModifierCodeSequence, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
47   getRules()->addRule(new IODRule(DCM_MeasurementUnitsCodeSequence, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
48 }
49 
50 
read(DcmItem & source,const OFBool clearOldData)51 OFCondition TrcStatistic::read(DcmItem& source,
52                                const OFBool clearOldData)
53 {
54   if (clearOldData)
55     this->clearData();
56   // Read as much as possible. In order to return success at minimum the tracks
57   // must be readable.
58   IODComponent::read(source, OFFalse /* we cleared data before */);
59   DcmIODUtil::readSingleItem(source, DCM_ConceptNameCodeSequence, m_Type, getRules()->getByTag(DCM_ConceptNameCodeSequence));
60   DcmIODUtil::readSingleItem(source, DCM_MeasurementUnitsCodeSequence, m_Units, getRules()->getByTag(DCM_MeasurementUnitsCodeSequence));
61   DcmIODUtil::readSingleItem(source, DCM_ModifierCodeSequence, m_TypeModifier, getRules()->getByTag(DCM_ModifierCodeSequence));
62   return EC_Normal;
63 }
64 
65 
write(DcmItem & destination)66 OFCondition TrcStatistic::write(DcmItem& destination)
67 {
68   OFCondition result;
69   DcmIODUtil::writeSingleItem(result, DCM_ConceptNameCodeSequence, m_Type, getData(), getRules()->getByTag(DCM_ConceptNameCodeSequence));
70   DcmIODUtil::writeSingleItem(result, DCM_MeasurementUnitsCodeSequence, m_Units, getData(), getRules()->getByTag(DCM_MeasurementUnitsCodeSequence));
71   DcmIODUtil::writeSingleItem(result, DCM_ModifierCodeSequence, m_TypeModifier, getData(), getRules()->getByTag(DCM_ModifierCodeSequence));
72   if (result.good()) result = IODComponent::write(destination);
73   return result;
74 }
75 
76 
clearData()77 void TrcStatistic::clearData()
78 {
79   m_Type.clearData();
80   m_Units.clearData();
81   m_TypeModifier.clearData();
82   IODComponent::clearData();
83 }
84 
get(CodeSequenceMacro & typeCode,CodeSequenceMacro & typeModifierCode,CodeSequenceMacro & unitsCode)85 OFCondition TrcStatistic::get(CodeSequenceMacro& typeCode,
86                               CodeSequenceMacro& typeModifierCode,
87                               CodeSequenceMacro& unitsCode)
88 {
89   typeCode = m_Type;
90   typeModifierCode = m_TypeModifier;
91   unitsCode = m_Units;
92   return EC_Normal;
93 }
94 
95 
setCommon(const CodeSequenceMacro & typeCode,const CodeSequenceMacro & typeModifierCode,const CodeSequenceMacro & unitsCode)96 OFCondition TrcStatistic::setCommon(const CodeSequenceMacro& typeCode,
97                                     const CodeSequenceMacro& typeModifierCode,
98                                     const CodeSequenceMacro& unitsCode)
99 {
100   OFCondition result;
101   result = OFconst_cast(CodeSequenceMacro*, &typeCode)->check(OFTrue /* quiet */);
102   if (result.good())
103   {
104     m_Type = typeCode;
105   }
106   if (result.good())
107   {
108     result = OFconst_cast(CodeSequenceMacro*, &typeModifierCode)->check(OFTrue /* quiet */);
109     if (result.good())
110     {
111       m_TypeModifier = typeModifierCode;
112     }
113   }
114   if (result.good())
115   {
116     result = OFconst_cast(CodeSequenceMacro*, &unitsCode)->check(OFTrue /* quiet */);
117     if (result.good())
118     {
119       m_Units = unitsCode;
120     }
121   }
122   return result;
123 }
124 
125 
~TrcStatistic()126 TrcStatistic::~TrcStatistic()
127 {
128   // nothing to do
129 }
130 
131 
132 
133 // ----------------------------- class TrcTrackStatistic -----------------------
134 
TrcTracksStatistic()135 TrcTracksStatistic::TrcTracksStatistic()
136 : TrcStatistic()
137 {
138   resetRules();
139 }
140 
141 
~TrcTracksStatistic()142 TrcTracksStatistic::~TrcTracksStatistic()
143 {
144 // nothing to do
145 }
146 
create(const CodeSequenceMacro & typeCode,const CodeSequenceMacro & typeModifierCode,const CodeSequenceMacro & unitsCode,const Float32 * statisticValues,const size_t numValues,TrcTracksStatistic * & statistic)147 OFCondition TrcTracksStatistic::create(const CodeSequenceMacro& typeCode,
148                                        const CodeSequenceMacro& typeModifierCode,
149                                        const CodeSequenceMacro& unitsCode,
150                                        const Float32* statisticValues,
151                                        const size_t numValues,
152                                        TrcTracksStatistic*& statistic)
153 {
154   statistic = new TrcTracksStatistic();
155   if (!statistic)
156     return EC_MemoryExhausted;
157 
158   //OFCondition result = OFstatic_cast(TrcStatistic*,statistic)->set(typeCode, typeModifierCode, unitsCode);
159   OFCondition result = statistic->TrcStatistic::setCommon(typeCode, typeModifierCode, unitsCode);
160   if (result.good())
161   {
162     result = statistic->getData().putAndInsertFloat32Array(DCM_FloatingPointValues, statisticValues, OFstatic_cast(unsigned long, numValues));
163     if (result.bad())
164     {
165       result = TRC_EC_InvalidStatisticData;
166     }
167   }
168   if (result.bad())
169   {
170     delete statistic;
171     statistic = NULL;
172   }
173   return result;
174 }
175 
176 
read(DcmItem & source,const OFBool clearOldData)177 OFCondition TrcTracksStatistic::read(DcmItem& source,
178                                      const OFBool clearOldData)
179 {
180   return TrcStatistic::read(source, clearOldData);
181 }
182 
183 
write(DcmItem & destination)184 OFCondition TrcTracksStatistic::write(DcmItem& destination)
185 {
186   OFCondition result;
187   result = TrcStatistic::write(destination);
188   if (result.good())
189   {
190     result = IODComponent::write(destination);
191   }
192   return result;
193 }
194 
195 
get(CodeSequenceMacro & typeCode,CodeSequenceMacro & typeModifierCode,CodeSequenceMacro & unitsCode,const Float32 * & statisticValues,unsigned long & numValues)196 OFCondition TrcTracksStatistic::get(CodeSequenceMacro& typeCode,
197                                     CodeSequenceMacro& typeModifierCode,
198                                     CodeSequenceMacro& unitsCode,
199                                     const Float32*& statisticValues,
200                                     unsigned long& numValues)
201 {
202   OFCondition result = TrcStatistic::get(typeCode, typeModifierCode, unitsCode);
203 
204   if (result.good())
205   {
206     result = m_Item->findAndGetFloat32Array(DCM_FloatingPointValues, statisticValues, &numValues);
207   }
208   return result;
209 }
210 
211 
getName() const212 OFString TrcTracksStatistic::getName() const
213 {
214   return "TrackStatisticsSequenceItem";
215 }
216 
217 
resetRules()218 void TrcTracksStatistic::resetRules()
219 {
220   TrcStatistic::resetRules();
221   m_Rules->addRule(new IODRule(DCM_FloatingPointValues, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
222 }
223 
224 
set(const CodeSequenceMacro & typeCode,const CodeSequenceMacro & typeModifierCode,const CodeSequenceMacro & unitsCode,const Float32 * statisticValues,const size_t numValues)225 OFCondition TrcTracksStatistic::set(const CodeSequenceMacro& typeCode,
226                                     const CodeSequenceMacro& typeModifierCode,
227                                     const CodeSequenceMacro& unitsCode,
228                                     const Float32* statisticValues,
229                                     const size_t numValues)
230 {
231   if ( !statisticValues || (numValues == 0))
232   {
233     return TRC_EC_InvalidStatisticData;
234   }
235   OFCondition result = TrcStatistic::setCommon(typeCode, typeModifierCode, unitsCode);
236   if (result.good())
237   {
238     result = m_Item->putAndInsertFloat32Array(DCM_FloatingPointValues, statisticValues, OFstatic_cast(unsigned long, numValues));
239   }
240   return result;
241 }
242 
243 
244 // --------------------------- class TrcTrackSetStatistic ----------------------
245 
TrcTrackSetStatistic()246 TrcTrackSetStatistic::TrcTrackSetStatistic()
247 : TrcStatistic()
248 {
249   resetRules();
250 }
251 
252 
~TrcTrackSetStatistic()253 TrcTrackSetStatistic::~TrcTrackSetStatistic()
254 {
255   // nothing to do
256 }
257 
258 
create(const CodeSequenceMacro & typeCode,const CodeSequenceMacro & typeModifierCode,const CodeSequenceMacro & unitsCode,const Float64 statisticValue,TrcTrackSetStatistic * & statistic)259 OFCondition TrcTrackSetStatistic::create(const CodeSequenceMacro& typeCode,
260                                          const CodeSequenceMacro& typeModifierCode,
261                                          const CodeSequenceMacro& unitsCode,
262                                          const Float64 statisticValue,
263                                          TrcTrackSetStatistic *&statistic)
264 {
265   statistic = new TrcTrackSetStatistic();
266   if (!statistic)
267     return EC_MemoryExhausted;
268 
269   OFCondition result = statistic->set(typeCode, typeModifierCode, unitsCode, statisticValue);
270   if (result.bad())
271   {
272     delete statistic;
273     statistic = NULL;
274   }
275   return result;
276 }
277 
278 
read(DcmItem & source,const OFBool clearOldData)279 OFCondition TrcTrackSetStatistic::read(DcmItem& source,
280                                        const OFBool clearOldData)
281 {
282   OFCondition result = IODComponent::read(source, clearOldData);
283   if (result.good())
284   {
285     TrcStatistic::read(source, clearOldData);
286   }
287   return result;
288 }
289 
290 
write(DcmItem & destination)291 OFCondition TrcTrackSetStatistic::write(DcmItem& destination)
292 {
293   OFCondition result;
294   result = TrcStatistic::write(destination);
295   if (result.good())
296   {
297     result = IODComponent::write(destination);
298   }
299   return result;
300 }
301 
302 
303 
get(CodeSequenceMacro & typeCode,CodeSequenceMacro & typeModifierCode,CodeSequenceMacro & unitsCode,Float64 & statisticValue)304 OFCondition TrcTrackSetStatistic::get(CodeSequenceMacro& typeCode,
305                                       CodeSequenceMacro& typeModifierCode,
306                                       CodeSequenceMacro& unitsCode,
307                                       Float64& statisticValue)
308 {
309   OFCondition result = TrcStatistic::get(typeCode, typeModifierCode, unitsCode);
310   if (result.good())
311   {
312     result = m_Item->findAndGetFloat64(DCM_FloatingPointValue, statisticValue, 0);
313     if (result.bad())
314     {
315       result = TRC_EC_InvalidStatisticData;
316     }
317   }
318   return result;
319 }
320 
321 
getName() const322 OFString TrcTrackSetStatistic::getName() const
323 {
324   return "TrackSetStatisticsSequenceItem";
325 }
326 
327 
resetRules()328 void TrcTrackSetStatistic::resetRules()
329 {
330  TrcStatistic::resetRules();
331  m_Rules->addRule(new IODRule(DCM_FloatingPointValue, "1","1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
332 }
333 
334 
set(const CodeSequenceMacro & typeCode,const CodeSequenceMacro & typeModifierCode,const CodeSequenceMacro & unitsCode,const Float64 statisticValue)335 OFCondition TrcTrackSetStatistic::set(const CodeSequenceMacro& typeCode,
336                                       const CodeSequenceMacro& typeModifierCode,
337                                       const CodeSequenceMacro& unitsCode,
338                                       const Float64 statisticValue)
339 {
340   OFCondition result = TrcStatistic::setCommon(typeCode, typeModifierCode, unitsCode);
341   if (result.good())
342   {
343     result = m_Item->putAndInsertFloat64(DCM_FloatingPointValue, statisticValue, 0);
344     if (result.bad())
345     {
346       result = TRC_EC_InvalidStatisticData;
347     }
348   }
349   return result;
350 }
351