Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First step of implementing CEP-002: Change container structure #2204

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

maxnoe
Copy link
Member

@maxnoe maxnoe commented Jan 10, 2023

No description provided.

@maxnoe
Copy link
Member Author

maxnoe commented Jan 10, 2023

Before I continue changing everything, could you review the new container structure?

I think it's already a big step in the right direction, as the structure is much simpler, we could get rid of many indirections...

@maxnoe maxnoe requested a review from kosack January 11, 2023 08:28
@nbiederbeck
Copy link
Contributor

nbiederbeck commented Jan 11, 2023

This comment just looked at ctapipe/containers.py. In general I think the structure looks fine, it makes more sense as seen in the tests, but while we're at it, some comments:

  • For the EventContainers: and why do we have count?

  • Should there be a general MuonContainer?

  • Why does the TelescopePointingContainer have no ra/dec?
    Or why does ArrayPointingContainer have it?

  • Should we rename the ParticleClassificationContainer and TelescopeImpactParameterContainer to be more consistent with ReconstructedEnergyContainer and ReconstructedGeometryContainer? E.g. ReconstructedParticleContainer, ReconstructedImpactContainer.

  • Is Reconstructed[…].telescopes sensible to be None if Mono? Or should it just hold the corresponding tel_id and be of type int?

  • Is TelescopeTriggerContainer.n_trigger_pixels with default -1 sensible? Or is 0 better to have an unsigned int?

  • SimulationConfigContainer have many nans, but str seems more appropriate given the description. Or None.

  • TelescopeSimulationContainer.impact is not called true_impact.

  • MorphologyContainer, is -1 a better default than 0? Does it make a difference of default 0 and filled 0?

  • Is CameraTimingParametersContainer still needed?

  • LeakageContainer.intensity_width_{1,2} is ambiguously documented (intensity vs. fraction of intensity, as of the docstring).

  • There are some Camera-containers, which I think we can get rid of?

@maxnoe maxnoe changed the title Start working on inverted container structure Implement CEP-002: Change container structure to ArrayEvent -> TelescopeEvent -> Data Levels Jun 2, 2023
@maxnoe
Copy link
Member Author

maxnoe commented Jun 5, 2023

Why does the TelescopePointingContainer have no ra/dec?

Because all our telescopes are alt/az mounts, so this is the actual information that is monitored.

Or why does ArrayPointingContainer have it?

Because that's the reference point the array is tracking, which might be in sky-fixed coordinates.

TelescopeSimulationContainer.impact is not called true_impact.

Isn't this accomplished by adding the true_ prefix in the data writer?

Is TelescopeTriggerContainer.n_trigger_pixels with default -1 sensible? Or is 0 better to have an unsigned int?

I think it's important to distinguish invalid from valid data, 0 trigger pixels are possible (e.g. for pedestal events which are randomly triggered), so better distinguish. Same for the other positive integers.

@maxnoe
Copy link
Member Author

maxnoe commented Jun 5, 2023

For the EventContainers: and why do we have count?

Just nice to have I guess.

@maxnoe
Copy link
Member Author

maxnoe commented Jun 5, 2023

Is CameraTimingParametersContainer still needed?

That's connected to all the other Camera... containers and to #2141, we need them as long as we still support computing image parameters in CameraFrame

@maxnoe maxnoe force-pushed the container_structure branch from ce1d8ad to 352b041 Compare July 6, 2023 08:03
@StFroese
Copy link
Member

StFroese commented Jul 7, 2023

The ArrayEventContainer contains the DL2 data (geometry, energy, classification) of the event in the ArrayDL2Container.
It also contains the telescopes as a map of TelescopeEventContainer's which contains all data levels like r0... and also dl2. dl2 in this case is a TelescopeDL2Container which is a subclass of the ArrayDL2Container again.

Why do we save the array event reconstructions at telescope level again? This is a little bit confusing to me

@maxnoe
Copy link
Member Author

maxnoe commented Jul 7, 2023

Why do we save the array event reconstructions at telescope level again? This is a little bit confusing to me

The DL2TelescopeContainer is for monoscopic predictions, not for repeating the subarray info.

The inheritance here is just to get the same fields, but I agree that it's confusing that isinstance(DL2TelescopeContainer, DL2SubarrayContainer). I had an intermediate version where both just inherited from Container and then duplicated the field definitions.

@maxnoe maxnoe force-pushed the container_structure branch from 352b041 to c522715 Compare July 7, 2023 10:25
@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@@ -209,51 +210,49 @@ def _parameterize_image(
# parameterization
return default

def _process_telescope_event(self, event):
def _process_telescope_event(self, tel_event):
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest adding type hints for functions like this while you are at it, especially for ones where the type changed.

def _process_telescope_event(self, tel_event: DL1TelescopeContainer):

That will make it more clear what is expected where, and also support language servers and mypy to do better completion, etc.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a TelescopeEventContainer, but yes, I'll add type hints for these. However, these are not terribly helpful, since at least my lsp only looks at the class variable, not the instance variables or rather assumes they are of the same type.

@StFroese
Copy link
Member

The inheritance here is just to get the same fields, but I agree that it's confusing that isinstance(DL2TelescopeContainer, DL2SubarrayContainer). I had an intermediate version where both just inherited from Container and then duplicated the field definitions.

Can we add a ReconstrucedShowerContainer which contains the fields and DL2{Telescope|Subarray}Container inherit from that?

@maxnoe maxnoe force-pushed the container_structure branch 2 times, most recently from 900249d to bd7d777 Compare October 31, 2023 16:57
@maxnoe
Copy link
Member Author

maxnoe commented Oct 31, 2023

Hi all,

I rebased this on the current main and squashed the commits into one, to ease follow-up rebases when we make updates to main.

I'd appreciate a fresh review now.

I suggest to first only review the container structure in ctapipe.containers (beware, this is collapsed by default) before reviewing any of the resulting code changes.

Once we are happy with the container structure and renaming, I'll fix up the rest of the code and we can commence the review there.

@maxnoe maxnoe requested review from kosack, ccossou and Tobychev October 31, 2023 17:01
@@ -759,12 +748,11 @@ class SimulatedCameraContainer(Container):
)


class SimulatedEventContainer(Container):
class SimulationSubarrayContainer(Container):
shower = Field(
Copy link
Member Author

Choose a reason for hiding this comment

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

Right now, simulationsubarrayContainer has a single subcontainer, shower.

We could just attach the shower container at the SubarrayEventContainer to get rid of one level of indirection.

@ccossou
Copy link
Contributor

ccossou commented Nov 6, 2023

For the EventContainers: and why do we have count?

Just nice to have I guess.

On this part. This, to me, is related to how people parse the file and shouldn't be in the container itself, or if it is, should be hidden and not publicly exposed (even if in python, private just means harder to type). But that's a minor comment and not the main purpose of CEP-002.

)
for container in simulation.true_parameters.values():
Copy link
Contributor

Choose a reason for hiding this comment

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

If the prefix doesn't start with "true_", doesn't that mean there's something wrong with the file and we should raise an error rather than silently correcting it?

Copy link
Member Author

Choose a reason for hiding this comment

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

If the prefix doesn't start with "true_", doesn't that mean there's something wrong with the file

Has nothing to do with the input file, since the container is created by the _parametrize_image methods, but you are right, this is confusing.

I will check if it is needed / can be improved.

@ccossou
Copy link
Contributor

ccossou commented Nov 7, 2023

(Sorry, commented on file without realizing it wasn't container.py anymore, got carried away.)

@maxnoe maxnoe force-pushed the container_structure branch 2 times, most recently from 02e167c to 2a71a42 Compare April 30, 2024 13:17
@maxnoe
Copy link
Member Author

maxnoe commented Apr 30, 2024

Wow, resolving the conflicts here was no fun.... I'd really appreciate if we can tackle this one next.

I will do a self-review again and it would be nice if others could start reviewing the structure in src/ctapipe/containers.py

One particular issue (noted with a fixme in the CameraCalibrator) is that we (in accordance with the CTAO data model) moved the trigger information to dl0, but the SimTelEventSource and also other event source implementations are allowed to return event data with only R1 inside.

This has the issue of the CameraCalibrator.r1_to_dl0 method needing to fill trigger information... which it now does by checking if there is a pre-existing dl0 container. Not so nice conceptually.

I see two solutions:

  • Putting trigger info also at R1 so that e.g. CameraCalibrator can just forward it from r1 to dl0
  • Requiring event sources to provide dl0, removing the dvr step from CameraCalibrator so that it only deals with the calibration from dl0 to dl1

I think the latter is the option that is more closely aligned with how we expect actual CTAO operations to be.

Studies for DVR can still be done, if we for example at dvr options to simteleventsource or in an intermediate step.

@maxnoe maxnoe force-pushed the container_structure branch from 2a71a42 to 7022224 Compare April 30, 2024 13:29

This comment has been minimized.

description="DL2 reconstructed event properties",
)

pointing = Field(
Copy link
Member Author

Choose a reason for hiding this comment

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

Move into dl0?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure, is it very helpful?

Putting pointing in dl0 means you can't make geometry reconstruction using pure dl2 files, but maybe that's fine? Not sure what other costs there are.

Copy link
Member Author

Choose a reason for hiding this comment

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

DL2 files could always include the dl0 monitoring table. Independent of where this field is stored in the object, it is written to /dl0 in the hdf5 data files.

Copy link
Contributor

Choose a reason for hiding this comment

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

There is also pointing information in the tel field below, although it is per telescope rather than for the subarray.

Putting the subarray pointing info into the dl0 now seems strange, are there any quantities that depend on the subarray pointing at dl0? Isn't the telescope pointing the natural pointing until you do stereo?

This comment has been minimized.

@maxnoe maxnoe force-pushed the container_structure branch 2 times, most recently from e475e40 to e6719b0 Compare April 30, 2024 13:47

This comment has been minimized.

1 similar comment

This comment has been minimized.

src/ctapipe/io/tableloader.py Show resolved Hide resolved
src/ctapipe/io/tableloader.py Show resolved Hide resolved
src/ctapipe/image/reducer.py Show resolved Hide resolved
src/ctapipe/instrument/trigger.py Show resolved Hide resolved
description="DL2 reconstructed event properties",
)

pointing = Field(
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure, is it very helpful?

Putting pointing in dl0 means you can't make geometry reconstruction using pure dl2 files, but maybe that's fine? Not sure what other costs there are.

src/ctapipe/io/datawriter.py Show resolved Hide resolved
src/ctapipe/io/datawriter.py Show resolved Hide resolved
src/ctapipe/io/datawriter.py Outdated Show resolved Hide resolved
src/ctapipe/io/hdf5eventsource.py Show resolved Hide resolved
kosack
kosack previously approved these changes Jul 10, 2024
Copy link
Contributor

@kosack kosack left a comment

Choose a reason for hiding this comment

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

I don't see any major problem.

@maxnoe maxnoe force-pushed the container_structure branch 4 times, most recently from f8939d0 to 7f603c4 Compare July 15, 2024 08:53
@maxnoe maxnoe force-pushed the container_structure branch 3 times, most recently from bbecf66 to 1a17ad8 Compare July 15, 2024 11:37
@maxnoe maxnoe force-pushed the container_structure branch from 1a17ad8 to 399bb24 Compare July 15, 2024 12:07

This comment has been minimized.

@maxnoe maxnoe force-pushed the container_structure branch from 399bb24 to 8603de0 Compare July 15, 2024 12:47
@maxnoe maxnoe force-pushed the container_structure branch from 8603de0 to 5474dca Compare July 15, 2024 13:05
Copy link

Passed

Analysis Details

12 Issues

  • Bug 0 Bugs
  • Vulnerability 0 Vulnerabilities
  • Code Smell 12 Code Smells

Coverage and Duplications

  • Coverage 96.30% Coverage (93.70% Estimated after merge)
  • Duplications 1.09% Duplicated Code (0.60% Estimated after merge)

Project ID: cta-observatory_ctapipe_AY52EYhuvuGcMFidNyUs

View in SonarQube

@@ -262,6 +272,25 @@ class TelEventIndexContainer(Container):
tel_id = tel_id_field()


class TelescopeTriggerContainer(Container):
default_prefix = ""
Copy link
Contributor

Choose a reason for hiding this comment

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

No docstring here?



class SubarrayTriggerContainer(Container):
default_prefix = ""
Copy link
Contributor

Choose a reason for hiding this comment

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

No docstring here?

@@ -773,12 +775,11 @@ class SimulatedCameraContainer(Container):
)


class SimulatedEventContainer(Container):
class SimulationSubarrayContainer(Container):
Copy link
Contributor

Choose a reason for hiding this comment

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

No docstring here?

array_altitude = Field(nan * u.rad, "Array pointing altitude", unit=u.rad)
array_ra = Field(nan * u.rad, "Array pointing right ascension", unit=u.rad)
array_dec = Field(nan * u.rad, "Array pointing declination", unit=u.rad)
class SubarrayPointingContainer(Container):
Copy link
Contributor

Choose a reason for hiding this comment

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

No docstring here?

shower = Field(
default_factory=SimulatedShowerContainer,
description="True event information",
)
tel = Field(default_factory=partial(Map, SimulatedCameraContainer))
Copy link
Contributor

Choose a reason for hiding this comment

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

With the tel removed this container now only contains one thing, so its not clear what the extra indirection step achieves.

description="DL2 reconstructed event properties",
)

pointing = Field(
Copy link
Contributor

Choose a reason for hiding this comment

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

There is also pointing information in the tel field below, although it is per telescope rather than for the subarray.

Putting the subarray pointing info into the dl0 now seems strange, are there any quantities that depend on the subarray pointing at dl0? Isn't the telescope pointing the natural pointing until you do stereo?

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.

Rename *Camera*Containers to *Telescope*Containers Discussion on restructuring Event Container structure
6 participants