template_synthesis.numpy.io module

class template_synthesis.numpy.io.CoreasHDF5(file_path)

Bases: object

The CoreasHDF5 class is a base class for reading in HDF5 files produced by CoREAS.

It extracts the settings used in the CoREAS simulation, like the time resolution and the core position. It also reads in settings from the CORSIKA part, such as the geometry and the magnetic field. These two are available as dictionaries in the coreas_settings and corsika_settings properties. Next to the settings, it is also possible to get in the longitudinal profile of the shower. Furthermore, the class offers a method to read in the time traces of an observer in the HDF5 file.

Note that it returns all quantities in the NRR coordinate system, which is different from the CORSIKA coordinate system.

Parameters:
file_path : str

The path to the CoREAS HDF5 file

property coreas_settings

Get the CoREAS configuration of this simulation. This is contained in a dictionary, with the following keys:

  • core_coordinate: The core position in the NRR coordinate system

  • time_resolution: The time resolution of the simulation

  • automatic_time_boundaries: The automatic time boundaries of the simulation

  • manual_time_boundaries: The manual time boundaries of the simulation

  • n0: The refractive index at sea level

property corsika_settings

Get the CORSIKA configuration of this simulation. This is contained in a dictionary, with the following keys:

  • zenith: The zenith angle of the shower

  • azimuth: The azimuth angle of the shower

  • magnetic_field: The magnetic field vector in the NRR coordinate system

  • observation_level: The observation level of the shower

  • atmosphere_model: The atmosphere model used in the simulation

  • primary_particle: The primary particle used in the simulation

  • primary_energy: The energy of the primary particle

  • thinning_level: The thinning level used in the simulation

filter_trace(trace, f_min, f_max)

Filter a trace between f_min and f_max using the internal time resolution of the simulation.

The function assumes the time samples are on the last axis, but if this dimension does not match the trace length it will check the other axes to see if any other dimension matches the trace length. The filter used is a straightforward bandpass filter, using the bandpass_filter_trace() function.

Parameters:
trace : np.ndarray

The trace to filter. Can be multidimensional.

f_min : float

The lower frequency (in internal units)

f_max : float

The upper frequency (in internal units)

Returns:

filtered_trace – The bandpass filtered trace

Return type:

np.ndarray

static get_long_profile(file)

Get the longitudinal profile of the shower from the HDF5 file.

The profile is read from the “NumberOfParticles” dataset, which sits in the “atmosphere” group.

Parameters:
file

The HDF5 file object

Returns:

long_profile – The longitudinal profile of the shower

Return type:

np.ndarray

get_trace_slice_raw(observer_name)

Get the raw trace (as produced by CoREAS) from an observer in the HDF5.

The trace is converted to the internal coordinate system before being returned.

Parameters:
observer_name : str

The name of the observer as defined in the HDF5 file

Returns:

  • trace_slice_ground (np.ndarray) – The raw trace (on the ground), shaped as (trace_length, 3).

  • trace_time_array (np.ndarray) – The array containing the timings of the samples, shaped as (trace_length,). This is just the first column of the CoREAS output, converted to internal units.

property name

Get the name of the simulation, which is the filename without the extension.

property trace_length

The number of samples in each time trace. This is calculated from the time boundaries (automatic or manual) and the time resolution of the simulation.

class template_synthesis.numpy.io.Shower

Bases: object

The Shower class represents an air shower setup and evolution.

It holds the geometric information for a shower, like the zenith/azimuth, as well as the longitudinal profile. Next to this, it can also store the magnetic field, the atmosphere in which it was simulated, and the core. These variables are used to calculate the radiotools.coordinatesystems.cstrafo object, which can be used to convert between different coordinate systems. The primary use case is to specify the target parameters for a shower in template synthesis.

atmosphere

The atmosphere in which the shower was simulated

Type:

radiotools.atmosphere.models.Atmosphere

core

The position of the core in the NRR coordinate system

Type:

np.ndarray

property azimuth

The azimuth angle of the shower (in internal units). Can be set using geometry.

copy_settings(other)

This convenience method allows to easily copy the settings from another Shower, which is useful when for example creating a target Shower.

Parameters:
other : Shower

The Shower to copy the settings from.

Notes

The settings which are copied from the other shower are:

  • The geometry

  • The magnetic field vector

  • The simulation core

  • The slice grammage

  • The atmosphere

fit_gaisser_hillas()

Fit a Gaisser-Hillas function to the currently loaded longitudinal profile, to determine the parameters like \(X_{max}\) and \(N_{max}\).

Returns:

popt – The parameters of the Gaisser-Hillas function, in the order [N, X0, Xmax, p0, p1, p2] (p0,p1,p2 are the polynomial coefficients in denominator for lambda)

Return type:

np.ndarray

Notes

The Gaisser-Hillas function is defined as:

\[f(X) = N \left( \frac{X - X_0}{X_{max} - X_0} \right)^{\frac{X_{max} - X_0}{\lambda}} \exp\left( \frac{X_{max} - X}{\lambda} \right)\]
property geomagnetic_angle

Calculate the angle between the magnetic field vector and the shower axis

property geometry

Store the zenith and azimuth. These must be provided in the internal unit system!

get_transformer()

Get the transformer object from radiotools which can be used to convert between different coordinate systems. The transformer is cached, so that it is only calculated once. If the geometry or magnetic field vector gets updated, the transformer is reset.

Returns:

transformer – The cstrafo object with the current geometry and magnetic field vector.

Return type:

radiotools.coordinatesystems.cstrafo

property long

The longitudinal profile of the shower. The first column contains the grammage, the second column the sum of positrons and electrons. When setting the longitudinal profile, it is supported to pass in the particle table from CORSIKA. This is checked by looking at the number of columns, ie the second dimension. If this is equal to 10, a CORSIKA particle table is assumed and the third and fourth columns are summed. Otherwise, the profile should have the shape (slices, 2).

property magnet

Magnetic field vector in the NRR coordinate system

property nmax

The \(N_{max}\) of the shower. This results from fitting a GH to the longitudinal profile (ie not set manually).

property slice_grammage

The (slant depth) step width with which the longitudinal profile is sampled. This is inferred from the longitudinal profile when that one is set.

property xmax

The \(X_{max}\) of the shower. This is the result from fitting a GH to the longitudinal profile (not set manually).

property zenith

The zenith angle of the shower (in internal units). Can be set using geometry.

class template_synthesis.numpy.io.SlicedShower(file_path)

Bases: Shower, CoreasHDF5

This class can be used to read in an HDF5 file of sliced CoREAS simulation.

It can read in the traces of all slices for a given antenna and return them in a Numpy array. Note that the implementation assumes that the antenna’s in each slice have the same physical position and are named identically apart from a suffix ‘xN’, where N is the grammage at the bottom of the slice. The antenna names are inferred by splitting the antenna names on the ‘x’ character, taking the first part and adding them all to a set to removes doubles. The number of slices is then calculated as the number of observers in the file, divided by the number of unique antenna names (i.e. the length of the set). Finally, the antenna positions are added to a structured array by looping over all unique antenna names, adding x{slice_grammage} (of which the value is inferred from the longitudinal profiel) at the end and looking at the position attribute. This structured array is then sorted by distance to the core, to ensure consistency across read-ins.

Parameters:
file_path : str

The path to the HDF5 file

antenna_names

The set of all antenna names present in this shower

Type:

set

antenna_array

A structured array containing for each antenna the name and position on ground. It contains the fields ‘name’ and ‘position’.

Type:

np.ndarray

nr_of_slices

The number of slices in the shower

Type:

int

get_antenna_position(ant_names)

Get the position of the antennas in ant_names on the ground.

The position is returned in our coordinate system, where the x-axis points to the magnetic east, the y-axis to the magnetic north and the z-axis up.

Parameters:
ant_names : str or list of str

Either a single antenna names or a list of antenna names for which to retrieve the positions. All names must be present in SlicedShower.antenna_names!

Returns:

antenna_ground – The positions of the antennas in ant_names.

Return type:

np.ndarray

get_antenna_position_showerplane(ant_names)

Get the position of the antennas in ant_names in the shower plane.

The shower plane coordinate system is that from radiotools, so the x-axis points along the \(\vec{v} \times \vec{B}\) direction, the y-axis along \(\vec{v} \times ( \vec{v} \times \vec{B} )\) direction and the z-axis along \(\vec{v}\).

Parameters:
ant_names : str or list of str

Either a single antenna names or a list of antenna names for which to retrieve the positions. All names must be present in SlicedShower.antenna_names!

Returns:

antenna_showerplane – The position of the antennas in the shower plane.

Return type:

np.ndarray

get_trace(ant_name: str, return_start_time: bool = False) tuple[ndarray, ndarray] | tuple[ndarray, ndarray, ndarray]

Get the traces from all slices for a given antenna. The traces are converted to GEO/CE components.

Parameters:
ant_name : str

The name of the antenna. Must be the same as the key in the HDF5!

return_start_time : bool, default=False

If True, an array containing the time of the first sample of each slice is returned

Returns:

  • traces_geo (np.ndarray) – The geomagnetic traces, shaped as (slices, samples)

  • traces_ce (np.ndarray) – The charge-excess traces, shaped as (slices, samples)

  • traces_start_times (np.ndarray (returned only if return_start_times is True)) – The time of the first sample of each trace

get_trace_slice(ant_name, slice_value, return_start_time=False)

Similar to get_trace(), but only gets the traces for a single slice. The traces are converted to GEO/CE components.

Parameters:
slice_value : int

The grammage of the slice. Must exist in the HDF5.

ant_name : str

The name of the antenna. Must be the same as the key in the HDF5!

return_start_time : bool, default=False

If True, an array containing the time of the first sample of each slice is returned

Returns:

  • trace_geo (np.ndarray) – The geomagnetic trace

  • trace_ce (np.ndarray) – The charge-excess trace

  • trace_start_time (np.ndarray (returned only if return_start_times is True)) – The time of the first sample of the trace

get_trace_slice_on_sky(ant_name, slice_value, return_start_time=False)

Similar to get_trace_slice(), but the traces are converted to on-sky components instead of GEO/CE components.

Parameters:
slice_value : int

The grammage of the slice. Must exist in the HDF5.

ant_name : str

The name of the antenna. Must be the same as the key in the HDF5!

return_start_time : bool, default=False

If True, an array containing the time of the first sample of each slice is returned

Returns:

  • trace_geo (np.ndarray) – The geomagnetic trace

  • trace_ce (np.ndarray) – The charge-excess trace

  • trace_start_time (np.ndarray (returned only if return_start_times is True)) – The time of the first sample of the trace

class template_synthesis.numpy.io.SlicedShowerCherenkov(file_path)

Bases: CoreasHDF5, Shower

This class can be used to read in an HDF5 file of sliced CoREAS simulation, where every slice has the same number of antennas.

It differs from SlicedShower in that it does not assume that all observers have the same position. Rather, it only assumes that each slice has the same number of observers. The antenna names are taken to be all observer names in HDF5 (they are still stored in a set, but this should not change anything because the observer names in CoREAS should be unique). The antenna_array is created by looping over all antenna names and extracting the position attribute. It is also sorted by distance to the core, to ensure it is always the same when reading in a shower. To calculate the number of slices, it divides the number of observers by the number of observers whose name ends with the slice grammage extracted from the longitudinal profile.

Its primary use case is for sliced simulation where the antennas where all place under the same Cherenkov angle in each slice.

Parameters:
file_path : str

The path to the HDF5 file

antenna_names

The set of all antenna names present in this shower

Type:

set

antenna_array

A structured array containing for each antenna the name and position on ground. It contains the fields ‘name’ and ‘position’.

Type:

np.ndarray

nr_of_slices

The number of slices in the shower

Type:

int

get_antenna_position(ant_names)

Get the position of the antennas in ant_names on the ground.

The position is returned in our coordinate system, where the x-axis points to the magnetic east, the y-axis to the magnetic north and the z-axis up.

Parameters:
ant_names : str or list of str

Either a single antenna names or a list of antenna names for which to retrieve the positions. All names must be present in SlicedShower.antenna_names!

Returns:

antenna_ground – The positions of the antennas in ant_names.

Return type:

np.ndarray

get_antenna_position_showerplane(ant_names)

Get the position of the antennas in ant_names in the shower plane.

The shower plane coordinate system is that from radiotools, so the x-axis points along the \(\vec{v} \times \vec{B}\) direction, the y-axis along \(\vec{v} \times ( \vec{v} \times \vec{B} )\) direction and the z-axis along \(\vec{v}\).

Parameters:
ant_names : str or list of str

Either a single antenna names or a list of antenna names for which to retrieve the positions. All names must be present in SlicedShower.antenna_names!

Returns:

antenna_showerplane – The position of the antennas in the shower plane.

Return type:

np.ndarray

get_trace_slice(ant_name, slice_gram=None, return_start_time=False)

Retrieves the traces for an observer and converts them to GEO/CE components.

Parameters:
ant_name : str

The name of the observer as used in the HDF5 file

slice_gram : None

This variable is not used, but is kept to mirror the method of SlicedShower, which allows this class to be used in TemplateSynthesis

return_start_time : bool, default=False

If True, an array containing the time of the first sample of each slice is returned

Returns:

  • trace_geo (np.ndarray) – The geomagnetic trace

  • trace_ce (np.ndarray) – The charge-excess trace

  • trace_start_time (np.ndarray (returned only if return_start_times is True)) – The time of the first sample of the trace

template_synthesis.numpy.io.bandpass_filter_trace(trace, trace_sampling, f_min, f_max, sample_axis=0)

Bandpass filter a trace between f_min and f_max. Both should be provided in the internal unit system, just like the trace_sampling parameter. The trace array can be multidimensional, in which case the sample_axis parameter indicates which dimension should be taken as the time samples (ie this parameter is passed on to the np.fft.rfft call).

Parameters:
trace : np.ndarray

The array containing the time traces to be filtered

trace_sampling : float

The sampling interval of the time traces, in internal units

f_min : float

The lower frequency to filter by, in internal units

f_max : float

The upper frequency to filter by, in internal units

sample_axis : int, default=0

The axis of trace which contains the time samples

Returns:

filtered_trace – The filtered traces, in the same shape as trace

Return type:

np.ndarray

Notes

To avoid issues when the maximum of the trace is too close to the edge, all traces are first shifted to have their maxima more or less in the middle. After the filter has been applied, the traces are rolled back so that they are on same time axis as the input traces.