1 /* 2 * 3 * Copyright (C) 2000-2016, OFFIS e.V. 4 * All rights reserved. See COPYRIGHT file for details. 5 * 6 * This software and supporting documentation were developed by 7 * 8 * OFFIS e.V. 9 * R&D Division Health 10 * Escherweg 2 11 * D-26121 Oldenburg, Germany 12 * 13 * 14 * Module: dcmsr 15 * 16 * Author: Joerg Riesmeier 17 * 18 * Purpose: 19 * classes: DSRNumericMeasurementValue 20 * 21 */ 22 23 24 #ifndef DSRNUMVL_H 25 #define DSRNUMVL_H 26 27 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ 28 29 #include "dcmtk/dcmsr/dsrcodvl.h" 30 31 #include "dcmtk/dcmdata/dcvrfd.h" 32 #include "dcmtk/dcmdata/dcvrsl.h" 33 #include "dcmtk/dcmdata/dcvrul.h" 34 35 36 /*---------------------* 37 * class declaration * 38 *---------------------*/ 39 40 /** Class for numeric values and measurements 41 */ 42 class DCMTK_DCMSR_EXPORT DSRNumericMeasurementValue 43 { 44 // allow access to getValuePtr() 45 friend class DSRContentItem; 46 47 public: 48 49 /** default constructor 50 */ 51 DSRNumericMeasurementValue(); 52 53 /** constructor 54 ** @param numericValue numeric value (VR=DS, mandatory) 55 * @param measurementUnit code representing the units of measurement (mandatory) 56 * @param check if enabled, check 'numericValue' and 'measurementUnit' for 57 * validity before setting them. See corresponding setValue() 58 * method for details. 59 */ 60 DSRNumericMeasurementValue(const OFString &numericValue, 61 const DSRCodedEntryValue &measurementUnit, 62 const OFBool check = OFTrue); 63 64 /** constructor 65 ** @param valueQualifier code representing the numeric value qualifier. Used to 66 * specify the reason for the absence of the measured value 67 * sequence, i.e. why the numeric value and measurement unit 68 * are empty. 69 * @param check if enabled, check value for validity before setting it. 70 * See corresponding setValue() method for details. 71 */ 72 DSRNumericMeasurementValue(const DSRCodedEntryValue &valueQualifier, 73 const OFBool check = OFTrue); 74 75 /** constructor 76 ** @param numericValue numeric value (VR=DS, mandatory) 77 * @param measurementUnit code representing the units of measurement (mandatory) 78 * @param valueQualifier code representing the numeric value qualifier (optional). 79 * Can also be used to specify the reason for the absence of 80 * the measured value sequence (where 'numericValue' and 81 * 'measurementUnit' are stored). 82 * @param check if enabled, check values for validity before setting them. 83 * See corresponding setValue() method for details. 84 */ 85 DSRNumericMeasurementValue(const OFString &numericValue, 86 const DSRCodedEntryValue &measurementUnit, 87 const DSRCodedEntryValue &valueQualifier, 88 const OFBool check = OFTrue); 89 90 /** copy constructor 91 ** @param numericMeasurement numeric measurement value to be copied (not checked !) 92 */ 93 DSRNumericMeasurementValue(const DSRNumericMeasurementValue &numericMeasurement); 94 95 /** destructor 96 */ 97 virtual ~DSRNumericMeasurementValue(); 98 99 /** assignment operator 100 ** @param numericMeasurement numeric measurement value to be copied (not checked !) 101 ** @return reference to this numeric value after 'numericMeasurement' has been copied 102 */ 103 DSRNumericMeasurementValue &operator=(const DSRNumericMeasurementValue &numericMeasurement); 104 105 /** comparison operator "equal". 106 * Two numeric measurement values are equal if the numeric value, the measurement unit 107 * and the value qualifier are equal. Other (additional) information is not used. 108 ** @param numericMeasurement numeric measurement value that should be compared to the 109 * current one 110 ** @return OFTrue if both numeric measurement values are equal, OFFalse otherwise 111 */ 112 OFBool operator==(const DSRNumericMeasurementValue &numericMeasurement) const; 113 114 /** comparison operator "not equal". 115 * Two numeric measurement values are not equal if either the numeric value or the 116 * measurement unit or the value qualifier are not equal. Other (additional) information 117 * is not used for comparison. 118 ** @param numericMeasurement numeric measurement value that should be compared to the 119 * current one 120 ** @return OFTrue if both numeric measurement values are not equal, OFFalse otherwise 121 */ 122 OFBool operator!=(const DSRNumericMeasurementValue &numericMeasurement) const; 123 124 /** clear all internal variables. 125 * Use this method to create an empty numeric measurement value. 126 */ 127 virtual void clear(); 128 129 /** check whether the current numeric measurement value is valid. 130 * The value is valid if isEmpty() is true or both the numeric value and the measurement 131 * unit contain a valid value, and the value qualifier is valid (see checkXXX() methods). 132 * The possibly available additional representations of the numeric value are never 133 * checked. 134 ** @return OFTrue if value is valid, OFFalse otherwise 135 */ 136 virtual OFBool isValid() const; 137 138 /** check whether the current numeric measurement value is empty. 139 * Checks whether both the numeric value and the measurement are empty. The optional 140 * value qualifier is not checked since it might contain the reason for the absence of 141 * the measured value sequence. 142 ** @return OFTrue if value is empty, OFFalse otherwise 143 */ 144 virtual OFBool isEmpty() const; 145 146 /** check whether the current numeric measurement value is complete, i.e.\ whether the 147 * numeric value is non-empty and the measurement unit is complete, or whether the 148 * value qualifier is complete. This is just a basic check that might be useful for 149 * "validating" input data. See isValid() for a more sophisticated way of checking 150 * the current numeric measurement value. 151 ** @return OFTrue if value is complete, OFFalse otherwise 152 */ 153 virtual OFBool isComplete() const; 154 155 /** print numeric measurement value. 156 * The output of a typical numeric measurement value looks like this: 157 * "3.5" (cm,UCUM[1.4],"centimeter"). If the value is empty, the text "empty" is printed 158 * instead, followed by the numeric value qualifier (if present). The possibly available 159 * additional floating point and rational representations of the numeric value are never 160 * printed. 161 ** @param stream output stream to which the numeric measurement value should be printed 162 * @param flags flag used to customize the output (not used) 163 ** @return status, EC_Normal if successful, an error code otherwise 164 */ 165 virtual OFCondition print(STD_NAMESPACE ostream &stream, 166 const size_t flags) const; 167 168 /** read numeric measurement value from XML document 169 ** @param doc document containing the XML file content 170 * @param cursor cursor pointing to the starting node 171 * @param flags flag used to customize the reading process (see DSRTypes::XF_xxx) 172 ** @return status, EC_Normal if successful, an error code otherwise 173 */ 174 virtual OFCondition readXML(const DSRXMLDocument &doc, 175 DSRXMLCursor cursor, 176 const size_t flags); 177 178 /** write numeric measurement value in XML format 179 ** @param stream output stream to which the XML document is written 180 * @param flags flag used to customize the output (see DSRTypes::XF_xxx) 181 ** @return status, EC_Normal if successful, an error code otherwise 182 */ 183 virtual OFCondition writeXML(STD_NAMESPACE ostream &stream, 184 const size_t flags) const; 185 186 /** read measured value sequence and numeric value qualifier code sequence from dataset. 187 * The number of items within the sequences is checked. If error/warning output are 188 * enabled, a warning message is printed if a sequence is absent or contains more than 189 * one item. 190 ** @param dataset DICOM dataset from which the sequences should be read 191 * @param flags flag used to customize the reading process (see DSRTypes::RF_xxx) 192 ** @return status, EC_Normal if successful, an error code otherwise 193 */ 194 virtual OFCondition readSequence(DcmItem &dataset, 195 const size_t flags); 196 197 /** write measured value sequence and numeric value qualifier code sequence to dataset. 198 * The measured value sequence is always written (might be empty, though). The numeric 199 * value qualifier code sequence is optional and, therefore, only written if non-empty. 200 ** @param dataset DICOM dataset to which the sequences should be written 201 ** @return status, EC_Normal if successful, an error code otherwise 202 */ 203 virtual OFCondition writeSequence(DcmItem &dataset) const; 204 205 /** render numeric measurement value in HTML/XHTML format 206 ** @param docStream output stream to which the main HTML/XHTML document is written 207 * @param annexStream output stream to which the HTML/XHTML document annex is written 208 * @param annexNumber reference to the variable where the current annex number is stored. 209 * Value is increased automatically by 1 after a new entry has been added. 210 * @param flags flag used to customize the output (see DSRTypes::HF_xxx) 211 ** @return status, EC_Normal if successful, an error code otherwise 212 */ 213 virtual OFCondition renderHTML(STD_NAMESPACE ostream &docStream, 214 STD_NAMESPACE ostream &annexStream, 215 size_t &annexNumber, 216 const size_t flags) const; 217 218 /** get reference to numeric measurement value 219 ** @return reference to numeric measurement value 220 */ getValue()221 inline const DSRNumericMeasurementValue &getValue() const 222 { 223 return *this; 224 } 225 226 /** get copy of numeric measurement value 227 ** @param numericMeasurement reference to variable in which the value should be stored 228 ** @return always returns EC_Normal 229 */ 230 OFCondition getValue(DSRNumericMeasurementValue &numericMeasurement) const; 231 232 /** get numeric value 233 ** @return current numeric value (might be invalid or an empty string) 234 */ getNumericValue()235 inline const OFString &getNumericValue() const 236 { 237 return NumericValue; 238 } 239 240 /** get measurement unit 241 ** @return reference to current measurement unit code (might be invalid or empty) 242 */ getMeasurementUnit()243 inline const DSRCodedEntryValue &getMeasurementUnit() const 244 { 245 return MeasurementUnit; 246 } 247 248 /** get numeric value qualifier (optional) 249 ** @return reference to current numeric value qualifier code (might be invalid or empty) 250 */ getNumericValueQualifier()251 inline const DSRCodedEntryValue &getNumericValueQualifier() const 252 { 253 return ValueQualifier; 254 } 255 256 /** get copy of measurement unit 257 ** @param measurementUnit reference to variable in which the code should be stored 258 ** @return always returns EC_Normal 259 */ 260 OFCondition getMeasurementUnit(DSRCodedEntryValue &measurementUnit) const; 261 262 /** get copy of numeric value qualifier (optional). 263 * Can be used to specify the reason for the absence of the measured value sequence. 264 ** @param valueQualifier reference to variable in which the code should be stored 265 ** @return always returns EC_Normal 266 */ 267 OFCondition getNumericValueQualifier(DSRCodedEntryValue &valueQualifier) const; 268 269 /** get floating point representation of the numeric value (optional) 270 ** @param floatingPoint reference to variable in which the floating point representation 271 * should be stored 272 ** @return status, EC_Normal if successful, an error code otherwise. Returns 273 * SR_EC_RepresentationNotAvailable if floating point representation is not available. 274 */ 275 OFCondition getFloatingPointRepresentation(Float64 &floatingPoint) const; 276 277 /** get rational representation of the numeric value (optional) 278 ** @param rationalNumerator reference to variable in which the integer numerator of 279 * the rational representation should be stored 280 ** @param rationalDenominator reference to variable in which the integer denominator of 281 * the rational representation should be stored 282 ** @return status, EC_Normal if successful, an error code otherwise. Returns 283 * SR_EC_RepresentationNotAvailable if rational representation is not available. 284 */ 285 OFCondition getRationalRepresentation(Sint32 &rationalNumerator, 286 Uint32 &rationalDenominator) const; 287 288 /** set numeric measurement value. 289 * Before setting the value, it is usually checked. If the value is invalid, the current 290 * value is not replaced and remains unchanged. 291 ** @param numericMeasurement value to be set 292 * @param check if enabled, check value for validity before setting it. 293 * See checkXXX() methods for details. Empty values are only 294 * accepted for non-mandatory attributes. 295 ** @return status, EC_Normal if successful, an error code otherwise 296 */ 297 OFCondition setValue(const DSRNumericMeasurementValue &numericMeasurement, 298 const OFBool check = OFTrue); 299 300 /** set numeric value and measurement unit. 301 * Before setting the values, they are usually checked. Please note that both values 302 * (i.e. 'numericValue' and 'measurementUnit') either have to be empty or non-empty. 303 * If the value pair is invalid, the current value pair is not replaced and remains 304 * unchanged. If the value pair is replaced, the optional floating point and rational 305 * representations are cleared, i.e. they have to be set manually if needed. 306 ** @param numericValue numeric value to be set (VR=DS, mandatory) 307 * @param measurementUnit measurement unit to be set (mandatory) 308 * @param check if enabled, check values for validity before setting them. 309 * See checkXXX() methods for details. 310 ** @return status, EC_Normal if successful, an error code otherwise 311 */ 312 OFCondition setValue(const OFString &numericValue, 313 const DSRCodedEntryValue &measurementUnit, 314 const OFBool check = OFTrue); 315 316 /** set empty numeric value and measurement unit with a numeric value qualifier. 317 * Before setting the value, it is usually checked. If the value is invalid, the 318 * current numeric measurement value is not replaced and remains unchanged. 319 ** @param valueQualifier numeric value qualifier to be set. Used to specify the 320 * reason for the absence of the measured value sequence, 321 * i.e. why the numeric value and measurement unit are empty. 322 * @param check if enabled, check value for validity before setting it. 323 * See checkNumericValueQualifier() method for details. 324 ** @return status, EC_Normal if successful, an error code otherwise 325 */ 326 OFCondition setValue(const DSRCodedEntryValue &valueQualifier, 327 const OFBool check = OFTrue); 328 329 /** set numeric value, measurement unit and numeric value qualifier. 330 * Before setting the values, they are usually checked. Please note that both 331 * 'numericValue' and 'measurementUnit' either have to be empty or non-empty. 332 * If one of the three values is invalid, the current numeric measurement value is not 333 * replaced and remains unchanged. If the values are replaced, the optional floating 334 * point and rational representations are cleared, i.e. they have to be set manually if 335 * needed. 336 ** @param numericValue numeric value to be set (VR=DS, mandatory) 337 * @param measurementUnit measurement unit to be set (mandatory) 338 * @param valueQualifier numeric value qualifier to be set (optional). Can also be 339 * used to specify the reason for the absence of the measured 340 * value sequence (where 'numericValue' and 'measurementUnit' 341 * are stored). Use an empty code to remove the current value. 342 * @param check if enabled, check values for validity before setting them. 343 * See checkXXX() methods for details. 344 ** @return status, EC_Normal if successful, an error code otherwise 345 */ 346 OFCondition setValue(const OFString &numericValue, 347 const DSRCodedEntryValue &measurementUnit, 348 const DSRCodedEntryValue &valueQualifier, 349 const OFBool check = OFTrue); 350 351 /** set numeric value. 352 * Before setting the value, it is usually checked. If the value is invalid, the current 353 * value is not replaced and remains unchanged. If the value is replaced, the optional 354 * floating point and rational representations are cleared, i.e. they have to be set 355 * manually if needed. 356 ** @param numericValue numeric value to be set (VR=DS, mandatory) 357 * @param check if enabled, check value for validity before setting it. 358 * See checkNumericValue() method for details. An empty value is 359 * never accepted, use the clear() method instead. 360 ** @return status, EC_Normal if successful, an error code otherwise 361 */ 362 OFCondition setNumericValue(const OFString &numericValue, 363 const OFBool check = OFTrue); 364 365 /** set numeric value from element. 366 * Before setting the value, it is usually checked. If the value is invalid, the current 367 * value is not replaced and remains unchanged. If the value is replaced, the optional 368 * floating point and rational representations are cleared, i.e. they have to be set 369 * manually if needed. 370 ** @param delem DICOM element from which the numeric value should be retrieved 371 * @param pos index of the value in case of multi-valued elements (0..vm-1) 372 * @param check if enabled, check numeric value for validity before setting it. See 373 * checkNumericValue() method for details. An empty value is never 374 * accepted. 375 ** @return status, EC_Normal if successful, an error code otherwise 376 */ 377 OFCondition setNumericValue(const DcmElement &delem, 378 const unsigned long pos = 0, 379 const OFBool check = OFTrue); 380 381 /** set numeric value from dataset. 382 * Before setting the value, it is usually checked. If the value is invalid, the current 383 * value is not replaced and remains unchanged. If the value is replaced, the optional 384 * floating point and rational representations are cleared, i.e. they have to be set 385 * manually if needed. 386 ** @param dataset DICOM dataset from which the numeric value should be retrieved 387 * @param tagKey DICOM tag specifying the attribute from which the value should be 388 * retrieved. The search is limited to the top-level of the dataset. 389 * @param pos index of the value in case of multi-valued elements (0..vm-1) 390 * @param check if enabled, check numeric value for validity before setting it. 391 * See checkNumericValue() method for details. An empty value is 392 * never accepted. 393 ** @return status, EC_Normal if successful, an error code otherwise 394 */ 395 OFCondition setNumericValue(DcmItem &dataset, 396 const DcmTagKey &tagKey, 397 const unsigned long pos = 0, 398 const OFBool check = OFTrue); 399 400 /** set measurement unit. 401 * Before setting the code, it is usually checked. If the code is invalid the current 402 * code is not replaced and remains unchanged. 403 ** @param measurementUnit measurement unit to be set (mandatory) 404 * @param check if enabled, check value for validity before setting it. 405 * See checkMeasurementUnit() method for details. An empty 406 * value is never accepted, use the clear() method instead. 407 ** @return status, EC_Normal if successful, an error code otherwise 408 */ 409 OFCondition setMeasurementUnit(const DSRCodedEntryValue &measurementUnit, 410 const OFBool check = OFTrue); 411 412 /** set numeric value qualifier. 413 * This optional code specifies the qualification of the Numeric Value in the Measured 414 * Value Sequence, or the reason for the absence of the Measured Value Sequence Item. 415 * Before setting the code, it is usually checked. If the code is invalid the current 416 * code is not replaced and remains unchanged. 417 ** @param valueQualifier numeric value qualifier to be set (optional). Use an empty 418 * code to remove the current value. 419 * @param check if enabled, check value for validity before setting it. 420 * See checkNumericValueQualifier() method for details. 421 ** @return status, EC_Normal if successful, an error code otherwise 422 */ 423 OFCondition setNumericValueQualifier(const DSRCodedEntryValue &valueQualifier, 424 const OFBool check = OFTrue); 425 426 /** set floating point representation of the numeric value. 427 * According to the DICOM standard, this value is "required if the numeric value has 428 * insufficient precision to represent the value as a string. May be present otherwise." 429 * Please note that it is not checked whether this representation is consistent with the 430 * numeric value stored as a string. 431 ** @param floatingPoint floating point representation of the numeric value 432 * @param check dummy parameter (currently not used) 433 ** @return status, EC_Normal if successful, an error code otherwise 434 */ 435 OFCondition setFloatingPointRepresentation(const Float64 floatingPoint, 436 const OFBool check = OFTrue); 437 438 /** set rational representation of the numeric value. 439 * According to the DICOM standard, this value is "required if the numeric value has 440 * insufficient precision to represent a rational value as a string. May be present 441 * otherwise." Please note that it is not checked whether this representation is 442 * consistent with the numeric value stored as a string. 443 ** @param rationalNumerator integer numerator of a rational representation of the 444 * numeric value (encoded as a signed integer value) 445 * @param rationalDenominator integer denominator of a rational representation of the 446 * numeric value (encoded as a non-zero unsigned integer 447 * value) 448 * @param check if enabled, check values for validity before setting them. 449 * See checkRationalRepresentation() method for details. 450 ** @return status, EC_Normal if successful, an error code otherwise 451 */ 452 OFCondition setRationalRepresentation(const Sint32 rationalNumerator, 453 const Uint32 rationalDenominator, 454 const OFBool check = OFTrue); 455 456 /** remove floating point representation of the numeric value (if any). 457 * Internally, all elements that belong to this representation are cleared. 458 */ 459 void removeFloatingPointRepresentation(); 460 461 /** remove rational representation of the numeric value (if any). 462 * Internally, all elements that belong to this representation are cleared. 463 */ 464 void removeRationalRepresentation(); 465 466 467 protected: 468 469 /** get pointer to numeric measurement value 470 ** @return pointer to numeric measurement value (never NULL) 471 */ getValuePtr()472 inline DSRNumericMeasurementValue *getValuePtr() 473 { 474 return this; 475 } 476 477 /** read numeric measurement value from dataset 478 ** @param dataset DICOM dataset from which the value should be read 479 * @param flags flag used to customize the reading process (see DSRTypes::RF_xxx) 480 ** @return status, EC_Normal if successful, an error code otherwise 481 */ 482 virtual OFCondition readItem(DcmItem &dataset, 483 const size_t flags); 484 485 /** write numeric measurement value to dataset 486 ** @param dataset DICOM dataset to which the value should be written 487 ** @return status, EC_Normal if successful, an error code otherwise 488 */ 489 virtual OFCondition writeItem(DcmItem &dataset) const; 490 491 /** check the specified numeric value for validity. 492 * Currently, the only checks performed are that the string is non-empty and that the 493 * given value conforms to the corresponding VR (DS) and VM (1). 494 ** @param numericValue numeric value to be checked 495 ** @return status, EC_Normal if numeric value is valid, an error code otherwise 496 */ 497 virtual OFCondition checkNumericValue(const OFString &numericValue) const; 498 499 /** check the specified measurement unit for validity. 500 * Internally, the methods DSRCodedEntryValue::isEmpty() and 501 * DSRCodedEntryValue::checkCurrentValue() are used for this purpose. Conformance 502 * with the Context Group 82 (as defined in the DICOM standard) is not yet checked. 503 ** @param measurementUnit measurement unit to be checked 504 ** @return status, EC_Normal if measurement unit is valid, an error code otherwise 505 */ 506 virtual OFCondition checkMeasurementUnit(const DSRCodedEntryValue &measurementUnit) const; 507 508 /** check the specified numeric value qualifier for validity. 509 * Internally, DSRCodedEntryValue::isEmpty() and DSRCodedEntryValue::checkCurrentValue() 510 * are used for this purpose. Conformance with the Context Group 42 (as defined in the 511 * DICOM standard) is not checked; see class CMR_SRNumericMeasurementValue if needed, 512 * which supports such additional checks. 513 ** @param valueQualifier numeric value qualifier to be checked 514 ** @return status, EC_Normal if value qualifier is valid, an error code otherwise 515 */ 516 virtual OFCondition checkNumericValueQualifier(const DSRCodedEntryValue &valueQualifier) const; 517 518 /** check the specified rational representation for validity. 519 * The only check that is performed is that the 'rationalDenominator' is not zero, i.e. 520 * it is not checked whether this representation is consistent with the numeric value 521 * stored as a string. 522 ** @param rationalNumerator numerator of the rational representation to be checked 523 * @param rationalDenominator denominator of a rational representation to be checked 524 ** @return status, EC_Normal if rational representation is valid, an error code otherwise 525 */ 526 virtual OFCondition checkRationalRepresentation(const Sint32 rationalNumerator, 527 const Uint32 rationalDenominator) const; 528 529 /** check the currently stored numeric measurement value for validity. 530 * See above checkXXX() methods for details. 531 ** @return status, EC_Normal if current value is valid, an error code otherwise 532 */ 533 virtual OFCondition checkCurrentValue() const; 534 535 536 private: 537 538 /// Numeric Value (VR=DS, type 1 within a type 2 sequence) 539 OFString NumericValue; 540 /// Measurement Unit (type 1 within a type 2 sequence) 541 DSRCodedEntryValue MeasurementUnit; 542 /// Numeric Value Qualifier (type 3) 543 DSRCodedEntryValue ValueQualifier; 544 /// Floating Point Value (VR=FD, type 1C) 545 DcmFloatingPointDouble FloatingPointValue; 546 /// Rational Numerator Value (VR=SL, type 1C) 547 DcmSignedLong RationalNumeratorValue; 548 /// Rational Denominator Value (VR=UL, type 1C) 549 DcmUnsignedLong RationalDenominatorValue; 550 }; 551 552 553 /** output stream operator for numeric measurement values. 554 * Internally, the DSRNumericMeasurementValue::print() method is used, i.e. the output 555 * looks like this: "3.5" (cm,UCUM[1.4],"centimeter") or "empty" (if the value is empty) 556 * @param stream output stream to which the numeric measurement value is 557 * printed 558 * @param numericMeasurement numeric measurement value to be printed 559 * @return reference to output stream 560 */ 561 DCMTK_DCMSR_EXPORT STD_NAMESPACE ostream &operator<<(STD_NAMESPACE ostream &stream, 562 const DSRNumericMeasurementValue &numericMeasurement); 563 564 565 #endif 566