예제 #1
0
        // this method builds an R(rho, ft) array and then uses FFT to generate R(rho, t)
        private double[] DetermineROfTimeFromROfFtForFixedRho(double rho, IOpticalPropertyRegion[] regions,
                                                              out double[] FFTTimeSequence)
        {
            // get ops of top tissue region
            var op0 = regions[0].RegionOP;
            var fr1 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder1(op0.N);
            var fr2 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder2(op0.N);
            var diffusionParameters = GetDiffusionParameters(regions);
            var layerThicknesses    = GetLayerThicknesses(regions);

            int numFreq = 512;        // Kienle used 512 and deltaFreq = 0.1
            // Kienle says deltaFrequency depends on source-detector separation
            var deltaFrequency = 0.1; // 100 MHz

            if (rho <= 3)
            {
                deltaFrequency = 0.5;                         // so far I've found this value works for smaller rho
            }
            var F         = numFreq * deltaFrequency;         // 51 GHz
            var deltaTime = 1.0 / (numFreq * deltaFrequency); // 0.02 ns => T = 10 ns

            // var homoSDA = new PointSourceSDAForwardSolver(); // debug with h**o SDA
            // var rOfTime = new Complex[numFreq]; // debug array

            // considerations: 2n datapoint and pad with 0s beyond (deltaTime * numFreq)
            var rOfFt = new Complex[numFreq];

            double[] ft = Enumerable.Range(0, numFreq).Select(x => x * deltaFrequency).ToArray();
            FFTTimeSequence = Enumerable.Range(0, numFreq).Select(x => x * deltaTime).ToArray();

            for (int i = 0; i < numFreq; i++)
            {
                // normalize by F=(numFreq*deltaFrequency)
                rOfFt[i] = TemporalFrequencyReflectance(rho, ft[i], diffusionParameters, layerThicknesses, fr1, fr2) * F;
                // rOfTime[i] = homoSDA.ROfRhoAndTime(regions[1].RegionOP, rho, t[i]); // debug array
            }
            // to debug, use R(t) and FFT to see if result R(ft) is close to rOfFt
            //var dft2 = new MathNet.Numerics.IntegralTransforms.Algorithms.DiscreteFourierTransform();
            //dft2.Radix2Forward(rOfTime, FourierOptions.NoScaling);  // convert to R(ft) to compare with rOfFt
            //var relDiffReal = Enumerable.Zip(rOfTime, rOfFt, (x, y) => Math.Abs((y.Real - x.Real) / x.Real));
            //var relDiffImag = Enumerable.Zip(rOfTime, rOfFt, (x, y) => Math.Abs((y.Imaginary - x.Imaginary) / x.Imaginary));
            //var maxReal = relDiffReal.Max();
            //var maxImag = relDiffImag.Max();
            //var dum1 = maxReal;
            //var dum2 = maxImag;
            //dft2.Inverse(rOfTime, FourierOptions.NoScaling); // debug convert to R(t)
            // end debug code

            // FFT R(ft) to R(t)
            //var dft = new MathNet.Numerics.IntegralTransforms.Algorithms.DiscreteFourierTransform();
            //dft.Inverse(rOfFt, FourierOptions.NoScaling); // convert to R(t)
            Fourier.Inverse(rOfFt, FourierOptions.NoScaling);
            var rOfTime = new double[FFTTimeSequence.Length];

            rOfTime = rOfFt.Select(r => r.Real / (numFreq / 2)).ToArray();
            return(rOfTime);
        }
        // protected methods

        /// <summary>
        /// Calculates the reflectance based on the integral of the radiance over the backward hemisphere...
        /// </summary>
        /// <param name="surfaceFluence">diffuse fluence at the surface</param>
        /// <param name="surfaceFlux">diffuse flux at the surface</param>
        /// <param name="mediaRefractiveIndex">refractive index of the medium</param>
        /// <returns></returns>
        protected static double GetBackwardHemisphereIntegralDiffuseReflectance(
            double surfaceFluence, double surfaceFlux, double mediaRefractiveIndex)
        {
            var fr1 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder1(
                mediaRefractiveIndex);
            var fr2 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder2(
                mediaRefractiveIndex);

            return(GetBackwardHemisphereIntegralDiffuseReflectance(surfaceFluence, surfaceFlux,
                                                                   fr1, fr2));
        }
 public override IEnumerable <double> ROfRho(
     IEnumerable <OpticalProperties> ops,
     IEnumerable <double> rhos)
 {
     foreach (var op in ops)
     {
         DiffusionParameters dp = DiffusionParameters.Create(op, this.ForwardModel);
         var fr1 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder1(op.N);
         var fr2 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder2(op.N);
         foreach (var rho in rhos)
         {
             yield return(StationaryReflectance(dp, rho, fr1, fr2));
         }
     }
 }
        public override double ROfFx(IOpticalPropertyRegion[] regions, double fx)
        {
            // get ops of top tissue region
            var op0 = regions[0].RegionOP;
            var fr1 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder1(op0.N);
            var fr2 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder2(op0.N);

            var diffusionParameters = GetDiffusionParameters(regions);
            var layerThicknesses    = GetLayerThicknesses(regions);

            // check that embedded source is within top layer, otherwise solution invalid
            if (diffusionParameters[0].zp > layerThicknesses[0])
            {
                throw new ArgumentException("Top layer thickness must be greater than l* = 1/(mua+musp)");
            }
            return(SpatialFrequencyReflectance(2 * Math.PI * fx, diffusionParameters, layerThicknesses, fr1, fr2));
        }
 public override IEnumerable <Complex> ROfRhoAndFt(IEnumerable <OpticalProperties> ops,
                                                   IEnumerable <double> rhos, IEnumerable <double> fts)
 {
     foreach (var op in ops)
     {
         DiffusionParameters dp = DiffusionParameters.Create(op, this.ForwardModel);
         var fr1 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder1(op.N);
         var fr2 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder2(op.N);
         foreach (var rho in rhos)
         {
             foreach (var ft in fts)
             {
                 Complex k = ((op.Mua * dp.cn + Complex.ImaginaryOne * ft * 2 * Math.PI) /
                              (dp.cn * dp.D)).SquareRoot();
                 yield return(TemporalFrequencyReflectance(dp, rho, k, fr1, fr2));
             }
         }
     }
 }
        // this method builds an R(fx, ft) array and then uses FFT to generate R(fx, t)
        private double[] DetermineROfTimeFromROfFtForFixedFx(double fx, IOpticalPropertyRegion[] regions, out double[] FFTTimeSequence)
        {
            // get ops of top tissue region
            var op0 = regions[0].RegionOP;
            var fr1 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder1(op0.N);
            var fr2 = CalculatorToolbox.GetCubicFresnelReflectionMomentOfOrder2(op0.N);
            var diffusionParameters = GetDiffusionParameters(regions);
            var layerThicknesses    = GetLayerThicknesses(regions);

            int numFreq = 512;                                // Kienle used 512 and deltaFreq = 0.1
            // Kienle says deltaFrequency depends on source-detector separation
            var deltaFrequency = 0.5;                         // 500 MHz good for all fx

            var F         = numFreq * deltaFrequency;         // 51 GHz
            var deltaTime = 1.0 / (numFreq * deltaFrequency); // 0.02 ns => T = 10 ns

            // considerations: 2n datapoint and pad with 0s beyond (deltaTime * numFreq)
            var rOfFt = new Complex[numFreq];

            double[] ft = Enumerable.Range(0, numFreq).Select(x => x * deltaFrequency).ToArray();
            FFTTimeSequence = Enumerable.Range(0, numFreq).Select(x => x * deltaTime).ToArray();

            for (int i = 0; i < numFreq; i++)
            {
                // normalize by F=(numFreq*deltaFrequency)
                rOfFt[i] = SpatialAndTemporalFrequencyReflectance(2 * Math.PI * fx, ft[i], diffusionParameters, layerThicknesses, fr1, fr2) * F;
            }

            // FFT R(ft) to R(t)
            //var dft = new MathNet.Numerics.IntegralTransforms.Algorithms.DiscreteFourierTransform();
            //dft.Radix2Inverse(rOfFt, FourierOptions.NoScaling); // convert to R(t)
            Fourier.Radix2Inverse(rOfFt, FourierOptions.NoScaling);
            var rOfTime = new double[FFTTimeSequence.Length];

            rOfTime = rOfFt.Select(r => r.Real / (numFreq / 2)).ToArray();
            return(rOfTime);
        }