Add decliniation line support in production grid#2075
Conversation
There was a problem hiding this comment.
Pull request overview
Adds RA/Dec declination-line support to production grid generation and introduces a new plotting utility to visualize production-grid points in both local Alt/Az and equatorial RA/Dec projections.
Changes:
- Extend
GridGenerationto supportcoordinate_system="ra_dec"with (a) native declination-line/hour-angle sampling and (b) explicit RA/Dec axes mode. - Add
ProductionGridPlotterplus new CLI entrypointsimtools-plot-production-grid, including docs and integration configs. - Add/extend unit tests and test resources for RA/Dec grid generation and production-grid plotting.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/simtools/production_configuration/generate_production_grid.py |
Adds RA/Dec grid generation modes and lookup-table interpolation path for RA/Dec workflows. |
src/simtools/production_configuration/plot_production_grid.py |
New plotting module for production-grid sky projections with optional RA/Dec guide tracks. |
src/simtools/applications/plot_production_grid.py |
New CLI application wiring site metadata + plotter invocation. |
src/simtools/applications/production_generate_grid.py |
Updates CLI docs/help to describe new RA/Dec behavior. |
tests/unit_tests/production_configuration/test_generate_production_grid.py |
Adds RA/Dec-mode unit tests and refactors GridGeneration setup in tests. |
tests/unit_tests/production_configuration/test_plot_production_grid.py |
New unit tests covering normalization, inferred tracks, and output generation. |
tests/resources/production_grid_generation_axes_definition_radec.yml |
New RA/Dec axes definition fixture for tests/integration. |
tests/integration_tests/config/production_generate_grid_radec.yml |
New integration workflow for RA/Dec grid generation. |
tests/integration_tests/config/plot_production_grid.yml |
New integration workflow for plotting production grids. |
docs/source/user-guide/applications/simtools-plot-production-grid.rst |
New user-guide stub for the plotting CLI. |
docs/source/user-guide/applications.md |
Adds the new plotting CLI to the applications list. |
docs/source/api-reference/production_configuration.md |
Adds API docs entry for production_configuration.plot_production_grid. |
pyproject.toml |
Registers simtools-plot-production-grid console script. |
|
@GernotMaier thanks for the review and suggestions. I think I have adressed your points above. This got a bit bigger than I had hoped, but I have changed now all the instances where previously dictionaries where used for the grid points to tables. Time is now optional, and is taken from the grid file metadata, but can be also supplied if one wants to see the coverage in alt/az for a specific time for the given grid points. Naming is improved, tel ids are now consistently used as full name, utc time used, coverage increased . Please let me know if there is anything else. |
GernotMaier
left a comment
There was a problem hiding this comment.
A couple more mostly minor responses, not too much. After that we should merge and then do a discussion round with our user (Orel) - there might be a couple of items / use cases to do then.
Thanks for all the changes!
| observation_time : str | ||
| Observation time in ISO format. | ||
| observation_time : str, optional | ||
| Observation time in UTC ISO format. If None, metadata from the grid file is used. |
There was a problem hiding this comment.
Need help to understand this: the grid file contains pointings calculated for a given observation time. How can a user set a different observation time for the plotting? If it is only for some markers on the plot, please clarify the docstring.
There was a problem hiding this comment.
@tobiaskleiner - help me with this question please.
| raise ValueError(f"Unknown common identifier {common_identifier}") from exc | ||
|
|
||
|
|
||
| def normalize_array_element_identifier(array_element_identifier): |
There was a problem hiding this comment.
Is this used to convert sim_telarray telescope IDs to telescope name strings? Note the common identifiers are not sim_telarray telescope IDs but numerical IDs used by some CTAO software (e.g., ARCADA). Or are these the CTAO numerical IDs?
There was a problem hiding this comment.
Ah I was assuming this is the same as the sim_telarray id. Don't we have also a function to convert between these two?
There was a problem hiding this comment.
| """ | ||
| identifier_str = str(array_element_identifier).strip() | ||
| try: | ||
| common_identifier = int(identifier_str) |
There was a problem hiding this comment.
Should work but feels wrong if you e..g it is "float" -> str(float) -> int(str(float)) -> ValueError?
Would using isdigit make it a bit cleaner?
There was a problem hiding this comment.
Using isdigit is exactly what the code is already doing (with optional lstrip), so I think this is already the clean approach. non-integer strings return early before int conversion.
|
|
||
| .. code-block:: console | ||
|
|
||
| simtools-plot-production-grid \ |
There was a problem hiding this comment.
This example gives me:
simtools-production-generate-grid --site North --model_version 6.0.2 --axes tests/resources/production_grid_generation_axes_definition_radec.yml --coordinate_system ra_dec --observing_time "2017-09-16 00:00:00" --lookup_table tests/resources/corsika_simulation_limits/corsika_simulation_limits_lookup_01.ecsv --telescope_ids MSTN-15
INFO: Log messages will be written to: simtools-output/production_generate_grid_20260408T094331Z.log
INFO: simtools: 0.28.1.dev112+ga6a91c19e DB: CTAO-Simulation-Model v0.14.0 CORSIKA: 78010 sim_telarray: v2025-11-30-rc
Traceback (most recent call last):
File "/workdir/env/bin/simtools-production-generate-grid", line 6, in <module>
sys.exit(main())
^^^^^^
File "/workdir/external/simtools/src/simtools/applications/production_generate_grid.py", line 184, in main
grid_gen = GridGeneration(
^^^^^^^^^^^^^^^
File "/workdir/external/simtools/src/simtools/production_configuration/generate_production_grid.py", line 85, in __init__
self._prepare_lookup_table_limits_for_point_interpolation()
File "/workdir/external/simtools/src/simtools/production_configuration/generate_production_grid.py", line 164, in _prepare_lookup_table_limits_for_point_interpolation
key: LinearNDInterpolator(
^^^^^^^^^^^^^^^^^^^^^
File "scipy/interpolate/_interpnd.pyx", line 306, in scipy.interpolate._interpnd.LinearNDInterpolator.__init__
File "scipy/interpolate/_interpnd.pyx", line 97, in scipy.interpolate._interpnd.NDInterpolatorBase.__init__
File "scipy/interpolate/_interpnd.pyx", line 310, in scipy.interpolate._interpnd.LinearNDInterpolator._calculate_triangulation
File "scipy/spatial/_qhull.pyx", line 1889, in scipy.spatial._qhull.Delaunay.__init__
File "scipy/spatial/_qhull.pyx", line 356, in scipy.spatial._qhull._Qhull.__init__
scipy.spatial._qhull.QhullError: QH6214 qhull input error: not enough points(3) to construct initial simplex (need 5)
While executing: | qhull d Qz Qbb Qt Qc Q12
Options selected for Qhull 2020.2.r 2020/08/31:
run-id 1772452772 delaunay Qz-infinity-point Qbbound-last Qtriangulate
Qcoplanar-keep Q12-allow-wide _pre-merge _zero-centrum Qinterior-keep
_maxoutside 0
There was a problem hiding this comment.
This is due to not enough points for triangulatio, added explicit RA/Dec sparse-lookup handling that catches triangulation failures and raises ValueError. Documentation now points to the merged file that contains enough points for operation.
| output_file: grid_output_radec.json | ||
| output_path: simtools-output | ||
| site: North | ||
| telescope_ids: [] |
There was a problem hiding this comment.
Can you start a list of things to discuss with @orelgueta ? I think we might want to derive a production grid of pointings without the derivation of energy thresholds / scatter max values, etc. But let's check exactly the use case.
| coordinate system is 'ra_dec'. | ||
|
|
||
| For ``coordinate_system='ra_dec'``, the underlying grid generation supports a | ||
| native all-sky direction sampling mode (declination lines with hour-angle spacing) |
There was a problem hiding this comment.
Still don't understand the native. There is one plot in alt/az and one in ra/dec. Which one is native?
| ------- | ||
| To plot grid points on a sky projection: | ||
|
|
||
| .. code-block:: console |
| } | ||
|
|
||
| def _generate_grid_radec_mode(self): | ||
| """Generate grid points for RA/Dec mode using uniform declination lines.""" |
There was a problem hiding this comment.
OK - so maybe add this to the docstring (as it is not clear)
|
@GernotMaier somehow can't directly answer to your last 4 comments:
Please let me know if there is anything else. |
|
|
Could you improve the docstring with the native? Always best to react on questions like this and clarify things. |
|
@GernotMaier The docstring has been updated alread and the explanation about native has been addded to the application |
|
I am still trying to understand why need for plotting. Could that be simplified by adding ra/dec columns to the output table generated by simtools-production-generate-grid? |
So plotting both panels still needs transforms, which is why site + time inputs are still required. The simplification idea would be to always write both Alt/Az and RA/Dec (plus metadata) in the grid output. Should I add this now or in a follow up PR? |
GernotMaier
left a comment
There was a problem hiding this comment.
Thanks for this @tobiaskleiner
|
Fine with me to do this in a follow up approach. I do think it is better to keep plotting apps simple without requiring a lot of additional input. Approved! |
|
Thank you for the review @GernotMaier, will open a separate PR for the follow up. |





Adds RA/Dec declination-line support to production grid generation and introduces a new plotting utility to visualize production-grid points in both local Alt/Az and equatorial RA/Dec projections.