1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 /** 19 * \file itkPhilipsPAR.h 20 * The code for this file reader was written based on 21 * examination of Philips REC/PAR image files acquired at the 22 * Center for NMR Research at the Penn State Milton S. Hershey 23 * Medical Center. 24 * 25 * 26 * \author Don C. Bigler 27 * The Pennsylvania State University 2005 28 * 29 * This implementation was contributed as a paper to the Insight Journal 30 * https://hdl.handle.net/1926/1381 31 * 32 */ 33 34 #ifndef itkPhilipsPAR_h 35 #define itkPhilipsPAR_h 36 #include "ITKIOPhilipsRECExport.h" 37 38 #include <cstdio> 39 #include <cstdlib> 40 #include <string> 41 #include "itkLightProcessObject.h" 42 #include "itkVectorContainer.h" 43 #include "vnl/vnl_vector_fixed.h" 44 45 #define RESEARCH_IMAGE_EXPORT_TOOL_V3 30 46 #define RESEARCH_IMAGE_EXPORT_TOOL_V4 40 47 #define RESEARCH_IMAGE_EXPORT_TOOL_V4_1 41 48 #define RESEARCH_IMAGE_EXPORT_TOOL_V4_2 42 49 #define RESEARCH_IMAGE_EXPORT_TOOL_UNKNOWN -1 50 51 #define PAR_DEFAULT_STRING_LENGTH 32 52 #define PAR_DEFAULT_TRIGGER_TIMES_SIZE 128 53 #define PAR_DEFAULT_ECHO_TIMES_SIZE 128 54 #define PAR_DEFAULT_REP_TIMES_SIZE 128 55 #define PAR_DEFAULT_IMAGE_TYPES_SIZE 8 56 #define PAR_DEFAULT_SCAN_SEQUENCE_SIZE 8 57 #define PAR_RESCALE_VALUES_SIZE 3 58 #define PAR_DIFFUSION_VALUES_SIZE 3 59 60 #define PAR_SLICE_ORIENTATION_TRANSVERSAL 1 61 #define PAR_SLICE_ORIENTATION_SAGITTAL 2 62 #define PAR_SLICE_ORIENTATION_CORONAL 3 63 64 namespace itk 65 { 66 /** 67 * \struct par_parameter 68 */ 69 struct par_parameter //par_parameter 70 { 71 int problemreading; // Marked 1 if problem 72 // occurred reading in 73 // PAR file 74 int ResToolsVersion; // V3, V4, V4.1, or 75 // V4.2 PAR/REC 76 // version 77 char patient_name[PAR_DEFAULT_STRING_LENGTH]; // Patient name 78 char exam_name[PAR_DEFAULT_STRING_LENGTH]; // Examination name 79 char protocol_name[PAR_DEFAULT_STRING_LENGTH]; // Protocol name 80 char exam_date[PAR_DEFAULT_STRING_LENGTH]; // Examination 81 // date/time 82 char exam_time[PAR_DEFAULT_STRING_LENGTH]; // Examination 83 // date/time 84 char series_type[PAR_DEFAULT_STRING_LENGTH]; // Series Type 85 int scno; // Acquisition nr 86 int recno; // Reconstruction nr 87 int scan_duration; // Scan Duration [sec] 88 int cardiac_phases; // Max. number of 89 // cardiac phases 90 float trigger_times[PAR_DEFAULT_TRIGGER_TIMES_SIZE]; // trigger_time 91 // (float) 92 int echoes; // Max. number of 93 // echoes 94 float echo_times[PAR_DEFAULT_ECHO_TIMES_SIZE]; // Echo times read 95 // from PAR file 96 int slice; // Max. number of 97 // slices/locations 98 int dyn; // Max. number of 99 // dynamics 100 int mixes; // Max. number of 101 // mixes 102 char patient_position[PAR_DEFAULT_STRING_LENGTH]; // Patient position 103 char prep_direction[PAR_DEFAULT_STRING_LENGTH]; // Preparation 104 // direction 105 short int bit; // Image pixel size [8 106 // or 16 bits] 107 char technique[PAR_DEFAULT_STRING_LENGTH]; // Technique 108 char scan_mode[PAR_DEFAULT_STRING_LENGTH]; // Scan mode 109 int num_averages; // Number of averages 110 int scan_resolution[2]; // Scan resolution 111 // (x, y) 112 int scan_percent; // Scan percentage 113 int dim[3]; // Recon resolution 114 // (x, y) + slices (z) 115 float repetition_time[PAR_DEFAULT_REP_TIMES_SIZE]; // Repetition time 116 // [msec] 117 int sliceorient; // slice orientation ( 118 // TRA/SAG/COR ) 119 // (integer) 120 float slth; // Slice thickness 121 // [mm] 122 float gap; // Slice gap [mm] 123 float fov[3]; // FOV (ap,fh,rl) [mm] 124 float water_fat_shift; // Water Fat shift 125 // [pixels] 126 float angAP; // Angulation 127 // midslice(ap,fh,rl)[degr] 128 float angFH; // Angulation 129 // midslice(ap,fh,rl)[degr] 130 float angRL; // Angulation 131 // midslice(ap,fh,rl)[degr] 132 float offAP; // Off Centre 133 // midslice(ap,fh,rl) 134 // [mm] 135 float offFH; // Off Centre 136 // midslice(ap,fh,rl) 137 // [mm] 138 float offRL; // Off Centre 139 // midslice(ap,fh,rl) 140 // [mm] 141 int flow_comp; // Flow compensation 142 // <0=no 1=yes> ? 143 int presaturation; // Presaturation 144 // <0=no 1=yes> ? 145 int cardiac_freq; // Cardiac frequency 146 int min_rr_int; // Min. RR interval 147 int max_rr_int; // Max. RR interval 148 float phase_encode_vel[3]; // Phase encoding 149 // velocity [cm/sec] 150 int mtc; // MTC 151 // <0=no 152 // 1=yes> ? 153 int spir; // SPIR 154 // <0=no 155 // 1=yes> ? 156 int epi; // EPI factor 157 // <0,1=no EPI> 158 int turbo; // TURBO factor 159 // <0=no turbo> 160 int dynamic_scan; // Dynamic scan 161 // <0=no 1=yes> ? 162 int diffusion; // Diffusion 163 // <0=no 164 // 1=yes> ? 165 float diff_echo; // Diffusion echo time 166 // [msec] 167 float inversion_delay; // Inversion delay 168 // [msec] 169 int max_num_diff_vals; // Max. number of 170 // diffusion values 171 int max_num_grad_orient; // Max. number of 172 // gradient orients 173 int num_label_types; // Number of label 174 // types <0=no ASL> 175 float vox[3]; // pixel spacing (x,y) 176 // (in mm) 177 int slicessorted; // 1-slices sorted, 178 // 0-slices not sorted 179 int image_blocks; // The total number of 180 // image blocks stored 181 // in the REC file 182 int num_image_types; // The number of image 183 // types in the REC 184 // file 185 int image_types[PAR_DEFAULT_IMAGE_TYPES_SIZE]; // The different image 186 // types 187 // detected in the REC 188 int num_scanning_sequences; // The number of 189 // scanning sequences 190 // in the REC file 191 int scanning_sequences[PAR_DEFAULT_SCAN_SEQUENCE_SIZE]; // The different 192 // scanning sequences 193 // detected in the REC 194 int num_slice_repetitions; // If 195 // num_scanning_sequences 196 // > 1 then 197 // num_image_types may not equal the total number of slice 198 // repetitions for a single acquisition. This value is the 199 // total number of slice repetitions for a single acquisition 200 // and is valid only when slicessorted == 0. 201 }; 202 203 /** \class PhilipsPAR 204 * \brief Read parameters from a Philips PAR file. 205 * 206 * \sa PhilipsRECImageIO 207 * 208 * \ingroup IOFilters 209 * 210 * \ingroup ITKIOPhilipsREC 211 */ 212 class ITKIOPhilipsREC_EXPORT PhilipsPAR:public LightProcessObject 213 { 214 public: 215 ITK_DISALLOW_COPY_AND_ASSIGN(PhilipsPAR); 216 217 /** Standard class type aliases. */ 218 using Self = PhilipsPAR; 219 using Superclass = LightProcessObject; 220 using Pointer = SmartPointer< Self >; 221 222 /** Method for creation through the object factory. */ 223 itkNewMacro(Self); 224 225 /** Run-time type information (and related methods). */ 226 itkTypeMacro(PhilipsPAR, Superclass); 227 228 // Reads the PAR file parameters in "parFile" and stores the PAR parameters in 229 // pPar. 230 // Returns false if an error is encountered during reading, otherwise true is 231 // returned. 232 void ReadPAR(std::string parFile, struct par_parameter *pPar); 233 234 // Returns a vector of paired values, the first contains the slice index and 235 // the 236 // second is the image type for the PAR file "parFile". 237 using PARSliceIndexImageType = std::pair< int, int >; 238 using PARSliceIndexImageTypeVector = std::vector< PARSliceIndexImageType >; 239 PARSliceIndexImageTypeVector GetRECSliceIndexImageTypes( 240 std::string parFile); 241 242 // Returns a vector of paired values, the first contains the slice index and 243 // the 244 // second is the scan sequence for the PAR file "parFile". 245 using PARSliceIndexScanSequence = std::pair< int, int >; 246 using PARSliceIndexScanSequenceVector = std::vector< PARSliceIndexScanSequence >; 247 PARSliceIndexScanSequenceVector GetRECSliceIndexScanningSequence( 248 std::string parFile); 249 250 // Returns a vector of paired values, the first contains the image type and 251 // the 252 // second is the scan sequence for that image type for the PAR file "parFile". 253 using PARImageTypeScanSequence = std::pair< int, int >; 254 using PARImageTypeScanSequenceVector = std::vector< PARImageTypeScanSequence >; 255 PARImageTypeScanSequenceVector GetImageTypesScanningSequence( 256 std::string parFile); 257 258 // Stores rescale values in the VectorContainer "rescaleValues" for each image 259 // type of the specified scan sequence number "scan_sequence" (from 260 // scanning_sequences) for the PAR file "parFile". 261 // Returns false if an error is encountered during reading, otherwise true is 262 // returned. 263 using PARRescaleValues = 264 vnl_vector_fixed< double, PAR_RESCALE_VALUES_SIZE >; 265 using PARRescaleValuesContainer = 266 VectorContainer< unsigned int, PARRescaleValues >; 267 bool GetRECRescaleValues(std::string parFile, 268 PARRescaleValuesContainer *rescaleValues, int scan_sequence); 269 270 // Stores the diffusion gradient values in the VectorContainer 271 // "gradientValues" 272 // and the diffusion b values in the VectorContainer "bValues" for each 273 // gradient 274 // direction in the PAR file "parFile". This function is applicable only for 275 // PAR 276 // versions > 4.1 277 // Returns false if an error is encountered during reading, otherwise true is 278 // returned. 279 using PARDiffusionValues = 280 vnl_vector_fixed< double, PAR_DIFFUSION_VALUES_SIZE >; 281 using PARDiffusionValuesContainer = 282 VectorContainer< unsigned int, PARDiffusionValues >; 283 using PARBValuesContainer = 284 VectorContainer< unsigned int, double >; 285 bool GetDiffusionGradientOrientationAndBValues(std::string parFile, 286 PARDiffusionValuesContainer *gradientValues, 287 PARBValuesContainer *bValues); 288 289 // Returns a vector of ASL label types for the PAR file "parFile". 290 using PARLabelTypesASLContainer = VectorContainer< unsigned int, int >; 291 bool GetLabelTypesASL(std::string parFile, 292 PARLabelTypesASLContainer *labelTypes); 293 294 // Read a line number within the PAR file. 295 std::string GetLineNumber(std::string file, int lineNum); 296 297 protected: 298 PhilipsPAR(); 299 ~PhilipsPAR() override; 300 void PrintSelf(std::ostream & os, Indent indent) const override; 301 302 private: 303 /** Function used internally to get PAR version. */ 304 int GetPARVersion(std::string parFile); 305 306 /** Function used internally to get info string at top of PAR. */ 307 std::string GetGeneralInfoString(std::string file, int lineNum); 308 309 /** Filename to read. */ 310 std::string m_FileName; 311 312 /** Vector of strings for storing each line of PAR file. */ 313 std::vector< std::string > m_PARFileLines; 314 }; 315 } // end namespace itk 316 317 #endif /* itkPhilipsPAR_h */ 318