Skip to content

Commit 378a4c3

Browse files
authored
Merge pull request #1282 from cta-observatory/wf_noise_tuner
Waveform noise tuner
2 parents a3da2c0 + 20d04bb commit 378a4c3

File tree

7 files changed

+272
-146
lines changed

7 files changed

+272
-146
lines changed

lstchain/data/lstchain_lhfit_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@
279279
},
280280
"waveform_nsb_tuning":{
281281
"nsb_tuning": false,
282-
"nsb_tuning_ratio": 0.5,
282+
"nsb_tuning_rate_GHz": 0.15,
283283
"spe_location": null,
284284
"pre_computed_multiplicity": 10
285285
},

lstchain/data/lstchain_standard_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@
274274
},
275275
"waveform_nsb_tuning":{
276276
"nsb_tuning": false,
277-
"nsb_tuning_ratio": 0.5,
277+
"nsb_tuning_rate_GHz": 0.15,
278278
"spe_location": null,
279279
"pre_computed_multiplicity": 10
280280
},

lstchain/image/modifier.py

Lines changed: 220 additions & 101 deletions
Large diffs are not rendered by default.

lstchain/image/tests/test_modifier.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,26 @@ def test_calculate_required_additional_nsb(mc_gamma_testfile, observed_dl1_files
7070
mc_gamma_testfile,
7171
observed_dl1_files["dl1_file1"]
7272
)
73+
# Mean pixel charge variance in pedestals is 0 because there is only one
74+
# pedestal event in the test file
7375
assert np.isclose(data_ped_variance, 0.0, atol=0.1)
74-
assert np.isclose(mc_ped_variance, 3.11, atol=0.01)
75-
assert np.isclose(extra_nsb, -1.0)
76+
assert np.isclose(mc_ped_variance, 2.3, atol=0.2)
77+
assert np.isclose(extra_nsb, 0.08, atol=0.02)
7678

7779

7880
def test_tune_nsb_on_waveform():
7981
import astropy.units as u
8082
from ctapipe_io_lst import LSTEventSource
8183
from scipy.interpolate import interp1d
8284
from lstchain.io.io import get_resource_path
83-
from lstchain.image.modifier import WaveformNsbTunner
85+
from lstchain.image.modifier import WaveformNsbTuner
8486
from lstchain.data.normalised_pulse_template import NormalizedPulseTemplate
8587

8688
waveform = np.array(
8789
[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
8890
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
8991
)
90-
added_nsb_fraction, original_nsb = 1.0, {1: 0.1 * u.GHz}
92+
added_nsb_rate = {1: 0.1 * u.GHz}
9193
subarray = LSTEventSource.create_subarray(1)
9294
amplitude_HG = np.zeros(40)
9395
amplitude_LG = np.zeros(40)
@@ -106,23 +108,21 @@ def test_tune_nsb_on_waveform():
106108
charge_spe_cumulative_pdf = interp1d(spe_integral, spe[0], kind='cubic',
107109
bounds_error=False, fill_value=0.,
108110
assume_sorted=True)
109-
nsb_tunner = WaveformNsbTunner(added_nsb_fraction,
110-
original_nsb,
111-
pulse_templates,
112-
charge_spe_cumulative_pdf,
113-
pre_computed_multiplicity=0)
111+
nsb_tunner = WaveformNsbTuner(added_nsb_rate,
112+
pulse_templates,
113+
charge_spe_cumulative_pdf,
114+
pre_computed_multiplicity=0)
114115
nsb_tunner.tune_nsb_on_waveform(waveform, 1, gain, subarray)
115116
assert np.any(waveform != 0)
116117
assert np.isclose(np.mean(waveform), 0.0, atol=0.2)
117118
waveform = np.array(
118119
[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
119120
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
120121
)
121-
nsb_tunner = WaveformNsbTunner(added_nsb_fraction,
122-
original_nsb,
123-
pulse_templates,
124-
charge_spe_cumulative_pdf,
125-
pre_computed_multiplicity=10)
122+
nsb_tunner = WaveformNsbTuner(added_nsb_rate,
123+
pulse_templates,
124+
charge_spe_cumulative_pdf,
125+
pre_computed_multiplicity=10)
126126
nsb_tunner.tune_nsb_on_waveform(waveform, 1, gain, subarray)
127127
assert np.any(waveform != 0)
128128
assert np.isclose(np.mean(waveform), 0.0, atol=0.2)

lstchain/reco/r0_to_dl1.py

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from ..calib.camera import load_calibrator_from_config
3838
from ..calib.camera.calibration_calculator import CalibrationCalculator
3939
from ..image.cleaning import apply_dynamic_cleaning
40-
from ..image.modifier import calculate_required_additional_nsb, WaveformNsbTunner
40+
from ..image.modifier import calculate_required_additional_nsb, WaveformNsbTuner
4141
from .reconstructor import TimeWaveformFitter
4242
from ..image.muon import analyze_muon_event, tag_pix_thr
4343
from ..image.muon import create_muon_table, fill_muon_event
@@ -59,7 +59,7 @@
5959
write_subarray_tables
6060
)
6161

62-
from ..io.io import add_column_table, extract_simulation_nsb, dl1_params_lstcam_key, get_resource_path
62+
from ..io.io import add_column_table, dl1_params_lstcam_key, get_resource_path
6363
from ..io.lstcontainers import ExtraImageInfo, DL1MonitoringEventIndexContainer
6464
from ..paths import parse_r0_filename, run_to_dl1_filename, r0_to_dl1_filename
6565
from ..visualization.plot_reconstructor import plot_debug
@@ -403,25 +403,27 @@ def r0_to_dl1(
403403
metadata=metadata,
404404
)
405405
nsb_tuning = False
406-
nsb_tunner = None
407-
if 'waveform_nsb_tuning' in config.keys():
406+
nsb_tuner = None
407+
if 'waveform_nsb_tuning' in config:
408408
nsb_tuning = config['waveform_nsb_tuning']['nsb_tuning']
409409
if nsb_tuning:
410410
if is_simu:
411-
nsb_original = extract_simulation_nsb(input_filename)
412411
pulse_templates = {tel_id: NormalizedPulseTemplate.load_from_eventsource(
413412
subarray.tel[tel_id].camera.readout, resample=True)
414413
for tel_id in config['source_config']['LSTEventSource']['allowed_tels']}
415-
if 'nsb_tuning_ratio' in config['waveform_nsb_tuning'].keys():
414+
if 'nsb_tuning_rate_GHz' in config[
415+
'waveform_nsb_tuning']:
416416
# get value from config to possibly extract it beforehand on multiple files for averaging purposes
417417
# or gain time
418-
nsb_tuning_ratio = config['waveform_nsb_tuning']['nsb_tuning_ratio']
418+
nsb_tuning_rate = config['waveform_nsb_tuning'][
419+
'nsb_tuning_rate_GHz']
419420
else:
420421
# extract the pedestal variance difference between the current MC file and the target data
421422
# FIXME? fails for multiple telescopes
422-
nsb_tuning_ratio = calculate_required_additional_nsb(input_filename,
423-
config['waveform_nsb_tuning']['target_data'],
424-
config=config)[0]
423+
nsb_tuning_rate, _, _ = calculate_required_additional_nsb(
424+
input_filename,
425+
config['waveform_nsb_tuning']['target_data'],
426+
config=config)
425427
spe_location = (config['waveform_nsb_tuning']['spe_location']
426428
or get_resource_path("data/SinglePhE_ResponseInPhE_expo2Gaus.dat"))
427429
spe = np.loadtxt(spe_location).T
@@ -430,28 +432,33 @@ def r0_to_dl1(
430432
bounds_error=False, fill_value=0.,
431433
assume_sorted=True)
432434
pre_computed_multiplicity = config['waveform_nsb_tuning'].get('pre_computed_multiplicity', 10)
433-
logger.info('Tuning NSB on MC waveform from '
434-
+ str(np.asarray(nsb_original))
435-
+ ' to {0:d}%'.format(int(nsb_tuning_ratio * 100 + 100.5))
436-
+ ' for telescopes ids ' + str(config['source_config']['LSTEventSource']['allowed_tels']))
437-
nsb_tunner = WaveformNsbTunner(nsb_tuning_ratio,
438-
nsb_original,
439-
pulse_templates,
440-
charge_spe_cumulative_pdf,
441-
pre_computed_multiplicity)
435+
436+
allowed_tels = config['source_config']['LSTEventSource'][
437+
'allowed_tels']
438+
logger.info('Tuning NSB on MC waveform by adding ')
439+
logger.info(f'{nsb_tuning_rate:.3f} GHz for telescope ids:')
440+
logger.info(f'{allowed_tels}')
441+
442+
nsb_per_tel = {tel_id: nsb_tuning_rate * u.GHz for tel_id in
443+
allowed_tels}
444+
445+
nsb_tuner = WaveformNsbTuner(nsb_per_tel,
446+
pulse_templates,
447+
charge_spe_cumulative_pdf,
448+
pre_computed_multiplicity)
442449
else:
443450
logger.warning('NSB tuning on waveform active in config but file is real data, option will be ignored')
444451
nsb_tuning = False
445452

446453
lhfit_fitter = None
447-
if 'lh_fit_config' in config.keys():
454+
if 'lh_fit_config' in config:
448455
lhfit_fitter_config = {'TimeWaveformFitter': config['lh_fit_config']}
449456
lhfit_fitter = TimeWaveformFitter(subarray=subarray, config=Config(lhfit_fitter_config))
450457
if lhfit_fitter_config['TimeWaveformFitter']['use_interleaved']:
451458
tmp_source = EventSource(input_url=input_filename,
452459
config=Config(config["source_config"]))
453460
if is_simu:
454-
lhfit_fitter.get_ped_from_true_signal_less(tmp_source, nsb_tunner)
461+
lhfit_fitter.get_ped_from_true_signal_less(tmp_source, nsb_tuner)
455462
else:
456463
lhfit_fitter.get_ped_from_interleaved(tmp_source)
457464
del tmp_source
@@ -570,7 +577,7 @@ def r0_to_dl1(
570577
waveform = event.r1.tel[tel_id].waveform
571578
selected_gains = event.r1.tel[tel_id].selected_gain_channel
572579
mask_high = selected_gains == 0
573-
nsb_tunner.tune_nsb_on_waveform(waveform, tel_id, mask_high, subarray)
580+
nsb_tuner.tune_nsb_on_waveform(waveform, tel_id, mask_high, subarray)
574581

575582
# create image for all events
576583
r1_dl1_calibrator(event)

lstchain/scripts/lstchain_tune_nsb_waveform.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ def main():
8282

8383
config = read_configuration_file(args.config)
8484

85-
nsb_correction_ratio, data_ped_variance, mc_ped_variance = \
85+
extra_nsb_rate, data_ped_variance, mc_ped_variance = \
8686
calculate_required_additional_nsb(args.input_mc, args.input_data,
8787
config=Config(config))
8888

8989
dict_nsb = {
9090
"nsb_tuning": True,
91-
"nsb_tuning_ratio": np.round(nsb_correction_ratio, decimals=2),
91+
"nsb_tuning_rate_GHz": np.round(extra_nsb_rate, decimals=3),
9292
"spe_location": str(get_resource_path("data/SinglePhE_ResponseInPhE_expo2Gaus.dat"))
9393
}
9494

lstchain/scripts/tests/test_lstchain_scripts.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,16 @@ def test_validity_tune_nsb(tune_nsb):
236236

237237
def test_validity_tune_nsb_waveform(tune_nsb_waveform):
238238
"""
239-
The resulting nsb_tuning_ratio value of -1 expected in this test is meaningless
240-
because the input data do not allow a full test of the functionality.
241-
This test is only a formal check that the script runs.
239+
The resulting nsb_tuning_rate value of -1 expected in this test is
240+
meaningless because the input data do not allow a full test of the
241+
functionality. This test is only a formal check that the script runs.
242242
"""
243243
output_lines = tune_nsb_waveform.stdout.splitlines()
244244
for line in output_lines:
245245
if '"nsb_tuning"' in line:
246246
assert line == ' "nsb_tuning": true,'
247-
if '"nsb_tuning_ratio"' in line:
248-
assert line == ' "nsb_tuning_ratio": -1.0,'
247+
if '"nsb_tuning_rate"' in line:
248+
assert line == ' "nsb_tuning_rate": -1.0,'
249249
if '"spe_location"' in line:
250250
assert line == f' "spe_location": "{get_resource_path("data/SinglePhE_ResponseInPhE_expo2Gaus.dat")}"'
251251

0 commit comments

Comments
 (0)