function cfg = mcxcreate(benchname, varargin)
%
% Format:
%    list=mcxcreate
%    cfg=mcxcreate(benchname)
%    cfg=mcxcreate(benchname,'param1',value1,'param2',value2,...)
%
% Create MCX simulation from built-in benchmarks (similar to "mcx --bench")
%
% Author: Qianqian Fang <q.fang at neu.edu>
%
% Input:
%    benchname (optional): a string to specify the name of the benchmark
%
% Output:
%    cfg: a struct defining the parameters associated with a simulation. If
%         no input, this function returns a list of supported benchmarks.
%
% Example:
%    list=mcxcreate;
%    cfg=mcxcreate('cube60b');
%    cfg=mcxcreate('cube60','srctype','isotropic','srcpos',[30 30 30])
%
% This function is part of Monte Carlo eXtreme (MCX) URL: http://mcx.space
%
% License: GNU General Public License version 3, please read LICENSE.txt for details
%

mcxbench.cube60 = struct( ...
                         'nphoton', 1e6, ...
                         'vol', uint8(ones(60, 60, 60)), ...
                         'srctype', 'pencil', 'srcpos', [29 29 0], 'srcdir', [0 0 1], ...
                         'prop', [0 0 1 1; 0.005 1 0.01 1.37], ...
                         'tstart', 0, 'tend', 5e-9, 'tstep', 5e-9, ....
                         'isreflect', 0, 'seed', 1648335518, 'issrcfrom0', 1, ...
                         'detpos', [29, 19, 0, 1; 29, 39, 0, 1; 19, 29, 0, 1; 39, 29, 0, 1]);

mcxbench.cube60b = mcxbench.cube60;
mcxbench.cube60b.isreflect = 1;

mcxbench.cube60planar = mcxbench.cube60b;
mcxbench.cube60planar.srctype = 'planar';
mcxbench.cube60planar.srcpos = [10.0, 10.0, -10.0];
mcxbench.cube60planar.srcparam1 = [40.0, 0.0, 0.0, 0.0];
mcxbench.cube60planar.srcparam2 = [0.0, 40.0, 0.0, 0.0];

mcxbench.skinvessel = struct( ...
                             'nphoton', 1e6, ...
                             'vol', uint8(ones(200, 200, 200)), ...
                             'srctype', 'disk', 'srcpos', [100 100 20], 'srcdir', [0 0 1], ...
                             'srcparam1', [60 0 0 0], 'unitinmm', 0.005, ...
                             'prop', [0 0 1 1; 3.564e-05 1 1 1.37; ...
                                      23.05426549 9.398496241 0.9 1.37; ...
                                      0.04584957865 35.65405549 0.9 1.37; ...
                                      1.657237447 37.59398496 0.9 1.37], ...
                             'tstart', 0, 'tend', 5e-8, 'tstep', 5e-8, ....
                             'isreflect', 0, 'seed', 1648335518, 'issrcfrom0', 1);
mcxbench.skinvessel.shapes = ['{"Shapes":[{"ZLayers":[[1,20,1],[21,32,4],[33,200,3]]},' ...
                              '{"Cylinder": {"Tag":2, "C0": [0,100.5,100.5], "C1": [200,100.5,100.5], "R": 20}}]}'];

mcxbench.sphshell = struct( ...
                           'nphoton', 1e6, ...
                           'vol', uint8(ones(60, 60, 60)), ...
                           'srctype', 'pencil', 'srcpos', [30 30.1 0], 'srcdir', [0 0 1], ...
                           'prop', [0 0 1 1; ...
                                    0.02 7 0.89 1.37; ...
                                    0.004 0.009 0.89 1.37; ...
                                    0.02 9.0 0.89 1.37; ...
                                    0.05 0.0 1.00 1.37], ...
                           'tstart', 0, 'tend', 5e-9, 'tstep', 5e-9, ....
                           'isreflect', 1, 'seed', 1648335518, 'issrcfrom0', 1);
mcxbench.sphshell.shapes = ['{"Shapes":[{"Grid":{"Tag":1,"Size":[60,60,60]}},'...
                            '{"Sphere":{"Tag":2,"O":[30,30,30],"R":25}},'...
                            '{"Sphere":{"Tag":3,"O":[30,30,30],"R":23}},'...
                            '{"Sphere":{"Tag":4,"O":[30,30,30],"R":10}}]}'];
mcxbench.sphshell.detpos = mcxbench.cube60.detpos;

mcxbench.spherebox = struct( ...
                            'nphoton', 1e6, ...
                            'vol', uint8(ones(60, 60, 60)), ...
                            'srcpos', [29.5, 29.5 0], 'srcdir', [0 0 1], ...
                            'prop', [0 0 1 1; ...
                                     0.002 1 0.01 1.37; ...
                                     0.05 5 0.9 1.37], ...
                            'tstart', 0, 'tend', 5e-9, 'tstep', 1e-10, ....
                            'isreflect', 0, 'seed', 1648335518, 'issrcfrom0', 1);
mcxbench.spherebox.shapes = ['{"Shapes":[{"Grid":{"Tag":1,"Size":[60,60,60]}},'...
                             '{"Sphere":{"Tag":2,"O":[30,30,30],"R":10}}]}'];

if (nargin == 0)
    cfg = fieldnames(mcxbench);
    return
end

if (isfield(mcxbench, benchname))
    cfg = mcxbench.(benchname);
    if (~isempty(varargin))
        for i = 1:2:length(varargin)
            if (ischar(varargin{i}) && i + 1 <= length(varargin))
                cfg.(lower(varargin{i})) = varargin{i + 1};
            else
                error('input must be in the form of ...,''name'',value,... pairs or structs');
            end
        end
    end
else
    error('benchmark name is not supported');
end
