From 02dcb6d4eeebc5952d31c5d0afd32e75a50cfaa6 Mon Sep 17 00:00:00 2001 From: Ava Date: Wed, 1 Apr 2026 16:46:52 +0200 Subject: [PATCH 1/2] Evaluate NMAHEPaM eventwise --- DORNparser_trig.py | 177 +++++++++++++++++++++++++++++++ DORNparser_trig2.py | 252 ++++++++++++++++++++++++++++++++++++++++++++ event_filters.py | 2 +- 3 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 DORNparser_trig.py create mode 100644 DORNparser_trig2.py diff --git a/DORNparser_trig.py b/DORNparser_trig.py new file mode 100644 index 0000000..ed83267 --- /dev/null +++ b/DORNparser_trig.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Aug 26 13:47:24 2025 + +@author: ava +Parse ED-data for DORN files, create histograms and optional calculations +Trigger-enabled event histograms added +Filename suffix via -nameadd +""" + +import numpy as np +import argparse +import fileinput +import sys +import pandas as pd +from pathlib import Path + +from DORNconfiguration import NMAHEPAM_channels, SETH_channels, AHEPAM_channels +from event_filters import prepare_trigger_indices, check_trigger + +# --------------------------- +# Argumente +# --------------------------- +parser = argparse.ArgumentParser(description="Parse ED-data for DORN files with triggers") +parser.add_argument("file", type=str) +parser.add_argument("-map", type=str, default="ALL", + choices=["ALL", "NMAHEPAM", "SETH", "AHEPAM"]) +parser.add_argument("-eventhist", action="store_true") +parser.add_argument("-trigger", nargs="+", default=None, + help="Trigger selection: e.g. B1, allB, allV, V1") +parser.add_argument("-time", type=int, default=200, help="Event time window threshold") +parser.add_argument("-nameadd", type=str, default="", help="Optional suffix for output filename") +args = parser.parse_args() + +file = args.file +if not Path(file).is_file(): + print("No valid file:", file) + sys.exit() + +filename = Path(file).stem +Path("hists").mkdir(parents=True, exist_ok=True) + +minX = -100 +maxX = 5000 +resX = 5.0 + + +##################################################################### +# Helper +##################################################################### + +def apply_calibration(raw_value, name, u_dict): + return raw_value * u_dict.get(name, 1.0) + + +##################################################################### +# Mapping +##################################################################### + +def Evaluate_mapping(mapping_name): + if mapping_name == "ALL": + columns = [f"0-{i}" for i in range(24)] + [f"1-{i}" for i in range(24)] + return columns, lambda ch, plane: ch + plane * 24, None, None + elif mapping_name == "NMAHEPAM": + channels = NMAHEPAM_channels() + elif mapping_name == "SETH": + channels = SETH_channels() + elif mapping_name == "AHEPAM": + channels = AHEPAM_channels() + else: + print("Unknown mapping") + sys.exit() + + valid_channels = [ch for ch in channels if ch["name"]] + columns = [ch["name"] for ch in valid_channels] + + def resolver(ch, sl): + hwc_index = ch + sl * 24 + for idx, ch_dict in enumerate(valid_channels): + if ch_dict["hwc"] == hwc_index: + return idx + return None + + return columns, resolver, valid_channels, None + + +##################################################################### +# Event Histogram (mit Trigger) +##################################################################### + +def create_event_histogram(columns, resolver, mapping_channels, time_threshold=200, triggers=None): + bins = int((maxX - minX) / resX) + hist = np.zeros((bins + 1, len(columns) + 1)) + hist[:, 0] = np.linspace(minX, maxX, bins + 1) + u_dict = {ch["name"]: ch["u"] for ch in (mapping_channels or [])} + + trigchans = None + if triggers: + from event_filters import NMAHEPAM_triggers + trigchans = prepare_trigger_indices(triggers, columns, NMAHEPAM_triggers) + + current_event = [] + event_start = None + + with open(file, "r", encoding="utf-8", errors="ignore") as f: + for line in f: + if not line.startswith("ED"): + continue + parts = line.split() + try: + time = int(float(parts[1])) + sli = int(parts[2]) + cha = int(parts[3]) + raw = float(parts[-1]) / 0x20000 + except: + continue + idx = resolver(cha, sli) + if idx is None: + continue + name = columns[idx] + val = apply_calibration(raw, name, u_dict) + if event_start is None: + event_start = time + if abs(time - event_start) > time_threshold: + event_dict = {n: v for n, v in current_event} + if (trigchans is None) or check_trigger(event_dict, columns, trigchans, + {ch["name"]: ch["thr"] for ch in (mapping_channels or [])}): + fill_event(hist, current_event, columns) + current_event = [] + event_start = time + current_event.append((name, val)) + if current_event: + event_dict = {n: v for n, v in current_event} + if (trigchans is None) or check_trigger(event_dict, columns, trigchans, + {ch["name"]: ch["thr"] for ch in (mapping_channels or [])}): + fill_event(hist, current_event, columns) + return hist + + +def fill_event(hist, event, columns): + for name, val in event: + if val is None: + continue + if minX <= val <= maxX: + x = int((val - minX) / resX) + hist[x, columns.index(name) + 1] += 1 + + +##################################################################### +# Save +##################################################################### + +def save_hist(hist, columns, suffix): + add = f"_{args.nameadd}" if args.nameadd else "" + df = pd.DataFrame(hist, columns=["value"] + columns) + fname = f"hists/{filename}{add}.{suffix}" + df.to_csv(fname, sep=" ", index=False) + print(fname, "created") + + +##################################################################### +# MAIN +##################################################################### + +def main(): + columns, resolver, channels, _ = Evaluate_mapping(args.map) + + if args.eventhist: + hist = create_event_histogram(columns, resolver, channels, + time_threshold=args.time, + triggers=args.trigger) + save_hist(hist, columns, "eventhist") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/DORNparser_trig2.py b/DORNparser_trig2.py new file mode 100644 index 0000000..829cf14 --- /dev/null +++ b/DORNparser_trig2.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Aug 26 13:47:24 2025 + +@author: ava +Parse ED-data for DORN files, create histograms and optional calculations +Trigger-enabled event histograms added +Filename suffix via -nameadd +""" + +import numpy as np +import argparse +import sys +import pandas as pd +from pathlib import Path + +from DORNconfiguration import NMAHEPAM_channels, SETH_channels, AHEPAM_channels +from event_filters import prepare_trigger_indices, check_trigger + +# --------------------------- +# Argumente +# --------------------------- +parser = argparse.ArgumentParser(description="Parse ED-data for DORN files with triggers") +parser.add_argument("file", type=str) +parser.add_argument("-map", type=str, default="ALL", + choices=["ALL", "NMAHEPAM", "SETH", "AHEPAM"]) +parser.add_argument("-eventhist", action="store_true") +parser.add_argument("-Bhist", action="store_true", help="Histogram for B-channels + sum") +parser.add_argument("-trigger", nargs="+", default=None, + help="Trigger selection: e.g. B1, allB, allV, V1") +parser.add_argument("-time", type=int, default=200, help="Event time window threshold") +parser.add_argument("-nameadd", type=str, default="", help="Optional suffix for output filename") +args = parser.parse_args() + +file = args.file +if not Path(file).is_file(): + print("No valid file:", file) + sys.exit() + +filename = Path(file).stem +Path("hists").mkdir(parents=True, exist_ok=True) + +# --------------------------- +# Eventhist default +# --------------------------- +minX_event = -100 +maxX_event = 5000 +resX_event = 5.0 + +# --------------------------- +# B-Histogramm Parameter +# --------------------------- +minX_B = -5 +maxX_B = 300 +resX_B = 0.838214 / 2 + +# --------------------------- +# Helper +# --------------------------- +def apply_calibration(raw_value, name, u_dict): + return raw_value * u_dict.get(name, 1.0) + + +# --------------------------- +# Mapping +# --------------------------- +def Evaluate_mapping(mapping_name): + if mapping_name == "ALL": + columns = [f"0-{i}" for i in range(24)] + [f"1-{i}" for i in range(24)] + return columns, lambda ch, plane: ch + plane * 24, None, None + elif mapping_name == "NMAHEPAM": + channels = NMAHEPAM_channels() + elif mapping_name == "SETH": + channels = SETH_channels() + elif mapping_name == "AHEPAM": + channels = AHEPAM_channels() + else: + print("Unknown mapping") + sys.exit() + + valid_channels = [ch for ch in channels if ch["name"]] + columns = [ch["name"] for ch in valid_channels] + + def resolver(ch, sl): + hwc_index = ch + sl * 24 + for idx, ch_dict in enumerate(valid_channels): + if ch_dict["hwc"] == hwc_index: + return idx + return None + + return columns, resolver, valid_channels, None + + +# --------------------------- +# Generic Event Histogram +# --------------------------- +def create_event_histogram(columns, resolver, mapping_channels, time_threshold=200, triggers=None, + minX=minX_event, maxX=maxX_event, resX=resX_event, B_only=False): + """ + Generic event histogram. + If B_only=True, only B-channels (B1..B6) + sum are stored. + """ + if B_only: + channels_to_use = ["B1","B2","B3","B4","B5","B6"] + n_cols = len(channels_to_use) + 1 # +1 for sum + bins = int((maxX_B - minX_B) / resX_B) + hist = np.zeros((bins+1, n_cols + 1)) # value + B1..B6 + Sum + hist[:,0] = np.linspace(minX_B, maxX_B, bins+1) + u_dict = {ch["name"]: ch["u"] for ch in (mapping_channels or [])} + thr_dict = {ch["name"]: ch["thr"] for ch in (mapping_channels or [])} + else: + bins = int((maxX - minX) / resX) + hist = np.zeros((bins+1, len(columns)+1)) + hist[:,0] = np.linspace(minX, maxX, bins+1) + u_dict = {ch["name"]: ch["u"] for ch in (mapping_channels or [])} + channels_to_use = columns + thr_dict = {ch["name"]: ch["thr"] for ch in (mapping_channels or [])} + + # Trigger vorbereiten + trigchans = None + if triggers: + from event_filters import NMAHEPAM_triggers + trigchans = prepare_trigger_indices(triggers, columns_to_use:=columns if not B_only else channels_to_use, + NMAHEPAM_triggers) + + current_event = [] + event_start = None + + with open(file, "r", encoding="utf-8", errors="ignore") as f: + for line in f: + if not line.startswith("ED"): + continue + parts = line.split() + try: + time = int(float(parts[1])) + sli = int(parts[2]) + cha = int(parts[3]) + raw = float(parts[-1]) / 0x20000 + except: + continue + # Resolver + idx = None + if not B_only: + idx = resolver(cha, sli) + if idx is None: + continue + name = columns[idx] + else: + # B_only: prüfen, ob B-Kanal + for ch in mapping_channels: + if ch["hwc"] == cha + sli*24 and ch["name"] in channels_to_use: + name = ch["name"] + break + else: + continue + val = apply_calibration(raw, name, u_dict) + + if event_start is None: + event_start = time + + if abs(time - event_start) > time_threshold: + # Event abgeschlossen + event_dict = {n:v for n,v in current_event} + if (trigchans is None) or check_trigger(event_dict, columns_to_use, trigchans, thr_dict): + # fill + if B_only: + fill_B_event(hist, event_dict, channels_to_use, minX_B, maxX_B, resX_B) + else: + fill_event(hist, current_event, columns, minX, maxX, resX) + current_event = [] + event_start = time + current_event.append((name, val)) + + if current_event: + event_dict = {n:v for n,v in current_event} + if (trigchans is None) or check_trigger(event_dict, columns_to_use, trigchans, thr_dict): + if B_only: + fill_B_event(hist, event_dict, channels_to_use, minX_B, maxX_B, resX_B) + else: + fill_event(hist, current_event, columns, minX, maxX, resX) + + return hist + + +# --------------------------- +# Fill functions +# --------------------------- +def fill_event(hist, event, columns, minX, maxX, resX): + for name, val in event: + if val is None: + continue + if minX <= val <= maxX: + x = int((val - minX) / resX) + hist[x, columns.index(name)+1] += 1 + + +def fill_B_event(hist, event_dict, B_channels, minX, maxX, resX): + # Jeden B-Kanal + for i, b in enumerate(B_channels): + val = event_dict.get(b, 0) + if minX <= val <= maxX: + x = int((val - minX) / resX) + hist[x, i+1] += 1 + # Summe aller B-Kanäle pro Event + sum_val = sum(event_dict.get(b, 0) for b in B_channels) + if minX <= sum_val <= maxX: + x = int((sum_val - minX) / resX) + hist[x, -1] += 1 + + +# --------------------------- +# Save +# --------------------------- +def save_hist(hist, columns, suffix): + add = f"_{args.nameadd}" if args.nameadd else "" + df = pd.DataFrame(hist, columns=["value"] + columns) + fname = f"hists/{filename}{add}.{suffix}" + df.to_csv(fname, sep=" ", index=False) + print(fname, "created") + + +def save_B_hist(hist, B_channels, suffix): + add = f"_{args.nameadd}" if args.nameadd else "" + df = pd.DataFrame(hist, columns=["value"] + B_channels + ["Sum"]) + fname = f"hists/{filename}{add}.{suffix}" + df.to_csv(fname, sep=" ", index=False) + print(fname, "created") + + +# --------------------------- +# MAIN +# --------------------------- +def main(): + columns, resolver, channels, _ = Evaluate_mapping(args.map) + + if args.eventhist: + hist = create_event_histogram(columns, resolver, channels, + time_threshold=args.time, + triggers=args.trigger) + save_hist(hist, columns, "eventhist") + + if args.Bhist: + hist = create_event_histogram(columns, resolver, channels, + time_threshold=args.time, + triggers=args.trigger, + B_only=True) + save_B_hist(hist, ["B1","B2","B3","B4","B5","B6"], "Bhist") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/event_filters.py b/event_filters.py index 8aef489..c667508 100644 --- a/event_filters.py +++ b/event_filters.py @@ -79,7 +79,7 @@ def prepare_trigger_indices(trig_args, columns, triggers_dict=None): # prod ist Tupel von AND-Gruppen → kombinieren für ein großes AND combined = [i for group in prod for i in group] combined_groups.append(combined) - print(combined_groups) + #print(combined_groups) return combined_groups def check_trigger(event_dict, columns, trigchans, thr_dict): From 3f520cdf098a0aea5ee1ce52d9eab2091e2e9461 Mon Sep 17 00:00:00 2001 From: Ava Date: Tue, 14 Apr 2026 13:27:27 +0200 Subject: [PATCH 2/2] implement vertical triggers for all 17 triggerpositions to do overview-plot --- DORNparser_trig.py | 171 +++++++++++++++++++++++++------------------- DORNparser_trig2.py | 77 +++++++------------- 2 files changed, 125 insertions(+), 123 deletions(-) diff --git a/DORNparser_trig.py b/DORNparser_trig.py index ed83267..8d94b2d 100644 --- a/DORNparser_trig.py +++ b/DORNparser_trig.py @@ -1,17 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" -Created on Tue Aug 26 13:47:24 2025 - -@author: ava -Parse ED-data for DORN files, create histograms and optional calculations -Trigger-enabled event histograms added -Filename suffix via -nameadd -""" import numpy as np import argparse -import fileinput import sys import pandas as pd from pathlib import Path @@ -27,10 +18,10 @@ parser.add_argument("file", type=str) parser.add_argument("-map", type=str, default="ALL", choices=["ALL", "NMAHEPAM", "SETH", "AHEPAM"]) parser.add_argument("-eventhist", action="store_true") -parser.add_argument("-trigger", nargs="+", default=None, - help="Trigger selection: e.g. B1, allB, allV, V1") -parser.add_argument("-time", type=int, default=200, help="Event time window threshold") -parser.add_argument("-nameadd", type=str, default="", help="Optional suffix for output filename") +parser.add_argument("-Bhist", action="store_true") +parser.add_argument("-trigger", nargs="+", default=None) +parser.add_argument("-time", type=int, default=200) +parser.add_argument("-nameadd", type=str, default="") args = parser.parse_args() file = args.file @@ -41,60 +32,65 @@ if not Path(file).is_file(): filename = Path(file).stem Path("hists").mkdir(parents=True, exist_ok=True) -minX = -100 -maxX = 5000 -resX = 5.0 - - -##################################################################### -# Helper -##################################################################### - -def apply_calibration(raw_value, name, u_dict): - return raw_value * u_dict.get(name, 1.0) - - -##################################################################### -# Mapping -##################################################################### +# --------------------------- +# Parameter +# --------------------------- +minX_event, maxX_event, resX_event = -100, 5000, 0.838214 * 4 +minX_B, maxX_B, resX_B = -5, 300, 0.838214 / 2 +# --------------------------- +# Mapping (OPTIMIERT) +# --------------------------- def Evaluate_mapping(mapping_name): if mapping_name == "ALL": columns = [f"0-{i}" for i in range(24)] + [f"1-{i}" for i in range(24)] - return columns, lambda ch, plane: ch + plane * 24, None, None - elif mapping_name == "NMAHEPAM": + resolver_dict = {i: i for i in range(len(columns))} + return columns, lambda ch, sl: ch + sl*24, None, resolver_dict + + if mapping_name == "NMAHEPAM": channels = NMAHEPAM_channels() elif mapping_name == "SETH": channels = SETH_channels() elif mapping_name == "AHEPAM": channels = AHEPAM_channels() else: - print("Unknown mapping") - sys.exit() + sys.exit("Unknown mapping") - valid_channels = [ch for ch in channels if ch["name"]] - columns = [ch["name"] for ch in valid_channels] + valid = [ch for ch in channels if ch["name"]] + columns = [ch["name"] for ch in valid] + + # schneller Resolver + hwc_to_idx = {ch["hwc"]: i for i, ch in enumerate(valid)} def resolver(ch, sl): - hwc_index = ch + sl * 24 - for idx, ch_dict in enumerate(valid_channels): - if ch_dict["hwc"] == hwc_index: - return idx - return None + return hwc_to_idx.get(ch + sl*24) - return columns, resolver, valid_channels, None + return columns, resolver, valid, hwc_to_idx +# --------------------------- +# Histogram +# --------------------------- +def create_event_histogram(columns, resolver, mapping_channels, time_threshold=200, + triggers=None, B_only=False): -##################################################################### -# Event Histogram (mit Trigger) -##################################################################### + # index map statt .index() + col_index = {name: i for i, name in enumerate(columns)} + + if B_only: + B_channels = ["B1","B2","B3","B4","B5","B6"] + B_index = {b: i for i, b in enumerate(B_channels)} + + bins = int((maxX_B - minX_B) / resX_B) + hist = np.zeros((bins+1, len(B_channels)+2)) + hist[:,0] = np.linspace(minX_B, maxX_B, bins+1) + else: + bins = int((maxX_event - minX_event) / resX_event) + hist = np.zeros((bins+1, len(columns)+1)) + hist[:,0] = np.linspace(minX_event, maxX_event, bins+1) -def create_event_histogram(columns, resolver, mapping_channels, time_threshold=200, triggers=None): - bins = int((maxX - minX) / resX) - hist = np.zeros((bins + 1, len(columns) + 1)) - hist[:, 0] = np.linspace(minX, maxX, bins + 1) u_dict = {ch["name"]: ch["u"] for ch in (mapping_channels or [])} - + thr_dict = {ch["name"]: ch["thr"] for ch in (mapping_channels or [])} + trigchans = None if triggers: from event_filters import NMAHEPAM_triggers @@ -107,6 +103,7 @@ def create_event_histogram(columns, resolver, mapping_channels, time_threshold=2 for line in f: if not line.startswith("ED"): continue + parts = line.split() try: time = int(float(parts[1])) @@ -115,42 +112,68 @@ def create_event_histogram(columns, resolver, mapping_channels, time_threshold=2 raw = float(parts[-1]) / 0x20000 except: continue + idx = resolver(cha, sli) if idx is None: continue + name = columns[idx] - val = apply_calibration(raw, name, u_dict) + val = raw * u_dict.get(name, 1.0) + if event_start is None: event_start = time + if abs(time - event_start) > time_threshold: - event_dict = {n: v for n, v in current_event} - if (trigchans is None) or check_trigger(event_dict, columns, trigchans, - {ch["name"]: ch["thr"] for ch in (mapping_channels or [])}): - fill_event(hist, current_event, columns) + process_event(current_event, hist, B_only, trigchans, + columns, thr_dict, + col_index, B_index if B_only else None) + current_event = [] event_start = time + current_event.append((name, val)) + if current_event: - event_dict = {n: v for n, v in current_event} - if (trigchans is None) or check_trigger(event_dict, columns, trigchans, - {ch["name"]: ch["thr"] for ch in (mapping_channels or [])}): - fill_event(hist, current_event, columns) + process_event(current_event, hist, B_only, trigchans, + columns, thr_dict, + col_index, B_index if B_only else None) + return hist +# --------------------------- +# Event Processing (neu) +# --------------------------- +def process_event(event, hist, B_only, trigchans, columns, thr_dict, + col_index, B_index): -def fill_event(hist, event, columns): - for name, val in event: - if val is None: - continue - if minX <= val <= maxX: - x = int((val - minX) / resX) - hist[x, columns.index(name) + 1] += 1 + event_dict = dict(event) + if (trigchans is not None) and not check_trigger(event_dict, columns, trigchans, thr_dict): + return -##################################################################### + if B_only: + # B-Channels + Sum + sum_val = 0 + for b, i in B_index.items(): + val = event_dict.get(b, 0) + sum_val += val + if minX_B <= val <= maxX_B: + x = int((val - minX_B) / resX_B) + hist[x, i+1] += 1 + + if minX_B <= sum_val <= maxX_B: + x = int((sum_val - minX_B) / resX_B) + hist[x, -1] += 1 + + else: + for name, val in event: + if minX_event <= val <= maxX_event: + x = int((val - minX_event) / resX_event) + hist[x, col_index[name]+1] += 1 + +# --------------------------- # Save -##################################################################### - +# --------------------------- def save_hist(hist, columns, suffix): add = f"_{args.nameadd}" if args.nameadd else "" df = pd.DataFrame(hist, columns=["value"] + columns) @@ -158,11 +181,9 @@ def save_hist(hist, columns, suffix): df.to_csv(fname, sep=" ", index=False) print(fname, "created") - -##################################################################### +# --------------------------- # MAIN -##################################################################### - +# --------------------------- def main(): columns, resolver, channels, _ = Evaluate_mapping(args.map) @@ -172,6 +193,12 @@ def main(): triggers=args.trigger) save_hist(hist, columns, "eventhist") + if args.Bhist: + hist = create_event_histogram(columns, resolver, channels, + time_threshold=args.time, + triggers=args.trigger, + B_only=True) + save_hist(hist, ["B1","B2","B3","B4","B5","B6","SUM"], "Bhist") if __name__ == "__main__": main() \ No newline at end of file diff --git a/DORNparser_trig2.py b/DORNparser_trig2.py index 829cf14..b0dc1a7 100644 --- a/DORNparser_trig2.py +++ b/DORNparser_trig2.py @@ -46,7 +46,7 @@ Path("hists").mkdir(parents=True, exist_ok=True) # --------------------------- minX_event = -100 maxX_event = 5000 -resX_event = 5.0 +resX_event = 0.838214 * 3 # --------------------------- # B-Histogramm Parameter @@ -61,7 +61,6 @@ resX_B = 0.838214 / 2 def apply_calibration(raw_value, name, u_dict): return raw_value * u_dict.get(name, 1.0) - # --------------------------- # Mapping # --------------------------- @@ -91,38 +90,32 @@ def Evaluate_mapping(mapping_name): return columns, resolver, valid_channels, None - # --------------------------- # Generic Event Histogram # --------------------------- def create_event_histogram(columns, resolver, mapping_channels, time_threshold=200, triggers=None, minX=minX_event, maxX=maxX_event, resX=resX_event, B_only=False): - """ - Generic event histogram. - If B_only=True, only B-channels (B1..B6) + sum are stored. - """ + if B_only: channels_to_use = ["B1","B2","B3","B4","B5","B6"] - n_cols = len(channels_to_use) + 1 # +1 for sum + n_cols = len(channels_to_use) + 1 bins = int((maxX_B - minX_B) / resX_B) - hist = np.zeros((bins+1, n_cols + 1)) # value + B1..B6 + Sum + hist = np.zeros((bins+1, n_cols + 1)) hist[:,0] = np.linspace(minX_B, maxX_B, bins+1) - u_dict = {ch["name"]: ch["u"] for ch in (mapping_channels or [])} - thr_dict = {ch["name"]: ch["thr"] for ch in (mapping_channels or [])} else: bins = int((maxX - minX) / resX) hist = np.zeros((bins+1, len(columns)+1)) hist[:,0] = np.linspace(minX, maxX, bins+1) - u_dict = {ch["name"]: ch["u"] for ch in (mapping_channels or [])} channels_to_use = columns - thr_dict = {ch["name"]: ch["thr"] for ch in (mapping_channels or [])} - # Trigger vorbereiten + u_dict = {ch["name"]: ch["u"] for ch in (mapping_channels or [])} + thr_dict = {ch["name"]: ch["thr"] for ch in (mapping_channels or [])} + + # Trigger vorbereiten (IMMER mit allen Kanälen!) trigchans = None if triggers: from event_filters import NMAHEPAM_triggers - trigchans = prepare_trigger_indices(triggers, columns_to_use:=columns if not B_only else channels_to_use, - NMAHEPAM_triggers) + trigchans = prepare_trigger_indices(triggers, columns, NMAHEPAM_triggers) current_event = [] event_start = None @@ -131,6 +124,7 @@ def create_event_histogram(columns, resolver, mapping_channels, time_threshold=2 for line in f: if not line.startswith("ED"): continue + parts = line.split() try: time = int(float(parts[1])) @@ -139,42 +133,37 @@ def create_event_histogram(columns, resolver, mapping_channels, time_threshold=2 raw = float(parts[-1]) / 0x20000 except: continue - # Resolver - idx = None - if not B_only: - idx = resolver(cha, sli) - if idx is None: - continue - name = columns[idx] - else: - # B_only: prüfen, ob B-Kanal - for ch in mapping_channels: - if ch["hwc"] == cha + sli*24 and ch["name"] in channels_to_use: - name = ch["name"] - break - else: - continue + + # 🔧 FIX: IMMER alle Kanäle auflösen + idx = resolver(cha, sli) + if idx is None: + continue + + name = columns[idx] val = apply_calibration(raw, name, u_dict) if event_start is None: event_start = time if abs(time - event_start) > time_threshold: - # Event abgeschlossen event_dict = {n:v for n,v in current_event} - if (trigchans is None) or check_trigger(event_dict, columns_to_use, trigchans, thr_dict): - # fill + + if (trigchans is None) or check_trigger(event_dict, columns, trigchans, thr_dict): if B_only: fill_B_event(hist, event_dict, channels_to_use, minX_B, maxX_B, resX_B) else: fill_event(hist, current_event, columns, minX, maxX, resX) + current_event = [] event_start = time + current_event.append((name, val)) + # letztes Event if current_event: event_dict = {n:v for n,v in current_event} - if (trigchans is None) or check_trigger(event_dict, columns_to_use, trigchans, thr_dict): + + if (trigchans is None) or check_trigger(event_dict, columns, trigchans, thr_dict): if B_only: fill_B_event(hist, event_dict, channels_to_use, minX_B, maxX_B, resX_B) else: @@ -182,7 +171,6 @@ def create_event_histogram(columns, resolver, mapping_channels, time_threshold=2 return hist - # --------------------------- # Fill functions # --------------------------- @@ -194,21 +182,18 @@ def fill_event(hist, event, columns, minX, maxX, resX): x = int((val - minX) / resX) hist[x, columns.index(name)+1] += 1 - def fill_B_event(hist, event_dict, B_channels, minX, maxX, resX): - # Jeden B-Kanal for i, b in enumerate(B_channels): val = event_dict.get(b, 0) if minX <= val <= maxX: x = int((val - minX) / resX) hist[x, i+1] += 1 - # Summe aller B-Kanäle pro Event + sum_val = sum(event_dict.get(b, 0) for b in B_channels) if minX <= sum_val <= maxX: x = int((sum_val - minX) / resX) hist[x, -1] += 1 - # --------------------------- # Save # --------------------------- @@ -219,15 +204,6 @@ def save_hist(hist, columns, suffix): df.to_csv(fname, sep=" ", index=False) print(fname, "created") - -def save_B_hist(hist, B_channels, suffix): - add = f"_{args.nameadd}" if args.nameadd else "" - df = pd.DataFrame(hist, columns=["value"] + B_channels + ["Sum"]) - fname = f"hists/{filename}{add}.{suffix}" - df.to_csv(fname, sep=" ", index=False) - print(fname, "created") - - # --------------------------- # MAIN # --------------------------- @@ -245,8 +221,7 @@ def main(): time_threshold=args.time, triggers=args.trigger, B_only=True) - save_B_hist(hist, ["B1","B2","B3","B4","B5","B6"], "Bhist") - + save_hist(hist, ["B1","B2","B3","B4","B5","B6","SUM"], "Bhist") if __name__ == "__main__": main() \ No newline at end of file