1 /*
2  *
3  *  Copyright (C) 2016-2017, J. Riesmeier, Oldenburg, Germany
4  *  All rights reserved.  See COPYRIGHT file for details.
5  *
6  *  Header file for class TID1411_VolumetricROIMeasurements
7  *
8  *  Author: Joerg Riesmeier
9  *
10  */
11 
12 
13 #ifndef CMR_TID1411_H
14 #define CMR_TID1411_H
15 
16 #include "dcmtk/config/osconfig.h"   /* make sure OS specific configuration is included first */
17 
18 #include "dcmtk/dcmsr/dsrstpl.h"
19 
20 #include "dcmtk/dcmsr/cmr/define.h"
21 #include "dcmtk/dcmsr/cmr/srnumvlu.h"
22 #include "dcmtk/dcmsr/cmr/tid1419m.h"
23 #include "dcmtk/dcmsr/cmr/cid6147.h"
24 #include "dcmtk/dcmsr/cmr/cid7181.h"
25 #include "dcmtk/dcmsr/cmr/cid7464.h"
26 #include "dcmtk/dcmsr/cmr/cid7469.h"
27 
28 
29 // include this file in doxygen documentation
30 
31 /** @file tid1411.h
32  *  @brief Interface class for TID 1411 in module dcmsr/cmr
33  */
34 
35 
36 /*---------------------*
37  *  class declaration  *
38  *---------------------*/
39 
40 /** Implementation of DCMR Template:
41  *  TID 1411 - Volumetric ROI Measurements (and included templates 1502 and 1419).
42  *  All added content items are annotated with a text in the format "TID 1411 - Row [n]".
43  ** @tparam  T_Measurement  concept names for the numeric measurements (context group)
44  *  @tparam  T_Units        units of the numeric measurement values (context group)
45  *  @tparam  T_Method       methods used for measuring the values (context group)
46  *  @tparam  T_Derivation   methods of deriving or calculating the values (context group)
47  ** @note Please note that currently only the mandatory and some optional/conditional
48  *        content items and included templates are supported.
49  *  @note Also note that this template class requires explicit instantiation for those
50  *        combinations of the template parameters that are actually used.  This is
51  *        because the implementation is "hidden" in a separate source file, which has
52  *        some advantages over the usual header-only approach.
53  */
54 template<typename T_Measurement, typename T_Units, typename T_Method, typename T_Derivation>
55 class DCMTK_CMR_EXPORT TID1411_VolumetricROIMeasurements
56   : public DSRSubTemplate
57 {
58 
59   public:
60 
61     // type definition
62     typedef CMR_SRNumericMeasurementValueWithUnits<T_Units> MeasurementValue;
63 
64 
65     typedef TID1419_ROIMeasurements_Measurement<CID7469_GenericIntensityAndSizeMeasurements,
66                                                 CID7181_AbstractMultiDimensionalImageModelComponentUnits,
67                                                 CID6147_ResponseCriteria,
68                                                 CID7464_GeneralRegionOfInterestMeasurementModifiers>
69             TID1419_Measurement;
70 
71     /** (default) constructor
72      ** @param  createGroup  flag indicating whether to create an empty measurement group
73      *                       by calling createMeasurementGroup() during startup
74      */
75     TID1411_VolumetricROIMeasurements(const OFBool createGroup = OFFalse);
76 
77     /** clear internal member variables.
78      *  Also see notes on the clear() method of the base class.
79      */
80     virtual void clear();
81 
82     /** check whether the current internal state is valid.
83      *  That means, whether the base class is valid and whether all mandatory content
84      *  items and included templates are valid (present), i.e. hasMeasurementGroup(),
85      *  hasTrackingIdentifier(), hasTrackingUniqueIdentifier(), hasReferencedSegment(),
86      *  hasSourceSeriesForSegmentation() and hasROIMeasurements() return true.
87      ** @return OFTrue if valid, OFFalse otherwise
88      */
89     OFBool isValid() const;
90 
91     /** check whether the 'Measurement Group' content item (TID 1411 - Row 1) is present.
92      *  This mandatory content item can be created by the constructor of this class (if
93      *  not disabled, which is the default) or internally by createMeasurementGroup().
94      *  After clear() has been called, the content item has to be recreated, which is
95      *  done automatically when needed.
96      ** @param  checkChildren  optional flag indicating whether to also check for any
97      *                         children, i.e.\ whether the respective content item has
98      *                         child nodes.  By default, the presence of the higher-level
99      *                         CONTAINER is checked only.
100      ** @return OFTrue if the measurement group is present, OFFalse otherwise
101      */
102     OFBool hasMeasurementGroup(const OFBool checkChildren = OFFalse) const;
103 
104     /** check whether the 'Tracking Identifier' content item (TID 1411 - Row 2) is
105      *  present.  This content item is mandatory, i.e. should be present with a value.
106      ** @return OFTrue if the tracking identifier is present, OFFalse otherwise
107      */
108     OFBool hasTrackingIdentifier() const;
109 
110     /** check whether the 'Tracking Unique Identifier' content item (TID 1411 - Row 3) is
111      *  present.  This content item is mandatory, i.e. should be present with a value.
112      ** @return OFTrue if the tracking unique identifier is present, OFFalse otherwise
113      */
114     OFBool hasTrackingUniqueIdentifier() const;
115 
116     /** check whether the 'Referenced Segment' content item (TID 1411 - Row 7) is present.
117      *  This content item is conditional, but should be present to meet the conditions.
118      ** @return OFTrue if the referenced segment is present, OFFalse otherwise
119      */
120     OFBool hasReferencedSegment() const;
121 
122     /** check whether the 'Source Series for Segmentation' content item (TID 1411 -
123      *  Row 12) is present.  This content item is conditional, but should be present to
124      *  meet the conditions.
125      ** @return OFTrue if source series for segmentation is present, OFFalse otherwise
126      */
127     OFBool hasSourceSeriesForSegmentation() const;
128 
129     /** check whether there is an included 'ROI Measurements' template (TID 1411 -
130      *  Row 15) in this measurement template.  Initially, this mandatory sub-template
131      *  is created and included by the constructor of this class.  After clear() has
132      *  been called, the content item has to be recreated, which is done automatically
133      *  when needed.
134      ** @param  checkChildren  flag, which is enabled by default, indicating whether to
135      *                         check for any children, i.e.\ whether the respective
136      *                         sub-template has any content (child nodes).  If OFFalse,
137      *                         the "included template" content item is checked only.
138      ** @return OFTrue if measurements are present, OFFalse otherwise
139      */
140     OFBool hasMeasurements(const OFBool checkChildren = OFTrue) const;
141 
142     /** get current measurement value of this measurement group as defined by TID 1419
143      *  (ROI Measurements), i.e.\ the current instance of TID 1411 - Row 15.
144      *  This included template is mandatory, i.e. should be present and not be empty.
145      *  Further instances can be added by calling addMeasurement().
146      ** @return reference to internally managed SR template (current instance)
147      */
getMeasurement()148     inline TID1419_Measurement &getMeasurement() const
149     {
150         return *OFstatic_cast(TID1419_Measurement *, Measurement.get());
151     }
152 
153     /** set the value of the 'Activity Session' content item (TID 1411 - Row 1b).
154      *  A measurement group is created automatically (if none is present).  If the
155      *  content item already exists, its value is overwritten.
156      ** @param  session  identifier of the session during which the measurements were made
157      *  @param  check    if enabled, check values for validity before setting them
158      ** @return status, EC_Normal if successful, an error code otherwise
159      */
160     OFCondition setActivitySession(const OFString &session,
161                                    const OFBool check = OFTrue);
162 
163     /** set the value of the 'Tracking Identifier' content item (TID 1411 - Row 2).
164      *  A measurement group is created automatically (if none is present).  If the
165      *  content item already exists, its value is overwritten.
166      ** @param  trackingID  a text label used for tracking a finding or feature
167      *  @param  check       if enabled, check values for validity before setting them
168      ** @return status, EC_Normal if successful, an error code otherwise
169      */
170     OFCondition setTrackingIdentifier(const OFString &trackingID,
171                                       const OFBool check = OFTrue);
172 
173     /** set the value of the 'Tracking Unique Identifier' content item (TID 1411 - Row 3).
174      *  A measurement group is created automatically (if none is present).  If the
175      *  content item already exists, its value is overwritten.
176      ** @param  trackingUID  a unique identifier used for tracking a finding or feature
177      *                       (associated DICOM VR=UI)
178      *  @param  check        if enabled, check values for validity before setting them
179      ** @return status, EC_Normal if successful, an error code otherwise
180      */
181     OFCondition setTrackingUniqueIdentifier(const OFString &trackingUID,
182                                             const OFBool check = OFTrue);
183 
184     /** set the value of the 'Finding' content item (TID 1411 - Row 3b).
185      *  A measurement group is created automatically (if none is present).  If the
186      *  content item already exists, its value is overwritten.
187      ** @param  finding  coded entry that describes the type of the finding
188      *  @param  check    if enabled, check values for validity before setting them
189      ** @return status, EC_Normal if successful, an error code otherwise
190      */
191     OFCondition setFinding(const DSRCodedEntryValue &finding,
192                            const OFBool check = OFTrue);
193 
194     /** set the value of the 'Time Point' content item (TID 1502 - Row 3).
195      *  A measurement group is created automatically (if none is present).  If the
196      *  content item already exists, its value is overwritten.
197      ** @param  timePoint  a short pre-defined label that is human-readable
198      *  @param  check      if enabled, check values for validity before setting them
199      ** @return status, EC_Normal if successful, an error code otherwise
200      */
201     OFCondition setTimePoint(const OFString &timePoint,
202                              const OFBool check = OFTrue);
203 
204     /** set the value of the 'Referenced Segment' content item (TID 1411 - Row 7).
205      *  A measurement group is created automatically (if none is present).  If the
206      *  content item already exists, its value is overwritten.
207      ** @param  segment  reference to a segmentation object with a single selected
208      *                   segment; specifically the pixels or voxels identified as
209      *                   belonging to the classification of the identified segment
210      *  @param  check    if enabled, check values for validity before setting them
211      ** @return status, EC_Normal if successful, an error code otherwise
212      */
213     OFCondition setReferencedSegment(const DSRImageReferenceValue &segment,
214                                      const OFBool check = OFTrue);
215 
216     /** set the value of the 'Referenced Segment' content item (TID 1411 - Row 7).
217      *  A measurement group is created automatically (if none is present).  If the
218      *  content item already exists, its value is overwritten.
219      *  If 'copyTracking' is enabled and the 'dataset' contains appropriate tracking
220      *  information for the given 'segmentNumber', setTrackingIdentifier() and
221      *  setTrackingUniqueIdentifier() are also called by this method.
222      ** @param  dataset        DICOM dataset from which the values for the referenced
223      *                         segment (e.g. SOP class UID and SOP instance UID) should
224      *                         be retrieved
225      *  @param  segmentNumber  number of the segment that should be referenced.  The
226      *                         value is only checked when 'copyTracking' is enabled.
227      *  @param  copyTracking   flag indicating whether to copy tracking information
228      *                         (tracking ID and UID) from the 'dataset', if available
229      *  @param  check          if enabled, check values for validity before setting them
230      ** @return status, EC_Normal if successful, an error code otherwise
231      */
232     OFCondition setReferencedSegment(DcmItem &dataset,
233                                      const Uint16 segmentNumber,
234                                      const OFBool copyTracking = OFTrue,
235                                      const OFBool check = OFTrue);
236 
237     /** set the value of the 'Source series for segmentation' content item (TID 1411 -
238      *  Row 12).  A measurement group is created automatically (if none is present).
239      *  If the content item already exists, its value is overwritten.
240      ** @param  seriesUID  the unique identifier of the source series of images that
241      *                     were segmented to identify the ROI (associated DICOM VR=UI)
242      *  @param  check      if enabled, check values for validity before setting them
243      ** @return status, EC_Normal if successful, an error code otherwise
244      */
245     OFCondition setSourceSeriesForSegmentation(const OFString &seriesUID,
246                                                const OFBool check = OFTrue);
247 
248     /** set the value of the 'Real World Value Map used for measurement' content item
249      *  (TID 1411 - Row 14).  A measurement group is created automatically (if none is
250      *  present).  If the content item already exists, its value is overwritten.
251      ** @param  valueMap  reference to a real world value mapping object applied to the
252      *                    stored image pixel values before their use for a measurement
253      *  @param  check     if enabled, check values for validity before setting them
254      ** @return status, EC_Normal if successful, an error code otherwise
255      */
256     OFCondition setRealWorldValueMap(const DSRCompositeReferenceValue &valueMap,
257                                      const OFBool check = OFTrue);
258 
259     /** set the value of the 'Real World Value Map used for measurement' content item
260      *  (TID 1411 - Row 14).  A measurement group is created automatically (if none is
261      *  present).  If the content item already exists, its value is overwritten.
262      ** @param  dataset  DICOM dataset from which the values for the reference to a
263      *                   real world value mapping object (SOP class UID and SOP instance
264      *                   UID) should be retrieved
265      *  @param  check    if enabled, check values for validity before setting them
266      ** @return status, EC_Normal if successful, an error code otherwise
267      */
268     OFCondition setRealWorldValueMap(DcmItem &dataset,
269                                      const OFBool check = OFTrue);
270 
271     /** set the value of the 'Measurement Method' content item (TID 1419 - Row 1).
272      *  A measurement group is created automatically (if none is present).  If the
273      *  content item already exists, its value is overwritten.
274      ** @param  method  coded entry describing the method used for measuring the values
275      *                  in the group (e.g.\ from the given context group 'T_Method')
276      *  @param  check   if enabled, check values for validity before setting them
277      ** @return status, EC_Normal if successful, an error code otherwise
278      */
279     OFCondition setMeasurementMethod(const T_Method &method,
280                                      const OFBool check = OFTrue);
281 
282     /** add a 'Finding Site' content item (TID 1419 - Row 2, 3 and 4).
283      *  A measurement group is created automatically (if none is present).
284      *  @note Originally, the associated content item had the value multiplicity "1" and
285      *    thus the method was called setFindingSite().  This changed with CP-1591.  The
286      *    value multiplicity is now "1-n".  The requirement type is still "User option".
287      ** @param  site          coded entry describing the anatomic location of the
288      *                        measurements in the current group
289      *  @param  laterality    laterality associated with the 'site' (optional)
290      *  @param  siteModifier  coded entry describing the topographical modifier of the
291      *                        'site' (optional)
292      *  @param  check  if enabled, check values for validity before setting them
293      ** @return status, EC_Normal if successful, an error code otherwise
294      */
295     OFCondition addFindingSite(const DSRCodedEntryValue &site,
296                                const CID244e_Laterality &laterality = CID244e_Laterality(),
297                                const DSRCodedEntryValue &siteModifier = DSRCodedEntryValue(),
298                                const OFBool check = OFTrue);
299 
300     /** add a measurement as defined in 'ROI Measurements' (TID 1419 - Row 5).
301      *  A measurement group is created automatically (if none is present).  There should
302      *  be at least a single instance of the associated template.  Access to the current
303      *  instance is available through getMeasurement().
304      ** @param  conceptName   coded entry specifying the concept name of the measurement
305      *                        (e.g.\ from the given context group 'T_Measurement')
306      *  @param  numericValue  numeric measurement value to be set.  The measurement unit
307      *                        could be taken from the baseline context group 'T_Units'.
308      ** @param  checkEmpty    by default, it is checked whether the current instance of
309      *                        TID 1419 is empty, and thus no new instance is created.
310      *                        Setting this parameter to OFFalse disables this check and
311      *                        always creates and adds a new instance of this sub-template.
312      *  @param  checkValue    if enabled, check values for validity before setting them
313      ** @return status, EC_Normal if successful, an error code otherwise
314      */
315     OFCondition addMeasurement(const T_Measurement &conceptName,
316                                const MeasurementValue &numericValue,
317                                const OFBool checkEmpty = OFTrue,
318                                const OFBool checkValue = OFTrue);
319 
320     /** add a qualitative evaluation related to the subject of the measurement group as a
321      *  coded entry (TID 1411 - Row 16).
322      *  A measurement group is created automatically (if none is present).
323      ** @param  conceptName  coded entry to be set as the concept name
324      *  @param  codeValue    coded entry to be set as the value of the new content item
325      *  @param  check        if enabled, check values for validity before setting them
326      ** @return status, EC_Normal if successful, an error code otherwise
327      */
328     OFCondition addQualitativeEvaluation(const DSRCodedEntryValue &conceptName,
329                                          const DSRCodedEntryValue &codeValue,
330                                          const OFBool check = OFTrue);
331 
332     /** add a qualitative evaluation related to the subject of the measurement group in
333      *  text form (TID 1411 - Row 17).
334      *  A measurement group is created automatically (if none is present).
335      ** @param  conceptName  coded entry to be set as the concept name
336      *  @param  stringValue  character string to be set as the value of the content item
337      *  @param  check        if enabled, check values for validity before setting them
338      ** @return status, EC_Normal if successful, an error code otherwise
339      */
340     OFCondition addQualitativeEvaluation(const DSRCodedEntryValue &conceptName,
341                                          const OFString &stringValue,
342                                          const OFBool check = OFTrue);
343 
344 
345   protected:
346 
347     /** create the mandatory root content item of this template, i.e.\ TID 1411 - Row 1.
348      *  It is expected that the tree is currently empty.
349      ** @return status, EC_Normal if successful, an error code otherwise
350      */
351     OFCondition createMeasurementGroup();
352 
353     /** add a new or replace an existing content item with a given node ID.
354      *  If the content item does not exist, it is added to the measurement group, i.e.
355      *  below the root node.  If it does exist, both the 'valueType' and 'conceptName'
356      *  are checked before replacing the value.  However, the value is not replaced by
357      *  this method.  This is up to the caller after this method returned with success.
358      ** @param  nodePos           index of the list entry that stores the ID of the node
359      *                            to search for
360      *  @param  relationshipType  relationship type of the content item to be added/replaced
361      *  @param  valueType         value type of the content item to be added/replaced
362      *  @param  conceptName       concept name of the content item to be added/replaced
363      *  @param  annotationText    optional text used to annotate the content item
364      *  @param  check             if enabled, check values for validity before setting them
365      ** @return status, EC_Normal if successful, an error code otherwise
366      */
367     OFCondition addOrReplaceContentItem(const size_t nodePos,
368                                         const E_RelationshipType relationshipType,
369                                         const E_ValueType valueType,
370                                         const DSRCodedEntryValue &conceptName,
371                                         const OFString &annotationText,
372                                         const OFBool check);
373 
374 
375   private:
376 
377     // shared pointer to included template "ROI Measurements" (TID 1419, Row 5)
378     DSRSharedSubTemplate Measurement;
379 };
380 
381 
382 #endif
383