Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding some C++ coding practice [closed]

Tags:

c++

debugging

gdb

I am currently trying to understand how the following code (http://pastebin.com/zTHUrmyx) works, my approach is currently compiling the software in debug and using gdb to step through the code.

However, I'm running into the problem that 'step' does not always tell me what is going on. Particularly unclear to me is the EXECUTE {...} which I cannot step into.

How do I go about learning what the code is doing?

   1     /*
   2     Copyright 2008 Brain Research Institute, Melbourne, Australia
   3
   4     Written by J-Donald Tournier, 27/06/08.
   5
   6     This file is part of MRtrix.
   7
   8     MRtrix is free software: you can redistribute it and/or modify
   9     it under the terms of the GNU General Public License as published by
  10     the Free Software Foundation, either version 3 of the License, or
  11     (at your option) any later version.
  12
  13     MRtrix is distributed in the hope that it will be useful,
  14     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16     GNU General Public License for more details.
  17
  18     You should have received a copy of the GNU General Public License
  19     along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.
  20
  21
  22     15-10-2008 J-Donald Tournier <[email protected]>
  23     * fix -prs option handling
  24     * remove MR::DICOM_DW_gradients_PRS flag
  25
  26     15-10-2008 J-Donald Tournier <[email protected]>
  27     * add -layout option to manipulate data ordering within the image file
  28
  29     14-02-2010 J-Donald Tournier <[email protected]>
  30     * fix -coord option so that the "end" keyword can be used
  31
  32
  33 */
  34
  35 #include "app.h"
  36 #include "image/position.h"
  37 #include "image/axis.h"
  38 #include "math/linalg.h"
  39
  40 using namespace std;
  41 using namespace MR;
  42
  43 SET_VERSION_DEFAULT;
  44
  45 DESCRIPTION = {
  46   "perform conversion between different file types and optionally extract a subset of the input image.",
  47   "If used correctly, this program can be a very useful workhorse. In addition to converting images between different formats, it can be used to extract specific studies from a data set, extract a specific region of interest, flip the images, or to scale the intensity of the images.",
  48   NULL
  49 };
  50
  51 ARGUMENTS = {
  52   Argument ("input", "input image", "the input image.").type_image_in (),
  53   Argument ("ouput", "output image", "the output image.").type_image_out (),
  54   Argument::End
  55 };
  56
  57
  58 const gchar* type_choices[] = { "REAL", "IMAG", "MAG", "PHASE", "COMPLEX", NULL };
  59 const gchar* data_type_choices[] = { "FLOAT32", "FLOAT32LE", "FLOAT32BE", "FLOAT64", "FLOAT64LE", "FLOAT64BE",
  60     "INT32", "UINT32", "INT32LE", "UINT32LE", "INT32BE", "UINT32BE",
  61     "INT16", "UINT16", "INT16LE", "UINT16LE", "INT16BE", "UINT16BE",
  62     "CFLOAT32", "CFLOAT32LE", "CFLOAT32BE", "CFLOAT64", "CFLOAT64LE", "CFLOAT64BE",
  63     "INT8", "UINT8", "BIT", NULL };
  64
  65 OPTIONS = {
  66   Option ("coord", "select coordinates", "extract data only at the coordinates specified.", false, true)
  67     .append (Argument ("axis", "axis", "the axis of interest").type_integer (0, INT_MAX, 0))
  68     .append (Argument ("coord", "coordinates", "the coordinates of interest").type_sequence_int()),
  69
  70   Option ("vox", "voxel size", "change the voxel dimensions.")
  71     .append (Argument ("sizes", "new dimensions", "A comma-separated list of values. Only those values specified will be changed. For example: 1,,3.5 will change the voxel size along the x & z axes, and leave the y-axis voxel size unchanged.")
  72         .type_sequence_float ()),
  73
  74   Option ("datatype", "data type", "specify output image data type.")
  75     .append (Argument ("spec", "specifier", "the data type specifier.").type_choice (data_type_choices)),
  76
  77   Option ("scale", "scaling factor", "apply scaling to the intensity values.")
  78     .append (Argument ("factor", "factor", "the factor by which to multiply the intensities.").type_float (NAN, NAN, 1.0)),
  79
  80   Option ("offset", "offset", "apply offset to the intensity values.")
  81     .append (Argument ("bias", "bias", "the value of the offset.").type_float (NAN, NAN, 0.0)),
  82
  83   Option ("zero", "replace NaN by zero", "replace all NaN values with zero."),
  84
  85   Option ("output", "output type", "specify type of output")
  86     .append (Argument ("type", "type", "type of output.")
  87         .type_choice (type_choices)),
  88
  89   Option ("layout", "data layout", "specify the layout of the data in memory. The actual layout produced will depend on whether the output image format can support it.")
  90     .append (Argument ("spec", "specifier", "the data layout specifier.").type_string ()),
  91
  92   Option ("prs", "DW gradient specified as PRS", "assume that the DW gradients are specified in the PRS frame (Siemens DICOM only)."),
  93
  94   Option::End
  95 };
  96
  97
  98
  99 inline bool next (Image::Position& ref, Image::Position& other, const std::vector<int>* pos)
 100 {
 101   int axis = 0;
 102   do {
 103     ref.inc (axis);
 104     if (ref[axis] < ref.dim(axis)) {
 105       other.set (axis, pos[axis][ref[axis]]);
 106       return (true);
 107     }
 108     ref.set (axis, 0);
 109     other.set (axis, pos[axis][0]);
 110     axis++;
 111   } while (axis < ref.ndim());
 112   return (false);
 113 }
 114
 115
 116
 117
 118
 119 EXECUTE {
 120   std::vector<OptBase> opt = get_options (1); // vox
 121   std::vector<float> vox;
 122   if (opt.size())
 123     vox = parse_floats (opt[0][0].get_string());
 124
 125
 126   opt = get_options (3); // scale
 127   float scale = 1.0;
 128   if (opt.size()) scale = opt[0][0].get_float();
 129
 130   opt = get_options (4); // offset
 131   float offset = 0.0;
 132   if (opt.size()) offset = opt[0][0].get_float();
 133
 134   opt = get_options (5); // zero
 135   bool replace_NaN = opt.size();
 136
 137   opt = get_options (6); // output
 138   Image::OutputType output_type = Image::Default;
 139   if (opt.size()) {
 140     switch (opt[0][0].get_int()) {
 141       case 0: output_type = Image::Real; break;
 142       case 1: output_type = Image::Imaginary; break;
 143       case 2: output_type = Image::Magnitude; break;
 144       case 3: output_type = Image::Phase; break;
 145       case 4: output_type = Image::RealImag; break;
 146     }
 147   }
 148
 149
 150
 151
 152   Image::Object &in_obj (*argument[0].get_image());
 153
 154   Image::Header header (in_obj);
 155
 156   if (output_type == 0) {
 157     if (in_obj.is_complex()) output_type = Image::RealImag;
 158     else output_type = Image::Default;
 159   }
 160
 161   if (output_type == Image::RealImag) header.data_type = DataType::CFloat32;
 162   else if (output_type == Image::Phase) header.data_type = DataType::Float32;
 163   else header.data_type.unset_flag (DataType::ComplexNumber);
 164
 165  
 166   opt = get_options (2); // datatype
 167   if (opt.size()) header.data_type.parse (data_type_choices[opt[0][0].get_int()]);
 168
 169   for (guint n = 0; n < vox.size(); n++)
 170     if (isfinite (vox[n])) header.axes.vox[n] = vox[n];
 171
 172   opt = get_options (7); // layout
 173   if (opt.size()) {
 174     std::vector<Image::Axis> ax = parse_axes_specifier (header.axes, opt[0][0].get_string());
 175     if (ax.size() != (guint) header.axes.ndim())
 176       throw Exception (String("specified layout \"") + opt[0][0].get_string() + "\" does not match image dimensions");
 177
 178     for (guint i = 0; i < ax.size(); i++) {
 179       header.axes.axis[i] = ax[i].axis;
 180       header.axes.forward[i] = ax[i].forward;
 181     }
 182   }
 183
 184
 185   opt = get_options (8); // prs
 186   if (opt.size() && header.DW_scheme.rows() && header.DW_scheme.columns()) {
 187     for (guint row = 0; row < header.DW_scheme.rows(); row++) {
 188       double tmp = header.DW_scheme(row, 0);
 189       header.DW_scheme(row, 0) = header.DW_scheme(row, 1);
 190       header.DW_scheme(row, 1) = tmp;
 191       header.DW_scheme(row, 2) = -header.DW_scheme(row, 2);
 192     }
 193   }
 194
 195   std::vector<int> pos[in_obj.ndim()];
 196
 197   opt = get_options (0); // coord
 198   for (guint n = 0; n < opt.size(); n++) {
 199     int axis = opt[n][0].get_int();
 200     if (pos[axis].size()) throw Exception ("\"coord\" option specified twice for axis " + str (axis));
 201     pos[axis] = parse_ints (opt[n][1].get_string(), header.dim(axis)-1);
 202     header.axes.dim[axis] = pos[axis].size();
 203   }
 204
 205   for (int n = 0; n < in_obj.ndim(); n++) {
 206     if (pos[n].empty()) {
 207       pos[n].resize (in_obj.dim(n));
 208       for (guint i = 0; i < pos[n].size(); i++) pos[n][i] = i;
 209     }
 210   }
 211
 212
 213   in_obj.apply_scaling (scale, offset);
 214
 215
 216
 217
 218
 219
 220   Image::Position in (in_obj);
 221   Image::Position out (*argument[1].get_image (header));
 222
 223   for (int n = 0; n < in.ndim(); n++) in.set (n, pos[n][0]);
 224
 225   ProgressBar::init (out.voxel_count(), "copying data...");
 226
 227   do {
 228
 229     float re, im = 0.0;
 230     in.get (output_type, re, im);
 231     if (replace_NaN) if (gsl_isnan (re)) re = 0.0;
 232     out.re (re);
 233
 234     if (output_type == Image::RealImag) {
 235       if (replace_NaN) if (gsl_isnan (im)) im = 0.0;
 236       out.im (im);
 237     }
 238
 239     ProgressBar::inc();
 240   } while (next (out, in, pos));
 241
 242   ProgressBar::done();
 243 }
like image 917
Jesse RJ Avatar asked Apr 18 '13 06:04

Jesse RJ


1 Answers

As was noted in the comments, EXECUTE seems to be a macro, apparent from the context a function header (and maybe a bit more, e.g. some global variables and functions), so the part in curly braces is the function body.

To get to the definition of EXECUTE, you will have to examine the headers.

However, if you can reach some part of the code during debugging, you could insert a string or char[] at that point, giving it the stringified version of EXECUTE, so you get whatever the preprocessor will emit for EXECUTE at that position in the code.

#define STR(x) #x
#define STRINGIFY(x) STR(x)
char c[] = STRINGIFY(EXECUTE);

the two macros are a known little macro trick to get the content of any macro as a string literal. Try it out and inspect the char array in your debugger to get the content of execute.

My wild guess here: EXECUTE is the main function or a replacement for it, the OPTIONS and ARGUMENTS describe what arguments the program expects and what command line options you can pass to it. Those macros and some of the used functions and variables (get_options, argument) are part of a little framework that should facilitate the usage, evaluation and user information about command line options.

like image 161
Arne Mertz Avatar answered Oct 15 '22 00:10

Arne Mertz