Ejemplo n.º 1
0
def test_add():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    assert len(chargeres._df_list) == 1
    assert chargeres._df_list[0].index.size == 100
Ejemplo n.º 2
0
def test_add():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    assert len(chargeres._df_list) == 1
    assert chargeres._df_list[0].index.size == 100
    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"

        self.eventsource = EventSource(parent=self)

        self.calibrator = CameraCalibrator(parent=self,
                                           subarray=self.eventsource.subarray)
        self.calculator = ChargeResolutionCalculator()
Ejemplo n.º 4
0
def test_bin_dataframe():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()

    df = bin_dataframe(df_p, 20)
    assert "bin" in df.columns
    assert np.unique(df["bin"]).size <= 20
Ejemplo n.º 5
0
    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"

        self.eventsource = self.add_component(SimTelEventSource(parent=self))

        extractor = self.add_component(
            ImageExtractor.from_name(self.extractor_product, parent=self))

        self.calibrator = self.add_component(
            CameraCalibrator(parent=self, image_extractor=extractor))
        self.calculator = ChargeResolutionCalculator()
Ejemplo n.º 6
0
def test_bin_dataframe():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()

    df = bin_dataframe(df_p, 20)
    assert 'bin' in df.columns
    assert np.unique(df['bin']).size <= 20
Ejemplo n.º 7
0
def create_temp_cr_file(directory):
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()

    output_path = os.path.join(str(directory), "cr.h5")
    with pd.HDFStore(output_path, 'w') as store:
        store['charge_resolution_pixel'] = df_p
        store['charge_resolution_camera'] = df_c
    return output_path
Ejemplo n.º 8
0
    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"

        self.eventsource = SimTelEventSource(parent=self)

        extractor = ImageExtractor.from_name(self.extractor_product,
                                             parent=self)

        self.dl0 = CameraDL0Reducer(parent=self)

        self.dl1 = CameraDL1Calibrator(extractor=extractor, parent=self)

        self.calculator = ChargeResolutionCalculator()
Ejemplo n.º 9
0
def create_temp_cr_file(directory):
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()

    output_path = os.path.join(str(directory), "cr.h5")
    with pd.HDFStore(output_path, "w") as store:
        store["charge_resolution_pixel"] = df_p
        store["charge_resolution_camera"] = df_c
    return output_path
Ejemplo n.º 10
0
    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"
        kwargs = dict(config=self.config, parent=self)

        self.eventsource = SimTelEventSource(**kwargs)

        extractor = ChargeExtractor.from_name(self.extractor_product, **kwargs)

        self.r1 = HESSIOR1Calibrator(**kwargs)

        self.dl0 = CameraDL0Reducer(**kwargs)

        self.dl1 = CameraDL1Calibrator(extractor=extractor, **kwargs)

        self.calculator = ChargeResolutionCalculator()
Ejemplo n.º 11
0
def test_calculation():
    chargeres = ChargeResolutionCalculator()
    measured = np.array([3.5, 2.7])
    true = 3
    n = measured.size

    sum_ = np.sum(np.power(measured - true, 2))
    assert_almost_equal(sum_, 0.34, 3)
    assert_almost_equal(chargeres.rmse_abs(sum_, n), 0.412, 3)
    assert_almost_equal(chargeres.rmse(true, sum_, n), 0.137, 3)
    assert_almost_equal(chargeres.charge_res_abs(true, sum_, n), 1.780, 3)
    assert_almost_equal(chargeres.charge_res(true, sum_, n), 0.593, 3)

    assert chargeres.rmse_abs(sum_, n) == chargeres.rmse(true, sum_, n) * true
    assert (chargeres.charge_res_abs(
        true, sum_, n) == chargeres.charge_res(true, sum_, n) * true)
Ejemplo n.º 12
0
def test_amalgamate():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(1, true_charge, measured_charge)
    assert len(chargeres._df_list) == 3
    chargeres._amalgamate()
    assert len(chargeres._df_list) == 0
    assert chargeres._df.index.size == 200
Ejemplo n.º 13
0
def test_calculation():
    chargeres = ChargeResolutionCalculator()
    measured = np.array([3.5, 2.7])
    true = 3
    n = measured.size

    sum_ = np.sum(np.power(measured - true, 2))
    assert_almost_equal(sum_, 0.34, 3)
    assert_almost_equal(chargeres.rmse_abs(sum_, n), 0.412, 3)
    assert_almost_equal(chargeres.rmse(true, sum_, n), 0.137, 3)
    assert_almost_equal(chargeres.charge_res_abs(true, sum_, n), 1.780, 3)
    assert_almost_equal(chargeres.charge_res(true, sum_, n), 0.593, 3)

    assert chargeres.rmse_abs(sum_, n) == chargeres.rmse(true, sum_, n) * true
    assert (chargeres.charge_res_abs(true, sum_, n) ==
            chargeres.charge_res(true, sum_, n) * true)
Ejemplo n.º 14
0
def test_memory_limit():
    chargeres = ChargeResolutionCalculator()
    chargeres._max_bytes = 1
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    assert len(chargeres._df_list) == 0
    chargeres.add(0, true_charge, measured_charge)
    assert len(chargeres._df_list) == 0
Ejemplo n.º 15
0
def test_finish():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()
    assert np.array_equal(df_p['charge_resolution'].values,
                          df_c['charge_resolution'].values)
    chargeres.add(1, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()
    assert not np.array_equal(df_p['charge_resolution'].values,
                              df_c['charge_resolution'].values)
Ejemplo n.º 16
0
def test_amalgamate():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(1, true_charge, measured_charge)
    assert len(chargeres._df_list) == 3
    chargeres._amalgamate()
    assert len(chargeres._df_list) == 0
    assert chargeres._df.index.size == 200
Ejemplo n.º 17
0
def test_memory_limit():
    chargeres = ChargeResolutionCalculator()
    chargeres._max_bytes = 1
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    assert len(chargeres._df_list) == 0
    chargeres.add(0, true_charge, measured_charge)
    assert len(chargeres._df_list) == 0
Ejemplo n.º 18
0
def test_finish():
    chargeres = ChargeResolutionCalculator()
    true_charge = np.arange(100)
    measured_charge = np.arange(100)
    chargeres.add(0, true_charge, measured_charge)
    chargeres.add(0, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()
    assert np.array_equal(df_p['charge_resolution'].values,
                          df_c['charge_resolution'].values)
    chargeres.add(1, true_charge, measured_charge)
    df_p, df_c = chargeres.finish()
    assert not np.array_equal(df_p['charge_resolution'].values,
                              df_c['charge_resolution'].values)
Ejemplo n.º 19
0
def test_result_mc_true():
    chargeres = ChargeResolutionCalculator()
    measured = np.array([3.5, 2.7])
    true = 3
    n = measured.size
    sum_ = np.sum((measured - true)**2)

    chargeres.add(0, true, measured)
    df_p, df_c = chargeres.finish()
    assert df_p["charge_resolution"].values[0] == chargeres.charge_res(
        true, sum_, n)
    assert df_p["charge_resolution_abs"].values[0] == chargeres.charge_res_abs(
        true, sum_, n)
Ejemplo n.º 20
0
def test_result():
    chargeres = ChargeResolutionCalculator(mc_true=False)
    measured = np.array([3.5, 2.7])
    true = 3
    n = measured.size
    sum_ = np.sum(np.power(measured - true, 2))

    chargeres.add(0, true, measured)
    df_p, df_c = chargeres.finish()
    assert (df_p['charge_resolution'].values[0] == chargeres.rmse(
        true, sum_, n))
    assert (df_p['charge_resolution_abs'].values[0] == chargeres.rmse_abs(
        sum_, n))
Ejemplo n.º 21
0
def test_result():
    charge_res = ChargeResolutionCalculator(mc_true=False)
    measured = np.array([3.5, 2.7])
    true = 3
    n = measured.size
    sum_ = np.sum((measured - true)**2)

    charge_res.add(0, true, measured)
    df_p, df_c = charge_res.finish()
    resolution = df_p["charge_resolution"].values[0]
    assert resolution == charge_res.rmse(true, sum_, n)
    resolution_abs = df_p["charge_resolution_abs"].values[0]
    assert resolution_abs == charge_res.rmse_abs(sum_, n)
Ejemplo n.º 22
0
    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"

        self.eventsource = SimTelEventSource(parent=self)

        extractor = ImageExtractor.from_name(
            self.extractor_product,
            parent=self
        )

        self.dl0 = CameraDL0Reducer(parent=self)

        self.dl1 = CameraDL1Calibrator(extractor=extractor, parent=self)

        self.calculator = ChargeResolutionCalculator()
Ejemplo n.º 23
0
    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"
        kwargs = dict(config=self.config, tool=self)

        self.eventsource = SimTelEventSource(**kwargs)

        extractor = ChargeExtractorFactory.produce(**kwargs)

        self.r1 = HESSIOR1Calibrator(**kwargs)

        self.dl0 = CameraDL0Reducer(**kwargs)

        self.dl1 = CameraDL1Calibrator(extractor=extractor, **kwargs)

        self.calculator = ChargeResolutionCalculator()
Ejemplo n.º 24
0
def test_result_mc_true():
    chargeres = ChargeResolutionCalculator()
    measured = np.array([3.5, 2.7])
    true = 3
    n = measured.size
    sum_ = np.sum(np.power(measured - true, 2))

    chargeres.add(0, true, measured)
    df_p, df_c = chargeres.finish()
    assert (df_p['charge_resolution'].values[0] ==
            chargeres.charge_res(true, sum_, n))
    assert (df_p['charge_resolution_abs'].values[0] ==
            chargeres.charge_res_abs(true, sum_, n))
class ChargeResolutionGenerator(Tool):
    name = "ChargeResolutionGenerator"
    description = ("Calculate the Charge Resolution from a sim_telarray "
                   "simulation and store within a HDF5 file.")

    telescopes = List(Int,
                      None,
                      allow_none=True,
                      help='Telescopes to include from the event file. '
                      'Default = All telescopes').tag(config=True)
    output_path = Unicode(
        'charge_resolution.h5',
        help='Path to store the output HDF5 file').tag(config=True)
    extractor_product = tool_utils.enum_trait(
        ChargeExtractor, default='NeighbourPeakIntegrator')

    aliases = Dict(
        dict(
            f='SimTelEventSource.input_url',
            max_events='SimTelEventSource.max_events',
            T='SimTelEventSource.allowed_tels',
            extractor='ChargeResolutionGenerator.extractor_product',
            window_width='WindowIntegrator.window_width',
            window_shift='WindowIntegrator.window_shift',
            t0='SimpleIntegrator.t0',
            lwt='NeighbourPeakIntegrator.lwt',
            clip_amplitude='CameraDL1Calibrator.clip_amplitude',
            radius='CameraDL1Calibrator.radius',
            O='ChargeResolutionGenerator.output_path',
        ))

    classes = List([
        SimTelEventSource,
        CameraDL1Calibrator,
    ] + tool_utils.classes_with_traits(ChargeExtractor))

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.eventsource = None
        self.r1 = None
        self.dl0 = None
        self.dl1 = None
        self.calculator = None

    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"

        self.eventsource = SimTelEventSource(parent=self)

        extractor = ChargeExtractor.from_name(self.extractor_product,
                                              parent=self)

        self.r1 = HESSIOR1Calibrator(parent=self)

        self.dl0 = CameraDL0Reducer(parent=self)

        self.dl1 = CameraDL1Calibrator(extractor=extractor, parent=self)

        self.calculator = ChargeResolutionCalculator()

    def start(self):
        desc = "Extracting Charge Resolution"
        for event in tqdm(self.eventsource, desc=desc):
            self.r1.calibrate(event)
            self.dl0.reduce(event)
            self.dl1.calibrate(event)

            # Check events have true charge included
            if event.count == 0:
                try:
                    pe = list(event.mc.tel.values())[0].photo_electron_image
                    if np.all(pe == 0):
                        raise KeyError
                except KeyError:
                    self.log.exception('Source does not contain true charge!')
                    raise

            for mc, dl1 in zip(event.mc.tel.values(), event.dl1.tel.values()):
                true_charge = mc.photo_electron_image
                measured_charge = dl1.image[0]
                pixels = np.arange(measured_charge.size)
                self.calculator.add(pixels, true_charge, measured_charge)

    def finish(self):
        df_p, df_c = self.calculator.finish()

        output_directory = os.path.dirname(self.output_path)
        if not os.path.exists(output_directory):
            self.log.info(f"Creating directory: {output_directory}")
            os.makedirs(output_directory)

        with pd.HDFStore(self.output_path, 'w') as store:
            store['charge_resolution_pixel'] = df_p
            store['charge_resolution_camera'] = df_c

        self.log.info("Created charge resolution file: {}".format(
            self.output_path))
        Provenance().add_output_file(self.output_path)
Ejemplo n.º 26
0
class ChargeResolutionGenerator(Tool):
    name = "ChargeResolutionGenerator"
    description = ("Calculate the Charge Resolution from a sim_telarray "
                   "simulation and store within a HDF5 file.")

    telescopes = List(
        Int(),
        None,
        allow_none=True,
        help=
        "Telescopes to include from the event file. Default = All telescopes",
    ).tag(config=True)
    output_path = Unicode(
        "charge_resolution.h5",
        help="Path to store the output HDF5 file").tag(config=True)
    extractor_product = traits.enum_trait(ImageExtractor,
                                          default="NeighborPeakWindowSum")

    aliases = Dict(
        dict(
            f="SimTelEventSource.input_url",
            max_events="SimTelEventSource.max_events",
            T="SimTelEventSource.allowed_tels",
            extractor="ChargeResolutionGenerator.extractor_product",
            O="ChargeResolutionGenerator.output_path",
        ))

    classes = List([SimTelEventSource] +
                   traits.classes_with_traits(ImageExtractor))

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.eventsource = None
        self.calibrator = None
        self.calculator = None

    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"

        self.eventsource = self.add_component(SimTelEventSource(parent=self))

        extractor = self.add_component(
            ImageExtractor.from_name(
                self.extractor_product,
                parent=self,
                subarray=self.eventsource.subarray,
            ))

        self.calibrator = self.add_component(
            CameraCalibrator(
                parent=self,
                image_extractor=extractor,
                subarray=self.eventsource.subarray,
            ))
        self.calculator = ChargeResolutionCalculator()

    def start(self):
        desc = "Extracting Charge Resolution"
        for event in tqdm(self.eventsource, desc=desc):
            self.calibrator(event)

            # Check events have true charge included
            if event.count == 0:
                try:
                    pe = list(event.mc.tel.values())[0].photo_electron_image
                    if np.all(pe == 0):
                        raise KeyError
                except KeyError:
                    self.log.exception("Source does not contain true charge!")
                    raise

            for mc, dl1 in zip(event.mc.tel.values(), event.dl1.tel.values()):
                true_charge = mc.photo_electron_image
                measured_charge = dl1.image
                pixels = np.arange(measured_charge.size)
                self.calculator.add(pixels, true_charge, measured_charge)

    def finish(self):
        df_p, df_c = self.calculator.finish()

        output_directory = os.path.dirname(self.output_path)
        if not os.path.exists(output_directory):
            self.log.info(f"Creating directory: {output_directory}")
            os.makedirs(output_directory)

        with pd.HDFStore(self.output_path, "w") as store:
            store["charge_resolution_pixel"] = df_p
            store["charge_resolution_camera"] = df_c

        self.log.info("Created charge resolution file: {}".format(
            self.output_path))
        Provenance().add_output_file(self.output_path)
Ejemplo n.º 27
0
class ChargeResolutionGenerator(Tool):
    name = "ChargeResolutionGenerator"
    description = ("Calculate the Charge Resolution from a sim_telarray "
                   "simulation and store within a HDF5 file.")

    output_path = Unicode(
        'charge_resolution.h5',
        help='Path to store the output HDF5 file'
    ).tag(config=True)

    aliases = Dict(dict(
        f='SimTelEventSource.input_url',
        max_events='SimTelEventSource.max_events',
        T='SimTelEventSource.allowed_tels',
        extractor='ChargeExtractorFactory.product',
        window_width='ChargeExtractorFactory.window_width',
        t0='ChargeExtractorFactory.t0',
        window_shift='ChargeExtractorFactory.window_shift',
        sig_amp_cut_HG='ChargeExtractorFactory.sig_amp_cut_HG',
        sig_amp_cut_LG='ChargeExtractorFactory.sig_amp_cut_LG',
        lwt='ChargeExtractorFactory.lwt',
        clip_amplitude='CameraDL1Calibrator.clip_amplitude',
        radius='CameraDL1Calibrator.radius',
        max_pe='ChargeResolutionCalculator.max_pe',
        o='ChargeResolutionGenerator.output_path',
    ))
    classes = List([
        SimTelEventSource,
        ChargeExtractorFactory,
        CameraDL1Calibrator,
        ChargeResolutionCalculator
    ])

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.eventsource = None
        self.r1 = None
        self.dl0 = None
        self.dl1 = None
        self.calculator = None

    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"
        kwargs = dict(config=self.config, tool=self)

        self.eventsource = SimTelEventSource(**kwargs)

        extractor = ChargeExtractorFactory.produce(**kwargs)

        self.r1 = HESSIOR1Calibrator(**kwargs)

        self.dl0 = CameraDL0Reducer(**kwargs)

        self.dl1 = CameraDL1Calibrator(extractor=extractor, **kwargs)

        self.calculator = ChargeResolutionCalculator()

    def start(self):
        desc = "Extracting Charge Resolution"
        for event in tqdm(self.eventsource, desc=desc):
            self.r1.calibrate(event)
            self.dl0.reduce(event)
            self.dl1.calibrate(event)

            # Check events have true charge included
            if event.count == 0:
                try:
                    pe = list(event.mc.tel.values())[0].photo_electron_image
                    if np.all(pe == 0):
                        raise KeyError
                except KeyError:
                    self.log.exception(
                        'Source does not contain true charge!'
                    )
                    raise

            for mc, dl1 in zip(event.mc.tel.values(), event.dl1.tel.values()):
                true_charge = mc.photo_electron_image
                measured_charge = dl1.image[0]
                pixels = np.arange(measured_charge.size)
                self.calculator.add(pixels, true_charge, measured_charge)

    def finish(self):
        df_p, df_c = self.calculator.finish()

        output_directory = os.path.dirname(self.output_path)
        if not os.path.exists(output_directory):
            self.log.info("Creating directory: {}".format(output_directory))
            os.makedirs(output_directory)

        with pd.HDFStore(self.output_path, 'w') as store:
            store['charge_resolution_pixel'] = df_p
            store['charge_resolution_camera'] = df_c

        self.log.info("Created charge resolution file: {}"
                      .format(self.output_path))
        Provenance().add_output_file(self.output_path)
Ejemplo n.º 28
0
class ChargeResolutionGenerator(Tool):
    name = "ChargeResolutionGenerator"
    description = ("Calculate the Charge Resolution from a sim_telarray "
                   "simulation and store within a HDF5 file.")

    telescopes = List(Int, None, allow_none=True,
                      help='Telescopes to include from the event file. '
                           'Default = All telescopes').tag(config=True)
    output_path = Unicode(
        'charge_resolution.h5',
        help='Path to store the output HDF5 file'
    ).tag(config=True)
    extractor_product = tool_utils.enum_trait(
        ImageExtractor,
        default='NeighborPeakWindowSum'
    )

    aliases = Dict(dict(
        f='SimTelEventSource.input_url',
        max_events='SimTelEventSource.max_events',
        T='SimTelEventSource.allowed_tels',
        extractor='ChargeResolutionGenerator.extractor_product',
        O='ChargeResolutionGenerator.output_path',
    ))

    classes = List(
        [
            SimTelEventSource,
            CameraDL1Calibrator,
        ] + tool_utils.classes_with_traits(ImageExtractor)
    )

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.eventsource = None
        self.dl0 = None
        self.dl1 = None
        self.calculator = None

    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"

        self.eventsource = SimTelEventSource(parent=self)

        extractor = ImageExtractor.from_name(
            self.extractor_product,
            parent=self
        )

        self.dl0 = CameraDL0Reducer(parent=self)

        self.dl1 = CameraDL1Calibrator(extractor=extractor, parent=self)

        self.calculator = ChargeResolutionCalculator()

    def start(self):
        desc = "Extracting Charge Resolution"
        for event in tqdm(self.eventsource, desc=desc):
            self.dl0.reduce(event)
            self.dl1.calibrate(event)

            # Check events have true charge included
            if event.count == 0:
                try:
                    pe = list(event.mc.tel.values())[0].photo_electron_image
                    if np.all(pe == 0):
                        raise KeyError
                except KeyError:
                    self.log.exception(
                        'Source does not contain true charge!'
                    )
                    raise

            for mc, dl1 in zip(event.mc.tel.values(), event.dl1.tel.values()):
                true_charge = mc.photo_electron_image
                measured_charge = dl1.image[0]
                pixels = np.arange(measured_charge.size)
                self.calculator.add(pixels, true_charge, measured_charge)

    def finish(self):
        df_p, df_c = self.calculator.finish()

        output_directory = os.path.dirname(self.output_path)
        if not os.path.exists(output_directory):
            self.log.info(f"Creating directory: {output_directory}")
            os.makedirs(output_directory)

        with pd.HDFStore(self.output_path, 'w') as store:
            store['charge_resolution_pixel'] = df_p
            store['charge_resolution_camera'] = df_c

        self.log.info("Created charge resolution file: {}"
                      .format(self.output_path))
        Provenance().add_output_file(self.output_path)