/*========================================================================= Program: Visualization Toolkit Module: vtkMedicalImageProperties.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkMedicalImageProperties * @brief some medical image properties. * * vtkMedicalImageProperties is a helper class that can be used by medical * image readers and applications to encapsulate medical image/acquisition * properties. Later on, this should probably be extended to add * any user-defined property. * @sa * vtkMedicalImageReader2 */ #ifndef vtkMedicalImageProperties_h #define vtkMedicalImageProperties_h #include "vtkIOImageModule.h" // For export macro #include "vtkObject.h" class vtkMedicalImagePropertiesInternals; class VTKIOIMAGE_EXPORT vtkMedicalImageProperties : public vtkObject { public: static vtkMedicalImageProperties* New(); vtkTypeMacro(vtkMedicalImageProperties, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Convenience method to reset all fields to an empty string/value */ virtual void Clear(); ///@{ /** * Patient name * For ex: DICOM (0010,0010) = DOE,JOHN */ vtkSetStringMacro(PatientName); vtkGetStringMacro(PatientName); ///@} ///@{ /** * Patient ID * For ex: DICOM (0010,0020) = 1933197 */ vtkSetStringMacro(PatientID); vtkGetStringMacro(PatientID); ///@} ///@{ /** * Patient age * Format: nnnD, nnW, nnnM or nnnY (eventually nnD, nnW, nnY) * with D (day), M (month), W (week), Y (year) * For ex: DICOM (0010,1010) = 031Y */ vtkSetStringMacro(PatientAge); vtkGetStringMacro(PatientAge); ///@} /** * Take as input a string in VR=AS (DICOM PS3.5) and extract either * different fields namely: year month week day * Return 0 on error, 1 on success * One can test fields if they are different from -1 upon success */ static int GetAgeAsFields(const char* age, int& year, int& month, int& week, int& day); // For Tcl: // From C++ use GetPatientAge + GetAgeAsField // Those function parse a DICOM string, and return the value of the number // expressed this is either expressed in year, month or days. Thus if a // string is expressed in years // GetPatientAgeDay/GetPatientAgeWeek/GetPatientAgeMonth will return 0 int GetPatientAgeYear(); int GetPatientAgeMonth(); int GetPatientAgeWeek(); int GetPatientAgeDay(); ///@{ /** * Patient sex * For ex: DICOM (0010,0040) = M */ vtkSetStringMacro(PatientSex); vtkGetStringMacro(PatientSex); ///@} ///@{ /** * Patient birth date * Format: yyyymmdd * For ex: DICOM (0010,0030) = 19680427 */ vtkSetStringMacro(PatientBirthDate); vtkGetStringMacro(PatientBirthDate); ///@} // For Tcl: // From C++ use GetPatientBirthDate + GetDateAsFields int GetPatientBirthDateYear(); int GetPatientBirthDateMonth(); int GetPatientBirthDateDay(); ///@{ /** * Study Date * Format: yyyymmdd * For ex: DICOM (0008,0020) = 20030617 */ vtkSetStringMacro(StudyDate); vtkGetStringMacro(StudyDate); ///@} ///@{ /** * Acquisition Date * Format: yyyymmdd * For ex: DICOM (0008,0022) = 20030617 */ vtkSetStringMacro(AcquisitionDate); vtkGetStringMacro(AcquisitionDate); ///@} // For Tcl: // From C++ use GetAcquisitionDate + GetDateAsFields int GetAcquisitionDateYear(); int GetAcquisitionDateMonth(); int GetAcquisitionDateDay(); ///@{ /** * Study Time * Format: hhmmss.frac (any trailing component(s) can be omitted) * For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 */ vtkSetStringMacro(StudyTime); vtkGetStringMacro(StudyTime); ///@} ///@{ /** * Acquisition time * Format: hhmmss.frac (any trailing component(s) can be omitted) * For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 */ vtkSetStringMacro(AcquisitionTime); vtkGetStringMacro(AcquisitionTime); ///@} ///@{ /** * Image Date aka Content Date * Format: yyyymmdd * For ex: DICOM (0008,0023) = 20030617 */ vtkSetStringMacro(ImageDate); vtkGetStringMacro(ImageDate); ///@} // For Tcl: // From C++ use GetImageDate + GetDateAsFields int GetImageDateYear(); int GetImageDateMonth(); int GetImageDateDay(); /** * Take as input a string in ISO 8601 date (YYYY/MM/DD) and extract the * different fields namely: year month day * Return 0 on error, 1 on success */ static int GetDateAsFields(const char* date, int& year, int& month, int& day); /** * Take as input a string in VR:TM format (HHMMSS) and extract the * different fields namely: hour, minute and second * Return 0 on error, 1 on success */ static int GetTimeAsFields( const char* time, int& hour, int& minute, int& second /* , long &milliseconds */); /** * Take as input a string in ISO 8601 date (YYYY/MM/DD) and construct a * locale date based on the different fields (see GetDateAsFields to extract * different fields) * Return 0 on error, 1 on success */ static int GetDateAsLocale(const char* date, char* locale); ///@{ /** * Image Time * Format: hhmmss.frac (any trailing component(s) can be omitted) * For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 */ vtkSetStringMacro(ImageTime); vtkGetStringMacro(ImageTime); ///@} ///@{ /** * Image number * For ex: DICOM (0020,0013) = 1 */ vtkSetStringMacro(ImageNumber); vtkGetStringMacro(ImageNumber); ///@} ///@{ /** * Series number * For ex: DICOM (0020,0011) = 902 */ vtkSetStringMacro(SeriesNumber); vtkGetStringMacro(SeriesNumber); ///@} ///@{ /** * Series Description * User provided description of the Series * For ex: DICOM (0008,103e) = SCOUT */ vtkSetStringMacro(SeriesDescription); vtkGetStringMacro(SeriesDescription); ///@} ///@{ /** * Study ID * For ex: DICOM (0020,0010) = 37481 */ vtkSetStringMacro(StudyID); vtkGetStringMacro(StudyID); ///@} ///@{ /** * Study description * For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL */ vtkSetStringMacro(StudyDescription); vtkGetStringMacro(StudyDescription); ///@} ///@{ /** * Modality * For ex: DICOM (0008,0060)= CT */ vtkSetStringMacro(Modality); vtkGetStringMacro(Modality); ///@} ///@{ /** * Manufacturer * For ex: DICOM (0008,0070) = Siemens */ vtkSetStringMacro(Manufacturer); vtkGetStringMacro(Manufacturer); ///@} ///@{ /** * Manufacturer's Model Name * For ex: DICOM (0008,1090) = LightSpeed QX/i */ vtkSetStringMacro(ManufacturerModelName); vtkGetStringMacro(ManufacturerModelName); ///@} ///@{ /** * Station Name * For ex: DICOM (0008,1010) = LSPD_OC8 */ vtkSetStringMacro(StationName); vtkGetStringMacro(StationName); ///@} ///@{ /** * Institution Name * For ex: DICOM (0008,0080) = FooCity Medical Center */ vtkSetStringMacro(InstitutionName); vtkGetStringMacro(InstitutionName); ///@} ///@{ /** * Convolution Kernel (or algorithm used to reconstruct the data) * For ex: DICOM (0018,1210) = Bone */ vtkSetStringMacro(ConvolutionKernel); vtkGetStringMacro(ConvolutionKernel); ///@} ///@{ /** * Slice Thickness (Nominal reconstructed slice thickness, in mm) * For ex: DICOM (0018,0050) = 0.273438 */ vtkSetStringMacro(SliceThickness); vtkGetStringMacro(SliceThickness); virtual double GetSliceThicknessAsDouble(); ///@} ///@{ /** * Peak kilo voltage output of the (x-ray) generator used * For ex: DICOM (0018,0060) = 120 */ vtkSetStringMacro(KVP); vtkGetStringMacro(KVP); ///@} ///@{ /** * Gantry/Detector tilt (Nominal angle of tilt in degrees of the scanning * gantry.) * For ex: DICOM (0018,1120) = 15 */ vtkSetStringMacro(GantryTilt); vtkGetStringMacro(GantryTilt); virtual double GetGantryTiltAsDouble(); ///@} ///@{ /** * Echo Time * (Time in ms between the middle of the excitation pulse and the peak of * the echo produced) * For ex: DICOM (0018,0081) = 105 */ vtkSetStringMacro(EchoTime); vtkGetStringMacro(EchoTime); ///@} ///@{ /** * Echo Train Length * (Number of lines in k-space acquired per excitation per image) * For ex: DICOM (0018,0091) = 35 */ vtkSetStringMacro(EchoTrainLength); vtkGetStringMacro(EchoTrainLength); ///@} ///@{ /** * Repetition Time * The period of time in msec between the beginning of a pulse sequence and * the beginning of the succeeding (essentially identical) pulse sequence. * For ex: DICOM (0018,0080) = 2040 */ vtkSetStringMacro(RepetitionTime); vtkGetStringMacro(RepetitionTime); ///@} ///@{ /** * Exposure time (time of x-ray exposure in msec) * For ex: DICOM (0018,1150) = 5 */ vtkSetStringMacro(ExposureTime); vtkGetStringMacro(ExposureTime); ///@} ///@{ /** * X-ray tube current (in mA) * For ex: DICOM (0018,1151) = 400 */ vtkSetStringMacro(XRayTubeCurrent); vtkGetStringMacro(XRayTubeCurrent); ///@} ///@{ /** * Exposure (The exposure expressed in mAs, for example calculated * from Exposure Time and X-ray Tube Current) * For ex: DICOM (0018,1152) = 114 */ vtkSetStringMacro(Exposure); vtkGetStringMacro(Exposure); ///@} ///@{ /** * Get the direction cosine (default to 1,0,0,0,1,0) */ vtkSetVector6Macro(DirectionCosine, double); vtkGetVector6Macro(DirectionCosine, double); ///@} // Interface to allow insertion of user define values, for instance in DICOM // one would want to // store the Protocol Name (0018,1030), in this case one would do: // AddUserDefinedValue( "Protocol Name", "T1W/SE/1024" ); virtual void AddUserDefinedValue(const char* name, const char* value); virtual const char* GetUserDefinedValue(const char* name); virtual unsigned int GetNumberOfUserDefinedValues(); virtual const char* GetUserDefinedNameByIndex(unsigned int idx); virtual const char* GetUserDefinedValueByIndex(unsigned int idx); virtual void RemoveAllUserDefinedValues(); ///@{ /** * Add/Remove/Query the window/level presets that may have been associated * to a medical image. Window is also known as 'width', level is also known * as 'center'. The same window/level pair can not be added twice. * As a convenience, a comment (aka Explanation) can be associated to * a preset. * For ex: * \verbatim * DICOM Window Center (0028,1050) = 00045\000470 * DICOM Window Width (0028,1051) = 0106\03412 * DICOM Window Center Width Explanation (0028,1055) = WINDOW1\WINDOW2 * \endverbatim */ virtual int AddWindowLevelPreset(double w, double l); virtual void RemoveWindowLevelPreset(double w, double l); virtual void RemoveAllWindowLevelPresets(); virtual int GetNumberOfWindowLevelPresets(); virtual int HasWindowLevelPreset(double w, double l); virtual int GetWindowLevelPresetIndex(double w, double l); virtual int GetNthWindowLevelPreset(int idx, double* w, double* l); virtual double* GetNthWindowLevelPreset(int idx) VTK_SIZEHINT(2); virtual void SetNthWindowLevelPresetComment(int idx, const char* comment); virtual const char* GetNthWindowLevelPresetComment(int idx); ///@} ///@{ /** * Mapping from a sliceidx within a volumeidx into a DICOM Instance UID * Some DICOM reader can populate this structure so that later on from * a slice index in a vtkImageData volume we can backtrack and find out * which 2d slice it was coming from */ const char* GetInstanceUIDFromSliceID(int volumeidx, int sliceid); void SetInstanceUIDFromSliceID(int volumeidx, int sliceid, const char* uid); ///@} /** * Provides the inverse mapping. Returns -1 if a slice for this uid is * not found. */ int GetSliceIDFromInstanceUID(int& volumeidx, const char* uid); typedef enum { AXIAL = 0, CORONAL, SAGITTAL } OrientationType; int GetOrientationType(int volumeidx); void SetOrientationType(int volumeidx, int orientation); static const char* GetStringFromOrientationType(unsigned int type); /** * Copy the contents of p to this instance. */ virtual void DeepCopy(vtkMedicalImageProperties* p); protected: vtkMedicalImageProperties(); ~vtkMedicalImageProperties() override; char* StudyDate; char* AcquisitionDate; char* StudyTime; char* AcquisitionTime; char* ConvolutionKernel; char* EchoTime; char* EchoTrainLength; char* Exposure; char* ExposureTime; char* GantryTilt; char* ImageDate; char* ImageNumber; char* ImageTime; char* InstitutionName; char* KVP; char* ManufacturerModelName; char* Manufacturer; char* Modality; char* PatientAge; char* PatientBirthDate; char* PatientID; char* PatientName; char* PatientSex; char* RepetitionTime; char* SeriesDescription; char* SeriesNumber; char* SliceThickness; char* StationName; char* StudyDescription; char* StudyID; char* XRayTubeCurrent; double DirectionCosine[6]; /** * PIMPL Encapsulation for STL containers */ vtkMedicalImagePropertiesInternals* Internals; private: vtkMedicalImageProperties(const vtkMedicalImageProperties&) = delete; void operator=(const vtkMedicalImageProperties&) = delete; }; #endif