Skip to content

Add decliniation line support in production grid#2075

Merged
tobiaskleiner merged 52 commits into
mainfrom
production-grid-radec
Apr 9, 2026
Merged

Add decliniation line support in production grid#2075
tobiaskleiner merged 52 commits into
mainfrom
production-grid-radec

Conversation

@tobiaskleiner
Copy link
Copy Markdown
Collaborator

@tobiaskleiner tobiaskleiner commented Mar 12, 2026

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.

@tobiaskleiner tobiaskleiner marked this pull request as draft March 12, 2026 12:05
@tobiaskleiner tobiaskleiner requested a review from Copilot March 24, 2026 09:18
@tobiaskleiner tobiaskleiner marked this pull request as ready for review March 24, 2026 09:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 GridGeneration to support coordinate_system="ra_dec" with (a) native declination-line/hour-angle sampling and (b) explicit RA/Dec axes mode.
  • Add ProductionGridPlotter plus new CLI entrypoint simtools-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.

Comment thread src/simtools/production_configuration/generate_production_grid.py
Comment thread src/simtools/production_configuration/generate_production_grid.py Outdated
Comment thread src/simtools/production_configuration/plot_production_grid.py
@tobiaskleiner
Copy link
Copy Markdown
Collaborator Author

Example plot:
Screenshot 2026-03-31 at 10 20 21

@tobiaskleiner tobiaskleiner requested a review from Copilot March 31, 2026 08:22
@tobiaskleiner
Copy link
Copy Markdown
Collaborator Author

@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.

Copy link
Copy Markdown
Contributor

@GernotMaier GernotMaier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def get_sim_telarray_telescope_id_to_telescope_name_mapping(file):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you fix this?

Comment thread src/simtools/utils/names.py Outdated
Comment thread src/simtools/utils/names.py
Comment thread src/simtools/utils/names.py Outdated
"""
identifier_str = str(array_element_identifier).strip()
try:
common_identifier = int(identifier_str)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any answer here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: []
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice, yes!

}

def _generate_grid_radec_mode(self):
"""Generate grid points for RA/Dec mode using uniform declination lines."""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - so maybe add this to the docstring (as it is not clear)

@tobiaskleiner
Copy link
Copy Markdown
Collaborator Author

@GernotMaier somehow can't directly answer to your last 4 comments:

  • Yes I can start a list: In this case however one could simply provide a dummy lookup table and ignore the resulting columns in the grid table.
  • By ‘native’ I mean the coordinate system used to generate the grid points in the file, not one of the two panels. The plot always shows both Alt/Az and RA/Dec views, ‘native RA/Dec’ only means the input grid itself contains explicit RA/Dec columns
  • implemented
  • added to docstring

Please let me know if there is anything else.

@ctao-sonarqube
Copy link
Copy Markdown

ctao-sonarqube Bot commented Apr 9, 2026

@GernotMaier
Copy link
Copy Markdown
Contributor

Could you improve the docstring with the native? Always best to react on questions like this and clarify things.

@tobiaskleiner
Copy link
Copy Markdown
Collaborator Author

@GernotMaier The docstring has been updated alread and the explanation about native has been addded to the application plot_production_grid docstring. Please let me know if this is fine with you.

@GernotMaier
Copy link
Copy Markdown
Contributor

I am still trying to understand why need

--site North --model_version 6.0.2  --observation_time "2025-06-01 00:00:00"

for plotting. Could that be simplified by adding ra/dec columns to the output table generated by simtools-production-generate-grid?

@tobiaskleiner
Copy link
Copy Markdown
Collaborator Author

I am still trying to understand why need

--site North --model_version 6.0.2  --observation_time "2025-06-01 00:00:00"

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?
Currently zen/az mode stores alt/az columns and no ra/dec, and ra/dec mode stores no alt/az in the output.

Copy link
Copy Markdown
Contributor

@GernotMaier GernotMaier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this @tobiaskleiner

@GernotMaier
Copy link
Copy Markdown
Contributor

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!

@tobiaskleiner
Copy link
Copy Markdown
Collaborator Author

Thank you for the review @GernotMaier, will open a separate PR for the follow up.

@tobiaskleiner tobiaskleiner merged commit 34d6f68 into main Apr 9, 2026
17 checks passed
@tobiaskleiner tobiaskleiner deleted the production-grid-radec branch April 9, 2026 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants