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
20 #include "itkPhilipsPAR.h"
21 #include <fstream>
22 #include <iostream>
23 #include <algorithm>
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 * http://insight-journal.org/midas/handle.php?handle=1926/1381
31 *
32 */
33
34 namespace itk
35 {
36 /*#=== IMAGE INFORMATION DEFINITION ============================================
37 #
38 #The rest of this file contains ONE line per image, this line contains the
39 #following information:
40 #
41 #slice number (integer)
42 #echo number (integer)
43 #dynamic scan number (integer)
44 #cardiac phase number (integer)
45 #image_type_mr (integer)
46 #scanning sequence (integer)
47 #index in REC file (in images) (integer)
48 #rescale intercept (float)
49 #rescale slope (float)
50 #scale slope (float)
51 #window center (integer)
52 #window width (integer)
53 #image angulation (ap,fh,rl in degrees ) (3*float)
54 #image offcentre (ap,fh,rl in mm ) (3*float)
55 #image_display_orientation (integer)
56 #slice orientation ( TRA/SAG/COR ) (integer)
57 #fmri_status_indication (integer)
58 #image_type_ed_es (end diast/end syst) (integer)
59 #pixel spacing (x,y) (in mm) (2*float)
60 #echo_time (float)
61 #dyn_scan_begin_time (float)
62 #trigger_time (float)
63 #diffusion_b_factor (float)
64 #image_flip_angle (in degrees) (float)
65 #
66 #=== IMAGE INFORMATION =======================================================*/
67 /**
68 * \struct image_info_defV3
69 */
70 struct image_info_defV3 {
71 int problemreading;
72 int slice;
73 int echo;
74 int dynamic;
75 int cardiac;
76 int image_type_mr;
77 int scan_sequence;
78 int index;
79 float rescale_int;
80 float rescale_slope;
81 float scale_slope;
82 int window_center;
83 int window_width;
84 float angAP;
85 float angFH;
86 float angRL;
87 float offAP;
88 float offFH;
89 float offRL;
90 int display_orientation;
91 int slice_orientation;
92 int fmri_status_indication;
93 int image_type_ed_es;
94 float spacingx;
95 float spacingy;
96 float echo_time;
97 float dyn_scan_begin_time;
98 float trigger_time;
99 float diffusion_b_factor;
100 float image_flip_angle;
101 };
102
103 /*#=== IMAGE INFORMATION DEFINITION ============================================
104 #The rest of this file contains ONE line per image, this line contains the
105 #following information:
106 #
107 #slice number (integer)
108 #echo number (integer)
109 #dynamic scan number (integer)
110 #cardiac phase number (integer)
111 #image_type_mr (integer)
112 #scanning sequence (integer)
113 #index in REC file (in images) (integer)
114 #image pixel size (in bits) (integer)
115 #scan percentage (integer)
116 #recon resolution (x y) (2*integer)
117 #rescale intercept (float)
118 #rescale slope (float)
119 #scale slope (float)
120 #window center (integer)
121 #window width (integer)
122 #image angulation (ap,fh,rl in degrees ) (3*float)
123 #image offcentre (ap,fh,rl in mm ) (3*float)
124 #slice thickness (in mm ) (float)
125 #slice gap (in mm ) (float)
126 #image_display_orientation (integer)
127 #slice orientation ( TRA/SAG/COR ) (integer)
128 #fmri_status_indication (integer)
129 #image_type_ed_es (end diast/end syst) (integer)
130 #pixel spacing (x,y) (in mm) (2*float)
131 #echo_time (float)
132 #dyn_scan_begin_time (float)
133 #trigger_time (float)
134 #diffusion_b_factor (float)
135 #number of averages (integer)
136 #image_flip_angle (in degrees) (float)
137 #cardiac frequency (bpm) (integer)
138 #minimum RR-interval (in ms) (integer)
139 #maximum RR-interval (in ms) (integer)
140 #TURBO factor <0=no turbo> (integer)
141 #Inversion delay (in ms) (float)
142 Version 4.1
143 #diffusion b value number (imagekey!) (integer)
144 #gradient orientation number (imagekey!) (integer)
145 #contrast type (string)
146 #diffusion anisotropy type (string)
147 #diffusion (ap, fh, rl) (3*float)
148 Version 4.2
149 #label type (ASL) (imagekey!) (integer)
150 #
151 #=== IMAGE INFORMATION =======================================================*/
152 /**
153 * \struct image_info_defV4
154 */
155 struct image_info_defV4 {
156 int problemreading;
157 int slice;
158 int echo;
159 int dynamic;
160 int cardiac;
161 int image_type_mr;
162 int scan_sequence;
163 int index;
164 int image_bits;
165 int scan_percent;
166 int recon_dimx;
167 int recon_dimy;
168 float rescale_int;
169 float rescale_slope;
170 float scale_slope;
171 int window_center;
172 int window_width;
173 float angAP;
174 float angFH;
175 float angRL;
176 float offAP;
177 float offFH;
178 float offRL;
179 float slice_thick;
180 float slice_gap;
181 int display_orientation;
182 int slice_orientation;
183 int fmri_status_indication;
184 int image_type_ed_es;
185 float spacingx;
186 float spacingy;
187 float echo_time;
188 float dyn_scan_begin_time;
189 float trigger_time;
190 float diffusion_b_factor;
191 int num_averages;
192 float image_flip_angle;
193 int cardiac_freq;
194 int min_rr_int;
195 int max_rr_int;
196 int turbo_factor;
197 float inversion_delay;
198 // Version 4.1 added diffusion gradient information
199 int diffusion_b_value_number;
200 int gradient_orientation_number;
201 int contrast_type;
202 float diffusion_ap;
203 float diffusion_fh;
204 float diffusion_rl;
205 // Version 4.2 added ASL labels
206 int labelTypeASL;
207 };
208
GetImageInformationDefinitionV3(std::string file,int lineNum,PhilipsPAR * philipsPARClass)209 struct image_info_defV3 GetImageInformationDefinitionV3(std::string file,
210 int lineNum, PhilipsPAR *philipsPARClass)
211 {
212 struct image_info_defV3 tempInfo;
213 std::string currentLine = "";
214
215 memset( (void *)&tempInfo, 0, sizeof( struct image_info_defV3 ) );
216 if ( lineNum < 89 )
217 {
218 tempInfo.problemreading = 1;
219 return tempInfo;
220 }
221 currentLine = philipsPARClass->GetLineNumber(file, lineNum);
222 if ( ( currentLine == "" )
223 || ( currentLine == "\n" )
224 || ( currentLine == "\r\n" )
225 || ( currentLine == "\r" )
226 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
227 "=========================" )
228 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
229 "=========================\r" ) )
230 {
231 tempInfo.problemreading = 1;
232 return tempInfo;
233 }
234 std::istringstream inString(currentLine);
235 if ( !inString )
236 {
237 tempInfo.problemreading = 1;
238 return tempInfo;
239 }
240 inString >> tempInfo.slice >> tempInfo.echo >> tempInfo.dynamic;
241 inString >> tempInfo.cardiac >> tempInfo.image_type_mr
242 >> tempInfo.scan_sequence;
243 inString >> tempInfo.index >> tempInfo.rescale_int >> tempInfo.rescale_slope;
244 inString >> tempInfo.scale_slope >> tempInfo.window_center
245 >> tempInfo.window_width;
246 inString >> tempInfo.angAP >> tempInfo.angFH >> tempInfo.angRL;
247 inString >> tempInfo.offAP >> tempInfo.offFH >> tempInfo.offRL;
248 inString >> tempInfo.display_orientation >> tempInfo.slice_orientation
249 >> tempInfo.fmri_status_indication;
250 inString >> tempInfo.image_type_ed_es >> tempInfo.spacingx
251 >> tempInfo.spacingy;
252 inString >> tempInfo.echo_time >> tempInfo.dyn_scan_begin_time
253 >> tempInfo.trigger_time;
254 inString >> tempInfo.diffusion_b_factor >> tempInfo.image_flip_angle;
255 return tempInfo;
256 }
257
GetImageInformationDefinitionV4(std::string file,int lineNum,PhilipsPAR * philipsPARClass)258 struct image_info_defV4 GetImageInformationDefinitionV4(std::string file,
259 int lineNum, PhilipsPAR *philipsPARClass)
260 {
261 struct image_info_defV4 tempInfo;
262 std::string currentLine = "";
263
264 memset( (void *)&tempInfo, 0, sizeof( struct image_info_defV4 ) );
265 if ( lineNum < 92 )
266 {
267 tempInfo.problemreading = 1;
268 return tempInfo;
269 }
270 currentLine = philipsPARClass->GetLineNumber(file, lineNum);
271 if ( ( currentLine == "" )
272 || ( currentLine == "\n" )
273 || ( currentLine == "\r\n" )
274 || ( currentLine == "\r" )
275 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
276 "=========================" )
277 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
278 "=========================\r" ) )
279 {
280 tempInfo.problemreading = 1;
281 return tempInfo;
282 }
283 std::istringstream inString(currentLine);
284 if ( !inString )
285 {
286 tempInfo.problemreading = 1;
287 return tempInfo;
288 }
289 inString >> tempInfo.slice >> tempInfo.echo >> tempInfo.dynamic;
290 inString >> tempInfo.cardiac >> tempInfo.image_type_mr
291 >> tempInfo.scan_sequence;
292 inString >> tempInfo.index >> tempInfo.image_bits >> tempInfo.scan_percent;
293 inString >> tempInfo.recon_dimx >> tempInfo.recon_dimy;
294 inString >> tempInfo.rescale_int >> tempInfo.rescale_slope;
295 inString >> tempInfo.scale_slope >> tempInfo.window_center
296 >> tempInfo.window_width;
297 inString >> tempInfo.angAP >> tempInfo.angFH >> tempInfo.angRL;
298 inString >> tempInfo.offAP >> tempInfo.offFH >> tempInfo.offRL;
299 inString >> tempInfo.slice_thick >> tempInfo.slice_gap;
300 inString >> tempInfo.display_orientation >> tempInfo.slice_orientation
301 >> tempInfo.fmri_status_indication;
302 inString >> tempInfo.image_type_ed_es >> tempInfo.spacingx
303 >> tempInfo.spacingy;
304 inString >> tempInfo.echo_time >> tempInfo.dyn_scan_begin_time
305 >> tempInfo.trigger_time;
306 inString >> tempInfo.diffusion_b_factor >> tempInfo.num_averages
307 >> tempInfo.image_flip_angle;
308 inString >> tempInfo.cardiac_freq >> tempInfo.min_rr_int
309 >> tempInfo.max_rr_int;
310 inString >> tempInfo.turbo_factor >> tempInfo.inversion_delay;
311 return tempInfo;
312 }
313
GetImageInformationDefinitionV41(std::string file,int lineNum,PhilipsPAR * philipsPARClass)314 struct image_info_defV4 GetImageInformationDefinitionV41(std::string file,
315 int lineNum, PhilipsPAR *philipsPARClass)
316 {
317 struct image_info_defV4 tempInfo;
318 std::string currentLine = "";
319
320 memset( (void *)&tempInfo, 0, sizeof( struct image_info_defV4 ) );
321 if ( lineNum < 99 )
322 {
323 tempInfo.problemreading = 1;
324 return tempInfo;
325 }
326 currentLine = philipsPARClass->GetLineNumber(file, lineNum);
327 if ( ( currentLine == "" )
328 || ( currentLine == "\n" )
329 || ( currentLine == "\r\n" )
330 || ( currentLine == "\r" )
331 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
332 "=========================" )
333 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
334 "=========================\r" ) )
335 {
336 tempInfo.problemreading = 1;
337 return tempInfo;
338 }
339 std::istringstream inString(currentLine);
340 if ( !inString )
341 {
342 tempInfo.problemreading = 1;
343 return tempInfo;
344 }
345 inString >> tempInfo.slice >> tempInfo.echo >> tempInfo.dynamic;
346 inString >> tempInfo.cardiac >> tempInfo.image_type_mr
347 >> tempInfo.scan_sequence;
348 inString >> tempInfo.index >> tempInfo.image_bits >> tempInfo.scan_percent;
349 inString >> tempInfo.recon_dimx >> tempInfo.recon_dimy;
350 inString >> tempInfo.rescale_int >> tempInfo.rescale_slope;
351 inString >> tempInfo.scale_slope >> tempInfo.window_center
352 >> tempInfo.window_width;
353 inString >> tempInfo.angAP >> tempInfo.angFH >> tempInfo.angRL;
354 inString >> tempInfo.offAP >> tempInfo.offFH >> tempInfo.offRL;
355 inString >> tempInfo.slice_thick >> tempInfo.slice_gap;
356 inString >> tempInfo.display_orientation >> tempInfo.slice_orientation
357 >> tempInfo.fmri_status_indication;
358 inString >> tempInfo.image_type_ed_es >> tempInfo.spacingx
359 >> tempInfo.spacingy;
360 inString >> tempInfo.echo_time >> tempInfo.dyn_scan_begin_time
361 >> tempInfo.trigger_time;
362 inString >> tempInfo.diffusion_b_factor >> tempInfo.num_averages
363 >> tempInfo.image_flip_angle;
364 inString >> tempInfo.cardiac_freq >> tempInfo.min_rr_int
365 >> tempInfo.max_rr_int;
366 inString >> tempInfo.turbo_factor >> tempInfo.inversion_delay;
367 inString >> tempInfo.diffusion_b_value_number
368 >> tempInfo.gradient_orientation_number;
369 inString >> tempInfo.contrast_type >> tempInfo.contrast_type;
370 inString >> tempInfo.diffusion_ap >> tempInfo.diffusion_fh
371 >> tempInfo.diffusion_rl;
372 return tempInfo;
373 }
374
GetImageInformationDefinitionV42(std::string file,int lineNum,PhilipsPAR * philipsPARClass)375 struct image_info_defV4 GetImageInformationDefinitionV42(std::string file,
376 int lineNum, PhilipsPAR *philipsPARClass)
377 {
378 struct image_info_defV4 tempInfo;
379 std::string currentLine = "";
380
381 memset( (void *)&tempInfo, 0, sizeof( struct image_info_defV4 ) );
382 if ( lineNum < 101 )
383 {
384 tempInfo.problemreading = 1;
385 return tempInfo;
386 }
387 currentLine = philipsPARClass->GetLineNumber(file, lineNum);
388 if ( ( currentLine == "" )
389 || ( currentLine == "\n" )
390 || ( currentLine == "\r\n" )
391 || ( currentLine == "\r" )
392 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
393 "=========================" )
394 || ( currentLine == "#=== END OF DATA DESCRIPTION FILE ======================"
395 "=========================\r" ) )
396 {
397 tempInfo.problemreading = 1;
398 return tempInfo;
399 }
400 std::istringstream inString(currentLine);
401 if ( !inString )
402 {
403 tempInfo.problemreading = 1;
404 return tempInfo;
405 }
406 inString >> tempInfo.slice >> tempInfo.echo >> tempInfo.dynamic;
407 inString >> tempInfo.cardiac >> tempInfo.image_type_mr
408 >> tempInfo.scan_sequence;
409 inString >> tempInfo.index >> tempInfo.image_bits >> tempInfo.scan_percent;
410 inString >> tempInfo.recon_dimx >> tempInfo.recon_dimy;
411 inString >> tempInfo.rescale_int >> tempInfo.rescale_slope;
412 inString >> tempInfo.scale_slope >> tempInfo.window_center
413 >> tempInfo.window_width;
414 inString >> tempInfo.angAP >> tempInfo.angFH >> tempInfo.angRL;
415 inString >> tempInfo.offAP >> tempInfo.offFH >> tempInfo.offRL;
416 inString >> tempInfo.slice_thick >> tempInfo.slice_gap;
417 inString >> tempInfo.display_orientation >> tempInfo.slice_orientation
418 >> tempInfo.fmri_status_indication;
419 inString >> tempInfo.image_type_ed_es >> tempInfo.spacingx
420 >> tempInfo.spacingy;
421 inString >> tempInfo.echo_time >> tempInfo.dyn_scan_begin_time
422 >> tempInfo.trigger_time;
423 inString >> tempInfo.diffusion_b_factor >> tempInfo.num_averages
424 >> tempInfo.image_flip_angle;
425 inString >> tempInfo.cardiac_freq >> tempInfo.min_rr_int
426 >> tempInfo.max_rr_int;
427 inString >> tempInfo.turbo_factor >> tempInfo.inversion_delay;
428 inString >> tempInfo.diffusion_b_value_number
429 >> tempInfo.gradient_orientation_number;
430 inString >> tempInfo.contrast_type >> tempInfo.contrast_type;
431 inString >> tempInfo.diffusion_ap >> tempInfo.diffusion_fh
432 >> tempInfo.diffusion_rl;
433 inString >> tempInfo.labelTypeASL;
434 return tempInfo;
435 }
436
PhilipsPAR()437 PhilipsPAR::PhilipsPAR()
438 {
439 this->m_FileName = "";
440 this->m_PARFileLines.resize(0);
441 }
442
~PhilipsPAR()443 PhilipsPAR::~PhilipsPAR()
444 {}
445
GetLineNumber(std::string file,int lineNum)446 std::string PhilipsPAR::GetLineNumber(std::string file, int lineNum)
447 {
448 std::string line = "";
449 char readFileBuffer[1024] = "";
450
451 if ( lineNum <= 0 )
452 {
453 return line;
454 }
455
456 // If this is the first time, read the whole file into memory.
457 if ( file != this->m_FileName )
458 {
459 this->m_FileName = file;
460 this->m_PARFileLines.resize(0);
461
462 // Try to read the text file.
463 std::ifstream local_InputStream;
464 local_InputStream.open(file.c_str(), std::ios::in);
465 if ( local_InputStream.fail() )
466 {
467 return line;
468 }
469 while ( !local_InputStream.eof() )
470 {
471 local_InputStream.getline( readFileBuffer, sizeof( readFileBuffer ) );
472 line = readFileBuffer;
473 this->m_PARFileLines.push_back(line);
474 }
475 local_InputStream.close();
476 }
477
478 // Return line if not EOF.
479 line = "";
480 if ( ( std::vector< std::string >::size_type )lineNum
481 <= this->m_PARFileLines.size() )
482 {
483 line = this->m_PARFileLines[lineNum - 1];
484 }
485
486 return line;
487 }
488
GetPARVersion(std::string parFile)489 int PhilipsPAR::GetPARVersion(std::string parFile)
490 {
491 //read version number of Philips research tools
492 //Research tools are used to extract data from database; data formats differ
493 //considerably between versions. Handles V3, V4, V4.1, and V4.2
494 int ResToolsVersion = RESEARCH_IMAGE_EXPORT_TOOL_UNKNOWN;
495
496 // Character index 61 on line 8 should be 'V'.
497 std::string currentLine = this->GetLineNumber(parFile, 8);
498 if ( ( currentLine.length() >= 63 )
499 && ( currentLine[61] == 'V' ) )
500 {
501 // Next characters contain the version number.
502 switch ( currentLine[62] )
503 {
504 case '3':
505 ResToolsVersion = RESEARCH_IMAGE_EXPORT_TOOL_V3;
506 break;
507 case '4':
508 {
509 if ( ( currentLine.length() == 63 )
510 || ( currentLine[63] ) != '.' )
511 {
512 ResToolsVersion = RESEARCH_IMAGE_EXPORT_TOOL_V4;
513 }
514 else if ( currentLine.length() >= 65 )
515 {
516 switch ( currentLine[64] )
517 {
518 case '1':
519 ResToolsVersion = RESEARCH_IMAGE_EXPORT_TOOL_V4_1;
520 break;
521 case '2':
522 ResToolsVersion = RESEARCH_IMAGE_EXPORT_TOOL_V4_2;
523 break;
524 }
525 }
526 }
527 break;
528 }
529 }
530 return ResToolsVersion;
531 }
532
GetGeneralInfoString(std::string file,int lineNum)533 std::string PhilipsPAR::GetGeneralInfoString(std::string file, int lineNum)
534 {
535 std::string currentLine = "";
536 std::string::size_type index;
537 std::string outString = "";
538
539 if ( ( lineNum < 12 ) || ( lineNum > 51 ) )
540 {
541 return outString;
542 }
543 currentLine = this->GetLineNumber(file, lineNum);
544 index = currentLine.find(":");
545 if ( index != std::string::npos )
546 {
547 std::string tempString = ":";
548 outString = currentLine.substr( index + tempString.length() );
549 }
550 return outString;
551 }
552
553 #define UNDEFINED "Undefined"
554
555 // Originally adapted from r2agui.m
ReadPAR(std::string parFile,struct par_parameter * pPar)556 void PhilipsPAR::ReadPAR(std::string parFile, struct par_parameter *pPar)
557 {
558 std::istringstream inString;
559
560 if ( pPar == nullptr )
561 {
562 std::ostringstream message;
563 message << "ReadPAR: pPar == nullptr";
564 ExceptionObject exception(__FILE__, __LINE__,
565 message.str(),
566 ITK_LOCATION);
567 throw exception;
568 }
569
570 // Zero out struct.
571 memset( (void *)pPar, 0, sizeof( struct par_parameter ) );
572 // Need to set strings to UNDEFINED to avoid segmentation faults.
573 strcpy(pPar->patient_name, UNDEFINED);
574 strcpy(pPar->exam_name, UNDEFINED);
575 strcpy(pPar->protocol_name, UNDEFINED);
576 strcpy(pPar->exam_date, UNDEFINED);
577 strcpy(pPar->exam_time, UNDEFINED);
578 strcpy(pPar->series_type, UNDEFINED);
579 strcpy(pPar->patient_position, UNDEFINED);
580 strcpy(pPar->prep_direction, UNDEFINED);
581 strcpy(pPar->technique, UNDEFINED);
582 strcpy(pPar->scan_mode, UNDEFINED);
583 // Set image types index to -1.
584 memset( (void *)pPar->image_types, -1, sizeof( pPar->image_types ) );
585 // Set num_slice_repetitions to 1 to avoid divide by zero.
586 pPar->num_slice_repetitions = 1;
587
588 // Get PAR version.
589 pPar->ResToolsVersion = this->GetPARVersion(parFile);
590
591 // Parse PAR file according to version.
592 switch ( pPar->ResToolsVersion )
593 {
594 case RESEARCH_IMAGE_EXPORT_TOOL_V3:
595 {
596 struct image_info_defV3 tempInfo;
597 struct image_info_defV3 tempInfo1;
598 float fovAP, fovFH, fovRL;
599 // Start at line 12 and work through PAR file.
600 // Line numbers are hard-coded on purpose.
601 strncpy( pPar->patient_name, this->GetGeneralInfoString(parFile, 12).c_str(),
602 sizeof( pPar->patient_name ) );
603 strncpy( pPar->exam_name, this->GetGeneralInfoString(parFile, 13).c_str(),
604 sizeof( pPar->exam_name ) );
605 strncpy( pPar->protocol_name, this->GetGeneralInfoString(parFile, 14).c_str(),
606 sizeof( pPar->protocol_name ) );
607 strncpy( pPar->exam_date, this->GetGeneralInfoString(parFile, 15).c_str(),
608 this->GetGeneralInfoString(parFile, 15).find("/") );
609 strncpy( pPar->exam_time,
610 this->GetGeneralInfoString(parFile, 15).substr(
611 this->GetGeneralInfoString(parFile, 15).find("/") + 1).c_str(),
612 sizeof( pPar->exam_time ) );
613 inString.str( this->GetGeneralInfoString(parFile, 16) );
614 inString >> pPar->scno;
615 inString.clear();
616 inString.str( this->GetGeneralInfoString(parFile, 17) );
617 inString >> pPar->recno;
618 inString.clear();
619 inString.str( this->GetGeneralInfoString(parFile, 18) );
620 inString >> pPar->scan_duration;
621 inString.clear();
622 inString.str( this->GetGeneralInfoString(parFile, 19) );
623 inString >> pPar->cardiac_phases;
624 inString.clear();
625 inString.str( this->GetGeneralInfoString(parFile, 20) );
626 inString >> pPar->echoes;
627 inString.clear();
628 inString.str( this->GetGeneralInfoString(parFile, 21) );
629 inString >> pPar->slice;
630 inString.clear();
631 inString.str( this->GetGeneralInfoString(parFile, 22) );
632 inString >> pPar->dyn;
633 inString.clear();
634 inString.str( this->GetGeneralInfoString(parFile, 23) );
635 inString >> pPar->mixes;
636 inString.clear();
637 inString.str( this->GetGeneralInfoString(parFile, 24) );
638 inString >> pPar->bit;
639 inString.clear();
640 strncpy( pPar->technique, this->GetGeneralInfoString(parFile, 25).c_str(),
641 sizeof( pPar->technique ) );
642 strncpy( pPar->scan_mode, this->GetGeneralInfoString(parFile, 26).c_str(),
643 sizeof( pPar->scan_mode ) );
644 inString.str( this->GetGeneralInfoString(parFile, 27) );
645 inString >> pPar->scan_resolution[0];
646 inString >> pPar->scan_resolution[1];
647 inString.clear();
648 inString.str( this->GetGeneralInfoString(parFile, 28) );
649 inString >> pPar->scan_percent;
650 inString.clear();
651 inString.str( this->GetGeneralInfoString(parFile, 29) );
652 inString >> pPar->dim[0] >> pPar->dim[1];
653 pPar->dim[2] = pPar->slice;
654 inString.clear();
655 inString.str( this->GetGeneralInfoString(parFile, 30) );
656 inString >> pPar->num_averages;
657 inString.clear();
658 // It appears that the max number of mixes
659 // parameter indicates the number of experiment
660 // repititions. This assumption is based on
661 // the T1 mapping images that use the look-locker
662 // sequence.
663 inString.str( this->GetGeneralInfoString(parFile, 31) );
664 for ( int repTime = 0; repTime < pPar->mixes; repTime++ )
665 {
666 inString >> pPar->repetition_time[repTime];
667 }
668 inString.clear();
669 tempInfo = GetImageInformationDefinitionV3(parFile, 89, this);
670 if ( tempInfo.problemreading )
671 {
672 std::ostringstream message;
673 message << "ReadPAR: Problem with GetImageInformationDefinitionV3()";
674 ExceptionObject exception(__FILE__, __LINE__,
675 message.str(),
676 ITK_LOCATION);
677 throw exception;
678 }
679 pPar->sliceorient = tempInfo.slice_orientation;
680 int echoNumber = tempInfo.echo;
681 pPar->echo_times[0] = tempInfo.echo_time;
682 int cardiacPhase = tempInfo.cardiac;
683 pPar->trigger_times[0] = tempInfo.trigger_time;
684 pPar->vox[0] = tempInfo.spacingx;
685 pPar->vox[1] = tempInfo.spacingy;
686 inString.str( this->GetGeneralInfoString(parFile, 32) );
687 inString >> fovAP >> fovFH >> fovRL;
688 inString.clear();
689 // slice orientation: transversal
690 if ( pPar->sliceorient == PAR_SLICE_ORIENTATION_TRANSVERSAL )
691 {
692 pPar->fov[0] = fovAP;
693 pPar->fov[1] = fovRL;
694 }
695 // slice orientation: sagittal
696 if ( pPar->sliceorient == PAR_SLICE_ORIENTATION_SAGITTAL )
697 {
698 pPar->fov[0] = fovFH;
699 pPar->fov[1] = fovAP;
700 }
701 // slice orientation: coronal
702 if ( pPar->sliceorient == PAR_SLICE_ORIENTATION_CORONAL )
703 {
704 pPar->fov[0] = fovRL;
705 pPar->fov[1] = fovFH;
706 }
707 inString.str( this->GetGeneralInfoString(parFile, 33) );
708 inString >> pPar->slth;
709 inString.clear();
710 inString.str( this->GetGeneralInfoString(parFile, 34) );
711 inString >> pPar->gap;
712 inString.clear();
713 pPar->fov[2] = ( pPar->gap + pPar->slth ) * pPar->slice;
714 pPar->vox[2] = pPar->slth + pPar->gap;
715 inString.str( this->GetGeneralInfoString(parFile, 35) );
716 inString >> pPar->water_fat_shift;
717 inString.clear();
718 inString.str( this->GetGeneralInfoString(parFile, 36) );
719 inString >> pPar->angAP;
720 inString >> pPar->angFH;
721 inString >> pPar->angRL;
722 inString.clear();
723 inString.str( this->GetGeneralInfoString(parFile, 37) );
724 inString >> pPar->offAP;
725 inString >> pPar->offFH;
726 inString >> pPar->offRL;
727 inString.clear();
728 inString.str( this->GetGeneralInfoString(parFile, 38) );
729 inString >> pPar->flow_comp;
730 inString.clear();
731 inString.str( this->GetGeneralInfoString(parFile, 39) );
732 inString >> pPar->presaturation;
733 inString.clear();
734 inString.str( this->GetGeneralInfoString(parFile, 40) );
735 inString >> pPar->cardiac_freq;
736 inString.clear();
737 inString.str( this->GetGeneralInfoString(parFile, 41) );
738 inString >> pPar->min_rr_int;
739 inString.clear();
740 inString.str( this->GetGeneralInfoString(parFile, 42) );
741 inString >> pPar->max_rr_int;
742 inString.clear();
743 inString.str( this->GetGeneralInfoString(parFile, 43) );
744 inString >> pPar->phase_encode_vel[0];
745 inString >> pPar->phase_encode_vel[1];
746 inString >> pPar->phase_encode_vel[2];
747 inString.clear();
748 inString.str( this->GetGeneralInfoString(parFile, 44) );
749 inString >> pPar->mtc;
750 inString.clear();
751 inString.str( this->GetGeneralInfoString(parFile, 45) );
752 inString >> pPar->spir;
753 inString.clear();
754 inString.str( this->GetGeneralInfoString(parFile, 46) );
755 inString >> pPar->epi;
756 inString.clear();
757 inString.str( this->GetGeneralInfoString(parFile, 47) );
758 inString >> pPar->turbo;
759 inString.clear();
760 inString.str( this->GetGeneralInfoString(parFile, 48) );
761 inString >> pPar->dynamic_scan;
762 inString.clear();
763 inString.str( this->GetGeneralInfoString(parFile, 49) );
764 inString >> pPar->diffusion;
765 inString.clear();
766 inString.str( this->GetGeneralInfoString(parFile, 50) );
767 inString >> pPar->diff_echo;
768 inString.clear();
769 inString.str( this->GetGeneralInfoString(parFile, 51) );
770 inString >> pPar->inversion_delay;
771 inString.clear();
772 // OK, need to figure out how many images are stored in the REC file
773 // and whether or not the images are sorted by slice or by image blocks.
774 // Also get echo times and trigger_times.
775 if ( pPar->slice > 1 )
776 {
777 int lineIncrement = 89;
778 int echoIndex = 0;
779 int cardiacIndex = 0;
780 tempInfo1 = GetImageInformationDefinitionV3(parFile, 90, this);
781 if ( tempInfo1.problemreading )
782 {
783 pPar->problemreading = 1;
784 std::ostringstream message;
785 message << "ReadPAR: Problem with GetImageInformationDefinitionV3()";
786 ExceptionObject exception(__FILE__, __LINE__,
787 message.str(),
788 ITK_LOCATION);
789 throw exception;
790 }
791 if ( ( tempInfo1.slice - tempInfo.slice ) > 0 )
792 {
793 pPar->slicessorted = 1;
794 }
795 // If slices are sorted I only need to calculate the number of
796 // image blocks (if more than 1) and store the echo times.
797 if ( pPar->slicessorted )
798 {
799 ++pPar->image_blocks;
800 ++pPar->num_image_types;
801 pPar->image_types[0] = tempInfo.image_type_mr;
802 ++pPar->num_scanning_sequences;
803 pPar->scanning_sequences[0] = tempInfo.scan_sequence;
804 lineIncrement += pPar->slice;
805 tempInfo1 = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
806 while ( !tempInfo1.problemreading && tempInfo1.slice )
807 {
808 int isUnique = 1;
809 // Find unique image types in REC.
810 for ( int i = 0; i < pPar->num_image_types; i++ )
811 {
812 if ( pPar->image_types[i] == tempInfo1.image_type_mr )
813 {
814 isUnique = 0;
815 break;
816 }
817 }
818 if ( isUnique )
819 {
820 ++pPar->num_image_types;
821 pPar->image_types[pPar->num_image_types - 1] =
822 tempInfo1.image_type_mr;
823 }
824 isUnique = 1;
825 // Find all of the scanning sequences.
826 for ( int i = 0; i < pPar->num_scanning_sequences; i++ )
827 {
828 if ( pPar->scanning_sequences[i] == tempInfo1.scan_sequence )
829 {
830 isUnique = 0;
831 break;
832 }
833 }
834 if ( isUnique )
835 {
836 ++pPar->num_scanning_sequences;
837 pPar->scanning_sequences[pPar->num_scanning_sequences - 1] =
838 tempInfo1.scan_sequence;
839 }
840 ++pPar->image_blocks;
841 lineIncrement += pPar->slice;
842 // Get the echo times.
843 if ( echoNumber != tempInfo1.echo )
844 {
845 ++echoIndex;
846 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
847 echoNumber = tempInfo1.echo;
848 }
849 // Get the trigger times
850 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
851 (cardiacPhase != tempInfo1.cardiac) )
852 {
853 ++cardiacIndex;
854 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
855 cardiacPhase = tempInfo1.cardiac;
856 }
857 tempInfo1 = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
858 }
859 }
860 // Slices are not sorted.
861 else
862 {
863 int slice = tempInfo.slice;
864 ++pPar->image_blocks;
865 ++pPar->num_image_types;
866 pPar->image_types[0] = tempInfo.image_type_mr;
867 ++pPar->num_scanning_sequences;
868 pPar->scanning_sequences[0] = tempInfo.scan_sequence;
869 ++lineIncrement;
870 tempInfo1 = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
871 while ( !tempInfo1.problemreading && tempInfo1.slice )
872 {
873 if ( slice == tempInfo1.slice )
874 {
875 int isUnique = 1;
876 // Find unique image types in REC.
877 for ( int i = 0; i < pPar->num_image_types; i++ )
878 {
879 if ( pPar->image_types[i] == tempInfo1.image_type_mr )
880 {
881 isUnique = 0;
882 break;
883 }
884 }
885 if ( isUnique )
886 {
887 ++pPar->num_image_types;
888 pPar->image_types[pPar->num_image_types - 1] =
889 tempInfo1.image_type_mr;
890 }
891 isUnique = 1;
892 // Find all of the scanning sequences.
893 for ( int i = 0; i < pPar->num_scanning_sequences; i++ )
894 {
895 if ( pPar->scanning_sequences[i] == tempInfo1.scan_sequence )
896 {
897 isUnique = 0;
898 break;
899 }
900 }
901 if ( isUnique )
902 {
903 ++pPar->num_scanning_sequences;
904 pPar->scanning_sequences[pPar->num_scanning_sequences - 1] =
905 tempInfo1.scan_sequence;
906 }
907 ++pPar->image_blocks;
908 // Get the echo times.
909 if ( echoNumber != tempInfo1.echo )
910 {
911 ++echoIndex;
912 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
913 echoNumber = tempInfo1.echo;
914 }
915 // Get the trigger times
916 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
917 (cardiacPhase != tempInfo1.cardiac) )
918 {
919 ++cardiacIndex;
920 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
921 cardiacPhase = tempInfo1.cardiac;
922 }
923 }
924 else
925 {
926 lineIncrement = 89;
927 // OK, I need to determine if there are more image blocks, only
928 // if pPar->num_image_types or pPar->num_scanning_sequences > 1
929 if ( ( pPar->num_image_types > 1 )
930 || ( pPar->num_scanning_sequences > 1 ) )
931 {
932 pPar->num_slice_repetitions = pPar->image_blocks;
933 lineIncrement += ( pPar->slice * pPar->num_slice_repetitions );
934 tempInfo1 = GetImageInformationDefinitionV3(parFile,
935 lineIncrement, this);
936 while ( !tempInfo1.problemreading && tempInfo1.slice )
937 {
938 // Get the echo times.
939 if ( echoNumber != tempInfo1.echo )
940 {
941 ++echoIndex;
942 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
943 echoNumber = tempInfo1.echo;
944 }
945 // Get the trigger times
946 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
947 (cardiacPhase != tempInfo1.cardiac) )
948 {
949 ++cardiacIndex;
950 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
951 cardiacPhase = tempInfo1.cardiac;
952 }
953 pPar->image_blocks += pPar->num_slice_repetitions;
954 lineIncrement += ( pPar->slice * pPar->num_slice_repetitions );
955 tempInfo1 = GetImageInformationDefinitionV3(parFile,
956 lineIncrement, this);
957 }
958 }
959 break;
960 }
961 ++lineIncrement;
962 tempInfo1 = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
963 }
964 }
965 // This is a sanity check. The echoIndex should match
966 // (pPar->echoes-1).
967 if ( ( pPar->echoes - 1 ) != echoIndex )
968 {
969 pPar->problemreading = 1;
970 std::ostringstream message;
971 message << "ReadPAR: (pPar->echoes-1) != echoIndex, "
972 << "pPar->echoes-1 = " << pPar->echoes - 1
973 << " and echoIndex = " << echoIndex;
974 ExceptionObject exception(__FILE__, __LINE__,
975 message.str(),
976 ITK_LOCATION);
977 throw exception;
978 }
979 // Another sanity check. The cardiacIndex should match
980 // (pPar->cardiac_phases-1).
981 if ( ( pPar->cardiac_phases - 1 ) != cardiacIndex )
982 {
983 pPar->problemreading = 1;
984 std::ostringstream message;
985 message << "ReadPAR: (pPar->cardiac_phases-1) != cardiacIndex, "
986 << "pPar->cardiac_phases-1 = " << pPar->cardiac_phases - 1
987 << " and cardiacIndex = " << cardiacIndex;
988 ExceptionObject exception(__FILE__, __LINE__,
989 message.str(),
990 ITK_LOCATION);
991 throw exception;
992 }
993 }
994 // Only 1 slice, but how many repetitions of that slice?
995 else
996 {
997 int lineIncrement = 89;
998 int echoIndex = 0;
999 int cardiacIndex = 0;
1000 int slice = tempInfo.slice;
1001 int firstEchoNumber = echoNumber;
1002 int firstCardiacPhase = cardiacPhase;
1003 int firstDynamic = tempInfo.dynamic;
1004 ++pPar->image_blocks;
1005 ++pPar->num_image_types;
1006 pPar->image_types[0] = tempInfo.image_type_mr;
1007 ++pPar->num_scanning_sequences;
1008 pPar->scanning_sequences[0] = tempInfo.scan_sequence;
1009 ++lineIncrement;
1010 tempInfo1 = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1011 while ( !tempInfo1.problemreading && tempInfo1.slice )
1012 {
1013 if ( slice == tempInfo1.slice )
1014 {
1015 int isUnique = 1;
1016 // Find unique image types in REC.
1017 for ( int i = 0; i < pPar->num_image_types; i++ )
1018 {
1019 if ( pPar->image_types[i] == tempInfo1.image_type_mr )
1020 {
1021 isUnique = 0;
1022 break;
1023 }
1024 }
1025 if ( isUnique )
1026 {
1027 ++pPar->num_image_types;
1028 pPar->image_types[pPar->num_image_types - 1] =
1029 tempInfo1.image_type_mr;
1030 }
1031 isUnique = 1;
1032 // Find all of the scanning sequences.
1033 for ( int i = 0; i < pPar->num_scanning_sequences; i++ )
1034 {
1035 if ( pPar->scanning_sequences[i] == tempInfo1.scan_sequence )
1036 {
1037 isUnique = 0;
1038 break;
1039 }
1040 }
1041 if ( isUnique )
1042 {
1043 ++pPar->num_scanning_sequences;
1044 pPar->scanning_sequences[pPar->num_scanning_sequences - 1] =
1045 tempInfo1.scan_sequence;
1046 }
1047 ++pPar->image_blocks;
1048 // Get the echo times.
1049 if ( echoNumber != tempInfo1.echo )
1050 {
1051 ++echoIndex;
1052 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
1053 echoNumber = tempInfo1.echo;
1054 }
1055 // Get the trigger times
1056 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
1057 (cardiacPhase != tempInfo1.cardiac) )
1058 {
1059 ++cardiacIndex;
1060 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
1061 cardiacPhase = tempInfo1.cardiac;
1062 }
1063 // Need to keep track of the number of consecutive slice
1064 // repetitions.
1065 if ( ( pPar->echoes > 1 ) && ( firstEchoNumber == tempInfo1.echo ) )
1066 {
1067 ++pPar->num_slice_repetitions;
1068 }
1069 if ( ( pPar->cardiac_phases > 1 )
1070 && ( firstCardiacPhase == tempInfo1.cardiac ) )
1071 {
1072 ++pPar->num_slice_repetitions;
1073 }
1074 if ( ( pPar->dyn > 1 ) && ( firstDynamic == tempInfo1.dynamic ) )
1075 {
1076 ++pPar->num_slice_repetitions;
1077 }
1078 }
1079 else
1080 {
1081 break;
1082 }
1083 ++lineIncrement;
1084 tempInfo1 = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1085 }
1086 // This is a sanity check. The echoIndex should match
1087 // (pPar->echoes-1).
1088 if ( ( pPar->echoes - 1 ) != echoIndex )
1089 {
1090 pPar->problemreading = 1;
1091 std::ostringstream message;
1092 message << "ReadPAR: (pPar->echoes-1) != echoIndex, "
1093 << "pPar->echoes-1 = " << pPar->echoes - 1
1094 << " and echoIndex = " << echoIndex;
1095 ExceptionObject exception(__FILE__, __LINE__,
1096 message.str(),
1097 ITK_LOCATION);
1098 throw exception;
1099 }
1100 // Another sanity check. The cardiacIndex should match
1101 // (pPar->cardiac_phases-1).
1102 if ( ( pPar->cardiac_phases - 1 ) != cardiacIndex )
1103 {
1104 pPar->problemreading = 1;
1105 std::ostringstream message;
1106 message << "ReadPAR: (pPar->cardiac_phases-1) != cardiacIndex, "
1107 << "pPar->cardiac_phases-1 = " << pPar->cardiac_phases - 1
1108 << " and cardiacIndex = " << cardiacIndex;
1109 ExceptionObject exception(__FILE__, __LINE__,
1110 message.str(),
1111 ITK_LOCATION);
1112 throw exception;
1113 }
1114 }
1115 }
1116 break;
1117
1118 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
1119 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1120 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
1121 {
1122 struct image_info_defV4 tempInfo;
1123 struct image_info_defV4 tempInfo1;
1124 float fovAP, fovFH, fovRL;
1125 // Start at line 12 and work through PAR file.
1126 // Line numbers are hard-coded on purpose.
1127 strncpy( pPar->patient_name, this->GetGeneralInfoString(parFile, 12).c_str(),
1128 sizeof( pPar->patient_name ) );
1129 strncpy( pPar->exam_name, this->GetGeneralInfoString(parFile, 13).c_str(),
1130 sizeof( pPar->exam_name ) );
1131 strncpy( pPar->protocol_name, this->GetGeneralInfoString(parFile, 14).c_str(),
1132 sizeof( pPar->protocol_name ) );
1133 strncpy( pPar->exam_date,
1134 this->GetGeneralInfoString(parFile, 15).c_str(),
1135 this->GetGeneralInfoString(parFile, 15).find("/") );
1136 strncpy( pPar->exam_time,
1137 this->GetGeneralInfoString(parFile, 15).substr(
1138 this->GetGeneralInfoString(parFile, 15).find("/") + 1).c_str(),
1139 sizeof( pPar->exam_time ) );
1140 strncpy( pPar->series_type, this->GetGeneralInfoString(parFile, 16).c_str(),
1141 sizeof( pPar->series_type ) );
1142 inString.str( this->GetGeneralInfoString(parFile, 17) );
1143 inString >> pPar->scno;
1144 inString.clear();
1145 inString.str( this->GetGeneralInfoString(parFile, 18) );
1146 inString >> pPar->recno;
1147 inString.clear();
1148 inString.str( this->GetGeneralInfoString(parFile, 19) );
1149 inString >> pPar->scan_duration;
1150 inString.clear();
1151 inString.str( this->GetGeneralInfoString(parFile, 20) );
1152 inString >> pPar->cardiac_phases;
1153 inString.clear();
1154 inString.str( this->GetGeneralInfoString(parFile, 21) );
1155 inString >> pPar->echoes;
1156 inString.clear();
1157 inString.str( this->GetGeneralInfoString(parFile, 22) );
1158 inString >> pPar->slice;
1159 inString.clear();
1160 inString.str( this->GetGeneralInfoString(parFile, 23) );
1161 inString >> pPar->dyn;
1162 inString.clear();
1163 inString.str( this->GetGeneralInfoString(parFile, 24) );
1164 inString >> pPar->mixes;
1165 inString.clear();
1166 strncpy( pPar->patient_position, this->GetGeneralInfoString(parFile, 25).c_str(),
1167 sizeof( pPar->patient_position ) );
1168 strncpy( pPar->prep_direction, this->GetGeneralInfoString(parFile, 26).c_str(),
1169 sizeof( pPar->prep_direction ) );
1170 strncpy( pPar->technique, this->GetGeneralInfoString(parFile, 27).c_str(),
1171 sizeof( pPar->technique ) );
1172 inString.str( this->GetGeneralInfoString(parFile, 28) );
1173 inString >> pPar->scan_resolution[0];
1174 inString >> pPar->scan_resolution[1];
1175 inString.clear();
1176 inString.str( this->GetGeneralInfoString(parFile, 29) );
1177 inString >> pPar->scan_mode;
1178 inString.clear();
1179 // It appears that the max number of mixes
1180 // parameter indicates the number of experiment
1181 // repititions. This assumption is based on
1182 // the T1 mapping images that use the look-locker
1183 // sequence.
1184 inString.str( this->GetGeneralInfoString(parFile, 30) );
1185 for ( int repTime = 0; repTime < pPar->mixes; repTime++ )
1186 {
1187 inString >> pPar->repetition_time[repTime];
1188 }
1189 inString.clear();
1190 switch ( pPar->ResToolsVersion )
1191 {
1192 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
1193 tempInfo = GetImageInformationDefinitionV4(parFile, 92, this);
1194 break;
1195 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1196 tempInfo = GetImageInformationDefinitionV41(parFile, 99, this);
1197 break;
1198 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
1199 tempInfo = GetImageInformationDefinitionV42(parFile, 101, this);
1200 break;
1201 }
1202 if ( tempInfo.problemreading )
1203 {
1204 pPar->problemreading = 1;
1205 std::ostringstream message;
1206 message << "ReadPAR: Problem with GetImageInformationDefinitionV4()";
1207 ExceptionObject exception(__FILE__, __LINE__,
1208 message.str(),
1209 ITK_LOCATION);
1210 throw exception;
1211 }
1212 pPar->sliceorient = tempInfo.slice_orientation;
1213 int echoNumber = tempInfo.echo;
1214 pPar->echo_times[0] = tempInfo.echo_time;
1215 int cardiacPhase = tempInfo.cardiac;
1216 pPar->trigger_times[0] = tempInfo.trigger_time;
1217 pPar->dim[0] = tempInfo.recon_dimx;
1218 pPar->dim[1] = tempInfo.recon_dimy;
1219 pPar->dim[2] = pPar->slice;
1220 pPar->bit = tempInfo.image_bits;
1221 pPar->slth = tempInfo.slice_thick;
1222 pPar->gap = tempInfo.slice_gap;
1223 pPar->vox[0] = tempInfo.spacingx;
1224 pPar->vox[1] = tempInfo.spacingy;
1225 pPar->vox[2] = tempInfo.slice_thick + tempInfo.slice_gap;
1226 inString.str( this->GetGeneralInfoString(parFile, 31) );
1227 inString >> fovAP >> fovFH >> fovRL;
1228 inString.clear();
1229 // slice orientation: transversal
1230 if ( pPar->sliceorient == PAR_SLICE_ORIENTATION_TRANSVERSAL )
1231 {
1232 pPar->fov[0] = fovAP;
1233 pPar->fov[1] = fovRL;
1234 }
1235 // slice orientation: sagittal
1236 if ( pPar->sliceorient == PAR_SLICE_ORIENTATION_SAGITTAL )
1237 {
1238 pPar->fov[0] = fovFH;
1239 pPar->fov[1] = fovAP;
1240 }
1241 // slice orientation: coronal
1242 if ( pPar->sliceorient == PAR_SLICE_ORIENTATION_CORONAL )
1243 {
1244 pPar->fov[0] = fovRL;
1245 pPar->fov[1] = fovFH;
1246 }
1247 pPar->fov[2] = ( pPar->gap + pPar->slth ) * pPar->slice;
1248 inString.str( this->GetGeneralInfoString(parFile, 32) );
1249 inString >> pPar->water_fat_shift;
1250 inString.clear();
1251 inString.str( this->GetGeneralInfoString(parFile, 33) );
1252 inString >> pPar->angAP;
1253 inString >> pPar->angFH;
1254 inString >> pPar->angRL;
1255 inString.clear();
1256 inString.str( this->GetGeneralInfoString(parFile, 34) );
1257 inString >> pPar->offAP;
1258 inString >> pPar->offFH;
1259 inString >> pPar->offRL;
1260 inString.clear();
1261 inString.str( this->GetGeneralInfoString(parFile, 35) );
1262 inString >> pPar->flow_comp;
1263 inString.clear();
1264 inString.str( this->GetGeneralInfoString(parFile, 36) );
1265 inString >> pPar->presaturation;
1266 inString.clear();
1267 inString.str( this->GetGeneralInfoString(parFile, 37) );
1268 inString >> pPar->phase_encode_vel[0];
1269 inString >> pPar->phase_encode_vel[1];
1270 inString >> pPar->phase_encode_vel[2];
1271 inString.clear();
1272 inString.str( this->GetGeneralInfoString(parFile, 38) );
1273 inString >> pPar->mtc;
1274 inString.clear();
1275 inString.str( this->GetGeneralInfoString(parFile, 39) );
1276 inString >> pPar->spir;
1277 inString.clear();
1278 inString.str( this->GetGeneralInfoString(parFile, 40) );
1279 inString >> pPar->epi;
1280 inString.clear();
1281 inString.str( this->GetGeneralInfoString(parFile, 41) );
1282 inString >> pPar->dynamic_scan;
1283 inString.clear();
1284 inString.str( this->GetGeneralInfoString(parFile, 42) );
1285 inString >> pPar->diffusion;
1286 inString.clear();
1287 inString.str( this->GetGeneralInfoString(parFile, 43) );
1288 inString >> pPar->diff_echo;
1289 inString.clear();
1290 // Versions >= 4.1
1291 if ( pPar->ResToolsVersion >= RESEARCH_IMAGE_EXPORT_TOOL_V4_1 )
1292 {
1293 inString.str( this->GetGeneralInfoString(parFile, 44) );
1294 inString >> pPar->max_num_diff_vals;
1295 inString.clear();
1296 inString.str( this->GetGeneralInfoString(parFile, 45) );
1297 inString >> pPar->max_num_grad_orient;
1298 inString.clear();
1299 }
1300 // Version 4.2 only
1301 if ( pPar->ResToolsVersion == RESEARCH_IMAGE_EXPORT_TOOL_V4_2 )
1302 {
1303 inString.str( this->GetGeneralInfoString(parFile, 46) );
1304 inString >> pPar->num_label_types;
1305 inString.clear();
1306 }
1307 // OK, need to figure out how many images are stored in the REC file
1308 // and whether or not the images are sorted by slice or by image blocks.
1309 // Also get echo times.
1310 if ( pPar->slice > 1 )
1311 {
1312 int lineIncrement = 92;
1313 int echoIndex = 0;
1314 int cardiacIndex = 0;
1315 switch ( pPar->ResToolsVersion )
1316 {
1317 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
1318 tempInfo1 = GetImageInformationDefinitionV4(parFile, 93, this);
1319 break;
1320 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1321 lineIncrement = 99;
1322 tempInfo1 = GetImageInformationDefinitionV41(parFile, 100, this);
1323 break;
1324 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
1325 lineIncrement = 101;
1326 tempInfo1 = GetImageInformationDefinitionV42(parFile, 102, this);
1327 break;
1328 }
1329 if ( tempInfo1.problemreading )
1330 {
1331 pPar->problemreading = 1;
1332 std::ostringstream message;
1333 message << "ReadPAR: Problem with GetImageInformationV4()";
1334 ExceptionObject exception(__FILE__, __LINE__,
1335 message.str(),
1336 ITK_LOCATION);
1337 throw exception;
1338 }
1339 if ( ( tempInfo1.slice - tempInfo.slice ) > 0 )
1340 {
1341 pPar->slicessorted = 1;
1342 }
1343 // If slices are sorted I only need to calculate the number of
1344 // image blocks (if more than 1) and store the echo times.
1345 if ( pPar->slicessorted )
1346 {
1347 ++pPar->image_blocks;
1348 ++pPar->num_image_types;
1349 pPar->image_types[0] = tempInfo.image_type_mr;
1350 ++pPar->num_scanning_sequences;
1351 pPar->scanning_sequences[0] = tempInfo.scan_sequence;
1352 lineIncrement += pPar->slice;
1353 // lineIncrement is set according to version 4.x PAR file.
1354 tempInfo1 = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1355 while ( !tempInfo1.problemreading && tempInfo1.slice )
1356 {
1357 int isUnique = 1;
1358 // Find unique image types in REC.
1359 for ( int i = 0; i < pPar->num_image_types; i++ )
1360 {
1361 if ( pPar->image_types[i] == tempInfo1.image_type_mr )
1362 {
1363 isUnique = 0;
1364 break;
1365 }
1366 }
1367 if ( isUnique )
1368 {
1369 ++pPar->num_image_types;
1370 pPar->image_types[pPar->num_image_types - 1] =
1371 tempInfo1.image_type_mr;
1372 }
1373 isUnique = 1;
1374 // Find all of the scanning sequences.
1375 for ( int i = 0; i < pPar->num_scanning_sequences; i++ )
1376 {
1377 if ( pPar->scanning_sequences[i] == tempInfo1.scan_sequence )
1378 {
1379 isUnique = 0;
1380 break;
1381 }
1382 }
1383 if ( isUnique )
1384 {
1385 ++pPar->num_scanning_sequences;
1386 pPar->scanning_sequences[pPar->num_scanning_sequences - 1] =
1387 tempInfo1.scan_sequence;
1388 }
1389 ++pPar->image_blocks;
1390 // Get the echo times.
1391 if ( echoNumber != tempInfo1.echo )
1392 {
1393 ++echoIndex;
1394 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
1395 echoNumber = tempInfo1.echo;
1396 }
1397 // Get the trigger times
1398 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
1399 (cardiacPhase != tempInfo1.cardiac) )
1400 {
1401 ++cardiacIndex;
1402 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
1403 cardiacPhase = tempInfo1.cardiac;
1404 }
1405 lineIncrement += pPar->slice;
1406 // lineIncrement is set according to version 4.x PAR file.
1407 tempInfo1 = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1408 }
1409 }
1410 // Slices are not sorted.
1411 else
1412 {
1413 int slice = tempInfo.slice;
1414 ++pPar->image_blocks;
1415 ++pPar->num_image_types;
1416 pPar->image_types[0] = tempInfo.image_type_mr;
1417 ++pPar->num_scanning_sequences;
1418 pPar->scanning_sequences[0] = tempInfo.scan_sequence;
1419 ++lineIncrement;
1420 // lineIncrement is set according to version 4.x PAR file.
1421 tempInfo1 = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1422 while ( !tempInfo1.problemreading && tempInfo1.slice )
1423 {
1424 // This if statement applies to just the first slice.
1425 if ( slice == tempInfo1.slice )
1426 {
1427 // Find unique image types in REC.
1428 int isUnique = 1;
1429 for ( int i = 0; i < pPar->num_image_types; i++ )
1430 {
1431 if ( pPar->image_types[i] == tempInfo1.image_type_mr )
1432 {
1433 isUnique = 0;
1434 break;
1435 }
1436 }
1437 if ( isUnique )
1438 {
1439 ++pPar->num_image_types;
1440 pPar->image_types[pPar->num_image_types - 1] =
1441 tempInfo1.image_type_mr;
1442 }
1443 isUnique = 1;
1444 // Find all of the scanning sequences.
1445 for ( int i = 0; i < pPar->num_scanning_sequences; i++ )
1446 {
1447 if ( pPar->scanning_sequences[i] == tempInfo1.scan_sequence )
1448 {
1449 isUnique = 0;
1450 break;
1451 }
1452 }
1453 if ( isUnique )
1454 {
1455 ++pPar->num_scanning_sequences;
1456 pPar->scanning_sequences[pPar->num_scanning_sequences - 1] =
1457 tempInfo1.scan_sequence;
1458 }
1459 ++pPar->image_blocks;
1460 // Get the echo times.
1461 if ( echoNumber != tempInfo1.echo )
1462 {
1463 ++echoIndex;
1464 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
1465 echoNumber = tempInfo1.echo;
1466 }
1467 // Get the trigger times
1468 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
1469 (cardiacPhase != tempInfo1.cardiac) )
1470 {
1471 ++cardiacIndex;
1472 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
1473 cardiacPhase = tempInfo1.cardiac;
1474 }
1475 }
1476 // Now we have sufficient information to parse the rest of the PAR
1477 // file.
1478 else
1479 {
1480 switch ( pPar->ResToolsVersion )
1481 {
1482 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
1483 lineIncrement = 92;
1484 break;
1485 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1486 lineIncrement = 99;
1487 break;
1488 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
1489 lineIncrement = 101;
1490 break;
1491 }
1492 // OK, I need to determine if there are more image blocks, only
1493 // if pPar->num_image_types or pPar->num_scanning_sequences > 1
1494 if ( ( pPar->num_image_types > 1 )
1495 || ( pPar->num_scanning_sequences > 1 ) )
1496 {
1497 pPar->num_slice_repetitions = pPar->image_blocks;
1498 lineIncrement += ( pPar->slice * pPar->num_slice_repetitions );
1499 // lineIncrement is set according to version 4.x PAR file.
1500 tempInfo1 = GetImageInformationDefinitionV4(parFile,
1501 lineIncrement, this);
1502 while ( !tempInfo1.problemreading && tempInfo1.slice )
1503 {
1504 // Get the echo times.
1505 if ( echoNumber != tempInfo1.echo )
1506 {
1507 ++echoIndex;
1508 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
1509 echoNumber = tempInfo1.echo;
1510 }
1511 // Get the trigger times
1512 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
1513 (cardiacPhase != tempInfo1.cardiac) )
1514 {
1515 ++cardiacIndex;
1516 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
1517 cardiacPhase = tempInfo1.cardiac;
1518 }
1519 pPar->image_blocks += pPar->num_slice_repetitions;
1520 lineIncrement += ( pPar->slice * pPar->num_slice_repetitions );
1521 tempInfo1 = GetImageInformationDefinitionV4(parFile,
1522 lineIncrement, this);
1523 }
1524 }
1525 break;
1526 }
1527 ++lineIncrement;
1528 tempInfo1 = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1529 }
1530 }
1531 // This is a sanity check. The echoIndex should match
1532 // (pPar->echoes-1).
1533 if ( ( pPar->echoes - 1 ) != echoIndex )
1534 {
1535 pPar->problemreading = 1;
1536 std::ostringstream message;
1537 message << "ReadPAR: (pPar->echoes-1) != echoIndex, "
1538 << "pPar->echoes-1 = " << pPar->echoes - 1
1539 << " and echoIndex = " << echoIndex;
1540 ExceptionObject exception(__FILE__, __LINE__,
1541 message.str(),
1542 ITK_LOCATION);
1543 throw exception;
1544 }
1545 // Another sanity check. The cardiacIndex should match
1546 // (pPar->cardiac_phases-1).
1547 if ( ( pPar->cardiac_phases - 1 ) != cardiacIndex )
1548 {
1549 pPar->problemreading = 1;
1550 std::ostringstream message;
1551 message << "ReadPAR: (pPar->cardiac_phases-1) != cardiacIndex, "
1552 << "pPar->cardiac_phases-1 = " << pPar->cardiac_phases - 1
1553 << " and cardiacIndex = " << cardiacIndex;
1554 ExceptionObject exception(__FILE__, __LINE__,
1555 message.str(),
1556 ITK_LOCATION);
1557 throw exception;
1558 }
1559 }
1560 // Only 1 slice, but how many repetitions of that slice?
1561 else
1562 {
1563 int lineIncrement = 92;
1564 int echoIndex = 0;
1565 int cardiacIndex = 0;
1566 int slice = tempInfo.slice;
1567 int firstEchoNumber = echoNumber;
1568 int firstCardiacPhase = cardiacPhase;
1569 int firstDynamic = tempInfo.dynamic;
1570 ++pPar->image_blocks;
1571 ++pPar->num_image_types;
1572 pPar->image_types[0] = tempInfo.image_type_mr;
1573 ++pPar->num_scanning_sequences;
1574 pPar->scanning_sequences[0] = tempInfo.scan_sequence;
1575 switch ( pPar->ResToolsVersion )
1576 {
1577 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1578 lineIncrement = 99;
1579 break;
1580 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
1581 lineIncrement = 101;
1582 break;
1583 }
1584 ++lineIncrement;
1585 tempInfo1 = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1586 while ( !tempInfo1.problemreading && tempInfo1.slice )
1587 {
1588 if ( slice == tempInfo1.slice )
1589 {
1590 int isUnique = 1;
1591 // Find unique image types in REC.
1592 for ( int i = 0; i < pPar->num_image_types; i++ )
1593 {
1594 if ( pPar->image_types[i] == tempInfo1.image_type_mr )
1595 {
1596 isUnique = 0;
1597 break;
1598 }
1599 }
1600 if ( isUnique )
1601 {
1602 ++pPar->num_image_types;
1603 pPar->image_types[pPar->num_image_types - 1] =
1604 tempInfo1.image_type_mr;
1605 }
1606 isUnique = 1;
1607 // Find all of the scanning sequences.
1608 for ( int i = 0; i < pPar->num_scanning_sequences; i++ )
1609 {
1610 if ( pPar->scanning_sequences[i] == tempInfo1.scan_sequence )
1611 {
1612 isUnique = 0;
1613 break;
1614 }
1615 }
1616 if ( isUnique )
1617 {
1618 ++pPar->num_scanning_sequences;
1619 pPar->scanning_sequences[pPar->num_scanning_sequences - 1] =
1620 tempInfo1.scan_sequence;
1621 }
1622 ++pPar->image_blocks;
1623 // Should be equal after the first iteration, but will only
1624 // add additional echoes in latter iterations if they differ
1625 // from the first.
1626 if ( echoNumber != tempInfo1.echo )
1627 {
1628 ++echoIndex;
1629 pPar->echo_times[echoIndex] = tempInfo1.echo_time;
1630 echoNumber = tempInfo1.echo;
1631 }
1632 // Get the trigger times
1633 if ( (cardiacIndex < (pPar->cardiac_phases-1)) &&
1634 (cardiacPhase != tempInfo1.cardiac) )
1635 {
1636 ++cardiacIndex;
1637 pPar->trigger_times[cardiacIndex] = tempInfo1.trigger_time;
1638 cardiacPhase = tempInfo1.cardiac;
1639 }
1640 // Need to keep track of the number of consecutive slice
1641 // repetitions.
1642 if ( ( pPar->echoes > 1 ) && ( firstEchoNumber == tempInfo1.echo ) )
1643 {
1644 ++pPar->num_slice_repetitions;
1645 }
1646 if ( ( pPar->cardiac_phases > 1 )
1647 && ( firstCardiacPhase == tempInfo1.cardiac ) )
1648 {
1649 ++pPar->num_slice_repetitions;
1650 }
1651 if ( ( pPar->dyn > 1 ) && ( firstDynamic == tempInfo1.dynamic ) )
1652 {
1653 ++pPar->num_slice_repetitions;
1654 }
1655 }
1656 else
1657 {
1658 break;
1659 }
1660 ++lineIncrement;
1661 tempInfo1 = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1662 }
1663 // This is a sanity check. The echoIndex should match
1664 // (pPar->echoes-1).
1665 if ( ( pPar->echoes - 1 ) != echoIndex )
1666 {
1667 pPar->problemreading = 1;
1668 std::ostringstream message;
1669 message << "ReadPAR: (pPar->echoes-1) != echoIndex, "
1670 << "pPar->echoes-1 = " << pPar->echoes - 1
1671 << " and echoIndex = " << echoIndex;
1672 ExceptionObject exception(__FILE__, __LINE__,
1673 message.str(),
1674 ITK_LOCATION);
1675 throw exception;
1676 }
1677 // Another sanity check. The cardiacIndex should match
1678 // (pPar->cardiac_phases-1).
1679 if ( ( pPar->cardiac_phases - 1 ) != cardiacIndex )
1680 {
1681 pPar->problemreading = 1;
1682 std::ostringstream message;
1683 message << "ReadPAR: (pPar->cardiac_phases-1) != cardiacIndex, "
1684 << "pPar->cardiac_phases-1 = " << pPar->cardiac_phases - 1
1685 << " and cardiacIndex = " << cardiacIndex;
1686 ExceptionObject exception(__FILE__, __LINE__,
1687 message.str(),
1688 ITK_LOCATION);
1689 throw exception;
1690 }
1691 }
1692 }
1693 break;
1694
1695 default:
1696 {
1697 pPar->problemreading = 1;
1698 std::ostringstream message;
1699 message << "ReadPAR: Unknown PAR version";
1700 ExceptionObject exception(__FILE__, __LINE__,
1701 message.str(),
1702 ITK_LOCATION);
1703 throw exception;
1704 }
1705 }
1706
1707 // Reorder the image type matrix so that it is least to greatest.
1708 // Only if the slices need sorting.
1709 if ( !pPar->slicessorted )
1710 {
1711 std::vector< int > sortedImageTypes;
1712 for ( int j = 0; j < pPar->num_image_types; j++ )
1713 {
1714 sortedImageTypes.push_back(pPar->image_types[j]);
1715 }
1716
1717 std::sort( sortedImageTypes.begin(), sortedImageTypes.end() );
1718 for ( int k = 0; k < pPar->num_image_types; k++ )
1719 {
1720 pPar->image_types[k] = sortedImageTypes[k];
1721 }
1722
1723 // Reorder the scanning sequences matrix so that it is least to greatest.
1724 std::vector< int > sortedScanningSequences;
1725 for ( int l = 0; l < pPar->num_scanning_sequences; l++ )
1726 {
1727 sortedScanningSequences.push_back(pPar->scanning_sequences[l]);
1728 }
1729
1730 std::sort( sortedScanningSequences.begin(), sortedScanningSequences.end() );
1731 for ( int m = 0; m < pPar->num_scanning_sequences; m++ )
1732 {
1733 pPar->scanning_sequences[m] = sortedScanningSequences[m];
1734 }
1735 }
1736
1737 // This is a final fixup that will report the total z dimension
1738 // as the product of the #of slices and the number of image blocks.
1739 pPar->dim[2] *= pPar->image_blocks;
1740 }
1741
1742 PhilipsPAR::PARSliceIndexImageTypeVector
GetRECSliceIndexImageTypes(std::string parFile)1743 PhilipsPAR::GetRECSliceIndexImageTypes(std::string parFile)
1744 {
1745 PhilipsPAR::PARSliceIndexImageTypeVector recSliceIndexImageTypes;
1746 int ResToolsVersion;
1747
1748 // Check version of PAR file.
1749 ResToolsVersion = this->GetPARVersion(parFile);
1750 if ( ResToolsVersion == RESEARCH_IMAGE_EXPORT_TOOL_UNKNOWN )
1751 {
1752 return recSliceIndexImageTypes;
1753 }
1754
1755 switch ( ResToolsVersion )
1756 {
1757 case RESEARCH_IMAGE_EXPORT_TOOL_V3:
1758 {
1759 struct image_info_defV3 tempInfo;
1760 PhilipsPAR::PARSliceIndexImageType sliceAndType;
1761 int lineIncrement = 89;
1762 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1763 while ( !tempInfo.problemreading && tempInfo.slice )
1764 {
1765 sliceAndType.first = tempInfo.slice;
1766 sliceAndType.second = tempInfo.image_type_mr;
1767 recSliceIndexImageTypes.push_back(sliceAndType);
1768 ++lineIncrement;
1769 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1770 }
1771 }
1772 break;
1773 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
1774 {
1775 struct image_info_defV4 tempInfo;
1776 PhilipsPAR::PARSliceIndexImageType sliceAndType;
1777 int lineIncrement = 92;
1778 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1779 while ( !tempInfo.problemreading && tempInfo.slice )
1780 {
1781 sliceAndType.first = tempInfo.slice;
1782 sliceAndType.second = tempInfo.image_type_mr;
1783 recSliceIndexImageTypes.push_back(sliceAndType);
1784 ++lineIncrement;
1785 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1786 }
1787 }
1788 break;
1789 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1790 {
1791 struct image_info_defV4 tempInfo;
1792 PhilipsPAR::PARSliceIndexImageType sliceAndType;
1793 int lineIncrement = 99;
1794 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
1795 while ( !tempInfo.problemreading && tempInfo.slice )
1796 {
1797 sliceAndType.first = tempInfo.slice;
1798 sliceAndType.second = tempInfo.image_type_mr;
1799 recSliceIndexImageTypes.push_back(sliceAndType);
1800 ++lineIncrement;
1801 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
1802 }
1803 }
1804 break;
1805 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
1806 {
1807 struct image_info_defV4 tempInfo;
1808 PhilipsPAR::PARSliceIndexImageType sliceAndType;
1809 int lineIncrement = 101;
1810 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
1811 while ( !tempInfo.problemreading && tempInfo.slice )
1812 {
1813 sliceAndType.first = tempInfo.slice;
1814 sliceAndType.second = tempInfo.image_type_mr;
1815 recSliceIndexImageTypes.push_back(sliceAndType);
1816 ++lineIncrement;
1817 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
1818 }
1819 }
1820 break;
1821 }
1822 return recSliceIndexImageTypes;
1823 }
1824
1825 PhilipsPAR::PARSliceIndexScanSequenceVector
GetRECSliceIndexScanningSequence(std::string parFile)1826 PhilipsPAR::GetRECSliceIndexScanningSequence(std::string parFile)
1827 {
1828 PhilipsPAR::PARSliceIndexScanSequenceVector recSliceIndexScanSequence;
1829 int ResToolsVersion;
1830
1831 // Check version of PAR file.
1832 ResToolsVersion = this->GetPARVersion(parFile);
1833 if ( ResToolsVersion == RESEARCH_IMAGE_EXPORT_TOOL_UNKNOWN )
1834 {
1835 return recSliceIndexScanSequence;
1836 }
1837
1838 switch ( ResToolsVersion )
1839 {
1840 case RESEARCH_IMAGE_EXPORT_TOOL_V3:
1841 {
1842 struct image_info_defV3 tempInfo;
1843 PhilipsPAR::PARSliceIndexScanSequence sliceAndSequence;
1844 int lineIncrement = 89;
1845 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1846 while ( !tempInfo.problemreading && tempInfo.slice )
1847 {
1848 sliceAndSequence.first = tempInfo.slice;
1849 sliceAndSequence.second = tempInfo.scan_sequence;
1850 recSliceIndexScanSequence.push_back(sliceAndSequence);
1851 ++lineIncrement;
1852 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1853 }
1854 }
1855 break;
1856 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
1857 {
1858 struct image_info_defV4 tempInfo;
1859 PhilipsPAR::PARSliceIndexScanSequence sliceAndSequence;
1860 int lineIncrement = 92;
1861 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1862 while ( !tempInfo.problemreading && tempInfo.slice )
1863 {
1864 sliceAndSequence.first = tempInfo.slice;
1865 sliceAndSequence.second = tempInfo.scan_sequence;
1866 recSliceIndexScanSequence.push_back(sliceAndSequence);
1867 ++lineIncrement;
1868 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1869 }
1870 }
1871 break;
1872 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1873 {
1874 struct image_info_defV4 tempInfo;
1875 PhilipsPAR::PARSliceIndexScanSequence sliceAndSequence;
1876 int lineIncrement = 99;
1877 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
1878 while ( !tempInfo.problemreading && tempInfo.slice )
1879 {
1880 sliceAndSequence.first = tempInfo.slice;
1881 sliceAndSequence.second = tempInfo.scan_sequence;
1882 recSliceIndexScanSequence.push_back(sliceAndSequence);
1883 ++lineIncrement;
1884 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
1885 }
1886 }
1887 break;
1888 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
1889 {
1890 struct image_info_defV4 tempInfo;
1891 PhilipsPAR::PARSliceIndexScanSequence sliceAndSequence;
1892 int lineIncrement = 101;
1893 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
1894 while ( !tempInfo.problemreading && tempInfo.slice )
1895 {
1896 sliceAndSequence.first = tempInfo.slice;
1897 sliceAndSequence.second = tempInfo.scan_sequence;
1898 recSliceIndexScanSequence.push_back(sliceAndSequence);
1899 ++lineIncrement;
1900 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
1901 }
1902 }
1903 break;
1904 }
1905 return recSliceIndexScanSequence;
1906 }
1907
1908 PhilipsPAR::PARImageTypeScanSequenceVector
GetImageTypesScanningSequence(std::string parFile)1909 PhilipsPAR::GetImageTypesScanningSequence(std::string parFile)
1910 {
1911 PhilipsPAR::PARImageTypeScanSequenceVector recImageTypesScanSequence;
1912 struct par_parameter parParam;
1913
1914 // Read the PAR file.
1915 try
1916 {
1917 this->ReadPAR(parFile, &parParam);
1918 }
1919 catch ( ExceptionObject & )
1920 {
1921 return recImageTypesScanSequence;
1922 }
1923
1924 switch ( parParam.ResToolsVersion )
1925 {
1926 case RESEARCH_IMAGE_EXPORT_TOOL_V3:
1927 {
1928 struct image_info_defV3 tempInfo;
1929 for ( int scanIndex = 0; scanIndex < parParam.num_scanning_sequences;
1930 scanIndex++ )
1931 {
1932 PhilipsPAR::PARImageTypeScanSequence imageTypeAndSequence;
1933 int lineIncrement = 89;
1934 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
1935 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1936 while ( !tempInfo.problemreading && tempInfo.slice )
1937 {
1938 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
1939 && ( tempInfo.scan_sequence == *( parParam.scanning_sequences + scanIndex ) ) )
1940 {
1941 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
1942 }
1943 ++lineIncrement;
1944 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
1945 }
1946 for ( int imageTypeIndex = 0; imageTypeIndex < PAR_DEFAULT_IMAGE_TYPES_SIZE;
1947 imageTypeIndex++ )
1948 {
1949 if ( *( imageType + imageTypeIndex ) >= 0 )
1950 {
1951 imageTypeAndSequence.first = imageTypeIndex;
1952 imageTypeAndSequence.second =
1953 *( parParam.scanning_sequences + scanIndex );
1954 recImageTypesScanSequence.push_back(imageTypeAndSequence);
1955 }
1956 }
1957 }
1958 }
1959 break;
1960 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
1961 {
1962 struct image_info_defV4 tempInfo;
1963 for ( int scanIndex = 0; scanIndex < parParam.num_scanning_sequences;
1964 scanIndex++ )
1965 {
1966 PhilipsPAR::PARImageTypeScanSequence imageTypeAndSequence;
1967 int lineIncrement = 92;
1968 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
1969 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1970 while ( !tempInfo.problemreading && tempInfo.slice )
1971 {
1972 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
1973 && ( tempInfo.scan_sequence == *( parParam.scanning_sequences + scanIndex ) ) )
1974 {
1975 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
1976 }
1977 ++lineIncrement;
1978 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
1979 }
1980 for ( int imageTypeIndex = 0; imageTypeIndex < PAR_DEFAULT_IMAGE_TYPES_SIZE;
1981 imageTypeIndex++ )
1982 {
1983 if ( *( imageType + imageTypeIndex ) >= 0 )
1984 {
1985 imageTypeAndSequence.first = imageTypeIndex;
1986 imageTypeAndSequence.second =
1987 *( parParam.scanning_sequences + scanIndex );
1988 recImageTypesScanSequence.push_back(imageTypeAndSequence);
1989 }
1990 }
1991 }
1992 }
1993 break;
1994 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
1995 {
1996 struct image_info_defV4 tempInfo;
1997 for ( int scanIndex = 0; scanIndex < parParam.num_scanning_sequences;
1998 scanIndex++ )
1999 {
2000 PhilipsPAR::PARImageTypeScanSequence imageTypeAndSequence;
2001 int lineIncrement = 99;
2002 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
2003 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
2004 while ( !tempInfo.problemreading && tempInfo.slice )
2005 {
2006 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
2007 && ( tempInfo.scan_sequence == *( parParam.scanning_sequences + scanIndex ) ) )
2008 {
2009 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
2010 }
2011 ++lineIncrement;
2012 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
2013 }
2014 for ( int imageTypeIndex = 0; imageTypeIndex < PAR_DEFAULT_IMAGE_TYPES_SIZE;
2015 imageTypeIndex++ )
2016 {
2017 if ( *( imageType + imageTypeIndex ) >= 0 )
2018 {
2019 imageTypeAndSequence.first = imageTypeIndex;
2020 imageTypeAndSequence.second =
2021 *( parParam.scanning_sequences + scanIndex );
2022 recImageTypesScanSequence.push_back(imageTypeAndSequence);
2023 }
2024 }
2025 }
2026 }
2027 break;
2028 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
2029 {
2030 struct image_info_defV4 tempInfo;
2031 for ( int scanIndex = 0; scanIndex < parParam.num_scanning_sequences;
2032 scanIndex++ )
2033 {
2034 PhilipsPAR::PARImageTypeScanSequence imageTypeAndSequence;
2035 int lineIncrement = 101;
2036 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
2037 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
2038 while ( !tempInfo.problemreading && tempInfo.slice )
2039 {
2040 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
2041 && ( tempInfo.scan_sequence == *( parParam.scanning_sequences + scanIndex ) ) )
2042 {
2043 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
2044 }
2045 ++lineIncrement;
2046 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
2047 }
2048 for ( int imageTypeIndex = 0; imageTypeIndex < PAR_DEFAULT_IMAGE_TYPES_SIZE;
2049 imageTypeIndex++ )
2050 {
2051 if ( *( imageType + imageTypeIndex ) >= 0 )
2052 {
2053 imageTypeAndSequence.first = imageTypeIndex;
2054 imageTypeAndSequence.second =
2055 *( parParam.scanning_sequences + scanIndex );
2056 recImageTypesScanSequence.push_back(imageTypeAndSequence);
2057 }
2058 }
2059 }
2060 }
2061 break;
2062 }
2063 return recImageTypesScanSequence;
2064 }
2065
GetRECRescaleValues(std::string parFile,PhilipsPAR::PARRescaleValuesContainer * rescaleValues,int scan_sequence)2066 bool PhilipsPAR::GetRECRescaleValues(std::string parFile,
2067 PhilipsPAR::PARRescaleValuesContainer *rescaleValues, int scan_sequence)
2068 {
2069 int ResToolsVersion;
2070
2071 rescaleValues->clear();
2072 // Must match size of image_types
2073 rescaleValues->resize(PAR_DEFAULT_IMAGE_TYPES_SIZE);
2074 PhilipsPAR::PARRescaleValues zero(0.0);
2075 for ( unsigned int zeroIndex = 0; zeroIndex < rescaleValues->size(); zeroIndex++ )
2076 {
2077 ( *rescaleValues )[zeroIndex] = zero; // Zero out everything
2078 }
2079
2080 // Check version of PAR file.
2081 ResToolsVersion = this->GetPARVersion(parFile);
2082 if ( ResToolsVersion == RESEARCH_IMAGE_EXPORT_TOOL_UNKNOWN )
2083 {
2084 return false;
2085 }
2086
2087 switch ( ResToolsVersion )
2088 {
2089 case RESEARCH_IMAGE_EXPORT_TOOL_V3:
2090 {
2091 struct image_info_defV3 tempInfo;
2092 PhilipsPAR::PARRescaleValues rescale;
2093 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
2094 int lineIncrement = 89;
2095 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
2096 while ( !tempInfo.problemreading && tempInfo.slice )
2097 {
2098 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
2099 && ( tempInfo.scan_sequence == scan_sequence ) )
2100 {
2101 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
2102 rescale[0] = tempInfo.rescale_int;
2103 rescale[1] = tempInfo.rescale_slope;
2104 rescale[2] = tempInfo.scale_slope;
2105 ( *rescaleValues )[tempInfo.image_type_mr] = rescale;
2106 }
2107 ++lineIncrement;
2108 tempInfo = GetImageInformationDefinitionV3(parFile, lineIncrement, this);
2109 }
2110 }
2111 break;
2112 case RESEARCH_IMAGE_EXPORT_TOOL_V4:
2113 {
2114 struct image_info_defV4 tempInfo;
2115 PhilipsPAR::PARRescaleValues rescale;
2116 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
2117 int lineIncrement = 92;
2118 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
2119 while ( !tempInfo.problemreading && tempInfo.slice )
2120 {
2121 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
2122 && ( tempInfo.scan_sequence == scan_sequence ) )
2123 {
2124 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
2125 rescale[0] = tempInfo.rescale_int;
2126 rescale[1] = tempInfo.rescale_slope;
2127 rescale[2] = tempInfo.scale_slope;
2128 ( *rescaleValues )[tempInfo.image_type_mr] = rescale;
2129 }
2130 ++lineIncrement;
2131 tempInfo = GetImageInformationDefinitionV4(parFile, lineIncrement, this);
2132 }
2133 }
2134 break;
2135 case RESEARCH_IMAGE_EXPORT_TOOL_V4_1:
2136 {
2137 struct image_info_defV4 tempInfo;
2138 PhilipsPAR::PARRescaleValues rescale;
2139 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
2140 int lineIncrement = 99;
2141 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
2142 while ( !tempInfo.problemreading && tempInfo.slice )
2143 {
2144 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
2145 && ( tempInfo.scan_sequence == scan_sequence ) )
2146 {
2147 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
2148 rescale[0] = tempInfo.rescale_int;
2149 rescale[1] = tempInfo.rescale_slope;
2150 rescale[2] = tempInfo.scale_slope;
2151 ( *rescaleValues )[tempInfo.image_type_mr] = rescale;
2152 }
2153 ++lineIncrement;
2154 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
2155 }
2156 }
2157 break;
2158 case RESEARCH_IMAGE_EXPORT_TOOL_V4_2:
2159 {
2160 struct image_info_defV4 tempInfo;
2161 PhilipsPAR::PARRescaleValues rescale;
2162 int imageType[PAR_DEFAULT_IMAGE_TYPES_SIZE] = { -1, -1, -1, -1, -1, -1, -1, -1 };
2163 int lineIncrement = 101;
2164 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
2165 while ( !tempInfo.problemreading && tempInfo.slice )
2166 {
2167 if ( ( *( imageType + tempInfo.image_type_mr ) < 0 )
2168 && ( tempInfo.scan_sequence == scan_sequence ) )
2169 {
2170 *( imageType + tempInfo.image_type_mr ) = tempInfo.image_type_mr;
2171 rescale[0] = tempInfo.rescale_int;
2172 rescale[1] = tempInfo.rescale_slope;
2173 rescale[2] = tempInfo.scale_slope;
2174 ( *rescaleValues )[tempInfo.image_type_mr] = rescale;
2175 }
2176 ++lineIncrement;
2177 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
2178 }
2179 }
2180 break;
2181 }
2182 return true;
2183 }
2184
GetDiffusionGradientOrientationAndBValues(std::string parFile,PhilipsPAR::PARDiffusionValuesContainer * gradientValues,PhilipsPAR::PARBValuesContainer * bValues)2185 bool PhilipsPAR::GetDiffusionGradientOrientationAndBValues(std::string parFile,
2186 PhilipsPAR::PARDiffusionValuesContainer *gradientValues,
2187 PhilipsPAR::PARBValuesContainer *bValues)
2188 {
2189 gradientValues->resize(0); // Reset to zero size.
2190 bValues->resize(0);
2191 struct par_parameter tempPar;
2192 int ResToolsVersion;
2193
2194 // Check version of PAR file.
2195 // Diffusion gradients are only stored in PAR version >= 4.1
2196 ResToolsVersion = this->GetPARVersion(parFile);
2197 if ( ResToolsVersion >= RESEARCH_IMAGE_EXPORT_TOOL_V4_1 )
2198 {
2199 struct image_info_defV4 tempInfo;
2200 int gradientOrientationNumber = -1;
2201 int lineIncrement = 99;
2202
2203 if ( ResToolsVersion == RESEARCH_IMAGE_EXPORT_TOOL_V4_2 )
2204 {
2205 lineIncrement = 101;
2206 }
2207
2208 try
2209 {
2210 this->ReadPAR(parFile, &tempPar);
2211 }
2212 catch ( ExceptionObject & )
2213 {
2214 return false;
2215 }
2216
2217 gradientValues->resize(tempPar.max_num_grad_orient);
2218 bValues->resize(tempPar.max_num_grad_orient);
2219
2220 if ( tempPar.max_num_grad_orient <= 0 )
2221 {
2222 return true;
2223 }
2224
2225 // Can use either version 4.1 or 4.2 GetImageInformationDefinition
2226 // function.
2227 int gradientDirectionCount = 0;
2228 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
2229 while ( !tempInfo.problemreading && tempInfo.slice
2230 && ( gradientDirectionCount < tempPar.max_num_grad_orient ) )
2231 {
2232 int tempGradientOrientationNumber = tempInfo.gradient_orientation_number;
2233 if ( gradientOrientationNumber != tempGradientOrientationNumber )
2234 {
2235 PhilipsPAR::PARDiffusionValues direction;
2236 direction[0] = tempInfo.diffusion_ap;
2237 direction[1] = tempInfo.diffusion_fh;
2238 direction[2] = tempInfo.diffusion_rl;
2239 ( *gradientValues )[gradientDirectionCount] = direction;
2240 ( *bValues )[gradientDirectionCount] = tempInfo.diffusion_b_factor;
2241 ++gradientDirectionCount;
2242 gradientOrientationNumber = tempGradientOrientationNumber;
2243 }
2244 ++lineIncrement;
2245 tempInfo = GetImageInformationDefinitionV41(parFile, lineIncrement, this);
2246 }
2247 }
2248 return true;
2249 }
2250
GetLabelTypesASL(std::string parFile,PhilipsPAR::PARLabelTypesASLContainer * labelTypes)2251 bool PhilipsPAR::GetLabelTypesASL(std::string parFile,
2252 PhilipsPAR::PARLabelTypesASLContainer *labelTypes)
2253 {
2254 labelTypes->resize(0); // Reset to zero size.
2255 struct par_parameter tempPar;
2256 int ResToolsVersion;
2257
2258 // Check version of PAR file.
2259 // ASL labels are only stored in PAR version >= 4.2
2260 ResToolsVersion = this->GetPARVersion(parFile);
2261 if ( ResToolsVersion >= RESEARCH_IMAGE_EXPORT_TOOL_V4_2 )
2262 {
2263 struct image_info_defV4 tempInfo;
2264 int aslLabelNumber = -1;
2265 int lineIncrement = 101;
2266
2267 try
2268 {
2269 this->ReadPAR(parFile, &tempPar);
2270 }
2271 catch ( ExceptionObject & )
2272 {
2273 return false;
2274 }
2275
2276 labelTypes->resize(tempPar.num_label_types);
2277
2278 if ( tempPar.num_label_types <= 0 )
2279 {
2280 return true;
2281 }
2282
2283 int aslLabelCount = 0;
2284 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
2285 while ( !tempInfo.problemreading && tempInfo.slice
2286 && ( aslLabelCount < tempPar.num_label_types ) )
2287 {
2288 int tempASLLabelNumber = tempInfo.labelTypeASL;
2289 if ( aslLabelNumber != tempASLLabelNumber )
2290 {
2291 ( *labelTypes )[aslLabelCount] = tempASLLabelNumber;
2292 ++aslLabelCount;
2293 aslLabelNumber = tempASLLabelNumber;
2294 }
2295 ++lineIncrement;
2296 tempInfo = GetImageInformationDefinitionV42(parFile, lineIncrement, this);
2297 }
2298 }
2299 return true;
2300 }
2301
PrintSelf(std::ostream & os,Indent indent) const2302 void PhilipsPAR::PrintSelf(std::ostream & os, Indent indent) const
2303 {
2304 Superclass::PrintSelf(os, indent);
2305 }
2306 } // end namespace itk
2307