From 62752822b94c06c99456ee5bcfec9db2ee10474b Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 22 Jul 2026 16:46:36 +0200 Subject: [PATCH] jungfrau calibration --- CMakeLists.txt | 56 --- include/BadChannels.hpp | 14 - include/JungfrauCalibration.hpp | 0 jfcal/JungfrauCalibration.py | 502 ++++++++++++++++++++ jfcal/JungfrauCalibrationParameters.py | 138 ++++++ jfcal/JungfrauCalibrationResult.py | 21 + jfcal/JungfrauFitParameters.py | 69 +++ jfcal/PlotHelpers.py | 139 ++++++ jfcal/Plotter.py | 213 +++++++++ jfcal/__init__.py | 15 +- jfcal/helpers.py | 6 +- jfcal/utils.py | 66 +++ jungfrauinput.json | 16 + notebooks/JFCalibration2.ipynb | 355 ++++++++++++++ python/jungfrau.config | 0 python/src/JungfrauCalibration.py | 96 ---- python/src/JungfrauCalibrationParameters.py | 77 --- python/src/helpers.py | 11 - src/BadChannels.cpp | 51 -- 19 files changed, 1534 insertions(+), 311 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 include/BadChannels.hpp delete mode 100644 include/JungfrauCalibration.hpp create mode 100644 jfcal/JungfrauCalibration.py create mode 100644 jfcal/JungfrauCalibrationParameters.py create mode 100644 jfcal/JungfrauCalibrationResult.py create mode 100644 jfcal/JungfrauFitParameters.py create mode 100644 jfcal/PlotHelpers.py create mode 100644 jfcal/Plotter.py create mode 100644 jfcal/utils.py create mode 100644 jungfrauinput.json create mode 100644 notebooks/JFCalibration2.ipynb delete mode 100644 python/jungfrau.config delete mode 100644 python/src/JungfrauCalibration.py delete mode 100644 python/src/JungfrauCalibrationParameters.py delete mode 100644 python/src/helpers.py delete mode 100644 src/BadChannels.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 113acf9..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -cmake_minimum_required(VERSION 3.15) - -project( - jungfraucalibration - DESCRIPTION "helper functions for Jungfrau calibration software" - HOMEPAGE_URL "https://gitea.psi.ch/detectors/JFCalibration2" - LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -include(FetchContent) - -option(JF_FETCH_AARE "Fetch aare library from github" ON) - -if(JF_FETCH_AARE) - FetchContent_Declare(aare GIT_REPOSITORY https://github.com/slsdetectorgroup/aare - GIT_TAG dev/jungfraucalibration) #use newest version - change to main once merged - FetchContent_MakeAvailable(aare) - install( - TARGETS aare_core - EXPORT ${TARGETS_EXPORT_NAME} - ) - install(TARGETS aare_compiler_flags - EXPORT ${TARGETS_EXPORT_NAME} - ) #mmh is this the way to go I think I will define the same compiler options twice now? can directly use aare_compiler_flags instead of compiler_flags - message(STATUS "target: aare") -else() - #set(AARE_INSTALL_PATH "/usr/local/aare" CACHE PATH "Installation directory for AARE") - list(APPEND CMAKE_PREFIX_PATH ${AARE_INSTALL_PATH}) - message(STATUS "looking for aare in: ${CMAKE_PREFIX_PATH}") - find_package(aare REQUIRED) - - if(TARGET aare_core) - message(STATUS "found aare_core target") - else() - message(FATAL_ERROR "aare_core target was not found!") - endif() - #message(STATUS "found aare: ${AARE_INCLUDE_DIRS}") -endif() - -set(SourceFiles - ${CMAKE_CURRENT_SOURCE_DIR}/src/BadChannels.cpp) - -add_library(jungfraucalibration STATIC ${SourceFiles} ${PUBLICHEADERS}) -target_include_directories( - jungfraucalibration PUBLIC "$") - -target_link_libraries(jungfraucalibration PUBLIC aare_core) # TODO: should it be public? - -# TODO: add other compile options? -target_compile_features(jungfraucalibration PRIVATE cxx_std_17) - -#add_subdirectory(examples) - diff --git a/include/BadChannels.hpp b/include/BadChannels.hpp deleted file mode 100644 index 8938857..0000000 --- a/include/BadChannels.hpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include "aare/JungfrauDataFile.hpp" -#include "aare/NDArray.hpp" - -using namespace aare; - -namespace jungfraucalibration -{ - - NDArray CreateBadChannelPixelMask(JungfrauDataFile &pedestal_file, const size_t num_pedestals_g0, const size_t num_pedestals_g1, const size_t num_pedestals_g2); - - NDArray CreateBadChannelPixelMask(JungfrauDataFile &pedestals_g0_file, const JungfrauDataFile &pedestals_g1_file, const JungfrauDataFile &pedestal_g2_file); - -} // namespace jungfraucalibration \ No newline at end of file diff --git a/include/JungfrauCalibration.hpp b/include/JungfrauCalibration.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/jfcal/JungfrauCalibration.py b/jfcal/JungfrauCalibration.py new file mode 100644 index 0000000..2ce96cc --- /dev/null +++ b/jfcal/JungfrauCalibration.py @@ -0,0 +1,502 @@ +import math +from pathlib import Path +from pyexpat import model +import time +from aare import JungfrauDataFile, File, Jungfrau, random_pixel +from jfcal.utils import get_first_file +import numpy as np +from dataclasses import dataclass +import logging +from functools import cached_property + +from aare import PedestalTrackingPixelHistogram + +#import pickle + +from aare import GaussianChargeSharingKb + +from jfcal.JungfrauFitParameters import FitParams, GAINTYPE + +from jfcal.JungfrauCalibrationParameters import JungfrauCalibrationParameters + +from jfcal.JungfrauCalibrationResult import JungfrauCalibrationResult + +@dataclass +class HistogramParameters: + adu_min : float = 600.5 # minimum ADU value to consider for the histogram + adu_max : float = 1400.5 # maximum ADU value to consider for the histogram + bin_width : int = 4 # width of each bin in the histogram + sigma_multiplier : float = 1.0 # used to determine the threshold for updating the pedestal - residuals less than sigma_multiplier*std are considered - for sigma_multiplier <= 0 no pedestal update + batch_size : int = 100 # number of frames to process in each batch - frames in a batch are loaded sequentially - once a batch was loaded processing of the histogram calculation starts + n_threads : int = 16 # number of threads to use for calculating the histogram + +logger = logging.getLogger(__name__) + +class JungfrauCalibration: + + def __init__(self, calibration_params: JungfrauCalibrationParameters, beam_energy : float = 8.0): + """ + Initialize calibration. + + Parameters + ---------- + calibration_params : JungfrauCalibrationParameters + The calibration parameters. + beam_energy : float, optional + The energy of the beam in keV. Default is 8.0 keV. + """ + self.calibration_params = calibration_params + + self._beam_energy : float = beam_energy # energy of the beam in keV + + self.bad_channel_mask : np.ndarray = None + self._ph_computer : PedestalTrackingPixelHistogram + + # TODO: easier to save but stored twice - e.g. also in ph_computer - pickle might really be the better option to save ph computer - but patching together mean etc. also has computational cost + self.histogram_values : np.ndarray + self.histogram_bin_edges : np.ndarray + self.pedestal_mean : np.ndarray + self.pedestal_std : np.ndarray + + self._n_rows : int = Jungfrau.rows + self._n_cols : int = Jungfrau.cols + + self.initial_fit_params : FitParams = None + + # If one wants to make those parameters configurable can still set fitmodel from outside class + self.fitmodel = GaussianChargeSharingKb(max_calls = 4000, compute_errors = False, tolerance = 1e-2) # K_\alpha, K_\beta, gaussian charge sharing model + + self.fit_result : dict = None # dictionary with "par" storing the fitted parameters and "chi2" storing the chi2 values for each pixel + + self.calibration_result : JungfrauCalibrationResult = JungfrauCalibrationResult(self.beam_energy) + + @property + def calibration_params(self) -> JungfrauCalibrationParameters: + return self._calibration_params + + @calibration_params.setter + def calibration_params(self, calibration_params : JungfrauCalibrationParameters): + if not isinstance(calibration_params, JungfrauCalibrationParameters): + raise ValueError("calibration_params must be an instance of JungfrauCalibrationParameters.") + self._calibration_params = calibration_params + + @property + def beam_energy(self) -> float: + return self._beam_energy + + @property + def ph_computer(self) -> PedestalTrackingPixelHistogram: + return self._ph_computer + + @ph_computer.setter + def ph_computer(self, ph_computer: PedestalTrackingPixelHistogram): + if not isinstance(ph_computer, PedestalTrackingPixelHistogram): + raise ValueError("ph_computer must be an instance of PedestalTrackingPixelHistogram.") + self.__dict__.pop("bin_centers", None) + self._ph_computer = ph_computer + + def calculate_bad_pixels_mask(self, save_result : bool = False): + """ + Calculate the bad pixels mask for the Jungfrau detector and store it under self.bad_channel_mask. A pixel is considered bad if it does not have the expected gain in one of the pedestal frames. + + Params: + save_result : bool, optional + Whether to save the bad pixels mask to a file. Default is False. + """ + + if(self.calibration_params.num_pedestals_g0 is not None and self.calibration_params.num_pedestals_g1 is not None and self.calibration_params.num_pedestals_g2 is not None): + + pedestal_file = JungfrauDataFile(get_first_file(self.calibration_params.pedestal_file_dir, self.calibration_params.pedestal_file_prefix)) + + # potential ROI + self._n_rows, self._n_cols = pedestal_file.rows, pedestal_file.cols + + t0 = time.perf_counter() + _, g0_pedestal_frames = pedestal_file.read_n(self.calibration_params.num_pedestals_g0) # TODO: option to only read gain? - mmh reading things twice from filesystem also bad - needed for pedestal calculation - but only for G0? + t1 = time.perf_counter()-t0 + logger.info(f'G0 pedestal file read took {t1:.2f}s or {self.calibration_params.num_pedestals_g0/t1:.2f} frames/s', flush=True) + _, g1_pedestal_frames = pedestal_file.read_n(self.calibration_params.num_pedestals_g1) + t1 = time.perf_counter()-t0 + logger.info(f'G1 pedestal file read took {t1:.2f}s or {self.calibration_params.num_pedestals_g1/t1:.2f} frames/s', flush=True) + _, g2_pedestal_frames = pedestal_file.read_n(self.calibration_params.num_pedestals_g2) + t1 = time.perf_counter()-t0 + logger.info(f'G2 pedestal file read took {t1:.2f}s or {self.calibration_params.num_pedestals_g2/t1:.2f} frames/s', flush=True) + + else: + pedestal_g0_file = JungfrauDataFile(get_first_file(self.calibration_params.pedestal_file_dir, self.calibration_params.pedestal_g0_file_prefix)) + pedestal_g1_file = JungfrauDataFile(get_first_file(self.calibration_params.pedestal_file_dir, self.calibration_params.pedestal_g1_file_prefix)) + pedestal_g2_file = JungfrauDataFile(get_first_file(self.calibration_params.pedestal_file_dir, self.calibration_params.pedestal_g2_file_prefix)) + + if(pedestal_g0_file.rows != pedestal_g1_file.rows or pedestal_g0_file.rows != pedestal_g2_file.rows or pedestal_g0_file.cols != pedestal_g1_file.cols or pedestal_g0_file.cols != pedestal_g1_file.cols or pedestal_g1_file.cols != pedestal_g2_file.cols): + raise ValueError("Pedestal files have different dimensions.") + + self._n_rows, self._n_cols = pedestal_g0_file.rows, pedestal_g0_file.cols + + t0 = time.perf_counter() + _, g0_pedestal_frames = pedestal_g0_file.read_n(pedestal_g0_file.total_frames()) + t1 = time.perf_counter()-t0 + logger.info(f'G0 pedestal file read took {t1:.2f}s or {pedestal_g0_file.total_frames()/t1:.2f} frames/s') + t0 = time.perf_counter() + _, g1_pedestal_frames = pedestal_g1_file.read_n(pedestal_g1_file.total_frames()) + t1 = time.perf_counter()-t0 + logger.info(f'G1 pedestal file read took {t1:.2f}s or {pedestal_g1_file.total_frames()/t1:.2f} frames/s') + t0 = time.perf_counter() + _, g2_pedestal_frames = pedestal_g2_file.read_n(pedestal_g2_file.total_frames()) + t1 = time.perf_counter()-t0 + logger.info(f'G2 pedestal file read took {t1:.2f}s or {pedestal_g2_file.total_frames()/t1:.2f} frames/s') + + # get gain from each pixel - update mask + bad_channel_mask = np.zeros((self._n_rows, self._n_cols), dtype=bool) # bad channels pixel mask + + t0 = time.perf_counter() + mask0 = np.any(g0_pedestal_frames >> 14 != 0, axis=0) + mask1 = np.any(g1_pedestal_frames >> 14 != 1, axis=0) + mask2 = np.any(g2_pedestal_frames >> 14 != 3, axis=0) + + self.bad_channel_mask = mask0 | mask1 | mask2 + + t1 = time.perf_counter()-t0 + logger.info(f'Bad channel mask calculation took {t1:.2f}s') + + if save_result: + self.save_bad_pixel_mask(self.calibration_params.output_dir / self.calibration_params.bad_pixel_mask_output_file) + + def save_bad_pixel_mask(self, output_file_path : Path): + """ + Save the bad pixels mask to a file. + + Params: + output_file_path: + Path : The path to the file to save the bad pixels mask to. + """ + + if self.bad_channel_mask is None: + raise ValueError("Bad channel mask has not been calculated yet. Please run calculate_bad_pixels_mask() first.") + + np.save(output_file_path, self.bad_channel_mask) + logger.info(f'Bad channel mask saved to {output_file_path}') + + def load_bad_pixel_mask(self, bad_pixel_mask_file_path : Path): + """ + Load the bad pixels mask from a file. + + Params: + bad_pixel_mask_file_path: + Path : The path to the file containing the bad pixels mask. + """ + + if not bad_pixel_mask_file_path.exists(): + raise ValueError(f"Bad pixel mask file {bad_pixel_mask_file_path} does not exist.") + + self.bad_channel_mask = np.load(bad_pixel_mask_file_path) + + def calculate_pedestal(self, adu_min : float = 600.5, adu_max : float = 1400.5, bin_width : int = 4, sigma_multiplier : float = 1.0, batch_size : int = 100, n_threads : int = 16): + """ + Calculate the pedestal for each pixel and sets up the Histogram class for further histogram calculations. + + Params: + adu_min : float, optional + The minimum ADU value to consider for the histogram. Default is 600.5. + adu_max : float, optional + The maximum ADU value to consider for the histogram. Default is 1400.5. + bin_width : int, optional + The width of each bin in the histogram. Default is 4. + sigma_multiplier : float, optional + Used to determine the threshold for updating the pedestal. Residuals less than sigma_multiplier * std are considered. For sigma_multiplier <= 0, there is no pedestal update. Default is 1.0. + batch_size : int, optional + The number of frames to process in each batch. Frames in a batch are loaded sequentially. Once a batch was loaded, processing of the histogram calculation starts. Default is 100. + n_threads : int, optional + The number of threads to use for calculating the histogram. Default is 16. + """ + + if(self.calibration_params.num_pedestals_g0 is not None): + pedestal_file_name = get_first_file(self.calibration_params.pedestal_file_dir, self.calibration_params.pedestal_file_prefix) + frames_to_read = self.calibration_params.num_pedestals_g0 # read twice now - bad - rather store - second option to pass view in PedestalTrackingHistogram + else: + pedestal_file_name = get_first_file(self.calibration_params.pedestal_file_dir, self.calibration_params.pedestal_g0_file_prefix) + frames_to_read = -1 # read all frames in file + + file = JungfrauDataFile(pedestal_file_name) + + if(file.rows != self._n_rows or file.cols != self._n_cols): + raise ValueError(f"Pedestal file {pedestal_file_name} has different dimensions than expected. Expected: ({self._n_rows}, {self._n_cols}), got: ({file.rows}, {file.cols})") + + num_bins = int((self._adu_max - self._adu_min) / self._bin_width) # number of bins in histogram + + if (self.bad_channel_mask is None): + logger.warning("Bad channel mask is not set. All pixels will be considered as good pixels for pedestal calculation.") + + # create histogram computer + self._ph_computer = PedestalTrackingPixelHistogram(rows = self._n_rows, cols = self._n_cols, n_bins = num_bins, xmin = adu_min, xmax = adu_max, n_threads = n_threads, max_pending = batch_size, n_sigma = sigma_multiplier, mask = self.bad_channel_mask) + + t0 = time.perf_counter() + + self._ph_computer.process_pedestal_file(pedestal_file_name, max_frames=frames_to_read, verbose=True) + + t1 = time.perf_counter()-t0 + + logger.info(f'Pedestal calculation took {t1:.2f}s or {frames_to_read/t1:.2f} frames/s') + + # TODO: set pedestal mean and std already here? - consistent with usage but recalculated in calculate_histogram + + def calculate_histogram(self, max_frames = None, save_result : bool = False): + """ + Calculate the histogram of each pixel. Update pedestal if residual data-pedestal within threshold std*sigma_multiplier. + + Params: + max_frames : int, optional + The maximum number of frames to process. If None, all frames in the raw file are processed. Default is None. + save_result : bool, optional + Whether to save the histogram to a file. Default is False. + """ + + # TODO: do we want one large histogram or one for pedestal peak, beta_peak, alpha_peak? + fname = get_first_file(self.calibration_params.raw_file_dir, self.calibration_params.raw_file_prefix_G0) + + max_frames = self.max_frames if self.max_frames is not None else File(fname).total_frames + + self._ph_computer.fill_from_file(fname, max_frames = max_frames, verbose = True) + + self.histogram_values = self._ph_computer.values() + self.histogram_bin_edges = self._ph_computer.bin_edges() + self.pedestal_mean = self._ph_computer.pedestal_mean() + self.pedestal_std = self._ph_computer.pedestal_std() + + if save_result: + self.save_histogram(self.calibration_params.output_dir / self.calibration_params.histogram_output_file) + + def save_histogram(self, histogram_file_path : Path): + """ + Save the histogram to a file. + + Params: + histogram_file_path: + Path : The path to the file to save the histogram to. + """ + + if self.histogram_values is None or self.histogram_bin_edges is None or self.pedestal_mean is None or self.pedestal_std is None: + raise ValueError("Histogram has not been calculated yet. Please run calculate_histogram() first.") + + # TODO: guess pickle is the best for intermediate saving - but maybe store as numpy as well - need to add support for pybind- a lot to store + #with open(output_dir / output_file_name, 'wb') as f: + # pickle.dump(self.ph_computer, f) + np.savez_compressed(histogram_file_path, values = self.histogram_values, bin_edges = self.histogram_bin_edges, pedestal_mean = self.pedestal_mean, pedestal_std = self.pedestal_std) + logger.info(f'Histogram saved to {histogram_file_path}') + + + def load_histogram(self, histogram_file_path : Path): + """ + Load the histogram from a file. + + Params: + histogram_file_path: + Path : The path to the file containing the histogram. + """ + + if not histogram_file_path.exists(): + raise ValueError(f"Histogram file {histogram_file_path} does not exist.") + + self.histogram_values, self.histogram_bin_edges, self.pedestal_mean, self.pedestal_std = np.load(histogram_file_path).values() + + @cached_property + def bin_centers(self) -> np.ndarray: + """ + Get the bin centers of the histogram. + + Returns: + np.ndarray: The bin centers of the histogram. + """ + + if self.histogram_bin_edges is None: + raise ValueError("Histogram has not been calculated yet. Please run calculate_histogram() first.") + + return self.histogram_bin_edges[:-1] + 0.5 * self.ph_computer.bin_width + + def estimate_initital_fit_params(self, gain_type : GAINTYPE = GAINTYPE.G0, elastic_scattering : bool = False): + """ + Estimate the initial fit parameters for the fitting. + + Params: + gain_type : GAINTYPE, optional + The gain type to use for the initial fit parameters. Default is GAINTYPE.G0 + elastic_scattering : bool, optional + Whether to include elastic scattering when estimating fit parameters. Default is False + """ + + self.initial_fit_params = FitParams(gain_type = gain_type) + + # estimate K_alpha_mean, K_alpha_peak + adc_counts = self.histogram_values # histogram values for each pixel + adc_bin_centers = self.bin_centers + + mean_K_alpha_mean : float = 0.0 + mean_K_alpha_amplitude : float = 0.0 + mean_elastic_scattering_intercept : float = 0.0 + mean_elastic_scattering_slope : float = 0.0 + + num_estimates : int = 3 # number of random pixels to estimate initial fit parameters from + + # TODO: is this neccessary is one enough? + for i in range(num_estimates): + is_bad_pixel : bool = True + while(is_bad_pixel): + pixel = random_pixel(0, self._n_rows, 0, self._n_cols) + is_bad_pixel = self.bad_channel_mask[pixel[0], pixel[1]] + + # TODO: maybe have sepearte function that only estimates amplitude and mean of K_alpha_peak + elastic_scattering_intercept, elastic_scattering_slope, K_alpha_mean, _, K_alpha_amplitude, _, _, _ = self.fitmodel.estimate_par(adc_bin_centers, adc_counts[pixel[0], pixel[1], :], elastic_scattering) + mean_K_alpha_mean += K_alpha_mean + mean_K_alpha_amplitude += K_alpha_amplitude + mean_elastic_scattering_intercept += elastic_scattering_intercept + mean_elastic_scattering_slope += elastic_scattering_slope + + self.initial_fit_params.K_alpha_mean.value = mean_K_alpha_mean / num_estimates + self.initial_fit_params.amplitude_K_alpha.value = mean_K_alpha_amplitude / num_estimates + + self.initial_fit_params.elastic_scattering_intercept.value = mean_elastic_scattering_intercept / num_estimates + self.initial_fit_params.elastic_scattering_slope.value = mean_elastic_scattering_slope / num_estimates + + def fit_function(self, fit_elastic_scattering : bool = False, initial_fit_params : FitParams = None, save_result : bool = False): + """ + Fit two Gaussian peaks for K_\alpha and K_beta including charge sharing to the histogram of each pixel. + + Params: + fit_elastic_scattering : bool, optional + Whether to fit the elastic scattering parameters. Default is False. + initial_fit_params : FitParams, optional + The initial fit parameters to use for the fitting. If None, the initial fit parameters estimated by estimate_initital_fit_params() are used. Default is None. + save_result : bool, optional + Whether to save the fitted parameters to a file. Default is False. + """ + + initial_fit_params = initial_fit_params if initial_fit_params is not None else self.initial_fit_params + + if initial_fit_params is None: + logger.warning("Initial fit parameters are not set. Estimating initial fit parameters.") + self.estimate_initital_fit_params(elastic_scattering = fit_elastic_scattering) + + self.fitmodel.SetParameter("p0", initial_fit_params.elastic_scattering_intercept.value) + self.fitmodel.SetParameter("p1", initial_fit_params.elastic_scattering_slope.value) + self.fitmodel.SetParameter("mu", initial_fit_params.K_alpha_mean.value) + self.fitmodel.SetParameter("sigma", initial_fit_params.sigma.value) + self.fitmodel.SetParameter("N", initial_fit_params.amplitude_K_alpha.value) + self.fitmodel.SetParameter("C", initial_fit_params.ratio_amplitude_charge_sharing.value) + self.fitmodel.SetParameter("kb_mean", initial_fit_params.ratio_mean_K_beta.value) + self.fitmodel.SetParameter("kb_frac", initial_fit_params.ratio_amplitude_K_beta.value) + + for param_idx, param in enumerate(initial_fit_params): + if param.lower_bound is not None and param.upper_bound is not None: + self.fitmodel.SetParLimits(param_idx, param.lower_bound, param.upper_bound) + elif param.lower_bound is not None: + self.fitmodel.SetParLimits(param_idx, param.lower_bound, math.inf) + elif param.upper_bound is not None: + self.fitmodel.SetParLimits(param_idx, -math.inf, param.upper_bound) + else: + pass + + if(not fit_elastic_scattering): + self.fitmodel.FixParameter("p0", self.initial_fit_params.elastic_scattering_intercept.value) + self.fitmodel.FixParameter("p1", self.initial_fit_params.elastic_scattering_slope.value) + + adc_counts = self.histogram_values # histogram values for each pixel + adc_bins = self.bin_centers # histogram bin centers for each pixel + + t0 = time.perf_counter() + res = self.fitmodel.fit(adc_bins, adc_counts, np.sqrt(adc_counts), n_threads = self.num_threads) + t = time.perf_counter()-t0 + logger.info(f'Fit took {t:.2f}s or {adc_counts.shape[0]*adc_counts.shape[1]/t:.2f} pixels/s') + + self.fit_result = res + + if save_result: + self.save_fitted_parameters(self.calibration_params.output_dir / self.calibration_params.fit_params_output_file) + + def save_fitted_parameters(self, fitted_parameters_file_path : Path): + """ + Save the fitted parameters to a file. + + Params: + fitted_parameters_file_path: + Path : The path to the file to save the fitted parameters to. + """ + + if self.fit_result is None: + raise ValueError("Fit result has not been calculated yet. Please run fit_function() first.") + + np.savez_compressed(fitted_parameters_file_path, par = self.fit_result["par"], chi2 = self.fit_result["chi2"]) + logger.info(f'Fitted parameters saved to {fitted_parameters_file_path}') + + def load_fitted_parameters(self, fitted_parameters_file_path : Path): + """ + Load the fitted parameters from a file. + + Params: + fitted_parameters_file_path: + Path : The path to the file containing the fitted parameters. + """ + + if not fitted_parameters_file_path.exists(): + raise ValueError(f"Fitted parameters file {fitted_parameters_file_path} does not exist.") + + self.fit_result = np.load(fitted_parameters_file_path) + + def calculate_G0(self): + """ + Calculate the G0 gain of the Jungfrau detector. + """ + self.calibration_result.G0 = self.fit_results["par"][:,:, 2]/self.beam_energy + + def calibrate_G0(self, histogram_params : HistogramParameters = HistogramParameters(), max_frames : int = None, elastic_scattering : bool = False, high_gain0 : bool = False, save_intermediate_results : bool = False): + """ + Calibrate the G0 gain of the Jungfrau detector. + + Params: + histogram_params : HistogramParameters, optional + The parameters for the histogram calculation. Default is HistogramParameters(). + max_frames : int, optional + The maximum number of frames to take into account for histogram calculation. If None, all frames in the raw file are used. + elastic_scattering : bool, optional + Whether to include elastic scattering when estimating fit parameters. Default is False. + high_gain0 : bool, optional + Whether to use high gain 0 for the calibration. Default is False. + save_intermediate_results : bool, optional + Whether to save intermediate results (bad pixel mask, histogram, fitted parameters) to files. + """ + gain_type = GAINTYPE.HG0 if high_gain0 else GAINTYPE.G0 + + self.calculate_bad_pixels_mask(save_intermediate_results) + self.calculate_pedestal(adu_min = histogram_params.adu_min, adu_max = histogram_params.adu_max, bin_width = histogram_params.bin_width, sigma_multiplier = histogram_params.sigma_multiplier, batch_size = histogram_params.batch_size, n_threads = histogram_params.n_threads) + self.calculate_histogram(save_intermediate_results) + self.estimate_initital_fit_params(gain_type = gain_type, elastic_scattering = elastic_scattering) + self.fit_function(elastic_scattering = elastic_scattering, save_result = save_intermediate_results) + self.calculate_G0() + + def calibrate_HG0(self, histogram_params : HistogramParameters = HistogramParameters(), max_frames : int = None, elastic_scattering : bool = False, save_intermediate_results : bool = False): + """ + Calibrate the HG0 gain of the Jungfrau detector. + + Params: + histogram_params : HistogramParameters, optional + The parameters for the histogram calculation. Default is HistogramParameters(). + max_frames : int, optional + The maximum number of frames to take into account for histogram calculation. If None, all frames in the raw file are used. + elastic_scattering : bool, optional + Whether to include elastic scattering when estimating fit parameters. Default is False. + save_intermediate_results : bool, optional + Whether to save intermediate results (bad pixel mask, histogram, fitted parameters) to files. + """ + self.calibrate_G0(histogram_params, max_frames, elastic_scattering, high_gain0 = True, save_intermediate_results = save_intermediate_results) + + + + + + + + + + + + + + diff --git a/jfcal/JungfrauCalibrationParameters.py b/jfcal/JungfrauCalibrationParameters.py new file mode 100644 index 0000000..8d0e755 --- /dev/null +++ b/jfcal/JungfrauCalibrationParameters.py @@ -0,0 +1,138 @@ +from pathlib import Path + +from dataclasses import dataclass + +import json + +import logging + +logger = logging.getLogger(__name__) + +# depercated decorator +def deprecated(message : str): + """ + Decorator to mark functions as deprecated. It will result in a warning being emitted when the function is used. + """ + def decorator(func): + def new_func(*args, **kwargs): + logger.warning(f"Call to deprecated function {func.__name__}. {message}") + return func(*args, **kwargs) + return new_func + return decorator + +@dataclass +class JungfrauInputParameters: + """ + A class to hold input parameters for the Jungfrau detector calibration. + """ + + _pedestal_file_dir : Path = None + + #deprecated - use pedestal_g0_file_prefix instead + _pedestal_file_prefix : str = None + _num_pedestals_g0 : int = 1000 + _num_pedestals_g1 : int = 1000 + _num_pedestals_g2 : int = 1000 + + pedestal_g0_file_prefix : str = None + pedestal_g1_file_prefix : str = None + pedestal_g2_file_prefix : str = None + + _raw_file_dir : Path = None + raw_file_prefix : str = None + + # outputs + _output_dir : Path = Path.cwd() # default to current working directory + + bad_pixel_mask_output_file : str = "bad_pixels_mask.npy" + + histogram_output_file : str = "histogram.npz" + + fit_params_output_file : str = "fit_parameters.npz" + + @classmethod + def from_config(cls, config_file : Path): + """ + Create an instance of JungfrauInputParameters from a json configuration file. + """ + cls = cls() + if( not (config_file.exists() and config_file.is_file())): + raise ValueError(f"Configuration file {config_file} does not exist or is not a file.") + + with open(config_file, 'r') as f: + config = json.load(f) + for key, value in config.items(): + if hasattr(cls, key): + if(value is not None): + setattr(cls, key, value) + else: + logger.warning(f"Unknown configuration parameter {key} in {config_file}.") + + + # TODO: maybe add HistogramParameters to JungfrauInputParameters and load them here as well. and all other parameters e.g. high_gain0, elastic_scattering etc. + + @property + def pedestal_file_dir(self) -> Path: + return self._pedestal_file_dir + + @pedestal_file_dir.setter + def pedestal_file_dir(self, filepath : Path): + if not filepath.exists(): + raise ValueError(f"Pedestal file directory {filepath} does not exist.") + self._pedestal_file_dir = filepath + + @deprecated("Setting pedestal_file_prefix is deprecated use a distinct file for each gain instead.") + @property + def pedestal_file_prefix(self) -> str: + return self._pedestal_file_prefix + + @pedestal_file_prefix.setter + def pedestal_file_prefix(self, file_prefix : str): + self._pedestal_file_prefix = file_prefix + + @property + def num_pedestals_g0(self) -> int: + return self._num_pedestals_g0 + + @deprecated("Setting num_pedestals_g0 is deprecated use different files for each gain instead.") + @num_pedestals_g0.setter + def num_pedestals_g0(self, num_pedestals : int): + self._num_pedestals_g0 = num_pedestals + + @property + def num_pedestals_g1(self) -> int: + return self._num_pedestals_g1 + + @deprecated("Setting num_pedestals_g1 is deprecated use different files for each gain instead.") + @num_pedestals_g1.setter + def num_pedestals_g1(self, num_pedestals : int): + self._num_pedestals_g1 = num_pedestals + + @property + def num_pedestals_g2(self) -> int: + return self._num_pedestals_g2 + + @deprecated("Setting num_pedestals_g2 is deprecated use different files for each gain instead.") + @num_pedestals_g2.setter + def num_pedestals_g2(self, num_pedestals : int): + self._num_pedestals_g2 = num_pedestals + + @property + def raw_file_dir(self) -> Path: + return self._raw_file_dir + + @raw_file_dir.setter + def raw_file_dir(self, filepath : Path): + if not filepath.exists(): + raise ValueError(f"Raw file directory {filepath} does not exist.") + self._raw_file_dir = filepath + + @property + def output_dir(self) -> Path: + return self._output_dir + + @output_dir.setter + def output_dir(self, filepath : Path): + if not filepath.exists(): + raise ValueError(f"Output directory {filepath} does not exist.") + self._output_dir = filepath diff --git a/jfcal/JungfrauCalibrationResult.py b/jfcal/JungfrauCalibrationResult.py new file mode 100644 index 0000000..c3aa29c --- /dev/null +++ b/jfcal/JungfrauCalibrationResult.py @@ -0,0 +1,21 @@ + +import numpy as np + +class JungfrauCalibrationResult: + def __init__(self, beam_energy : float): + """ + Class to store the results of the Jungfrau calibration. + + Parameters + ---------- + beam_energey : float + The energy of the beam in keV. + """ + + self.beam_energy : float = beam_energy # in keV -> should be frozen set by calibration + self.gain0 : np.ndarray + self.gain1 : np.ndarray + self.gain2 : np.ndarray + + + diff --git a/jfcal/JungfrauFitParameters.py b/jfcal/JungfrauFitParameters.py new file mode 100644 index 0000000..bfe1131 --- /dev/null +++ b/jfcal/JungfrauFitParameters.py @@ -0,0 +1,69 @@ + +from dataclasses import dataclass +from enum import Enum +from typing import ClassVar + +class GAINTYPE(Enum): + G0 = 0 # gain 0 + HG0 = 1 # high gain 0 + #G1 = 2 # gain 1 + #G2 = 3 # gain 2 + +@dataclass +class Parameter: + value : float # the value of the parameter + lower_bound : float = None # a parameter limit of None defaults to -infinity + upper_bound : float = None # a parameter limit of None defaults to infinity + +@dataclass +class FitParams: + + _CHARGE_SHARING_G0 : ClassVar[float] = 16.0 # sigma gaussian peaks used as initial guess + _CHARGE_SHARING_HG0 : ClassVar[float] = 29.0 # sigma gaussian peaks used as initial guess + _RATIO_CHARGE_SHARING_K_ALPHA_G0 : ClassVar[float] = 0.17 # ratio of charge sharing peak to K_alpha peak used as initial guess + _RATIO_CHARGE_SHARING_K_ALPHA_HG0 : ClassVar[float] = 0.14 + _RATIO_MEAN_K_BETA : ClassVar[float] = 1.12 # ratio of K_beta mean to K_alpha mean used as initial guess # 8.04 keV, 8.9 keV - 8.9/8.04 = 1.106 + _RATIO_AMPLITUDE_K_BETA_G0 : ClassVar[float] = 0.12 # ratio of K_beta amplitude to K_alpha amplitude used as initial guess + _RATIO_AMPLITUDE_K_BETA_HG0 : ClassVar[float] = 0.14 + + # module parameters for elastic scattering - moduled as linear function - only important for trailing edge of K_\beta peak + elastic_scattering_intercept : Parameter = Parameter(0.0, None, None) + elastic_scattering_slope : Parameter = Parameter(0.0, None, None) + + # module parameters for K_\alpha peak + K_alpha_mean : Parameter = Parameter(None, 850, 1350) # TODO: should there be a rule? for the bounds + amplitude_K_alpha : Parameter = Parameter(None, 0, 500) + + # noise + sigma : Parameter | None = None + + # module parameters for charge sharing + ratio_amplitude_charge_sharing : Parameter | None = None # amplitude_{charge_sharing}/amplitude_{K_\alpha} + + # module parameters for K_\beta peak + ratio_mean_K_beta : Parameter = Parameter(_RATIO_MEAN_K_BETA, 1.02, 1.30) # \mu_{K_\beta}/\mu_{K_\alpha} + ratio_amplitude_K_beta : Parameter | None = None # \amplitude_{K_\beta}/\amplitude_{K_\alpha} + + def __post_init__(self, gain_type : GAINTYPE = GAINTYPE.G0): + if gain_type == GAINTYPE.G0: + self.sigma = Parameter(FitParams._CHARGE_SHARING_G0, 5, 50) + self.ratio_charge_sharing = Parameter(FitParams._RATIO_CHARGE_SHARING_K_ALPHA_G0, None, None) + self.ratio_amplitude_K_beta = Parameter(FitParams._RATIO_AMPLITUDE_K_BETA_G0, 0.05, 0.4) + elif gain_type == GAINTYPE.HG0: + self.sigma = Parameter(FitParams._CHARGE_SHARING_HG0, 5, 50) + self.ratio_charge_sharing = Parameter(FitParams._RATIO_CHARGE_SHARING_K_ALPHA_HG0, None, None) + self.ratio_amplitude_K_beta = Parameter(FitParams._RATIO_AMPLITUDE_K_BETA_HG0, 0.05, 0.4) + else: + raise ValueError(f"Unsupported gain type: {gain_type}") + + def __iter__(self): + yield self.elastic_scattering_intercept + yield self.elastic_scattering_slope + yield self.K_alpha_mean + yield self.sigma + yield self.amplitude_K_alpha + yield self.ratio_amplitude_charge_sharing + yield self.ratio_mean_K_beta + yield self.ratio_amplitude_K_beta + + \ No newline at end of file diff --git a/jfcal/PlotHelpers.py b/jfcal/PlotHelpers.py new file mode 100644 index 0000000..57b45ca --- /dev/null +++ b/jfcal/PlotHelpers.py @@ -0,0 +1,139 @@ +from pprint import pp +import matplotlib.pyplot as plt +import numpy as np +from aare import add_colorbar + +def plot_histogram(histogram_data : np.ndarray, bin_edges : np.ndarray, Count_range : tuple[int, int] = None, bin_range : tuple[int, int] = None, label : str = None, title : str = None, xlabel : str = None, axis : plt.Axes = None) -> plt.Axes: + """ + Plot the histogram of the pedestal values. + + Parameters + ---------- + histogram_data : np.ndarray + The histogram data to plot. + bin_edges : np.ndarray + The edges of the bins for the histogram. + Count_range : tuple[int, int], optional + The range of counts to display on the y-axis. Default is None. + bin_range : tuple[int, int], optional + The range of bin values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None. + label : str, optional + The label for the histogram. Default is None. + title : str, optional + The title for the plot. Default is None. + xlabel : str, optional + The label for the x-axis. Default is None. + axis : plt.Axes, optional + The axis to plot on. If None, a new figure and axis will be created. + + Returns + ------- + plt.Axes + The axis with the histogram plot. + + """ + + if axis is None: + fig, ax = plt.subplots(figsize = (8,5)) + else: + ax = axis + + ax.stairs(histogram_data, bin_edges, label = label, zorder = 3) + + if bin_range is None: + bin_range = (bin_edges[0]-0.01*bin_edges[0], bin_edges[-1]+0.01*bin_edges[-1]) + + if Count_range is not None: + ax.set_ylim(*Count_range) + + ax.set_xlim(*bin_range) + ax.grid(zorder = 0) + ax.set_title(title) + ax.set_xlabel(xlabel) + ax.set_ylabel('Counts') + + if label is not None: + ax.legend() + + return ax + +def plot_fitted_function(histogram_data : np.ndarray, bin_edges : np.ndarray, function : callable, Count_range : tuple[int, int] = None, bin_range : tuple[int, int] = None, label : str = None, xlabel : str = None, title : str = None, axis : plt.Axes = None) -> plt.Axes: + + """ + Plot the histogram of the pedestal values along with the fitted function. + + Parameters + ---------- + histogram_data : np.ndarray + The histogram data to plot. + bin_edges : np.ndarray + The edges of the bins for the histogram. + function : callable + The fitted function to plot. + Count_range : tuple[int, int], optional + The range of counts to display on the y-axis. Default is None. + bin_range : tuple[int, int], optional + The range of bin values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None. + label : str, optional + The label for the fitted function. Default is None. + xlabel : str, optional + The label for the x-axis. Default is None. + title : str, optional + The title for the plot. Default is None. + axis : plt.Axes, optional + The axis to plot on. If None, a new figure and axis will be created. + + Returns + ------- + + plt.Axes + The axis with the histogram and fitted function plot. + + """ + + ax = plot_histogram(histogram_data, bin_edges, Count_range = Count_range, bin_range = bin_range, xlabel = xlabel, axis = axis, title = title) + + bin_centers = bin_edges[:-1] + np.diff(bin_edges)/2 + + ax.plot(bin_centers, function(bin_centers), label=label, color='red', zorder=4) + + if label is not None: + ax.legend(prop={"family": "monospace", "size": 10}, loc= 'upper left') + + return ax + +def plot_parameter(fit_parameter : np.ndarray, parameter_name : str, suppress_outliers : bool = True) -> None: + """ + Plot the parameter for all pixels. + + Parameters + ---------- + fit_parameter : np.ndarray + The parameter values to plot. + parameter_name : str + The name of the parameter to plot - used for plot title. + suppress_outliers : bool, optional + Whether to suppress outliers in the plot (True, don't plot outliers). Default is True. + """ + + fig, ax = plt.subplots(figsize = (15,5)) + im = ax.imshow(fit_parameter) + #suppress outliers for colorbar + if suppress_outliers: + mean = np.mean(fit_parameter) + std = np.std(fit_parameter) + im.set_clim(mean-3*std,mean+3*std) + ax.set_xlabel('Pixel X') + ax.set_ylabel('Pixel Y') + ax.set_title(parameter_name) + add_colorbar(ax, im) + plt.show() + + + + + + + + + diff --git a/jfcal/Plotter.py b/jfcal/Plotter.py new file mode 100644 index 0000000..a4e5273 --- /dev/null +++ b/jfcal/Plotter.py @@ -0,0 +1,213 @@ + +from jfcal import JungfrauCalibration + +from jfcal.PlotHelpers import plot_histogram, plot_fitted_function, plot_parameter + +from jfcal.utils import create_histogram_from_data + +import matplotlib.pyplot as plt + +from enum import Enum + +class Parameters(Enum): + ELASTIC_SCATTERING_INTERCEPT = "elastic_scattering_intercept" + ELASTIC_SCATTERING_SLOPE = "elastic_scattering_slope" + K_ALPHA_MEAN = "k_alpha_mean" + SIGMA = "sigma" + K_ALPHA_AMPLITUDE = "k_alpha_amplitude" + RATIO_AMPLITUDE_CHARGE_SHARING = "ratio_amplitude_charge_sharing" + RATIO_MEAN_K_BETA = "ratio_mean_k_beta" + RATIO_AMPLITUDE_K_BETA = "ratio_amplitude_k_beta" + +class Plotter: + def __init__(self, jungfrau_calibration : JungfrauCalibration): + self.calibration = jungfrau_calibration + + + def plot_ADU_histogram(self, pixel : tuple[int, int], Count_range : tuple[int, int] = None, ADU_range : tuple[int, int] = None, label = None, axis : plt.Axes = None, show_plot : bool = True) -> plt.Axes: + """ + Plot the histogram of ADU values for a specific pixel. + + Parameters + ---------- + pixel : tuple[int, int] + The pixel coordinates to plot the histogram for. + Count_range : tuple[int, int], optional + The range of counts to display on the y-axis. Default is None. + ADU_range : tuple[int, int], optional + The range of ADU values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None. + label : str, optional + The label for the histogram. Default is None. + axis : plt.Axes, optional + The axis to plot on. If None, a new figure and axis will be created. + show_plot : bool, optional + Whether to display the plot. Default is True. + + Returns + ------- + plt.Axes + The axis with the histogram plot. + + """ + + ax = plot_histogram(self.calibration.histogram_values[pixel[0], pixel[1], :], self.calibration.histogram_bin_edges, Count_range = Count_range, bin_range = ADU_range, label = label, title = f"ADU Histogram for pixel {pixel}", xlabel = "ADU", axis = axis) + + if show_plot: + plt.show() + + return ax + + + def plot_fitted_function(self, pixel : tuple[int, int], Count_range : tuple[int, int] = None, ADU_range : tuple[int, int] = None, axis : plt.Axes = None, show_plot : bool = True) -> plt.Axes: + """ + Plot the histogram of the ADU values along with the fitted function for a specific pixel. + + Parameters + ---------- + pixel : tuple[int, int] + The pixel coordinates to plot the histogram and fitted function for. + Count_range : tuple[int, int], optional + The range of counts to display on the y-axis. Default is None. + ADU_range : tuple[int, int], optional + The range of ADU values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None. + axis : plt.Axes, optional + The axis to plot on. If None, a new figure and axis will be created. + show_plot : bool, optional + Whether to display the plot. Default is True. + + Returns + ------- + plt.Axes + The axis with the histogram and fitted function plot. + """ + + function_parameters = self.calibration.fit_results["par"][pixel[0],pixel[1],:] + + variable_name_width = 8 + variable_width = 8 + decimal_places = 3 + + alpha = "\u03B1" + beta = "\u03B2" + sigma = "\u03C3" + mu = "\u03BC" + + fit_label = ( + f"{f'k{alpha}_{mu}:':<{variable_name_width}}{function_parameters[2]:>{variable_width}.{decimal_places}f}\n" + f"{f'{sigma}:':<{variable_name_width}}{function_parameters[3]:>{variable_width}.{decimal_places}f}\n" + f"{f'k{alpha}_N:':<{variable_name_width}}{function_parameters[4]:>{variable_width}.{decimal_places}f}\n" + f"{f'C:':<{variable_name_width}}{function_parameters[5]:>{variable_width}.{decimal_places}f}\n" + f"{f'k{beta}_m:':<{variable_name_width}}{function_parameters[6]:>{variable_width}.{decimal_places}f}\n" + f"{f'k{beta}_f:':<{variable_name_width}}{function_parameters[7]:>{variable_width}.{decimal_places}f}" + ) + + func = lambda x : self.calibration.fitmodel(x, function_parameters) + + ax = plot_fitted_function(self.calibration.histogram_values[pixel[0], pixel[1], :], self.calibration.histogram_bin_edges, function=func, Count_range = Count_range, bin_range = ADU_range, label = fit_label, xlabel = "ADU", title = f"Fitted Function for pixel {pixel}", axis = axis) + + if show_plot: + plt.show() + + return ax + + + def plot_fitted_parameter(self, parameter_name : str, suppress_outliers: bool = True): + """ + Plot the parameter for all pixels. + + Parameters + ---------- + parameter_name : str + The name of the parameter to plot. Must be one of the following: + "elastic_scattering_intercept", "elastic_scattering_slope", "k_alpha_mean", "sigma", "k_alpha_amplitude", "ratio_amplitude_charge_sharing", "ratio_mean_k_beta", "ratio_amplitude_k_beta". + suppress_outliers : bool, optional + Whether to suppress outliers in the plot. Default is True. + """ + match parameter_name: + case Parameters.ELASTIC_SCATTERING_INTERCEPT.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 0], parameter_name="Elastic scattering intercept", suppress_outliers=suppress_outliers) + case Parameters.ELASTIC_SCATTERING_SLOPE.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 1], parameter_name="Elastic scattering slope", suppress_outliers=suppress_outliers) + case Parameters.K_ALPHA_MEAN.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 2], parameter_name="Cu K_alpha mean", suppress_outliers=suppress_outliers) + case Parameters.SIGMA.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 3], parameter_name="Charge sharing sigma", suppress_outliers=suppress_outliers) + case Parameters.K_ALPHA_AMPLITUDE.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 4], parameter_name="Cu K_alpha amplitude", suppress_outliers=suppress_outliers) + case Parameters.RATIO_AMPLITUDE_CHARGE_SHARING.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 5], parameter_name="Charge sharing amplitude ratio", suppress_outliers=suppress_outliers) + case Parameters.RATIO_MEAN_K_BETA.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 6], parameter_name="Cu K_beta mean ratio", suppress_outliers=suppress_outliers) + case Parameters.RATIO_AMPLITUDE_K_BETA.value: + plot_parameter(self.calibration.fit_results["par"][:, :, 7], parameter_name="Cu K_beta amplitude ratio", suppress_outliers=suppress_outliers) + case _: + raise ValueError(f"Unknown parameter name: {parameter_name}. Valid options are: {[param.value for param in Parameters]}") + + def plot_parameter_histogram(self, parameter_name : str, bin_range : tuple[float, float] = None, bin_width : float = None, axis : plt.Axes = None, show_plot : bool = True) -> plt.Axes: + """ + Plot the histogram of the fitted parameter for all pixels. + + Parameters + ---------- + parameter_name : str + The name of the parameter to plot. Must be one of the following: + "elastic_scattering_intercept", "elastic_scattering_slope", "k_alpha_mean", "sigma", "k_alpha_amplitude", "ratio_amplitude_charge_sharing", "ratio_mean_k_beta", "ratio_amplitude_k_beta". + bin_range : tuple[float, float], optional + The range of bin values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None. + bin_width : float, optional + The width of the bins for the histogram. If None, it will be set to the default bin width of bin_range / 200. Default is None. + axis : plt.Axes, optional + The axis to plot on. If None, a new figure and axis will be created. + show_plot : bool, optional + Whether to display the plot. Default is True. + + Returns + ------- + plt.Axes + The axis with the histogram plot. + """ + + match parameter_name: + case Parameters.ELASTIC_SCATTERING_INTERCEPT.value: + data = self.calibration.fit_results["par"][:, :, 0].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Elastic scattering intercept", axis=axis) + case Parameters.ELASTIC_SCATTERING_SLOPE.value: + data = self.calibration.fit_results["par"][:, :, 1].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Elastic scattering slope", axis=axis) + case Parameters.K_ALPHA_MEAN.value: + data = self.calibration.fit_results["par"][:, :, 2].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"$k_\alpha$ mean", axis=axis) + case Parameters.SIGMA.value: + data = self.calibration.fit_results["par"][:, :, 3].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"$\sigma$", axis=axis) + case Parameters.K_ALPHA_AMPLITUDE.value: + data = self.calibration.fit_results["par"][:, :, 4].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"$k_\alpha$ amplitude", axis=axis) + case Parameters.RATIO_AMPLITUDE_CHARGE_SHARING.value: + data = self.calibration.fit_results["par"][:, :, 5].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Ratio amplitude charge sharing", axis=axis) + case Parameters.RATIO_MEAN_K_BETA.value: + data = self.calibration.fit_results["par"][:, :, 6].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Ratio $k_\beta$ mean", axis=axis) + case Parameters.RATIO_AMPLITUDE_K_BETA.value: + data = self.calibration.fit_results["par"][:, :, 7].flatten() + histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width) + ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Ratio $k_\beta$ amplitude", axis=axis) + case _: + raise ValueError(f"Unknown parameter name: {parameter_name}. Valid options are: {[param.value for param in Parameters]}") + + if show_plot: + plt.show() + + return ax + + + + \ No newline at end of file diff --git a/jfcal/__init__.py b/jfcal/__init__.py index 565dc95..4e2db94 100644 --- a/jfcal/__init__.py +++ b/jfcal/__init__.py @@ -1 +1,14 @@ -from .helpers import * \ No newline at end of file +from .helpers import * + +from .JungfrauCalibration import * + +from .JungfrauFitParameters import * + +from .JungfrauCalibrationParameters import * + +from .JungfrauCalibrationResult import * + +from .PlotHelpers import * + +from .Plotter import * + diff --git a/jfcal/helpers.py b/jfcal/helpers.py index 1c2865e..e5886bc 100644 --- a/jfcal/helpers.py +++ b/jfcal/helpers.py @@ -50,8 +50,4 @@ def get_fname(path, gain, label = 'CuFluo', index = -1): return file_sets[index] # -def get_fname(path : Path, file_prefix : str): - first_file = min(path.glob(str(Path)+f'{file_prefix}_*', default=None)) - if first_file is None: - raise ValueError(f"No files found in {path} with prefix {file_prefix}") - return first_file + diff --git a/jfcal/utils.py b/jfcal/utils.py new file mode 100644 index 0000000..4671688 --- /dev/null +++ b/jfcal/utils.py @@ -0,0 +1,66 @@ +import glob +from pathlib import Path + +import boost_histogram as bh +import numpy as np + +def get_first_file(path : Path, file_prefix : str): + """ + Get the first file with lowest index in directory that matches the given prefix. + """ + first_file = min(path.glob(f'{file_prefix}*'), default=None) + if first_file is None: + raise ValueError(f"No files found in {path} with prefix {file_prefix}") + return first_file + + +def save_fit_parameters(fit_params : dict, output_file : Path): + """ + Save the fit parameters to a text file. + + Parameters + ---------- + fit_params : dict + The fit parameters to save. + output_file : Path + The path to the output file. + """ + with open(output_file, 'w') as f: + for key, value in fit_params.items(): + f.write(f"{key}: {value}\n") + + +def create_histogram_from_data(data : np.ndarray, bin_range : tuple[float, float] = None, bin_width : float = None) -> bh.Histogram: + """ + Create a histogram from the given data. + + Parameters + ---------- + data : np.ndarray + The data to create the histogram from. + bin_range : tuple[float, float], optional + The range of the bins. Default is None, which means the range is determined from the data. + bin_width : float, optional + The width of each bin. Default is None, which means the number of bins is determined automatically. + + Returns + ------- + bh.Histogram + The created boost histogram. + """ + + if bin_range is None: + min = np.min(data) + max = np.max(data) + bin_range = (min - 0.05*(max - min), max + 0.05*(max - min)) # add 5% margin to the range + + if bin_width is None: + bins = 200 # 0.5 % + else: + bins = int((bin_range[1] - bin_range[0]) / bin_width) + + hist = bh.Histogram(bh.axis.Regular(bins, bin_range[0], bin_range[1])) + hist.fill(data) + return hist + + \ No newline at end of file diff --git a/jungfrauinput.json b/jungfrauinput.json new file mode 100644 index 0000000..bd7de06 --- /dev/null +++ b/jungfrauinput.json @@ -0,0 +1,16 @@ +{ + "pedestal_file_dir": "/mnt/sls_det_storage/jungfrau_calib/data/Module_749_Calib", + "pedestal_g0_file_prefix": null, + "pedestal_g1_file_prefix": null, + "pedestal_g2_file_prefix": null, + "pedestal_file_prefix": "pedeHG0_M749_2026-05-18_000000.dat", + "num_pedestals_g0": 1000, + "num_pedestals_g1": 1000, + "num_pedestals_g2": 1000, + "raw_file_dir": "/mnt/sls_det_storage/jungfrau_calib/data/Module_749_Calib", + "raw_file_prefix": "CuFluoHG0_M749_2026-05-18_", + "output_dir": "/mnt/sls_det_storage/jungfrau_calib/data/Module_749_Calib_output", + "bad_pixel_mask_output_file": null, + "histogram_output_file": null, + "fit_params_output_file": null +} \ No newline at end of file diff --git a/notebooks/JFCalibration2.ipynb b/notebooks/JFCalibration2.ipynb new file mode 100644 index 0000000..f54d4ec --- /dev/null +++ b/notebooks/JFCalibration2.ipynb @@ -0,0 +1,355 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "62ff76b0", + "metadata": {}, + "outputs": [], + "source": [ + "import jfcal \n", + "from jfcal import JungfrauCalibrationParameters, JungfrauCalibration, plot_histogram, plot_fitted_function\n", + "from jfcal import GAINTYPE\n", + "import aare\n", + "\n", + "from pathlib import Path\n", + "\n", + "# only needed for external plotting\n", + "import boost_histogram as bh\n", + "import uproot \n", + "import matplotlib.pyplot as plt\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a90018ea", + "metadata": {}, + "outputs": [], + "source": [ + "calibration_params = JungfrauCalibrationParameters()\n", + "\n", + "calibration_params.pedestal_file_dir = Path(\"/mnt/sls_det_storage/jungfrau_calib/data/Module_749_Calib\")\n", + "\n", + "calibration_params.pedestal_file_prefix = \"pedeHG0_M749_2026-05-18_000000.dat\"\n", + " \n", + "calibration_params.num_pedestals_g0 = 1000\n", + "calibration_params.num_pedestals_g1 = 1000\n", + "calibration_params.num_pedestals_g2 = 1000\n", + "\n", + "calibration_params.raw_file_dir = calibration_params.pedestal_file_dir\n", + "\n", + "calibration_params.output_dir = Path(\"/mnt/sls_det_storage/jungfrau_calib/data/Module_749_Calib_output\") \n", + "\n", + "calibration_params.raw_file_prefix = \"CuFluoHG0_M749_2026-05-18_\" " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2e6e8b1d", + "metadata": {}, + "outputs": [], + "source": [ + "jungfrau_calibration = JungfrauCalibration(calibration_params)\n", + "\n", + "jungfrau_calibration.adu_min = 600.5\n", + "\n", + "jungfrau_calibration.adu_max = 1400.5\n", + "\n", + "jungfrau_calibration.bin_width = 4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb4f180e", + "metadata": {}, + "outputs": [], + "source": [ + "jungfrau_calibration.calculate_bad_pixels_mask(output_file_name=\"bad_pixels_mask.npy\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "09214f6f", + "metadata": {}, + "outputs": [], + "source": [ + "jungfrau_calibration.load_bad_pixel_mask(Path(\"/mnt/sls_det_storage/jungfrau_calib/data/Module_708_Calib_output/bad_pixels_mask.npy\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b73072c7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Progress: 1000/1000 (100.0%) 2330.7 FPS \n", + "\n", + "Pedestal calculation took 0.45s or 2201.65 frames/s\n" + ] + } + ], + "source": [ + "jungfrau_calibration.calculate_pedestal() \n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "12aadbd5", + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'JungfrauCalibrationParameters' object has no attribute 'raw_file_prefix_G0'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mjungfrau_calibration\u001b[49m\u001b[43m.\u001b[49m\u001b[43mcalculate_histogram\u001b[49m\u001b[43m(\u001b[49m\u001b[43moutput_file_name\u001b[49m\u001b[43m=\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mhistogram.npz\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/Documents/JFCalibration2/jfcal/JungfrauCalibration.py:224\u001b[39m, in \u001b[36mJungfrauCalibration.calculate_histogram\u001b[39m\u001b[34m(self, gain_type, output_file_name)\u001b[39m\n\u001b[32m 216\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mcalculate_histogram\u001b[39m(\u001b[38;5;28mself\u001b[39m, gain_type : GAINTYPE = GAINTYPE.G0, output_file_name : \u001b[38;5;28mstr\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m):\n\u001b[32m 217\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m 218\u001b[39m \u001b[33;03m Calculate the histogram of each pixel. Update pedestal if residual data-pedestal within a certain threshold. \u001b[39;00m\n\u001b[32m 219\u001b[39m \n\u001b[32m 220\u001b[39m \u001b[33;03m Returns:\u001b[39;00m\n\u001b[32m 221\u001b[39m \u001b[33;03m np.ndarray: The histogram for each pixel value \u001b[39;00m\n\u001b[32m 222\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m224\u001b[39m raw_file_prefix = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mcalibration_params\u001b[49m\u001b[43m.\u001b[49m\u001b[43mraw_file_prefix_G0\u001b[49m \u001b[38;5;28;01mif\u001b[39;00m gain_type == GAINTYPE.G0 \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m.calibration_params.raw_file_prefix_HG0 \n\u001b[32m 226\u001b[39m \u001b[38;5;66;03m# TODO: do we want one large histogram or one for pedestal peak, beta_peak, alpha_peak? \u001b[39;00m\n\u001b[32m 227\u001b[39m fname = get_first_file(\u001b[38;5;28mself\u001b[39m.calibration_params.raw_file_dir, raw_file_prefix)\n", + "\u001b[31mAttributeError\u001b[39m: 'JungfrauCalibrationParameters' object has no attribute 'raw_file_prefix_G0'" + ] + } + ], + "source": [ + "jungfrau_calibration.calculate_histogram(output_file_name=\"histogram.npz\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "9b9a2094", + "metadata": {}, + "outputs": [], + "source": [ + "jungfrau_calibration.load_histogram(calibration_params.output_dir / \"histogram.npz\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f31b03cc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(46, 407)\n" + ] + }, + { + "data": { + "image/png": "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9gL7+PiIx8THx4u9xiqVCtnZ2UhMTDToJY6Pj0fHjh0LvbZcLodcLi+wXSaTVf8fVKn2JZdJpUAZ79Vs8TJjmyo7q/gZMzPGzHSMmekYM9MxZqZjzEynH7PyjJ3FBtX16NEDFy5cwLlz58Svtm3bYsiQITh37hzq1asHlUpl0FWenZ2Nw4cPi8lumzZtIJPJDI65d+8eLl68WGRCTERERESkY7EeYicnJwQEBBhsc3BwgIeHh7h9ypQpWLBgARo0aIAGDRpgwYIFUCqVeOuttwAALi4uGDlyJKZPnw4PDw+4u7tjxowZaN68OQIDAyv8noiIiIio6rH4LBNF+eCDD6BWqzFu3DgkJibiueeew759++Dk5CQe880330AqlWLgwIFQq9Xo0aMHQkJCYGtra8GWExEREVFVUakS4kOHDhk8lkgkmDt3LubOnVvoc+zt7bFixQqsWLGifBtHRERERNWSxRfmICIiIiKyJCbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbE1iYjwdItICIiIqpUmBBbk6TbwJZgQKYElB6Wbg0RERFRpSC1dAOoAmU8AjQZwNBtgKu/pVtDREREVCmwh9gaKT0t3QIiIiKiSoMJMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkxEREREVo0JMRERERFZNSbERERERGTVmBATERERkVVjQkyVR8I1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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pixel = aare.random_pixel(0,jungfrau_calibration._n_cols,0,jungfrau_calibration._n_rows)\n", + "print(pixel)\n", + "pixel = (128, 806)\n", + "ax = plot_histogram(jungfrau_calibration.histogram_values, jungfrau_calibration.histogram_bin_edges, pixel_to_plot = pixel, Count_range = (0,500))\n", + "\n", + "previous_histogram = Path(\"/mnt/sls_det_storage/jungfrau_calib/ana/M749_CalibAna/CuFluo_HG0_file0to19.root\")\n", + "\n", + "file_index, pixel_index = jfcal.helpers.row_col_to_file_and_pixel_index(*pixel)\n", + "with uproot.open(previous_histogram) as f:\n", + " root_hist = f[f'adc2d_{file_index+1}'].to_boost()\n", + "\n", + "rh = root_hist[bh.rebin(4),pixel_index] #rebinning of 4 is used for fitting \n", + "\n", + "_ = plot_histogram(np.expand_dims(rh.values(), axis=(0, 1)), rh.axes[0].edges[:], pixel_to_plot = (0,0), Count_range = (0,500), axis=ax)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28a5e6a2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.85, 0.0, 1062.5, 13.589148804608305, 200.15, 0.10492130901823632, 1.1, 0.1]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "jungfrau_calibration.fitmodel.estimate_par(jungfrau_calibration.histogram_bin_edges + 0.5 * jungfrau_calibration.bin_width, jungfrau_calibration.histogram_values[10,10,:])\n", + "\n", + "# elastic scattering intercept, elastic scattering slope, K_alpha mean, sigma, amplitude K_alpha, ratio amplitude charge sharing, K_beta mean ratio , K_beta fraction\n", + "\n", + "#0, 0, 29, 0.14, 1.12, 0.14 \n", + "#maybe no hardcoded parameter values? \n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "65e3403e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fit took 107.43s or 4880.47 pixels/s\n" + ] + } + ], + "source": [ + "jungfrau_calibration.estimate_initital_fit_params(gain_type=GAINTYPE.HG0)\n", + "jungfrau_calibration.fit_function(output_file_name=\"fitted_parameters.npz\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4f36ed22", + "metadata": {}, + "outputs": [], + "source": [ + "jungfrau_calibration.load_fitted_parameters(calibration_params.output_dir / \"fitted_parameters.npz\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6ea31158", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/mazzol_a/Documents/JFCalibration2/jfcal/Plothelpers.py:50: UserWarning: No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.\n", + " ax.legend()\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAr4AAAHUCAYAAADcACvUAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQAAnYdJREFUeJzs3Xd4VFX+x/H3pPdGII0AofcixYJSpKgIFlAUVkVFpQiKgAURxV2wK/rDhbWj7iKs2FhQEFRABJRikGIBCRBCAiSkJ6Te3x9DxgzpySQzST6v55knM/eee+73nkySb86ce47JMAwDEREREZEGzsneAYiIiIiI1AUlviIiIiLSKCjxFREREZFGQYmviIiIiDQKSnxFREREpFFQ4isiIiIijYISXxERERFpFJT4ioiIiEijoMRXRERERBoFJb4iDu7//u//MJlMdO3atcwyJpPJ8nB2diYwMJAePXowadIkduzYUaL8pk2bMJlMrFq1qtT6pk2bhslkqjC2O++8Ex8fnzL3+/j4cOedd1peHz16FJPJxLJlyyqsu7jly5fz6quvVumYhig3N5fJkycTFhaGs7MzPXv2tHdIFiaTifnz59da/XfeeSetWrWqdPkhQ4YwefJkq21PPPEEI0eOJCIiApPJZPXeLO7tt9/mhhtuoFWrVnh6etK2bVumTJlCfHx8ibJpaWnMnTuX9u3b4+XlRUREBDfffDMHDhyoyuVZMQyDt956i969e+Pn50eTJk0YOHAga9euLbX84sWL6dixI+7u7kRFRfH000+Tl5dXatkvvviCgQMH4ufnh7e3N126dOHNN9+07M/Ly6NNmzb6eZMGS4mviIN79913AThw4AA//vhjmeVuuukmtm/fztatW1mxYgV33HEHO3bs4NJLL+XBBx+sq3DLFRYWxvbt27n22murdJwSX7OlS5fyxhtvMHfuXLZu3cqHH35o75Astm/fzj333GPvMABzcvfDDz8wb948q+2LFi0iKSmJ6667Djc3tzKPf+qpp/Dx8eGZZ55h3bp1PPLII6xZs4bevXtz6tQpq7KjRo3i1Vdf5d5772Xt2rU899xzREdHc+mll3Ls2LFqxf/UU09x33330a9fPz755BOWLVuGu7s7I0eO5NNPP7Uqu3DhQh588EFGjx7N+vXrmTp1Ks888wz3339/iXqfe+45Ro8eTdeu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/XXj22+/NebOnWs4Ozsb48ePL3F80TCOC39mROo79fiKOKh33nkHT09PS6+Rj48PN998M99//z2HDh2qUl1GLX5c6enpyc6dO0t9eHp6Vnh8v379WLZsGQsWLGDHjh0VfuRf3Lfffou3tzc33XST1faiu/W/+eYbwNxbBzB27FircuPGjSuz7tJ6QjMyMnj00Udp27YtLi4uuLi44OPjQ2ZmJr/++muJ8iNHjrR63alTJ4ASN/d16tSp2jdCffvttwAlZii4+eab8fb2trRBke7du9O+fftK1+/r68t1111ntW38+PEUFhayZcuWco/t378/Cxcu5NVXX2XKlCncdtttTJw40bJ/zZo1mEwmbrvtNqtPCkJDQ+nRowebNm2qdJxFTp48WepQheo6d+4co0eP5tixY3z88cclZjGZMmUKn3zyCYsWLWLz5s2sXLkSNzc3rrzyymp/T9977z0efPBBpk2bxsaNG/nyyy8ZPnw4119/PevXr7cqW97sK8X3FRYWkp6ezpIlS7j//vsZPHgwCxYsYPr06SxfvpzDhw9bHVvUhnFxcdW6BhFHpcRXxAEdPnyYLVu2WD7KTklJISUlxZLgFc30UFlFf4DDw8MBcHFxASgxTrNIfn6+pUxFnJyc6NOnT6mPyoypXLlyJRMmTODtt9/m0ksvJSgoiDvuuIOEhIQKj01KSiI0NLTEH/9mzZrh4uJiGS6RlJSEi4sLQUFBVuVCQkLKrDssLKzEtvHjx/P6669zzz33sH79en766Sd27txJ06ZNyc7OLlH+wvMVzSRQ2vZz586Vc6VlK7q2pk2bWm03mUyEhoaWuDO/tOsqT2ltFBoaajl3Rf72t7/h5uZGTk4ODz/8sNW+U6dOYRgGISEhuLq6Wj127NhR6vCRimRnZ1d7bO2FcnJyuPHGG9m6dSurV6/m4osvttpfNBzhjTfeYMaMGQwYMICxY8eyYcMGzp49W63p3ZKTk7n//vu55557eOmllxgyZAjXXHONZdhT8SnamjRpwrlz50od93/27Fmr91mTJk0AuOqqq6zKXXPNNYB5CExxRW1Y2vtapD6r3F82EalT7777LoZhsGrVqlLn2n3//fdZsGABzs7OFdaVnZ3Nxo0badOmDc2bNwf+SmbK6s2Ji4srNym0peDgYF599VVeffVVjh8/zurVq3nsscc4ffo069atK/fYJk2a8OOPP2IYhlXye/r0afLz8wkODraUy8/PL5EMlJdcX5hMp6amsmbNGp566ikee+wxy/acnBzOnj1bpWu2paJrO3PmjFXyaxgGCQkJ9O3b16p8ZeZnLq60cbZF7VaUTJWloKCAv/3tbwQGBuLu7s7EiRP54YcfLP8ABAcHYzKZ+P7773F3dy9xfGnbKhIcHGyT70dOTg433HAD3333HV988QVDhgwpUSY6OhqgRBsHBATQtm3bao2P/f3338nOzi5RJ0CfPn3YvHkzGRkZ+Pj4WMb27tu3zyopT0hIIDEx0Wru7+7du5f6fi/6NOjCf1KL2rDoZ0ikoVCPr4iDKSgo4P3336dNmzZ89913JR6zZs0iPj6er776qlJ1TZs2jaSkJB599FHL9nbt2tGyZUs+/vjjEsMgzpw5w3fffcfQoUNtfm0VadGiBdOmTWPYsGFWPVDu7u6l9jwNGTKEjIwMq7vXAT744APLfoCBAwcC5t7l4lasWFHp2EwmE4ZhlEjG3n777TJ7zutC0TX++9//ttr+ySefkJmZWWrCVhXp6emsXr3aatvy5ctxcnKq8Aayp556iu+//57//Oc/rFy5kr1791r1+o4cORLDMIiLiyv1E4MLb9qqjI4dO1Z7RogiRT293377LZ988kmJXtIiRZ+gXLhITFJSEn/88YflH82qKKtOwzDYsWMHgYGBlhsDr776ajw8PEosCFM0q8gNN9xg2VY0dOfC3xtffvklTk5OJRLtojbs3Llzla9BxJGpx1fEwXz11VecPHmS559/nkGDBpXY37VrV15//XXeeecdqzGkp06dYseOHRiGQXp6Ovv37+eDDz5g7969PPTQQ9x7771W9bz00kuMHTuWIUOGcO+99xIaGsqhQ4d47rnncHNzKzH5f21ITU1l8ODBjB8/no4dO+Lr68vOnTtZt26d1awM3bp149NPP2Xp0qX07t3bMrzijjvu4J///CcTJkzg6NGjdOvWja1bt/LMM88wYsQIS/J+9dVX079/f2bNmkVaWhq9e/dm+/btlgS5MkMy/Pz8GDBgAC+++CLBwcG0atWKzZs3884771imr7KHYcOGcdVVV/Hoo4+SlpZG//79+eWXX3jqqafo1atXqdN6VUWTJk2YMmUKx48fp3379nz55Ze89dZbTJkyhRYtWpR53IYNG3j22WeZN2+eJfl+9tlnmT17NoMGDeLGG2+kf//+3Hfffdx1113s2rWLAQMG4O3tTXx8PFu3bqVbt25MmTKlSvEOGjSId999lz/++KPEWObNmzdz5swZwPxP4bFjxyyfqAwcONDSY37TTTfx1VdfMXfuXJo0aWKVhPr5+VmSwdGjR/Pkk08yZcoUTpw4wUUXXUR8fDwvvvgiWVlZJWa+MJlMDBw4sNyxyy1atGD06NG8+eabuLu7M2LECHJycnj//ff54Ycf+Mc//mHptQ8KCuKJJ55g3rx5BAUFMXz4cHbu3Mn8+fO55557rJLWu+66izfeeIOpU6eSmJhI586d2bhxI//85z+ZOnUqLVu2tIpjx44dtTI7hojd2eeeOhEpyw033GC4ubkZp0+fLrPMrbfeari4uBgJCQmGYRhWd5Q7OTkZfn5+Rrdu3Yz77rvP2L59e5n1bNy40Rg+fLgREBBguLi4GGFhYcZtt91mHDp0qFKxVnUBiwtndTh37pwxefJko3v37oafn5/h6elpdOjQwXjqqaesFo04e/ascdNNNxkBAQGGyWSymnEiKSnJmDx5shEWFma4uLgYLVu2NObMmWOcO3fOKpazZ88ad911lxEQEGB4eXkZw4YNM3bs2GEAVjMyFM3qcObMmRLXc+LECWPMmDFGYGCg4evra1x99dXG/v37jZYtW1pdZ9GsDjt37rQ6vqy6K2rHisplZ2cbjz76qNGyZUvD1dXVCAsLM6ZMmWIkJydblWvZsqVx7bXXVnieIgMHDjS6dOlibNq0yejTp4/h7u5uhIWFGY8//riRl5dnVZZiszqcPHnSaNasmXHllVdaLRpRWFhojBo1yggICLCa9eDdd981Lr74YsPb29vw9PQ02rRpY9xxxx3Grl27rK69MrM6pKamGj4+PiVmuSi6nuI/K8Uf3333ndW1lPUYOHCgVZ3x8fHGtGnTjLZt2xoeHh5GeHi4ce2115b4uUtPTzeAUhfWuFB2drbx4osvGt27dzd8fX2NoKAg45JLLjH+/e9/G4WFhSXKv/baa0b79u0NNzc3o0WLFsZTTz1l5ObmliiXlJRkTJo0yQgJCTFcXV2N9u3bGy+++KLV96jIFVdcYYwaNarCWEXqG5NhaHZqEWmcli9fzt/+9jd++OEHLrvsMnuH43AGDRpEYmJivZvLdfr06XzzzTccOHCgymOaa8uXX37JyJEj2bt3b7WGcNSlP//8k3bt2rF+/XqGDRtm73BEbEqJr4g0Ch999BFxcXF069YNJycnduzYwYsvvkivXr0s052Jtfqa+J46dYr27dvzzjvvlJjqzl4efvhh4uLiWL58ub1DqdBdd93FiRMn2LBhg71DEbE5jfEVkUbB19eXFStWsGDBAjIzMwkLC+POO+9kwYIF9g5NbCwkJIT//Oc/JCcn2zsUC0dYMrwy8vPzadOmDXPmzLF3KCK1Qj2+IiIiItIo2HU6s6VLl9K9e3f8/Pzw8/Pj0ksvtZpqxTAM5s+fT3h4OJ6engwaNIgDBw5Y1ZGTk8P06dMJDg7G29ub6667jhMnTtT1pYiIiIiIg7Nr4tu8eXOee+45du3axa5du7jyyiu5/vrrLcntCy+8wCuvvMLrr7/Ozp07CQ0NZdiwYaSnp1vqmDFjBp999hkrVqxg69atZGRkMHLkSLvOqykiIiIijsfhhjoEBQXx4osvcvfddxMeHs6MGTMsE+/n5OQQEhLC888/z6RJk0hNTaVp06Z8+OGH3HLLLYB5nfbIyEi+/PLLMicdFxEREZHGx2FubisoKODjjz8mMzOTSy+9lJiYGBISEhg+fLiljLu7OwMHDmTbtm1MmjSJ3bt3k5eXZ1UmPDycrl27sm3btjIT35ycHHJyciyvCwsLOXv2LE2aNHGYqW9ERERE5C/G+QWawsPDK7XwUGnsnvju27ePSy+9lHPnzuHj48Nnn31G586d2bZtG2C+O7e4kJAQjh07BpjXI3dzcyMwMLBEmdLWJC/y7LPP8vTTT9v4SkRERESktsXGxlZrSXBwgMS3Q4cOREdHk5KSwieffMKECROs5tS8sAfWMIwKe2UrKjNnzhxmzpxpeZ2amkqLFi2IiYnB19eXvLw8vvvuOwYPHoyrq2s1r6zxUHtVntqqatReVaP2qjy1VdWovSpPbVU1VWmv9PR0oqKi8PX1rfb57J74urm50bZtWwD69OnDzp07ee211yzjehMSEggLC7OUP336tKUXODQ0lNzcXJKTk616fU+fPl3uKkzu7u64u7uX2B4UFISfnx95eXl4eXnRpEkTvWkrQe1VeWqrqlF7VY3aq/LUVlWj9qo8tVXVVKW9ivbXZFiqXWd1KI1hGOTk5BAVFUVoaKjVyjG5ubls3rzZktT27t0bV1dXqzLx8fHs379fy4+KiIiIiBW79vg+/vjjXHPNNURGRpKens6KFSvYtGkT69atw2QyMWPGDJ555hnatWtHu3bteOaZZ/Dy8mL8+PEA+Pv7M3HiRGbNmkWTJk0ICgpi9uzZdOvWjaFDh9rz0kRERETEwdg18T116hS333478fHx+Pv70717d9atW8ewYcMAeOSRR8jOzmbq1KkkJydz8cUX8/XXX1uN7Vi0aBEuLi6MHTuW7OxshgwZwrJly3B2drbXZYmIiIiIA7Jr4vvOO++Uu99kMjF//nzmz59fZhkPDw8WL17M4sWLbRydNcMwyM/P18IYpcjLy8PFxYVz586pfSpg67ZydnbGxcVF0/CJiIhUgt1vbqsPcnNziY+PJysry96hOCTDMAgNDSU2NlYJWAVqo628vLwICwvDzc3NJvWJiIg0VEp8K1BYWEhMTAzOzs6Eh4fj5uam5O4ChYWFZGRk4OPjU+0JpRsLW7aVYRjk5uZy5swZYmJiaNeundpfRESkHEp8K5Cbm0thYSGRkZF4eXnZOxyHVFhYSG5uLh4eHkq8KmDrtvL09MTV1ZVjx45Z6hUREZHSKUupJCV04qj03hQREakc/cUUERERkUZBia+IiIiINApKfEVERESkUVDi28DNmjWLUaNG2TsMEREREbtT4tvARUdH07NnT3uHYeXgwYOMGTOGiIgITCYTq1atKlHGMAzmzZtHs2bN8PHxYdy4caSmplr2x8fHc+utt9K0aVN8fX0ZPXo08fHxJer53//+R+/evfHw8CAkJIR58+ZVKdaqHP/AAw+UuJ4Lr2P8+PFW1yEiIiJ1R4lvA7d371569epl7zCsZGRk0Lp1a1577bUyyyxZsoRFixbx1ltvsWnTJqKjo5k8ebJl/+23387x48fZsGEDW7duJTExkbFjx1rVsXHjRm666SZGjx5NdHQ033zzDVdccUWl46zK8Rs2bOCXX36p8Dr27t3LzJkzKx2DiIiI2I7m8W3AYmNjSUpKsvT4pqSkcPvtt5OUlMQnn3xCWFhYlevcunUrgwcPJiMjA3d3dwBiYmJo27YtR44cISoqylI2OTmZzMxMwsLCcHZ2tmzv168f/fr1K/c8b7zxBlOmTOH6668H4LnnnmPMmDG8/vrreHh48O2337J27VrLtb388sv069eP3377jY4dOwKwYMECJkyYwNy5cy31du3atdLXWtnjz549y9SpU/nyyy9p3759udfxzDPPcPPNN5OUlETTpk0rHYuIiIjUnHp8G7Do6Gj8/f2Jiopi37599O3bl7CwMDZt2lStpLeozk6dOlmS3uLnadmypVXZhx56iMjISGJjY6t0jpycHA4cOED//v0t2wYMGEBBQQE///wzBQUFGIZhtURv0cINP//8MwB5eXls27aN9u3bM3DgQEJCQhg6dGipvbKlqcrxU6ZMYdKkSbRr165K1yEiIiJ1S4lvAxYdHU2PHj346KOPGDBgALNnz+bNN9+0ShirqrShE3v37q1ST2pFkpKSKCwsJDg4mEcffZQ+ffoQEBCAs7MzZ86cwc/Pjx49erB48WLS09PJyMhg4cKFlv0AiYmJ5OXl8cILL3D77bfz1Vdf0axZM6666ioyMjIqjKGyx3/44YccPXqUhx56qMrXISIiInVLiW8DFh0dzb59+5g2bRpr165l0qRJNqnzwpvlfv7551IT32XLlmEYBq1atarSOQzDsDwPDg6mRYsWJcp88MEHHD58GH9/f4KCgmjTpg1eXl6WVcwKCwsBGDVqFPfccw8XXXQRb7zxBomJiWzcuLHCGCpzfGxsLLNmzeLdd9+1GspRlesQERGRuqPEtwGLjo5mzJgxnDt3jpSUlBL7f/75ZwYNGkTbtm15//33ufHGGzl79myZ9RUUFHDgwIESPb4///wz3bp1s1ncwcHBODk5kZiYyMMPP8ynn35KSkoKBQUFlnGx3bt3Z//+/Zw5c4YzZ84we/Zs0tPTCQ8PByAoKAiTyWQ15tbX15fg4GDi4uIqjKEyx+/evZvExETLrA9Fwy3Gjx/P+PHjK3UdIiIiUnd0c1sDlZ6eTkxMDFOnTqV///6MGzeObdu20aVLFwAyMzMZN24cX375JW5ublx22WWMHTuWoKCgMuv8/fffyc7OtiSXANu3bycuLq7UHt/ExEQyMjJo3rw5Li6Vf6u5u7vTpUsXfvjhB2644QYAtmzZgrOzc4mku0mTJgAsXboUFxcXLr/8cgA8PT3p0KEDR44csZTNysoiKSmJiIiICuOszPFDhw7l4MGDVnV16tSJl156iZtuuqlK1yEiIiK1T4lvAxUdHY2zszOdO3emV69eHDhwgFGjRvHTTz8RHBzM+vXrGThwIK1btyY/P59Tp06VOk71wjoBFi9ezAMPPMDhw4d54IEHAPONXBeaPXs277//PjExMVbDHXJzc60SxqNHjxIdHU1oaCihoaEATJo0iUcffZQrrriC8PBwHnvsMW6++WZLovvDDz+QmZlJhw4d2LlzJ3PnzmXKlCk0a9bMUu/EiRN58sknGTJkCL169eLFF18kKCiIIUOGVCrOio738fGxzCBRXHh4uOWfgwuv4/HHH+f666+3XIeIiIjUHSW+DdTevXvp2LGjZfaF559/nl9//ZXRo0ezceNGq5vUDh48SP/+/Uv0hF4oOjqaYcOGERMTQ9euXencuTPPPfccd999N2+//TZDhw6tVGwnT5606vF8+OGHAXjqqaeYP38+AFOnTiU+Pp6JEyeSlZXFqFGjWLp0qeWYrKwsJk+ezIkTJwgJCeH+++/nqaeesjrPzJkzOXv2LA888AAZGRlcdNFFfPXVV/j6+lYqzpoeX9p1jBw5khdeeKHSx4uIiIjtmIzid+A0Umlpafj7+5Oamoqfnx95eXl8+eWXjBgxgoKCAmJiYoiKirKM4WwIFixYQHZ2Nv/4xz+48cYbSUpKYuvWreUec9VVV3HRRRfx7LPPWm0vLCwkLS0NPz8/y81lUrraaKtz5841yPcoYPWz6Orqau9wHJ7aq/LUVlWj9qo8tVXVVKW9LszXqkNZSiN12223sWbNGjp16sTNN98MmFcZK8/evXvp3r17XYQnIiIiYnMa6tBItWrVir1791pe33bbbRw/fhwfH59Sy587d46CggIlviIiIlJvKfEVi/DwcMsNbKVp1apVlWZnEBEREXEkymLEwsXFhbZt29o7DBEREZFaoTG+IiIiItIoKPEVERERkUZBia+IiIiINApKfKVWLVy4kG7duuHt7U14eDj33HMPiYmJZZZ/4IEHMJlMrFq1qtLnMJlMpT4+/vhjS5mUlBTuvvtuQkJC8PX1ZcCAAfz00082i0FEREQcnxJfqVXbt2/n0UcfZffu3Xz66afs2rWLW265pdSyGzZs4JdffqnyOeLj460eb775Jt7e3lx99dWWMjNnzmTbtm188cUX7Nmzh6ioKEaMGMG5c+dsEoOIiIg4Ps3q0MDt2LGDuXPnsnfvXpKSkqz2JScnExAQQHJyMpmZmYSFheHs7GzT869Zs8bq9ZNPPsmYMWNITU3F39/fsv3s2bNMnTqVL7/8kvbt21fpHKGhoVavP/vsM2666SarpYV//PFHxo0bxyWXXALAI488wgcffMCxY8fo0KFDjWMQERERx6ce3wZs7969DBo0iB49erBlyxbWrVtHUFAQgwcPZuXKlQQEBADw0EMPERkZSWxsbK3HdOrUKTw9PXF3d7faPmXKFCZNmkS7du1qVH9sbCzr16/n7rvvttp+xRVXsH79epKSksjPz2flypV07NiR1q1b2zwGERERcUzq8W3AHnjgAa6//npeeeUVADp37sy4ceP48ccfGTt2bJ3Hk5GRwaJFi7j//vvx8PCwbP/www85evQoy5cvr/E53nnnHdq0acOAAQOstr/22mtMmjSJ4OBgnJ2dadOmDevXr7esC27LGERERMQxqce3gTp16hRbt25l6tSpVtu9vb0xmUxW25YtW4ZhGLRq1arW4snPz2f8+PGEh4ezcOFCy/bY2FhmzZrFu+++W+NhFoWFhbz77rvcddddJfYtWbKEPXv2sHHjRn766ScuvfRSRo4cSXZ2tk1jEBEREcelHt8Gavfu3RQWFtKjR48S2/v06VOnsRQWFnLHHXcQHx/PN998g5ubm1U8iYmJ9O7d2+qY8ePH8+mnn1apB3bdunWcPHmSCRMmWG3Pyclhzpw5fPLJJwwZMgSAt99+m4CAAD7//HM8PT1tFoOIiIg4LiW+DVRhYSEA2dnZlrG8+/btY8uWLfz973+3KpuYmEhGRgbNmzfHxcW2bwnDMJg4cSIHDx7k22+/xc/Pz2r/0KFDOXjwoNW2Tp068dJLL3HTTTdVKc633nqLq666ivDwcKvtWVlZ5OTkWPV0Ozk5YTKZyM7OZtSoUZWOQUREROovJb4N1MUXX4ynpyePPPIIc+fO5c8//2T69OlMnjyZyy67zKrs7Nmzef/994mJibH5cIfJkyfz7bffsmbNGnJzc0lISACgadOmODs74+PjQ8eOHUscFx4eXiKBLS/OhIQE1qxZw4oVK0rUFRgYSL9+/XjiiScICgqiSZMm/N///R+FhYUMHjy4SjGIiIhI/aXEt4Fq2rQp//3vf5k1axbdu3cnMjKSyZMnM3v27DqN48033wSge/fuVtttnWS/9957BAQEcN1115W6f9WqVcyePZvrrruO7OxsunXrxpo1a4iKirJZDCIiIuLYlPg2YCNHjmTkyJEVllu2bBnLli2rlRgMw7DZMeXFOWfOHObMmVNmnZGRkaxcubLGMYiIiEj9pVkdRERERKRRUOIrIiIiIo2CEl8RERERaRSU+IqIiIhIo6DEV0REREQaBSW+IiIiItIoKPFt4GbNmsWoUaPsHYaIiIiI3SnxbeCio6Pp2bOnTescMGAAJpOJjz76yGr70qVLadasmc3Os3DhQrp164a3tzfh4eHcc889JCYmWpUxDIN58+bRrFkzfHx8GDduHKmpqVWqoyJ33nknJpPJ6jF//nzL/pSUFO6++25CQkLw9fVlwIAB/PTTT1Z1zJ8/n44dO+Lj40P79u25/fbbiY+Pr3qjiIiISLUp8W3g9u7dS69evWxWn2EYREdHExYWxieffGK1b8+ePVx00UU2O9f27dt59NFH2b17N59++im7du3illtusSqzZMkSFi1axFtvvcWmTZuIjo5m8uTJVaqjMoYOHUp8fLzlUXwFvJkzZ7Jt2za++OIL9uzZQ1RUFCNGjODcuXOWMq1bt2bJkiXs27ePVatWcfLkSW6++eZqtIqIiIhUl1Zua8BiY2NJSkqy9PimpKRw++23k5SUxCeffEJYWFiV6zx06BDp6ek899xzPPzww2RlZeHh4QGYE98RI0aUOCY5OZnMzEzCwsJwdnau9LnWrFlj9frJJ59kzJgxpKam4u/vD8Abb7zBlClTuP766wF47rnnGDNmDK+//jpNmjSpVB2V4e7uTmhoaKn7fvzxR8aNG8cll1wCwCOPPMIHH3zAsWPH6NChAwB33HEHAIWFhTRp0oQZM2Zw4403cu7cOUv7iYiISO1Sj28DFh0djb+/P1FRUezbt4++ffsSFhbGpk2bqpX0AuzevRsPDw/uuece/Pz8+OqrrwDIycnhwIEDpfb4PvTQQ0RGRhIbG1uj6zl16hSenp64u7tbnbN///6WMgMGDKCgoICff/65UnVU1tatW2nWrBmdOnVizpw5Vr25V1xxBevXrycpKYn8/HxWrlxJx44dad26dal1JScn8+GHH9KlSxclvSIiInVIiW8DFh0dTY8ePfjoo48YMGAAs2fP5s0338TNza3ade7Zs4fu3bvj5ubGjTfeyKpVqwA4cOAAeXl59O7d21bhW8nIyGDRokXcf//9lmQxKSmJwsJCgoODefTRR+nTpw8BAQE4Oztz5syZStVRGSNGjGDFihV88803PPbYY7zzzjvcf//9lv2vvfYa7du3Jzg4GA8PD1auXMlXX32Fq6urVT1r1qzBz8+P1q1bExcXx4YNG6rZGiIiIlIdSnwbsOjoaPbt28e0adNYu3YtkyZNqnGdu3fvtvTqjh49mrVr15KTk0N0dDRBQUG0atWqxDHLli3DMIxS91VGfn4+48ePJzw8nIULF1q2G4ZheR4cHEyLFi2qXEdljB07lquvvppu3boxYcIEFi1axHvvvUdmZiZgHme8Z88eNm7cyE8//cSll17KyJEjyc7Otqpn8ODB7N69m88//xwnJydmzJhRpThERESkZpT4NmDR0dGMGTOGc+fOkZKSUmL/zz//zKBBg2jbti3vv/8+N954I2fPni23zp9//tnSqzto0CDc3NxYv349v/zyi01voitSWFjIHXfcQXx8PKtXr7bqrQ4ODsbJyYnExEQefvhhPv30U1JSUigoKKBp06aVqqM6evXqhWEYHD9+nJycHObMmcOzzz7LkCFDuOiii3j77bc5evQon3/+udVx3t7etGvXjoEDB7J8+XJWrlzJzp07axSLiIiIVJ4S3wYqPT2dmJgYpk6dypIlSxg3bhwHDhyw7M/MzGTcuHG8++67bNq0iXnz5tGmTRuCgoLKrPPIkSOkpKRYenxdXFwYNWoUn376KdHR0WXO6JCYmMjRo0fJz8+v0jUYhsHEiRM5ePAg69evx8/Pz2q/u7s7Xbp04YcffrBs27JlC87OzpYkvKI6qhPjb7/9hslkokWLFmRlZZGTk4PJZLLsd3JywmQylejxLa7oJr+MjIwKzyciIiK2ocS3gYqOjsbZ2ZnOnTtz5513ct999zFq1CjLHLbr169n4MCBtG7dmtDQUE6dOsVDDz1Ubp27d+/Gzc2Nrl27WraNGTOG//3vf/z6669l9vjOnj2bqKgoTpw4UaVrmDx5Mt9++y0ffvghubm5JCQkkJCQQEFBgaXMpEmTWLp0KatXr2bXrl089thj3HzzzTRp0qTSdZQXY0ZGBg899BDbtm3j6NGjrFmzhoceeoi7774bb29vAgMD6devH0888QQ7duzg0KFDPPjggxQWFjJ48GBLHQ8++CCbNm3i6NGj7Nq1i7vuuovmzZvTt2/fKrWJiIiIVJ9dE99nn32Wvn374uvrS7Nmzbjhhhv4/fffrcqUtnhA0bRRRXJycpg+fTrBwcF4e3tz3XXXVTnJamj27t1Lx44dLbMXPP/883Tu3JnRo0eTm5trNb/vwYMH6d+/PxEREeXWuWfPHrp27Wo1VGDYsGEUFBSQm5tr0zl8Ad58802OHz9O9+7dCQsLszyKzw4xdepUZsyYwcSJExk4cCA9evRg6dKlVaqjPM7Ozuzdu5eRI0fSvn17HnzwQW677TYWL15sKbNq1SratWvHddddx0UXXcTu3btZs2YNUVFRgLln/MSJE9x222106tSJ8ePH4+3tzddff42Pj4+NWktEREQqYtd5fDdv3sz9999P3759yc/PZ+7cuQwfPpyDBw/i7e1tKXf11Vfz3nvvWV5fOEZzxowZ/O9//2PFihU0adKEWbNmMXLkSHbv3l2leWMbkmnTpjFt2jTLaycnJ6s5bV1dXYmNjaWwsJB58+aRm5tbYZ3PPvsszz77rNU2d3d3UlJSSEtLK3MYwbJly1i2bFmVr6H4zWtlMZlMLFiwgAULFlS7Dig7Rk9PT7799ttyj42MjGTlypVl7vfw8LAs9lFYWGhpKycnfeAiIiJSl+z6l3fdunXceeeddOnShR49evDee+9x/Phxdu/ebVWuaPGAokfxcaipqam88847vPzyywwdOpRevXrx73//m3379rFx48a6vqR647bbbmPNmjV06tTJsoLYkiVL7ByViIiISO1xqJXbUlNTAUrcYLVp0yaaNWtGQEAAAwcOZOHChTRr1gwwjzvNy8tj+PDhlvLh4eF07dqVbdu2cdVVV5U4T05ODjk5OZbXaWlpAOTl5VkeRa8LCgowDIPCwkIKCwtte8F21KJFC6tFHsaPH8/x48fL/eh9//79pU4ZVtSrWtROUrbaaKvCwkIMwyAvL6/BfcJR/GdRKqb2qjy1VdWovSpPbVU1VWkvW7SpyajsZ8G1zDAMrr/+epKTk/n+++8t21euXImPjw8tW7YkJiaGefPmkZ+fz+7du3F3d2f58uXcddddVokswPDhw4mKiuKNN94oca758+fz9NNPl9i+fPlyvLy8rLa5uLgQGhpKZGRkjafBcnT5+fkcP368zP0tWrTAxcWh/lcSIDc3l9jYWBISEqo8c4aIiEh9kZWVxfjx40lNTS1zeGVFHCaLmTZtGr/88gtbt2612n7LLbdYnnft2pU+ffrQsmVL1q5dy+jRo8uszzAMqymmipszZw4zZ860vE5LSyMyMpLhw4fj5+dHXl4eGzZssNy4FRsbi4+PT6NYXra86czKYhgG6enp+Pr6ltnmYlYbbXXu3Dk8PT0ZMGBAg3uPFv9ZvHAlPClJ7VV5aquqUXtVntqqaqrSXkWf0NeEQyS+06dPZ/Xq1WzZsoXmzZuXWzYsLIyWLVty6NAhAEJDQ8nNzSU5OZnAwEBLudOnT3PZZZeVWoe7u7tltoPiXF1drRrd1dXVMierk5OTbkYqQ9FH9kXtJGWrjbYqeo9e+P5tSBrytdUGtVflqa2qRu1VeWqrqqlMe9miPe2a+BqGwfTp0/nss8/YtGmTZfqn8iQlJREbG0tYWBgAvXv3xtXVlQ0bNjB27FgA4uPj2b9/Py+88EJtBA1ZWbavtzK8vEA9qiIi1RaXkk1yZi75+fmczam4vIg0LHZNfO+//36WL1/OF198ga+vLwkJCQD4+/vj6elJRkYG8+fPZ8yYMYSFhXH06FEef/xxgoODufHGGy1lJ06cyKxZs2jSpAlBQUHMnj2bbt26MXToUNsHnZUF9pp7NSMDik3zJiIilReXks3QlzeTnWdewMbNyZmWXRNp5m++tyPQ242IAE97higitcyun0svXbqU1NRUBg0aZLW4QNGcqM7Ozuzbt4/rr7+e9u3bM2HCBNq3b8/27dvx9fW11LNo0SJuuOEGxo4dS//+/fHy8uJ///tfg7vDvbp2797NrbfeSnh4OB4eHrRp04a7776bP/74w96hORTDMJg3bx7NmjXDx8eHcePGWWYaqayDBw8yZswYIiIiMJlMrFq1qsyyDzzwQKllFi5cSLdu3fD29iY8PJx77rnHsuKeiFRfcmYu2XkFvHpLT969w7zgzt0f7GHk4q2MXLyVoS9vJi6l7KXGRaT+s/tQh/J4enqyfv36Cuvx8PBg8eLFVqtp1RovL3PPqz1cMONEZbz99ttMnjyZiRMn8umnnxIWFsaff/7J//3f//HOO+/w/PPP10Kg9dOSJUtYtGgR//nPf4iIiOD2229n8uTJfPTRR5WuIyMjg9atWzNu3DjL/Mil2bBhA7/88kup+7Zv386jjz5Knz59SElJYfLkydxyyy188803Vb4mESmpbTMfOjTzYk7PAnpdfDkuLi4cPp3BjJXRJGfmqtdXpAFziJvb6hWTqd4MN9i6dSuTJk3i9ddfZ8qUKZbtLVu25Morr+Ts2bOWbcnJyWRmZhIWFtZoe8rfeOMNpkyZwvXXXw/Ac889x5gxY3j99ddp0qRJpero168f/fr1K7dMcnIy06ZN48svv6R9+/Yl9hdfYQ/gySefZMyYMaSmpuLv71/JqxGRigS5Q5dwP92AJNKI6Bb8BmzmzJkMHDjQKuktrvjUZQ899BCRkZHExsbWVXgOJScnhwMHDtC/f3/LtgEDBlBQUGC10IctzJo1i/vuu4927dpVqvypU6fw9PQsdSYSERERqTwlvg3Ur7/+ys6dO7n//vvtHUq9kJSURGFhIcHBwZZhBgEBATg7O3PmzBmbnefDDz/k+PHjzJgxo1LlMzIyWLRoEffff3+Dm6NXRESkrinxbaD27NkDmKd7q4xly5ZhGAatWrWqxagcV/Hx5sHBwaUuzVxTsbGxPPzwwyxevLhSw0ny8/MZP3484eHhLFy40ObxiIiINDYa49tAZZ2fa9jHXlOv1TPBwcE4OTmRmJjIww8/DJjH4hYUFNC0aVObnGP37t0kJiYyePBgq+3jx4/n008/Zfny5ZZthYWF3HHHHcTHx/PNN980+OWyRURE6oJ6fBuorl27AvD999+Xuj8723rKnsTERI4ePUp+fn6tx+aI3N3d6dKlCz/88INl25YtW3B2dqZXr15WZavbVkOHDmX//v1s2bKFPXv2EB0dDcBLL73ESy+9ZClnGAYTJ07k4MGDrF+/vtrrkYuIiIg1Jb4N1KWXXsrw4cOZOnUqH374IYcPH+aPP/7gP//5D1dccQV//vmnVfnZs2cTFRXFiRMn7BSx/U2aNImlS5eyevVqdu3axWOPPcbNN99cYkaH8toqNzeX6OhoS1J79OhRoqOjSUhIwMfHh44dO9K+fXs6duxIx44dAQgPDyc8PNxSx+TJk/n222/58MMPyc3NJSEhgYSEBAoKCmrv4kVERBoBDXVowFavXs2iRYt44YUXOHLkCO7u7rRt25ZRo0bRuXNne4fncKZOnUp8fDwTJ04kKyuLUaNGsXTp0irVcfLkSase4qJhE0899RTz58+vVB1vvvkmAN27d7faHhMT02jHYIuIiNiCEt8GzN3dnccee4zHHnuswrLLli1j2bJltR+UAzOZTCxYsIAFCxaUW668tmrVqlWFC7MUV1rZqhwvIiIilaehDiIiIiLSKCjxFREREZFGQYmviIiIiDQKSnxFREREpFFQ4isiIiIijYISXxERERFpFJT4NnCzZs1i1KhR9g5DRERExO6U+DZw0dHR9OzZ095hOISDBw8yZswYIiIiMJlMrFq1qsp1zJ8/n44dO+Ll5UVISAi33XYb8fHxlv2GYTBv3jyaNWuGj48P48aNIzU11aoOwzB48sknyy0jIiIitqfEt4Hbu3ev1UpijVlGRgatW7fmtddeq3YdrVu3ZsmSJRw4cIB169YRFxfHzTffbNm/ZMkSFi1axFtvvcWmTZuIjo5m8uTJVnW8/fbbvPrqq+WWEREREdtT4tuAxcbGkpSUZOnxTUlJYdSoUVx22WVWvZRVcfToUUwmE59++ikDBgzA09OTvn37cvz4cTZt2kS/fv3w8vJi8ODBnD17tsTxycnJnDhxgoKCgppcWrX069ePF198kZtuuqnaddxxxx1ceeWVREVF0atXL2bOnMm2bds4d+4cAG+88QZTpkzh+uuvp0+fPjz33HN8/PHHJCUlWepYtmwZkydPLreMiNhOXEo2++NSOXw6w96hiIidKfFtwKKjo/H39ycqKop9+/bRt29fwsLC2LRpE2FhYdWuE8w9m8888wzbt28nKSmJSZMm8cILL/DPf/6TTZs2sW/fPt55550Sxz/00ENERkYSGxtbk0tzCGfPnuWDDz6gS5cueHh4kJOTw4EDB+jfv7+lzIABAygoKODnn38GICcnh99++43LLruszDIiYjtxKdkMfXkzIxdvZcbKaDxdnQn0drN3WCJiJ0p8G7Do6Gh69OjBRx99xIABA5g9ezZvvvkmbm7mX/qGYfDggw/SvXt3OnbsyLp16yqsc+/evQQGBrJixQouv/xyevbsyaBBgzhx4gQff/wxffv2pV+/fvTt25eEhITavkS7WLNmDT4+PjRp0oQTJ06wYcMGAJKSkigsLCQ4OJhHH32UPn36EBAQgLOzM2fOnKl0GRGxneTMXLLzCnj1lp6smX45G2cNJCLA095hiYidKPFtwKKjo9m3bx/Tpk1j7dq1TJo0yWr/qlWrSE5OZu/evTz33HOWBK6iOq+77jqCg4Mt22JjYxkzZgze3t6WbcePHycqKqrE8cuWLcMwDFq1alX9C7OzwYMH8/PPP7Nx40acnJyYMWMGYP5HokhwcDAtWrQocWxlyoiI7bVt5kPXCH8lvSKNnBLfBiw6OpoxY8Zw7tw5UlJSSuxfs2YNd955JxkZGbz77rtcd911Fda5d+9eLrnkkhLn6dOnj+X1uXPn+OOPPxrsbBLe3t60a9eOIUOGsGLFClauXMnOnTsJDg7GycmJxMREHn74YT799FNSUlIoKCigadOmAJUqIyIiIrVDiW8DlZ6eTkxMDFOnTmXJkiWMGzeOAwcOWJWJjo7myJEjNG3alOzsbK644opy60xLS+Po0aNWs0QcO3aMs2fP0r17d8u2AwcOUFBQQI8ePUrUkZiYyNGjR8nPz6/hFdaeqsTo7OwMmGeMcHd3p0uXLvzwww+W/Vu2bMHZ2dnSZu7u7nTs2JFt27aVWUZERERqhxLfBio6OhpnZ2c6d+7MnXfeyX333ceoUaNITEwEIDc3l8zMTO655x5OnTpFYWEhH3/8cbl17t27FycnJ6skNzo6moCAAKuP7Pfu3Uvr1q3x9fUtUcfs2bOJiorixIkTNrrSysvNzSU6Otpyg97Ro0eJjo4uMRa5rBgzMjJ48MEH2bRpE0ePHuXHH3/kzjvvpHnz5vTt2xeASZMmsXTpUlavXs2uXbt47LHHuPnmm2nSpImlnjvvvJN//etf5ZYRERER23OxdwBSO/bu3UvHjh1xd3cH4Pnnn+fXX39l9OjRbNy4kYMHD9K5c2cA/P39ueiiiyrs4Syq09PzrzFyP//8c4me3b179zrkMIeTJ09a9ao+/PDDADz11FPMnz+/wuNdXFw4ceIEt912G2fOnCEgIIDLLruMr7/+Gh8fHwCmTp1KfHw8EydOJCsri1GjRrF06VKreu655x5SUlLKLSMiIiK2p8S3gZo2bRrTpk2zvHZycmLNmjWW13v37iU7OxvDMEhLS+Prr7/mkUceqVKdYF7JrLCwkLS0NMu28haIWLZsGcuWLavi1dhGq1atrG4uK0tZMXp4ePDJJ5+Ue6zJZGLBggUsWLCg3DL/+Mc/WLhwYYWxiIiIiO0o8W2k9u7dy5kzZ2jTpg3BwcEsXLhQN1eJiIhIg6bEt5Hau3cvH3/8Me3atbNsO378uGX4Q2kOHjyo6bdEpF6IS8kmOTNXq7WJiBUlvo3U4cOHadOmjdW28PBwy41fpQkPD6/lqEREaq5otbbsPPPS6FqtTUSKKPFtpI4dO1Zim4uLC23btrVDNCIitlN8tba2zXwI9HbTwhUiAijxFRGRBqpotTYAVq4EZ2cYMwZMJvsGJiJ2o3l8RUSkYfvsM7j1Vrj5ZrjhBjhzxt4RiYidKPEVEZGGKykJpkz56/Xq1dCtG6aNG+0Xk4jYjRJfERFpuB58EE6dgk6d4McfoWtXOHUK55tuwjVDMz6INDZKfEVEpEHyXb8W/vMfcHKC996Dfv1g507o1AlTVhZhP/5o7xBFpI4p8RURkQbHPS+H8MdnmV/Mng0XX2x+7uEBf/sbABHff2+n6ETEXpT4NnCzZs1i1KhRNq/3n//8J61atcLFxaXCpY5FROrapcd/wfVUAoSHw9NPW++85RYAgn/5BU6ftkN0ImIvSnwbuOjoaHr27GnTOvfv38+MGTP45z//SWxsLPPnz7dp/dVhGAbz5s2jWbNm+Pj4MG7cOFJTU2uljv/973/07t0bDw8PQkJCmDdvnmVfSkoKd999NyEhIfj6+jJgwAB++umnGl+fiFTNwJg95icjR5p7eYtr25bCPn1wKizE6dNP6z44EbEbJb4N3N69e+nVq5dN61y9ejW9e/fm2muvJSwsDC8vL5vWXx1Llixh0aJFvPXWW2zatIno6GgmT55s8zo2btzITTfdxOjRo4mOjuabb77hiiuusOyfOXMm27Zt44svvmDPnj1ERUUxYsQIzp07Z5PrFJHKGXhkt/nJ1VeXut8YOxYA03//W1chiYgDUOLbgMXGxpKUlGTp8U1JSWHUqFFcdtllxMfHV6vONm3aMHfuXH788UdMJhO33367ZV9ycjInTpygoKDAFuFXyRtvvMGUKVO4/vrr6dOnD8899xwff/wxSUlJNq1jwYIFTJgwgblz59KxY0e6du3K8OHDLft//PFHxo0bxyWXXEK7du145JFHSEpKKnWlPBGpHa7HjtI6+SSGiwtceWWpZQpvugkAp61b4cSJugxPROxIiW8DFh0djb+/P1FRUezbt4++ffsSFhbGpk2bCAsLq1ad27dvp3Xr1rz44ovEx8ezZMkSy76ZM2cSGRlJbGysrS6hUnJycjhw4AD9+/e3bBswYAAFBQX8/PPPNqsjLy+Pbdu20b59ewYOHEhISAhDhw7ll19+sRxzxRVXsH79epKSksjPz2flypV07NiR1q1b2+hqRaQivpu/ASCrdz/w9y+9UPPmJHbubH6uXl+RRkOJbwMWHR1Njx49+OijjxgwYACzZ8/mzTffxM3NDTCPaX3wwQfp3r07HTt2ZN26dRXW6ePjw9GjR7n88ssJDQ3F19e3ti+jQklJSRQWFhIcHMyjjz5Knz59CAgIwNnZmTOVXKGpMnUkJiaSl5fHCy+8wO23385XX31Fs2bNuOqqq8g4Px/oa6+9Rvv27QkODsbDw4OVK1fy1Vdf4erqWmvXLyLWfDaZF6fIGDSk3HJxl19ufrJihWXb4dMZ7I9LJS4lu9biExH7UeLbgEVHR7Nv3z6mTZvG2rVrmTRpktX+VatWkZyczN69e3nuuefYsGFDhXUW9W5269atxL733nsPwzBo1aqVTeKvLMMwLM+Dg4Np0aJFrdRRWFgIwKhRo7jnnnu46KKLeOONN0hMTGTj+VWglixZwp49e9i4cSM//fQTl156KSNHjiQ7W39ERepEbi7eW7cAkF5B4nvyssswTCbYuZMmWSl4ujozY2U0IxdvZejLm5X8ijRALvYOQGpPdHQ0Y8aM4T//+Q8pKSkl9q9Zs4Y777yTjIwM3n33XWbNmlWpOtu2bYu3t3ctRFw9wcHBODk5kZiYyMMPPwyYxxsXFBTQtGlTm9URFBSEyWSiffv2luN8fX0JDg4mLi6OnJwc5syZwyeffMKQIeY/uG+//TYBAQF8/vnnjBs3zpaXLSKl+eEHnLMyOeMVwLku3cstmhsQAO3bw++/E3b4IBtnDSI5M5fDpzOYsTKa5MxcIgI86yZuEakT6vFtoNLT04mJiWHq1KksWbKEcePGceDAAasy0dHRHDlyhKZNm5KdnW01O0FZioZPlCYxMZGjR4+Sn59vk2uoLHd3d7p06cIPP/xg2bZlyxacnZ1LndGitDgrU4enpycdOnTgyJEjljJZWVkkJSURERFBVlYWOTk5mEwmy34nJydMJpN6fEXqyvkhW1uieplXbKuA0bu3+cmuXUQEeNI1wp+2zXxqM0IRsSMlvg1UdHQ0zs7OdO7cmTvvvJP77ruPUaNGkZiYCEBubi6ZmZncc889nDp1isLCQj7++ONK1VvWvMAPP/wwUVFRnLDDHdKTJk1i6dKlrF69ml27dvHYY49x880306RJkxJlZ8+eXWqclalj4sSJfPjhh/z3v//l0KFDzJgxg6CgIIYMGUJgYCD9+vXjiSeeYMeOHRw6dIgHH3yQwsJCBg8eXOttICLA+vUAbG7du1LFiye+ItLwaahDA7V37146duyIu7s7AM8//zy//voro0ePZuPGjRw8eJDO5+9o9vf356KLLqqwp7awsJB9+/ZZLdjgKKZOnUp8fDwTJ04kKyuLUaNGsXTpUpvXMXPmTM6ePcsDDzxARkYGF110EV999ZXlJr9Vq1Yxe/ZsrrvuOrKzs+nWrRtr1qwhKirKZtcqImU4dQr27sUwmdjaqhf3VeIQJb4ijYsS3wZq2rRpTJs2zfLaycmJNWvWWF7v3buX7OxsDMMgLS2Nr7/+usKlh52cnMjMzCxz/3vvvcf7779f8+CrwWQysWDBAhYsWFBh2WXLlrFs2bJq1eHk5MQzzzzDM888U+r+yMhIVq5cWem4RcSGdpsXrchp256zXmVMY3YBo0cP85CIkyfNj/Dw2oxQROxMiW8jtXfvXs6cOUObNm0IDg5m4cKFlb4RTETEIUVHA1R4U5sVb2/o3Bn27zcnzkp8RRo0Jb6N1N69e/n4449p166dZdvx48ctwx9Kc/DgwWpNFSYiUheydu7GCzjRqkPVDuzTx5z47toFo0bVSmwi4hiU+DZShw8fpk2bNlbbwsPDiT7fY1KacPWEiIiDikvJJn/zDloCz8Z74NnOmUBvt8od3KcPLFumcb4ijYAS30bq2LFjJba5uLjQtm1bO0QjIlIzqaeS6Jx8EoAnHr8VvxbhlZ+Dt08f89edO6HYYjYi0vDYdTqzZ599lr59++Lr60uzZs244YYb+P33363KGIbB/PnzCQ8Px9PTk0GDBpWYjzYnJ4fp06cTHByMt7c31113nV2m1BIREfvw+NX8dyEvNJxO3dtUbeGJ7t3BxQXOnIHY2FqKUEQcgV0T382bN3P//fezY8cONmzYQH5+PsOHD7eaOeCFF17glVde4fXXX2fnzp2EhoYybNgw0tPTLWVmzJjBZ599xooVK9i6dSsZGRmMHDmSgoICe1yWiIjUMY8D+wDI7lJyOfUKeXpC167m5xruINKg2TXxXbduHXfeeSddunShR48evPfeexw/fpzd56ekMQyDV199lblz5zJ69Gi6du3K+++/T1ZWFsuXLwcgNTWVd955h5dffpmhQ4fSq1cv/v3vf7Nv3z42btxoz8sTEZE6UpT4nqtO4gt/DXdQ4ivSoDnUGN/U1FQAgoKCAIiJiSEhIYHhw4dbyri7uzNw4EC2bdvGpEmT2L17N3l5eVZlwsPD6dq1K9u2beOqq64qcZ6cnBxycnIsr9PS0gDIy8uzPIpeFxQUYBgGhYWFFBYW2v6iGwDj/Ji4onaSstVGWxUWFmIYBnl5eTg7O9ukTkdR/GdRKtaY28vjwC8AZHbsXKnrv7CtnHr1whko3LnTsphPfn5+o2zL0jTm91ZVqa2qpirtZYs2dZjE1zAMZs6cyeWXX07X8x85JSQkABASEmJVNiQkxHJzVkJCAm5ubgQGBpYoU3T8hZ599lmefvrpEtu//vprvLy8LK83bNiAi4sLoaGhpKenk5ubW/0LbASKDz+R8tmyrXJycsjOzmbLli0Vrr5XX23YsMHeIdQrja29TPn5jDg/xvf77Bz8v/yy0scWtZV/djaDgPwdO9j6/feAK1u3buWYj+3jrc8a23urJtRWVVOZ9srKyqrxeRwm8Z02bRq//PILW7duLbHPZDJZvTYMo8S2C5VXZs6cOcycOdPyOi0tjcjISIYPH46fnx95eXls2LCBYcOG4eTkxJEjR3BycsLPz68aV9bwGYZBeno6vr6+FX5fGrvaaKukpCQ8PT0ZMmRIg+zxLfpZdHV1tXc4Dq/Rttf+/bjk5ZHu5kn3G8fQpXlAhYeUaKvcXIzHHsMtI4PBbVrz0v5YLr/8crqE6/c+NOL3VjWoraqmKu1V9Al9TThE4jt9+nRWr17Nli1baN68uWV7aGgoYO7VDQsLs2w/ffq0pRc4NDSU3NxckpOTrXp9T58+zWWXXVbq+dzd3XF3dy+x3dXV1arRi14HBgaSmJiIk5MTXl5eSu4uUFhYSG5uLjk5OTg52XXYuMOzZVsZhkFWVhaJiYkEBgbi4eFhoygdz4U/m1K+Rtde52f6+bVZFF5ublW6dktbubpC69bwxx94HYsBXHBxcWlc7VgJje69VQNqq6qpTHvZoj3tmvgahsH06dP57LPP2LRpE1FRUVb7o6KiCA0NZcOGDfTq1QuA3NxcNm/ezPPPPw9A7969cXV1ZcOGDYwdOxaA+Ph49u/fzwsvvGCTOIsS8NOnT9ukvobGMAyys7Px9PTUPwUVqI22CggIsLxHRRql8wvvHGzWmj41qadDB/jjD9yPHAY62iAwEXE0dk1877//fpYvX84XX3yBr6+vZUyuv7+/JTGYMWMGzzzzDO3ataNdu3Y888wzeHl5MX78eEvZiRMnMmvWLJo0aUJQUBCzZ8+mW7duDB061CZxmkwmwsLCaNasmQarlyIvL48tW7YwYMAA/XdbAVu3laura4Mb3iBSZbZKfNu3B8Dtz0PQVImvSENk18R36dKlAAwaNMhq+3vvvcedd94JwCOPPEJ2djZTp04lOTmZiy++mK+//hpfX19L+UWLFuHi4sLYsWPJzs5myJAhLFu2zOYJgbOzs5KMUjg7O5Ofn4+Hh4cS3wqorURszDD+SnxDWtesrg4dAHD/8zA0rWFcIuKQ7D7UoSImk4n58+czf/78Mst4eHiwePFiFi9ebMPoRETE4cXFQVIShosLh4Jb1KyuosT3yCG4xAaxiYjD0Z1IIiJSf/36KwA5rVqT4+JWs7rOJ76uJ2Jxz9f0lSINkRJfERGpv37/HYDcNm1rXlezZuDvj8kwaJl8sub1iYjDUeIrIiL11x9/AJATZYPE12Sy3ODW+mxczesTEYejxFdEROovW/b4gmW4gxJfkYZJia+IiNRfRT2+rZX4ikjFlPiKiEj9lJ0Nx44BkNOmnW3qtCS+J2xTn4g4FCW+IiJSP/35p3keX39/CpoE26bO4j2+lZhyU0TqFyW+IiJSP50f35sV1ZbDZzJtU2db85CJgHMZOCeftU2dIuIwlPiKiEi9lLr3AADr8vyYsTIaT1dnAr1rOJevlxe5Ec0BcP/zUE1DFBEHY9eV20RERKqr8LffAOg0oDdrpl9OoLcbEQGeNa43t0073OJO4PbnIeCqGtcnIo5DPb4iIlIvuR/5EwDv7l3oGuFvk6QX/pohwv3PwzapT0QchxJfERGpl9zOD0XIbd3GpvVaEt8jSnxFGholviIiUv8kJeGSkgxATpRtE9/c81OjuSnxFWlwlPiKiEj9c35Gh5O+wRhe3jatOuf8KnBuR49Afr5N6xYR+1LiKyIi9c/5FduOBEXYvOq88ObkOLvilJcHsbE2r19E7EeJr4iI1D/ne3xjaiHxxcmJE/4h5vp37iMuJdv25xARu1DiKyIi9U8t9vgGertxMsCc+C5Z9g1DX96s5FekgVDiKyIi9U9Rj2+g7RPfiABPeg3sBcA9ESay8wpIzsy1+XlEpO4p8RURkfqloAAOm2dc+LNJ81o5hU9H88wOIWfja6V+EbEPJb4iIlK/HD8OOTkUurkR59e0ds7RqhUArrHHa6d+EbELJb4iIlK//GlesS0vsiWFTs61c46oKADcjh+rnfpFxC6U+IqISP0SEwNAbotWtXeOoh7fU/G45efV3nlEpE4p8RURkfrFkvi2rL1zBAeDt3lhjIi007V3HhGpU0p8RUSkfilKfCNrMfE1mSzDHZqnnqq984hInVLiKyIi9cv5xDcvskXtnuf8cIdIJb4iDYYSXxERqV/qYqgDWHp8I1OU+Io0FEp8RUSk/sjMhNPmMbe5ka1q91zne3w11EGk4VDiKyIi9cfRo+av/v4UBgTU7rmKenyV+Io0GEp8RUSk/jg/zKEoKa1VurlNpMFxsXcAIiIilVaXie/5oQ7BWalsP2YeXhHo7UZEgGftn1tEaoUSXxERqT/qMvENCKDQPwCn1BT+750NHGraEk9XZzbOGqjkV6Se0lAHERGpP+oy8QWcWpvP89bAYF69pSfZeQUkZ+bWyblFxPaU+IqISP1Rx4lv0XCHVmmnadvMp27OKSK1RomviIjUD4ZR94lv0XmKzisi9ZoSXxERqR+SkyEtzfz8fE9srSs6T9E0aiJSrynxFRGR+qGo1zUkBLy86uac6vEVaVCqlfju2bOHffv2WV5/8cUX3HDDDTz++OPk5mrQv4iI1IK6HuZQ/Fzq8RVpEKqV+E6aNIk//vgDgCNHjnDrrbfi5eXFxx9/zCOPPGLTAEVERAD7JL4tW5q/JifjlJZad+cVkVpRrcT3jz/+oGfPngB8/PHHDBgwgOXLl7Ns2TI++eQTW8YnIiJiZo/E18cHmjQBwPVEbN2dV0RqRbUSX8MwKCwsBGDjxo2MGDECgMjISBITE20XnYiISBF7JL4ALVoA4BofV7fnFRGbq1bi26dPHxYsWMCHH37I5s2bufbaawGIiYkhJCTEpgGKiIgA9kt8IyMBcD2pxFekvqtW4rto0SL27NnDtGnTmDt3Lm3btgVg1apVXHbZZTYNUEREhMLCv24wU+IrItXkUp2DevToYTWrQ5EXX3wRF5dqVSkiIlK2hATIyQEnJ+J8g0mOS+Xw6Yy6Off5oQ5ucbHQrm5OKSK1o1pZauvWrdm5cydNzg/4L3Lu3Dkuuugijhw5YpPgREREAMswh/yI5gz9v21k5xUA4OnqTKC3W+2eu3iPrxJfkXqtWonv0aNHKSgoKLE9JyeHEydO1DgoERERK+cT33PNW5CdV8Crt/SkbTMfAr3diAjwrN1zFyW+urlNpN6rUuK7evVqy/P169fj7+9veV1QUMA333xDVF2PvRIRkYbvfOKb18I8r27bZj50jfAv7wjbOZ/4usSfxGQU1s05RaRWVCnxveGGGwAwmUxMmDDBap+rqyutWrXi5ZdftllwIiIigCXxzY1sWffnDg8HJyeccnMJztQiFiL1WZUS36K5e6Oioti5cyfBwcG1EpSIiIiV4onvyTo+t6srhIVBXBxh6Wfq+OQiYkvVms4sJiZGSa+IiNSdC4Y61Lnzwx3C0rRIk0h9Vu25x7755hu++eYbTp8+bekJLvLuu+/WODAREREA8vIg1rxccG5kS9jxZ93HEBkJO3YQkaYeX5H6rFqJ79NPP83f//53+vTpQ1hYGCaTydZxiYiImMXGmhewcHcnv1kIYIfE9/xcvhrqIFK/VSvx/de//sWyZcu4/fbbbR2PiIiItaKlilu1AqdqjdCrOQ11EGkQqvUbJDc3V0sTi4hI3ShKfO05Xeb5xDdcPb4i9Vq1Et977rmH5cuX1/jkW7ZsYdSoUYSHh2Mymfj888+t9t95552YTCarxyWXXGJVJicnh+nTpxMcHIy3tzfXXXedFtEQEWlIHCnx1RhfkXqtWkMdzp07x5tvvsnGjRvp3r07rq6uVvtfeeWVStWTmZlJjx49uOuuuxgzZkypZa6++mree+89y2s3N+ulKWfMmMH//vc/VqxYQZMmTZg1axYjR45k9+7dODs7V/HKRETE4Rw5Yv5qz8T3/BjfZhnJJObl2S8OEamRaiW+v/zyCz179gRg//79VvuqcqPbNddcwzXXXFNuGXd3d0JDQ0vdl5qayjvvvMOHH37I0KFDAfj3v/9NZGQkGzdu5Kqrrqp0LCIi4qAcoce3aVMK3dxwys3F9VQ8tNKUniL1UbUS3++++87WcZRp06ZNNGvWjICAAAYOHMjChQtp1qwZALt37yYvL4/hw4dbyoeHh9O1a1e2bdtWZuKbk5NDTk6O5XVaWhoAeXl5lkfRa6mY2qvy1FZVo/aqmobaXi4xMZiAvMhI8vPzAcjPz6/RdVanrQpDw3E/fhSn48fIu6hjtc9dHzXU91ZtUFtVTVXayxZtWu15fOvCNddcw80330zLli2JiYlh3rx5XHnllezevRt3d3cSEhJwc3MjMDDQ6riQkBASEhLKrPfZZ5/l6aefLrH966+/xsvLy/J6w4YNtruYRkDtVXlqq6pRe1VNQ2ov53PnGHn6NAAbDh3iyOEEwIWtW7dyzKfm9VelrXp7+9AciNn0LQfdCmp+8nqoIb23apvaqmoq015ZWVk1Pk+1Et/BgweXO6Th22+/rXZAxd1yyy2W5127dqVPnz60bNmStWvXMnr06DKPMwyj3PjmzJnDzJkzLa/T0tKIjIxk+PDh+Pn5kZeXx4YNGxg2bFiJ8ctSktqr8tRWVaP2qpoG2V4HDgBg+PkxbOxYDsSn89K+HVx++eV0CferdrXVaav0D5bDr/vp6utL0xEjqn3u+qhBvrdqidqqaqrSXkWf0NdEtRLfovG9RfLy8oiOjmb//v1MmDChxkGVJSwsjJYtW3Lo0CEAQkNDyc3NJTk52arX9/Tp0+VOt+bu7o67u3uJ7a6urlaNfuFrKZ/aq/LUVlWj9qqaBtVe52fpMUVF4ermhouL+c+Wi4uLTa6xKm2VH2Ge2cE9Ib7htG8VNaj3Vi1TW1VNZdrLFu1ZrcR30aJFpW6fP38+GRkZNQqoPElJScTGxhIWFgZA7969cXV1ZcOGDYwdOxaA+Ph49u/fzwsvvFBrcYiISB1xhBvbzssLjwDA9WSsnSMRkeqy6Rjf2267jX79+vHSSy9VqnxGRgaHDx+2vI6JiSE6OpqgoCCCgoKYP38+Y8aMISwsjKNHj/L4448THBzMjTfeCIC/vz8TJ05k1qxZNGnShKCgIGbPnk23bt0sszyIiEg95lCJb3MAXE/G2TkSEakumya+27dvx8PDo9Lld+3axeDBgy2vi8bdTpgwgaVLl7Jv3z4++OADUlJSCAsLY/DgwaxcuRJfX1/LMYsWLcLFxYWxY8eSnZ3NkCFDWLZsmebwFRFpCBwq8S3q8VXiK1JfVSvxvfDGMsMwiI+PZ9euXcybN6/S9QwaNAjDMMrcv379+grr8PDwYPHixSxevLjS5xURkXrifOKb1DSc+LhUDp+uveF0FSlKfF2Sz0JWFhSbBUhE6odqJb7+/v5Wr52cnOjQoQN///vfrebUFRERqTbDsCS+d25KZF/0VgA8XZ0J9HYr78haUejnT4abJz652RAbCx061HkMIlIz1Up8iy8hLCIiUiuSk+H89EWHvYJ59ZaetG3mQ6C3GxEBnnUfj8nESd+mtE86rsRXpJ6q0Rjf3bt38+uvv2IymejcuTO9evWyVVwiItLYne/tzQ9uSrabB22b+dA1wr+Cg2pXvF/wX4mviNQ71Up8T58+za233sqmTZsICAjAMAxSU1MZPHgwK1asoGnTpraOU0REGpvziW9ui1b2jaOYk77B5ifHj9s3EBGpFqfqHDR9+nTS0tI4cOAAZ8+eJTk5mf3795OWlsYDDzxg6xhFRKQxKkp8I1vaOZC/xPud79iJjSUuJZv9cansj0slLiXbvoGJSKVUq8d33bp1bNy4kU6dOlm2de7cmX/+85+6uU1ERGzD0uPrOInvyfOJ77mYYwx9eTPZeQWA+Ya7jbMG2mfssYhUWrV6fAsLC0tdNs7V1ZXCwsIaByUiIlKU+OY5UI+vZahDbCzZeQW8ektPXr2lJ9l5BSRn5to3OBGpULUS3yuvvJIHH3yQkydPWrbFxcXx0EMPMWTIEJsFJyIijZgD9vgWDXVwjTsBhkHbZj60beZj56hEpLKqlfi+/vrrpKen06pVK9q0aUPbtm2JiooiPT1dC0mIiEjNFRbC0aOAY43xLerxdc7KxC8n087RiEhVVWuMb2RkJHv27GHDhg389ttvGIZB586dGTp0qK3jExGRxighAXJywMnp/IppJ+wdEQA5ru7kBzXB5WwS4Wln7B2OiFRRlXp8v/32Wzp37kza+QnFhw0bxvTp03nggQfo27cvXbp04fvvv6+VQEVEpBE5P8yByEgo5Z4SeypauliJr0j9U6XE99VXX+Xee+/Fz8+vxD5/f38mTZrEK6+8YrPgRESkkSpKfKOi7BtHKSyJb3qinSMRkaqqUuK7d+9err766jL3Dx8+nN27d9c4KBERaeQcOvFtDkCYenxF6p0qJb6nTp0qdRqzIi4uLpw5o18EIiJSQ+cT31NNwjh8OsPOwVgrmtkhTD2+IvVOlRLfiIgI9u3bV+b+X375hbCwsBoHJSIijVvOoT8BePa3HGasjMbT1ZlAbze7xhTo7YanqzNvxuQBEJl+xu4xiUjVVGlWhxEjRvDkk09yzTXX4OHhYbUvOzubp556ipEjR9o0QBERaXxMR809vqNHX849wy8n0NvN7quiRQR4snHWQHK+A/73Ir1MGbgEeGrhCpF6pEqJ7xNPPMGnn35K+/btmTZtGh06dMBkMvHrr7/yz3/+k4KCAubOnVtbsYqISGOQl4fryTgAmnXvSMcIfzsH9JeIAE/o3RkAl5Nx5vmGRaTeqFLiGxISwrZt25gyZQpz5szBMAwATCYTV111FUuWLCEkJKRWAhURkUYiNhZTYSE5zq7kN3PAvynh4eDkBHl5cOoU4GXviESkkqq8gEXLli358ssvSU5O5vDhwxiGQbt27QgMDKyN+EREpLE5f2PbCf8Qc4LpaFxcICwM4uIgNhYiOtg7IhGppGqt3AYQGBhI3759bRmLiIiIJfGN9Q8h2M6hlKlFCyW+IvWQA/4rLSIijVpR4hvggMMcikRGmr/Gxto3DhGpEiW+IiLiWIr1+DqsosT3+HH7xiEiVaLEV0REHEt9SnzV4ytSryjxFRERx2IZ6hBq50DK0aKF+asSX5F6RYmviIg4jqys81OE1ZMeXw11EKlXlPiKiIjjOHoUgAJfP1I9fOwbS3mKEt+EBEy5WrlNpL5Q4isiIo7j/DCH3MgWYDLZOZhyNG0Kbm5gGLicird3NCJSSUp8RUTEcfz5JwC5LaPsHEgFnJwsvb5FyyuLiONT4isiIo7jyBEAclu0sm8clVGU+MadsHMgIlJZSnxFRMRxFPX4tnLwHl+wzOygHl+R+kOJr4iIOI7zPb559anH96R6fEXqCyW+IiLiGAoL/xrq4OhjfKFYj6858T18OoP9canEpWTbMyoRKYeLvQMQEREBID4ezp0DZ2dyI5oDDj6E4HyPr2f8STxdnZmxMtr82tWZjbMGEhHgacfgRKQ0SnxFRMQxnO/tpUULcHW1byyVUWyow8ZZA0nOzOXw6QxmrIwmOTNXia+IA1LiKyIijuH8jW20bm3fOCqraNni5GQiXAqIiPC3bzwiUiGN8RUREcdQ1OPbpo1946gsPz/zAyA21r6xiEilKPEVERHHUN96fOGvXl8lviL1ghJfERFxDOd7fI8HhHH4dIadg6mk8+N8OX7cvnGISKVojK+IiDiEgsN/4gxM2Z7MgZhoPF2dCfR2s3dY5VOPr0i9osRXRETsLz0d58QzAEy5ezit2oQT6O3m+DMjqMdXpF5R4isiIvZ3fpjDWU8/WrUJp2t9mSGhKPFVj69IvaAxviIiYn+W8b0hdg6kioqGOqjHV6ReUOIrIiL2d35Gh+MBYXYOpIqK9/gahn1jEZEKKfEVERH7syS+oXYOpIqaNzd/PXcOkpLsG4uIVEiJr4iI2N/5oQ7H6lvi6+4OIeeHZ2i4g4jDU+IrIiL2d77HN7a+Jb6gKc1E6hElviIiYl/5+XDsGADH6tsYX9CUZiL1iBJfERGxr9hYyM+n0M2NUz5B9o6m6jSlmUi9ocRXRETs6/wwh7zmLSh0crZzMNWgKc1E6g0lviIiYl+HDgGQE9XGzoFUk3p8ReoNJb4iImJff/wBQG6btnYOpJrU4ytSbyjxFRER+zqf+Oa0rqeJb1GP78mT5hv1RMRhKfEVERH7Kurxra9DHUJDwdUVCgtxPZ1g72hEpBx2TXy3bNnCqFGjCA8Px2Qy8fnnn1vtNwyD+fPnEx4ejqenJ4MGDeLAgQNWZXJycpg+fTrBwcF4e3tz3XXXceLEiTq8ChERqbbcXIiJAepxj6+Tk2UFN9cTGucr4sjsmvhmZmbSo0cPXn/99VL3v/DCC7zyyiu8/vrr7Ny5k9DQUIYNG0Z6erqlzIwZM/jss89YsWIFW7duJSMjg5EjR1JQUFBXlyEiItUVEwMFBeDlRX5oPZzDt0jLloASXxFH52LPk19zzTVcc801pe4zDINXX32VuXPnMnr0aADef/99QkJCWL58OZMmTSI1NZV33nmHDz/8kKFDhwLw73//m8jISDZu3MhVV11VZ9ciIiLV8Pvv5q/t24PJZN9YauJ84ut24jiYwu0cjIiUxa6Jb3liYmJISEhg+PDhlm3u7u4MHDiQbdu2MWnSJHbv3k1eXp5VmfDwcLp27cq2bdvKTHxzcnLIycmxvE5LSwMgLy/P8ih6LRVTe1We2qpq1F5VUx/by+nXX3EGCtu1I//8jWH5+fm1fg22biunyEicAefYY9Dikjq5hrpUH99b9qK2qpqqtJct2tRhE9+EBPMNAiEhIVbbQ0JCOHZ+acuEhATc3NwIDAwsUabo+NI8++yzPP300yW2f/3113h5eVleb9iwodrxN0Zqr8pTW1WN2qtq6lN79fjmG1oBh0wmtm7dCriwdetWjvnUzflt1VYtUlPpBWTt+wVa3FKn11CX6tN7y97UVlVTmfbKysqq8XkcNvEtYrrgoy/DMEpsu1BFZebMmcPMmTMtr9PS0oiMjGT48OH4+fmRl5fHhg0bGDZsGK6urjW7gEZA7VV5aquqUXtVTX1sL+dXXgGgzTXXkH355by0bweXX345XcL9avW8tm4rk5cXLF5Ms6wMgDq5hrpUH99b9qK2qpqqtFfRJ/Q14bCJb2hoKGDu1Q0L++uGh9OnT1t6gUNDQ8nNzSU5Odmq1/f06dNcdtllZdbt7u6Ou7t7ie2urq5WjX7haymf2qvy1FZVo/aqmnrVXudXbXPp3BkXF/OfJBcXlzqL32Zt1cY8FZtb3AlMRmGdXkNdqlfvLTtTW1VNZdrLFu3psPP4RkVFERoaatX1nZuby+bNmy1Jbe/evXF1dbUqEx8fz/79+8tNfEVExAGkp0N8vPl5u3b2jaWmmjcHJyeccnIIzky1dzQiUga79vhmZGRw+PBhy+uYmBiio6MJCgqiRYsWzJgxg2eeeYZ27drRrl07nnnmGby8vBg/fjwA/v7+TJw4kVmzZtGkSROCgoKYPXs23bp1s8zyICIiDup8by9Nm0JgIGTV44TRzQ3Cw+HECSLSTts7GhEpg10T3127djF48GDL66JxtxMmTGDZsmU88sgjZGdnM3XqVJKTk7n44ov5+uuv8fX1tRyzaNEiXFxcGDt2LNnZ2QwZMoRly5bh7Oxc59cjIiJVcH7FNjp0sG8cttKqFZw4QfPUU/aORETKYNfEd9CgQRiGUeZ+k8nE/PnzmT9/fpllPDw8WLx4MYsXL66FCEVEpNYUn8O3IWjZErZuVY+viANz2JvbRESk4YpLycY7+gABQEJICxLjUjl8OsPeYdVMq1YANE9V4iviqJT4iohInYpLyWboy5tZsSOaAOCp33JZv3grAJ6uzgR6u9k1vmo7v3pbhBJfEYelxFdEROpUcmYu2bn5dM4wLzQ0e9oopnfoBECgtxsRAZ72DK/6ivX45to3EhEpgxJfERGpc8FZKbhmpIPJRLvLeoKHh71DqrmiHt+008SUc/+KiNiPw87jKyIiDVfU2Tjzk1atGkbSC9CiBQDeeedwTj5r52BEpDRKfEVEpM61S4o1P2koU5kBeHiQ18y8sqjriVg7ByMipVHiKyIida79mWPmJ1272jcQG8trbu71dYs9ZudIRKQ0SnxFRKTOtU88bn7SwBLf3OaRALjGqcdXxBEp8RURkTrXPrGB9vhGmBNft9jjdo5EREqjxFdEROqUc+IZgrNSMUwm6NTJ3uHYVF6keaiDenxFHJMSXxERqVMevx8EILdlFHh52Tka28o93+Orm9tEHJMSXxERqVPuv/0KQE6HjnaOxPaKenzdTmiog4gjUuIrIiJ1yuN3c+J7rkNnO0die0U3tzmnpUFKin2DEZESlPiKiEidcv/jNwByOjSs8b0Ahpc3SZ5+5hdHj9o1FhEpSYmviIjUHcMo1uPb8BJfgNgA8yIWHDli30BEpAQlviIiUndOnMA5PY08J2dyW7e1dzS14nhAmPnJn3/aNxARKUGJr4iI1J39+wE4EhSB4eZm52BqxzElviIOy8XeAYiISP0Ul5JNcmYuAIHebkQEeFZc5nzi+0dwS6LqLtQ6dTwg1PxEia+Iw1HiKyIiVRaXks3QlzeTnVcAgKerMxtnDbRKfksr893+XYQCvzdtuInvsUD1+Io4Kg11EBGRKkvOzCU7r4BXb+nJq7f0JDuvwNKzW1qZ9+/uB8CZ7bsBOBbSikDvhjrUwdzjaxw/TtyZNDtHIyLFKfEVEZFqa9vMh7bNfCosM7B9UzbOuJwuqScBmPvY2FKHRtR3gd5upAc25ZyLG6aCAu6ev4q4lGx7hyUi5ynxFRGROhGRnIDTuWzw8CC0Z8NbvAIgIsCTDbMHQ+vWAIScOVGiJ1xE7EeJr4iI1I19+8xfO3UCZ2f7xlKLIgI88ejQDoAWKQl2jkZEilPiKyIidWO3eXwvF11k3zjqQps2ALRMibdzICJSnBJfERGpG7t2mb/26WPfOOqCJfFVj6+II1HiKyIitc8wYOdO8/NGlPi2SFaPr4gjUeIrIiK17+hROHsWXF2hWzd7R1P7ihLf1ARz0i8iDkELWIiIiE0cPp0BlLGKW9Ewhx49wN29jiOzg1atMJyc8MrLweX0KWgeYO+IRAQlviIiUkOB3m54ujozY2U08NcqblYa0/heADc38sIjcDsRi9uxGLiog70jEhGU+IqISA1FBHiycdZAkjNzOXw6gxkro0vOXdvYEl8gt2XUX4mviDgEjfEVEZEaiwjwpGuEf+mruBUWNtrEF8DtqBJfEUehxFdERGqV29EjkJYGHh7QpYu9w6kzlsT32FH7BiIiFkp8RUSkVnnu/dn8pFcvcGk8I+z+SnzV4yviKBrPbyAREamWuJRsy5jdUmdsKEXRDA8Anr+cT3wb0TAHgNxWrQAlviKORImviIiUKS4lm6EvbyY7rwAoY8aGYkqb4cF3n/l5o0t8z/f4upxNMg/18POzc0QiosRXRETKlJyZS3ZeAa/e0hOg9Bkbiik+wwNAoIcz7q9Em3f27VvL0TqWQl8/kjz9aJKdBn/+aR7qISJ2pcRXREQqVOpsDWWICPD8azjEgQOQlQU+PtC+fS1F57higiJoEpcGf/yhxFfEAejmNhERqT0//mj+etFF4Oxs31js4M+g5uYnv/5q30BEBFDiKyIitWnTJvPXK66waxj28meT84nvb7/ZNxARAZT4iohIbTEM+O478/PBg+0bi50cbhJpfqIeXxGHoMRXRERqx5EjcOIEuLrCpZfaOxq7sPT4/vEHFBTYNxgR0c1tIiKNWVlz9BZtLz4fb5UV9fZecgl4edU01Hop1j+EQjc3nM6dg+PHISrK3iGJNGpKfEVEGqny5ui9cHugt1u505iVqmh876BBNoq4/il0ciY3qi0evx80D3dQ4itiV0p8RUQaqfLm6C3a3raZj6UnuEqJr8b3WuS0bWdOfH/7DUaMsHc4Io2aEl8RkXqoOssIl6WsOXrbNvOha4R/9So9dAhOngQ3N/NQh0Ysp+35+Yt1g5uI3SnxFRGpZ8oaotDM24F+pRcNc7j0UvCsflLeEFgSX01pJmJ3DvRbUkREKqOsIQq2SHxrdDNbcUXDHBrx+N4iOe2U+Io4CiW+IiL1VFWWEa5IoLcbnq7OzFgZDfx1Q1u1GMZfPb6NfHwvQE7rtuYniYnmR3CwfQMSacSU+IqINACHT2eQn5/P2ZzqHR8R4MnGWQNtM274998hIQHc3eHii6tXRwNieHlDixbm6cx++w0uv9zeIYk0Wkp8RUTqsQt7at2cnLlycDYtm7pWua6IAM8a3SRnsWGD+eull4KHR83rawg6dTInvr/+qsRXxI6U+IqI1GPFe2p/i09l9qp9JGfl0bKcY2yyOEV5Pv3U/HXUqNqpvz7q2BHWr9c4XxE7U+IrIuIAajI9WVFPbX5+PgCHz2Ti4uJSaj2lzQhR7bG8pTlzBrZsMT+/8Ubb1Vvfdepk/qrEV8SulPiKiNhZWdOTVXXYQaCXK25OBrNX7SuznuIzQhRfnMJmVq+GwkK46CKtUlZcx47mr5rLV8SunOwdgIhIY1c8GX31lp5k5xVUfXlgIDzAkzk9C/h8yiUV1lO0OIVNk174a5jD6NG2rbe+K0p8jx6F7Gy7hiLSmDl04jt//nxMJpPVIzQ01LLfMAzmz59PeHg4np6eDBo0iAMHDtgxYhGR6mvbzKfcKcriUrLZH5da7tjcIHfoEu5Xop7KHFtjqal/3dimxNdas2YQGGie6u2PP+wdjUij5fBDHbp06cLGjRstr52dnS3PX3jhBV555RWWLVtG+/btWbBgAcOGDeP333/H19fXHuGKiNSKmozNrfVxvUXWroW8PHPvZtGYVjEzmaBLF9i6Ffbtgx497B2RSKPk8Imvi4uLVS9vEcMwePXVV5k7dy6jz/csvP/++4SEhLB8+XImTZpU16GKiNSamozNrfVxvUWKhjmMGWP7uhuCnj3NiW90NNx2m72jEWmUHD7xPXToEOHh4bi7u3PxxRfzzDPP0Lp1a2JiYkhISGD48OGWsu7u7gwcOJBt27aVm/jm5OSQk/PXLO9paWkA5OXlWR5Fr6Viaq/KU1tVTWNpr6LZGIq+Fj0vft1F+1oFedChmRdQsl2Kt1dpdZZ3bI3jzMrC5auvMAF5111n7vl1YHXx3ireXnl5eZi6dcMFKPz5ZwocvH0u1Fh+Fm1BbVU1VWkvW7SpQye+F198MR988AHt27fn1KlTLFiwgMsuu4wDBw6QkJAAQEhIiNUxISEhHDt2rNx6n332WZ5++ukS27/++mu8vLwsrzcUjVWTSlF7VZ7aqmoaenvFZgC4sHXr1vNbzM+P+ZRe5lgFKxVv2LChUnXaMs6wbdvol5VFZrNmbDx5EuLjq3+iOlSb760Lv2f+6ekMAvJ37uSrtWvNwx/qmYb+s2hLaquqqUx7ZWVl1fg8Dp34XnPNNZbn3bp149JLL6VNmza8//77XHLJJQCYLvjFYRhGiW0XmjNnDjNnzrS8TktLIzIykuHDh+Pn50deXh4bNmxg2LBhuLpWffWjxkbtVXn1ra1OpmSTnGX+DzvQy5Xw2vh4vBx13V7Frxfq7poPnEzjpX07uPz8il5Fz7uE+5Vapvj24oq31x9nsius05ZxOi9eDIDHHXcw4tprq32OulIX760S37Nz5zAeewy39HRGdO8OkZG1ct7aUN9+d9mT2qpqqtJeRZ/Q14RDJ74X8vb2plu3bhw6dIgbbrgBgISEBMLCwixlTp8+XaIX+ELu7u64u7uX2O7q6mrV6Be+lvKpvSqvPrRVXEo2V//fthrPLWsLddFeF14v1N01u7i4WH0tel78mouXqagtXF1dcXHJq7BOm8V5+DB88w04OeF8//04O/h7u7jafG+V+J65uppv+tu3D9cDB6B161o5b22qqL1qshBLQ1Mffs87ksq0ly3a06GnM7tQTk4Ov/76K2FhYURFRREaGmrVNZ6bm8vmzZu57LLL7BilSMNgq7ll64vi17tm+uWN4ppt5p//NH8dNQpatbJrKA6vZ0/z159/tmsYtaFo9pCRi7cycvFWhr68mbgUzVksjsWhe3xnz57NqFGjaNGiBadPn2bBggWkpaUxYcIETCYTM2bM4JlnnqFdu3a0a9eOZ555Bi8vL8aPH2/v0EUcRk17YIrPB1s0B2xD7skpWtjBlhpyL5hTehq8/775xbRp9g3GQVn93PTqBR9+aJ7ZoYEp/s8jwIyV0SRn5jao97vUfw6d+J44cYJx48aRmJhI06ZNueSSS9ixYwctW7YE4JFHHiE7O5upU6eSnJzMxRdfzNdff605fEXOs9lSuN5ueLo6M2NldI3qaYxK+x786/beNPF2axBJcMDHH0FGhnnu3iFD7B2OQynt52ZFu1b0APL3/OzYf4BroLxFWETszaF/7lasWFHufpPJxPz585k/f37dBCRSz9iqByYiwJONswaSnJnL4dMZDt2TY8/e1dLOXfx7EOjtxuQPdzPh3Z+Av/6BqK9MRiFNlr1lfjFtWr2cpaA2Ff+5ScrMZfKHu7ljdw57AZdjRzl5LJ7wlmEV1iMituPQia+I2IYtemAiAjwdMtEtzlY93LY8d5GiIRSl/QNRXw2I+Rn3I4fB1xfuuMPe4Tik4j83Rd/7rI+b4xV/gnM790BLx58BQ6QhUeIrIg2GPcYYFvXyHj6dUeq5L1TZfyAcfjx1QQGPbXrP/HziRHPyK+Uq+t6nde8O8SfwPLAPblLiK1KXlPiKSINTV2MMS+vl7RsVVKNe3LLGUzuawI8+IOLMUfL9A3B54gl7h1OvnOvcDb/1X+Jx4Bd7hyLS6CjxFRGppuI9zG2b+ViN662ussZTOxKn1BRCXlgAwOlZcwhv0sTOEdUv2V27A+BxYJ+dI7GPhjzLiTg+Jb4iIjVk6ynQHH08dbNXX8DlbBKHmkSSc/vdhNs7oHrmXJduALgf+h1yc8HNzc4R1R17jsMXgXq2gIWIiNhXm8RYmrz3JgD/uPIe82pkUiV5EZGkePjglJcHBw7YO5w61dgWxhHHo8RXpI7EpWRz4GQasRlwUqsZSRUcPp1hudnNnpwy0ln6+bOY8vNJG3oVW1r3tndI9ZPJxP6QNubnP/5o31jspG0zH833K3ahoQ4idcD64z0X/vnbD2ycNciuH+9pnJ3jK+1Gt0Dvqn0sbrOEubCQ5g9Oxi/pONnBIWx7eCF8m2CbuhuhXc07c/mxvbB1K0yebO9wRBoNJb4OqKoJiRIYx1LeIgYv3dSNvdHRfHgYuy4AUVvj7Brie9Ge04oVv9GtqjHYImm2smABfuvXkuvswrhrHiH624Sa19mI7WzeBYDczVs4k5LdIH5WROoDJb4OpqoJiW4UcCwVLmLQ1JsET8Ne4VnUxny3De296CjLNFf3RreaJM0lvPcePPUUAJmvvc6CG26teZ2NWKC3G7+16ES+yQm3E7Hc9uQq/v33m9SWInVAia+DqWpCYo8J+6VsZX0/6lrxRRXKY8sxdnX9XqxJ73Jljq2rZZprc+xujWeHKCyEJ5+EhQvNrx94gMD7JxFom/AarYgAT1Y/fg1567vj8ks0XY/uIznzunr1e7shfrojjYMS3zpQnV8QVU1IdJOAY7HF96O6f1hK63kN9HazeQJe1hCAungvVtSzbqtja3NaMZsPRbC1rCzzimwrVphfP/44/OMf9o2pAYkI8ITBA+GXaHrH/WrvcKqktJ+hf93eu9zfMZX9Z1yktinxraLiyQhUnJA0tI9/xXbKGztak/dNbSyqUJwjrCxWk551W/TKV/aPeHn7bToUwZYMA1auhEcegdhYcHGBN9+Eu+6yd2QNz+WXw2uv0ffEQew/AKryiv8MBXq7MfnD3Ux49yeg5D/ah09nkJSZy+QPd9f6P+MilaHEtwouTEag4oSksQ9FsNXHYY5WT014u4Knq1O5Y0dLe9/sjDlLcrFEtiK2XlShSFVWFqvKjWE1/WSkqj1J1e2ZLqtHvbjK9uY61EIVeXnw1Vfwwgvwww/mbS1bmsf3Dh5s39gaqv79Aeh45ii/p6VCLfy81qai3zFl/QN34c/A+3f3o4m3m83/GRepCiW+VXBhT1pVxv01xqEIturtdrR6airIHdY90J/0XKPC91BRj60j3GRVXEUJW1VjLut708y74l9RZSWZtfVHtawe9eIctjf3QunpsH27OeH9z3/gzBnzdi8vmDMHZs0CTweMu6EICyOnZRTux2Lw2rMLOrWwd0TVUtrvg3rzMyCNjhLfaqitnrSGxla93bVZT1V7UW0lPMAT10queFVXN1nZUlVjLut73MzbhbM5cOBkGi4uLlVKMquS+FZn3GFFvwccoje3oMCc3J4+bX6cPAmHDsEff8D+/RAdbb6BrUhICNx2G8yYAc2b2yvqRiWr78XmxHfndvjbaHuHY1MO8TMgcgElvmVwycjA+frrwWSybGt5Lp93j56l5c4g8HCxfu3uXGo9Lc/l896xs7T8KQjgr+cXlD+XV0BegUHT3HyWxafT8kfzfdPLjiWbn5dT//vHk2m5w1ze8ryM8uUyqjjK7Hx5Z8Pg0sREnBcvtmqvVjn5fHg8hV7bAgD49/FkWv0QAO6Ve9udyysgv6CQkNwC/nM6nR5bzfX850QKrbaWUk8F8bfKyWf5iVS6f++Pq7MTYceTKfzIIB3INJkIjgzA3cV6McOc/ELyCsyJgckwcHF2KlGmuKicfFbEpRK12R8Mg5Un04ja5AfAypNptP3Ol+aZaTi//DKYTETl5LPyZBqhG7zJdHXCxclcf1RuPivjzh/r5kIEEAGW7aFf+5wvbyoRT1RuAf89mUrUd/7g5mwV28cn04j61hxPqc8vKL8qPo2ob6y3X3iuojImw+CT+DRabzSXL4q5dW4Bn8SnEfaVN1muzjgXxVzs+9U6t4BPE9LouMEcz6cJabTe4EehCXrGp1EI5BmQ6ARNw/xoXWDwWUI6rb/2tTpXca1z8vn8VDrha73IcnHGxdmEm7MTrXML+PxUOq3X++LibOKL+HSMDwzAYLXJRPsNvuBs3aatcwv4/HQ6EWu8APj8bBat1/mAaxV+zqr581VpBQW4ZGYyPDkZl8JCyMyE3Eok/61awYABcPPNcPXV5jG9Umey+l5K4KoVeP20w96hiDQK+g1XBqf8fJy++spqmy9wJcCR0l+XxhcYXKxM8efFeZx/+AIhADHm7YOKPS+r/oHFyhR/XlecgGalbPcBrgA4Zn59ebHnleFRrJ6mxY7tX8V6isdzGcBx8+uLLyxQSp3u5x+V5Q1cAhBb7BwXPPe5oHzxMiW2n6jc9gvL9Cvj2L4AcebXZT0vXr5PKdvLK9Mb4KR1Ga8ytl9Y5qJiZYo/73Vh4ThwK9oeX36dPUspc+H2HhceWEqcFx4TWMG57cUElNq/5utr7s0NCYG2baF9e/PjkkvUs2tnWf0uAcDr593mcdaV/CRIRKpHiW8Z8j09yX/rLVyc/+rROZGcxWsbD/Hg0HY0D/Qq8bp4b2fxY17deIgZQ9sBWJ4XL38iOYtFGw4x/uIWhPi54+3uQqCXm2X7Q8Pa0TzIu9Q4TyRn8cqGP5g5rD2A5XlZ5UtlMnE2M5fnvvqN3PO9m27OTjx2TUeCSpte6YLrzM/PZ+/evfTo0YO0nEKe/fJXSz2uLs48PqITmTn5vPj17zw8vAPe7i48U6yMm7MTj4/oZD7X+bpjz2bx4vrfuf3SloT6eeDt7kKQt5tl+8NXdSCySenXeDYzl4VrD5Kbf75+FyfmXtuZjNwCXlj3G49c3ZEWQV6W8sfPZpW+PTmb57/6jQmXtSLU34OE1HO8v+0oj15jXa54mxw/m8VzX/3GY9d0BCjx/OHh7Ug8+hu9LroIl/M9a0mZuWSeyychLZv3fjjKnGs6AfDsV78y55pOtAi2vk5z+TwS0s7x7g9HefyajrQo1hbHz2ax8MvfmDvigu1JmZbtAAu//I3HrzWf65kvf+XxEZ1oWaz8saTMktsv+N4fS8pk4dpfmXu+nqLnLZt4W5VNyswh41w+6efyWbrpT6vv/d9v6ELGuXz+sfY35o001/OPNb8yb2QnCgoKeOarP3j8mvY4OztbtgP8fe2vPDmys1XMF0rKyCEjJ5+0nAKWfHeYnPPvCXcXJxbc0JUmPmX8W1PKz3Li+boAfNxdCC46tpSy5apK+aqUdXIi382NrXv20H/4cFz9/c1jdb29wcOj4uPFLnLatuespx9B2WmwZw9cXOJfchGxISW+ZSh0d8eYMMHqv++UuFQ+Pr2VCbdcTvMI/xKvS5MSl8qqU1u5c+zlAJbnxcunxKXyScJW7ppYxvaby6//0/it3H2Tuf6i580j/Kt0l/zJuFT+G7PVaozlHSMvJ6gSY5mNvDxOBATQfcQITp7O4uMjW61u/AkK8ORkXCqrT2zlvhsvJxVY9WdTq3PdOcL6XKlxqayO3cp9d1xOZGnbb7DefuG1fHKoiVX9d11tbp81x7Yy+brLre6eTotLLXP72qNbmXLb5bSI8De/Tt7KlFGXl3n3dVpcKl/GbGXqSPP5Lnx+37WXcDK6CT1HjLC8t5qcf6TFpfJV0lbuP1/+q5gm5ucXnKt4+XWJW5l2bcm41/8ZxPQR5WwH8/Nrzj8/HMg1vXuSXmy8c3pcKusPB5rLlHG96XGpfH0ogBEXmdv660MBPHB12TEDPD4+22rs75SB5hg2/uHPjOHnn//ux4zhl5Ofn8/Gw4FMG3YJLi4ulu0A3/zux0PDyo7twvM+cYv1z0OTKo49DD7/cGRGXh6pqanQoYN6DusLk4kfI7tyzR/bYN06Jb4itUyJbwNV1gTjxaeSKU1Fs09UNpmuzA2AtT3TRV3OpFGfJme/MMaazMtbnUUYLrzhpa7aTDfaiKP6tk1fc+K7Zo1laWhHVHSj6dGz5+wdiki1KfFtoCqaYLwq02EVJXWlTUJe2SmnGrK6WimtLJWdK7esJLW0GRh2xpyt1LlrMmVRXU9DJuKovmvTB8NkwrRrl3nmjfDwOjlvlT4VTMnm2WhncveYb8Kz5UqDVZnvW6SmGnfGUo9VtofxwgnGiyc2FU3jVdaKO+/f3Y/kzFyrKadqqrq/+BxhQQpbr5RW2R7QqvbUlpekFvWG2qIHt7KqOw1ZfehVF6mKRO9Asnv2xuvnXbB2Ldx7b62fs6qfCiZn5ZFbaOKlm7rRMczfJr9vHXGOcmn4lPjWQ9XpYSwvsbkwWSqtzIUr7uyPS7XJtdTkY/ayFj2wl5rO71zVpLMqK6gVP6a8Pyp1Pel8VZLm6iTlIvVF+tCrzInvmjV1kvhW91PBtk29bTaPfX2co1zqPyW+dlDTj3Vq0sNYmWSpLpOfmnzMXtaiB/VVddq9NsatOupYWK0EJQ1Z+rCrCXlxIWzYANnZdbZiXlmfCtZVAuqov2+k4VLiW4eq27tZVqJc3R7GytxcVNVfRjW56aEmH7OD7W5iq61xZlX5aF5/BMqn9pGG6lynruY5lU+cgO++gxEjKnWcrYZ76WdLGgslvnWoqh9Nl5YI/uv23jbr1bTVR8dVuemhvCTQXj16NRluUdV6A71cq7P2RqN0+HQG+QUF9g5DpG6YTDByJPzrXySt+IT4Hv0r/B1Y1nAvJbAiZVPiawNV6SmsylROxRPBopvMio/Bqun4RlskmkXJSUU3PVQ2ya5pr0NZ7VnZdq7sWNnKKK19m3m7EF3jmhu2C98rbk4GgV6ak1YatsOnMzAuGkA3/kXO56sZGXYjnm4u5SayZQ33qs+Jr2Z4kNqmxLcGanJHanUSwdroDa1uollactK3ZQAtm/qVeZ7a7M0trz3rIuEuy4X15uXl2fwcDU3x90p+fj4//7iVcP0BlAaq+O8u9zx3ol3cCU9P5L2erty1N79SiWxdzlleWzTDg9QVJb5lKBqz6uLiUmaSVtaNWcnFfgmV1dPoKDcyVVd1kpPajL+89tQNUfVP0XslLy+PY2WsKizSEFz4u4s/roI1q+n23WoIqtw434agvL+n+r0ttqTEtxSljVkta2xtWTdmFVfXvYx1vRKWPZKTqtyQV512rkwb1qfV2kTEcVn9jpp0L6xZTcCqFbjdPcy+gVHs99yZzFo/V0XTbir5FVtQ4luK4hN1N/XzrNTY2hL/tRdjz5u0Gto8p7V9jZWtv6y5lEVEauTqqyEiApe4OK76Yxsw2C5hlLaAUV2Nty9vfl9HWLRI6jclvuVo29Sbni2bVPqjcnsPRWgM85zW9jVWtv6y5lIWEakRFxe4+274xz+49Zf1wNw6PX1ZCxj5uzvV6Xj70v6eahYLsQUlvpVg74S2KupTrNVV29dYlfprulqbiEgJEydiLFhA/2O/8MfRGIjoWWenLuuff0cYb98QZ7GQuqfEV6SKNKZXRGpVy5ZkDByC76aNBH70AfTvWaend8QOlOK/dxvCLBZiP0p8RSqpMYyhFhHHkDz+Dnw3bSTgv/+BRc+Dq23G1ta3m3LL+r1b1COteX+lqpT4ilRSYxhDLSKOIW3YNZzxDqDpmdPwySdw6601rrM+3pRb3u9dzfwg1aHEV6QKHPEjQBFpgFxd+aDXtcza+h+YNw/GjKlxr299vSm3tN+75c38IFIeJ3sHICK2c/h0Rr35CFNEyvdO3xvID24Khw/D22/brN6im3Lre5IYEeBJ1wh/jfmVKlHiK9IAFB8HN2NldL34CFNEypfl5snpGY+YXzz9NGRU/p/auJRs9selsj8ulbiU7FqKUKT+0VAHkQZA449FGqadw8ZwzVv/xO3YUXj1VXjiiQpvUCtrvlsRUeIr0mBo/LFIw1H0Kc6Dnx5kY/ebWXzsRQpfeIFTt97B0PcPlrhBrfiqoWXNdysiSnxFREQcjtXNWwnd2ffTp3Q79Sfccy/ZF0/n1Vt7Wd2gVlpi21jHvmpZYymPEl8REREHVPQpTqC3G9NHzeCj9x4ibPPXTHFtQd85Q5TQlULLGtczmzdjys+v01Pq5jYREREHFhHgyeIXJ5L0j+cBeOS794g4+HOpZRv7zC7Fh3m8ektPsvMKNMzDEe3YAUOHwqBBOD/4IBQW1tmp1eMrIiLi4CICPOGxh2DvT5hWroRbboFduyAkBKj8CmeNRWnDPIoPgQANg7CLPXvgySdh7Vrza1dXCi+/HOecnDoLQYmviIhIfWAywZtvmpOHQ4dgwAD4+mto2bJKK5w1xqkOLxwCARoGUaf274ennoJPPzW/dnaGCRNg3jwKIyIo+PLLOgtFia+IiEh94edn7i0bOhT++AMuu8yc/HbpUuEKZ9B4ezkvXLVOq73VAcOA776DV175q4fXZILx481JcLt25m15eXUalhJfERGR+qRdO9i2DYYPh4MH4Yor4K23YPRoc2JxgcYy1WFlhnMUrVontSg5GZYvN3868csv5m0mk/n9+fTT0KWLXcNT4isiIlLfRETA99/DtdeabxS66SYYMQJefx2iouwdXZ2qaHxzZZQ1BZqmRqukzExYvx7++1/4/HMoGrPr5QV33QUPPvhXD6+dKfEVERGpj4KCzB8lP/MMPPccfPkldO4Mt90GkyZBnz72jrBOlDWco7KJb3kr3WlqtDIYBvz2G3z7LWzYYB5uk11saezu3WHiRPN7MSjIfnGWQomviIhIfeXhAX//u3nc5NSp5kT47bfNj169YORIuPJKuOQSc9kGqibDOUpb6W5nzFmAUlfAa3SJb14eHDliTnT37IHdu80zipw6ZV2uVSvzcIZx46B371KH3TgCJb4iIiL1XceO8M035uEPb7wBq1bBzz+bH//4B7i5QYcO5nIdOpiHSoSGmqdD8/UFb++/Hp6e4NQ4pvkvPi64aCW8C4dN9I0KqrW5gCszxKIsVR16EZeUQUpyOk7ncghwKSTMDUhJMY/JTU6GlBRST54m93QiLgkncU2IxzXuBG6xxzAVFJSs0MMD+veHwYPh2muJa9me5KzzN6qdTLNJzLWhwSS+S5Ys4cUXXyQ+Pp4uXbrw6quvcsUVV9g7LBERkbphMpmnOBswAF57zTzW8rvvzB9HJyTAvn3mR2V4eoKLi3naKScn/r+9ew+K6rz7AP49yy4LEtgYCC6LFUETTdQQgm2j5G1zscTES9/mTYwaiR11Js7YREzjJU1bnWRM1E6MaZ1o9SV2EtORdKpOg4kUrLUhUqDAeolGfSvxygaLLAKrsLvn9/6x4ciyyy3hfr6fmWeU53nOwznfWYYfZ885azQY8KjbDWNzUWwwaGNa62dn+O7wqDjgvI7YXWYAwIG6Rgz/UzhgNGCMKjh41QV1u2/uQQDD/zwEJoOCo6pAVQUAYDAoMH2oIObrtZq3b49RBI80NMAYERE0E/fX63tVQdO1G2guA5sAuKJ8Z+Vb9gOAIgKDCBR8/a+oUAA0hhthgACqCkV8/xpEYBDVdzmCqgJeL6SxEfFeL+I7yKyt2/5cJjMqhsbjZGwivoi/A88tm4XbH5wMmH3ZBntcXDD94XKRQVH4ZmdnIzMzE++88w7S0tLw+9//Ho899hhOnDiBESNG9PXuERER9a6YGGDRIl8TASoqfG9Vf/GF7zFoDoevffUVUF/vuzmp5TWaLf8PQAEQBgC1tb15FN+KGcAoAPBdtYDIFv83AQi4BbDFWEdrtUcBEPjxGTe1XL+tfej07YnBT6wG3aeWvIoBYjbDG2XBBTUUNeZbUBsWAVd4JO5LSYJx+HC442zwWOPQODIJnjgboCgwVtXjf7Pt+O/x9+F2s1k7M/1/VfV+j4sLpr88Qm5QFL4bN27EwoULsWjRIgDApk2bkJubiy1btuCNN97o470jIiLqQ4oCJCX52uOPtz1PVQGXy1cEu1yA1+vrU1W4Gxvx6aFD+K+0NJgMBq1fa8HeCu8HrtQ1ou6G7+33yDATbo80f6N1zl6px4o/H8WG/7kHkWEmZO4qR6P3m33MrjnEgJceHQNLuMlvnzrc15Zn1g0GVDU04doND2AwQBRfv7PRizU5J3HDo0JVDFAVBQIFjUYTDGFh+POyhyFhYZjy9md+N+1tzUiFNSK0S5ciBLsp8LuJt/X5pQwdGfCFb1NTE0pLS7Fq1Sq//vT0dBw+fDjoNo2NjWhs8fF4tV//BXv16lW43W44v/7aWVuL6uoe2vFBxO12w+Vyobq6GiZTsL+VqRmz6hrm1TXMq/OYVTuMRt8HZbTgdrvx1e23ozo+fkDlZYD/2/ff9Ff65dsa8K/hXnwW4zsX+1ncDbw2bTQSowOLPI/Hg3+VlGDid78LozGwzLo13Ii4qJtFbfM+dXVfQwAMbdV3G4D1d4+C87on6Pc1hxsANOFPC+7R5vj2xwDAA3g9qK52tfk9nbUNAIDysw4Avpv/mnO4NdyIMK+rze1bbuts8c6Bx+OBo/Z6p34W6+rqAAAi0u68dskAd+nSJQEgn332mV//2rVr5c477wy6zerVqwUAGxsbGxsbGxvbAGsXLlz4xnXjgD/j20xpdQG5iAT0NXv55Zfx4osval+rqoqrV68iOjoaiqLg2rVr+M53voMLFy4gqtVfvRSIeXUes+oa5tU1zKvzmFXXMK/OY1Zd05W8RAR1dXWw2Wzf+PsN+MI3JiYGISEhcDgcfv1VVVUYNmxY0G3MZjPMZv9rZ2699daAeVFRUXzRdgHz6jxm1TXMq2uYV+cxq65hXp3HrLqms3lZLJZv9X0G/IP6QkNDkZqairy8PL/+vLw8TJ48uY/2ioiIiIj6mwF/xhcAXnzxRWRkZGDixImYNGkStm3bhvPnz2Px4sV9vWtERERE1E8MisL36aefRnV1NV599VVUVlZi/Pjx+Pjjj5GQkPCN1jObzVi9enXA5RAUHPPqPGbVNcyra5hX5zGrrmFencesuqa381JEvs0zIYiIiIiIBoYBf40vEREREVFnsPAlIiIiIl1g4UtEREREusDCl4iIiIh0QVeF76VLlzBv3jxER0djyJAhuPfee1FaWqqNiwjWrFkDm82G8PBwPPjgg/j888/91mhsbMTzzz+PmJgYREREYObMmbh48WJvH0qPGjlyJBRFCWhLliwBwJxa83g8+OUvf4nExESEh4cjKSkJr776KlRV1eYws5vq6uqQmZmJhIQEhIeHY/LkySgpKdHG9ZzVP/7xD8yYMQM2mw2KomDv3r1+492VTU1NDTIyMmCxWGCxWJCRkQGn09nDR9f9Ospr9+7dePTRRxETEwNFUWC32wPWYF4+brcbK1euxIQJExAREQGbzYZnn30Wly9f9ltDL3l19Npas2YNxo4di4iICAwdOhRTpkxBUVGR3xy9ZAV0nFdLzz33HBRFwaZNm/z6eysv3RS+NTU1SEtLg8lkwieffIITJ07gzTff9PvEtg0bNmDjxo3YvHkzSkpKYLVa8aMf/Qh1dXXanMzMTOzZswe7du1CQUEB6uvrMX36dHi93j44qp5RUlKCyspKrTV/OMhTTz0FgDm1tn79emzduhWbN2/GyZMnsWHDBvzmN7/B7373O20OM7tp0aJFyMvLw/vvv49jx44hPT0dU6ZMwaVLlwDoO6uGhgYkJydj8+bNQce7K5u5c+fCbrdj//792L9/P+x2OzIyMnr8+LpbR3k1NDQgLS0N69ata3MN5uXjcrlQVlaGX/3qVygrK8Pu3btx+vRpzJw502+eXvLq6LV15513YvPmzTh27BgKCgowcuRIpKen48qVK9ocvWQFdJxXs71796KoqCjoRw73Wl6iEytXrpQHHnigzXFVVcVqtcq6deu0vhs3bojFYpGtW7eKiIjT6RSTySS7du3S5ly6dEkMBoPs37+/53a+jy1dulRGjRolqqoypyCmTZsmCxYs8Ot74oknZN68eSLC11ZLLpdLQkJCJCcnx68/OTlZXnnlFWbVAgDZs2eP9nV3ZXPixAkBIP/85z+1OYWFhQJAvvjiix4+qp7TOq+WKioqBICUl5f79TOvPe3OKS4uFgBy7tw5EdFvXp3Jqra2VgBIfn6+iOg3K5G287p48aLEx8fL8ePHJSEhQd566y1trDfz0s0Z37/85S+YOHEinnrqKcTGxiIlJQXbt2/XxisqKuBwOJCenq71mc1m/PCHP8Thw4cBAKWlpXC73X5zbDYbxo8fr80ZbJqamrBz504sWLAAiqIwpyAeeOABHDhwAKdPnwYAHDlyBAUFBXj88ccB8LXVksfjgdfrRVhYmF9/eHg4CgoKmFU7uiubwsJCWCwWfP/739fm3H///bBYLIM6v2CYV/tqa2uhKIr2zijzCq6pqQnbtm2DxWJBcnIyAGbVmqqqyMjIwPLlyzFu3LiA8d7MSzeF79mzZ7FlyxbccccdyM3NxeLFi/HCCy/gvffeAwA4HA4AwLBhw/y2GzZsmDbmcDgQGhqKoUOHtjlnsNm7dy+cTid++tOfAmBOwaxcuRJz5szB2LFjYTKZkJKSgszMTMyZMwcAM2spMjISkyZNwmuvvYbLly/D6/Vi586dKCoqQmVlJbNqR3dl43A4EBsbG7B+bGzsoM4vGObVths3bmDVqlWYO3cuoqKiADCv1nJycnDLLbcgLCwMb731FvLy8hATEwOAWbW2fv16GI1GvPDCC0HHezOvQfGRxZ2hqiomTpyI119/HQCQkpKCzz//HFu2bMGzzz6rzVMUxW87EQnoa60zcwaqrKwsPPbYYwHX4zCnm7Kzs7Fz50788Y9/xLhx42C325GZmQmbzYb58+dr85iZz/vvv48FCxYgPj4eISEhuO+++zB37lyUlZVpc5hV27ojm2Dz9ZJfZ+g9L7fbjdmzZ0NVVbzzzjsdztdrXg899BDsdjv+85//YPv27Zg1axaKioqCFmfN9JhVaWkp3n77bZSVlXX5uHoiL92c8Y2Li8Pdd9/t13fXXXfh/PnzAACr1QoAAX81VFVVaWdYrFYrmpqaUFNT0+acweTcuXPIz8/HokWLtD7mFGj58uVYtWoVZs+ejQkTJiAjIwPLli3DG2+8AYCZtTZq1CgcOnQI9fX1uHDhAoqLi+F2u5GYmMis2tFd2VitVnz11VcB61+5cmVQ5xcM8wrkdrsxa9YsVFRUIC8vTzvbCzCv1iIiIjB69Gjcf//9yMrKgtFoRFZWFgBm1dKnn36KqqoqjBgxAkajEUajEefOncPPf/5zjBw5EkDv5qWbwjctLQ2nTp3y6zt9+jQSEhIAQPul2/wEA8B33c6hQ4cwefJkAEBqaipMJpPfnMrKShw/flybM5js2LEDsbGxmDZtmtbHnAK5XC4YDP4/SiEhIdrjzJhZcBEREYiLi0NNTQ1yc3Px4x//mFm1o7uymTRpEmpra1FcXKzNKSoqQm1t7aDOLxjm5a+56D1z5gzy8/MRHR3tN8682iciaGxsBMCsWsrIyMDRo0dht9u1ZrPZsHz5cuTm5gLo5bw6fRvcAFdcXCxGo1HWrl0rZ86ckQ8++ECGDBkiO3fu1OasW7dOLBaL7N69W44dOyZz5syRuLg4uXbtmjZn8eLFMnz4cMnPz5eysjJ5+OGHJTk5WTweT18cVo/xer0yYsQIWblyZcAYc/I3f/58iY+Pl5ycHKmoqJDdu3dLTEyMrFixQpvDzG7av3+/fPLJJ3L27Fn561//KsnJyfK9731PmpqaRETfWdXV1Ul5ebmUl5cLANm4caOUl5drd9V3VzZTp06Ve+65RwoLC6WwsFAmTJgg06dP7/Xj/bY6yqu6ulrKy8tl3759AkB27dol5eXlUllZqa3BvHx5ud1umTlzpgwfPlzsdrtUVlZqrbGxUVtDL3m1l1V9fb28/PLLUlhYKF9++aWUlpbKwoULxWw2y/Hjx7U19JKVSMc/i621fqqDSO/lpZvCV0Tko48+kvHjx4vZbJaxY8fKtm3b/MZVVZXVq1eL1WoVs9ksP/jBD+TYsWN+c65fvy4/+9nP5LbbbpPw8HCZPn26nD9/vjcPo1fk5uYKADl16lTAGHPyd+3aNVm6dKmMGDFCwsLCJCkpSV555RW/XxbM7Kbs7GxJSkqS0NBQsVqtsmTJEnE6ndq4nrM6ePCgAAho8+fPF5Huy6a6ulqeeeYZiYyMlMjISHnmmWekpqaml46y+3SU144dO4KOr169WluDefnyan7kW7B28OBBbQ295NVeVtevX5ef/OQnYrPZJDQ0VOLi4mTmzJlSXFzst4ZeshLp+GextWCFb2/lpYiIdP78MBERERHRwKSba3yJiIiISN9Y+BIRERGRLrDwJSIiIiJdYOFLRERERLrAwpeIiIiIdIGFLxERERHpAgtfIiIiItIFFr5EREREpAssfImIiIhIF1j4EhENEIcPH0ZISAimTp3q1//ll19CURStRUZGYty4cViyZAnOnDnjN3fNmjW49957A9Z2Op1QFAV///vfe/AIiIj6FgtfIqIB4t1338Xzzz+PgoICnD9/PmA8Pz8flZWVOHLkCF5//XWcPHkSycnJOHDgQB/sLRFR/2Ps6x0gIqKONTQ04MMPP0RJSQkcDgf+8Ic/4Ne//rXfnOjoaFitVgBAUlISZsyYgUceeQQLFy7Ev//9b4SEhPTFrhMR9Rs840tENABkZ2djzJgxGDNmDObNm4cdO3ZARNrdxmAwYOnSpTh37hxKS0t7aU+JiPovFr5ERANAVlYW5s2bBwCYOnUq6uvrO3UJw9ixYwH4rgMmItI7Fr5ERP3cqVOnUFxcjNmzZwMAjEYjnn76abz77rsdbtt8VlhRlB7dRyKigYDX+BIR9XNZWVnweDyIj4/X+kQEJpMJNTU17W578uRJAEBiYiIAICoqCrW1tQHznE4nAMBisXTTXhMR9T8840tE1I95PB689957ePPNN2G327V25MgRJCQk4IMPPmhzW1VV8dvf/haJiYlISUkB4Lv04eLFi3A4HH5zS0pKYDAYMHr06B49HiKivsQzvkRE/VhOTg5qamqwcOHCgLOxTz75JLKysjB9+nQAQHV1NRwOB1wuF44fP45NmzahuLgY+/bt057okJ6ejrvuuguzZ8/G2rVrYbPZcPToUbz00ktYvHgxIiMje/0YiYh6iyId3RZMRER9ZsaMGVBVFfv27QsYKysrQ2pqKkpLS5Gamqr1DxkyBAkJCXjooYewbNmygLO4DocDv/jFL/C3v/0NVVVVSEhIwNy5c7FixQqYzeYePyYior7CwpeIiIiIdIHX+BIRERGRLrDwJSIiIiJdYOFLRERERLrAwpeIiIiIdIGFLxERERHpAgtfIiIiItIFFr5EREREpAssfImIiIhIF1j4EhEREZEusPAlIiIiIl1g4UtEREREuvD/OSfpeqbG/RwAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_fitted_function(jungfrau_calibration.histogram_values, jungfrau_calibration.histogram_bin_edges, pixel_to_plot = pixel, function_parameters=jungfrau_calibration.fit_results[\"par\"][pixel[0],pixel[1],:], function=jungfrau_calibration.fitmodel, Count_range = (0,300))\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "632d3064", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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F0eJa0VE5oyBlIiITCq3oATaUh22Te+DQG9XeLg4wt/dWepqEZEZYyAlIqImEejtimB/hdTVICIL0OTLPhERERER1YaBlIiIiIgkxVv2RERktSpm+wPgWFYiM8ZASkREVsnQbP/4yBEMpURmiLfsiYjIKlWe7b9teh9oS3VibykRmRf2kBIRkVUL9HaVugpEVAf2kBIRERGRpBhIiYiIiEhSDKREREREJCkGUiIiIiKSFAMpEREREUmKgZSIiIiIJMVln4iIyCQqnop0K0sjdVXMog5EVH8MpERE1GiGnork4eLY7PXwcHGEs4McEYdUevXggvhE5o2BlIiIGq3yU5ECvV0le268v7sz4iNHVHt+PQMpkXljICUiIpMJ9HZFsL9C0jr4uzvzefVEFoaTmoiIiIhIUgykRERERCQpBlIiIiIikhQDKRERERFJioGUiIiIiCTFQEpEREREkmIgJSIiIiJJMZASERERkaQYSImIiIhIUgykRERERCQpBlIiIiIikhQDKRERERFJioGUiIiIiCTFQEpEREREkmIgJSIiIiJJMZASERERkaQYSImIiIhIUvZSV4CIiKi53MrSAAA8XBzh7+4scW2IqAIDKRERWT0PF0c4O8gRcUgFAHB2kCM+cgRDKZGZYCAlIiKr5+/ujPjIEcgtKMGtLA0iDqmQW1DCQEpkJhhIiYjIJvi7OzOAEpkpTmoiIiIiIkkxkBIRERGRpBhIiYiIiEhSDKREREREJClOaiIiogZLz9OKM9eJiBqKgZSIiBokPU+LMe+ehbZUB+DJ2p4eLo4S14qILBEDKRERNUhuQQm0pTpsm94Hgd6ufPoRETUYAykRETVKoLcrgv0VUleDiCwYJzURERERkaQYSImIiIhIUgykRERERCQpBlIiIiIikhQDKRERERFJioGUiIiIiCTFQEpEREREkmIgJSIiIiJJMZASERERkaQYSImIiIhIUgykRERERCQpBlIiIiIikhQDKRERERFJioGUiIiIiCTFQEpEREREkjI6kJ47dw6hoaFQKpWQyWQ4fvy43n5BELB+/XoolUo4Oztj5MiRuH79ul6Z4uJiLF26FF5eXnBxccHEiRNx7969Rl0IEREREVkmowNpQUEBevfujR07dhjcv2XLFrz33nvYsWMHrly5Al9fXzz33HN4/PixWCYiIgLHjh3DwYMH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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "variable_name_width = 0\n", + "variable_width = 15\n", + "decimal_places = 3\n", + "function_parameters = jungfrau_calibration.fit_results[\"par\"][pixel[0],pixel[1],:]\n", + "\n", + "variable_1 = r'$k_{\\alpha}\\_\\mu: \\quad$'\n", + "variable_2 = r'$\\sigma:\\quad$'\n", + "variable_3 = r'$k_{\\alpha}\\_N:\\quad$'\n", + "variable_4 = r'$C:\\quad$'\n", + "variable_5 = r'$k_{\\beta}\\_m:\\quad$'\n", + "variable_6 = r'$k_{\\beta}\\_f:\\quad$'\n", + "\n", + "fit_label = (\n", + " f\"{variable_1:<{variable_name_width}}{function_parameters[2]:.{decimal_places}f}\\n\"\n", + " f\"{variable_2:<{variable_name_width}}{function_parameters[3]:.{decimal_places}f}\\n\"\n", + " f\"{variable_3:<{variable_name_width}}{function_parameters[4]:.{decimal_places}f}\\n\"\n", + " f\"{variable_4:<{variable_name_width}}{function_parameters[5]:.{decimal_places}f}\\n\"\n", + " f\"{variable_5:<{variable_name_width}}{function_parameters[6]:.{decimal_places}f}\\n\"\n", + " f\"{variable_6:<{variable_name_width}}{function_parameters[7]:.{decimal_places}f}\"\n", + " )\n", + "\n", + "fit_label = f\"$\\begin{{aligned}}k_{{\\alpha,\\mu}} &= {function_parameters[2]:.3f} \\\\\\sigma &= {function_parameters[3]:.3f}\\end{{aligned}}$\"\n", + "\n", + "\n", + "fig, ax = plt.subplots(figsize = (8,5))\n", + "\n", + "ax.stairs(jungfrau_calibration.histogram_values[pixel[0],pixel[1],:],jungfrau_calibration.histogram_bin_edges, label = fit_label, zorder = 3)\n", + "ax.legend(prop={\"family\": \"monospace\", \"size\": 10}, loc= 'upper left')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32e72a2f", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/jungfrau.config b/python/jungfrau.config deleted file mode 100644 index e69de29..0000000 diff --git a/python/src/JungfrauCalibration.py b/python/src/JungfrauCalibration.py deleted file mode 100644 index a0ec3d3..0000000 --- a/python/src/JungfrauCalibration.py +++ /dev/null @@ -1,96 +0,0 @@ -from pathlib import Path -import JungfrauCalibrationParameters -from aare import JungfrauDataFile -from helpers import get_first_file -import numpy as np - -from aare.calibration import get_gain - - -class JungfrauCalibration: - - def __init__(self, calibration_params: JungfrauCalibrationParameters): - self.calibration_params = calibration_params - self.bad_channel_mask : np.ndarray - self.histogram : np.ndarray - - - # TODO: maybe pass num pedestals, pedestal file instead of calibration params? - def calculate_bad_pixels_mask(self) -> np.ndarray: - """ - Calculate the bad pixels mask for the Jungfrau detector. - - Returns: - np.ndarray: A boolean array where True indicates a bad pixel. - """ - if(self.calibration_params.num_pedestals_g0 is not None and self.calibration_params.num_pedestals_g1 is not None and self.calibration_params.num_pedestals_g2 is not None): - - jungfrau_file = JungfrauDataFile(get_first_file(self.calibration_params.pedestal_file_dir, self.calibration_params.pedestal_file_prefix)) - - g0_pedestal_frames = jungfrau_file.read_n(self.calibration_params.num_pedestals_g0) # TODO: option to only read gain? - mmh reading things twice from filesystem also bad - g1_pedestal_frames = jungfrau_file.read_n(self.calibration_params.num_pedestals_g1) - - g2_pedestal_frames = jungfrau_file.read_n(self.calibration_params.num_pedestals_g2) - - # get gain from each pixel - update mask - max_frames = max(self.calibration_params.num_pedestals_g0, self.calibration_params.num_pedestals_g1, self.calibration_params.num_pedestals_g2) - - bad_channel_mask = np.zeros((jungfrau_file.rows(), jungfrau_file.cols()), dtype=bool) # bad channels pixel mask - - # TODO loop to etensive - - return bad_channel_mask - - - def calculate_histogram(self): - """ - Calculate the histogram of each pixel. - - Returns: - np.ndarray: The histogram for each pixel value - """ - - - def fit_function(self): - """ - Fit a Gaussian to the histogram of each pixel. - - Returns: - np.ndarray: The fitted Gaussian parameters for each pixel. - """ - - def calibrate_G0(self): - """ - Calibrate the G0 gain of the Jungfrau detector. - - Returns: - np.ndarray: The calibrated G0 gain values for each pixel. - """ - - self.calculate_bad_pixels_mask() - self.calculate_histogram() - self.fit_function() - -## additional plot methods for visualizing the histogram and fitted Gaussian parameters can be added here - depens how fast not neccessary to compute on the fly - -def main(): - calibration_params = JungfrauCalibrationParameters() - - calibration_params.pedestal_file_dir = Path("/mnt/sls_det_storage/jungfrau_calib/data/Module_708_Calib") - - calibration_params.pedestal_file_prefix = "pedeG0_M708_2025-12-09_" - - calibration_params.num_pedestals_g0 = 1000 - calibration_params.num_pedestals_g1 = 1000 - calibration_params.num_pedestals_g2 = 1000 - - - - - - - - - - - diff --git a/python/src/JungfrauCalibrationParameters.py b/python/src/JungfrauCalibrationParameters.py deleted file mode 100644 index 5d1d120..0000000 --- a/python/src/JungfrauCalibrationParameters.py +++ /dev/null @@ -1,77 +0,0 @@ -from pathlib import Path - -class JungfrauCalibrationParameters: - """ - A class to hold calibration parameters for the Jungfrau detector. - """ - - @property - def pedestal_file_dir(self) -> Path: - return self._pedestal_file_dir - - @pedestal_file_dir.setter - def pedestal_file_dir(self, filepath : Path): - if not filepath.exists(): - raise ValueError(f"Pedestal file directory {filepath} does not exist.") - self._pedestal_file_dir = filepath - - @property - def pedestal_g0_file_prefix(self) -> str: - return self._pedestal_g0_file_prefix - - @pedestal_g0_file_prefix.setter - def pedestal_g0_file_prefix(self, file_prefix : str): - self._pedestal_g0_file_prefix = file_prefix - - # TODO: add deprecated decorator - @property - def pedestal_file_prefix(self) -> str: - return self._pedestal_file_prefix - @pedestal_file_prefix.setter - def pedestal_file_prefix(self, file_prefix : str): - self._pedestal_file_prefix = file_prefix - - @property - def num_pedestals_g0(self) -> int: - return self._num_pedestals_g0 - - @num_pedestals_g0.setter - def num_pedestals_g0(self, num_pedestals : int): - self._num_pedestals_g0 = num_pedestals - - @property - def num_pedestals_g1(self) -> int: - return self._num_pedestals_g1 - - @num_pedestals_g1.setter - def num_pedestals_g1(self, num_pedestals : int): - self._num_pedestals_g1 = num_pedestals - - @property - def num_pedestals_g2(self) -> int: - return self._num_pedestals_g2 - - @num_pedestals_g2.setter - def num_pedestals_g2(self, num_pedestals : int): - self._num_pedestals_g2 = num_pedestals - - @property - def raw_file_dir(self) -> Path: - return self._raw_file_dir - - @raw_file_dir.setter - def raw_file_dir(self, filepath : Path): - if not filepath.exists(): - raise ValueError(f"Raw file directory {filepath} does not exist.") - self._raw_file_dir = filepath - - @property - def raw_file_prefix(self) -> str: - return self._raw_file_prefix - - @raw_file_prefix.setter - def raw_file_prefix(self, file_prefix : str): - self._raw_file_prefix = file_prefix - - - # TODO add a read_config method \ No newline at end of file diff --git a/python/src/helpers.py b/python/src/helpers.py deleted file mode 100644 index 4326c1f..0000000 --- a/python/src/helpers.py +++ /dev/null @@ -1,11 +0,0 @@ -import glob -from pathlib import Path - -def get_first_file(path : Path, file_prefix : str): - """ - Get the first file with lowest index in directory that matches the given prefix. - """ - first_file = min(path.glob(str(Path)+f'{file_prefix}*', default=None)) - if first_file is None: - raise ValueError(f"No files found in {path} with prefix {file_prefix}") - return first_file \ No newline at end of file diff --git a/src/BadChannels.cpp b/src/BadChannels.cpp deleted file mode 100644 index d95c0b5..0000000 --- a/src/BadChannels.cpp +++ /dev/null @@ -1,51 +0,0 @@ - -#include "BadChannels.hpp" -#include "aare/calibration.hpp" - -using namespace aare; - -namespace jungfraucalibration -{ - - NDArray CreateBadChannelPixelMask(JungfrauDataFile &pedestal_file, const size_t num_pedestals_g0, const size_t num_pedestals_g1, const size_t num_pedestals_g2) - { - auto pedestals_g0 = pedestal_file.read_n(num_pedestals_g0); - auto pedestals_g1 = pedestal_file.read_n(num_pedestals_g1); - auto pedestals_g2 = pedestal_file.read_n(num_pedestals_g2); - - const size_t rows = pedestal_file.rows(); - const size_t cols = pedestal_file.cols(); - - // get gain from each pixel - update mask - NDArray bad_channel_mask({static_cast(rows), static_cast(cols)}, false); // bad channels pixel mask - - size_t max_frames = std::max({num_pedestals_g0, num_pedestals_g1, num_pedestals_g2}); - - // TODO is this more efficient e.g. all three frames fit into cache instead of doing one file at the time? - for (size_t frame_idx = 0; frame_idx < max_frames; ++frame_idx) - { - for (size_t row = 0; row < rows; ++row) - { - for (size_t col = 0; col < cols; ++col) - { - // TODO: nicer to access element from frame directly instead of view()? What is the type? - if (frame_idx < num_pedestals_g0 && get_gain(pedestals_g0[frame_idx].view()(row, col)) != 0) - { - bad_channel_mask(row, col) = true; - } - if (frame_idx < num_pedestals_g1 && get_gain(pedestals_g1[frame_idx].view()(row, col)) != 1) - { - bad_channel_mask(row, col) = true; - } - if (frame_idx < num_pedestals_g2 && get_gain(pedestals_g2[frame_idx].view()(row, col)) != 2) - { - bad_channel_mask(row, col) = true; - } - } - } - } - - return bad_channel_mask; - } - -} // namespace jungfraucalibration