1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkMedicalImageProperties.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 /** 16 * @class vtkMedicalImageProperties 17 * @brief some medical image properties. 18 * 19 * vtkMedicalImageProperties is a helper class that can be used by medical 20 * image readers and applications to encapsulate medical image/acquisition 21 * properties. Later on, this should probably be extended to add 22 * any user-defined property. 23 * @sa 24 * vtkMedicalImageReader2 25 */ 26 27 #ifndef vtkMedicalImageProperties_h 28 #define vtkMedicalImageProperties_h 29 30 #include "vtkIOImageModule.h" // For export macro 31 #include "vtkObject.h" 32 33 class vtkMedicalImagePropertiesInternals; 34 35 class VTKIOIMAGE_EXPORT vtkMedicalImageProperties : public vtkObject 36 { 37 public: 38 static vtkMedicalImageProperties* New(); 39 vtkTypeMacro(vtkMedicalImageProperties, vtkObject); 40 void PrintSelf(ostream& os, vtkIndent indent) override; 41 42 /** 43 * Convenience method to reset all fields to an empty string/value 44 */ 45 virtual void Clear(); 46 47 ///@{ 48 /** 49 * Patient name 50 * For ex: DICOM (0010,0010) = DOE,JOHN 51 */ 52 vtkSetStringMacro(PatientName); 53 vtkGetStringMacro(PatientName); 54 ///@} 55 56 ///@{ 57 /** 58 * Patient ID 59 * For ex: DICOM (0010,0020) = 1933197 60 */ 61 vtkSetStringMacro(PatientID); 62 vtkGetStringMacro(PatientID); 63 ///@} 64 65 ///@{ 66 /** 67 * Patient age 68 * Format: nnnD, nnW, nnnM or nnnY (eventually nnD, nnW, nnY) 69 * with D (day), M (month), W (week), Y (year) 70 * For ex: DICOM (0010,1010) = 031Y 71 */ 72 vtkSetStringMacro(PatientAge); 73 vtkGetStringMacro(PatientAge); 74 ///@} 75 76 /** 77 * Take as input a string in VR=AS (DICOM PS3.5) and extract either 78 * different fields namely: year month week day 79 * Return 0 on error, 1 on success 80 * One can test fields if they are different from -1 upon success 81 */ 82 static int GetAgeAsFields(const char* age, int& year, int& month, int& week, int& day); 83 84 // For Tcl: 85 // From C++ use GetPatientAge + GetAgeAsField 86 // Those function parse a DICOM string, and return the value of the number 87 // expressed this is either expressed in year, month or days. Thus if a 88 // string is expressed in years 89 // GetPatientAgeDay/GetPatientAgeWeek/GetPatientAgeMonth will return 0 90 int GetPatientAgeYear(); 91 int GetPatientAgeMonth(); 92 int GetPatientAgeWeek(); 93 int GetPatientAgeDay(); 94 95 ///@{ 96 /** 97 * Patient sex 98 * For ex: DICOM (0010,0040) = M 99 */ 100 vtkSetStringMacro(PatientSex); 101 vtkGetStringMacro(PatientSex); 102 ///@} 103 104 ///@{ 105 /** 106 * Patient birth date 107 * Format: yyyymmdd 108 * For ex: DICOM (0010,0030) = 19680427 109 */ 110 vtkSetStringMacro(PatientBirthDate); 111 vtkGetStringMacro(PatientBirthDate); 112 ///@} 113 114 // For Tcl: 115 // From C++ use GetPatientBirthDate + GetDateAsFields 116 int GetPatientBirthDateYear(); 117 int GetPatientBirthDateMonth(); 118 int GetPatientBirthDateDay(); 119 120 ///@{ 121 /** 122 * Study Date 123 * Format: yyyymmdd 124 * For ex: DICOM (0008,0020) = 20030617 125 */ 126 vtkSetStringMacro(StudyDate); 127 vtkGetStringMacro(StudyDate); 128 ///@} 129 130 ///@{ 131 /** 132 * Acquisition Date 133 * Format: yyyymmdd 134 * For ex: DICOM (0008,0022) = 20030617 135 */ 136 vtkSetStringMacro(AcquisitionDate); 137 vtkGetStringMacro(AcquisitionDate); 138 ///@} 139 140 // For Tcl: 141 // From C++ use GetAcquisitionDate + GetDateAsFields 142 int GetAcquisitionDateYear(); 143 int GetAcquisitionDateMonth(); 144 int GetAcquisitionDateDay(); 145 146 ///@{ 147 /** 148 * Study Time 149 * Format: hhmmss.frac (any trailing component(s) can be omitted) 150 * For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 151 */ 152 vtkSetStringMacro(StudyTime); 153 vtkGetStringMacro(StudyTime); 154 ///@} 155 156 ///@{ 157 /** 158 * Acquisition time 159 * Format: hhmmss.frac (any trailing component(s) can be omitted) 160 * For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 161 */ 162 vtkSetStringMacro(AcquisitionTime); 163 vtkGetStringMacro(AcquisitionTime); 164 ///@} 165 166 ///@{ 167 /** 168 * Image Date aka Content Date 169 * Format: yyyymmdd 170 * For ex: DICOM (0008,0023) = 20030617 171 */ 172 vtkSetStringMacro(ImageDate); 173 vtkGetStringMacro(ImageDate); 174 ///@} 175 176 // For Tcl: 177 // From C++ use GetImageDate + GetDateAsFields 178 int GetImageDateYear(); 179 int GetImageDateMonth(); 180 int GetImageDateDay(); 181 182 /** 183 * Take as input a string in ISO 8601 date (YYYY/MM/DD) and extract the 184 * different fields namely: year month day 185 * Return 0 on error, 1 on success 186 */ 187 static int GetDateAsFields(const char* date, int& year, int& month, int& day); 188 189 /** 190 * Take as input a string in VR:TM format (HHMMSS) and extract the 191 * different fields namely: hour, minute and second 192 * Return 0 on error, 1 on success 193 */ 194 static int GetTimeAsFields( 195 const char* time, int& hour, int& minute, int& second /* , long &milliseconds */); 196 197 /** 198 * Take as input a string in ISO 8601 date (YYYY/MM/DD) and construct a 199 * locale date based on the different fields (see GetDateAsFields to extract 200 * different fields) 201 * Return 0 on error, 1 on success 202 */ 203 static int GetDateAsLocale(const char* date, char* locale); 204 205 ///@{ 206 /** 207 * Image Time 208 * Format: hhmmss.frac (any trailing component(s) can be omitted) 209 * For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 210 */ 211 vtkSetStringMacro(ImageTime); 212 vtkGetStringMacro(ImageTime); 213 ///@} 214 215 ///@{ 216 /** 217 * Image number 218 * For ex: DICOM (0020,0013) = 1 219 */ 220 vtkSetStringMacro(ImageNumber); 221 vtkGetStringMacro(ImageNumber); 222 ///@} 223 224 ///@{ 225 /** 226 * Series number 227 * For ex: DICOM (0020,0011) = 902 228 */ 229 vtkSetStringMacro(SeriesNumber); 230 vtkGetStringMacro(SeriesNumber); 231 ///@} 232 233 ///@{ 234 /** 235 * Series Description 236 * User provided description of the Series 237 * For ex: DICOM (0008,103e) = SCOUT 238 */ 239 vtkSetStringMacro(SeriesDescription); 240 vtkGetStringMacro(SeriesDescription); 241 ///@} 242 243 ///@{ 244 /** 245 * Study ID 246 * For ex: DICOM (0020,0010) = 37481 247 */ 248 vtkSetStringMacro(StudyID); 249 vtkGetStringMacro(StudyID); 250 ///@} 251 252 ///@{ 253 /** 254 * Study description 255 * For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL 256 */ 257 vtkSetStringMacro(StudyDescription); 258 vtkGetStringMacro(StudyDescription); 259 ///@} 260 261 ///@{ 262 /** 263 * Modality 264 * For ex: DICOM (0008,0060)= CT 265 */ 266 vtkSetStringMacro(Modality); 267 vtkGetStringMacro(Modality); 268 ///@} 269 270 ///@{ 271 /** 272 * Manufacturer 273 * For ex: DICOM (0008,0070) = Siemens 274 */ 275 vtkSetStringMacro(Manufacturer); 276 vtkGetStringMacro(Manufacturer); 277 ///@} 278 279 ///@{ 280 /** 281 * Manufacturer's Model Name 282 * For ex: DICOM (0008,1090) = LightSpeed QX/i 283 */ 284 vtkSetStringMacro(ManufacturerModelName); 285 vtkGetStringMacro(ManufacturerModelName); 286 ///@} 287 288 ///@{ 289 /** 290 * Station Name 291 * For ex: DICOM (0008,1010) = LSPD_OC8 292 */ 293 vtkSetStringMacro(StationName); 294 vtkGetStringMacro(StationName); 295 ///@} 296 297 ///@{ 298 /** 299 * Institution Name 300 * For ex: DICOM (0008,0080) = FooCity Medical Center 301 */ 302 vtkSetStringMacro(InstitutionName); 303 vtkGetStringMacro(InstitutionName); 304 ///@} 305 306 ///@{ 307 /** 308 * Convolution Kernel (or algorithm used to reconstruct the data) 309 * For ex: DICOM (0018,1210) = Bone 310 */ 311 vtkSetStringMacro(ConvolutionKernel); 312 vtkGetStringMacro(ConvolutionKernel); 313 ///@} 314 315 ///@{ 316 /** 317 * Slice Thickness (Nominal reconstructed slice thickness, in mm) 318 * For ex: DICOM (0018,0050) = 0.273438 319 */ 320 vtkSetStringMacro(SliceThickness); 321 vtkGetStringMacro(SliceThickness); 322 virtual double GetSliceThicknessAsDouble(); 323 ///@} 324 325 ///@{ 326 /** 327 * Peak kilo voltage output of the (x-ray) generator used 328 * For ex: DICOM (0018,0060) = 120 329 */ 330 vtkSetStringMacro(KVP); 331 vtkGetStringMacro(KVP); 332 ///@} 333 334 ///@{ 335 /** 336 * Gantry/Detector tilt (Nominal angle of tilt in degrees of the scanning 337 * gantry.) 338 * For ex: DICOM (0018,1120) = 15 339 */ 340 vtkSetStringMacro(GantryTilt); 341 vtkGetStringMacro(GantryTilt); 342 virtual double GetGantryTiltAsDouble(); 343 ///@} 344 345 ///@{ 346 /** 347 * Echo Time 348 * (Time in ms between the middle of the excitation pulse and the peak of 349 * the echo produced) 350 * For ex: DICOM (0018,0081) = 105 351 */ 352 vtkSetStringMacro(EchoTime); 353 vtkGetStringMacro(EchoTime); 354 ///@} 355 356 ///@{ 357 /** 358 * Echo Train Length 359 * (Number of lines in k-space acquired per excitation per image) 360 * For ex: DICOM (0018,0091) = 35 361 */ 362 vtkSetStringMacro(EchoTrainLength); 363 vtkGetStringMacro(EchoTrainLength); 364 ///@} 365 366 ///@{ 367 /** 368 * Repetition Time 369 * The period of time in msec between the beginning of a pulse sequence and 370 * the beginning of the succeeding (essentially identical) pulse sequence. 371 * For ex: DICOM (0018,0080) = 2040 372 */ 373 vtkSetStringMacro(RepetitionTime); 374 vtkGetStringMacro(RepetitionTime); 375 ///@} 376 377 ///@{ 378 /** 379 * Exposure time (time of x-ray exposure in msec) 380 * For ex: DICOM (0018,1150) = 5 381 */ 382 vtkSetStringMacro(ExposureTime); 383 vtkGetStringMacro(ExposureTime); 384 ///@} 385 386 ///@{ 387 /** 388 * X-ray tube current (in mA) 389 * For ex: DICOM (0018,1151) = 400 390 */ 391 vtkSetStringMacro(XRayTubeCurrent); 392 vtkGetStringMacro(XRayTubeCurrent); 393 ///@} 394 395 ///@{ 396 /** 397 * Exposure (The exposure expressed in mAs, for example calculated 398 * from Exposure Time and X-ray Tube Current) 399 * For ex: DICOM (0018,1152) = 114 400 */ 401 vtkSetStringMacro(Exposure); 402 vtkGetStringMacro(Exposure); 403 ///@} 404 405 ///@{ 406 /** 407 * Get the direction cosine (default to 1,0,0,0,1,0) 408 */ 409 vtkSetVector6Macro(DirectionCosine, double); 410 vtkGetVector6Macro(DirectionCosine, double); 411 ///@} 412 413 // Interface to allow insertion of user define values, for instance in DICOM 414 // one would want to 415 // store the Protocol Name (0018,1030), in this case one would do: 416 // AddUserDefinedValue( "Protocol Name", "T1W/SE/1024" ); 417 virtual void AddUserDefinedValue(const char* name, const char* value); 418 virtual const char* GetUserDefinedValue(const char* name); 419 virtual unsigned int GetNumberOfUserDefinedValues(); 420 virtual const char* GetUserDefinedNameByIndex(unsigned int idx); 421 virtual const char* GetUserDefinedValueByIndex(unsigned int idx); 422 virtual void RemoveAllUserDefinedValues(); 423 424 ///@{ 425 /** 426 * Add/Remove/Query the window/level presets that may have been associated 427 * to a medical image. Window is also known as 'width', level is also known 428 * as 'center'. The same window/level pair can not be added twice. 429 * As a convenience, a comment (aka Explanation) can be associated to 430 * a preset. 431 * For ex: 432 * \verbatim 433 * DICOM Window Center (0028,1050) = 00045\000470 434 * DICOM Window Width (0028,1051) = 0106\03412 435 * DICOM Window Center Width Explanation (0028,1055) = WINDOW1\WINDOW2 436 * \endverbatim 437 */ 438 virtual int AddWindowLevelPreset(double w, double l); 439 virtual void RemoveWindowLevelPreset(double w, double l); 440 virtual void RemoveAllWindowLevelPresets(); 441 virtual int GetNumberOfWindowLevelPresets(); 442 virtual int HasWindowLevelPreset(double w, double l); 443 virtual int GetWindowLevelPresetIndex(double w, double l); 444 virtual int GetNthWindowLevelPreset(int idx, double* w, double* l); 445 virtual double* GetNthWindowLevelPreset(int idx) VTK_SIZEHINT(2); 446 virtual void SetNthWindowLevelPresetComment(int idx, const char* comment); 447 virtual const char* GetNthWindowLevelPresetComment(int idx); 448 ///@} 449 450 ///@{ 451 /** 452 * Mapping from a sliceidx within a volumeidx into a DICOM Instance UID 453 * Some DICOM reader can populate this structure so that later on from 454 * a slice index in a vtkImageData volume we can backtrack and find out 455 * which 2d slice it was coming from 456 */ 457 const char* GetInstanceUIDFromSliceID(int volumeidx, int sliceid); 458 void SetInstanceUIDFromSliceID(int volumeidx, int sliceid, const char* uid); 459 ///@} 460 461 /** 462 * Provides the inverse mapping. Returns -1 if a slice for this uid is 463 * not found. 464 */ 465 int GetSliceIDFromInstanceUID(int& volumeidx, const char* uid); 466 467 typedef enum 468 { 469 AXIAL = 0, 470 CORONAL, 471 SAGITTAL 472 } OrientationType; 473 474 int GetOrientationType(int volumeidx); 475 void SetOrientationType(int volumeidx, int orientation); 476 static const char* GetStringFromOrientationType(unsigned int type); 477 478 /** 479 * Copy the contents of p to this instance. 480 */ 481 virtual void DeepCopy(vtkMedicalImageProperties* p); 482 483 protected: 484 vtkMedicalImageProperties(); 485 ~vtkMedicalImageProperties() override; 486 487 char* StudyDate; 488 char* AcquisitionDate; 489 char* StudyTime; 490 char* AcquisitionTime; 491 char* ConvolutionKernel; 492 char* EchoTime; 493 char* EchoTrainLength; 494 char* Exposure; 495 char* ExposureTime; 496 char* GantryTilt; 497 char* ImageDate; 498 char* ImageNumber; 499 char* ImageTime; 500 char* InstitutionName; 501 char* KVP; 502 char* ManufacturerModelName; 503 char* Manufacturer; 504 char* Modality; 505 char* PatientAge; 506 char* PatientBirthDate; 507 char* PatientID; 508 char* PatientName; 509 char* PatientSex; 510 char* RepetitionTime; 511 char* SeriesDescription; 512 char* SeriesNumber; 513 char* SliceThickness; 514 char* StationName; 515 char* StudyDescription; 516 char* StudyID; 517 char* XRayTubeCurrent; 518 double DirectionCosine[6]; 519 520 /** 521 * PIMPL Encapsulation for STL containers 522 */ 523 vtkMedicalImagePropertiesInternals* Internals; 524 525 private: 526 vtkMedicalImageProperties(const vtkMedicalImageProperties&) = delete; 527 void operator=(const vtkMedicalImageProperties&) = delete; 528 }; 529 530 #endif 531