options.h 12.8 KB
//AnyOption for command-line processing
//#include "anyoption.h"

#include "rts/material.h"

#include "nearfield.h"
#include "microscope.h"
#include "colormap.h"
#include "fileout.h"
//extern nearfieldStruct* NF;
extern microscopeStruct* SCOPE;
extern fileoutStruct gFileOut;

//default values
#include "defaults.h"

#include <string>
#include <sstream>
#include <fstream>
#include <limits>
using namespace std;

#include <boost/program_options.hpp>
namespace po = boost::program_options;

static void loadSpheres(string sphereList)
{
    /*This function loads a list of sphere given in the string sphereList
        The format is:
            x y z a m
        where
            x, y, z = sphere position (required)
            a = sphere radius (required)
            m = material ID (optional) */

    std::stringstream ss(sphereList);

    while(!ss.eof())
    {
        //create a new sphere
        sphere newS;

        //get the sphere data
        ss>>newS.p[0];
        ss>>newS.p[1];
        ss>>newS.p[2];
        ss>>newS.a;

        if(ss.peek() != '\n')
            ss>>newS.iMaterial;

        //add the new sphere to the sphere vector
        SCOPE->nf.sVector.push_back(newS);

        //ignore the rest of the line
        ss.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

        //check out the next element (this should set the EOF error flag)
        ss.peek();
    }



}

static void loadSpheres(po::variables_map vm)
{
    //if a files are specified
    if(vm.count("sphere-file"))
    {
        cout<<"Sphere files detected."<<endl;
        vector<string> filenames = vm["sphere-file"].as< vector<string> >();
        //load each file
        for(int iS=0; iS<filenames.size(); iS++)
        {
            //load the file into a string
            std::ifstream ifs(filenames[iS].c_str());

            if(!ifs)
            {
                cout<<"Error loading sphere file."<<endl;
                exit(1);
            }

            std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

            //load the list of spheres from a string
            loadSpheres(instr);
        }
    }

    //load the sphere from the command line
    if(vm.count("sx") || vm.count("sy") || vm.count("sz") || vm.count("s"))
    {
        //create a new sphere
        sphere newS;

		//set defaults
		if(vm.count("sx"))
            newS.p[0] = vm["sx"].as<ptype>();
        else
            newS.p[0] = DEFAULT_SPHERE_X;


		if(vm.count("sy"))
            newS.p[1] = vm["sy"].as<ptype>();
        else
            newS.p[1] = DEFAULT_SPHERE_Y;

		if(vm.count("sz"))
            newS.p[2] = vm["sz"].as<ptype>();
        else
            newS.p[2] = DEFAULT_SPHERE_Z;

		if(vm.count("radius"))
            newS.a = vm["radius"].as<ptype>();
        else
            newS.a = DEFAULT_SPHERE_A;

        //add the sphere to the sphere vector
        SCOPE->nf.sVector.push_back(newS);

    }
}

static void loadMaterials(po::variables_map vm)
{
	//if materials are specified at the command line
	if(vm.count("materials"))
	{
		vector<ptype> matVec = vm["materials"].as< vector<ptype> >();
		if(matVec.size() %2 != 0)
		{
			cout<<"BIMSim Error: materials must be specified in n, k pairs"<<endl;
			exit(1);
		}

		
		for(int i=0; i<matVec.size(); i+=2)
		{
			rts::material<ptype> newM(vm["lambda"].as<ptype>(), matVec[i], matVec[i+1]);
			SCOPE->nf.mVector.push_back(newM);
		}
	}
	else
	{
		//add the command line material as the default (material 0)
		rts::material<ptype> newM(vm["lambda"].as<ptype>(), vm["n"].as<ptype>(), vm["k"].as<ptype>());
		SCOPE->nf.mVector.push_back(newM);
	}

	//if file names are specified, load the materials
	if(vm.count("material-file"))
	{
        vector<string> filenames = vm["material-file"].as< vector<string> >();
        for(int i=0; i<filenames.size(); i++)
        {
            //load the file into a string
            std::ifstream ifs(filenames[i].c_str());

            std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

            //load the list of spheres from a string
            rts::material<ptype> newM;
            newM.fromStr(instr, "");
            SCOPE->nf.mVector.push_back(newM);
        }
	}

}

static void loadNearfieldParams(po::variables_map vm)
{
	//test to see if we are simulating a plane wave
	bool planeWave = DEFAULT_PLANEWAVE;
	if(vm.count("plane-wave"))
		planeWave = !planeWave;
	SCOPE->nf.planeWave = planeWave;

	//get the wavelength
    SCOPE->nf.lambda = vm["lambda"].as<ptype>();

	//get the incident field amplitude
	SCOPE->nf.A = vm["amplitude"].as<ptype>();

	//get the condenser parameters
    SCOPE->nf.condenser[0] = vm["condenser-min"].as<ptype>();
    SCOPE->nf.condenser[1] = vm["condenser-max"].as<ptype>();


	//get the focal rtsPoint position
    SCOPE->nf.focus[0] = vm["fx"].as<ptype>();
    SCOPE->nf.focus[1] = vm["fy"].as<ptype>();
    SCOPE->nf.focus[2] = vm["fz"].as<ptype>();

	//get the incident light direction (k-vector)
	bsVector spherical;
	spherical[0] = 1.0;
    spherical[1] = vm["theta"].as<ptype>();
    spherical[2] = vm["phi"].as<ptype>();
	SCOPE->nf.k = spherical.sph2cart();


    //incident field order
    SCOPE->nf.m = vm["field-order"].as<int>();

    //number of Monte-Carlo samples
    SCOPE->nf.nWaves = vm["samples"].as<int>();



}

static void loadSliceParams(po::variables_map vm)
{
    //parameters for the sample plane


	//set the default values for the slice position and orientation
	bsPoint pMin(vm["plane-min-x"].as<ptype>(), vm["plane-min-y"].as<ptype>(), vm["plane-min-z"].as<ptype>());
	bsPoint pMax(vm["plane-max-x"].as<ptype>(), vm["plane-max-y"].as<ptype>(), vm["plane-max-z"].as<ptype>());
	bsVector normal(vm["plane-norm-x"].as<ptype>(), vm["plane-norm-y"].as<ptype>(), vm["plane-norm-z"].as<ptype>());
	SCOPE->setPos(pMin, pMax, normal);

	//resolution
	SCOPE->setRes(vm["resolution"].as<unsigned int>(),
				  vm["resolution"].as<unsigned int>(),
				  vm["padding"].as<unsigned int>(),
				  vm["supersample"].as<unsigned int>());





	SCOPE->setNearfield();



}

static void loadMicroscopeParams(po::variables_map vm)
{
    //objective
    SCOPE->objective[0] = vm["objective-min"].as<ptype>();
    SCOPE->objective[1] = vm["objective-max"].as<ptype>();





}

static void loadOutputParams(po::variables_map vm)
{

	//image parameters
	//component of the field to be saved
	std::string fieldStr;
    fieldStr = vm["output-type"].as<string>();

    if(fieldStr == "magnitude")
        gFileOut.field = fileoutStruct::fieldMag;
    else if(fieldStr == "intensity")
        gFileOut.field = fileoutStruct::fieldIntensity;
    else if(fieldStr == "polarization")
        gFileOut.field = fileoutStruct::fieldPolar;
    else if(fieldStr == "imaginary")
        gFileOut.field = fileoutStruct::fieldImag;
    else if(fieldStr == "real")
        gFileOut.field = fileoutStruct::fieldReal;
    else if(fieldStr == "angular-spectrum")
        gFileOut.field = fileoutStruct::fieldAngularSpectrum;


	//image file names
	gFileOut.intFile = vm["intensity"].as<string>();
	gFileOut.absFile = vm["absorbance"].as<string>();
	gFileOut.transFile = vm["transmittance"].as<string>();
	gFileOut.nearFile = vm["near-field"].as<string>();
	gFileOut.farFile = vm["far-field"].as<string>();

	//colormap
	std::string cmapStr;
    cmapStr = vm["colormap"].as<string>();
    if(cmapStr == "brewer")
        gFileOut.colormap = rts::colormap::cmBrewer;
    else if(cmapStr == "gray")
        gFileOut.colormap = rts::colormap::cmGrayscale;
    else
        cout<<"color-map value not recognized (using default): "<<cmapStr<<endl;
}

static void OutputOptions()
{
	cout<<SCOPE->nf.toStr();

}

static void SetOptions(po::options_description &desc)
{
	desc.add_options()
		("help,h", "prints this help")
		("plane-wave,P", "simulates an incident plane wave")
		("intensity,I", po::value<string>()->default_value(DEFAULT_INTENSITY_FILE), "output measured intensity (filename)")
		("absorbance,A", po::value<string>()->default_value(DEFAULT_ABSORBANCE_FILE), "output measured absorbance (filename)")
		("transmittance,T", po::value<string>()->default_value(DEFAULT_TRANSMITTANCE_FILE), "output measured transmittance (filename)")
		("far-field,F", po::value<string>()->default_value(DEFAULT_FAR_FILE), "output far-field at detector (filename)")
		("near-field,N", po::value<string>()->default_value(DEFAULT_NEAR_FILE), "output field at focal plane (filename)")
		("extended-source,X", po::value<string>()->default_value(DEFAULT_EXTENDED_SOURCE), "image of source at focus (filename)")
		//("sx,x", po::value<ptype>()->default_value(DEFAULT_SPHERE_X), "sphere coordinates")
		//("sy,y", po::value<ptype>()->default_value(DEFAULT_SPHERE_Y))
		//("sz,z", po::value<ptype>()->default_value(DEFAULT_SPHERE_Z))
		("sx,x", po::value<ptype>(), "sphere coordinates")
		("sy,y", po::value<ptype>())
		("sz,z", po::value<ptype>())
		("radius,r", po::value<ptype>()->default_value(DEFAULT_SPHERE_A), "sphere radius")
		("samples,s", po::value<int>()->default_value(DEFAULT_SAMPLES), "Monte-Carlo samples used to compute Us")
		("sphere-file,S", po::value< vector<string> >()->multitoken(), "sphere file:\n [x y z radius material]")
		("amplitude,a", po::value<ptype>()->default_value(DEFAULT_AMPLITUDE), "incident field amplitude")
		("n,n", po::value<ptype>()->default_value(DEFAULT_N, "1.4"), "sphere phase speed")
		("k,k", po::value<ptype>()->default_value(DEFAULT_K), "sphere absorption coefficient")
		("material-file,M", po::value< vector<string> >()->multitoken(), "material file:\n [lambda n k]")
		("materials", po::value< vector<ptype> >()->multitoken(), "materials specified using n, k pairs:\n ex. --materials n1 k1 n2 k2\n (if used --n and --k are ignored)")
		("lambda,l", po::value<ptype>()->default_value(DEFAULT_LAMBDA), "incident wavelength")
		("theta,t", po::value<ptype>()->default_value(DEFAULT_K_THETA), "light direction (polar coords)")
		("phi,p", po::value<ptype>()->default_value(DEFAULT_K_PHI))
		("fx", po::value<ptype>()->default_value(DEFAULT_FOCUS_X), "incident focal point")
		("fy", po::value<ptype>()->default_value(DEFAULT_FOCUS_Y))
		("fz", po::value<ptype>()->default_value(DEFAULT_FOCUS_Z))
		("condenser-max,C", po::value<ptype>()->default_value(DEFAULT_CONDENSER_MAX), "condenser numerical aperature")
		("condenser-min,c", po::value<ptype>()->default_value(DEFAULT_CONDENSER_MIN), "condenser obscuration NA")
		("objective-max,O", po::value<ptype>()->default_value(DEFAULT_OBJECTIVE_MAX), "objective numerical aperature")
		("objective-min,o", po::value<ptype>()->default_value(DEFAULT_OBJECTIVE_MIN), "objective obscuration NA")
		("field-order", po::value<int>()->default_value(DEFAULT_FIELD_ORDER), "order of the incident field")
		("output-type,f", po::value<string>()->default_value(DEFAULT_FIELD_TYPE), "output field value:\n magnitude, polarization, real, imaginary, angular-spectrum")
		("resolution,R", po::value<unsigned int>()->default_value(DEFAULT_SLICE_RES), "resolution of the detector")
		("padding,d", po::value<unsigned int>()->default_value(DEFAULT_PADDING), "FFT padding for the objective bandpass")
		("supersample", po::value<unsigned int>()->default_value(DEFAULT_SUPERSAMPLE), "super-sampling rate for the detector field")
		("colormap", po::value<string>()->default_value(DEFAULT_COLORMAP), "colormap: gray, brewer")
		("append", "append result to an existing file\n (binary files only)")
		("plane-min-x,u", po::value<ptype>()->default_value(DEFAULT_SLICE_MIN_X), "lower-left corner of the field slice")
		("plane-min-y,v", po::value<ptype>()->default_value(DEFAULT_SLICE_MIN_Y))
		("plane-min-z,w", po::value<ptype>()->default_value(DEFAULT_SLICE_MIN_Z))
		("plane-max-x,U", po::value<ptype>()->default_value(DEFAULT_SLICE_MAX_X), "upper-right corner of the field slice")
		("plane-max-y,V", po::value<ptype>()->default_value(DEFAULT_SLICE_MAX_Y))
		("plane-max-z,W", po::value<ptype>()->default_value(DEFAULT_SLICE_MAX_Z))
		("plane-norm-x", po::value<ptype>()->default_value(DEFAULT_SLICE_NORM_X), "field slice normal")
		("plane-norm-y", po::value<ptype>()->default_value(DEFAULT_SLICE_NORM_Y))
		("plane-norm-z", po::value<ptype>()->default_value(DEFAULT_SLICE_NORM_Z));
}

static void LoadParameters(int argc, char *argv[])
{
	//create an option description
	po::options_description desc("Allowed options");

	//fill it with options
	SetOptions(desc);

    po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	//display help and exit
	if(vm.count("help"))
	{
		cout<<desc<<endl;
		exit(1);
	}

	//load spheres
	loadSpheres(vm);

	//load materials
	loadMaterials(vm);

	loadNearfieldParams(vm);

	loadOutputParams(vm);

	loadMicroscopeParams(vm);

	loadSliceParams(vm);

    //if an extended source will be used
    if(vm["extended-source"].as<string>() != "")
    {
        //load the point sources
        string filename = vm["extended-source"].as<string>();
        SCOPE->LoadExtendedSource(filename);

    }





}