private static ValidationResult ValidateDetectorInput(SimulationInput si)
 {
     if (((si.Options.Databases == null) || (si.Options.Databases.Count() < 1)) && (si.DetectorInputs.Count() < 1))
     {
         return(new ValidationResult(
                    false,
                    "No detector inputs specified and no database to be written",
                    "Make sure list of DetectorInputs is not empty or null if no databases are to be written"));
     }
     // black list of unimplemented detectors
     foreach (var detectorInput in si.DetectorInputs)
     {
         if (detectorInput.TallyDetails.IsNotImplementedYet)
         {
             return(new ValidationResult(
                        false,
                        "DetectorInput not implemented yet:" + detectorInput.ToString(),
                        "Please omit " + detectorInput.ToString() + " from DetectorInput list"));
         }
     }
     return(new ValidationResult(
                true,
                "DetectorInput must be valid",
                ""));
 }
        /// <summary>
        /// Output from a Monte Carlo simulation
        /// </summary>
        /// <param name="si">SimulationInput</param>
        /// <param name="detectorResults">list of IDetector</param>
        public SimulationOutput(SimulationInput si, IList <IDetector> detectorResults)
        {
            int count = 1;

            Input             = si;
            ResultsDictionary = new Dictionary <String, IDetector>();
            foreach (var detector in detectorResults)
            {
                try
                {
                    ResultsDictionary.Add(detector.Name, detector);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Problem adding detector results to dictionary.\n\nDetails:\n\n" + e + "\n");
                    if (e is ArgumentException)
                    {
                        Console.WriteLine("detector with that name already exists in dictionary\n");
                        Console.WriteLine("Adding detector with name = " + detector.Name + count + " instead.\n");
                        string newName = detector.Name + count;
                        ResultsDictionary.Add(newName, detector);
                        ++count;
                    }
                }
            }
            //ResultsDictionary = detectorResults.ToDictionary(d => d.Name);
            _detectorResults = detectorResults;
        }
        /// <summary>
        /// Master of call validation methods. Calls methods to validate source,
        /// tissue and detector definitions.
        /// </summary>
        /// <param name="input">SimulationInput to be validated</param>
        /// <returns>ValidationResult with IsValid bool set and message about error if false</returns>
        public static ValidationResult ValidateInput(SimulationInput input)
        {
            var validations = new Func <SimulationInput, ValidationResult>[]
            {
                si => ValidateN(si.N),
                si => ValidateSourceInput(si.SourceInput, si.TissueInput),
                si => ValidateTissueInput(si.TissueInput),
                si => ValidateDetectorInput(si),
                si => ValidateCombinedInputParameters(si),
                si => ValidateCurrentIncapabilities(si)
            };

            foreach (var validation in validations)
            {
                var tempResult = validation(input);
                if (!tempResult.IsValid)
                {
                    return(tempResult);
                }
            }

            return(new ValidationResult(true, "Simulation input is valid"));
        }
 /// <summary>
 /// Method checks SimulationInput against current incapabilities of the code.
 /// </summary>
 /// <param name="input">SimulationInput</param>
 /// <returns>ValidationResult</returns>
 private static ValidationResult ValidateCurrentIncapabilities(SimulationInput input)
 {
     if (input.Options.AbsorptionWeightingType == AbsorptionWeightingType.Continuous)
     {
         foreach (var detectorInput in input.DetectorInputs)
         {
             if (detectorInput.TallyDetails.IsNotImplementedForCAW)
             {
                 return(new ValidationResult(
                            false,
                            "The use of Continuous Absorption Weighting is not implemented for one of the infile detectors",
                            "Modify AbsorptionWeightingType to Discrete"));
             }
         }
     }
     if (input.Options.AbsorptionWeightingType == AbsorptionWeightingType.Discrete)
     {
         foreach (var detectorInput in input.DetectorInputs)
         {
             if (detectorInput.TallyDetails.IsNotImplementedForDAW)
             {
                 return(new ValidationResult(
                            false,
                            "The use of Discrete Absorption Weighting with path length type detectors not implemented yet",
                            "Modify AbsorptionWeightingType to Continuous"));
             }
         }
     }
     foreach (var detectorInput in input.DetectorInputs)
     {
         // can only run dMC detectors with 1 perturbed region for the present
         if (detectorInput.TallyType.Contains("dMCdROfRhodMua"))
         {
             return(dMCdROfRhodMuaDetectorInputValidation.ValidateInput(detectorInput));
         }
         if (detectorInput.TallyType.Contains("dMCdROfRhodMus"))
         {
             return(dMCdROfRhodMusDetectorInputValidation.ValidateInput(detectorInput));
         }
         // check that number in blood volume list matches number of tissue subregions
         if (detectorInput.TallyType.Contains("ReflectedDynamicMTOfRhoAndSubregionHist"))
         {
             return(ReflectedDynamicMTOfRhoAndSubregionHistDetectorInputValidation.ValidateInput(detectorInput, input.TissueInput.Regions.Count()));
         }
         if (detectorInput.TallyType.Contains("ReflectedDynamicMTOfXAndYAndSubregionHist"))
         {
             return(ReflectedDynamicMTOfXAndYAndSubregionHistDetectorInputValidation.ValidateInput(detectorInput, input.TissueInput.Regions.Count()));
         }
         if (detectorInput.TallyType.Contains("TransmittedDynamicMTOfRhoAndSubregionHist"))
         {
             return(TransmittedDynamicMTOfRhoAndSubregionHistDetectorInputValidation.ValidateInput(detectorInput, input.TissueInput.Regions.Count()));
         }
         if (detectorInput.TallyType.Contains("TransmittedDynamicMTOfXAndYAndSubregionHist"))
         {
             return(TransmittedDynamicMTOfXAndYAndSubregionHistDetectorInputValidation.ValidateInput(detectorInput, input.TissueInput.Regions.Count()));
         }
         if (detectorInput.TallyType.Contains("SurfaceFiber"))
         {
             return(SurfaceFiberDetectorInputValidation.ValidateInput(detectorInput));
         }
     }
     return(new ValidationResult(
                true,
                "Detector definitions are consistent with current capabilities"));
 }
 /// <summary>
 /// This method checks the input against combined combinations of options
 /// and source, tissue, detector definitions.
 /// </summary>
 /// <param name="input">input to be validated</param>
 /// <returns>ValidationResult with IsValid set and error message if false</returns>
 private static ValidationResult ValidateCombinedInputParameters(SimulationInput input)
 {
     // check that absorption weighting type set to analog and RR weight threshold != 0.0
     if ((input.Options.AbsorptionWeightingType == AbsorptionWeightingType.Analog) &&
         input.Options.RussianRouletteWeightThreshold != 0.0)
     {
         return(new ValidationResult(
                    false,
                    "Russian Roulette cannot be employed with Analog absorption weighting is specified",
                    "With Analog absorption weighting, set Russian Roulette weight threshold = 0.0"));
     }
     // check that if single ellipsoid tissue specified and (r,z) detector specified,
     // that (1) ellipsoid is centered at x=0, y=0, (2) ellipsoid is cylindrically symmetric (dx=dy)
     if (input.TissueInput is SingleEllipsoidTissueInput)
     {
         foreach (var detectorInput in input.DetectorInputs)
         {
             var ellipsoid = (EllipsoidTissueRegion)((SingleEllipsoidTissueInput)input.TissueInput).
                             EllipsoidRegion;
             if (detectorInput.TallyDetails.IsCylindricalTally &&
                 (ellipsoid.Center.X != 0.0) && (ellipsoid.Center.Y != 0.0))
             {
                 return(new ValidationResult(
                            false,
                            "Ellipsoid must be centered at (x,y)=(0,0) for cylindrical tallies",
                            "Change ellipsoid center to (0,0) or specify non-cylindrical type tally"));
             }
             if (detectorInput.TallyDetails.IsCylindricalTally && (ellipsoid.Dx != ellipsoid.Dy))
             {
                 return(new ValidationResult(
                            false,
                            "Ellipsoid must have Dx=Dy for cylindrical tallies",
                            "Change ellipsoid.Dx to be = to Dy or specify non-cylindrical type tally"));
             }
             if (detectorInput.TallyType == TallyType.ROfFx)
             {
                 return(new ValidationResult(
                            false,
                            "R(fx) tallies assume a homogeneous or layered tissue geometry",
                            "Change tissue type to be homogeneous or layered"));
             }
         }
     }
     // check that if single voxel or single infinite cylinder tissue specified,
     // cannot specify (r,z) detector
     if ((input.TissueInput is SingleVoxelTissueInput) ||
         (input.TissueInput is SingleInfiniteCylinderTissueInput))
     {
         foreach (var detectorInput in input.DetectorInputs)
         {
             if (detectorInput.TallyDetails.IsCylindricalTally)
             {
                 return(new ValidationResult(
                            false,
                            "Cannot use Single Voxel Tissue for cylindrical tallies",
                            "Change detector inputs to specify non-cylindrical type tallies"));
             }
             if (detectorInput.TallyType == TallyType.ROfFx)
             {
                 return(new ValidationResult(
                            false,
                            "R(fx) tallies assume a homogeneous or layered tissue geometry",
                            "Change tissue type to be homogeneous or layered"));
             }
         }
     }
     // check that if bounding volume tissue specified, the ATotalBoundingVolumeTissueInput detector needs
     // to be specified
     if (input.TissueInput is BoundingCylinderTissueInput)
     {
         if (!input.DetectorInputs.Any(d => d.TallyType == TallyType.ATotalBoundingVolume))
         {
             return(new ValidationResult(
                        false,
                        "BoundingCylinderTissueInput needs associated detector ATotalBoundingVolume to be defined",
                        "Add ATotalBoundingVolumeDetectorInput to detector inputs"));
         }
     }
     if (input.SourceInput is DirectionalPointSourceInput)
     {
         var source = (DirectionalPointSourceInput)input.SourceInput;
         if (source.Direction != new Direction(0, 0, 1))
         {
             foreach (var detectorInput in input.DetectorInputs)
             {
                 if (detectorInput.TallyDetails.IsCylindricalTally)
                 {
                     return(new ValidationResult(
                                false,
                                "If source is angled, cannot define cylindrically symmetric detectors",
                                "Change detector to Cartesian equivalent or define source to be normal"));
                 }
             }
         }
     }
     foreach (var detectorInput in input.DetectorInputs)
     {
         if (detectorInput.TallyDetails.IsTransmittanceTally && (input.TissueInput is MultiLayerTissueInput))
         {
             if ((((dynamic)detectorInput).FinalTissueRegionIndex == 0))
             {
                 return(new ValidationResult(
                            false,
                            "Transmittance detectors with MultiLayerTissues cannot detect in tissue region 0",
                            "Change FinalTissueRegionIndex to be index of air below tissue (index >= 2)"));
             }
         }
     }
     return(new ValidationResult(
                true,
                "Input options or tissue/detector combinations are valid",
                ""));
 }
Esempio n. 6
0
        /// <summary>
        /// Class that takes in SimulationInput and methods to initialize and execute Monte Carlo simulation
        /// </summary>
        /// <param name="input">SimulationInput</param>
        public MonteCarloSimulation(SimulationInput input)
        {
            _outputPath = "";

            // all field/property defaults should be set here
            _input = input;

            var result = SimulationInputValidation.ValidateInput(_input);

            if (result.IsValid == false)
            {
                throw new ArgumentException(result.ValidationRule + (!string.IsNullOrEmpty(result.Remarks) ? "; " + result.Remarks : ""));
            }

            _numberOfPhotons = input.N;

            AbsorptionWeightingType = input.Options.AbsorptionWeightingType; // CKH add 12/14/09
            TrackStatistics         = input.Options.TrackStatistics;
            if (TrackStatistics)
            {
                _simulationStatistics = new SimulationStatistics();
            }
            _rng = RandomNumberGeneratorFactory.GetRandomNumberGenerator(
                input.Options.RandomNumberGeneratorType, input.Options.Seed);

            this.SimulationIndex = input.Options.SimulationIndex;

            _tissue = TissueFactory.GetTissue(input.TissueInput, input.Options.AbsorptionWeightingType, input.Options.PhaseFunctionType, input.Options.RussianRouletteWeightThreshold);
            _source = SourceFactory.GetSource(input.SourceInput, _rng);

            // instantiate vb (and associated detectors) for each vb group
            _virtualBoundaryController = new VirtualBoundaryController(new List <IVirtualBoundary>());

            List <VirtualBoundaryType> dbVirtualBoundaries =
                input.Options.Databases.Select(db => db.GetCorrespondingVirtualBoundaryType()).ToList();


            foreach (var vbType in EnumHelper.GetValues <VirtualBoundaryType>())
            {
                IEnumerable <IDetectorInput> detectorInputs = null;

                switch (vbType)
                {
                case VirtualBoundaryType.DiffuseReflectance:
                default:
                    detectorInputs = input.DetectorInputs.Where(d => d.TallyDetails.IsReflectanceTally).ToList();
                    break;

                case VirtualBoundaryType.DiffuseTransmittance:
                    detectorInputs = input.DetectorInputs.Where(d => d.TallyDetails.IsTransmittanceTally).ToList();
                    break;

                case VirtualBoundaryType.SpecularReflectance:
                    detectorInputs = input.DetectorInputs.Where(d => d.TallyDetails.IsSpecularReflectanceTally).ToList();
                    break;

                case VirtualBoundaryType.GenericVolumeBoundary:
                    detectorInputs = input.DetectorInputs.Where(d => d.TallyDetails.IsVolumeTally).ToList();
                    break;

                case VirtualBoundaryType.SurfaceRadiance:
                    detectorInputs = input.DetectorInputs.Where(d => d.TallyDetails.IsInternalSurfaceTally).ToList();
                    break;

                case VirtualBoundaryType.pMCDiffuseReflectance:
                    detectorInputs = input.DetectorInputs.Where(d => d.TallyDetails.IspMCReflectanceTally).ToList();
                    break;

                case VirtualBoundaryType.BoundingCylinderVolume:
                    detectorInputs = input.DetectorInputs.Where(d => d.TallyDetails.IsBoundingVolumeTally).ToList();
                    break;
                }

                // make sure VB Controller has at least diffuse reflectance and diffuse transmittance
                // may change this in future if tissue OnDomainBoundary changes
                if ((detectorInputs.Count() > 0) || (vbType == VirtualBoundaryType.DiffuseReflectance) ||
                    (vbType == VirtualBoundaryType.DiffuseTransmittance) || (dbVirtualBoundaries.Any(vb => vb == vbType)))
                {
                    var detectors          = DetectorFactory.GetDetectors(detectorInputs, _tissue, _rng);
                    var detectorController = DetectorControllerFactory.GetDetectorController(vbType, detectors, _tissue);
                    // var detectorController = new DetectorController(detectors);
                    var virtualBoundary = VirtualBoundaryFactory.GetVirtualBoundary(vbType, _tissue, detectorController);
                    _virtualBoundaryController.VirtualBoundaries.Add(virtualBoundary);
                }
            }

            // needed?
            //_detectorControllers = _virtualBoundaryController.VirtualBoundaries.Select(vb=>vb.DetectorController).ToList();

            // set doPMC flag
            if (input.Options.Databases.Any(d => d.IspMCDatabase()))
            {
                doPMC = true;
            }

            _isCancelled      = false;
            _isRunning        = false;
            _resultsAvailable = false;
        }
        //[DllImport(@"Vts.MonteCarlo.Unmanaged.dll", EntryPoint = "RunTest")]
        //public static extern void RunUnmanagedMC(ref UnmanagedPhoton unmanagedPhoton,
        //    ref UnmanagedTissue unmanagedTissue, ref UnmanagedPerturb unmanagedPerturb,
        //    ref UnmanagedOutput unmanagedOutput);

        public UnmanagedMonteCarloSimulation(SimulationInput input)
            : base(input)
        {
        }
Esempio n. 8
0
 /// <summary>
 /// This method checks the input against combined combinations of options
 /// and source, tissue, detector definitions.
 /// </summary>
 /// <param name="input">input to be validated</param>
 /// <returns>ValidationResult with IsValid set and error message if false</returns>
 private static ValidationResult ValidateCombinedInputParameters(SimulationInput input)
 {
     // check that absorption weighting type set to analog and RR weight threshold != 0.0
     if ((input.Options.AbsorptionWeightingType == AbsorptionWeightingType.Analog) &&
         input.Options.RussianRouletteWeightThreshold != 0.0)
     {
         return(new ValidationResult(
                    false,
                    "Russian Roulette cannot be employed with Analog absorption weighting is specified",
                    "With Analog absorption weighting, set Russian Roulette weight threshold = 0.0"));
     }
     // check that if single ellipsoid tissue specified and (r,z) detector specified,
     // that (1) ellipsoid is centered at x=0, y=0, (2) ellipsoid is cylindrically symmetric (dx=dy)
     if (input.TissueInput is SingleEllipsoidTissueInput)
     {
         foreach (var detectorInput in input.DetectorInputs)
         {
             var ellipsoid = (EllipsoidTissueRegion)((SingleEllipsoidTissueInput)input.TissueInput).
                             EllipsoidRegion;
             if (detectorInput.TallyDetails.IsCylindricalTally &&
                 (ellipsoid.Center.X != 0.0) && (ellipsoid.Center.Y != 0.0))
             {
                 return(new ValidationResult(
                            false,
                            "Ellipsoid must be centered at (x,y)=(0,0) for cylindrical tallies",
                            "Change ellipsoid center to (0,0) or specify non-cylindrical type tally"));
             }
             if (detectorInput.TallyDetails.IsCylindricalTally && (ellipsoid.Dx != ellipsoid.Dy))
             {
                 return(new ValidationResult(
                            false,
                            "Ellipsoid must have Dx=Dy for cylindrical tallies",
                            "Change ellipsoid.Dx to be = to Dy or specify non-cylindrical type tally"));
             }
             if (detectorInput.TallyType == "ROfFx")
             {
                 return(new ValidationResult(
                            false,
                            "R(fx) tallies assume a homogeneous or layered tissue geometry",
                            "Change tissue type to be homogeneous or layered"));
             }
         }
     }
     // check that if single voxel or single infinite cylinder tissue specified,
     // cannot specify (r,z) detector
     if ((input.TissueInput is SingleVoxelTissueInput) ||
         (input.TissueInput is SingleInfiniteCylinderTissueInput))
     {
         foreach (var detectorInput in input.DetectorInputs)
         {
             if (detectorInput.TallyDetails.IsCylindricalTally)
             {
                 return(new ValidationResult(
                            false,
                            "Cannot use Single Voxel Tissue for cylindrical tallies",
                            "Change detector inputs to specify non-cylindrical type tallies"));
             }
             if (detectorInput.TallyType == "ROfFx")
             {
                 return(new ValidationResult(
                            false,
                            "R(fx) tallies assume a homogeneous or layered tissue geometry",
                            "Change tissue type to be homogeneous or layered"));
             }
         }
     }
     // check that if non-normal source defined, that detectors defined are not cylindrical tallies
     // this could be greatly expanded, just an initial start
     if (input.SourceInput is DirectionalPointSourceInput)
     {
         var source = (DirectionalPointSourceInput)input.SourceInput;
         if (source.Direction != new Direction(0, 0, 1))
         {
             foreach (var detectorInput in input.DetectorInputs)
             {
                 if (detectorInput.TallyDetails.IsCylindricalTally)
                 {
                     return(new ValidationResult(
                                false,
                                "If source is angled, cannot define cylindrically symmetric detectors",
                                "Change detector to Cartesian equivalent or define source to be normal"));
                 }
             }
         }
     }
     return(new ValidationResult(
                true,
                "Input options or tissue/detector combinations are valid",
                ""));
 }