Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 08:28:30

0001 /**
0002  * Regression tests for scintillation-spectrum compatibility with the Opticks
0003  * GPU representation.
0004  *
0005  * Geant4 permits each of `SCINTILLATIONCOMPONENT1`,
0006  * `SCINTILLATIONCOMPONENT2`, and `SCINTILLATIONCOMPONENT3` to use a distinct
0007  * emission spectrum. Opticks currently serializes one inverse CDF shared by
0008  * every timing component, so accepting distinct inputs would silently sample
0009  * the wrong wavelengths. These tests verify that secondary and tertiary
0010  * spectrum differences are rejected in both Debug and Release builds.
0011  */
0012 
0013 #include <cstdlib>
0014 #include <iostream>
0015 #include <stdexcept>
0016 #include <string>
0017 
0018 #include "NP.hh"
0019 #include "NPFold.h"
0020 #include "U4Scint.h"
0021 
0022 namespace
0023 {
0024 /**
0025  * Terminates the test executable with a diagnostic when a requirement fails.
0026  *
0027  * @param condition requirement result
0028  * @param message diagnostic printed when `condition` is false
0029  */
0030 void Require(bool condition, const char* message)
0031 {
0032     if (condition)
0033         return;
0034     std::cerr << "U4ScintSpectrumTest FAILED: " << message << std::endl;
0035     std::exit(EXIT_FAILURE);
0036 }
0037 
0038 /**
0039  * Creates a two-point serialized emission spectrum.
0040  *
0041  * @param secondValue intensity stored at the second energy
0042  * @return newly allocated double-precision property array
0043  */
0044 NP* MakeSpectrum(double secondValue)
0045 {
0046     NP*     spectrum = NP::Make<double>(2, 2);
0047     double* values = spectrum->values<double>();
0048     values[0] = 2.;
0049     values[1] = 1.;
0050     values[2] = 3.;
0051     values[3] = secondValue;
0052     return spectrum;
0053 }
0054 
0055 /**
0056  * Verifies rejection when `SCINTILLATIONCOMPONENT2` differs from component 1.
0057  */
0058 void TestDistinctSecondComponentIsRejected()
0059 {
0060     NPFold fold;
0061     fold.add("SCINTILLATIONCOMPONENT1", MakeSpectrum(2.));
0062     fold.add("SCINTILLATIONCOMPONENT2", MakeSpectrum(3.));
0063 
0064     bool rejected = false;
0065     try
0066     {
0067         U4Scint scint(&fold, "DistinctSecondComponent");
0068     }
0069     catch (const std::runtime_error& error)
0070     {
0071         rejected = std::string(error.what()).find("distinct scintillation component spectra") !=
0072                    std::string::npos;
0073     }
0074     Require(rejected, "distinct second component was accepted");
0075 }
0076 
0077 /**
0078  * Verifies rejection when `SCINTILLATIONCOMPONENT3` differs from components
0079  * 1 and 2.
0080  */
0081 void TestDistinctThirdComponentIsRejected()
0082 {
0083     NPFold fold;
0084     fold.add("SCINTILLATIONCOMPONENT1", MakeSpectrum(2.));
0085     fold.add("SCINTILLATIONCOMPONENT2", MakeSpectrum(2.));
0086     fold.add("SCINTILLATIONCOMPONENT3", MakeSpectrum(3.));
0087 
0088     bool rejected = false;
0089     try
0090     {
0091         U4Scint scint(&fold, "DistinctThirdComponent");
0092     }
0093     catch (const std::runtime_error& error)
0094     {
0095         rejected = std::string(error.what()).find("distinct scintillation component spectra") !=
0096                    std::string::npos;
0097     }
0098     Require(rejected, "distinct third component was accepted");
0099 }
0100 
0101 /**
0102  * Verifies that identical spectra remain supported for all three timing
0103  * components.
0104  */
0105 void TestIdenticalComponentsAreAccepted()
0106 {
0107     NPFold fold;
0108     fold.add("SCINTILLATIONCOMPONENT1", MakeSpectrum(2.));
0109     fold.add("SCINTILLATIONCOMPONENT2", MakeSpectrum(2.));
0110     fold.add("SCINTILLATIONCOMPONENT3", MakeSpectrum(2.));
0111 
0112     bool accepted = false;
0113     try
0114     {
0115         U4Scint scint(&fold, "IdenticalComponents");
0116         accepted = scint.icdf != nullptr;
0117     }
0118     catch (const std::runtime_error&)
0119     {
0120         accepted = false;
0121     }
0122     Require(accepted, "identical component spectra were rejected");
0123 }
0124 
0125 } // namespace
0126 
0127 int main()
0128 {
0129     TestDistinctSecondComponentIsRejected();
0130     TestDistinctThirdComponentIsRejected();
0131     TestIdenticalComponentsAreAccepted();
0132     return 0;
0133 }