artist.optim

Submodules

Classes

KinematicsReconstructor

Initialize the kinematics optimizer.

AngleLoss

Initialize the angle loss.

FocalSpotLoss

Initialize the focal spot loss.

KLDivergenceLoss

Initialize the Kullback-Leibler divergence loss.

Loss

Initialize the base loss.

PixelLoss

Initialize the pixel loss.

VectorLoss

Initialize the vector loss.

MotorPositionsOptimizer

Initialize the motor-positions optimizer.

IdealSurfaceRegularizer

Initialize the regularizer.

SmoothnessRegularizer

Initialize the regularizer.

SurfaceReconstructor

Initialize the surface reconstructor.

EarlyStopping

Initialize the early stopping.

Functions

mean_loss_per_heliostat(→ torch.Tensor)

Calculate the mean loss per heliostat from a loss per sample.

cyclic(→ torch.optim.lr_scheduler.LRScheduler)

Create a cyclic learning rate scheduler.

exponential(→ torch.optim.lr_scheduler.LRScheduler)

Create an exponential learning rate scheduler.

reduce_on_plateau(→ torch.optim.lr_scheduler.LRScheduler)

Create learning rate scheduler that reduces on plateaus.

Package Contents

class artist.optim.KinematicsReconstructor(ddp_setup: artist.util.env.DdpSetup, scenario: artist.scenario.scenario.Scenario, data: dict[str, artist.io.calibration_parser.CalibrationDataParser | list[tuple[str, list[pathlib.Path], list[pathlib.Path]]]], optimization_configuration: dict[str, Any], dni: float | None = None, reconstruction_method: str = constants.kinematics_reconstruction_raytracing, bitmap_resolution: torch.Tensor = torch.tensor([256, 256]))

Initialize the kinematics optimizer.

Parameters

ddp_setupDdpSetup

Information about the distributed environment, process groups, devices, ranks, world size, and heliostat-group-to-ranks mapping.

scenarioScenario

The scenario.

datadict[str, CalibrationDataParser | list[tuple[str, list[pathlib.Path], list[pathlib.Path]]]]

The data parser and the mapping of heliostat name and calibration data.

optimization_configurationdict[str, Any]

Parameters for the optimizer, learning rate scheduler, regularizers, and early stopping.

dnifloat | None

Direct normal irradiance in W/m^2 (default is None which leads to a ray magnitude of 1.0).

reconstruction_methodstr

The reconstruction method. Currently, only reconstruction via ray tracing is implemented.

bitmap_resolutiontorch.Tensor

The resolution of all bitmaps during reconstruction (default is torch.tensor([256, 256])). Shape is [2].

ddp_setup
scenario
data
optimizer_dict
scheduler_dict
dni = None
bitmap_resolution
reconstruct_kinematics(loss_definition: artist.optim.loss.Loss, device: torch.device | None = None) tuple[torch.Tensor, list[Any]]

Reconstruct the kinematic parameters.

Parameters

loss_definitionLoss

The definition of the loss function and pre-processing of the prediction.

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

Returns

torch.Tensor

The final loss of the kinematics reconstruction for each heliostat in each group. Shape is [total_number_of_heliostats_in_scenario].

list[list[dict[str, list[float]]]]

Loss histories over epochs grouped by rank. Outer list: one entry per rank. Inner list: one entry per heliostat group processed on that rank. Each group entry is a dict with key "total_loss" mapping to a list of per-epoch scalar loss values. In non-distributed mode, this is a single-rank container: [local_group_histories].

_reconstruct_kinematics_parameters_with_raytracing(loss_definition: artist.optim.loss.Loss, device: torch.device | None = None) tuple[torch.Tensor, list[list[dict[str, list[float]]]]]

Reconstruct the kinematics parameters using ray tracing.

This reconstruction method optimizes the kinematics parameters by extracting the focal points of calibration images and using heliostat-tracing.

Parameters

loss_definitionLoss

Definition of the loss function and pre-processing of the prediction.

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

Returns

torch.Tensor

The final loss of the kinematics reconstruction for each heliostat in each group. Shape is [total_number_of_heliostats_in_scenario].

list[list[dict[str, list[float]]]]

Loss histories over epochs grouped by rank. Outer list: one entry per rank. Inner list: one entry per heliostat group processed on that rank. Each group entry is a dict with key "total_loss" mapping to a list of per-epoch scalar loss values. In non-distributed mode, this is a single-rank container: [local_group_histories].

class artist.optim.AngleLoss

Bases: Loss

Initialize the angle loss.

__call__(prediction: torch.Tensor, ground_truth: torch.Tensor, **kwargs: Any) torch.Tensor

Compute the cosine similarity between the prediction and ground truth.

Parameters

predictiontorch.Tensor

The predicted values. Shape is [number_of_samples, 4].

ground_truthtorch.Tensor

The ground truth. Shape is [number_of_samples, 4].

**kwargsAny

Keyword arguments.

Returns

torch.Tensor

The summed loss reduced along the specified dimensions. Shape is [number_of_samples].

class artist.optim.FocalSpotLoss(scenario: artist.scenario.scenario.Scenario)

Bases: Loss

Initialize the focal spot loss.

Parameters

scenarioScenario

The scenario.

scenario
__call__(prediction: torch.Tensor, ground_truth: torch.Tensor, **kwargs: Any) torch.Tensor

Compute the focal spot loss.

First the focal spots of the prediction are computed, then the loss is computed and reduced along the specified dimensions.

Parameters

predictiontorch.Tensor

The predicted values. Shape is [number_of_samples, bitmap_resolution_e, bitmap_resolution_u].

ground_truthtorch.Tensor

The ground truth. Shape is [number_of_samples, 4].

**kwargsAny

Keyword arguments. target_area_indices and device are expected keyword arguments for the focal spot loss.

Raises

ValueError

If expected keyword arguments are not passed.

Returns

torch.Tensor

The focal spot loss. Shape is [number_of_samples].

class artist.optim.KLDivergenceLoss

Bases: Loss

Initialize the Kullback-Leibler divergence loss.

__call__(prediction: torch.Tensor, ground_truth: torch.Tensor, **kwargs: Any) torch.Tensor

Compute the Kullback-Leibler divergence loss \(D_{\mathrm{KL}}(P \parallel Q)\).

The elements in the prediction and ground truth are normalized and shifted, to be greater or equal to zero. The KL-divergence is defined by:

\[D_{\mathrm{KL}}(P \parallel Q) = \sum_{x} P(x) \log \frac{P(x)}{Q(x)},\]

where \(P\) is the ground truth distribution and \(Q\) is the approximation or prediction of \(Q\). The KL-divergence is an asymmetric function. Switching \(P\) and \(Q\) has the following effect: \(P \parallel Q\) Penalizes extra mass in the prediction where the ground truth has none. \(Q \parallel P\) Penalizes missing mass in the prediction where the ground truth has mass.

Parameters

predictiontorch.Tensor

The predicted values. Shape is [number_of_samples, bitmap_resolution_e, bitmap_resolution_u].

ground_truthtorch.Tensor

The ground truth. Shape is [number_of_samples, bitmap_resolution_e, bitmap_resolution_u].

**kwargsAny

Keyword arguments. reduction_dimensions is an expected keyword argument for the KL-divergence loss.

Raises

ValueError

If expected keyword arguments are not passed.

Returns

torch.Tensor

The summed KL-divergence loss reduced along the specified dimensions. Shape is [number_of_samples].

class artist.optim.Loss(loss_function: torch.nn.Module)

Initialize the base loss.

Parameters

loss_functiontorch.nn.Module

A torch module implementing a loss.

loss_function
abstractmethod __call__(prediction: torch.Tensor, ground_truth: torch.Tensor, **kwargs: Any) torch.Tensor

Compute the loss.

Parameters

predictiontorch.Tensor

The predicted values. Shape is variable.

ground_truthtorch.Tensor

The ground truth. Shape is variable.

**kwargsAny

Keyword arguments.

Raises

NotImplementedError

This abstract method must be overridden.

class artist.optim.PixelLoss(scenario: artist.scenario.scenario.Scenario)

Bases: Loss

Initialize the pixel loss.

Parameters

scenarioScenario

The scenario.

scenario
__call__(prediction: torch.Tensor, ground_truth: torch.Tensor, **kwargs: Any) torch.Tensor

Compute the pixel loss.

First the predicted bitmaps and the ground truth are normalized, then the loss is computed and reduced along the specified dimensions.

Parameters

predictiontorch.Tensor

The predicted values. Shape is [number_of_samples, bitmap_resolution_e, bitmap_resolution_u].

ground_truthtorch.Tensor

The ground truth. Shape is [number_of_samples, bitmap_resolution_e, bitmap_resolution_u].

**kwargsAny

Keyword arguments. reduction_dimensions, target_area_indices, and device are expected keyword arguments for the pixel loss.

Raises

ValueError

If expected keyword arguments are not passed.

Returns

torch.Tensor

The summed MSE pixel loss reduced along the specified dimensions. Shape is [number_of_samples].

class artist.optim.VectorLoss

Bases: Loss

Initialize the vector loss.

__call__(prediction: torch.Tensor, ground_truth: torch.Tensor, **kwargs: Any) torch.Tensor

Compute the vector loss.

Parameters

predictiontorch.Tensor

The predicted values. Shape is [number_of_samples, ...].

ground_truthtorch.Tensor

The ground truth. Shape is [number_of_samples, ...].

**kwargsAny

Keyword arguments. reduction_dimensions is an expected keyword argument for the vector loss.

Raises

ValueError

If expected keyword arguments are not passed.

Returns

torch.Tensor

The summed MSE vector loss reduced along the specified dimensions. Shape is [number_of_samples].

artist.optim.mean_loss_per_heliostat(loss_per_sample: torch.Tensor, number_of_samples_per_heliostat: int) torch.Tensor

Calculate the mean loss per heliostat from a loss per sample.

Parameters

loss_per_sampletorch.Tensor

Loss per sample. Shape is [number_of_samples].

number_of_samples_per_heliostatint

Number of samples per heliostat.

Returns

torch.Tensor

Loss per heliostat. Shape is [number_of_heliostats].

class artist.optim.MotorPositionsOptimizer(ddp_setup: artist.util.env.DdpSetup, scenario: artist.scenario.scenario.Scenario, optimization_configuration: dict[str, Any], incident_ray_direction: torch.Tensor, target_area_index: int, ground_truth: torch.Tensor, dni: float, bitmap_resolution: torch.Tensor = torch.tensor([256, 256]), epsilon: float = 1e-12, device: torch.device | None = None)

Initialize the motor-positions optimizer.

Parameters

ddp_setupDdpSetup

Information about the distributed environment, process groups, devices, ranks, world size, and heliostat-group-to-ranks mapping.

scenarioScenario

The scenario.

optimization_configurationdict[str, Any]

Parameters for the optimizer, learning rate scheduler, regularizers, and early stopping.

incident_ray_directiontorch.Tensor

Incident ray direction during the optimization. Shape is [4].

target_area_indexint

Index of the target used for the optimization.

ground_truthtorch.Tensor

Desired focal spot or distribution. Shape is [4] or [bitmap_resolution_e, bitmap_resolution_u].

dnifloat

Direct normal irradiance in W/m^2.

bitmap_resolutiontorch.Tensor

Resolution of all bitmaps during optimization (default is torch.tensor([256,256])). Shape is [2].

epsilonfloat

A small value to avoid division by zero (default is 1e-12).

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

ddp_setup
scenario
optimizer_dict
scheduler_dict
constraint_dict
incident_ray_direction
target_area_index
ground_truth
dni
bitmap_resolution
epsilon = 1e-12
optimize(loss_definition: artist.optim.loss.Loss, device: torch.device | None = None) tuple[torch.Tensor, dict[str, list], torch.Tensor, torch.Tensor, torch.Tensor]

Optimize the motor positions.

The motor positions are optimized through a reparameterization to ensure stable training across different heliostats with widely varying initial motor positions and ranges. Motor positions can range from 0 to up to ~80000. Instead of directly optimizing the absolute motor positions, which can differ in magnitudes, an unconstrained parameter is optimized. Directly optimizing the absolute motor positions would have very different effects depending on the scale of the motors. For small initial motor positions (e.g. ~100), a gradient update of size 10 may cause a ~10% relative change, drastically altering the motor positions of this heliostat. For large initial motor positions (e.g. ~50000), the same optimizer step would correspond to only a 0.02% relative change in motor positions, effectively freezing the optimization of this heliostat. This mismatch makes it impossible to choose a single learning rate that works robustly across all heliostats. Reparameterizing the motor positions to be optimized defines the optimizable parameter as:

\[\text{motor\_positions\_optimized} = \tanh( \text{torch.nn.Parameter(optimizable\_parameter)} )\]

The true motor positions can be reconstructed by:

\[\text{motor\_positions} = \text{initial\_motor\_positions} + \text{motor\_positions\_normalized} \cdot \text{scale}\]

where scale defines the range (e.g. up to ~80000) for adjustments. By optimizing reparameterized instead of raw motor positions, every heliostat sees updates of comparable relative magnitude, regardless of the absolute size of its motors positions.

Parameters

loss_definitionLoss

The definition of the loss function and pre-processing of the prediction.

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

Returns

torch.Tensor

Final loss of the motor position optimization.

dict[str, list]

Loss history over epochs, with keys "total_loss", "flux_loss", "local_flux_constraint", "intercept_constraint", "flux_integral_constraint", and "flux_integral". Each value is a list of per-epoch scalar floats.

torch.Tensor

Final intercept factors for each heliostat.

torch.Tensor

Final fraction of rays hitting the target, neglecting blocking effects, for each heliostat.

torch.Tensor

Final fraction of rays not being blocked, for each heliostat.

class artist.optim.IdealSurfaceRegularizer(reduction_dimensions: tuple[int, Ellipsis])

Bases: Regularizer

Initialize the regularizer.

Parameters

reduction_dimensionstuple[int, …]

Dimensions along which to reduce the loss.

__call__(current_control_points: torch.Tensor, original_control_points: torch.Tensor, device: torch.device | None = None, **kwargs: Any) torch.Tensor

Compute the L2 loss between current control points and original control points.

Parameters

current_control_pointstorch.Tensor

The current control points. Shape is [number_of_heliostats, number_of_facets_per_surface, number_of_control_points_u_direction, number_of_control_points_v_direction, 3].

original_control_pointstorch.Tensor

The current control points. Shape is [number_of_heliostats, number_of_facets_per_surface, number_of_control_points_u_direction, number_of_control_points_v_direction, 3].

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

Returns

torch.Tensor

L2 deviation loss per surface.

class artist.optim.SmoothnessRegularizer(reduction_dimensions: tuple[int, Ellipsis])

Bases: Regularizer

Initialize the regularizer.

Parameters

reduction_dimensionstuple[int, …]

Dimensions along which to reduce the loss.

__call__(current_control_points: torch.Tensor, original_control_points: torch.Tensor, device: torch.device | None = None, **kwargs: Any) torch.Tensor

Compute the Laplacian regularization loss.

The loss measures how much each control-point displacement differs from the average of its four immediate neighbors, thereby penalizing localized, non-smooth deformations.

Parameters

current_control_pointstorch.Tensor

The current control points. Shape is [number_of_heliostats, number_of_facets_per_surface, number_of_control_points_u_direction, number_of_control_points_v_direction, 3].

original_control_pointstorch.Tensor

The original control points. Shape is [number_of_heliostats, number_of_facets_per_surface, number_of_control_points_u_direction, number_of_control_points_v_direction, 3].

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

Returns

torch.Tensor

Laplacian regularization loss per surface.

class artist.optim.SurfaceReconstructor(ddp_setup: artist.util.env.DdpSetup, scenario: artist.scenario.scenario.Scenario, data: dict[str, artist.io.calibration_parser.CalibrationDataParser | list[tuple[str, list[pathlib.Path], list[pathlib.Path]]]], optimization_configuration: dict[str, Any], dni: float | None = None, number_of_surface_points: torch.Tensor = torch.tensor([50, 50]), bitmap_resolution: torch.Tensor = torch.tensor([256, 256]), epsilon: float | None = 1e-12, device: torch.device | None = None)

Initialize the surface reconstructor.

Parameters

ddp_setupDdpSetup

Information about the distributed environment, process groups, devices, ranks, world size, and heliostat-group-to-ranks mapping.

scenarioScenario

The scenario.

datadict[str, CalibrationDataParser | list[tuple[str, list[pathlib.Path], list[pathlib.Path]]]]

The data parser and the mapping of heliostat name and calibration data.

optimization_configurationdict[str, Any]

The parameters for the optimizer, learning rate scheduler, early stopping, and constraints.

dnifloat | None

Direct normal irradiance in W/m² used to scale the ray-traced flux (default is None). If None, the HeliostatRayTracer uses its own default.

number_of_surface_pointstorch.Tensor

The number of surface points of the reconstructed surfaces (default is torch.tensor([50, 50])). Shape is [2].

bitmap_resolutiontorch.Tensor

The resolution of all bitmaps during reconstruction (default is torch.tensor([256, 256])). Shape is [2].

epsilonfloat | None

Small numerical offset used to avoid division by zero in the energy constraint (default is 1e-12).

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

ddp_setup
scenario
data
optimizer_dict
scheduler_dict
constraint_dict
number_of_surface_points
dni = None
bitmap_resolution
epsilon = 1e-12
reconstruct_surfaces(loss_definition: artist.optim.loss.Loss, device: torch.device | None = None) tuple[torch.Tensor, list[list[dict[str, list[float]]]]]

Reconstruct NURBS surfaces from bitmaps.

Parameters

loss_definitionLoss

The definition of the loss function and pre-processing of the prediction.

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

Returns

torch.Tensor

The final reconstruction loss per heliostat, one entry per heliostat in the scenario. Shape is [total_number_of_heliostats_in_scenario].

list[list[dict[str, list[float]]]]

Loss histories over epochs grouped by rank.

  • Outer list: one entry per rank.

  • Inner list: one entry per heliostat group processed on that rank.

  • Each group entry is a dict with keys: "total_loss", "flux_loss", "smoothness_regularizer", "ideal_regularizer", "flux_integral", and "flux_integral_constraint". Each value is a list of per-epoch scalar floats.

    In non-distributed mode, this is a single-rank container: [local_group_histories].

static lock_control_points_on_outer_edges(gradients: torch.Tensor, device: torch.device | None = None) torch.Tensor

Lock the u and v values of the control points on the outer edges of each facet.

As the knots of the first and last knots on each facet have full multiplicity, the NURBS surfaces all start and end in control points. If the outer control points are not fixed in their u and v values, the reconstructed surfaces may not be rectangular anymore. To keep them rectangular, this function zeros the gradients of the u and v coordinates of all outer control points.

Parameters

gradientstorch.Tensor

The full control point gradient tensor for all active heliostats. Gradients on the outer edges will be zeroed; interior gradients are returned unchanged. Shape is [number_of_active_heliostats, number_of_facets_per_surface, number_of_control_points_u_direction, number_of_control_points_v_direction, 3].

devicetorch.device | None

The device on which to perform computations or load tensors and models (default is None). If None, ARTIST will automatically select the most appropriate device (CUDA or CPU) based on availability and OS.

Returns

torch.Tensor

The updated gradients. Shape is [number_of_active_heliostats, number_of_facets_per_surface, number_of_control_points_u_direction, number_of_control_points_v_direction, 3].

class artist.optim.EarlyStopping(window_size: int = 10, patience: int = 20, min_improvement: float = 0.0001, relative: bool = True, eps: float = 1e-08)

Initialize the early stopping.

Parameters

window_sizeint

Number of epochs used to estimate loss trend (default is 10).

patienceint

Number of consecutive non-improving windows before stopping (default is 20).

min_improvementfloat

Minimum required improvement over the window to reset patience (default is 1e-4).

relativebool

Indicates whether improvement is normalized by loss magnitude (default is True).

epsfloat

Small value for stability (default is 1e-8).

window_size = 10
patience = 20
min_improvement = 0.0001
relative = True
eps = 1e-08
loss_history: Deque[float]
counter = 0
step(loss: float) bool

Update stopping state.

Parameters

lossfloat

Current loss value.

Returns

bool

True if optimization should stop, otherwise False.

artist.optim.cyclic(optimizer: torch.optim.Optimizer, parameters: dict[str, float]) torch.optim.lr_scheduler.LRScheduler

Create a cyclic learning rate scheduler.

Parameters

optimizerOptimizer

The optimizer.

parametersdict[str, float]

The scheduler parameters.

Returns

LRScheduler

A cyclic learning rate scheduler.

artist.optim.exponential(optimizer: torch.optim.Optimizer, parameters: dict[str, float]) torch.optim.lr_scheduler.LRScheduler

Create an exponential learning rate scheduler.

Parameters

optimizerOptimizer

The optimizer.

parametersdict[str, float]

The scheduler parameters.

Returns

LRScheduler

An exponential learning rate scheduler.

artist.optim.reduce_on_plateau(optimizer: torch.optim.Optimizer, parameters: dict[str, float]) torch.optim.lr_scheduler.LRScheduler

Create learning rate scheduler that reduces on plateaus.

Parameters

optimizerOptimizer

The optimizer.

parametersdict[str, float]

The scheduler parameters.

Returns

LRScheduler

A learning rate scheduler that reduces on plateaus.