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