Ejemplo n.º 1
0
        public static Complex[] ComputeFluenceComplex(
            IForwardSolver forwardSolver,
            FluenceSolutionDomainType solutionDomainType,
            // keeping us from uniting the above. needs to be a single SolutionDomainType enum
            IndependentVariableAxis[] independentAxesTypes,
            double[][] independentValues,
            OpticalProperties opticalProperties,
            params double[] constantValues)
        {
            var parameters = new double[4]
            {
                opticalProperties.Mua, opticalProperties.Musp, opticalProperties.G,
                opticalProperties.N
            };

            // todo: current assumption below is that the second axes is z. need to generalize
            var func = GetForwardFluenceFuncComplex(forwardSolver, solutionDomainType, independentAxesTypes[0]);

            // create a list of inputs (besides optical properties) that corresponds to the behavior of the function above
            List <object> inputValues = new List <object>(independentValues);

            constantValues.ForEach(cv => inputValues.Add(cv));

            return(func(parameters, inputValues.ToArray()));
        }
Ejemplo n.º 2
0
        // overload for ITissueRegion forward solvers todo: merge with above?
        public static double[] ComputeFluence(
            IForwardSolver forwardSolver,
            FluenceSolutionDomainType solutionDomainType,
            // keeping us from uniting the above. needs to be a single SolutionDomainType enum
            IndependentVariableAxis[] independentAxesTypes,
            double[][] independentValues,
            IOpticalPropertyRegion[] tissueRegions,
            params double[] constantValues)
        {
            var parameters = tissueRegions.SelectMany(region =>
            {
                double[] regionParameters = null;
                if (region is ILayerOpticalPropertyRegion)
                {
                    var layerRegion  = (ILayerOpticalPropertyRegion)region;
                    regionParameters = new[]
                    {
                        layerRegion.RegionOP.Mua,
                        layerRegion.RegionOP.Musp,
                        layerRegion.RegionOP.G,
                        layerRegion.RegionOP.N,
                        layerRegion.ZRange.Delta
                    };
                }
                //else if(region is EllipsoidTissueRegion)
                //{
                //
                //}
                else
                {
                    throw new Exception("Forward model " +
                                        forwardSolver.ToString() +
                                        " is not supported.");
                }
                return(regionParameters);
            }).ToArray();

            // todo: current assumption below is that the second axis is z. need to generalize
            var func = GetForwardFluenceFunc(forwardSolver, solutionDomainType, independentAxesTypes[0]);

            // create a list of inputs (besides optical properties) that corresponds to the behavior of the function above
            List <object> inputValues = new List <object>(independentValues);

            constantValues.ForEach(cv => inputValues.Add(cv));

            return(func(parameters, inputValues.ToArray()));
        }
Ejemplo n.º 3
0
        private static Func <double[], object[], Complex[]> GetForwardFluenceFuncComplex(
            IForwardSolver fs, FluenceSolutionDomainType type, IndependentVariableAxis axis)
        {
            Func <double[], OpticalProperties> getOP = op => new OpticalProperties(op[0], op[1], op[2], op[3]);

            // note: the following uses the convention that the independent variable(s) is (are) first in the forward data object array
            // note: secondly, if there are multiple independent axes, they will be assigned in order of appearance in the method signature
            switch (type)
            {
            case FluenceSolutionDomainType.FluenceOfRhoAndZAndFt:
                switch (axis)
                {
                case IndependentVariableAxis.Rho:
                    if (fs is TwoLayerSDAForwardSolver)         // todo: future generalization to IMultiRegionForwardSolver?
                    {
                        return((fitData, otherData) => fs.FluenceOfRhoAndZAndFt(new[] { getLayerTissueRegionArray(fitData) }, (double[])otherData[0], (double[])otherData[1], new[] { (double)otherData[2] }));
                    }
                    return((fitData, otherData) => fs.FluenceOfRhoAndZAndFt(new[] { getOP(fitData) }, (double[])otherData[0], (double[])otherData[1], new[] { (double)otherData[2] }));

                case IndependentVariableAxis.Ft:
                    if (fs is TwoLayerSDAForwardSolver)
                    {
                        return((fitData, otherData) => fs.FluenceOfRhoAndZAndFt(new[] { getLayerTissueRegionArray(fitData) }, (double[])otherData[2], (double[])otherData[1], new[] { (double)otherData[0] }));
                    }
                    return((fitData, otherData) => fs.FluenceOfRhoAndZAndFt(new[] { getOP(fitData) }, new[] { (double)otherData[2] }, (double[])otherData[1], (double[])otherData[0]));

                default:
                    throw new ArgumentOutOfRangeException("axis");
                }

            case FluenceSolutionDomainType.FluenceOfFxAndZAndFt:
                switch (axis)
                {
                case IndependentVariableAxis.Fx:
                    return((fitData, otherData) => fs.FluenceOfFxAndZAndFt(new[] { getOP(fitData) }, (double[])otherData[0], (double[])otherData[1], new[] { (double)otherData[2] }));

                case IndependentVariableAxis.Ft:
                    return((fitData, otherData) => fs.FluenceOfFxAndZAndFt(new[] { getOP(fitData) }, new[] { (double)otherData[2] }, (double[])otherData[1], (double[])otherData[0]));

                default:
                    throw new ArgumentOutOfRangeException("axis");
                }

            default:
                throw new ArgumentOutOfRangeException("type");
            }
        }
Ejemplo n.º 4
0
 // overload that calls the above method with just one set of optical properties
 public static double[] ComputeFluence(
     IForwardSolver forwardSolver,
     FluenceSolutionDomainType solutionDomainType,
     // keeping us from uniting the above. needs to be a single SolutionDomainType enum
     IndependentVariableAxis[] independentAxesTypes,
     double[][] independentValues,
     OpticalProperties opticalProperties,
     params double[] constantValues)
 {
     return(ComputeFluence(
                forwardSolver,
                solutionDomainType,
                independentAxesTypes,
                independentValues,
                new[] { opticalProperties },
                constantValues));
 }
Ejemplo n.º 5
0
 public static double[] ComputeFluence(
     ForwardSolverType forwardSolverType,
     FluenceSolutionDomainType solutionDomainType, // keeping us from uniting the above. needs to be a single SolutionDomainType enum
     IndependentVariableAxis[] independentAxesTypes,
     double[][] independentValues,
     OpticalProperties[] opticalProperties,
     params double[] constantValues)
 {
     // use factory method on each call, as opposed to injecting an instance from the outside
     // -- still time-efficient if singletons are used
     // -- potentially memory-inefficient if the user creates lots of large solver instances
     return(ComputeFluence(
                SolverFactory.GetForwardSolver(forwardSolverType),
                solutionDomainType,
                independentAxesTypes,
                independentValues,
                opticalProperties,
                constantValues));
 }
Ejemplo n.º 6
0
        public static double[] ComputeFluence(
            IForwardSolver forwardSolver,
            FluenceSolutionDomainType solutionDomainType, // keeping us from uniting the above. needs to be a single SolutionDomainType enum
            IndependentVariableAxis[] independentAxesTypes,
            double[][] independentValues,
            OpticalProperties[] opticalProperties,
            params double[] constantValues)
        {
            // todo: current assumption below is that the second axes is z. need to generalize
            var func = GetForwardFluenceFunc(forwardSolver, solutionDomainType, independentAxesTypes[0]);

            // create a list of inputs (besides optical properties) that corresponds to the behavior of the function above
            List <object> inputValues = new List <object>(independentValues);

            constantValues.ForEach(cv => inputValues.Add(cv));

            if (opticalProperties.Length == 1) // optimization that skips duplicate arrays if we're not multiplexing over optical properties (e.g. wavelength)
            {
                var op         = opticalProperties[0];
                var parameters = new[] { op.Mua, op.Musp, op.G, op.N };
                return(func(parameters, inputValues.ToArray()));
            }

            var numOp   = opticalProperties.Length;
            var numIv   = independentValues.Length;
            var fluence = new double[numOp * numIv];

            for (int opi = 0; opi < numOp; opi++) // todo: parallelize
            {
                var op         = opticalProperties[opi];
                var parameters = new[] { op.Mua, op.Musp, op.G, op.N };
                var tempValues = func(parameters, inputValues.ToArray());

                for (int ivi = 0; ivi < numIv; ivi++)
                {
                    fluence[opi * numIv + ivi] = tempValues[ivi];
                }
            }
            return(fluence);
        }
Ejemplo n.º 7
0
        public static string GetUnits(this FluenceSolutionDomainType sdType)
        {
            switch (sdType)
            {
            case FluenceSolutionDomainType.FluenceOfRhoAndZ:
            default:
                return(DependentVariableAxisUnits.PerMMCubed.GetInternationalizedString());

            case FluenceSolutionDomainType.FluenceOfFxAndZ:
                return(DependentVariableAxisUnits.PerMM.GetInternationalizedString());

            case FluenceSolutionDomainType.FluenceOfRhoAndZAndTime:
                return(DependentVariableAxisUnits.PerMMCubedPerNS.GetInternationalizedString());

            case FluenceSolutionDomainType.FluenceOfFxAndZAndTime:
                return(DependentVariableAxisUnits.PerMMPerNS.GetInternationalizedString());

            case FluenceSolutionDomainType.FluenceOfRhoAndZAndFt:
                return(DependentVariableAxisUnits.PerMMCubedPerGHz.GetInternationalizedString());

            case FluenceSolutionDomainType.FluenceOfFxAndZAndFt:
                return(DependentVariableAxisUnits.PerMMPerGHz.GetInternationalizedString());
            }
        }
Ejemplo n.º 8
0
        // todo: array overloads for fluence forward solvers too
        private static Func <double[], object[], double[]> GetForwardFluenceFunc(
            IForwardSolver fs, FluenceSolutionDomainType type, IndependentVariableAxis axis)
        {
            Func <double[], OpticalProperties> getOP = op => new OpticalProperties(op[0], op[1], op[2], op[3]);

            // note: the following uses the convention that the independent variable(s) is (are) first in the forward data object array
            // note: secondly, if there are multiple independent axes, they will be assigned in order of appearance in the method signature
            switch (type)
            {
            case FluenceSolutionDomainType.FluenceOfRhoAndZ:
                if (fs is TwoLayerSDAForwardSolver)     // todo: future generalization to IMultiRegionForwardSolver?
                {
                    return((fitData, otherData) => fs.FluenceOfRhoAndZ(new[] { getLayerTissueRegionArray(fitData) }, (double[])otherData[0], (double[])otherData[1]));
                }
                return((fitData, otherData) => fs.FluenceOfRhoAndZ(new[] { getOP(fitData) }, (double[])otherData[0], (double[])otherData[1]));

            case FluenceSolutionDomainType.FluenceOfFxAndZ:
                return((fitData, otherData) => fs.FluenceOfFxAndZ(new[] { getOP(fitData) }, (double[])otherData[0], (double[])otherData[1]));

            case FluenceSolutionDomainType.FluenceOfRhoAndZAndTime:
                switch (axis)
                {
                case IndependentVariableAxis.Rho:
                    return((fitData, otherData) => fs.FluenceOfRhoAndZAndTime(new[] { getOP(fitData) }, (double[])otherData[0], (double[])otherData[1], new[] { (double)otherData[2] }));

                case IndependentVariableAxis.Time:
                    return((fitData, otherData) => fs.FluenceOfRhoAndZAndTime(new[] { getOP(fitData) }, new[] { (double)otherData[2] }, (double[])otherData[1], (double[])otherData[0]));

                //case IndependentVariableAxis.Wavelength:
                //    return (chromPlusMusp, constantData) =>
                //               {
                //                   var wv = (double[]) constantData[0];
                //                   var tissue = (Tissue) constantData[1];
                //                   int i = 0;
                //                   tissue.Absorbers.ForEach(abs => abs.Concentration = chromPlusMusp[i++]);
                //                   tissue.Scatterer = new PowerLawScatterer(chromPlusMusp[i], chromPlusMusp[i + 1]);
                //                   var muas = wv.Select(w => tissue.GetMua(w));
                //                   var musps = wv.Select(w => tissue.GetMusp(w));
                //                   return EnumerableExtensions.Zip(muas,musps,(mua,musp)=>fs.ROfRhoAndTime())...
                //               };
                //    return op => fs.ROfRhoAndTime(op, ((double)constantValues[0]).AsEnumerable(), ((double)constantValues[1]).AsEnumerable());
                default:
                    throw new ArgumentOutOfRangeException("axis");
                }

            case FluenceSolutionDomainType.FluenceOfFxAndZAndTime:
                switch (axis)
                {
                case IndependentVariableAxis.Fx:
                    return((fitData, otherData) => fs.FluenceOfFxAndZAndTime(new[] { getOP(fitData) }, (double[])otherData[0], (double[])otherData[1], new[] { (double)otherData[2] }));

                case IndependentVariableAxis.Time:
                    return((fitData, otherData) => fs.FluenceOfFxAndZAndTime(new[] { getOP(fitData) }, new[] { (double)otherData[2] }, (double[])otherData[1], (double[])otherData[0]));

                default:
                    throw new ArgumentOutOfRangeException("axis");
                }

            default:
                throw new ArgumentOutOfRangeException("type");
            }
        }
Ejemplo n.º 9
0
 public static bool IsComplexSolver(FluenceSolutionDomainType solutionDomainType)
 {
     return
         ((solutionDomainType == FluenceSolutionDomainType.FluenceOfRhoAndZAndFt) ||
          (solutionDomainType == FluenceSolutionDomainType.FluenceOfFxAndZAndFt));
 }
Ejemplo n.º 10
0
 public static bool IsSolverWithConstantValues(FluenceSolutionDomainType solutionDomainType)
 {
     return
         (!(solutionDomainType == FluenceSolutionDomainType.FluenceOfRhoAndZ) &&
          !(solutionDomainType == FluenceSolutionDomainType.FluenceOfFxAndZ));
 }