예제 #1
0
        public MapData ExecuteForwardSolver()               // todo: simplify method calls to ComputationFactory, as with Forward/InverseSolver(s)
        {
            var opticalProperties = GetOpticalProperties(); // could be OpticalProperties[] or IOpticalPropertyRegion[][]

            //double[] rhos = RhoRangeVM.Values.Reverse().Concat(RhoRangeVM.Values).ToArray();
            double[] rhos = RhoRangeVM.Values.Reverse().Select(rho => - rho).Concat(RhoRangeVM.Values).ToArray();
            double[] zs   = ZRangeVM.Values.ToArray();

            double[][] independentValues = new[] { rhos, zs };

            var sd = GetSelectedSolutionDomain();

            // todo: too much thinking at the VM layer?
            double[] constantValues = new double[0];

            if (ComputationFactory.IsSolverWithConstantValues(sd.SelectedValue))
            {
                switch (sd.SelectedValue)
                {
                case FluenceSolutionDomainType.FluenceOfRhoAndZAndFt:
                    constantValues = new[] { TimeModulationFrequency };
                    break;

                default:
                    constantValues = new[] { sd.ConstantAxesVMs[0].AxisValue };
                    break;
                }
            }

            IndependentVariableAxis[] independentAxes =
                GetIndependentVariableAxesInOrder(
                    sd.IndependentVariableAxisOptionVM.SelectedValue,
                    IndependentVariableAxis.Z);

            double[] results = null;
            if (ComputationFactory.IsComplexSolver(sd.SelectedValue))
            {
                Complex[] fluence;
                if (IsMultiRegion)
                {
                    fluence =
                        ComputationFactory.ComputeFluenceComplex(
                            ForwardSolverTypeOptionVM.SelectedValue,
                            sd.SelectedValue,
                            independentAxes,
                            independentValues,
                            ((IOpticalPropertyRegion[][])opticalProperties)[0],
                            constantValues);
                }
                else
                {
                    fluence =
                        ComputationFactory.ComputeFluenceComplex(
                            ForwardSolverTypeOptionVM.SelectedValue,
                            sd.SelectedValue,
                            independentAxes,
                            independentValues,
                            ((OpticalProperties[])opticalProperties)[0],
                            constantValues);
                }

                switch (MapTypeOptionVM.SelectedValue)
                {
                case MapType.Fluence:
                    results = fluence.Select(f => f.Magnitude).ToArray();
                    break;

                case MapType.AbsorbedEnergy:
                    results = ComputationFactory.GetAbsorbedEnergy(fluence, ((OpticalProperties[])opticalProperties)[0].Mua).Select(a => a.Magnitude).ToArray();    // todo: is this correct?? DC 12/08/12
                    break;

                case MapType.PhotonHittingDensity:
                    switch (PhotonHittingDensitySolutionDomainTypeOptionVM.SelectedValue)
                    {
                    case FluenceSolutionDomainType.FluenceOfRhoAndZAndFt:
                        results = ComputationFactory.GetPHD(
                            ForwardSolverTypeOptionVM.SelectedValue,
                            fluence.ToArray(),
                            SourceDetectorSeparation,
                            TimeModulationFrequency,
                            (OpticalProperties[])opticalProperties,
                            independentValues[0],
                            independentValues[1]).ToArray();
                        break;

                    case FluenceSolutionDomainType.FluenceOfFxAndZAndFt:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("FluenceSolutionDomainType");
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException("MapType");
                }
            }
            else
            {
                double[] fluence;
                if (IsMultiRegion)
                {
                    fluence = ComputationFactory.ComputeFluence(
                        ForwardSolverTypeOptionVM.SelectedValue,
                        sd.SelectedValue,
                        independentAxes,
                        independentValues,
                        ((IOpticalPropertyRegion[][])opticalProperties)[0],
                        constantValues).ToArray();
                }
                else
                {
                    fluence = ComputationFactory.ComputeFluence(
                        ForwardSolverTypeOptionVM.SelectedValue,
                        sd.SelectedValue,
                        independentAxes,
                        independentValues,
                        (OpticalProperties[])opticalProperties,
                        constantValues).ToArray();
                }

                switch (MapTypeOptionVM.SelectedValue)
                {
                case MapType.Fluence:
                    results = fluence;
                    break;

                case MapType.AbsorbedEnergy:
                    if (IsMultiRegion)
                    {
                        if (ForwardSolver is TwoLayerSDAForwardSolver)
                        {
                            var regions = ((MultiRegionTissueViewModel)TissueInputVM).GetTissueInput().Regions
                                          .Select(region => (ILayerOpticalPropertyRegion)region).ToArray();
                            var muas = getRhoZMuaArrayFromLayerRegions(regions, rhos, zs);
                            results = ComputationFactory.GetAbsorbedEnergy(fluence, muas).ToArray();
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        // Note: the line below was originally overwriting the multi-region results. I think this was a bug (DJC 7/11/14)
                        results = ComputationFactory.GetAbsorbedEnergy(fluence, ((OpticalProperties[])opticalProperties)[0].Mua).ToArray();
                    }
                    break;

                case MapType.PhotonHittingDensity:
                    switch (PhotonHittingDensitySolutionDomainTypeOptionVM.SelectedValue)
                    {
                    case FluenceSolutionDomainType.FluenceOfRhoAndZ:
                        if (IsMultiRegion)
                        {
                            var nop = (IOpticalPropertyRegion[][])opticalProperties;
                            results = ComputationFactory.GetPHD(
                                ForwardSolverTypeOptionVM.SelectedValue,
                                fluence,
                                SourceDetectorSeparation,
                                (from LayerTissueRegion tissue in nop[0] select tissue.RegionOP).ToArray(),
                                independentValues[0],
                                independentValues[1]).ToArray();
                        }
                        else
                        {
                            results = ComputationFactory.GetPHD(
                                ForwardSolverTypeOptionVM.SelectedValue,
                                fluence,
                                SourceDetectorSeparation,
                                (OpticalProperties[])opticalProperties,
                                independentValues[0],
                                independentValues[1]).ToArray();
                        }
                        break;

                    case FluenceSolutionDomainType.FluenceOfFxAndZ:
                        break;

                    case FluenceSolutionDomainType.FluenceOfRhoAndZAndTime:
                        break;

                    case FluenceSolutionDomainType.FluenceOfFxAndZAndTime:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("PhotonHittingDensitySolutionDomainTypeOptionVM.SelectedValue");
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException("MapTypeOptionVM.SelectedValue");
                }
            }

            // flip the array (since it goes over zs and then rhos, while map wants rhos and then zs
            double[] destinationArray = new double[results.Length];
            long     index            = 0;

            for (int rhoi = 0; rhoi < rhos.Length; rhoi++)
            {
                for (int zi = 0; zi < zs.Length; zi++)
                {
                    destinationArray[rhoi + rhos.Length * zi] = results[index++];
                }
            }

            var dRho  = 1D;
            var dZ    = 1D;
            var dRhos = Enumerable.Select(rhos, rho => 2 * Math.PI * Math.Abs(rho) * dRho).ToArray();
            var dZs   = Enumerable.Select(zs, z => dZ).ToArray();

            //var twoRhos = Enumerable.Concat(rhos.Reverse(), rhos).ToArray();
            //var twoDRhos = Enumerable.Concat(dRhos.Reverse(), dRhos).ToArray();

            return(new MapData(destinationArray, rhos, zs, dRhos, dZs));
        }