Skip to content

Commit

Permalink
Merge pull request #1873 from cta-observatory/modifier_switch
Browse files Browse the repository at this point in the history
Add switch to ImageProcessor to enable/disable ImageModifier
  • Loading branch information
maxnoe authored Apr 12, 2022
2 parents 9b2ea31 + 0061b7e commit 0b17d4c
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 30 deletions.
14 changes: 11 additions & 3 deletions ctapipe/image/image_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
PeakTimeStatisticsContainer,
)
from ..core import QualityQuery, TelescopeComponent
from ..core.traits import Bool, List, create_class_enum_trait
from ..core.traits import Bool, BoolTelescopeParameter, List, create_class_enum_trait
from ..instrument import SubarrayDescription
from . import (
ImageCleaner,
Expand Down Expand Up @@ -61,11 +61,17 @@ class ImageProcessor(TelescopeComponent):
image_cleaner_type = create_class_enum_trait(
base_class=ImageCleaner, default_value="TailcutsImageCleaner"
)

use_telescope_frame = Bool(
default_value=True,
help="Whether to calculate parameters in the telescope or camera frame",
).tag(config=True)

apply_image_modifier = BoolTelescopeParameter(
default_value=False,
help="If true, apply ImageModifier to dl1 images"
).tag(config=True)

def __init__(
self, subarray: SubarrayDescription, config=None, parent=None, **kwargs
):
Expand Down Expand Up @@ -196,8 +202,10 @@ def _process_telescope_event(self, event):
geometry = self.telescope_frame_geometries[tel_id]
else:
geometry = self.subarray.tel[tel_id].camera.geometry
# compute image parameters only if requested to write them
dl1_camera.image = self.modify(tel_id=tel_id, image=dl1_camera.image)

if self.apply_image_modifier.tel[tel_id]:
dl1_camera.image = self.modify(tel_id=tel_id, image=dl1_camera.image)

dl1_camera.image_mask = self.clean(
tel_id=tel_id,
image=dl1_camera.image,
Expand Down
60 changes: 33 additions & 27 deletions ctapipe/image/modifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,30 +160,36 @@ def __init__(
self.rng = np.random.default_rng(self.rng_seed)

def __call__(self, tel_id, image, rng=None):
geom = self.subarray.tel[tel_id].camera.geometry
smeared_image = _smear_psf_randomly(
image=image,
fraction=self.psf_smear_factor.tel[tel_id],
indices=geom.neighbor_matrix_sparse.indices,
indptr=geom.neighbor_matrix_sparse.indptr,
smear_probabilities=np.full(geom.max_neighbors, 1 / geom.max_neighbors),
seed=self.rng.integers(0, np.iinfo(np.int64).max),
)

noise = np.where(
image > self.noise_transition_charge.tel[tel_id],
self.noise_level_bright_pixels.tel[tel_id],
self.noise_level_dim_pixels.tel[tel_id],
)
image_with_noise = _add_noise(
smeared_image,
noise,
rng=self.rng,
correct_bias=self.noise_correct_bias.tel[tel_id],
)
bias = np.where(
image > self.noise_transition_charge.tel[tel_id],
0,
self.noise_bias_dim_pixels.tel[tel_id],
)
return (image_with_noise + bias).astype(np.float32)
dtype = image.dtype

if self.psf_smear_factor.tel[tel_id] > 0:
geom = self.subarray.tel[tel_id].camera.geometry
image = _smear_psf_randomly(
image=image,
fraction=self.psf_smear_factor.tel[tel_id],
indices=geom.neighbor_matrix_sparse.indices,
indptr=geom.neighbor_matrix_sparse.indptr,
smear_probabilities=np.full(geom.max_neighbors, 1 / geom.max_neighbors),
seed=self.rng.integers(0, np.iinfo(np.int64).max),
)

if (
self.noise_level_dim_pixels.tel[tel_id] > 0
or self.noise_level_bright_pixels.tel[tel_id] > 0
):
bright_pixels = image > self.noise_transition_charge.tel[tel_id]
noise = np.where(
bright_pixels,
self.noise_level_bright_pixels.tel[tel_id],
self.noise_level_dim_pixels.tel[tel_id],
)
image = _add_noise(
image,
noise,
rng=self.rng,
correct_bias=self.noise_correct_bias.tel[tel_id],
)

image[~bright_pixels] += self.noise_bias_dim_pixels.tel[tel_id]

return image.astype(dtype, copy=False)
13 changes: 13 additions & 0 deletions ctapipe/image/tests/test_modifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,16 @@ def test_smear_image():
# drawn from the poissonian (especially with signal value 1)
if fraction > 0:
assert not ((image > 0) == (smeared > 0)).all()


def test_defaults_no_change(example_subarray):
"""Test that the default settings do not change the input image"""
rng = np.random.default_rng(0)

modifier = modifications.ImageModifier(example_subarray)
tel_id = 1
n_pixels = example_subarray.tel[tel_id].camera.geometry.n_pixels
image = rng.normal(50, 15, size=n_pixels).astype(np.float32)

new_image = modifier(tel_id=tel_id, image=image)
assert np.all(image == new_image)
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
"ImageProcessor": {
"image_cleaner_type": "TailcutsImageCleaner",
"apply_image_modifier": [["type", "*", true]],
"TailcutsImageCleaner": {
"picture_threshold_pe": [
["type", "*", 10.0],
Expand Down

0 comments on commit 0b17d4c

Please sign in to comment.