diff --git a/fuse/context.py b/fuse/context.py index 0654aa96..b428d040 100644 --- a/fuse/context.py +++ b/fuse/context.py @@ -91,7 +91,7 @@ fuse.fastsim.MacroClusters, fuse.fastsim.S1Areas, fuse.fastsim.S2Areas, - fuse.fastsim.FastsimEventsUncorrected + fuse.fastsim.FastsimEventsUncorrected, ] @@ -244,8 +244,6 @@ def fastsim_context( "drift_time_gate": "electron_drift_time_gate", }, run_without_proper_corrections=False, - - ): """Function to create a fuse fastsim context.""" diff --git a/fuse/plugins/fastsim/fastsim_events_uncorrected.py b/fuse/plugins/fastsim/fastsim_events_uncorrected.py index 0226e0f4..3a7e6618 100644 --- a/fuse/plugins/fastsim/fastsim_events_uncorrected.py +++ b/fuse/plugins/fastsim/fastsim_events_uncorrected.py @@ -13,48 +13,53 @@ @export class FastsimEventsUncorrected(FuseBasePlugin): - """ - Plugin to simulate S1 and (alt) S2 areas from photon hits and electrons extracted + """Plugin to simulate S1 and (alt) S2 areas from photon hits and electrons + extracted.""" - """ __version__ = "0.0.1" depends_on = ("fastsim_macro_clusters",) provides = "fastsim_events_uncorrected" data_kind = "fastsim_events" dtype = [ - (("S1 area, uncorrected [PE]", "s1_area"), np.float32), - (("S2 area, uncorrected [PE]", "s2_area"), np.float32), - (("Alternate S2 area, uncorrected [PE]", "alt_s2_area"), np.float32), - (("Sum of S2 areas in event, uncorrected [PE]", "s2_sum"), np.float32), - (("Number of S2s in event", "multiplicity"), np.int32), - (("Drift time between main S1 and S2 [ns]", "drift_time"), np.float32), - (("Drift time using alternate S2 [ns]", "alt_s2_interaction_drift_time"), np.float32), - (("Main S2 reconstructed X position, uncorrected [cm]", "s2_x"), np.float32), - (("Main S2 reconstructed Y position, uncorrected [cm]", "s2_y"), np.float32), - (("Alternate S2 reconstructed X position, uncorrected [cm]", "alt_s2_x"), np.float32), - (("Alternate S2 reconstructed Y position, uncorrected [cm]", "alt_s2_y"), np.float32), - (("Main interaction r-position with observed position [cm]", "r_naive"), np.float32), - (("Alternate interaction r-position with observed position [cm]", "alt_s2_r_naive"), np.float32), - (("Main interaction z-position with observed position [cm]", "z_naive"), np.float32), - (("Alternate interaction z-position with observed position [cm]", "alt_s2_z_naive"), np.float32), - ] + strax.time_fields + (("S1 area, uncorrected [PE]", "s1_area"), np.float32), + (("S2 area, uncorrected [PE]", "s2_area"), np.float32), + (("Alternate S2 area, uncorrected [PE]", "alt_s2_area"), np.float32), + (("Sum of S2 areas in event, uncorrected [PE]", "s2_sum"), np.float32), + (("Number of S2s in event", "multiplicity"), np.int32), + (("Drift time between main S1 and S2 [ns]", "drift_time"), np.float32), + (("Drift time using alternate S2 [ns]", "alt_s2_interaction_drift_time"), np.float32), + (("Main S2 reconstructed X position, uncorrected [cm]", "s2_x"), np.float32), + (("Main S2 reconstructed Y position, uncorrected [cm]", "s2_y"), np.float32), + (("Alternate S2 reconstructed X position, uncorrected [cm]", "alt_s2_x"), np.float32), + (("Alternate S2 reconstructed Y position, uncorrected [cm]", "alt_s2_y"), np.float32), + (("Main interaction r-position with observed position [cm]", "r_naive"), np.float32), + ( + ("Alternate interaction r-position with observed position [cm]", "alt_s2_r_naive"), + np.float32, + ), + (("Main interaction z-position with observed position [cm]", "z_naive"), np.float32), + ( + ("Alternate interaction z-position with observed position [cm]", "alt_s2_z_naive"), + np.float32, + ), + ] + strax.time_fields save_when = strax.SaveWhen.TARGET photon_area_distribution = straxen.URLConfig( default="simple_load://resource://simulation_config://" - "SIMULATION_CONFIG_FILE.json?" - "&key=photon_area_distribution" - "&fmt=csv", + "SIMULATION_CONFIG_FILE.json?" + "&key=photon_area_distribution" + "&fmt=csv", cache=True, help="Photon area distribution", ) s2_secondary_sc_gain_mc = straxen.URLConfig( default="take://resource://" - "SIMULATION_CONFIG_FILE.json?&fmt=json" - "&take=s2_secondary_sc_gain", + "SIMULATION_CONFIG_FILE.json?&fmt=json" + "&take=s2_secondary_sc_gain", type=(int, float), cache=True, help="Secondary scintillation gain [PE/e-]", @@ -62,34 +67,34 @@ class FastsimEventsUncorrected(FuseBasePlugin): se_gain_from_map = straxen.URLConfig( default="take://resource://" - "SIMULATION_CONFIG_FILE.json?&fmt=json" - "&take=se_gain_from_map", + "SIMULATION_CONFIG_FILE.json?&fmt=json" + "&take=se_gain_from_map", cache=True, help="Boolean indication if the secondary scintillation gain is taken from a map", ) se_gain_map = straxen.URLConfig( default="itp_map://resource://simulation_config://" - "SIMULATION_CONFIG_FILE.json?" - "&key=se_gain_map" - "&fmt=json", + "SIMULATION_CONFIG_FILE.json?" + "&key=se_gain_map" + "&fmt=json", cache=True, help="Map of the single electron gain", ) s2_correction_map = straxen.URLConfig( default="itp_map://resource://simulation_config://" - "SIMULATION_CONFIG_FILE.json?" - "&key=s2_correction_map" - "&fmt=json", + "SIMULATION_CONFIG_FILE.json?" + "&key=s2_correction_map" + "&fmt=json", cache=True, help="S2 correction map", ) p_double_pe_emision = straxen.URLConfig( default="take://resource://" - "SIMULATION_CONFIG_FILE.json?&fmt=json" - "&take=p_double_pe_emision", + "SIMULATION_CONFIG_FILE.json?&fmt=json" + "&take=p_double_pe_emision", type=(int, float), cache=True, help="Probability of double photo-electron emission", @@ -98,33 +103,38 @@ class FastsimEventsUncorrected(FuseBasePlugin): @staticmethod def get_s1_area_with_spe(spe_distribution, num_photons): """ - :params: spe_distribution, the spe distribution to draw photon areas from - :params: num_photons, number of photons to draw from spe distribution + :params: spe_distribution, the spe distribution to draw photon areas from + :params: num_photons, number of photons to draw from spe distribution """ s1_area_spe = [] for n_ph in num_photons: - s1_area_spe.append(np.sum(spe_distribution[ - (np.random.random(n_ph) * len(spe_distribution)).astype(np.int64)])) + s1_area_spe.append( + np.sum( + spe_distribution[ + (np.random.random(n_ph) * len(spe_distribution)).astype(np.int64) + ] + ) + ) return np.array(s1_area_spe) def compute(self, fastsim_macro_clusters): - eventids = np.unique(fastsim_macro_clusters['eventid']) + eventids = np.unique(fastsim_macro_clusters["eventid"]) result = np.zeros(len(eventids), dtype=self.dtype) for i, eventid in enumerate(eventids): - these_clusters = fastsim_macro_clusters[fastsim_macro_clusters['eventid'] == eventid] + these_clusters = fastsim_macro_clusters[fastsim_macro_clusters["eventid"] == eventid] result[i]["time"] = these_clusters[0]["time"] result[i]["endtime"] = these_clusters[0]["endtime"] - photons = np.sum(these_clusters['n_s1_photon_hits']) + photons = np.sum(these_clusters["n_s1_photon_hits"]) result["s1_area"][i] = photons * 1.28 # TODO: replace 1.28 with correct spe value cluster_info = [] for cluster in these_clusters: pos = np.array([cluster["x"], cluster["y"]]).T # TODO: check if correct positions ly = self.get_s2_light_yield(pos)[0] - s2_area = ly * cluster['n_electron_extracted'] + s2_area = ly * cluster["n_electron_extracted"] if s2_area > 0: cluster_info.append((s2_area, cluster)) @@ -134,24 +144,26 @@ def compute(self, fastsim_macro_clusters): # Assign the highest and second-highest s2_area and drift time values if len(cluster_info_sorted) > 0: s2_areas = [info[0] for info in cluster_info_sorted] - result[i]['s2_sum'] = np.sum(s2_areas) - result[i]['s2_area'] = cluster_info_sorted[0][0] - result[i]['drift_time'] = cluster_info_sorted[0][1]['drift_time_mean'] - result[i]['s2_x'] = cluster_info_sorted[0][1]['x_obs'] - result[i]['s2_y'] = cluster_info_sorted[0][1]['y_obs'] - result[i]['z_naive'] = cluster_info_sorted[0][1]['z_obs'] + result[i]["s2_sum"] = np.sum(s2_areas) + result[i]["s2_area"] = cluster_info_sorted[0][0] + result[i]["drift_time"] = cluster_info_sorted[0][1]["drift_time_mean"] + result[i]["s2_x"] = cluster_info_sorted[0][1]["x_obs"] + result[i]["s2_y"] = cluster_info_sorted[0][1]["y_obs"] + result[i]["z_naive"] = cluster_info_sorted[0][1]["z_obs"] if len(cluster_info_sorted) > 1: - result[i]['alt_s2_area'] = cluster_info_sorted[1][0] - result[i]['alt_s2_interaction_drift_time'] = cluster_info_sorted[1][1]['drift_time_mean'] - result[i]['alt_s2_x'] = cluster_info_sorted[1][1]['x_obs'] - result[i]['alt_s2_y'] = cluster_info_sorted[1][1]['y_obs'] - result[i]['alt_s2_z_naive'] = cluster_info_sorted[1][1]['z_obs'] + result[i]["alt_s2_area"] = cluster_info_sorted[1][0] + result[i]["alt_s2_interaction_drift_time"] = cluster_info_sorted[1][1][ + "drift_time_mean" + ] + result[i]["alt_s2_x"] = cluster_info_sorted[1][1]["x_obs"] + result[i]["alt_s2_y"] = cluster_info_sorted[1][1]["y_obs"] + result[i]["alt_s2_z_naive"] = cluster_info_sorted[1][1]["z_obs"] result[i]["multiplicity"] = len(cluster_info_sorted) - - result['r_naive'] = np.sqrt(result['s2_x'] ** 2 + result['s2_y'] ** 2) - result['alt_s2_r_naive'] = np.sqrt(result['alt_s2_x'] ** 2 + result['alt_s2_y'] ** 2) + + result["r_naive"] = np.sqrt(result["s2_x"] ** 2 + result["s2_y"] ** 2) + result["alt_s2_r_naive"] = np.sqrt(result["alt_s2_x"] ** 2 + result["alt_s2_y"] ** 2) return result diff --git a/fuse/plugins/fastsim/fastsim_macro_clusters.py b/fuse/plugins/fastsim/fastsim_macro_clusters.py index 2ddc0549..01a185b8 100644 --- a/fuse/plugins/fastsim/fastsim_macro_clusters.py +++ b/fuse/plugins/fastsim/fastsim_macro_clusters.py @@ -34,12 +34,16 @@ def merge_clusters(cluster1, cluster2): @export class MacroClusters(FuseBasePlugin): - """Plugin to simulate macro clusters for fastsim + """Plugin to simulate macro clusters for fastsim.""" - """ __version__ = "0.0.1" - depends_on = ("drifted_electrons", "extracted_electrons", "microphysics_summary", "s1_photon_hits") + depends_on = ( + "drifted_electrons", + "extracted_electrons", + "microphysics_summary", + "s1_photon_hits", + ) provides = "fastsim_macro_clusters" data_kind = "fastsim_macro_clusters" @@ -49,33 +53,46 @@ def infer_dtype(self): def compute(self, interactions_in_roi): for ix1, _ in enumerate(interactions_in_roi): for ix2 in range(1, len(interactions_in_roi[ix1:])): - if interactions_in_roi[ix1]['eventid'] != interactions_in_roi[ix1 + ix2]['eventid']: + if interactions_in_roi[ix1]["eventid"] != interactions_in_roi[ix1 + ix2]["eventid"]: break if merge_clusters(interactions_in_roi[ix1], interactions_in_roi[ix1 + ix2]): - ne1 = interactions_in_roi[ix1]['n_electron_extracted'] - ne2 = interactions_in_roi[ix1 + ix2]['n_electron_extracted'] + ne1 = interactions_in_roi[ix1]["n_electron_extracted"] + ne2 = interactions_in_roi[ix1 + ix2]["n_electron_extracted"] ne_total = ne1 + ne2 - interactions_in_roi[ix1 + ix2]['n_electron_extracted'] = ne_total - interactions_in_roi[ix1]['n_electron_extracted'] = -1 # flag to throw this instruction away later - - for quantity in ['photons', 'electrons', 'excitons', 'ed', 'n_electron_interface', - 'n_s1_photon_hits']: - interactions_in_roi[ix1 + ix2][quantity] += interactions_in_roi[ix1][quantity] - - for quantity in ['drift_time_mean', 'drift_time_spread']: - interactions_in_roi[ix1 + ix2][quantity] += interactions_in_roi[ix1][quantity] + interactions_in_roi[ix1 + ix2]["n_electron_extracted"] = ne_total + interactions_in_roi[ix1][ + "n_electron_extracted" + ] = -1 # flag to throw this instruction away later + + for quantity in [ + "photons", + "electrons", + "excitons", + "ed", + "n_electron_interface", + "n_s1_photon_hits", + ]: + interactions_in_roi[ix1 + ix2][quantity] += interactions_in_roi[ix1][ + quantity + ] + + for quantity in ["drift_time_mean", "drift_time_spread"]: + interactions_in_roi[ix1 + ix2][quantity] += interactions_in_roi[ix1][ + quantity + ] interactions_in_roi[ix1 + ix2][quantity] /= 2 if ne_total > 0: - for coord in ['x', 'y', 'z']: - for obs in ['', '_obs']: - interactions_in_roi[ix1 + ix2][f'{coord}{obs}'] = \ - (interactions_in_roi[ix1][f'{coord}{obs}'] * ne1 + - interactions_in_roi[ix1 + ix2][f'{coord}{obs}'] * ne2) / ne_total + for coord in ["x", "y", "z"]: + for obs in ["", "_obs"]: + interactions_in_roi[ix1 + ix2][f"{coord}{obs}"] = ( + interactions_in_roi[ix1][f"{coord}{obs}"] * ne1 + + interactions_in_roi[ix1 + ix2][f"{coord}{obs}"] * ne2 + ) / ne_total - interactions_in_roi[ix1 + ix2]['x_pri'] = interactions_in_roi[ix1]['x_pri'] - interactions_in_roi[ix1 + ix2]['y_pri'] = interactions_in_roi[ix1]['y_pri'] - interactions_in_roi[ix1 + ix2]['z_pri'] = interactions_in_roi[ix1]['z_pri'] + interactions_in_roi[ix1 + ix2]["x_pri"] = interactions_in_roi[ix1]["x_pri"] + interactions_in_roi[ix1 + ix2]["y_pri"] = interactions_in_roi[ix1]["y_pri"] + interactions_in_roi[ix1 + ix2]["z_pri"] = interactions_in_roi[ix1]["z_pri"] break - return interactions_in_roi[interactions_in_roi['n_electron_extracted'] >= 0] + return interactions_in_roi[interactions_in_roi["n_electron_extracted"] >= 0] diff --git a/fuse/plugins/fastsim/fastsim_s1.py b/fuse/plugins/fastsim/fastsim_s1.py index 012a8c0a..d652d4e8 100644 --- a/fuse/plugins/fastsim/fastsim_s1.py +++ b/fuse/plugins/fastsim/fastsim_s1.py @@ -13,9 +13,8 @@ @export class S1Areas(FuseBasePlugin): - """Plugin to simulate macro clusters for fastsim + """Plugin to simulate macro clusters for fastsim.""" - """ __version__ = "0.0.1" depends_on = ("fastsim_macro_clusters",) @@ -27,9 +26,9 @@ class S1Areas(FuseBasePlugin): photon_area_distribution = straxen.URLConfig( default="simple_load://resource://simulation_config://" - "SIMULATION_CONFIG_FILE.json?" - "&key=photon_area_distribution" - "&fmt=csv", + "SIMULATION_CONFIG_FILE.json?" + "&key=photon_area_distribution" + "&fmt=csv", cache=True, help="Photon area distribution", ) @@ -37,22 +36,31 @@ class S1Areas(FuseBasePlugin): @staticmethod def get_s1_area_with_spe(spe_distribution, num_photons): """ - :params: spe_distribution, the spe distribution to draw photon areas from - :params: num_photons, number of photons to draw from spe distribution + :params: spe_distribution, the spe distribution to draw photon areas from + :params: num_photons, number of photons to draw from spe distribution """ s1_area_spe = [] for n_ph in num_photons: - s1_area_spe.append(np.sum(spe_distribution[ - (np.random.random(n_ph) * len(spe_distribution)).astype(np.int64)])) + s1_area_spe.append( + np.sum( + spe_distribution[ + (np.random.random(n_ph) * len(spe_distribution)).astype(np.int64) + ] + ) + ) return np.array(s1_area_spe) def compute(self, fastsim_macro_clusters): - eventids = np.unique(fastsim_macro_clusters['eventid']) + eventids = np.unique(fastsim_macro_clusters["eventid"]) result = np.zeros(len(eventids), dtype=self.dtype) result["time"] = fastsim_macro_clusters["time"] result["endtime"] = fastsim_macro_clusters["endtime"] for i, eventid in enumerate(eventids): - photons = np.sum(fastsim_macro_clusters[fastsim_macro_clusters['eventid'] == eventid]['n_s1_photon_hits']) + photons = np.sum( + fastsim_macro_clusters[fastsim_macro_clusters["eventid"] == eventid][ + "n_s1_photon_hits" + ] + ) result["s1_area"][i] = photons * 1.28 return result diff --git a/fuse/plugins/fastsim/fastsim_s2.py b/fuse/plugins/fastsim/fastsim_s2.py index ff374edb..740443f5 100644 --- a/fuse/plugins/fastsim/fastsim_s2.py +++ b/fuse/plugins/fastsim/fastsim_s2.py @@ -13,27 +13,27 @@ @export class S2Areas(FuseBasePlugin): - """Plugin to simulate S2 areas from electrons extracted for fastsim + """Plugin to simulate S2 areas from electrons extracted for fastsim.""" - """ __version__ = "0.0.1" depends_on = ("fastsim_macro_clusters",) provides = "fastsim_s2" data_kind = "fastsim_events" - dtype = [(("S2 area, uncorrected [PE]", "s2_area"), np.float32), - (("Alternate S2 area, uncorrected [PE]", "alt_s2_area"), np.float32), - (("Sum of S2 areas in event, uncorrected [PE]", "s2_sum"), np.float32), - (("Number of S2s in event", "multiplicity"), np.int32) - ] + strax.time_fields + dtype = [ + (("S2 area, uncorrected [PE]", "s2_area"), np.float32), + (("Alternate S2 area, uncorrected [PE]", "alt_s2_area"), np.float32), + (("Sum of S2 areas in event, uncorrected [PE]", "s2_sum"), np.float32), + (("Number of S2s in event", "multiplicity"), np.int32), + ] + strax.time_fields save_when = strax.SaveWhen.ALWAYS s2_secondary_sc_gain_mc = straxen.URLConfig( default="take://resource://" - "SIMULATION_CONFIG_FILE.json?&fmt=json" - "&take=s2_secondary_sc_gain", + "SIMULATION_CONFIG_FILE.json?&fmt=json" + "&take=s2_secondary_sc_gain", type=(int, float), cache=True, help="Secondary scintillation gain [PE/e-]", @@ -41,41 +41,41 @@ class S2Areas(FuseBasePlugin): se_gain_from_map = straxen.URLConfig( default="take://resource://" - "SIMULATION_CONFIG_FILE.json?&fmt=json" - "&take=se_gain_from_map", + "SIMULATION_CONFIG_FILE.json?&fmt=json" + "&take=se_gain_from_map", cache=True, help="Boolean indication if the secondary scintillation gain is taken from a map", ) se_gain_map = straxen.URLConfig( default="itp_map://resource://simulation_config://" - "SIMULATION_CONFIG_FILE.json?" - "&key=se_gain_map" - "&fmt=json", + "SIMULATION_CONFIG_FILE.json?" + "&key=se_gain_map" + "&fmt=json", cache=True, help="Map of the single electron gain", ) s2_correction_map = straxen.URLConfig( default="itp_map://resource://simulation_config://" - "SIMULATION_CONFIG_FILE.json?" - "&key=s2_correction_map" - "&fmt=json", + "SIMULATION_CONFIG_FILE.json?" + "&key=s2_correction_map" + "&fmt=json", cache=True, help="S2 correction map", ) p_double_pe_emision = straxen.URLConfig( default="take://resource://" - "SIMULATION_CONFIG_FILE.json?&fmt=json" - "&take=p_double_pe_emision", + "SIMULATION_CONFIG_FILE.json?&fmt=json" + "&take=p_double_pe_emision", type=(int, float), cache=True, help="Probability of double photo-electron emission", ) def compute(self, fastsim_macro_clusters): - eventids = np.unique(fastsim_macro_clusters['eventid']) + eventids = np.unique(fastsim_macro_clusters["eventid"]) result = np.zeros(len(eventids), dtype=self.dtype) result["time"] = fastsim_macro_clusters["time"] result["endtime"] = fastsim_macro_clusters["endtime"] @@ -85,7 +85,7 @@ def compute(self, fastsim_macro_clusters): for cluster in clusters: pos = np.array([cluster["x"], cluster["y"]]).T # TODO: check if correct positions ly = self.get_s2_light_yield(pos)[0] - area = ly * cluster['n_electron_extracted'] + area = ly * cluster["n_electron_extracted"] if area > 0: s2_areas.append(area) if len(s2_areas):