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

Variance calibration #2636

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

Variance calibration #2636

wants to merge 20 commits into from

Conversation

ctoennis
Copy link

@ctoennis ctoennis commented Nov 4, 2024

This PR adds a trait to the CameraCalibrator called "image_calibration_type". This trait allows to switch the method of calibration between "charge" and "variance", with the former being the calibration method for the existing image extractors and the latter being the method to calibrate variance images.

I also made some small adjustment to the variance extractor so that it works in the CameraCalibrator.

@ctoennis ctoennis self-assigned this Nov 4, 2024

This comment has been minimized.

1 similar comment

This comment has been minimized.

@TjarkMiener
Copy link
Member

thanks for putting this together @ctoennis! In case I'm not missing something, I think we can (maybe should) apply this sqrt operation before writing the coefficients. Therefore we do not need the different cases here in the code. Would that work?

@ctoennis
Copy link
Author

ctoennis commented Nov 4, 2024

@TjarkMiener Yes, that should work. The calibration events would only need the sqrt coeficcients. Only thing is that this needs to be documented somewhere.

@ctoennis
Copy link
Author

ctoennis commented Nov 4, 2024

Though, the changes to the variance extractor should then still be kept so that it works with the calibrator.

src/ctapipe/calib/camera/calibrator.py Outdated Show resolved Hide resolved
@@ -73,6 +79,15 @@ class CameraCalibrator(TelescopeComponent):
help="Name of the ImageExtractor subclass to be used.",
).tag(config=True)

image_calibration_type = CaselessStrEnum(
Copy link
Contributor

Choose a reason for hiding this comment

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

see l.66

if (
self.apply_peak_time_shift.tel[tel_id]
and remaining_shift is not None
and self.image_calibration_type == "charge"
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we really need to alter this condition?

Copy link
Author

Choose a reason for hiding this comment

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

The variance extractor has no peak time, so applying the peak time shift otherwise throws an error

Copy link
Member

Choose a reason for hiding this comment

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

Just check if dl1.peak_time is not None instead of a specific extractor.

Copy link
Author

Choose a reason for hiding this comment

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

@maxnoe that makes sense

src/ctapipe/calib/camera/calibrator.py Outdated Show resolved Hide resolved
calibrator(example_event)
image = example_event.dl1.tel[tel_id].image
assert image is not None
assert image.shape == (1764,)
Copy link
Contributor

Choose a reason for hiding this comment

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

from where this shape comes? What telescope is this?

Copy link
Author

Choose a reason for hiding this comment

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

That is from the example event. Not sure what telescope this is

Copy link
Member

Choose a reason for hiding this comment

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

FlashCam from the number of pixels

@@ -1308,7 +1308,7 @@ def __call__(
self, waveforms, tel_id, selected_gain_channel, broken_pixels
) -> DL1CameraContainer:
container = DL1CameraContainer(
image=np.nanvar(waveforms, dtype="float32", axis=2),
image=np.nanvar(waveforms, dtype="float32", axis=2)[0],
Copy link
Contributor

Choose a reason for hiding this comment

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

We shall be able to work with multiple gains, why do you introduce this change?

Copy link
Author

Choose a reason for hiding this comment

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

np.nanvar was giving me an extra dimension on top of the gain. I think I can fix this with the keepdims parameter

Comment on lines 314 to 319
if self.image_calibration_type == "charge":
dl1.image *= dl1_calib.relative_factor / dl1_calib.absolute_factor
elif self.image_calibration_type == "variance":
dl1.image *= np.sqrt(
dl1_calib.relative_factor / dl1_calib.absolute_factor
)
Copy link
Member

Choose a reason for hiding this comment

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

You could check here if the extractor.__class__.__name__ is VarianceExtractor rather than passing the specific config parameter.

This comment has been minimized.

@@ -1308,7 +1308,7 @@ def __call__(
self, waveforms, tel_id, selected_gain_channel, broken_pixels
) -> DL1CameraContainer:
container = DL1CameraContainer(
image=np.nanvar(waveforms, dtype="float32", axis=2),
image=np.nanvar(waveforms, dtype="float32", keepdims=False, axis=2),
Copy link
Contributor

Choose a reason for hiding this comment

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

A bit weird that you need to set keepdims=False explicitly, but ok.

Copy link
Author

Choose a reason for hiding this comment

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

i will check again if i make it work without that

Copy link
Contributor

Choose a reason for hiding this comment

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

Should work without it:

x  = np.random.uniform(size=(2,1800, 1000))

In [1]: np.nanvar(x, axis=2).shape
Out[2]: (2, 1800)

In [2]: np.nanvar(x, axis=2, keepdims=True).shape
Out[2]: (2, 1800, 1)

In [3]: np.nanvar(x, axis=2, keepdims=False).shape
Out[3]: (2, 1800)

calibrator(example_event)
image = example_event.dl1.tel[tel_id].image
assert image is not None
assert image.shape == (
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a test with the LST (two gains)

Copy link
Author

Choose a reason for hiding this comment

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

ok

Copy link
Author

Choose a reason for hiding this comment

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

would it make sense to add a test for other extractor with the LST?

Copy link
Contributor

Choose a reason for hiding this comment

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

You could use a parametrized test here to test all telescope types. (@pytest.mark.parametrized). See for example the code in ctapipe/instrument/tests/test_telescope.py

This comment has been minimized.

mexanick
mexanick previously approved these changes Nov 6, 2024
@@ -0,0 +1 @@
Makes changes to the CameraCalibrator in ctapipe.calib.camera.calibrator that allows it to correctly variance images generated with the VarianceExtractor
Copy link
Member

Choose a reason for hiding this comment

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

Please describe the actual change, not just say "there are changes". Also there is a verb missing here (calibrate?)

Copy link
Author

Choose a reason for hiding this comment

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

i added some explanation

@maxnoe
Copy link
Member

maxnoe commented Nov 6, 2024

You still need the peak_time check, right?

@ctoennis
Copy link
Author

ctoennis commented Nov 6, 2024

Oh yes, that will be still needed

@TjarkMiener
Copy link
Member

I discussed with @mexanick offline yesterday. We might not want to run the tool for computing camera calibration coefficients twice and store two separated files (one for comics; one for pointing calibration), just to square one column here. What do you think?

@mexanick
Copy link
Contributor

mexanick commented Nov 6, 2024

at least for now, I would avoid recomputation of the calibrations just for variance. With the current code, we can always have this possibility to test, if needed.

src/ctapipe/calib/camera/calibrator.py Outdated Show resolved Hide resolved
calibrator(example_event)
image = example_event.dl1.tel[tel_id].image
assert image is not None
assert image.shape == (
Copy link
Contributor

Choose a reason for hiding this comment

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

You could use a parametrized test here to test all telescope types. (@pytest.mark.parametrized). See for example the code in ctapipe/instrument/tests/test_telescope.py

@ctoennis
Copy link
Author

ctoennis commented Nov 7, 2024

i will change the test to check all cameras

@ctoennis
Copy link
Author

ctoennis commented Nov 7, 2024

@kosack I used the camera_geometry fixture instead to check for all cameras. In the end I just need the geometry, so that should work well.

@ctoennis
Copy link
Author

ctoennis commented Nov 7, 2024

I think there is an issue with the recent change to the changelog check (#2637).

@ctoennis
Copy link
Author

ctoennis commented Nov 8, 2024

i switched it to a parametrized test for the different cameras now and caught the other test for name and switched it to isinstance

@ctoennis ctoennis requested a review from kosack November 8, 2024 14:51
@ctoennis ctoennis requested a review from maxnoe November 10, 2024 12:07
if (
self.apply_peak_time_shift.tel[tel_id]
and remaining_shift is not None
and dl1.peak_time is not None
Copy link
Member

Choose a reason for hiding this comment

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

logically, I'd put the dl1.peak_time is not None check first

@ctoennis ctoennis requested a review from maxnoe November 12, 2024 14:40
@ctoennis ctoennis requested a review from maxnoe November 12, 2024 15:05
@maxnoe maxnoe added this to the 0.23.0 milestone Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants