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