Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changes/3063.datamodel.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add monitoring containers for pointing-related data
147 changes: 144 additions & 3 deletions src/ctapipe/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
"TimingParametersContainer",
"TriggerContainer",
"TelescopePointingContainer",
"TelescopeStructurePointingContainer",
"TelescopeStructureDisplacementContainer",
"CameraDisplacementContainer",
"TelescopePointingCorrectionContainer",
"ArrayPointingContainer",
"StatisticsContainer",
"ChunkContainer",
Expand All @@ -71,6 +75,7 @@
"ObservationBlockContainer",
"ObservingMode",
"ObservationBlockState",
"WeatherMonitoringContainer",
]


Expand Down Expand Up @@ -1187,8 +1192,95 @@ class DL2Container(Container):
)


# Calibration containers
# Pointing containers
# Calibration and Monitoring containers


# Pointing-related containers
class TelescopeStructurePointingContainer(Container):
"""
Pointing of the telescope structure in local coordinates (Alt/Az)
as measured by the telescope hardware (e.g. drive encoders).
"""

default_prefix = "structure_pointing"
azimuth = Field(
nan * u.rad, "Raw azimuth measured by structure encoders", unit=u.rad
)
altitude = Field(
nan * u.rad, "Raw altitude measured by structure encoders", unit=u.rad
)


class TelescopeStructureDisplacementContainer(Container):
"""
Difference between ideal and real direction of the telescope axis for
a given elevation in local coordinates (e.g. structural bending model).
"""

default_prefix = "structure_displacement"
delta_azimuth = Field(
nan * u.rad,
"Azimuth offset due to structure bending/deformation",
unit=u.rad,
)
delta_altitude = Field(
nan * u.rad,
"Altitude offset due to structure bending/deformation",
unit=u.rad,
)


class CameraDisplacementContainer(Container):
"""
Displacement and tilt of the camera w.r.t. its nominal position in the
telescope structure.
"""

default_prefix = "camera_displacement"
delta_x = Field(
nan * u.m, "Camera displacement along X axis (horizontal)", unit=u.m
)
delta_y = Field(nan * u.m, "Camera displacement along Y axis (vertical)", unit=u.m)
delta_z = Field(
nan * u.m, "Camera displacement along optical Z axis (focal offset)", unit=u.m
)
tilt_x = Field(nan * u.rad, "Camera tilt angle around X axis (pitch)", unit=u.rad)
tilt_y = Field(nan * u.rad, "Camera tilt angle around Y axis (yaw)", unit=u.rad)
tilt_z = Field(
nan * u.rad, "Camera rotation angle around optical Z axis (roll)", unit=u.rad
)


class AuxiliaryPointingCorrectionContainer(Container):
"""
Pointing correction in celestial coordinates derived using auxiliary hardware, such as e.g. StarGuider camera.
"""

default_prefix = "aux_pointing_correction"
delta_ra = Field(
nan * u.rad, "Residual Right Ascension offset correction", unit=u.rad
)
delta_dec = Field(nan * u.rad, "Residual Declination offset correction", unit=u.rad)


class TelescopePointingCorrectionContainer(Container):
"""
Residual sky-pointing corrections in celestial coordinates (RA/Dec/Rotation).
Comment thread
maxnoe marked this conversation as resolved.
Outdated

This container holds abstract celestial offsets regardless of how they were
derived (e.g. analytical StarTracker, auxiliary hardware devices,
or a combination/fusion model).
"""

default_prefix = "pointing_correction"
delta_alt = Field(nan * u.rad, "Residual Altitude offset correction", unit=u.rad)
Comment thread
maxnoe marked this conversation as resolved.
Outdated
delta_az = Field(nan * u.rad, "Residual Azimuth offset correction", unit=u.rad)

# Optional uncertainty tracking
sigma_alt = Field(nan * u.rad, "Uncertainty on Alt offset correction", unit=u.rad)
sigma_az = Field(nan * u.rad, "Uncertainty on Az offset correction", unit=u.rad)


class TelescopePointingContainer(Container):
"""
Container holding pointing information for a single telescope
Expand All @@ -1214,6 +1306,29 @@ class ArrayPointingContainer(Container):
array_dec = Field(nan * u.rad, "Array pointing declination", unit=u.rad)


# Environmental Monitoring containers
class WeatherMonitoringContainer(Container):
"""
Environmental parameters at the observatory site.

Note: Astronomical refraction derived from weather measurements SHALL ONLY
be used when fitting star positions during offline optical pointing calibration.
It SHALL NOT be applied during Cherenkov atmospheric shower direction reconstruction.
"""

default_prefix = "weather"
temperature = Field(
nan * u.K, "Ambient air temperature at observatory site", unit=u.K
Comment thread
maxnoe marked this conversation as resolved.
)
pressure = Field(
nan * u.hPa, "Atmospheric pressure at observatory site", unit=u.hPa
)
relative_humidity = Field(
nan,
"Relative humidity fraction (0.0 to 1.0)",
Comment thread
maxnoe marked this conversation as resolved.
)


# Camera containers
class CameraCalibrationContainer(Container):
"""
Expand Down Expand Up @@ -1347,8 +1462,29 @@ class TelescopeMonitoringContainer(Container):
default_factory=CameraMonitoringContainer,
description="Container for monitoring data for camera",
)
structure_pointing = Field(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Following our discussion on slack on when / how lower-level monitoring is combined, I don't really see the need to add these containers to the event structure.

Is there a use case remaining?

I think we agreed that the more efficient approach is to compute the final correction on the monitoring time scales based on tabular data and interpolate that to the event.

In that scenario, we would not need event-wise data structures for these lower-level parts.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think we still want them for the star tracking. However, in this case I should leave them as standalone containers, but remove from being linked to the event, so it is only filled on request and not for every event processed with ctapipe-process tool, right?

In this case, I will leave TelescopePointing and CameraDisplacement containers here (I believe there's no easy way around for Camera Displacement, as I believe it would be only used to modify image, so we just take it as is and interpolate to the event time).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You mean as output containers from the star tracking which would work on bunches of events? Or as intermediate input per event?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

as intermediate event-wise input to star tracker. The output of star tracker would be a grid of corrections (common grid with the structure monitoring).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why would the star-tracker not use the pointing filled from Structure + BendingModel into the telescope poiinting container?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It will use the pointing from Structure + BendingModel as the seed, but it will also use CDM for a given event and weather values for the given event.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sure, weather is needed and should be added here.

But for the pointing, I would think that you configure the DL0MonitoringSource to read Structure, BendingModel and CDM files and use that to fill the already existing pointing container.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, it will be done like that. However, I still need to define the TelescopeStructurePointingContainer, TelescopeStructureDisplacementContainer, etc for conversion, to abstract telescope-specific implementations. They, however, would not be added to the event monitoring structure.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand for what you need the containers then

default=None,
type=TelescopeStructurePointingContainer,
description="Pointing of the telescope structure in local coordinates (RAW).",
)
structure_displacement = Field(
default=None,
type=TelescopeStructureDisplacementContainer,
description="Difference between ideal and real direction of the telescope axis in local coordinates.",
)
camera_displacement = Field(
default=None,
type=CameraDisplacementContainer,
description="Displacement and tilt of the camera w.r.t. its nominal position in the telescope structure.",
)
aux_pointing_correction = Field(
default=None,
type=AuxiliaryPointingCorrectionContainer,
description="Pointing correction in celestial coordinates derived using auxiliary hardware.",
)
pointing = Field(
default_factory=TelescopePointingContainer,
default=None,
type=TelescopePointingContainer,
description="Telescope pointing positions",
)

Expand All @@ -1367,6 +1503,11 @@ class MonitoringContainer(Container):
default_factory=ArrayPointingContainer,
description="Array pointing positions",
)
weather = Field(
default=None,
type=WeatherMonitoringContainer,
description="Weather monitoring data",
)


# Muon containers
Expand Down
Loading