Analysis

class ledsa.analysis.ExtinctionCoefficients.ExtinctionCoefficients(experiment, reference_property='sum_col_val', num_ref_imgs=10, ref_img_indices=None, average_images=False, n_summarize=2, temperature_correction=None)[source]

Bases: ABC

Parent class for the calculation of the Extinction Coefficients.

Variables:
  • coefficients_per_image_and_layer (list[np.ndarray]) – List of coefficients for each image and layer.

  • experiment (Experiment) – Object representing the experimental setup.

  • reference_property (str) – Reference property to be analysed.

  • num_ref_imgs (int) – Number of reference images. # TODO: create test for this

  • ref_img_indices (list[int] or None) – Indices of reference images to use. If None, use num_ref_imgs.

  • ref_img_ids_of_loaded_data (list[int] or None) – Indices the reference images carry in the loaded image data. They differ from ref_img_indices when the averaged data are loaded, which are numbered from 1 again.

  • calculated_img_data (pd.DataFrame) – DataFrame containing calculated image data.

  • distances_per_led_and_layer (np.ndarray) – Array of distances traversed between camera and LEDs in each layer.

  • ref_intensities (np.ndarray) – Array of reference intensities for all LEDs.

  • cc_matrix (np.ndarray or None) – Color correction matrix.

  • average_images (bool) – Flag to determine if intensities are computed as an average from two consecutive images.

  • n_summarize (int) – Number of consecutive images summarized into one when averaging.

  • temperature_correction (TemperatureCorrection or None) – Reduction factors of the LED intensities over time and height, None for an analysis without the temperature correction.

  • temperature_corrected (bool) – Whether the reduction factors have been divided out of the loaded data.

  • solver – Indication whether the calculation is to be carried out numerically or analytically.

apply_color_correction(cc_matrix, on='sum_col_val', nchannels=3) → None[source]

Apply color correction on channel values based on color correction matrix.

Parameters:
  • cc_matrix (np.ndarray) – Color correction matrix.

  • on (str) – Reference property to apply the color correction on.

  • nchannels (int) – Number of channels.

apply_temperature_correction() → None[source]

Divide the reference property by the reduction factor of the time and height of every value.

Does nothing if the channel has no reduction factors configured or if they were divided out already, so that the factors enter the intensities exactly once however often this is called.

The correction runs before the reference intensities are averaged, so that I0 is a corrected intensity as well and the reduction of the reference images cancels out of the relative intensities. The factors are looked up on the (img_id, led_id) index of the loaded data rather than on a positional array, because the LED axis of the intensities is ordered by LED ID while the distance matrix follows the reversed LEDs of the experiment.

Raises:

ValueError – If an image or an LED of the loaded data has no time or height.

calc_and_set_coefficients() → None[source]

Serial calculation of extinction coefficients for every image

calc_and_set_coefficients_mp(cores=4) → None[source]

Uses multiprocessing to calculate and set extinction coefficients.

Parameters:

cores (int) – Number of cores to use.

calc_and_set_ref_intensities() → None[source]

Calculate and set the reference intensities for all LEDs based on the reference images.

Raises:

ValueError – if none of the reference images holds LED data.

abstractmethod calc_coefficients_of_img(rel_intensities: ndarray) → ndarray[source]

Calculate the extinction coefficients for a single image. Needs to be implemented by the child class.

Parameters:

rel_intensities – Array of relative change in intensity of every LED.

Returns:

Array of the computed extinction coefficients

Return type:

np.ndarray

calc_distance_array() → ndarray[source]

Calculate the distances traversed between camera and LEDs in each layer.

Returns:

Array of distances traversed between camera and LEDs in each layer.

Return type:

np.ndarray

load_img_data() → None[source]

Load processed image data from binary file

Raises:

ValueError – If the reference property is not among the columns of the binary data or contains NaN values.

save() → None[source]

Save the computed extinction coefficients to a file.

The file goes into a directory of its solver and its analysed quantity, so that the results of the quantities of one analysis run do not overwrite each other.

set_all_member_variables(save_distances: bool = True) → None[source]

Calculate distance traveled per layer, for every led, load image data from binary file and calculate reference intensities for each LED

Parameters:

save_distances (bool) – If True, write the distance matrix to a text file in the current working directory. Pass False when calling from a stacked context that manages its own distance file.

temperature_correction_info() → str[source]

Note for the result file stating whether the channel of this run is temperature corrected.

Returns:

The channel and the reduction factors it was corrected with, ‘None’ if the intensities were analysed as they were extracted.

Return type:

str

ledsa.analysis.ExtinctionCoefficients.multiindex_series_to_nparray(multi_series: pandas.Series) → ndarray[source]

Convert a multi-index series to a NumPy array.

Parameters:

multi_series (pd.Series) – Series with multi-index to convert.

Returns:

Converted array.

Return type:

np.ndarray

class ledsa.analysis.ExtinctionCoefficientsLinear.ExtinctionCoefficientsLinear(experiment, reference_property='sum_col_val', num_ref_imgs=10, average_images=False, ref_img_indices=None, lambda_reg=0.001, n_summarize=2, temperature_correction=None)[source]

Bases: ExtinctionCoefficients

ExtinctionCoefficientsLinear computes the extinction coefficients by linearizing the Beer–Lambert law. Specifically, using the transformation:

-ln(I_e / I_0) = sum_i (sigma_i * Delta s_{i})

the problem is recast as a linear least squares system that can be solved efficiently. A Tikhonov regularization is added via a finite-difference operator to enforce smoothness in the solution.

Variables:

solver (str) – Type of solver (linear or nonlinear).

calc_coefficients_of_img(rel_intensities: ndarray) → ndarray[source]

Calculate the extinction coefficients for a single image using a linearized approach. This method solves the linear system derived from the Beer-Lambert law using non-negative least squares with Tikhonov regularization.

LEDs whose relative intensity is at or below zero, or not finite, are left out: the intensities are not clipped at zero, so the signal of such an LED has vanished in the noise of the sensor, and it carries no information on the extinction. If no LED is left, the image yields NaN.

Known limitation: where the transmission approaches the read noise of the sensor, the LEDs that are left are those whose noise happened to be positive, so the extinction coefficients come out too low. In single images of the Warsaw fog test V008 this was 5 to 6 % at 1.24 1/m and 24 to 26 % at 1.64 1/m for farbg_sum_col_val, where the transmission of the red LEDs was 0.02 to 0.15 % of I0. For sum_col_val the pedestal of the search areas keeps the relative intensities above zero and limits first, by 21 to 27 % and 36 to 42 %.

Parameters:

rel_intensities (np.ndarray) – Array of relative (normalized) LED intensities (I_e/I_0).

Returns:

Array of the computed extinction coefficients (sigmas).

Return type:

np.ndarray

class ledsa.analysis.ExtinctionCoefficientsNonLinear.ExtinctionCoefficientsNonLinear(experiment, reference_property='sum_col_val', num_ref_imgs=10, ref_img_indices=None, average_images=False, weighting_curvature=0.01, weighting_preference=-0.006, num_iterations=1000, n_summarize=2, temperature_correction=None)[source]

Bases: ExtinctionCoefficients

ExtinctionCoefficientsNonLinear computes the extinction coefficients by directly minimizing the difference between observed and predicted intensities using the Beer-Lambert law:

I_e = I_0 * exp(-sum_i (sigma_i * Delta s_{i}))

A numerical optimization approach is used with regularization terms to enforce smoothness in the solution. The cost function is

rmse(sigma) + weighting_curvature * mean((D2 sigma)^2)
  • weighting_preference * mean(sigma),

where rmse is taken over the LEDs and D2 is the second difference over the layers. Every term is a mean, so the weights keep their meaning for any number of LEDs and layers.

Variables:
  • bounds (list[tuple]) – Bounds for each layer.

  • weighting_preference (float) – Weighting factor for the preference to push the numerical solver to high or low values for the extinction coefficients.

  • weighting_curvature (float) – Weighting factor for the smoothness of the solution.

  • num_iterations (int) – Maximum number of iterations of the numerical solver.

  • curvature_operator (np.ndarray) – Finite difference operator of the second derivative over the layers.

  • solver – Type of solver (linear or nonlinear).

calc_coefficients_of_img(rel_intensities: ndarray) → ndarray[source]

Calculate the extinction coefficients for a single image based on a minimization procedure.

Parameters:

rel_intensities – Array of relative (normalized) LED intensities (I_e/I_0).

Returns:

Array of the computed extinction coefficients (sigmas)

Return type:

np.ndarray

calc_intensities(sigmas: ndarray) → ndarray[source]

Calculate the intensities from a given set of extinction coefficients. This implements the Beer-Lambert law and is called during the minimization of the cost function.

Parameters:

sigmas (np.ndarray) – An array of extinction coefficients (sigma values).

Returns:

An array of the calculated relative intensities (I_e/I_0).

Return type:

np.ndarray

cost_function(sigmas: ndarray, target: ndarray) → float[source]

Calculate the cost based on the difference between the computed intensities and target intensities. The cost function aims to minimize the root mean square error (rmse) between the computed and target intensities, while also considering the smoothness of the solution (curvature) and boundaries of the coefficients (preference).

Parameters:
  • sigmas (np.ndarray) – Extinction coefficients (sigma values).

  • target (np.ndarray) – Target relative intensities (I_e/I_0).

Returns:

Computed cost.

Return type:

float

cost_gradient(sigmas: ndarray, target: ndarray) → ndarray[source]

Calculate the gradient of the cost function with respect to the extinction coefficients.

The minimizer needs the gradient of every term of cost_function(). Left to estimate it from finite differences, it stops at points that are far from the minimum: the intensities fall off exponentially, so the difference quotients are dominated by rounding error, and the stopping criteria of TNC are met long before the solution is reached.

Parameters:
  • sigmas (np.ndarray) – Extinction coefficients (sigma values).

  • target (np.ndarray) – Target relative intensities (I_e/I_0).

Returns:

Gradient of the cost with respect to every extinction coefficient.

Return type:

np.ndarray

ledsa.analysis.ExtinctionCoefficientsNonLinear.second_difference_operator(num_layers: int) → ndarray[source]

Build the finite difference operator of the second derivative over the layers.

Parameters:

num_layers (int) – Number of layers.

Returns:

Matrix that maps the extinction coefficients to their second differences. It has no rows if fewer than three layers are given, which have no second difference.

Return type:

np.ndarray

class ledsa.analysis.Experiment.Camera(pos_x: float, pos_y: float, pos_z: float, pane_distance: float | None = None)[source]

Bases: object

Contains a camera’s position in 3D space.

Variables:
  • pos_x (float) – The x-coordinate of the camera

  • pos_y (float) – The y-coordinate of the camera

  • pos_z (float) – The z-coordinate of the camera

  • pane_distance (float or None) – Distance [m] between the camera and the window pane it looks through into the smoke, None if the smoke reaches the camera. The pane is taken as normal to the line of sight, so the first pane_distance of every line of sight is free of smoke. The transmission of the pane itself is the same in the reference images and cancels in I/I0, and the refraction in a pane with parallel faces shifts the line of sight by less than the thickness of the pane, so neither is taken into account.

pane_distance: float | None = None
pos_x: float
pos_y: float
pos_z: float
class ledsa.analysis.Experiment.Experiment(layers: Layers, led_array: int, camera: Camera, path=PosixPath('.'), channel=0, merge_led_arrays=False)[source]

Bases: object

Represents an experimental setup involving layers, an LED array, and a camera.

Variables:
  • layers (Layers) – The spatial layers involved in the experiment.

  • led_array (int) – The identifier for the LED array.

  • camera (Camera) – The camera involved in the experiment.

  • leds (List[LED]) – List of LED light sources.

  • led_number (int) – Number of LEDs on LED array.

  • path (Path) – File path for experiment data.

  • channel (int) – The camera channel to be analysed.

  • merge_led_arrays (bool) – Whether to merge LED arrays.

calc_smoke_path_start(led: LED) → Tuple[float, float, float][source]

Find the point where the light path between an LED and the camera enters the smoke.

Without a pane, the smoke reaches the camera and the light path starts there. Behind a pane, it starts where the line of sight of the LED crosses the pane, pane_distance away from the camera, because the part between the camera and the pane is free of smoke. The pane is taken as normal to the line of sight. A flat pane normal to the optical axis of the camera is crossed by a line of sight at an angle theta to the axis pane_distance / cos(theta) away from the camera, at 15 degrees 3.5 % farther; this is negligible as long as the pane is close to the camera compared to the LEDs.

Parameters:

led (LED) – The LED light source

Returns:

Global X, Y, Z coordinates of the start of the light path through the smoke

Return type:

Tuple[float, float, float]

Raises:

PaneGeometryError – If the LED is not farther away from the camera than the pane.

calc_traversed_dist_in_plane(led: LED, start: Tuple[float, float, float] | None = None) → ndarray[source]

Calculate the distance traversed by light from an LED in a plane to the camera.

Parameters:
  • led (LED) – The LED light source

  • start (Tuple[float, float, float] or None) – Start of the light path through the smoke, the camera position if None

Returns:

Array of distances traversed in each layer within the plane

Return type:

np.ndarray

calc_traversed_dist_per_layer(led: LED) → ndarray[source]

Calculate the distance traversed by light from an LED through each layer to the camera.

Behind a pane, only the part of the light path between the pane and the LED is traversed in the smoke, see calc_smoke_path_start.

Parameters:

led (LED) – The LED light source

Returns:

Array of distances traversed in each layer

Return type:

np.ndarray

Raises:
calc_traversed_dist_per_layer_with_nonzero_alpha(alpha: float, led: LED, start: Tuple[float, float, float] | None = None) → ndarray[source]

Calculate the distance traversed by light from an LED through each layer to the camera, taking into account a non-zero angle of incidence.

Parameters:
  • alpha (float) – The angle of incidence

  • led (LED) – The LED light source

  • start (Tuple[float, float, float] or None) – Start of the light path through the smoke, the camera position if None

Returns:

Array of distances traversed in each layer considering the angle

Return type:

np.ndarray

calc_traversed_height_in_layer(led_height: float, layer_bot: float, layer_top: float, start_height: float | None = None) → float[source]

Calculate the vertical distance (height) traversed by light from an LED within a layer.

Parameters:
  • led_height (float) – The z-coordinate of the LED

  • layer_bot (float) – The z-coordinate of the bottom of the layer

  • layer_top (float) – The z-coordinate of the top of the layer

  • start_height (float or None) – The z-coordinate of the start of the light path through the smoke, that of the camera if None

Returns:

The vertical distance traversed within the layer

Return type:

float

distance_calculation_is_consistent(distance_per_layer: ndarray, led: LED, silent=True, start: Tuple[float, float, float] | None = None) → bool[source]

Check if the computed distance values for each layer are consistent with the Euclidean distance.

Parameters:
  • distance_per_layer (np.ndarray) – Array of distances traversed in each layer

  • led (LED) – The LED light source

  • silent (bool, optional) – If set to False, prints out debugging information, defaults to True

  • start (Tuple[float, float, float] or None) – Start of the light path through the smoke, the camera position if None

Returns:

True if computations are consistent, False otherwise

Return type:

bool

get_led_ids() → ndarray[source]

Retrieve the IDs for the LEDs involved in the experiment.

Returns:

Array of LED IDs

Return type:

np.ndarray

get_led_positions(ids: ndarray) → List[ndarray][source]

Retrieve the 3D positions for a set of LEDs.

Parameters:

ids (np.ndarray) – Array of LED identifiers

Returns:

List of arrays containing x, y, and z coordinates for each LED

Return type:

List[np.ndarray]

set_leds() → None[source]

Initialize the LED instances involved in the experiment based on loaded data.

exception ledsa.analysis.Experiment.InconsistentDistanceError[source]

Bases: ValueError

The light path of an LED does not add up to its distance from the camera.

The traversed distances are accumulated per layer, so the part of a light path that lies outside the layers is lost. Computing extinction coefficients from such a path would attribute the dimming of the whole path to the layers covering a part of it.

class ledsa.analysis.Experiment.LED(id: int, pos_x: float, pos_y: float, pos_z: float)[source]

Bases: object

Represents a LED light source in 3D space.

Variables:
  • id (int) – The identifier for the LED

  • pos_x (float) – The x-coordinate of the LED

  • pos_y (float) – The y-coordinate of the LED

  • pos_z (float) – The z-coordinate of the LED

id: int
pos_x: float
pos_y: float
pos_z: float
class ledsa.analysis.Experiment.Layer(bottom_border: float, top_border: float)[source]

Bases: object

Represents a spatial layer with a bottom and top border.

Variables:
  • bottom_border (float) – The z-coordinate of the bottom border of the layer

  • top_border (float) – The z-coordinate of the top border of the layer

bottom_border: float
top_border: float
class ledsa.analysis.Experiment.Layers(amount: int, bottom_border: float, top_border: float)[source]

Bases: object

Represents a collection of spatial layers.

Variables:
  • amount (int) – The number of layers

  • bottom_border (float) – The z-coordinate of the bottom-most border of the layers

  • top_border (float) – The z-coordinate of the top-most border of the layers

amount: int
borders: ndarray
bottom_border: float
layers: [<class 'ledsa.analysis.Experiment.Layer'>]
top_border: float
exception ledsa.analysis.Experiment.PaneGeometryError[source]

Bases: ValueError

The window pane in front of the camera does not lie between the camera and an LED.

The light path of an LED through the smoke starts where its line of sight crosses the pane, pane_distance away from the camera. An LED that is not farther away from the camera than the pane has no such crossing.

ledsa.analysis.Experiment.read_pane_distance(config: ConfigParser, section: str, file_name: str) → float | None[source]

Read the distance between a camera and the window pane it looks through into the smoke.

The option pane_distance is optional, so a config file written before it, or one that sets it to None, keeps the light paths reaching the camera through the smoke.

Parameters:
  • config (configparser.ConfigParser) – The loaded config file

  • section (str) – Section holding the options of the camera

  • file_name (str) – Name of the config file, for the error messages

Returns:

The distance [m], None if the option is not set

Return type:

Optional[float]

Raises:

ValueError – If the value is not a finite number of at least 0.

class ledsa.analysis.ExperimentData.ExperimentData(load_config_file=True)[source]

Bases: object

Dataclass containing the data for the extinction coefficient calculation from the experiment_data.txt input file.

Variables:
  • config – Configuration data.

  • config_analysis – Analysis configuration data.

  • camera – Camera data.

  • layers – Layer data.

  • channels – List of channels.

  • led_arrays – List of LED arrays.

  • n_cpus – Number of CPUs.

  • weighting_preference – Weighting preference for nonlinear solver.

  • weighting_curvature – Weighting curvature for nonlinear solver.

  • num_iterations – Number of iterations.

  • num_ref_images – Number of reference images.

  • ref_img_indices – Indices of reference images to use. If None, use num_ref_imgs.

  • average_images – Intensities are computed as an average from consecutive images.

  • n_summarize – Number of consecutive images summarized into one when averaging.

  • reference_properties – Reference properties to be analysed, one analysis each.

  • reduction_files – Path of the reduction factor file of the temperature correction per camera channel, None for the channels analysed without the correction.

  • merge_led_arrays – Merge LED arrays option.

  • lambda_reg – Regularization parameter for linear solver.

load_config_parameters() → None[source]

Load experiment data from configuration file.

request_config_parameters() → None[source]

Prompts the user to input missing parameters of analysis configuration and updates the configuration.

Correction of the LED intensities for the temperature of the LEDs.

An LED loses radiant power as it heats up, so the LEDs in the hot gas layer dim over the course of an experiment without any smoke between them and the camera. Left uncorrected, that drift enters the relative intensities as an extinction that is not there.

The factors the intensities are reduced by are measured or modelled outside LEDSA and read from one file per camera channel, as a table of the reduction factor over the experiment time and the height of the LED. LEDSA interpolates that table bilinearly to the time of every image and the height of every LED and divides the intensities by it, so that an uncorrected analysis is what it was before.

The interpolation stays between the tabulated times and heights. The table states where the reduction of the LEDs was determined, so an image or an LED outside it is left exactly as it was extracted rather than corrected with a factor the measurement does not cover.

class ledsa.analysis.temperature_correction.TemperatureCorrection(times: ndarray, heights: ndarray, factors: ndarray, source: str = '')[source]

Bases: object

Reduction factors of the LED intensities over the experiment time and the height of the LED.

Variables:
  • times (np.ndarray) – Experiment times [s] of the table, ascending.

  • heights (np.ndarray) – LED heights [m] of the table, ascending.

  • factors (np.ndarray) – Reduction factor of every time and height, indexed as [time, height].

  • source (str) – Name of the file the factors were read from, for the result file header.

factors_at(times: ndarray, heights: ndarray) → ndarray[source]

Reduction factor of every pair of a time and a height, interpolated bilinearly.

The factors are interpolated between the tabulated times and heights only. A time or a height the table does not cover gets UNCORRECTED_FACTOR, which leaves the intensity as it was extracted, because the table states where the reduction of the LEDs was determined and there is nothing outside it to extrapolate from.

Parameters:
  • times (np.ndarray) – Experiment time [s] of every value to correct, counted from start_time of config.ini like the Experiment_Time[s] of the image infos file the times are read from.

  • heights (np.ndarray) – Height [m] of the LED of every value to correct.

Returns:

The reduction factor of every value, in the order of the arguments.

Return type:

np.ndarray

classmethod from_file(file_path: str | Path) → TemperatureCorrection[source]

Read the reduction factors from a CSV file, in either of two layouts.

As a table, the first column holds the experiment time [s], the header of the other columns the height [m] of the LEDs the factors apply to, and every cell the factor the intensity of its time and height is reduced by. The name of the first column is not read, so any label can be used for it.

As a list, the file has the three columns named in LONG_FORMAT_COLUMNS in any order and one row per pair of a height and a time, which is pivoted into the same table.

Neither layout has to be sorted in either of its axes.

Parameters:

file_path (str or Path) – Path of the reduction factor file.

Returns:

The reduction factors, ready to be interpolated.

Return type:

TemperatureCorrection

Raises:
  • FileNotFoundError – If the file does not exist.

  • ValueError – If the file is not a table of numbers with at least two times and two heights, or if it holds a factor that is not positive.

ledsa.analysis.temperature_correction.load_temperature_corrections(file_paths_per_channel: Dict[int, str | None]) → Dict[int, TemperatureCorrection][source]

Read the reduction factor file of every channel that has one configured.

The files are read before the first coefficient is computed, so that an unreadable one stops the run right away instead of in the middle of it.

Parameters:

file_paths_per_channel (dict[int, str or None]) – Path of the reduction factor file of every channel, None for the channels to analyse without the correction.

Returns:

The reduction factors of the channels that are corrected.

Return type:

dict[int, TemperatureCorrection]

Stacked Multi-Camera Analysis

Stacked extinction coefficient computation across multiple cameras/LEDSA runs.

Usage example:

from ledsa.analysis.ConfigDataStacked import ConfigDataStacked
from ledsa.analysis.StackedExtinctionCoefficients import StackedExtinctionCoefficients

cfg = ConfigDataStacked()                    # reads config_stacked.ini

for reference_property in cfg.reference_properties:
    for arr_id in cfg.get_led_array_ids():
        for channel in cfg.camera_channels:
            sec = StackedExtinctionCoefficients(cfg, arr_id, channel, reference_property)
            sec.calc_and_set_coefficients()
            sec.save()
class ledsa.analysis.StackedExtinctionCoefficients.StackedExtinctionCoefficients(config: ConfigDataStacked, led_array_id: int, channel: int, reference_property: str | None = None)[source]

Bases: object

Joint inversion of extinction coefficients using ray data stacked across multiple cameras (LEDSA simulation directories).

For a given virtual LED-array ID and colour channel the class:

  1. Builds one Experiment per (simulation, led_array_id) pair.

  2. Constructs a stacked system matrix by vertically concatenating the per-experiment distance-per-layer matrices and writes it once per virtual array (channel-independent) to <output_path>/.

  3. Computes the common time axis across all simulations, writes a time-alignment report to <output_path>/, and stores it for reuse.

  4. Solves the augmented Beer–Lambert system with the configured solver.

  5. Writes extinction coefficient CSVs to <output_path>/analysis/extinction_coefficients/<solver>/<reference_property>/.

Variables:
  • config (ConfigDataStacked) – Stacked-analysis configuration.

  • led_array_id (int) – Virtual LED-array ID (integer key in [led_arrays]).

  • channel (int) – Colour channel index.

  • reference_property (str) – Quantity the coefficients are computed from.

  • layers (Layers) – Shared layer discretisation.

  • led_array_mapping (dict[int, int]) – {sim_idx: led_array_id} for this virtual array.

  • sub_experiments (list[Experiment]) – Per-simulation Experiment objects.

  • distances_per_led_and_layer (np.ndarray) – Stacked distance matrix (n_leds_total × n_layers).

  • ref_intensities (np.ndarray) – Stacked reference intensities (n_leds_total,).

  • coefficients_per_image_and_layer (list[np.ndarray]) – Computed extinction coefficients.

  • common_times (np.ndarray or None) – Experiment times [s] shared by all simulations.

calc_and_set_coefficients() → None[source]

Compute extinction coefficients for all time-aligned images.

Populates coefficients_per_image_and_layer and common_times.

calc_and_set_coefficients_mp(cores: int | None = None) → None[source]

Parallel computation using multiprocessing.

Parameters:

cores (int or None) – Number of worker processes. Defaults to config.num_cores.

save() → None[source]

Write computed extinction coefficients to CSV.

Output path:

<output_path>/analysis/extinction_coefficients/<solver>/<ref_prop>/
extinction_coefficients_<solver>_channel_<ch>_<ref_prop>_led_array_<id>.csv