66
77import numbers
88import warnings
9- from typing import Any
9+ from typing import TYPE_CHECKING , Any , Mapping
1010
1111import numpy as np
1212
13- from ._generation_surface import GenerationSurface , generation_surface
13+ from ._generation_surface import CompositeSurface , GenerationSurface
1414from ._powerlaw import PowerLaw
1515from ._spatial import NaturalRateCylinder
16- from ._utils import Column , constcol , get_column , get_table , has_column , has_table
16+ from ._utils import constcol , get_column , get_table , has_column , has_table
1717from ._weighter import Weighter
1818
19+ if TYPE_CHECKING :
20+ from numpy .typing import NDArray
1921
20- def sframe_corsika_surface (table : Any ) -> GenerationSurface :
22+
23+ class CorsikaSurface (GenerationSurface ):
24+ """Represents a surface on which CORSIKA simulation was generated on."""
25+
26+ def get_epdf (self : CorsikaSurface , weight_cols : Mapping [str , NDArray [np .float64 ]]) -> NDArray [np .float64 ]:
27+ """Get the extended pdf of a sample of CORSIKA."""
28+ return (
29+ self .nevents
30+ / weight_cols ["event_weight" ]
31+ * self .power_law .pdf (weight_cols ["energy" ])
32+ * self .spatial .pdf (weight_cols ["cos_zen" ])
33+ )
34+
35+
36+ def sframe_corsika_surface (table : Any ) -> CompositeSurface :
2137 """Inspect the rows of a CORSIKA S-Frame table object to generate a surface object.
2238
2339 This function works on files generated with either triggered CORSIKA or corsika-reader because
2440 `I3PrimaryInjectorInfo` and `I3CorsikaInfo` use exactly the same names for quantities.
2541 """
26- surfaces = []
42+ surfaces = CompositeSurface ()
2743 cylinder_height = get_column (table , "cylinder_height" )
2844 cylinder_radius = get_column (table , "cylinder_radius" )
2945 max_zenith = get_column (table , "max_zenith" )
@@ -39,32 +55,26 @@ def sframe_corsika_surface(table: Any) -> GenerationSurface:
3955 cylinder_radius [i ],
4056 np .cos (max_zenith [i ]),
4157 np .cos (min_zenith [i ]),
42- "cos_zen" ,
4358 )
4459 spectrum = PowerLaw (
4560 power_law_index [i ],
4661 min_energy [i ],
4762 max_energy [i ],
48- "energy" ,
4963 )
5064 oversampling_val = get_column (table , "oversampling" )[i ] if has_column (table , "oversampling" ) else 1
5165 pdgid = int (get_column (table , "primary_type" )[i ])
52- surfaces .append (
53- n_events [i ] * oversampling_val * generation_surface (pdgid , Column ("event_weight" ), spectrum , spatial ),
54- )
55- retval = sum (surfaces )
56- assert isinstance (retval , GenerationSurface )
57- return retval
66+ surfaces .insert (CorsikaSurface (pdgid , n_events [i ] * oversampling_val , spectrum , spatial ))
67+ return surfaces
5868
5969
60- def weight_map_corsika_surface (table : Any ) -> GenerationSurface :
70+ def weight_map_corsika_surface (table : Any ) -> CompositeSurface :
6171 """Inspect the `CorsikaWeightMap` table object of a corsika file to generate a surface object."""
6272 pdgids = sorted (np .unique (get_column (table , "ParticleType" ).astype (int )))
6373
6474 if len (pdgids ) == 0 :
6575 msg = "`CorsikaWeightMap` is empty. SimWeights cannot process this file"
6676 raise RuntimeError (msg )
67- surface : int | GenerationSurface = 0
77+ surface = CompositeSurface ()
6878 for pdgid in pdgids :
6979 mask = pdgid == get_column (table , "ParticleType" )
7080
@@ -73,7 +83,6 @@ def weight_map_corsika_surface(table: Any) -> GenerationSurface:
7383 constcol (table , "CylinderRadius" , mask ),
7484 np .cos (constcol (table , "ThetaMax" , mask )),
7585 np .cos (constcol (table , "ThetaMin" , mask )),
76- "cos_zen" ,
7786 )
7887
7988 primary_spectral_index = round (constcol (table , "PrimarySpectralIndex" , mask ), 6 )
@@ -83,11 +92,9 @@ def weight_map_corsika_surface(table: Any) -> GenerationSurface:
8392 primary_spectral_index ,
8493 constcol (table , "EnergyPrimaryMin" , mask ),
8594 constcol (table , "EnergyPrimaryMax" , mask ),
86- "energy" ,
8795 )
8896 nevents = constcol (table , "OverSampling" , mask ) * constcol (table , "NEvents" , mask )
89- surface += nevents * generation_surface (pdgid , spectrum , spatial )
90- assert isinstance (surface , GenerationSurface )
97+ surface .insert (CorsikaSurface (pdgid , nevents , spectrum , spatial ))
9198 return surface
9299
93100
@@ -145,7 +152,8 @@ def CorsikaWeighter(file_obj: Any, nfiles: float | None = None) -> Weighter: #
145152 )
146153
147154 table = get_table (file_obj , "CorsikaWeightMap" )
148- surface = nfiles * weight_map_corsika_surface (table )
155+ surface = weight_map_corsika_surface (table )
156+ surface .scale (nfiles )
149157 triggered = False
150158
151159 weighter = Weighter ([file_obj ], surface )
0 commit comments