gammasimtools 0.19.0__py3-none-any.whl → 0.21.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/METADATA +1 -3
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/RECORD +54 -51
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/entry_points.txt +3 -3
- simtools/_version.py +2 -2
- simtools/applications/calculate_incident_angles.py +182 -0
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +17 -14
- simtools/applications/db_add_value_from_json_to_db.py +6 -9
- simtools/applications/db_generate_compound_indexes.py +7 -3
- simtools/applications/db_get_file_from_db.py +11 -23
- simtools/applications/derive_psf_parameters.py +58 -39
- simtools/applications/derive_trigger_rates.py +91 -0
- simtools/applications/generate_corsika_histograms.py +7 -184
- simtools/applications/maintain_simulation_model_add_production.py +105 -0
- simtools/applications/plot_simtel_events.py +5 -189
- simtools/applications/print_version.py +8 -7
- simtools/applications/validate_file_using_schema.py +7 -4
- simtools/configuration/commandline_parser.py +17 -11
- simtools/corsika/corsika_histograms.py +81 -0
- simtools/data_model/validate_data.py +8 -3
- simtools/db/db_handler.py +122 -31
- simtools/db/db_model_upload.py +51 -30
- simtools/dependencies.py +10 -5
- simtools/layout/array_layout_utils.py +37 -5
- simtools/model/array_model.py +18 -1
- simtools/model/model_repository.py +118 -63
- simtools/model/site_model.py +25 -0
- simtools/production_configuration/derive_corsika_limits.py +9 -34
- simtools/ray_tracing/incident_angles.py +706 -0
- simtools/ray_tracing/psf_parameter_optimisation.py +999 -565
- simtools/schemas/model_parameter_and_data_schema.metaschema.yml +2 -2
- simtools/schemas/model_parameters/nsb_reference_spectrum.schema.yml +1 -1
- simtools/schemas/model_parameters/nsb_spectrum.schema.yml +22 -29
- simtools/schemas/model_parameters/stars.schema.yml +1 -1
- simtools/schemas/production_tables.schema.yml +5 -0
- simtools/simtel/simtel_config_writer.py +18 -20
- simtools/simtel/simtel_io_event_histograms.py +253 -516
- simtools/simtel/simtel_io_event_reader.py +51 -2
- simtools/simtel/simtel_io_event_writer.py +31 -11
- simtools/simtel/simtel_io_metadata.py +1 -1
- simtools/simtel/simtel_table_reader.py +3 -3
- simtools/simulator.py +1 -4
- simtools/telescope_trigger_rates.py +119 -0
- simtools/testing/log_inspector.py +13 -11
- simtools/utils/geometry.py +20 -0
- simtools/version.py +89 -0
- simtools/{corsika/corsika_histograms_visualize.py → visualization/plot_corsika_histograms.py} +109 -0
- simtools/visualization/plot_incident_angles.py +431 -0
- simtools/visualization/plot_psf.py +673 -0
- simtools/visualization/plot_simtel_event_histograms.py +376 -0
- simtools/visualization/{simtel_event_plots.py → plot_simtel_events.py} +284 -87
- simtools/visualization/visualize.py +1 -3
- simtools/applications/calculate_trigger_rate.py +0 -187
- simtools/applications/generate_sim_telarray_histograms.py +0 -196
- simtools/applications/maintain_simulation_model_add_production_table.py +0 -71
- simtools/simtel/simtel_io_histogram.py +0 -623
- simtools/simtel/simtel_io_histograms.py +0 -556
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.19.0.dist-info → gammasimtools-0.21.0.dist-info}/top_level.txt +0 -0
|
@@ -5,9 +5,7 @@ a gitlab repository ('SimulationModels'). This module provides service
|
|
|
5
5
|
functions to interact with and verify the repository.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import json
|
|
9
8
|
import logging
|
|
10
|
-
import shutil
|
|
11
9
|
from pathlib import Path
|
|
12
10
|
|
|
13
11
|
from simtools.io import ascii_handler
|
|
@@ -136,9 +134,15 @@ def _get_model_parameter_file_path(
|
|
|
136
134
|
)
|
|
137
135
|
|
|
138
136
|
|
|
139
|
-
def
|
|
137
|
+
def generate_new_production(args_dict):
|
|
140
138
|
"""
|
|
141
|
-
|
|
139
|
+
Generate a new production definition (production tables and model parameters).
|
|
140
|
+
|
|
141
|
+
The following steps are performed:
|
|
142
|
+
|
|
143
|
+
- copy of production tables from an existing base model version
|
|
144
|
+
- update production tables with changes defined in a YAML file
|
|
145
|
+
- generate new model parameter entries for changed parameters
|
|
142
146
|
|
|
143
147
|
Parameters
|
|
144
148
|
----------
|
|
@@ -147,85 +151,134 @@ def copy_and_update_production_table(args_dict):
|
|
|
147
151
|
"""
|
|
148
152
|
modifications = ascii_handler.collect_data_from_file(args_dict["modifications"])
|
|
149
153
|
changes = modifications.get("changes", {})
|
|
154
|
+
base_model_version = args_dict["base_model_version"]
|
|
150
155
|
model_version = modifications["model_version"]
|
|
151
156
|
|
|
152
157
|
simulation_models_path = Path(args_dict["simulation_models_path"])
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
target_prod_table_path = simulation_models_path / "productions" / model_version
|
|
158
|
+
source_path = simulation_models_path / "productions" / base_model_version
|
|
159
|
+
target_path = simulation_models_path / "productions" / model_version
|
|
157
160
|
model_parameters_dir = simulation_models_path / "model_parameters"
|
|
161
|
+
patch_update = args_dict.get("patch_update", False)
|
|
158
162
|
|
|
159
|
-
_logger.info(
|
|
160
|
-
f"Copying production tables from {source_prod_table_path} to {target_prod_table_path}"
|
|
161
|
-
)
|
|
163
|
+
_logger.info(f"Copying production tables from {source_path} to {target_path}")
|
|
162
164
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
_apply_changes_to_production_tables(
|
|
166
|
+
source_path,
|
|
167
|
+
target_path,
|
|
168
|
+
changes,
|
|
169
|
+
model_version,
|
|
170
|
+
patch_update,
|
|
171
|
+
)
|
|
168
172
|
|
|
169
|
-
|
|
173
|
+
_apply_changes_to_model_parameters(changes, model_parameters_dir)
|
|
170
174
|
|
|
171
|
-
for telescope, parameters in changes.items():
|
|
172
|
-
for param, param_data in parameters.items():
|
|
173
|
-
if param_data.get("value"):
|
|
174
|
-
_create_new_parameter_entry(telescope, param, param_data, model_parameters_dir)
|
|
175
175
|
|
|
176
|
+
def _apply_changes_to_production_tables(
|
|
177
|
+
source_path, target_path, changes, model_version, patch_update
|
|
178
|
+
):
|
|
179
|
+
"""
|
|
180
|
+
Apply changes to production tables and write them to target directory.
|
|
176
181
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
+
Parameters
|
|
183
|
+
----------
|
|
184
|
+
source_path: Path
|
|
185
|
+
Path to the source production tables.
|
|
186
|
+
target_path: Path
|
|
187
|
+
Path to the target production tables.
|
|
188
|
+
changes: dict
|
|
189
|
+
The changes to be applied.
|
|
190
|
+
model_version: str
|
|
191
|
+
The model version to be set in the JSON data.
|
|
192
|
+
patch_update: bool
|
|
193
|
+
Patch update, copy only tables for changed elements.
|
|
194
|
+
"""
|
|
195
|
+
target_path.mkdir(parents=True, exist_ok=True)
|
|
196
|
+
for file_path in Path(source_path).rglob("*.json"):
|
|
182
197
|
data = ascii_handler.collect_data_from_file(file_path)
|
|
183
|
-
_apply_changes_to_production_table(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
198
|
+
write_to_disk = _apply_changes_to_production_table(
|
|
199
|
+
data, changes, model_version, patch_update
|
|
200
|
+
)
|
|
201
|
+
if write_to_disk:
|
|
202
|
+
ascii_handler.write_data_to_file(data, target_path / file_path.name, sort_keys=True)
|
|
187
203
|
|
|
188
204
|
|
|
189
|
-
def _apply_changes_to_production_table(data, changes, model_version):
|
|
205
|
+
def _apply_changes_to_production_table(data, changes, model_version, patch_update):
|
|
190
206
|
"""
|
|
191
207
|
Recursively apply changes to the new production tables.
|
|
192
208
|
|
|
193
209
|
Parameters
|
|
194
210
|
----------
|
|
195
|
-
data: dict
|
|
196
|
-
The
|
|
211
|
+
data: dict
|
|
212
|
+
The data to be updated.
|
|
197
213
|
changes: dict
|
|
198
214
|
The changes to be applied.
|
|
199
215
|
model_version: str
|
|
200
216
|
The model version to be set in the JSON data.
|
|
217
|
+
patch_update: bool
|
|
218
|
+
Patch update, copy only tables for changed elements.
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
bool
|
|
223
|
+
True if data was modified and should be written to disk (patch updates) and always
|
|
224
|
+
for full updates.
|
|
201
225
|
"""
|
|
202
226
|
if isinstance(data, dict):
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
table_name = data["production_table_name"]
|
|
228
|
+
data["model_version"] = model_version
|
|
229
|
+
if table_name in changes:
|
|
230
|
+
data["parameters"] = _update_parameters(
|
|
231
|
+
{} if patch_update else data["parameters"].get(table_name, {}), changes, table_name
|
|
232
|
+
)
|
|
233
|
+
elif patch_update:
|
|
234
|
+
return False
|
|
235
|
+
else:
|
|
236
|
+
raise TypeError(f"Unsupported data type {type(data)} in production table update")
|
|
237
|
+
|
|
238
|
+
return True
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _update_parameters(table_parameters, changes, table_name):
|
|
242
|
+
"""
|
|
243
|
+
Create a new parameters dictionary containing only the parameters for the specified table.
|
|
244
|
+
|
|
245
|
+
Parameters
|
|
246
|
+
----------
|
|
247
|
+
table_parameters: dict
|
|
248
|
+
Parameters for the specific table.
|
|
249
|
+
changes: dict
|
|
250
|
+
The changes to be applied, containing table and parameter information.
|
|
251
|
+
table_name: str
|
|
252
|
+
The name of the production table to filter parameters for.
|
|
253
|
+
|
|
254
|
+
Returns
|
|
255
|
+
-------
|
|
256
|
+
dict
|
|
257
|
+
Dictionary containing only the new/changed parameters for the specified table.
|
|
258
|
+
"""
|
|
259
|
+
updated_parameters_dict = {table_name: table_parameters}
|
|
260
|
+
for param, data in changes[table_name].items():
|
|
261
|
+
version = data["version"]
|
|
262
|
+
_logger.info(f"Setting '{table_name} - {param}' to version {version}")
|
|
263
|
+
updated_parameters_dict[table_name][param] = version
|
|
264
|
+
return updated_parameters_dict
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _apply_changes_to_model_parameters(changes, model_parameters_dir):
|
|
268
|
+
"""
|
|
269
|
+
Apply changes to model parameters by creating new parameter entries.
|
|
270
|
+
|
|
271
|
+
Parameters
|
|
272
|
+
----------
|
|
273
|
+
changes: dict
|
|
274
|
+
The changes to be applied.
|
|
275
|
+
model_parameters_dir: str
|
|
276
|
+
Path to the model parameters directory.
|
|
277
|
+
"""
|
|
278
|
+
for telescope, parameters in changes.items():
|
|
279
|
+
for param, param_data in parameters.items():
|
|
280
|
+
if param_data.get("value"):
|
|
281
|
+
_create_new_parameter_entry(telescope, param, param_data, model_parameters_dir)
|
|
229
282
|
|
|
230
283
|
|
|
231
284
|
def _create_new_parameter_entry(telescope, param, param_data, model_parameters_dir):
|
|
@@ -266,14 +319,16 @@ def _create_new_parameter_entry(telescope, param, param_data, model_parameters_d
|
|
|
266
319
|
json_data["parameter_version"] = _update_model_parameter_version(
|
|
267
320
|
json_data, param_data, param, telescope
|
|
268
321
|
)
|
|
269
|
-
|
|
322
|
+
# important for e.g. nsb_pixel_rate
|
|
323
|
+
if isinstance(json_data["value"], list) and not isinstance(param_data["value"], list):
|
|
324
|
+
json_data["value"] = [param_data["value"]] * len(json_data["value"])
|
|
325
|
+
else:
|
|
326
|
+
json_data["value"] = param_data["value"]
|
|
270
327
|
|
|
271
328
|
new_file_name = f"{param}-{param_data['version']}.json"
|
|
272
329
|
new_file_path = param_dir / new_file_name
|
|
273
330
|
|
|
274
|
-
|
|
275
|
-
json.dump(json_data, f, indent=4)
|
|
276
|
-
f.write("\n")
|
|
331
|
+
ascii_handler.write_data_to_file(json_data, new_file_path, sort_keys=True)
|
|
277
332
|
_logger.info(f"Created new model parameter JSON file: {new_file_path}")
|
|
278
333
|
|
|
279
334
|
|
simtools/model/site_model.py
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
import logging
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
+
import numpy as np
|
|
8
|
+
from astropy import units as u
|
|
9
|
+
|
|
7
10
|
from simtools.model.model_parameter import ModelParameter
|
|
8
11
|
|
|
9
12
|
__all__ = ["SiteModel"]
|
|
@@ -160,3 +163,25 @@ class SiteModel(ModelParameter):
|
|
|
160
163
|
},
|
|
161
164
|
dest=model_directory,
|
|
162
165
|
)
|
|
166
|
+
|
|
167
|
+
def get_nsb_integrated_flux(self, wavelength_min=300 * u.nm, wavelength_max=650 * u.nm):
|
|
168
|
+
"""
|
|
169
|
+
Get the integrated flux for the NSB (Night Sky Background) model.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
float
|
|
174
|
+
Integrated flux value.
|
|
175
|
+
"""
|
|
176
|
+
table = self.db.get_ecsv_file_as_astropy_table(
|
|
177
|
+
file_name=self.get_parameter_value("nsb_spectrum")
|
|
178
|
+
)
|
|
179
|
+
table.sort("wavelength")
|
|
180
|
+
wl = table["wavelength"].quantity.to(u.nm)
|
|
181
|
+
rate = table["differential photon rate"].quantity.to(1 / (u.nm * u.cm**2 * u.ns * u.sr))
|
|
182
|
+
mask = (wl >= wavelength_min) & (wl <= wavelength_max)
|
|
183
|
+
integral_cm2 = np.trapezoid(rate[mask], wl[mask])
|
|
184
|
+
self._logger.debug(
|
|
185
|
+
f"NSB integral between {wavelength_min} and {wavelength_max}: {integral_cm2}"
|
|
186
|
+
)
|
|
187
|
+
return integral_cm2.value
|
|
@@ -9,8 +9,9 @@ from astropy.table import Column, Table
|
|
|
9
9
|
|
|
10
10
|
from simtools.data_model.metadata_collector import MetadataCollector
|
|
11
11
|
from simtools.io import ascii_handler, io_handler
|
|
12
|
-
from simtools.
|
|
12
|
+
from simtools.layout.array_layout_utils import get_array_elements_from_db_for_layouts
|
|
13
13
|
from simtools.simtel.simtel_io_event_histograms import SimtelIOEventHistograms
|
|
14
|
+
from simtools.visualization import plot_simtel_event_histograms
|
|
14
15
|
|
|
15
16
|
_logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
@@ -27,7 +28,7 @@ def generate_corsika_limits_grid(args_dict, db_config=None):
|
|
|
27
28
|
Database configuration dictionary.
|
|
28
29
|
"""
|
|
29
30
|
if args_dict.get("array_layout_name"):
|
|
30
|
-
telescope_configs =
|
|
31
|
+
telescope_configs = get_array_elements_from_db_for_layouts(
|
|
31
32
|
args_dict["array_layout_name"],
|
|
32
33
|
args_dict.get("site"),
|
|
33
34
|
args_dict.get("model_version"),
|
|
@@ -92,9 +93,11 @@ def _process_file(file_path, array_name, telescope_ids, loss_fraction, plot_hist
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
if plot_histograms:
|
|
95
|
-
|
|
96
|
+
plot_simtel_event_histograms.plot(
|
|
97
|
+
histograms.histograms,
|
|
96
98
|
output_path=io_handler.IOHandler().get_output_directory(),
|
|
97
99
|
limits=limits,
|
|
100
|
+
array_name=array_name,
|
|
98
101
|
)
|
|
99
102
|
|
|
100
103
|
return limits
|
|
@@ -213,34 +216,6 @@ def _create_table_columns(cols, columns, units):
|
|
|
213
216
|
return table_cols
|
|
214
217
|
|
|
215
218
|
|
|
216
|
-
def _read_array_layouts_from_db(layouts, site, model_version, db_config):
|
|
217
|
-
"""
|
|
218
|
-
Read array layouts from the database.
|
|
219
|
-
|
|
220
|
-
Parameters
|
|
221
|
-
----------
|
|
222
|
-
layouts : list[str]
|
|
223
|
-
List of layout names to read. If "all", read all available layouts.
|
|
224
|
-
site : str
|
|
225
|
-
Site name for the array layouts.
|
|
226
|
-
model_version : str
|
|
227
|
-
Model version for the array layouts.
|
|
228
|
-
db_config : dict
|
|
229
|
-
Database configuration dictionary.
|
|
230
|
-
|
|
231
|
-
Returns
|
|
232
|
-
-------
|
|
233
|
-
dict
|
|
234
|
-
Dictionary mapping layout names to telescope IDs.
|
|
235
|
-
"""
|
|
236
|
-
site_model = SiteModel(site=site, model_version=model_version, mongo_db_config=db_config)
|
|
237
|
-
layout_names = site_model.get_list_of_array_layouts() if layouts == ["all"] else layouts
|
|
238
|
-
layout_dict = {}
|
|
239
|
-
for layout_name in layout_names:
|
|
240
|
-
layout_dict[layout_name] = site_model.get_array_elements_for_layout(layout_name)
|
|
241
|
-
return layout_dict
|
|
242
|
-
|
|
243
|
-
|
|
244
219
|
def _compute_limits(hist, bin_edges, loss_fraction, limit_type="lower"):
|
|
245
220
|
"""
|
|
246
221
|
Compute the limits based on the loss fraction.
|
|
@@ -294,7 +269,7 @@ def compute_lower_energy_limit(histograms, loss_fraction):
|
|
|
294
269
|
"""
|
|
295
270
|
energy_min = (
|
|
296
271
|
_compute_limits(
|
|
297
|
-
histograms.histograms
|
|
272
|
+
histograms.histograms["energy"]["histogram"],
|
|
298
273
|
histograms.energy_bins,
|
|
299
274
|
loss_fraction,
|
|
300
275
|
limit_type="lower",
|
|
@@ -336,7 +311,7 @@ def compute_upper_radius_limit(histograms, loss_fraction):
|
|
|
336
311
|
"""
|
|
337
312
|
radius_limit = (
|
|
338
313
|
_compute_limits(
|
|
339
|
-
histograms.histograms
|
|
314
|
+
histograms.histograms["core_distance"]["histogram"],
|
|
340
315
|
histograms.core_distance_bins,
|
|
341
316
|
loss_fraction,
|
|
342
317
|
limit_type="upper",
|
|
@@ -374,7 +349,7 @@ def compute_viewcone(histograms, loss_fraction):
|
|
|
374
349
|
"""
|
|
375
350
|
viewcone_limit = (
|
|
376
351
|
_compute_limits(
|
|
377
|
-
histograms.histograms
|
|
352
|
+
histograms.histograms["angular_distance"]["histogram"],
|
|
378
353
|
histograms.view_cone_bins,
|
|
379
354
|
loss_fraction,
|
|
380
355
|
limit_type="upper",
|