]> Creatis software - gdcm.git/blob - Example/Dense2007ToDicom.cxx
Add :
[gdcm.git] / Example / Dense2007ToDicom.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: Dense2007ToDicom.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/07/10 11:00:50 $
7   Version:   $Revision: 1.1 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include <fstream>
20 #include <iostream>
21 //#include <values.h>
22
23 #include "gdcmFile.h"
24 #include "gdcmFileHelper.h"
25 #include "gdcmDebug.h"
26 #include "gdcmDirList.h"
27
28 #include "gdcmArgMgr.h"
29
30 /**
31   * \brief   
32   *  Converts the "Dense" ".txt" (2007 version)  files into 16 bits Dicom Files,
33   * Hope they don't change soon!
34   */  
35
36
37 void LoadPeakStrain(std::ifstream &from, std::string imageName);
38 void LoadStrain(std::ifstream &from, std::string imageName);
39 void MakeDicomImage(float *tabVal, float *X, float *Y, float *Z, int NP, std::string dcmImageName);
40
41
42 int main(int argc, char *argv[])
43 {
44    START_USAGE(usage)
45    " \n Dense2007ToDicom :\n                                                  ",
46    "        Converts the '.txt' files into 16 bits Dicom Files,               ",
47    " usage:                                                                   ",
48    " Dense2007ToDicom strain=...strain.txt  peak_strain=...peak_strain.txt    ",
49    "                 [verbose] [debug]                                        ",
50    "                                                                          ",
51    " verbose  : user wants to run the program in 'verbose mode'               ",
52    " debug    : *developer*  wants to run the program in 'debug mode'         ",
53    FINISH_USAGE
54
55    // ----- Initialize Arguments Manager ------
56       
57    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
58   
59    if (argc == 1 || am->ArgMgrDefined("usage")) 
60    {
61       am->ArgMgrUsage(usage); // Display 'usage'
62       delete am;
63       return 0;
64    }
65
66    const char *strain      = am->ArgMgrWantString("strain",usage);
67    const char *peak_strain = am->ArgMgrWantString("peak_strain",usage);
68    
69    if (am->ArgMgrDefined("debug"))
70       GDCM_NAME_SPACE::Debug::DebugOn();
71       
72    int verbose  = am->ArgMgrDefined("verbose");      
73
74    
75    // if unused Param we give up
76    if ( am->ArgMgrPrintUnusedLabels() )
77    { 
78       am->ArgMgrUsage(usage);
79       delete am;
80       return 0;
81    }
82    delete am;  // we don't need Argument Manager any longer
83
84    // ----- Begin Processing -----
85
86
87       std::ifstream fromPeakStrain( peak_strain );             
88       if ( !fromPeakStrain )
89       {
90          std::cout << "Can't open file" << peak_strain << std::endl;
91          exit(0);
92       }
93       
94       std::ifstream fromStrain( strain );      
95       if ( !fromStrain )
96       {
97          std::cout << "Can't open file" << strain << std::endl;
98           exit(0);
99      }      
100             
101       std::cout << "Success in open file" << peak_strain << std::endl;
102       LoadPeakStrain(fromPeakStrain, peak_strain);
103       fromPeakStrain.close();  
104      
105       std::cout << "Success in open file" << strain << std::endl;
106       LoadStrain(fromStrain, strain);
107       fromStrain.close();      
108                
109 }
110
111 // =====================================================================================================================
112
113 void LoadPeakStrain(std::ifstream &from, std::string textFileName)
114 {
115 // in sax_base_slice0_peak_strain.txt :
116
117 /*
118 Number of material points (NP) = 181
119 Origin of (readout, phase enc, slice sel) coordinates in 3D =  87.3243 3.19392
120 88.2381
121 Readout direction in 3D =  -0.162314 -0.0771294 -0.983720
122 Phase Enc. direction in 3D =  -0.540606 -0.827052 0.154046
123 Slice select direction in 3D =  0.825469 -0.556809 -0.0925458
124 The following are the (readout, phase enc, slice sel) coordinates (mm) of the grid points for which strains are calculated,
125 followed by their peak Ecc strain, an array of NP elements,
126 followed by their peak Err strain, an array of NP elements,
127 followed by their peak E11 strain, an array of NP elements,
128 followed by their Peak E22 strain, an array of NP elements,
129       42.0000      10.0000     0.000000
130       ...
131     -0.154905   -0.0840482    -0.157350    -0.221403    -0.168118    -0.131331
132     -0.153781    -0.148481    -0.166602    -0.232858    -0.222650    -0.213712
133     ...
134 */  
135
136    if (!from)
137       return;
138
139    std::string str1;
140    int NP;
141
142    //Number of material points (NP) = 181   
143     from >> str1;
144     from >> str1;
145     from >> str1;
146     from >> str1;
147     from >> str1;
148     from >> str1;
149     from >> NP;
150     
151     std::cout << "NP : " << NP << std::endl; 
152
153    //Origin of (readout, phase enc, slice sel) coordinates in 3D =  87.3243 3.19392 88.2381
154      from >> str1;
155      from >> str1;
156      from >> str1;
157      from >> str1;
158      from >> str1;
159      from >> str1;
160      from >> str1;
161      from >> str1;
162      from >> str1;
163      from >> str1;
164      from >> str1;
165      
166      float readout,  phase_enc, slice_sel;
167      from >> readout;
168      from >> phase_enc;
169      from >> slice_sel;
170      std::cout << " readout " << readout << " phase_enc " << phase_enc << " slice_sel " << slice_sel << std::endl;
171      
172     // Readout direction in 3D =  -0.162314 -0.0771294 -0.983720
173     
174     from >> str1;
175     from >> str1;
176     from >> str1;
177     from >> str1;
178     from >> str1;
179     
180     float readoutX, readoutY, readoutZ;
181     from >> readoutX;
182     from >> readoutY;       
183     from >> readoutZ;
184     std::cout << " readoutX " << readoutX <<  " readoutY " << readoutY <<  " readoutZ " << readoutZ << std::endl;
185      
186 // Phase Enc. direction in 3D =  -0.540606 -0.827052 0.154046
187
188      from >> str1;
189      from >> str1;
190      from >> str1;
191      from >> str1;
192      from >> str1;
193      from >> str1;
194      
195     float phase_encX, phase_encY, phase_encZ;
196     from >> phase_encX;
197     from >> phase_encY;       
198     from >> phase_encZ;
199     std::cout << " phase_encX " << phase_encX <<  " phase_encY " << phase_encY <<  " phase_encZ " << phase_encZ << std::endl; 
200
201 // Slice select direction in 3D =  0.825469 -0.556809 -0.0925458
202      from >> str1;
203      from >> str1;
204      from >> str1;
205      from >> str1;
206      from >> str1;
207      from >> str1;
208      
209     float slice_selX, slice_selY, slice_selZ;
210     from >> slice_selX;
211     from >> slice_selY;       
212     from >> slice_selZ;
213     std::cout << " slice_selX " << slice_selX <<  " slice_selY " << slice_selY <<  " slice_selZ " << slice_selZ << std::endl; 
214
215
216
217 // Skip 5 lines :
218 /*
219 The following are the (readout, phase enc, slice sel) coordinates (mm) of the grid points for which strains are calculated,
220 followed by their peak Ecc strain, an array of NP elements,
221 followed by their peak Err strain, an array of NP elements,
222 followed by their peak E11 strain, an array of NP elements,
223 followed by their Peak E22 strain, an array of NP elements,
224 */
225
226 std::cout << "------------start skipping 1 line---------------- " << std::endl;
227    std::getline(from, str1);
228    std::cout << "[" << str1 << "]" << std::endl;
229 std::cout << "------------start skipping 1 line---------------- " << std::endl;
230    std::getline(from, str1);
231    std::cout << "[" << str1 << "]" << std::endl;
232 std::cout << "------------start skipping 1 line---------------- " << std::endl;
233    std::getline(from, str1);
234    std::cout << "[" << str1 << "]" << std::endl;
235 std::cout << "------------start skipping 1 line---------------- " << std::endl;
236    std::getline(from, str1);
237    std::cout << "[" << str1 << "]" << std::endl;
238 std::cout << "------------start skipping 1 line---------------- " << std::endl;
239    std::getline(from, str1);
240    std::cout << "[" << str1 << "]" << std::endl;
241 std::cout << "------------start skipping 1 line---------------- " << std::endl;
242    std::getline(from, str1);
243    std::cout << "[" << str1 << "]" << std::endl;
244 std::cout << "------------stop skipping ---------------- " << std::endl;
245   
246    float *X = new float[NP];
247    float *Y = new float[NP];   
248    float *Z = new float[NP];
249       
250    char c;
251    int i;   
252    for (i=0; i<NP; i++) {   
253       from >> X[i];
254       for (;;) {
255         if (!from.get(c))
256           break;
257         if (!isspace(c)) {
258           from.putback(c);
259           break;
260         }
261      }  
262       from >> Y[i];    
263       for (;;) {
264         if (!from.get(c))
265           break;
266         if (!isspace(c)) {
267           from.putback(c);
268           break;
269         }
270      }        
271       from >> Z[i];              
272    }
273
274    std::cout << "--------------- Ecc_strain ------------------" << std::endl;
275    float *ecc_strain = new float[NP];
276    for (i=0; i<NP; i++) {
277        from >> ecc_strain[i]; 
278        std::cout <<  ecc_strain[i] <<  std::endl;
279    }
280
281    std::cout << "--------------- Err_strain ------------------" << std::endl;
282    float *err_strain = new float[NP];
283    for (i=0; i<NP; i++) {
284        from >> err_strain[i]; 
285        std::cout <<  err_strain[i] <<  std::endl;
286    }
287    
288    std::cout << "--------------- E11_strain ------------------" << std::endl;
289    float *e11_strain = new float[NP];
290    for (i=0; i<NP; i++) {
291        from >> e11_strain[i]; 
292        std::cout <<  e11_strain[i] <<  std::endl;
293    }  
294    
295    std::cout << "--------------- E22_strain ------------------" << std::endl;
296    float *e22_strain = new float[NP];
297    for (i=0; i<NP; i++) {
298        from >> e22_strain[i]; 
299        std::cout <<  e22_strain[i] <<  std::endl;
300    }    
301  
302    std::string dcmImageName;    
303
304 //followed by their peak Ecc strain, an array of NP elements,
305    dcmImageName = textFileName + "_peak_Ecc_strain.dcm";
306    MakeDicomImage(ecc_strain, X, Y, Z, NP, dcmImageName);
307
308 //followed by their peak Err strain, an array of NP elements,
309    dcmImageName = textFileName + "_peak_Err_strain.dcm";
310    MakeDicomImage(err_strain, X, Y, Z, NP, dcmImageName);
311    
312 //followed by their peak E11 strain, an array of NP elements,
313    dcmImageName = textFileName + "_peak_E11_strain.dcm";
314    MakeDicomImage(e11_strain, X, Y, Z, NP, dcmImageName);
315    
316 //followed by their Peak E22 strain, an array of NP elements,
317    dcmImageName = textFileName + "_peak_E22_strain.dcm";
318    MakeDicomImage(e22_strain, X, Y, Z, NP, dcmImageName);         
319 }
320
321 // =====================================================================================================================
322
323 void LoadStrain(std::ifstream &from, std::string textFileName)
324 {
325
326 // in sax_base_slice0_strain.txt :
327 /*
328 Number of cine frames = 18
329 Temporal resolution = 32.0000 ms
330 First frame starts at 48.0000 ms
331 Number of material points (NP) = 181
332 Origin of (readout, phase enc, slice sel) coordinates in 3D =  87.324341 3.193918 88.238113 
333 Readout direction in 3D =  -0.162314 -0.0771294 -0.983720
334 Phase Enc. direction in 3D =  -0.540606 -0.827052 0.154046
335 Slice select direction in 3D =  0.825469 -0.556809 -0.0925458
336 The following are the (readout, phase enc, slice sel) coordinates (mm) of the grid points for which strains are calculated,
337 followed by their Ecc strain, an array of dimensions(NP, number of cine frames),
338 followed by their Err strain, an array of dimensions(NP, number of cine frames),
339 followed by their E11 strain, an array of dimensions(NP, number of cine frames),
340 followed by their E22 strain, an array of dimensions(NP, number of cine frames),
341 Note that RV Err, E11 and E22 strains are not calculated due to the small thickness.
342       42.0000      10.0000     0.000000
343       44.0000      10.0000     0.000000
344       ...
345    -0.0622793   -0.0840482    -0.157350    -0.196722    -0.105844    -0.131331
346     -0.153781  -0.00940573   -0.0542236    -0.100403   -0.0369671   -0.0696840      
347 */ 
348
349    if (!from)
350       return;
351
352    std::string str1;
353    int NP;    // Number of Pints
354    int NCF;   // Number of cine frames
355    float TR;  // Temporal resolution
356    float FFS; // First frame starts
357    
358    // Number of cine frames = 18
359     from >> str1;
360     from >> str1;
361     from >> str1;
362     from >> str1;
363     from >> str1;
364     from >> NCF;
365
366    // Temporal resolution = 32.0000 ms
367     from >> str1;
368     from >> str1;
369     from >> str1;
370     from >> TR;
371     from >> str1;
372
373    // First frame starts at 48.0000 ms
374     from >> str1;
375     from >> str1;
376     from >> str1;
377     from >> str1;
378     from >> FFS;
379     from >> str1;        
380
381    //Number of material points (NP) = 181   
382     from >> str1;
383     from >> str1;
384     from >> str1;
385     from >> str1;
386     from >> str1;
387     from >> str1;
388     from >> NP;
389     
390     std::cout << "NP : " << NP << std::endl; 
391
392    //Origin of (readout, phase enc, slice sel) coordinates in 3D = 87.324341 3.193918 88.238113 
393      from >> str1;
394      from >> str1;
395      from >> str1;
396      from >> str1;
397      from >> str1;
398      from >> str1;
399      from >> str1;
400      from >> str1;
401      from >> str1;
402      from >> str1;
403      from >> str1;
404      
405      float readout,  phase_enc, slice_sel;
406      from >> readout;
407      from >> phase_enc;
408      from >> slice_sel;
409      std::cout << " readout " << readout << " phase_enc " << phase_enc << " slice_sel " << slice_sel << std::endl;
410      
411     // Readout direction in 3D =  -0.162314 -0.0771294 -0.983720
412     
413     from >> str1;
414     from >> str1;
415     from >> str1;
416     from >> str1;
417     from >> str1;
418     
419     float readoutX, readoutY, readoutZ;
420     from >> readoutX;
421     from >> readoutY;       
422     from >> readoutZ;
423     std::cout << " readoutX " << readoutX <<  " readoutY " << readoutY <<  " readoutZ " << readoutZ << std::endl;
424      
425 // Phase Enc. direction in 3D =  -0.540606 -0.827052 0.154046
426
427      from >> str1;
428      from >> str1;
429      from >> str1;
430      from >> str1;
431      from >> str1;
432      from >> str1;
433      
434     float phase_encX, phase_encY, phase_encZ;
435     from >> phase_encX;
436     from >> phase_encY;       
437     from >> phase_encZ;
438     std::cout << " phase_encX " << phase_encX <<  " phase_encY " << phase_encY <<  " phase_encZ " << phase_encZ << std::endl; 
439
440 // Slice select direction in 3D =  0.825469 -0.556809 -0.0925458
441      from >> str1;
442      from >> str1;
443      from >> str1;
444      from >> str1;
445      from >> str1;
446      from >> str1;
447      
448     float slice_selX, slice_selY, slice_selZ;
449     from >> slice_selX;
450     from >> slice_selY;       
451     from >> slice_selZ;
452     std::cout << " slice_selX " << slice_selX <<  " slice_selY " << slice_selY <<  " slice_selZ " << slice_selZ << std::endl; 
453
454
455
456 // Skip 6 lines :
457 /*
458 The following are the (readout, phase enc, slice sel) coordinates (mm) of the grid points for which strains are calculated,
459 followed by their Ecc strain, an array of dimensions(NP, number of cine frames),
460 followed by their Err strain, an array of dimensions(NP, number of cine frames),
461 followed by their E11 strain, an array of dimensions(NP, number of cine frames),
462 followed by their E22 strain, an array of dimensions(NP, number of cine frames),
463 Note that RV Err, E11 and E22 strains are not calculated due to the small thickness.
464 */
465 std::cout << "------------start skipping 1 line---------------- " << std::endl;
466    std::getline(from, str1);
467    std::cout << "[" << str1 << "]" << std::endl;
468 std::cout << "------------start skipping 1 line---------------- " << std::endl;
469    std::getline(from, str1);
470    std::cout << "[" << str1 << "]" << std::endl;
471 std::cout << "------------start skipping 1 line---------------- " << std::endl;
472    std::getline(from, str1);
473    std::cout << "[" << str1 << "]" << std::endl;
474 std::cout << "------------start skipping 1 line---------------- " << std::endl;
475    std::getline(from, str1);
476    std::cout << "[" << str1 << "]" << std::endl;
477 std::cout << "------------start skipping 1 line---------------- " << std::endl;
478    std::getline(from, str1);
479    std::cout << "[" << str1 << "]" << std::endl;
480 std::cout << "------------start skipping 1 line---------------- " << std::endl;
481    std::getline(from, str1);
482    std::cout << "[" << str1 << "]" << std::endl;
483 std::cout << "------------stop skipping ---------------- " << std::endl;
484    std::getline(from, str1);
485    std::cout << "[" << str1 << "]" << std::endl;
486 std::cout << "------------stop skipping ---------------- " << std::endl;
487   
488    float *X = new float[NP];
489    float *Y = new float[NP];   
490    float *Z = new float[NP];
491       
492    char c;
493    int i;   
494    for (i=0; i<NP; i++) {
495    
496       from >> X[i];
497       for (;;) {
498         if (!from.get(c))
499           break;
500         if (!isspace(c)) {
501           from.putback(c);
502           break;
503         }
504      }  
505       from >> Y[i];  
506       for (;;) {
507         if (!from.get(c))
508           break;
509         if (!isspace(c)) {
510           from.putback(c);
511           break;
512         }
513      }        
514       from >> Z[i];              
515    }
516
517    std::cout << "--------------- Ecc_strain ------------------" << std::endl;
518    float *ecc_strain = new float[NP];
519    for (i=0; i<NP; i++) {
520        from >> ecc_strain[i]; 
521        std::cout <<  ecc_strain[i] <<  std::endl;
522    }
523
524    std::cout << "--------------- Err_strain ------------------" << std::endl;
525    float *err_strain = new float[NP];
526    for (i=0; i<NP; i++) {
527        from >> err_strain[i]; 
528        std::cout <<  err_strain[i] <<  std::endl;
529    }
530    
531    std::cout << "--------------- E11_strain ------------------" << std::endl;
532    float *e11_strain = new float[NP];
533    for (i=0; i<NP; i++) {
534        from >> e11_strain[i]; 
535        std::cout <<  e11_strain[i] <<  std::endl;
536    }  
537    
538    std::cout << "--------------- E22_strain ------------------" << std::endl;
539    float *e22_strain = new float[NP];
540    for (i=0; i<NP; i++) {
541        from >> e22_strain[i]; 
542        std::cout <<  e22_strain[i] <<  std::endl;
543    }    
544
545    std::string dcmImageName;    
546
547 //followed by their Ecc strain, an array of NP elements,
548    dcmImageName = textFileName + "_Ecc_strain.dcm";
549    MakeDicomImage(ecc_strain, X, Y, Z, NP, dcmImageName);
550
551 //followed by their  Err strain, an array of NP elements,
552    dcmImageName = textFileName + "_Err_strain.dcm";
553    MakeDicomImage(err_strain, X, Y, Z, NP, dcmImageName);
554    
555 //followed by their E11 strain, an array of NP elements,
556    dcmImageName = textFileName + "_E11_strain.dcm";
557    MakeDicomImage(e11_strain, X, Y, Z, NP, dcmImageName);
558    
559 //followed by their E22 strain, an array of NP elements,
560    dcmImageName = textFileName + "_E22_strain.dcm";
561    MakeDicomImage(e22_strain, X, Y, Z, NP, dcmImageName);   
562       
563 }
564
565
566 // =====================================================================================================================
567     
568
569 void MakeDicomImage(float *tabVal, float *X, float *Y, float *Z, int NP, std::string dcmImageName)
570 {
571    float minX = 999., minY = 999., minZ = 999.;
572    float maxX = 0., maxY = 0., maxZ = 0.;
573    int i;
574    for (i=0; i<NP; i++) {
575       // std::cout << X[i] << " " << Y[i] << " " << Z[i] <<  std::endl;
576       if(maxX < X[i])
577          maxX = X[i];
578       if(maxY < Y[i])
579          maxY = Y[i];
580       if(maxZ < Z[i])
581          maxZ = Z[i];
582  
583       if(minX > X[i])
584          minX = X[i];
585       if(minY > Y[i])
586          minY = Y[i];
587       if(minZ > Z[i])
588          minZ = Z[i];
589  
590    }   
591       std::cout << "Min X,Y,Z " << minX << " " << minY << " " << minZ <<  std::endl;
592       std::cout << "Max X,Y,Z " << maxX << " " << maxY << " " << maxZ <<  std::endl;
593       std::cout << "Size X,Y,Z " << maxX-minX << " " << maxY-minY << " " << maxZ-minZ <<  std::endl;      
594
595
596     uint16_t *img = new uint16_t[int(maxX*maxY)];
597     
598     for(int i3=0;i3<int(maxX*maxY);i3++)
599        img[i3] = 0; 
600      
601     for(int i2=0; i2<NP; i2++) {
602     img[ int(maxX -(X[i2]-1))+  int((maxY -Y[i2])* maxX) ] = int(tabVal[i2]*100);
603     }       
604   
605  // GDCM_NAME_SPACE::Debug::DebugOn();
606   
607        std::ostringstream str; 
608        GDCM_NAME_SPACE::File *file;
609        file = GDCM_NAME_SPACE::File::New();       
610               
611   // Set the image size
612         str.str("");
613         str << (int)maxX;
614         file->InsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns
615         str.str("");
616         str << (int)maxY;
617         file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
618   // Set the pixel type
619   //      16; //8, 16, 32
620         file->InsertEntryString("16",0x0028,0x0100,"US"); // Bits Allocated
621         str.str("");
622         str << 16; // may be 12 or 16 if componentSize =16
623         file->InsertEntryString("16",0x0028,0x0101,"US"); // Bits Stored
624         file->InsertEntryString("15",0x0028,0x0102,"US"); // High Bit
625
626   // Set the pixel representation // 0/1 , 0=unsigned
627         file->InsertEntryString("1",0x0028,0x0103, "US"); // Pixel Representation
628   // Set the samples per pixel // 1:Grey level, 3:RGB
629         file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
630
631 /*
632   // Set Rescale Intercept
633         str.str("");
634         str << div;  
635         file->InsertEntryString(str.str(),0x0028,0x1052,"DS");
636
637   // Set Rescale Slope
638         str.str("");
639         str << mini;  
640         file->InsertEntryString(str.str(),0x0028,0x1053,"DS");
641 */
642     
643     GDCM_NAME_SPACE::FileHelper *fileH;
644     fileH = GDCM_NAME_SPACE::FileHelper::New(file);
645     // cast is just to avoid warnings (*no* conversion)
646     fileH->SetImageData((uint8_t *)img,int(maxX*maxY)*sizeof(uint16_t));
647     fileH->SetWriteModeToRaw(); 
648     fileH->SetWriteTypeToDcmExplVR();
649         
650     if( !fileH->Write(dcmImageName))
651        std::cout << "Failed for [" << dcmImageName << "]\n"
652                  << "           File is unwrittable" << std::endl;
653
654     file->Print();
655            
656    delete img;
657    file->Delete();
658    fileH->Delete();  
659 }