gammasimtools 0.6.0__py3-none-any.whl → 0.6.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gammasimtools
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Tools for the Simulation System of the CTA Observatory
5
5
  Author-email: simtools developers <simtools-developer@desy.de>
6
6
  License: BSD 3-Clause License
@@ -1,8 +1,8 @@
1
1
  simtools/__init__.py,sha256=yvx0i5ygbllmMtF2Tzy7pohvhQNH_dBdj0Bt8bKFYpc,231
2
- simtools/_version.py,sha256=2JKwcA-YQ0okV2N-gwTWy_n51igWrPcsKQFm0cnqsvw,411
2
+ simtools/_version.py,sha256=lgiCYGSijhLK71WmuudWf_AyhNAutwQWx2V8bV6a5VQ,411
3
3
  simtools/camera_efficiency.py,sha256=Bx9pCmx1egKzV3gtZKK4F3dea9ShauxqI17XTtCVAaQ,18817
4
4
  simtools/constants.py,sha256=QJr7NvjmyXd-xHd1xP_KuJxRFTeysxRLBYbC5tctE6Y,326
5
- simtools/db_handler.py,sha256=Cks1OIOziZIUh-Bxbmq8nMX99N9CvVN21PKv15iB318,47954
5
+ simtools/db_handler.py,sha256=5MEAK_E__NLHmYn5oJPsgO0D3ZTwWvB2yIKxN9w8hxU,47912
6
6
  simtools/psf_analysis.py,sha256=YnQJh_Xckp_TH5lMLB4EsmoUVIWECshFijYz5-zsBjM,14741
7
7
  simtools/ray_tracing.py,sha256=_MYHzYW4l3dAgUu_X5eKirnX8VYFU81_VwRvtimL8zI,18278
8
8
  simtools/simulator.py,sha256=Cor46oIrpPJebQOMYQkUwIUNyyu3m-4HUh_d5Y40e1k,25974
@@ -57,14 +57,14 @@ simtools/io_operations/io_handler.py,sha256=ZYVAtG7CMOXwMFv4gKSOg3dYdsP-DkvMMaZO
57
57
  simtools/job_execution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  simtools/job_execution/job_manager.py,sha256=oo0Ijj232w0dz7rqkTwsgg3jQhVEelug9aMYBfqBu4I,6050
59
59
  simtools/layout/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
- simtools/layout/array_layout.py,sha256=_qUjyxQ4FX6IzE14c4RiJ9MCkhkizJE0kuOxbSCchyE,30619
60
+ simtools/layout/array_layout.py,sha256=hpYFSdIIaO922V4X1JWvgnREqmTZ3r971fUWZCV5xlw,30997
61
61
  simtools/layout/geo_coordinates.py,sha256=Ect3lioZyMFUfHYeWF9WDMZiVq7YwMaX1f7aHQYmDDQ,5929
62
62
  simtools/layout/telescope_position.py,sha256=fiy9X_c0a9VitFGqXYa2hNQvYQvU_Ohq3M82Jnmscjc,17375
63
63
  simtools/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- simtools/model/array_model.py,sha256=t_-vn1m-0ddnUnqBFRApDAvXtdtnMMRiCB9QoiU5c88,14248
65
- simtools/model/camera.py,sha256=FnKjw5Df88MsAgJieQoQMrw2Mf5XjYdYxhOlBut1gtE,30776
64
+ simtools/model/array_model.py,sha256=cqpHFmMpY_H7DkW5Y-Z52gWD45lWSfV8qYnfSSOz818,14249
65
+ simtools/model/camera.py,sha256=UpFG6AOzocwjN5fpoVvEXSDiGuri_gQP1OKs_amZ_4o,30777
66
66
  simtools/model/mirrors.py,sha256=kHQXCoFfdSykXN1rwnPZorJDqAxU0KJ1gJ8hyQRspEA,8060
67
- simtools/model/model_utils.py,sha256=YrKl96I3pb3WzNkQLlejHMq5w-XwFMvfu5xlsED12P0,3748
67
+ simtools/model/model_utils.py,sha256=3FT5hd8aCnLCmd0FlbOmCjLLa-0sCusclkdgU3w8hGc,2010
68
68
  simtools/model/telescope_model.py,sha256=2Ae9ShuNUycNlTBdKszBRQmuiKIG3gKqCZbotaYSz-U,29313
69
69
  simtools/schemas/data.metaschema.yml,sha256=sTq7g1oNG9ZZs6vaasWHPVDMFkXexepRukiKfh5Cwe8,10053
70
70
  simtools/schemas/metadata.metaschema.yml,sha256=MrGxTkKAaJNqA5WAPLH20ACHvVVuqOrgukJX-kB0tXs,16494
@@ -79,13 +79,13 @@ simtools/simtel/simtel_runner_ray_tracing.py,sha256=q1hoMOBmGikCDjHirNIPL_mkRlF_
79
79
  simtools/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  simtools/utils/general.py,sha256=zlYBVkZ5McTbPHe-eLYaM_rgmFV0fl1u_TEY8OHAKss,26011
81
81
  simtools/utils/geometry.py,sha256=bj7ehKy89HuG0hk0Bc5JkJv_hpDFkfsSx_gV9D5pZjM,6300
82
- simtools/utils/names.py,sha256=rBQ3gTB4yuF6j3okEtvzWonJhKXqXiBC6Qz7d_aSgcU,19843
82
+ simtools/utils/names.py,sha256=sc1DZ9FrAoyfhSgeg4cxrFHfF198KeKG-o7KI5WQH8A,23574
83
83
  simtools/visualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
84
  simtools/visualization/legend_handlers.py,sha256=2Ja0QE7nTDPhvgFjp1yvI_CC3P7peiJzMuqd1I-cFDU,12643
85
- simtools/visualization/visualize.py,sha256=70H1lYtsUNXDYUzUVNRuG-gcdfUO2feplJ0aJhnuQ7I,21813
86
- gammasimtools-0.6.0.dist-info/LICENSE,sha256=idBrtxX6eQcUlG0YBTx-O2RNKNKg1Gidb8OQf9q0X7s,1543
87
- gammasimtools-0.6.0.dist-info/METADATA,sha256=OtOvzOR4FQt8iHWxHX33b_xIcXOGaSMBpEEYAcZ62I8,7888
88
- gammasimtools-0.6.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
89
- gammasimtools-0.6.0.dist-info/entry_points.txt,sha256=2Ph74hJHTVd6n_mDhOfzJzMRnoS_8OO1DvKDyhkhIi0,1770
90
- gammasimtools-0.6.0.dist-info/top_level.txt,sha256=9Yi7Q7aQX6alvpP2YGQtIYo208wdGkXUApHboEdj-ys,9
91
- gammasimtools-0.6.0.dist-info/RECORD,,
85
+ simtools/visualization/visualize.py,sha256=GP6djbTXzAePRszBD8XE9omg8ARNQXlvV-RSJBLMNiI,21815
86
+ gammasimtools-0.6.1.dist-info/LICENSE,sha256=idBrtxX6eQcUlG0YBTx-O2RNKNKg1Gidb8OQf9q0X7s,1543
87
+ gammasimtools-0.6.1.dist-info/METADATA,sha256=ODS_qH_gu9WVV_muqnRfGpgmKh81dsG8yJVk-gqIYP0,7888
88
+ gammasimtools-0.6.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
89
+ gammasimtools-0.6.1.dist-info/entry_points.txt,sha256=2Ph74hJHTVd6n_mDhOfzJzMRnoS_8OO1DvKDyhkhIi0,1770
90
+ gammasimtools-0.6.1.dist-info/top_level.txt,sha256=9Yi7Q7aQX6alvpP2YGQtIYo208wdGkXUApHboEdj-ys,9
91
+ gammasimtools-0.6.1.dist-info/RECORD,,
simtools/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.6.0'
16
- __version_tuple__ = version_tuple = (0, 6, 0)
15
+ __version__ = version = '0.6.1'
16
+ __version_tuple__ = version_tuple = (0, 6, 1)
simtools/db_handler.py CHANGED
@@ -13,7 +13,6 @@ from pymongo.errors import BulkWriteError
13
13
 
14
14
  import simtools.utils.general as gen
15
15
  from simtools.io_operations import io_handler
16
- from simtools.model.model_utils import get_telescope_class
17
16
  from simtools.utils import names
18
17
 
19
18
  __all__ = ["DatabaseHandler"]
@@ -287,8 +286,8 @@ class DatabaseHandler:
287
286
 
288
287
  """
289
288
 
290
- _tel_class = get_telescope_class(telescope_model_name)
291
- _tel_name_converted = names.convert_telescope_model_name_to_yaml(telescope_model_name)
289
+ _tel_class = names.get_telescope_class(telescope_model_name)
290
+ _tel_name_converted = names.convert_telescope_model_name_to_yaml_name(telescope_model_name)
292
291
 
293
292
  if _tel_class == "MST":
294
293
  # MST-FlashCam or MST-NectarCam
@@ -346,7 +345,7 @@ class DatabaseHandler:
346
345
 
347
346
  _site_validated = names.validate_site_name(site)
348
347
  _tel_name_db = self._get_telescope_model_name_for_db(_site_validated, telescope_model_name)
349
- _tel_class = get_telescope_class(telescope_model_name)
348
+ _tel_class = names.get_telescope_class(telescope_model_name)
350
349
 
351
350
  self._logger.debug(f"Tel_name_db: {_tel_name_db}")
352
351
  self._logger.debug(f"Tel_class: {_tel_class}")
@@ -416,12 +416,16 @@ class ArrayLayout:
416
416
 
417
417
  try:
418
418
  return self._corsika_telescope["corsika_sphere_center"][
419
- names.get_telescope_type(tel_name)
419
+ names.get_telescope_class(tel_name)
420
420
  ]
421
421
  except KeyError:
422
422
  self._logger.warning(
423
423
  "Missing definition of CORSIKA sphere center for telescope "
424
- f"{tel_name} of type {names.get_telescope_type(tel_name)}"
424
+ f"{tel_name} of type {names.get_telescope_class(tel_name)}"
425
+ )
426
+ except ValueError:
427
+ self._logger.warning(
428
+ f"Missing definition of CORSIKA sphere center for telescope {tel_name}"
425
429
  )
426
430
 
427
431
  return 0.0 * u.m
@@ -451,7 +455,11 @@ class ArrayLayout:
451
455
  try:
452
456
  tel.name = row["telescope_name"]
453
457
  if "asset_code" not in row:
454
- tel.asset_code = names.get_telescope_type(tel.name)
458
+ try:
459
+ tel.asset_code = names.get_telescope_class(tel.name)
460
+ # asset code is not a valid telescope name; possibly a calibration device
461
+ except ValueError:
462
+ tel.asset_code = tel.name.split("-")[0]
455
463
  except KeyError:
456
464
  pass
457
465
  try:
@@ -764,7 +772,7 @@ class ArrayLayout:
764
772
  pos_x, pos_y, pos_z = tel.get_coordinates("ground")
765
773
  try:
766
774
  sphere_radius = self._corsika_telescope["corsika_sphere_radius"][
767
- names.get_telescope_type(tel.name)
775
+ names.get_telescope_class(tel.name)
768
776
  ]
769
777
  except KeyError:
770
778
  self._logger.error("Missing definition of CORSIKA sphere radius")
@@ -882,7 +890,7 @@ class ArrayLayout:
882
890
  telescope_table["radius"] = [
883
891
  u.Quantity(
884
892
  telescope_table.meta["corsika_sphere_radius"][
885
- names.get_telescope_type(tel_name_now)
893
+ names.get_telescope_class(tel_name_now)
886
894
  ]
887
895
  )
888
896
  .to("m")
@@ -156,7 +156,7 @@ class ArrayModel:
156
156
  _all_telescope_model_names = [] # List of telescope names without repetition
157
157
  _all_pars_to_change = {}
158
158
  for tel in self.layout:
159
- tel_size = names.get_telescope_type(tel.name)
159
+ tel_size = names.get_telescope_class(tel.name)
160
160
 
161
161
  # Collecting telescope name and pars to change from array_config_data
162
162
  tel_model_name, pars_to_change = self._get_single_telescope_info_from_array_config(
simtools/model/camera.py CHANGED
@@ -11,11 +11,8 @@ from scipy.spatial import cKDTree as KDTree
11
11
  from scipy.spatial import distance
12
12
 
13
13
  import simtools.visualization.legend_handlers as leg_h
14
- from simtools.model.model_utils import (
15
- get_camera_name,
16
- get_telescope_class,
17
- is_two_mirror_telescope,
18
- )
14
+ from simtools.model.model_utils import is_two_mirror_telescope
15
+ from simtools.utils import names
19
16
  from simtools.utils.geometry import rotate
20
17
 
21
18
  __all__ = ["Camera"]
@@ -51,7 +48,7 @@ class Camera:
51
48
  self._logger = logging.getLogger(__name__)
52
49
 
53
50
  self._telescope_model_name = telescope_model_name
54
- self._camera_name = get_camera_name(self._telescope_model_name)
51
+ _, self._camera_name, _ = names.split_telescope_model_name(telescope_model_name)
55
52
  self._camera_config_file = camera_config_file
56
53
  self._focal_length = focal_length
57
54
  if self._focal_length <= 0:
@@ -743,7 +740,7 @@ class Camera:
743
740
 
744
741
  if self._pixels["pix_id"][i_pix] < pixels_id_to_print + 1:
745
742
  font_size = 4
746
- if get_telescope_class(self._telescope_model_name) == "SCT":
743
+ if names.get_telescope_class(self._telescope_model_name) == "SCT":
747
744
  font_size = 2
748
745
  plt.text(
749
746
  xy_pix_pos[0],
@@ -1,14 +1,11 @@
1
1
  #!/usr/bin/python3
2
2
 
3
- import logging
4
3
  import math
5
4
 
6
5
  from simtools.utils import names
7
6
 
8
7
  __all__ = [
9
8
  "compute_telescope_transmission",
10
- "get_telescope_class",
11
- "get_camera_name",
12
9
  "is_two_mirror_telescope",
13
10
  "split_simtel_parameter",
14
11
  ]
@@ -62,71 +59,6 @@ def compute_telescope_transmission(pars, off_axis):
62
59
  return pars[0] / (1.0 + pars[2] * t ** pars[4])
63
60
 
64
61
 
65
- def get_camera_name(telescope_model_name):
66
- """
67
- Get camera name from the telescope name.
68
-
69
- Parameters
70
- ----------
71
- telescope_model_name: str
72
- Telescope model name (e.g., LST-1).
73
-
74
- Returns
75
- -------
76
- str
77
- Camera name (validated by util.names).
78
- """
79
-
80
- _logger = logging.getLogger(__name__)
81
- camera_name = ""
82
- tel_class, tel_type = names.split_telescope_model_name(telescope_model_name)
83
- if tel_class == "LST":
84
- camera_name = "LST"
85
- elif tel_class == "MST":
86
- if "FlashCam" in tel_type:
87
- camera_name = "FlashCam"
88
- elif "NectarCam" in tel_type:
89
- camera_name = "NectarCam"
90
- else:
91
- _logger.error("Camera not found for MST class telescope")
92
- elif tel_class == "SCT":
93
- camera_name = "SCT"
94
- elif tel_class == "SST":
95
- if "ASTRI" in tel_type:
96
- camera_name = "ASTRI"
97
- elif "GCT" in tel_type:
98
- camera_name = "GCT"
99
- elif "1M" in tel_type:
100
- camera_name = "1M"
101
- else:
102
- camera_name = "SST"
103
- else:
104
- _logger.error("Invalid telescope name - please validate it first")
105
-
106
- camera_name = names.validate_camera_name(camera_name)
107
- _logger.debug(f"Camera name - {camera_name}")
108
- return camera_name
109
-
110
-
111
- def get_telescope_class(telescope_model_name):
112
- """
113
- Get telescope class from telescope name.
114
-
115
- Parameters
116
- ----------
117
- telescope_model_name: str
118
- Telescope model name (ex. LST-1).
119
-
120
- Returns
121
- -------
122
- str
123
- Telescope class (SST, MST, ...).
124
- """
125
-
126
- tel_class, _ = names.split_telescope_model_name(telescope_model_name)
127
- return tel_class
128
-
129
-
130
62
  def is_two_mirror_telescope(telescope_model_name):
131
63
  """
132
64
  Check if the telescope is a two mirror design.
@@ -141,7 +73,7 @@ def is_two_mirror_telescope(telescope_model_name):
141
73
  bool
142
74
  True if the telescope is a two mirror one.
143
75
  """
144
- tel_class, tel_type = names.split_telescope_model_name(telescope_model_name)
76
+ tel_class, tel_type, _ = names.split_telescope_model_name(telescope_model_name)
145
77
  if tel_class == "SST":
146
78
  # Only 1M is False
147
79
  return "1M" not in tel_type
simtools/utils/names.py CHANGED
@@ -4,26 +4,27 @@ import re
4
4
  _logger = logging.getLogger(__name__)
5
5
 
6
6
  __all__ = [
7
+ "array_element_id_from_telescope_model_name",
7
8
  "camera_efficiency_log_file_name",
8
9
  "camera_efficiency_results_file_name",
9
10
  "camera_efficiency_simtel_file_name",
10
- "convert_telescope_model_name_to_yaml",
11
+ "convert_telescope_model_name_to_yaml_name",
11
12
  "get_site_from_telescope_name",
12
- "get_telescope_type",
13
- "is_valid_name",
13
+ "get_telescope_class",
14
14
  "layout_telescope_list_file_name",
15
15
  "ray_tracing_file_name",
16
16
  "ray_tracing_plot_file_name",
17
17
  "ray_tracing_results_file_name",
18
+ "sanitize_name",
18
19
  "simtel_array_config_file_name",
20
+ "simtel_single_mirror_list_file_name",
19
21
  "simtel_telescope_config_file_name",
20
- "simtools_instrument_name",
22
+ "get_telescope_name_db",
21
23
  "split_telescope_model_name",
22
- "validate_camera_name",
24
+ "telescope_model_name_from_array_element_id",
25
+ "translate_simtools_to_corsika",
23
26
  "validate_array_layout_name",
24
27
  "validate_model_version_name",
25
- "validate_name",
26
- "validate_simtel_mode_name",
27
28
  "validate_site_name",
28
29
  "validate_sub_system_name",
29
30
  "validate_telescope_id_name",
@@ -49,20 +50,26 @@ all_telescope_class_names = {
49
50
  veritas: ["veritas"],
50
51
  }
51
52
 
52
- all_camera_names = {
53
- "SST": ["sst"],
53
+ all_subsystem_names = {
54
+ "SST": ["sst", "ssts", "SSTS"],
54
55
  "ASTRI": ["astri"],
55
56
  "GCT": ["gct", "gct-s"],
56
57
  "1M": ["1m"],
57
- "FlashCam": ["flashcam", "flash-cam"],
58
- "NectarCam": ["nectarcam", "nectar-cam"],
59
- "SCT": ["sct"],
60
- "LST": ["lst"],
58
+ "FlashCam": ["flashcam", "flash-cam", "msts", "MSTS"],
59
+ "NectarCam": ["nectarcam", "nectar-cam", "mstn", "MSTN"],
60
+ "SCT": ["sct", "scts", "SCTS"],
61
+ "LST": ["lst", "lsts", "LSTS", "lstn", "LSTN"],
62
+ "Camera": ["Camera", "camera"],
63
+ "Structure": ["Structure", "structure"],
64
+ "MAGIC": ["magic", "MAGIC"],
65
+ "VERITAS": ["veritas", "VERITAS"],
66
+ "HESS": ["hess", "HESS"],
61
67
  }
62
68
 
63
- all_structure_names = {"Structure": ["Structure", "structure"]}
64
-
65
- all_site_names = {"South": ["paranal", "south"], "North": ["lapalma", "north"]}
69
+ all_site_names = {
70
+ "South": ["paranal", "south", "cta-south", "ctao-south", "s"],
71
+ "North": ["lapalma", "north", "cta-north", "ctao-north", "n"],
72
+ }
66
73
 
67
74
  all_model_version_names = {
68
75
  "2015-07-21": [""],
@@ -87,16 +94,6 @@ all_model_version_names = {
87
94
  "Latest": [],
88
95
  }
89
96
 
90
- all_simtel_mode_names = {
91
- "RayTracing": ["raytracing", "ray-tracing"],
92
- "RayTracingSingleMirror": [
93
- "raytracing-singlemirror",
94
- "ray-tracing-singlemirror",
95
- "ray-tracing-single-mirror",
96
- ],
97
- "Trigger": ["trigger"],
98
- }
99
-
100
97
  all_array_layout_names = {
101
98
  "4LST": ["4-lst", "4lst"],
102
99
  "1LST": ["1-lst", "1lst"],
@@ -108,8 +105,16 @@ all_array_layout_names = {
108
105
  "TestLayout": ["test-layout"],
109
106
  }
110
107
 
111
- corsika_to_simtools_names = {
112
- "OBSLEV": "corsika_obs_level",
108
+ # array elements as defined by CTAO
109
+ # (includes for now only telescopes;
110
+ # can be extended to other elements)
111
+ all_array_element_id_names = {
112
+ "lstn": ["LSTN", "lstn"],
113
+ "mstn": ["MSTN", "mstn"],
114
+ "lsts": ["LSTS", "lsts"],
115
+ "msts": ["MSTS", "msts"],
116
+ "ssts": ["SSTS", "ssts"],
117
+ "scts": ["SCTS", "scts"],
113
118
  }
114
119
 
115
120
 
@@ -127,24 +132,24 @@ def validate_sub_system_name(name):
127
132
  str
128
133
  Validated name.
129
134
  """
130
- return validate_name(name, {**all_camera_names, **all_structure_names})
135
+ return _validate_name(name, all_subsystem_names)
131
136
 
132
137
 
133
- def validate_camera_name(name):
138
+ def validate_telescope_class_name(name):
134
139
  """
135
- Validate a camera name.
140
+ Validate a telescope class name (LST, MST, SST, ...).
136
141
 
137
142
  Parameters
138
143
  ----------
139
144
  name: str
140
- Camera name
145
+ Telescope class name.
141
146
 
142
147
  Returns
143
148
  -------
144
149
  str
145
150
  Validated name.
146
151
  """
147
- return validate_name(name, all_camera_names)
152
+ return _validate_name(name, all_telescope_class_names)
148
153
 
149
154
 
150
155
  def validate_telescope_id_name(name):
@@ -153,11 +158,11 @@ def validate_telescope_id_name(name):
153
158
 
154
159
  Valid names e.g.,
155
160
  - D
156
- - telescope ID
161
+ - telescope ID (e.g., 1, 5, 15)
157
162
 
158
163
  Parameters
159
164
  ----------
160
- name: str
165
+ name: str or int
161
166
  Telescope ID name.
162
167
 
163
168
  Returns
@@ -171,8 +176,8 @@ def validate_telescope_id_name(name):
171
176
  If name is not valid.
172
177
  """
173
178
 
174
- if name == "D" or name.isdigit():
175
- return name
179
+ if isinstance(name, int) or name.upper() in ("D", "D234", "TEST") or name.isdigit():
180
+ return str(name).upper()
176
181
 
177
182
  msg = f"Invalid telescope ID name {name}"
178
183
  _logger.error(msg)
@@ -193,24 +198,7 @@ def validate_model_version_name(name):
193
198
  str
194
199
  Validated name.
195
200
  """
196
- return validate_name(name, all_model_version_names)
197
-
198
-
199
- def validate_simtel_mode_name(name):
200
- """
201
- Validate a sim_telarray mode name.
202
-
203
- Parameters
204
- ----------
205
- name: str
206
- sim_telarray mode name.
207
-
208
- Returns
209
- -------
210
- str
211
- Validated name.
212
- """
213
- return validate_name(name, all_simtel_mode_names)
201
+ return _validate_name(name, all_model_version_names)
214
202
 
215
203
 
216
204
  def validate_site_name(name):
@@ -227,7 +215,7 @@ def validate_site_name(name):
227
215
  str
228
216
  Validated name.
229
217
  """
230
- return validate_name(name, all_site_names)
218
+ return _validate_name(name, all_site_names)
231
219
 
232
220
 
233
221
  def validate_array_layout_name(name):
@@ -244,10 +232,10 @@ def validate_array_layout_name(name):
244
232
  str
245
233
  Validated name.
246
234
  """
247
- return validate_name(name, all_array_layout_names)
235
+ return _validate_name(name, all_array_layout_names)
248
236
 
249
237
 
250
- def validate_name(name, all_names):
238
+ def _validate_name(name, all_names):
251
239
  """
252
240
  Validate a name given the all_names options. For each key in all_names, a list of options is \
253
241
  given. If name is in this list, the key name is returned.
@@ -269,7 +257,7 @@ def validate_name(name, all_names):
269
257
  If name is not valid.
270
258
  """
271
259
 
272
- if not is_valid_name(name, all_names):
260
+ if not _is_valid_name(name, all_names):
273
261
  msg = f"Invalid name {name}"
274
262
  raise ValueError(msg)
275
263
  for main_name, list_of_names in all_names.items():
@@ -280,7 +268,7 @@ def validate_name(name, all_names):
280
268
  return None
281
269
 
282
270
 
283
- def is_valid_name(name, all_names):
271
+ def _is_valid_name(name, all_names):
284
272
  """
285
273
  Check if name is valid.
286
274
 
@@ -320,27 +308,27 @@ def validate_telescope_model_name(name):
320
308
  Validated name.
321
309
  """
322
310
 
323
- tel_class, tel_type = split_telescope_model_name(name)
324
- tel_class = validate_name(tel_class, all_telescope_class_names)
325
- if "flashcam" in tel_type:
326
- tel_type = tel_type.replace("flashcam", "FlashCam")
327
- if "nectarcam" in tel_type:
328
- tel_type = tel_type.replace("nectarcam", "NectarCam")
329
- if "1m" in tel_type:
330
- tel_type = tel_type.replace("1m", "1M")
331
- if "gct" in tel_type:
332
- tel_type = tel_type.replace("gct", "GCT")
333
- if "astri" in tel_type:
334
- tel_type = tel_type.replace("astri", "ASTRI")
335
- if "-d" in "-" + tel_type:
336
- tel_type = tel_type.replace("d", "D")
311
+ # e.g, MSTN or MSTN-01
312
+ try:
313
+ return _validate_name(name, all_array_element_id_names)
314
+ except ValueError:
315
+ pass
337
316
 
338
- return tel_class + "-" + tel_type
317
+ # e.g., MST-FlashCam or MST-FlashCam-01
318
+ tel_class, tel_type, tel_id = split_telescope_model_name(name)
319
+ _telescope_name = tel_class
320
+ if tel_class != tel_type and len(tel_type) > 0:
321
+ _telescope_name += "-" + tel_type
322
+ if len(tel_id) > 0:
323
+ _telescope_name += "-" + tel_id
324
+ return _telescope_name
339
325
 
340
326
 
341
327
  def split_telescope_model_name(name):
342
328
  """
343
- Split a telescope name into class and type.
329
+ Split a telescope name into class, type, telescope id.
330
+ Allow various inputs, e.g., MST-FlashCam-01, MST-FlashCam,
331
+ MSTN-01, MSTN, MST-1
344
332
 
345
333
  Parameters
346
334
  ----------
@@ -349,14 +337,44 @@ def split_telescope_model_name(name):
349
337
 
350
338
  Returns
351
339
  -------
352
- str, str
353
- class (LST, MST, SST ...) and type (any complement).
340
+ str, str, str
341
+ class (LST, MST, SST ...), type (any complement), telescope id
354
342
  """
355
-
356
343
  name_parts = name.split("-")
344
+ # e.g., MSTN or MSTN-01
345
+ try:
346
+ _is_valid_name(name_parts[0], all_array_element_id_names)
347
+ return (
348
+ validate_telescope_class_name(name_parts[0][0:3]),
349
+ validate_sub_system_name(name_parts[0]),
350
+ validate_telescope_id_name(name_parts[1]) if len(name_parts) > 1 else "",
351
+ )
352
+ except ValueError:
353
+ pass
354
+
355
+ # e.g., MST-FlashCam or MST-FlashCam-01, MST-1
356
+ # (note that this complicated, as LST-1 is a valid
357
+ # name without explicit subsystem given in name)
357
358
  tel_class = name_parts[0]
358
- tel_type = "-".join(name_parts[1:])
359
- return tel_class, tel_type
359
+ try:
360
+ tel_id = validate_telescope_id_name(name_parts[-1])
361
+ _tmp_tel_type = name_parts[1:-1]
362
+ except ValueError:
363
+ tel_id = ""
364
+ _tmp_tel_type = name_parts[1:]
365
+ if len(_tmp_tel_type) > 0:
366
+ tel_type = "-".join(_tmp_tel_type)
367
+ else:
368
+ try:
369
+ tel_type = validate_sub_system_name(tel_class)
370
+ except ValueError:
371
+ tel_type = ""
372
+
373
+ return (
374
+ validate_telescope_class_name(tel_class),
375
+ validate_sub_system_name(tel_type) if len(tel_type) > 0 else "",
376
+ validate_telescope_id_name(tel_id) if len(tel_id) > 0 else "",
377
+ )
360
378
 
361
379
 
362
380
  def get_site_from_telescope_name(name):
@@ -373,12 +391,20 @@ def get_site_from_telescope_name(name):
373
391
  str
374
392
  Site name (South or North).
375
393
  """
394
+ # e.g, MSTN or MSTN-01 (tested by get_telescope_class)
395
+ try:
396
+ get_telescope_class(name)
397
+ return validate_site_name(name[3])
398
+ except ValueError:
399
+ pass
400
+ # e.g., South-MST-FlashCam
376
401
  return validate_site_name(name.split("-")[0])
377
402
 
378
403
 
379
404
  def validate_telescope_name_db(name):
380
405
  """
381
406
  Validate a telescope DB name.
407
+ Examples are North-LST-1, North-MST-NectarCam-D, or South-SST-Structure-D.
382
408
 
383
409
  Parameters
384
410
  ----------
@@ -395,7 +421,7 @@ def validate_telescope_name_db(name):
395
421
  return f"{validate_site_name(site)}-{validate_telescope_model_name(tel_model_name)}"
396
422
 
397
423
 
398
- def convert_telescope_model_name_to_yaml(name):
424
+ def convert_telescope_model_name_to_yaml_name(name):
399
425
  """
400
426
  Get telescope name following the old convention (yaml files) from the current telescope name.
401
427
 
@@ -414,8 +440,9 @@ def convert_telescope_model_name_to_yaml(name):
414
440
  ValueError
415
441
  if name is not valid.
416
442
  """
417
- tel_class, tel_type = split_telescope_model_name(name)
418
- new_name = tel_class + "-" + tel_type
443
+ tel_class, tel_type, tel_id = split_telescope_model_name(name)
444
+ new_name = tel_class if tel_class == tel_type else tel_class + "-" + tel_type
445
+ new_name = new_name + "-" + tel_id if len(tel_id) > 0 else new_name
419
446
  old_names = {
420
447
  "SST-D": "SST",
421
448
  "SST-1M": "SST-1M",
@@ -429,14 +456,97 @@ def convert_telescope_model_name_to_yaml(name):
429
456
  }
430
457
 
431
458
  if new_name not in old_names:
432
- raise ValueError(f"Telescope name {name} could not be converted to yml names")
459
+ raise ValueError(f"Telescope name {name}/{new_name} could not be converted to yml names")
433
460
 
434
461
  return old_names[new_name]
435
462
 
436
463
 
437
- def simtools_instrument_name(site, telescope_class_name, sub_system_name, telescope_id_name):
464
+ def array_element_id_from_telescope_model_name(site, telescope_model_name):
465
+ """
466
+ Array element ID (CTAO convention) from telescope model name.
467
+ This returns e.g., "LSTN" for any LST telescope in the North site.
468
+ If a telescope number is given, it adds it as e.g., "LSTN-01".
469
+
470
+ Parameters
471
+ ----------
472
+ site: str
473
+ Observatory site (e.g., South or North)
474
+ telescope_class_name: str
475
+ Name of the telescope class (e.g. LST-1, LST-D234, MST-FlashCam-D, ...)
476
+
477
+ Returns
478
+ -------
479
+ str
480
+ Array element ID (CTAO style).
481
+
482
+ """
483
+
484
+ _class, _type, _tel_id = split_telescope_model_name(telescope_model_name)
485
+ _id = _class.upper() + site[0].upper()
486
+ if _tel_id.isdigit():
487
+ _id += f"-{int(_tel_id):02d}"
488
+ return _id
489
+
490
+
491
+ def telescope_model_name_from_array_element_id(
492
+ array_element_id, sub_system_name="structure", available_telescopes=None
493
+ ):
494
+ """
495
+ Telescope model name from array element ID (CTAO convention).
496
+ Does not include the site in the returned name (e.g., returns
497
+ South-MST-FlashCam-1 for MSTS-01; this method is quite finetuned).
498
+
499
+ Parameters
500
+ ----------
501
+ array_element_id: str
502
+ Array element ID (CTAO convention).
503
+ available_telescopes: list
504
+ List of available telescopes.
505
+
506
+ Returns
507
+ -------
508
+ str
509
+ Telescope model name.
510
+ """
511
+
512
+ name_parts = array_element_id.split("-")
513
+ try:
514
+ _class = name_parts[0][0:3]
515
+ _site = validate_site_name(name_parts[0][3])
516
+ except IndexError as exc:
517
+ _logger.error("Invalid array element ID %s", array_element_id)
518
+ raise exc
519
+ try:
520
+ _id = int(name_parts[1])
521
+ except (ValueError, IndexError):
522
+ _id = "D"
523
+
524
+ if _class in ("LST", "SCT"):
525
+ sub_system_name = None
526
+ elif _class == "MST" and sub_system_name.lower() == "camera":
527
+ sub_system_name = "NectarCam" if _site == "North" else "FlashCam"
528
+
529
+ _simtools_name = get_telescope_name_db(
530
+ site=_site,
531
+ telescope_class_name=_class,
532
+ sub_system_name=sub_system_name,
533
+ telescope_id_name=_id,
534
+ )
535
+ if available_telescopes is not None and _simtools_name not in available_telescopes:
536
+ _logger.debug("Telescope %s not available", _simtools_name)
537
+ _simtools_name = get_telescope_name_db(
538
+ site=_site,
539
+ telescope_class_name=_class,
540
+ sub_system_name=sub_system_name,
541
+ telescope_id_name="D234" if _site == "North" and _class == "LST" else "D",
542
+ )
543
+ return _simtools_name.split("-", 1)[1]
544
+
545
+
546
+ def get_telescope_name_db(site, telescope_class_name, sub_system_name, telescope_id_name):
438
547
  """
439
548
  Instrument name following simtools naming convention
549
+ Examples are North-LST-1, North-MST-NectarCam-D, or South-SST-Structure-D.
440
550
 
441
551
  Parameters
442
552
  ----------
@@ -444,8 +554,8 @@ def simtools_instrument_name(site, telescope_class_name, sub_system_name, telesc
444
554
  South or North.
445
555
  telescope_class_name: str
446
556
  LST, MST, ...
447
- sub_system_name: str
448
- FlashCam, NectarCam
557
+ sub_system_name: str or None
558
+ FlashCam, NectarCam, Structure
449
559
  telescope_id_name: str
450
560
  telescope ID (e.g., D, numerical value)
451
561
 
@@ -458,9 +568,8 @@ def simtools_instrument_name(site, telescope_class_name, sub_system_name, telesc
458
568
  return (
459
569
  validate_site_name(site)
460
570
  + "-"
461
- + validate_name(telescope_class_name, all_telescope_class_names)
462
- + "-"
463
- + validate_sub_system_name(sub_system_name)
571
+ + _validate_name(telescope_class_name, all_telescope_class_names)
572
+ + ("" if sub_system_name is None else "-" + validate_sub_system_name(sub_system_name))
464
573
  + "-"
465
574
  + validate_telescope_id_name(telescope_id_name)
466
575
  )
@@ -497,7 +606,7 @@ def simtel_telescope_config_file_name(
497
606
  return name
498
607
 
499
608
 
500
- def simtel_array_config_file_name(array_name, site, version, label):
609
+ def simtel_array_config_file_name(array_name, site, model_version, label):
501
610
  """
502
611
  sim_telarray config file name for an array.
503
612
 
@@ -507,7 +616,7 @@ def simtel_array_config_file_name(array_name, site, version, label):
507
616
  Prod5, ...
508
617
  site: str
509
618
  South or North.
510
- version: str
619
+ model_version: str
511
620
  Version of the model.
512
621
  label: str
513
622
  Instance label.
@@ -517,7 +626,7 @@ def simtel_array_config_file_name(array_name, site, version, label):
517
626
  str
518
627
  File name.
519
628
  """
520
- name = f"CTA-{array_name}-{site}-{version}"
629
+ name = f"CTA-{array_name}-{site}-{model_version}"
521
630
  name += f"_{label}" if label is not None else ""
522
631
  name += ".cfg"
523
632
  return name
@@ -783,9 +892,9 @@ def camera_efficiency_log_file_name(site, telescope_model_name, zenith_angle, az
783
892
  return name
784
893
 
785
894
 
786
- def get_telescope_type(telescope_name):
895
+ def get_telescope_class(telescope_name):
787
896
  """
788
- Guess telescope type from name, e.g. "LST", "MST", ...
897
+ Guess telescope class from name, e.g. "LST", "MST", ...
789
898
 
790
899
  Parameters
791
900
  ----------
@@ -798,49 +907,24 @@ def get_telescope_type(telescope_name):
798
907
  Telescope type.
799
908
  """
800
909
 
801
- _tel_class, _ = split_telescope_model_name(telescope_name)
802
- try:
803
- for _class in all_telescope_class_names:
804
- if len(_class) == 3 and _tel_class[0:3] == _class:
805
- return _class
806
- if _tel_class == _class:
807
- return _class
808
- except IndexError:
809
- pass
810
-
811
- return ""
812
-
813
-
814
- def translate_corsika_to_simtools(corsika_par):
815
- """
816
- Translate the name of a CORSIKA parameter to the name used in simtools.
817
-
818
- Parameters
819
- ----------
820
- corsika_par: str
821
- Name of the corsika parameter to be translated.
822
-
823
- """
824
-
825
- try:
826
- return corsika_to_simtools_names[corsika_par]
827
- except KeyError:
828
- msg = f"Translation not found. We will proceed with the original parameter name:\
829
- {corsika_par}."
830
- _logger.debug(msg)
831
- return corsika_par
910
+ _tel_class, _, _ = split_telescope_model_name(telescope_name)
911
+ return _tel_class
832
912
 
833
913
 
834
914
  def translate_simtools_to_corsika(simtools_par):
835
915
  """
836
916
  Translate the name of a simtools parameter to the name used in CORSIKA.
837
917
 
918
+ TODO - this will go with the new simulation model
919
+
838
920
  Parameters
839
921
  ----------
840
922
  simtools_par: str
841
923
  Name of the simtools parameter to be translated.
842
924
  """
843
925
 
926
+ corsika_to_simtools_names = {"OBSLEV": "corsika_obs_level"}
927
+
844
928
  simtools_to_corsika_names = {
845
929
  new_key: new_value for new_value, new_key in corsika_to_simtools_names.items()
846
930
  }
@@ -563,7 +563,7 @@ def get_telescope_patch(name, x, y, radius):
563
563
  Instance of mpatches.Circle.
564
564
  """
565
565
  tel_obj = leg_h.TelescopeHandler()
566
- valid_name = names.get_telescope_type(name)
566
+ valid_name = names.get_telescope_class(name)
567
567
  fill_flag = False
568
568
 
569
569
  x = x.to(u.m)
@@ -647,7 +647,7 @@ def plot_array(telescopes, rotate_angle=0, show_tel_label=False):
647
647
  for tel_type in tel_counters:
648
648
  if tel_type in tel_now["telescope_name"]:
649
649
  tel_counters[tel_type] += 1
650
- i_tel_name = names.get_telescope_type(telescopes[i_tel]["telescope_name"])
650
+ i_tel_name = names.get_telescope_class(telescopes[i_tel]["telescope_name"])
651
651
  patches.append(
652
652
  get_telescope_patch(
653
653
  i_tel_name,