Commit d2e2f9f3f9dd94e27588dce087cf94c4bac70a71

Authored by David Mayerich
1 parent cdf09f30

updated command-line arguments

Showing 1 changed file with 547 additions and 0 deletions   Show diff stats
arguments.h 0 → 100644
  1 +#include "rts/tools/arguments.h"
  2 +
  3 +#include "rts/optics/material.h"
  4 +
  5 +#include "nearfield.h"
  6 +#include "microscope.h"
  7 +#include "rts/visualization/colormap.h"
  8 +#include "fileout.h"
  9 +extern microscopeStruct* SCOPE;
  10 +extern fileoutStruct gFileOut;
  11 +
  12 +//default values
  13 +#include "defaults.h"
  14 +
  15 +#include <string>
  16 +#include <sstream>
  17 +#include <fstream>
  18 +#include <limits>
  19 +
  20 +extern bool verbose;
  21 +extern bool gui;
  22 +
  23 +#ifdef _WIN32
  24 + extern bool ansi;
  25 +#endif
  26 +
  27 +void SetArguments(rts::arglist &args)
  28 +{
  29 + args.section("Interface Flags");
  30 + args.add("help", "prints this help");
  31 + args.add("gui", "run using the Qt GUI");
  32 + args.add("verbose", "verbose output");
  33 +
  34 +#ifdef _WIN32
  35 + args.add("ansi", "activates ANSI in Windows");
  36 +#endif
  37 +
  38 + args.section("Output Parameters");
  39 + args.add("vector", "run a vector field simulation");
  40 + args.add("intensity", "output measured intensity (filename)", DEFAULT_INTENSITY_FILE);
  41 + args.add("absorbance", "output measured absorbance (filename)", DEFAULT_ABSORBANCE_FILE);
  42 + args.add("transmittance", "output measured transmittance (filename)", DEFAULT_TRANSMITTANCE_FILE);
  43 + args.add("far-field", "output far-field at detector (filename)", DEFAULT_FAR_FILE);
  44 + args.add("near-field", "output field at focal plane (filename)", DEFAULT_NEAR_FILE);
  45 + args.add("extended-source", "image of source at focus (filename)", DEFAULT_EXTENDED_SOURCE);
  46 + args.add("output-type", "output field value", DEFAULT_FIELD_TYPE, "magnitude, polarization, real, imaginary");
  47 + args.add("colormap", "colormap", DEFAULT_COLORMAP, "gray, brewer");
  48 + args.add("append", "append result to an existing (binary) file");
  49 +
  50 + args.section("Sphere Parameters");
  51 + args.add("spheres", "sphere position", "", "--spheres x y z a m");
  52 + args.add("sphere-file", "sphere file:", "", "[x y z radius material]");
  53 + args.add("materials", "refractive indices as n, k pairs", DEFAULT_MATERIAL, "--materials n0 k0 n1 k1 n2 k2");
  54 + args.add("material-file", "material file", "", "[lambda n k]");
  55 +
  56 + args.section("Optics");
  57 + args.add("lambda", "incident wavelength (micrometers)", DEFAULT_LAMBDA);
  58 + args.add("nu", "incident frequency (in cm^-1)\n(if specified, lambda is ignored)");
  59 + args.add("k", "k-vector direction in spherical coordinates", "", "--k theta phi; theta = [0 2*pi], phi = [0 pi]");
  60 + args.add("amplitude", "incident field amplitude", DEFAULT_AMPLITUDE);
  61 + args.add("condenser", "condenser numerical aperature\nA pair of values specify an inner obscuration", DEFAULT_CONDENSER);
  62 + args.add("objective", "objective numerical aperature\nA pair of values specify an inner obscuration", DEFAULT_OBJECTIVE);
  63 + args.add("focus", "focal position for the incident point source", DEFAULT_FOCUS);
  64 + args.add("plane-wave", "simulates an incident plane wave");
  65 +
  66 + args.section("Imaging Parameters");
  67 + args.add("resolution", "resolution of the detector", DEFAULT_SLICE_RES);
  68 + args.add("plane-lower-left", "lower-left position of the image plane", DEFAULT_PLANE_MIN);
  69 + args.add("plane-upper-right", "upper-right position of the image plane", DEFAULT_PLANE_MAX);
  70 + args.add("plane-normal", "normal for the image plane", DEFAULT_PLANE_NORM);
  71 + args.add("xy", "specify an x-y axis-aligned image (standard microscope)");
  72 + args.add("xz", "specify a x-z axis-aligned image");
  73 + args.add("yz", "specify a y-z axis-aligned image");
  74 +
  75 + args.section("Sampling Parameters");
  76 + args.add("samples", "Monte-Carlo samples used to compute Us", DEFAULT_SAMPLES);
  77 + args.add("padding", "FFT padding for the objective bandpass", DEFAULT_PADDING);
  78 + args.add("supersample", "super-sampling rate for the detector field", DEFAULT_SUPERSAMPLE);
  79 + args.add("field-order", "order of the incident field", DEFAULT_FIELD_ORDER);
  80 + args.add("seed", "seed for the Monte-Carlo random number generator");
  81 + args.add("recursive", "evaluate all Bessel functions recursively");
  82 + args.add("recursive-us", "evaluate scattered-field Bessel functions recursively");
  83 + args.add("lut-uf", "evaluate the focused-field using a look-up table");
  84 +
  85 +}
  86 +
  87 +void lFlags(rts::arglist args)
  88 +{
  89 +
  90 + //flag for verbose output
  91 + if(args("verbose"))
  92 + verbose = true;
  93 +
  94 + if(args("recursive"))
  95 + {
  96 + SCOPE->nf.lut_us = false;
  97 + SCOPE->nf.lut_uf = false;
  98 + }
  99 + else if(args("recursive-us"))
  100 + {
  101 + SCOPE->nf.lut_us = false;
  102 + }
  103 + else if(args("lut-uf"))
  104 + {
  105 + SCOPE->nf.lut_uf = true;
  106 + }
  107 +
  108 + //gui
  109 + if(args("gui"))
  110 + gui = true;
  111 +
  112 + //ANSI output for color text
  113 +#ifdef _WIN32
  114 + if(args("ansi"))
  115 + ansi = true;
  116 +#endif
  117 +
  118 +}
  119 +
  120 +void lWavelength(rts::arglist args)
  121 +{
  122 + //load the wavelength
  123 + if(args("nu"))
  124 + {
  125 + //wavelength is given in wavenumber - transform and flag
  126 + SCOPE->nf.lambda = 10000/args["nu"].as_float();
  127 + gFileOut.wavenumber = true;
  128 + }
  129 + //otherwise we are using lambda = wavelength
  130 + else
  131 + {
  132 + SCOPE->nf.lambda = args["lambda"].as_float();
  133 + gFileOut.wavenumber = false;
  134 + }
  135 +}
  136 +
  137 +static void lMaterials(rts::arglist args)
  138 +{
  139 + //if materials are specified at the command line
  140 + if(args("materials"))
  141 + {
  142 + rts::argument mats = args["materials"];
  143 + int nMats = mats.nargs();
  144 +
  145 + if(nMats == 1)
  146 + {
  147 + rts::material<ptype> newM(SCOPE->nf.lambda, mats.as_float(), 0);
  148 + SCOPE->nf.mVector.push_back(newM);
  149 + }
  150 + else if(nMats %2 != 0)
  151 + {
  152 + cout<<"BIMSim Error: materials must be specified in n, k pairs"<<endl;
  153 + exit(1);
  154 + }
  155 + else
  156 + {
  157 + for(unsigned int i=0; i<nMats; i+=2)
  158 + {
  159 + rts::material<ptype> newM(SCOPE->nf.lambda, mats.as_float(i), mats.as_float(i+1));
  160 + SCOPE->nf.mVector.push_back(newM);
  161 + }
  162 + }
  163 + }
  164 +
  165 + //if file names are specified, load the materials
  166 + if(args("material-file"))
  167 + {
  168 + rts::argument matfiles = args["material-file"];
  169 + int nMats = matfiles.nargs();
  170 +
  171 + for(unsigned int i=0; i<nMats; i++)
  172 + {
  173 + //load the file into a string
  174 + //std::ifstream ifs(filenames[i].c_str());
  175 +
  176 + //std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
  177 +
  178 + //load the list of spheres from a string
  179 + rts::material<ptype> newM(matfiles.as_text(i));
  180 + //newM.fromStr(instr, "");
  181 + SCOPE->nf.mVector.push_back(newM);
  182 + }
  183 + }
  184 +
  185 +}
  186 +
  187 +static void lSpheres(string sphereList)
  188 +{
  189 + /*This function loads a list of spheres given in the string sphereList
  190 + The format is:
  191 + x y z a m
  192 + where
  193 + x, y, z = sphere position (required)
  194 + a = sphere radius (required)
  195 + m = material ID (optional) */
  196 +
  197 + std::stringstream ss(sphereList);
  198 +
  199 + while(!ss.eof())
  200 + {
  201 + //create a new sphere
  202 + sphere newS;
  203 +
  204 + //get the sphere data
  205 + ss>>newS.p[0];
  206 + ss>>newS.p[1];
  207 + ss>>newS.p[2];
  208 + ss>>newS.a;
  209 +
  210 + if(ss.peek() != '\n')
  211 + ss>>newS.iMaterial;
  212 +
  213 + //add the new sphere to the sphere vector
  214 + SCOPE->nf.sVector.push_back(newS);
  215 +
  216 + //ignore the rest of the line
  217 + ss.ignore(1000, '\n');
  218 +
  219 + //check out the next element (this should set the EOF error flag)
  220 + ss.peek();
  221 + }
  222 +}
  223 +
  224 +void lSpheres(rts::arglist args)
  225 +{
  226 + //if a sphere is specified at the command line
  227 + if(args("spheres"))
  228 + {
  229 + rts::argument sphere_arg = args["spheres"];
  230 + int nArgs = sphere_arg.nargs();
  231 +
  232 + //compute the number of spheres specified
  233 + unsigned int nS;
  234 + if(nArgs <= 5)
  235 + nS = 1;
  236 + else
  237 + {
  238 + //if the number of parameters is divisible by 4, compute the number of spheres
  239 + if(nArgs % 5 == 0)
  240 + nS = nArgs / 5;
  241 + else
  242 + {
  243 + cout<<"BIMSIM Error: Invalid number of sphere parameters."<<endl;
  244 + exit(1);
  245 + }
  246 + }
  247 +
  248 + stringstream ss;
  249 +
  250 + //for each sphere
  251 + for(unsigned int s=0; s<nS; s++)
  252 + {
  253 + //compute the number of sphere parameters
  254 + unsigned int nP;
  255 + if(nS == 1) nP = nArgs;
  256 + else nP = 5;
  257 +
  258 + //store each parameter as a string
  259 + for(unsigned int i=0; i<nP; i++)
  260 + {
  261 + ss<<sphere_arg.as_float(s*5 + i)<<" ";
  262 + }
  263 + ss<<endl;
  264 + }
  265 +
  266 +
  267 +
  268 + //convert the string to a sphere list
  269 + lSpheres(ss.str());
  270 + }
  271 +
  272 + //if a files are specified
  273 + if(args("sphere-file"))
  274 + {
  275 + rts::argument sfiles = args["sphere-file"];
  276 + int nFiles = sfiles.nargs();
  277 +
  278 + //load each file
  279 + for(unsigned int iS=0; iS<nFiles; iS++)
  280 + {
  281 + //load the file into a string
  282 + std::ifstream ifs(sfiles.as_text(iS).c_str());
  283 +
  284 + if(!ifs)
  285 + {
  286 + cout<<"Error loading sphere file."<<endl;
  287 + exit(1);
  288 + }
  289 +
  290 + std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
  291 +
  292 + //load the list of spheres from a string
  293 + lSpheres(instr);
  294 + }
  295 + }
  296 +
  297 + //make sure the appropriate materials are loaded
  298 + unsigned int nS = SCOPE->nf.sVector.size();
  299 +
  300 + //for each sphere
  301 + for(unsigned int s = 0; s<nS; s++)
  302 + {
  303 + //make sure the corresponding material exists
  304 + if(SCOPE->nf.sVector[s].iMaterial + 1 > SCOPE->nf.mVector.size())
  305 + {
  306 + //otherwise output an error
  307 + cout<<"BIMSIM Error - A material is not loaded for sphere "<<s+1<<"."<<endl;
  308 + cout<<"Material requested: "<<SCOPE->nf.sVector[s].iMaterial + 1<<endl;
  309 + cout<<"Number of materials: "<<SCOPE->nf.mVector.size()<<endl;
  310 + exit(1);
  311 + }
  312 + }
  313 +}
  314 +
  315 +static void lOptics(rts::arglist &args)
  316 +{
  317 + if(args("objective"))
  318 + {
  319 +
  320 + if(args["objective"].nargs() == 1)
  321 + {
  322 + SCOPE->objective[0] = 0.0;
  323 + SCOPE->objective[1] = args["objective"].as_float();
  324 + }
  325 + else
  326 + {
  327 + SCOPE->objective[0] = args["objective"].as_float(0);
  328 + SCOPE->objective[1] = args["objective"].as_float(1);
  329 + }
  330 + }
  331 +}
  332 +
  333 +static void lImagePlane(rts::arglist args)
  334 +{
  335 + bsPoint pMin(DEFAULT_PLANE_MIN_X, DEFAULT_PLANE_MIN_Y, DEFAULT_PLANE_MIN_Z);
  336 + bsPoint pMax(DEFAULT_PLANE_MAX_X, DEFAULT_PLANE_MAX_Y, DEFAULT_PLANE_MAX_Z);
  337 + bsVector normal(DEFAULT_PLANE_NORM_X, DEFAULT_PLANE_NORM_Y, DEFAULT_PLANE_NORM_Z);
  338 +
  339 + //set the default values for the slice position and orientation
  340 + if(args("plane-lower-left") && args("plane-upper-right") && args("plane-normal"))
  341 + {
  342 +
  343 +
  344 + pMin = bsPoint(args["plane-lower-left"].as_float(0), args["plane-lower-left"].as_float(1), args["plane-lower-left"].as_float(2));
  345 + pMax = bsPoint(args["plane-upper-right"].as_float(0), args["plane-upper-right"].as_float(1), args["plane-upper-right"].as_float(2));
  346 + normal = bsVector(args["plane-normal"].as_float(0), args["plane-normal"].as_float(1), args["plane-normal"].as_float(2));
  347 + }
  348 + else if(args("xy"))
  349 + {
  350 + //default plane size in microns
  351 + ptype s = DEFAULT_PLANE_SIZE;
  352 + ptype pos = DEFAULT_PLANE_POSITION;
  353 +
  354 +
  355 + if(args["xy"].nargs() >= 1)
  356 + s = args["xy"].as_float(0);
  357 + if(args["xy"].nargs() == 2)
  358 + pos = args["xy"].as_float(1);
  359 +
  360 + //calculate the plane corners and normal based on the size and position
  361 + pMin = bsPoint(-s/2, -s/2, pos);
  362 + pMax = bsPoint(s/2, s/2, pos);
  363 + normal = bsVector(0, 0, 1);
  364 + }
  365 + else if(args("xz"))
  366 + {
  367 + //default plane size in microns
  368 + ptype size = DEFAULT_PLANE_SIZE;
  369 + ptype pos = DEFAULT_PLANE_POSITION;
  370 +
  371 + if(args["xz"].nargs() >= 1)
  372 + size = args["xz"].as_float(0);
  373 + if(args["xz"].nargs() >= 2)
  374 + pos = args["xz"].as_float(1);
  375 +
  376 + //calculate the plane corners and normal based on the size and position
  377 + pMin = bsPoint(-size/2, pos, -size/2);
  378 + pMax = bsPoint(size/2, pos, size/2);
  379 + normal = bsVector(0, -1, 0);
  380 + }
  381 + else if(args("yz"))
  382 + {
  383 + //default plane size in microns
  384 + ptype size = DEFAULT_PLANE_SIZE;
  385 + ptype pos = DEFAULT_PLANE_POSITION;
  386 +
  387 + if(args["yz"].nargs() >= 1)
  388 + size = args["yz"].as_float(0);
  389 + if(args["yz"].nargs() >= 2)
  390 + pos = args["yz"].as_float(1);
  391 +
  392 + //calculate the plane corners and normal based on the size and position
  393 + pMin = bsPoint(pos, -size/2, -size/2);
  394 + pMax = bsPoint(pos, size/2, size/2);
  395 + normal = bsVector(1, 0, 0);
  396 + }
  397 + SCOPE->setPos(pMin, pMax, normal);
  398 +
  399 + //resolution
  400 + SCOPE->setRes(args["resolution"].as_float(),
  401 + args["resolution"].as_float(),
  402 + args["padding"].as_float(),
  403 + args["supersample"].as_float());
  404 +
  405 +
  406 +
  407 +
  408 +
  409 + SCOPE->setNearfield();
  410 +}
  411 +
  412 +static void lNearfield(rts::arglist args)
  413 +{
  414 + //test to see if we are running a vector field simulation
  415 + bool vectorField = false;
  416 + if(args("vector"))
  417 + vectorField = true;
  418 + SCOPE->scalarSim = !vectorField;
  419 +
  420 + //test to see if we are simulating a plane wave
  421 + bool planeWave = DEFAULT_PLANEWAVE;
  422 + if(args("plane-wave"))
  423 + planeWave = !planeWave;
  424 + SCOPE->nf.planeWave = planeWave;
  425 +
  426 + //get the incident field amplitude
  427 + SCOPE->nf.A = args["amplitude"].as_float();
  428 +
  429 + //get the condenser parameters
  430 +
  431 + if(args["condenser"].nargs() == 1)
  432 + {
  433 + SCOPE->nf.condenser[0] = 0;
  434 + SCOPE->nf.condenser[1] = args["condenser"].as_float(0);
  435 + }
  436 + else
  437 + {
  438 + SCOPE->nf.condenser[0] = args["condenser"].as_float(0);
  439 + SCOPE->nf.condenser[1] = args["condenser"].as_float(1);
  440 + }
  441 +
  442 +
  443 +
  444 + //get the focal rtsPoint position
  445 + SCOPE->nf.focus[0] = args["focus"].as_float(0);
  446 + SCOPE->nf.focus[1] = args["focus"].as_float(1);
  447 + SCOPE->nf.focus[2] = args["focus"].as_float(2);
  448 +
  449 + //get the incident light direction (k-vector)
  450 + bsVector spherical(1, 0, 0);
  451 +
  452 + //if a k-vector is specified
  453 + if(args("k"))
  454 + {
  455 +
  456 + spherical[1] = args["k"].as_float(0);
  457 + spherical[2] = args["k"].as_float(1);
  458 + }
  459 + SCOPE->nf.k = spherical.sph2cart();
  460 +
  461 +
  462 + //incident field order
  463 + SCOPE->nf.m = args["field-order"].as_int();
  464 +
  465 + //number of Monte-Carlo samples
  466 + SCOPE->nf.nWaves = args["samples"].as_int();
  467 +
  468 + //random number seed for Monte-Carlo samples
  469 + if(args("seed"))
  470 + srand(args["seed"].as_int());
  471 +}
  472 +
  473 +static void lOutputParams(rts::arglist args)
  474 +{
  475 + //append simulation results to previous binary files
  476 + gFileOut.append = DEFAULT_APPEND;
  477 + if(args("append"))
  478 + gFileOut.append = true;
  479 +
  480 + //image parameters
  481 + //component of the field to be saved
  482 + std::string fieldStr;
  483 + fieldStr = args["output-type"].as_text();
  484 +
  485 + if(fieldStr == "magnitude")
  486 + gFileOut.field = fileoutStruct::fieldMag;
  487 + else if(fieldStr == "intensity")
  488 + gFileOut.field = fileoutStruct::fieldIntensity;
  489 + else if(fieldStr == "polarization")
  490 + gFileOut.field = fileoutStruct::fieldPolar;
  491 + else if(fieldStr == "imaginary")
  492 + gFileOut.field = fileoutStruct::fieldImag;
  493 + else if(fieldStr == "real")
  494 + gFileOut.field = fileoutStruct::fieldReal;
  495 + else if(fieldStr == "angular-spectrum")
  496 + gFileOut.field = fileoutStruct::fieldAngularSpectrum;
  497 +
  498 +
  499 + //image file names
  500 + gFileOut.intFile = args["intensity"].as_text();
  501 + gFileOut.absFile = args["absorbance"].as_text();
  502 +
  503 + if(args("transmittance"))
  504 + gFileOut.transFile = args["transmittance"].as_text();
  505 + gFileOut.nearFile = args["near-field"].as_text();
  506 + gFileOut.farFile = args["far-field"].as_text();
  507 +
  508 + //colormap
  509 + std::string cmapStr;
  510 + cmapStr = args["colormap"].as_text();
  511 + if(cmapStr == "brewer")
  512 + gFileOut.colormap = rts::cmBrewer;
  513 + else if(cmapStr == "gray")
  514 + gFileOut.colormap = rts::cmGrayscale;
  515 + else
  516 + cout<<"color-map value not recognized (using default): "<<cmapStr<<endl;
  517 +}
  518 +
  519 +void LoadParameters(rts::arglist &args)
  520 +{
  521 + lFlags(args);
  522 + lWavelength(args);
  523 + lMaterials(args);
  524 + lSpheres(args);
  525 + lOptics(args);
  526 + lImagePlane(args);
  527 + lNearfield(args);
  528 + lOutputParams(args);
  529 +
  530 + //if an extended source will be used
  531 + if(args("extended-source"))
  532 + {
  533 + //load the point sources
  534 + string filename = args["extended-source"].as_text();
  535 + SCOPE->LoadExtendedSource(filename);
  536 +
  537 + }
  538 +
  539 +}
  540 +
  541 +static void OutputOptions()
  542 +{
  543 + cout<<SCOPE->toStr();
  544 +
  545 + cout<<"# of source points: "<<SCOPE->focalPoints.size()<<endl;
  546 +
  547 +}
... ...