Ejemplo n.º 1
0
        /// <summary>
        /// method to tally to detector
        /// </summary>
        /// <param name="photon">photon data needed to tally</param>
        public void Tally(Photon photon)
        {
            var dp = photon.DP;
            var ia = DetectorBinning.WhichBin(Math.Acos(photon.DP.Direction.Uz), Angle.Count - 1, Angle.Delta, Angle.Start);

            if (ia != -1)
            {
                var x       = dp.Position.X;
                var fxArray = Fx.AsEnumerable().ToArray();
                for (int ifx = 0; ifx < fxArray.Length; ifx++)
                {
                    double freq = fxArray[ifx];
                    var    sinNegativeTwoPiFX = Math.Sin(-2 * Math.PI * freq * x);
                    var    cosNegativeTwoPiFX = Math.Cos(-2 * Math.PI * freq * x);
                    // convert to Hz-sec from GHz-ns 1e-9*1e9=1
                    var deltaWeight = dp.Weight * (cosNegativeTwoPiFX + Complex.ImaginaryOne * sinNegativeTwoPiFX);

                    Mean[ifx, ia] += deltaWeight;
                    if (TallySecondMoment) // 2nd moment is E[xx*]=E[xreal^2]+E[ximag^2]
                    {
                        var deltaWeight2 = dp.Weight * dp.Weight * cosNegativeTwoPiFX * cosNegativeTwoPiFX +
                                           dp.Weight * dp.Weight * sinNegativeTwoPiFX * sinNegativeTwoPiFX;
                        SecondMoment[ifx, ia] += deltaWeight2;
                    }
                }
                TallyCount++;
            }
        }
        /// <summary>
        /// method to tally given two consecutive photon data points
        /// </summary>
        /// <param name="previousDP">previous data point</param>
        /// <param name="dp">current data point</param>
        /// <param name="currentRegionIndex">index of region photon current is in</param>
        public void TallySingle(PhotonDataPoint previousDP, PhotonDataPoint dp, int currentRegionIndex)
        {
            var iz = DetectorBinning.WhichBin(dp.Position.Z, Z.Count - 1, Z.Delta, Z.Start);
            // using Acos, -1<Uz<1 goes to pi<theta<0, so first bin is most forward directed angle
            var ia = DetectorBinning.WhichBin(Math.Acos(dp.Direction.Uz), Angle.Count - 1, Angle.Delta, Angle.Start);

            var weight = _absorptionWeightingMethod(previousDP, dp, currentRegionIndex);

            if (weight != 0.0)
            {
                var x       = dp.Position.X;
                var fxArray = Fx.AsEnumerable().ToArray();
                for (int ifx = 0; ifx < fxArray.Length; ifx++)
                {
                    double freq = fxArray[ifx];
                    var    sinNegativeTwoPiFX = Math.Sin(-2 * Math.PI * freq * x);
                    var    cosNegativeTwoPiFX = Math.Cos(-2 * Math.PI * freq * x);
                    // convert to Hz-sec from GHz-ns 1e-9*1e9=1
                    var deltaWeight = (weight / _ops[currentRegionIndex].Mua) *
                                      (cosNegativeTwoPiFX + Complex.ImaginaryOne * sinNegativeTwoPiFX);

                    Mean[ifx, iz, ia] += deltaWeight;
                    if (TallySecondMoment)
                    {
                        _tallyForOnePhoton[ifx, iz, ia] += deltaWeight;
                    }
                    TallyCount++;
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// method to tally to detector
        /// </summary>
        /// <param name="photon">photon data needed to tally</param>
        public void Tally(Photon photon)
        {
            if (!IsWithinDetectorAperture(photon))
            {
                return;
            }

            var dp      = photon.DP;
            var x       = dp.Position.X;
            var fxArray = Fx.AsEnumerable().ToArray();

            for (int i = 0; i < fxArray.Length; i++)
            {
                double freq = fxArray[i];
                var    sinNegativeTwoPiFX = Math.Sin(-2 * Math.PI * freq * x);
                var    cosNegativeTwoPiFX = Math.Cos(-2 * Math.PI * freq * x);
                // convert to Hz-sec from GHz-ns 1e-9*1e9=1
                var deltaWeight = dp.Weight * (cosNegativeTwoPiFX + Complex.ImaginaryOne * sinNegativeTwoPiFX);

                Mean[i] += deltaWeight;
                if (TallySecondMoment)  // 2nd moment is E[xx*]=E[xreal^2]+E[ximag^2]
                {
                    var deltaWeight2 = dp.Weight * dp.Weight * cosNegativeTwoPiFX * cosNegativeTwoPiFX +
                                       dp.Weight * dp.Weight * sinNegativeTwoPiFX * sinNegativeTwoPiFX;
                    SecondMoment[i] += deltaWeight2;
                }
            }
            TallyCount++;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// method to tally given two consecutive photon data points
        /// </summary>
        /// <param name="previousDP">previous data point</param>
        /// <param name="dp">current data point</param>
        /// <param name="currentRegionIndex">index of region photon current is in</param>
        public void TallySingle(PhotonDataPoint previousDP, PhotonDataPoint dp, int currentRegionIndex)
        {
            var x       = dp.Position.X;
            var fxArray = Fx.AsEnumerable().ToArray();
            var iz      = DetectorBinning.WhichBin(dp.Position.Z, Z.Count - 1, Z.Delta, Z.Start);
            var weight  = _absorptionWeightingMethod(previousDP, dp, currentRegionIndex);
            // Note: GetVolumeAbsorptionWeightingMethod in Initialize method determines the *absorbed* weight
            //  so for fluence this weight is divided by Mua
            var regionIndex = currentRegionIndex;

            if (weight != 0)
            {
                for (int ifx = 0; ifx < fxArray.Length; ifx++)
                {
                    double freq = fxArray[ifx];
                    var    sinNegativeTwoPiFX = Math.Sin(-2 * Math.PI * freq * x);
                    var    cosNegativeTwoPiFX = Math.Cos(-2 * Math.PI * freq * x);
                    // convert to Hz-sec from GHz-ns 1e-9*1e9=1
                    var deltaWeight = weight * (cosNegativeTwoPiFX + Complex.ImaginaryOne * sinNegativeTwoPiFX);

                    Mean[ifx, iz] += (deltaWeight / _ops[regionIndex].Mua);
                    if (TallySecondMoment) // 2nd moment is E[xx*]=E[xreal^2]+E[ximag^2]
                    {
                        _tallyForOnePhoton[ifx, iz] +=
                            (deltaWeight / _ops[regionIndex].Mua) * (deltaWeight / _ops[regionIndex].Mua) *
                            cosNegativeTwoPiFX * cosNegativeTwoPiFX +
                            (deltaWeight / _ops[regionIndex].Mua) * (deltaWeight / _ops[regionIndex].Mua) *
                            sinNegativeTwoPiFX * sinNegativeTwoPiFX;
                    }
                }
                TallyCount++;
            }
        }
Ejemplo n.º 5
0
        public void Initialize(ITissue tissue, Random rng)
        {
            // assign any user-defined outputs (except arrays...we'll make those on-demand)
            TallyCount = 0;

            // if the data arrays are null, create them (only create second moment if TallySecondMoment is true)
            Mean         = Mean ?? new Complex[Fx.Count, Time.Count - 1];
            SecondMoment = SecondMoment ?? (TallySecondMoment ? new Complex[Fx.Count, Time.Count - 1] : null);

            // intialize any other necessary class fields here
            _perturbedOps            = PerturbedOps;
            _perturbedRegionsIndices = PerturbedRegionsIndices;
            _referenceOps            = tissue.Regions.Select(r => r.RegionOP).ToArray();
            _absorbAction            = AbsorptionWeightingMethods.GetpMCTerminationAbsorptionWeightingMethod(tissue, this);
            _fxArray = Fx.AsEnumerable().ToArray();
        }
Ejemplo n.º 6
0
        /// <summary>
        /// method to tally to detector
        /// </summary>
        /// <param name="photon">photon data needed to tally</param>
        public void Tally(Photon photon)
        {
            // calculate the radial bin to attribute the deposition
            var    tissueMT  = new double[2]; // 2 is for [static, dynamic] tally separation
            bool   talliedMT = false;
            double totalMT   = 0;
            var    totalMTOfZForOnePhoton   = new Complex[Fx.Count, Z.Count - 1];
            var    dynamicMTOfZForOnePhoton = new Complex[Fx.Count, Z.Count - 1];
            var    fxArray            = Fx.AsEnumerable().ToArray();
            var    x                  = photon.DP.Position.X; // use final exiting x position
            var    sinNegativeTwoPiFX = fxArray.Select(fx => Math.Sin(-2 * Math.PI * fx * x)).ToArray();
            var    cosNegativeTwoPiFX = fxArray.Select(fx => Math.Cos(-2 * Math.PI * fx * x)).ToArray();

            // go through photon history and claculate momentum transfer
            // assumes that no MT tallied at pseudo-collisions (reflections and refractions)
            // this algorithm needs to look ahead to angle of next DP, but needs info from previous to determine whether real or pseudo-collision
            PhotonDataPoint previousDP = photon.History.HistoryData.First();
            PhotonDataPoint currentDP  = photon.History.HistoryData.Skip(1).Take(1).First();

            foreach (PhotonDataPoint nextDP in photon.History.HistoryData.Skip(2))
            {
                if (previousDP.Weight != currentDP.Weight)                // only for true collision points
                {
                    var csr = _tissue.GetRegionIndex(currentDP.Position); // get current region index
                    // get z bin of current position
                    var iz = DetectorBinning.WhichBin(currentDP.Position.Z, Z.Count - 1, Z.Delta, Z.Start);
                    // get angle between current and next
                    double cosineBetweenTrajectories = Direction.GetDotProduct(currentDP.Direction, nextDP.Direction);
                    var    momentumTransfer          = 1 - cosineBetweenTrajectories;
                    totalMT += momentumTransfer;
                    for (int ifx = 0; ifx < Fx.Count; ifx++)
                    {
                        var deltaWeight = photon.DP.Weight * cosNegativeTwoPiFX[ifx] +
                                          Complex.ImaginaryOne * sinNegativeTwoPiFX[ifx];
                        TotalMTOfZ[ifx, iz]             += deltaWeight * momentumTransfer;
                        totalMTOfZForOnePhoton[ifx, iz] += deltaWeight * momentumTransfer;
                    }
                    if (_rng.NextDouble() < _bloodVolumeFraction[csr]) // hit blood
                    {
                        tissueMT[1] += momentumTransfer;
                        for (int ifx = 0; ifx < Fx.Count; ifx++)
                        {
                            var deltaWeight = photon.DP.Weight * cosNegativeTwoPiFX[ifx] +
                                              Complex.ImaginaryOne * sinNegativeTwoPiFX[ifx];
                            DynamicMTOfZ[ifx, iz]             += deltaWeight * momentumTransfer;
                            dynamicMTOfZForOnePhoton[ifx, iz] += deltaWeight * momentumTransfer;
                        }
                        SubregionCollisions[csr, 1] += 1; // add to dynamic collision count
                    }
                    else // index 0 captures static events
                    {
                        tissueMT[0] += momentumTransfer;
                        SubregionCollisions[csr, 0] += 1; // add to static collision count
                    }
                    talliedMT = true;
                }
                previousDP = currentDP;
                currentDP  = nextDP;
            }
            if (totalMT > 0.0)  // only tally if momentum transfer accumulated
            {
                var imt = DetectorBinning.WhichBin(totalMT, MTBins.Count - 1, MTBins.Delta, MTBins.Start);
                for (int ifx = 0; ifx < Fx.Count; ifx++)
                {
                    var deltaWeight = photon.DP.Weight * cosNegativeTwoPiFX[ifx] +
                                      Complex.ImaginaryOne * sinNegativeTwoPiFX[ifx];
                    Mean[ifx, imt] += deltaWeight;
                    if (TallySecondMoment)
                    {
                        SecondMoment[ifx, imt] += deltaWeight * deltaWeight;
                        for (int i = 0; i < Fx.Count - 1; i++)
                        {
                            for (int j = 0; j < Z.Count - 1; j++)
                            {
                                TotalMTOfZSecondMoment[i, j] +=
                                    totalMTOfZForOnePhoton[i, j] * totalMTOfZForOnePhoton[i, j];
                                DynamicMTOfZSecondMoment[i, j] +=
                                    dynamicMTOfZForOnePhoton[i, j] * dynamicMTOfZForOnePhoton[i, j];
                            }
                        }
                    }

                    if (talliedMT)
                    {
                        TallyCount++;
                    }

                    // tally DYNAMIC fractional MT in each subregion
                    int ifrac;
                    for (int isr = 0; isr < NumSubregions; isr++)
                    {
                        // add 1 to ifrac to offset bin 0 added for =0 only tallies
                        ifrac = DetectorBinning.WhichBin(tissueMT[1] / totalMT,
                                                         FractionalMTBins.Count - 1, FractionalMTBins.Delta, FractionalMTBins.Start) + 1;
                        // put identically 0 fractional MT into separate bin at index 0
                        if (tissueMT[1] / totalMT == 0.0)
                        {
                            ifrac = 0;
                        }

                        // put identically 1 fractional MT into separate bin at index Count+1 -1
                        if (tissueMT[1] / totalMT == 1.0)
                        {
                            ifrac = FractionalMTBins.Count;
                        }

                        FractionalMT[ifx, imt, ifrac] += deltaWeight;
                    }
                }
            }
        }