Revert "Update package dependency from libwxgtk3.0-dev to libwxgtk3.0-gtk3-dev for...
[ctsim.git] / tools / phm2helix.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          phm2helix.cpp
5 **   Purpose:       Take projections of a phantom object
6 **   Programmers:   Ian Kay and Kevin Rosenberg
7 **   Date Started:  Aug 2001
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2009 Kevin Rosenberg
11 **
12 **  This program is free software; you can redistribute it and/or modify
13 **  it under the terms of the GNU General Public License (version 2) as
14 **  published by the Free Software Foundation.
15 **
16 **  This program is distributed in the hope that it will be useful,
17 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 **  GNU General Public License for more details.
20 **
21 **  You should have received a copy of the GNU General Public License
22 **  along with this program; if not, write to the Free Software
23 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 ******************************************************************************/
25
26 #include "ct.h"
27 #include "timer.h"
28
29
30 enum { O_PHANTOMPROG, O_PHMFILE,  O_DESC, O_NRAY, O_ROTANGLE, O_GEOMETRY, O_FOCAL_LENGTH, O_CENTER_DETECTOR_LENGTH,
31   O_VIEW_RATIO, O_SCAN_RATIO, O_OFFSETVIEW,  O_TRACE, O_VERBOSE, O_HELP, O_DEBUG, O_VERSION };
32
33 static struct option phm2helix_options[] =
34 {
35   {"phantom", 1, 0, O_PHANTOMPROG},
36   {"desc", 1, 0, O_DESC},
37   {"nray", 1, 0, O_NRAY},
38   {"rotangle", 1, 0, O_ROTANGLE},
39   {"geometry", 1, 0, O_GEOMETRY},
40   {"focal-length", 1, 0, O_FOCAL_LENGTH},
41   {"center-detector-length", 1, 0, O_CENTER_DETECTOR_LENGTH},
42   {"view-ratio", 1, 0, O_VIEW_RATIO},
43   {"scan-ratio", 1, 0, O_SCAN_RATIO},
44   {"offsetview", 1, 0, O_OFFSETVIEW},
45   {"trace", 1, 0, O_TRACE},
46   {"verbose", 0, 0, O_VERBOSE},
47   {"help", 0, 0, O_HELP},
48   {"debug", 0, 0, O_DEBUG},
49   {"version", 0, 0, O_VERSION},
50   {"phmfile", 1, 0, O_PHMFILE},
51   {0, 0, 0, 0}
52 };
53
54 static const char* g_szIdStr = "$Id$";
55
56
57 void
58 phm2helix_usage (const char *program)
59 {
60           std::cout << "usage: " << fileBasename(program) << " outfile ndet nview phmprog [OPTIONS]\n";
61           std::cout << "Calculate (projections) through time varying phantom object  \n\n";
62           std::cout << "     outfile          Name of output file for projectsions\n";
63           std::cout << "     ndet             Number of detectors\n";
64           std::cout << "     nview            Number of rotated views\n";
65           std::cout << "     phmprog          Name of phm generation executable\n";
66           std::cout << "     --phmfile        Temp phantom file name \n";
67           std::cout << "     --desc           Description of raysum\n";
68           std::cout << "     --nray           Number of rays per detector (default = 1)\n";
69           std::cout << "     --rotangle       Angle to rotate view through (fraction of a circle)\n";
70           std::cout << "                      (default = select appropriate for geometry)\n";
71           std::cout << "     --geometry       Geometry of scanning\n";
72           std::cout << "        parallel      Parallel scan beams (default)\n";
73           std::cout << "        equilinear    Equilinear divergent scan beams\n";
74           std::cout << "        equiangular   Equiangular divergent scan beams\n";
75           std::cout << "     --focal-length   Focal length ratio (ratio to radius of phantom)\n";
76           std::cout << "                      (default = 1)\n";
77           std::cout << "     --view-ratio     Length to view (view diameter to phantom diameter)\n";
78           std::cout << "                      (default = 1)\n";
79           std::cout << "     --scan-ratio     Length to scan (scan diameter to view diameter)\n";
80           std::cout << "                      (default = 1)\n";
81           std::cout << "     --offsetview     Initial gantry offset in 'views' (default = 0)\n";
82           std::cout << "     --trace          Trace level to use\n";
83           std::cout << "        none          No tracing (default)\n";
84           std::cout << "        console       Trace text level\n";
85           std::cout << "     --verbose        Verbose mode\n";
86           std::cout << "     --debug          Debug mode\n";
87           std::cout << "     --version        Print version\n";
88           std::cout << "     --help           Print this help message\n";
89 }
90
91
92 int
93 phm2helix_main (int argc, char* const argv[])
94 {
95         Phantom phm;
96         std::string optGeometryName = Scanner::convertGeometryIDToName(Scanner::GEOMETRY_PARALLEL);
97         char *opt_outfile = NULL;
98         std::string opt_desc;
99         std::string opt_PhmProg;
100         std::string opt_PhmFileName = "tmpphmfile";
101         int opt_ndet;
102         int opt_nview;
103         int opt_offsetview = 0;
104         int opt_nray = 1;
105         double dOptFocalLength = 2.;
106         double dOptCenterDetectorLength = 2;
107         double dOptViewRatio = 1.;
108         double dOptScanRatio = 1.;
109         int opt_trace = Trace::TRACE_NONE;
110         int opt_verbose = 0;
111         int opt_debug = 0;
112         double opt_rotangle = -1;
113         char* endptr = NULL;
114         char* endstr;
115
116         Timer timerProgram;
117
118         while (1) {
119                 int c = getopt_long(argc, argv, "", phm2helix_options, NULL);
120
121                 if (c == -1)
122                 break;
123
124         switch (c) {
125         case O_VERBOSE:
126                 opt_verbose = 1;
127                 break;
128         case O_DEBUG:
129                 opt_debug = 1;
130                 break;
131         case O_TRACE:
132                 if ((opt_trace = Trace::convertTraceNameToID(optarg))
133                                                                 == Trace::TRACE_INVALID) {
134                         phm2helix_usage(argv[0]);
135                         return (1);
136                 }
137                 break;
138                           case O_PHMFILE:
139                                 opt_PhmFileName = optarg;
140                                 break;
141                           case O_DESC:
142                                 opt_desc = optarg;
143                                 break;
144                           case O_ROTANGLE:
145                                 opt_rotangle = strtod(optarg, &endptr);
146                                 endstr = optarg + strlen(optarg);
147                                 if (endptr != endstr) {
148                                         std::cerr << "Error setting --rotangle to " << optarg << std::endl;
149                                         phm2helix_usage(argv[0]);
150                                         return (1);
151                                 }
152                                 break;
153                           case O_GEOMETRY:
154                                 optGeometryName = optarg;
155                                 break;
156                           case O_FOCAL_LENGTH:
157                                 dOptFocalLength = strtod(optarg, &endptr);
158                                 endstr = optarg + strlen(optarg);
159                                 if (endptr != endstr) {
160                                         std::cerr << "Error setting --focal-length to " << optarg << std::endl;
161                                         phm2helix_usage(argv[0]);
162                                         return (1);
163                                 }
164                                 break;
165                           case  O_CENTER_DETECTOR_LENGTH:
166                                 dOptCenterDetectorLength = strtod(optarg, &endptr);
167                                 endstr = optarg + strlen(optarg);
168                                 if (endptr != endstr) {
169                                         std::cerr << "Error setting --center-detector-length to " << optarg << std::endl;
170                                         phm2helix_usage(argv[0]);
171                                         return (1);
172                                 }
173                           break;
174                           case O_VIEW_RATIO:
175                                 dOptViewRatio = strtod(optarg, &endptr);
176                                 endstr = optarg + strlen(optarg);
177                                 if (endptr != endstr) {
178                                         std::cerr << "Error setting --view-ratio to " << optarg << std::endl;
179                                         phm2helix_usage(argv[0]);
180                                         return (1);
181                                 }
182                                 break;
183                           case O_SCAN_RATIO:
184                                 dOptScanRatio = strtod(optarg, &endptr);
185                                 endstr = optarg + strlen(optarg);
186                                 if (endptr != endstr) {
187                                         std::cerr << "Error setting --scan-ratio to " << optarg << std::endl;
188                                         phm2helix_usage(argv[0]);
189                                         return (1);
190                                 }
191                                 break;
192                           case O_NRAY:
193                                 opt_nray = strtol(optarg, &endptr, 10);
194                                 endstr = optarg + strlen(optarg);
195                                 if (endptr != endstr) {
196                                   std::cerr << "Error setting --nray to %s" << optarg << std::endl;
197                                   phm2helix_usage(argv[0]);
198                                   return (1);
199                                 }
200                                 break;
201                           case O_OFFSETVIEW:
202                                 opt_offsetview = strtol(optarg, &endptr, 10);
203                                 endstr = optarg + strlen(optarg);
204                                 if (endptr != endstr) {
205                                   std::cerr << "Error setting --offsetview to %s" << optarg << std::endl;
206                                   phm2helix_usage(argv[0]);
207                                   return (1);
208                                 }
209                                 break;
210                           case O_VERSION:
211 #ifdef VERSION
212                                   std::cout << "Version: " << VERSION << std::endl << g_szIdStr << std::endl;
213 #else
214                                           std::cout << "Unknown version number\n";
215 #endif
216                                   return (0);
217                           case O_HELP:
218                           case '?':
219                                 phm2helix_usage(argv[0]);
220                                 return (0);
221                           default:
222                                 phm2helix_usage(argv[0]);
223                                 return (1);
224                         } // end of switch
225           } // end of while loop
226
227           if (optind + 4 != argc) {
228                 phm2helix_usage(argv[0]);
229                 return (1);
230           }
231
232           opt_outfile = argv[optind];
233           opt_ndet = strtol(argv[optind+1], &endptr, 10);
234           endstr = argv[optind+1] + strlen(argv[optind+1]);
235           if (endptr != endstr) {
236                 std::cerr << "Error setting --ndet to " << argv[optind+1] << std::endl;
237                 phm2helix_usage(argv[0]);
238                 return (1);
239           }
240           opt_nview = strtol(argv[optind+2], &endptr, 10);
241           endstr = argv[optind+2] + strlen(argv[optind+2]);
242           if (endptr != endstr) {
243                 std::cerr << "Error setting --nview to " << argv[optind+2] << std::endl;
244                 phm2helix_usage(argv[0]);
245                 return (1);
246           }
247           opt_PhmProg = argv[optind+3];
248
249           if (opt_rotangle < 0) {
250                 if (optGeometryName.compare ("parallel") == 0)
251                   opt_rotangle = 0.5;
252                 else
253                   opt_rotangle = 1.0;
254           }
255
256           std::ostringstream desc;
257           desc << "phm2helix: NDet=" << opt_ndet
258                    << ", Nview=" << opt_nview
259                    << ", NRay=" << opt_nray
260                    << ", RotAngle=" << opt_rotangle
261                    << ", OffsetView =" << opt_offsetview
262                    << ", Geometry=" << optGeometryName
263                    << ", PhantomProg=" << opt_PhmProg
264                    << ", PhmFileName=" << opt_PhmFileName;
265           if (opt_desc.length()) {
266                 desc << ": " << opt_desc;
267           }
268           opt_desc = desc.str();
269
270           opt_rotangle *= TWOPI;
271
272           int stat;
273           char extcommand[100];
274           if(opt_debug != 0)
275                         std::cout  <<  opt_PhmProg  <<  " " << 0 << " " <<  opt_nview << " " << opt_PhmFileName  << std::endl;
276            //extcommand <<  opt_PhmProg  <<  " " << 0 << " " <<  opt_nview << " " << opt_PhmFileName ;
277
278           sprintf(extcommand, "%s %d %d %s",    opt_PhmProg.c_str(), 0, opt_nview, opt_PhmFileName.c_str() );
279
280            stat = system( extcommand );
281           if (stat != 0 )
282                         std::cerr << "Error executing external phantom program " << opt_PhmProg << " with command " << extcommand << std::endl;
283
284           phm.createFromPhmFile (opt_PhmFileName.c_str());
285           remove(opt_PhmFileName.c_str());
286
287           Scanner scanner (phm, optGeometryName.c_str(), opt_ndet, opt_nview,
288                                 opt_offsetview, opt_nray, opt_rotangle, dOptFocalLength,
289                                 dOptCenterDetectorLength, dOptViewRatio, dOptScanRatio);
290           if (scanner.fail()) {
291                  std::cout << "Scanner Creation Error: " << scanner.failMessage()
292                                                         << std::endl;
293                  return (1);
294           }
295
296           Projections pjGlobal(scanner);
297
298
299           for( int iView = 0; iView < opt_nview; iView++ ){
300                 if(opt_debug != 0)
301                         std::cout  <<  opt_PhmProg  <<  " " << iView << " " <<  opt_nview << " " << opt_PhmFileName  << std::endl;
302            //extcommand <<  opt_PhmProg  <<  " " << iView << " " <<  opt_nview << " " << opt_PhmFileName ;
303
304                 sprintf(extcommand, "%s %d %d %s",      
305                         opt_PhmProg.c_str(), iView, opt_nview, 
306                         opt_PhmFileName.c_str() );
307                 stat = system( extcommand );
308
309                 if (stat != 0 )
310                         std::cerr << "Error executing external phantom program " << opt_PhmProg << " with command " << extcommand << std::endl;
311                 Phantom phmtmp;
312                 phmtmp.createFromPhmFile (opt_PhmFileName.c_str());
313
314                 scanner.collectProjections (pjGlobal, phmtmp, iView,
315                           1, scanner.offsetView(), true, opt_trace);
316                 remove(opt_PhmFileName.c_str());
317           }
318
319
320           pjGlobal.setCalcTime (timerProgram.timerEnd());
321           pjGlobal.setRemark (opt_desc);
322           pjGlobal.write (opt_outfile);
323           if (opt_verbose) {
324             phm.print (std::cout);
325             std::cout << std::endl;
326             std::ostringstream os;
327             pjGlobal.printScanInfo (os);
328             std::cout << os.str() << std::endl;
329             std::cout << "  Remark: " << pjGlobal.remark() << std::endl;
330             std::cout << "Run time: " << pjGlobal.calcTime() << " seconds\n";
331           }
332           
333           return (0);
334 }
335
336
337 #ifndef NO_MAIN
338 int
339 main (int argc, char* argv[])
340 {
341   int retval = 1;
342
343   try {
344     retval = phm2helix_main(argc, argv);
345 #if HAVE_DMALLOC
346     //    dmalloc_shutdown();
347 #endif
348   } catch (exception e) {
349     std::cerr << "Exception: " << e.what() << std::endl;
350   } catch (...) {
351     std::cerr << "Unknown exception\n";
352   }
353
354   return (retval);
355 }
356 #endif
357