DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
tde_stream_db_gen.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2import argparse
3import os
4
5import pandas as pd
6import numpy as np
7import pathlib
8
9import conffwk
10
11from rich import print
12
13
14def get_includes() -> list[str]:
15 include_files = [
16 "schema/confmodel/dunedaq.schema.xml",
17 "schema/appmodel/application.schema.xml",
18 "schema/appmodel/fdmodules.schema.xml",
19 "schema/appmodel/tde.schema.xml",
20 ]
21 return include_files
22
23
24def get_mapping(det_name : str, base_sid : int) -> pd.DataFrame:
25 df = pd.read_csv(f"{os.environ['DBT_AREA_ROOT']}/sourcecode/tdemodules/config/mapping.txt", delim_whitespace = True, names = ["Crate", "AMC", "AMC_channel", "CRP", "view_type", "view_channel"])
26 if det_name == "tde-testcrate":
27 df = df[df["Crate"] == 0]
28 df = df[np.any([df["AMC"] == i for i in [1, 6, 7]], 0)]
29 # there may be less channels in the testcrate, but for now this is fine.
30
31 df["CRP"] += base_sid # This is needed to assign the source ID correctly for the TDE ()
32 return df
33
34
35def get_mapping_from_channel_map(channel_map : str):
36 df = pd.read_csv(channel_map, sep=r'\s+', names = ['offlchan', 'detid', 'detelement', 'crate', 'slot', 'stream', 'streamchan', 'plane', 'chan_in_plane', 'femb', 'asic ', 'asicchan'])
37
38 df23 = df[df['detelement'] < 4]
39
40 df_map = df23[['crate','slot', 'streamchan', 'detelement', 'plane', 'chan_in_plane']]
41 df_map.columns = ["Crate", "AMC", "AMC_channel", "CRP", "view_type", "view_channel"]
42 return df_map
43
44
45def create_db(oksfile : str, include_files : list[str]) -> conffwk.Configuration:
46 db = conffwk.Configuration("oksconflibs")
47 if not oksfile.endswith(".data.xml"):
48 oksfile = oksfile + ".data.xml"
49 print(f"Creating OKS database file {oksfile}")
50 db.create_db(oksfile, include_files)
51 db.set_active(oksfile)
52 return db
53
54
55def calculate_amc_net_info(crate, slot):
56 return {
57 "ip_1g" : f"10.73.{crate + 32}.{slot + 1}",
58 "ip_10g" : f"10.73.{crate + 32}.{slot + 13}",
59 "mac_1g" : "00:07:ED:A1:%02x:%02x" % (crate + 1, slot + 1),
60 "mac_10g" : "00:07:ED:A2:%02x:%02x" % (crate + 1, slot + 13),
61 }
62
63
64def create_det_connections(args : argparse.Namespace):
65 # key is crate number, so 10.73.(n+32).128, value is the number of AMCs each crate has installed.
66
67 if args.channel_map:
68 mapping = get_mapping_from_channel_map(args.channel_map)
69 else:
70 mapping = get_mapping(args.det_id, args.sid)
71 print(mapping)
72
73 db = create_db(f"crp23-det-senders", get_includes())
74
75 sid_counters = {i : i * 100 for i in pd.unique(mapping["CRP"])}
76 for e, cg in enumerate([[0, 1, 2, 6, 7], [3, 4, 5, 8, 9]]):
77 streams = []
78 resource = db.create_obj("ResourceSetAND", f"{args.det_name}-senders-crate-{'-'.join([str(c) for c in cg])}")
79 for crate in cg:
80 crate_map = mapping[mapping["Crate"] == crate]
81 amcs = pd.unique(crate_map["AMC"])
82 for amc in amcs:
83 name = f"crate{crate}-slot{amc}"
84 base_sid = pd.unique(crate_map[crate_map["AMC"] == amc]["CRP"])[0]
85 sid_counters[base_sid] += 1
86
87 amc_net_info = calculate_amc_net_info(crate, amc)
88 geo = db.create_obj(class_name = "GeoId", uid = f"geoId-{args.det_name}-amc-{sid_counters[base_sid]}")
89 geo["detector_id"] = args.det_id # channel map may be required for this ()
90 geo["crate_id"] = crate
91 geo["slot_id"] = amc
92
93 ds = db.create_obj(class_name = "DetectorStream", uid = f"DetStream-{sid_counters[base_sid]}")
94 ds["source_id"] = sid_counters[base_sid]
95 ds["geo_id"] = geo
96
97 nw_send = db.create_obj(class_name = "NetworkInterface", uid = f"nw-{args.det_name}-amc-{name}-10g")
98 nw_send["mac_address"] = amc_net_info["mac_10g"]
99 nw_send["ip_address"] = [amc_net_info["ip_10g"]]
100 nw_send["network_name"] = "Data"
101
102 nw_rec = db.create_obj(class_name = "NetworkInterface", uid = f"nw-{args.det_name}-amc-{name}-1g")
103 nw_rec["mac_address"] = amc_net_info["mac_1g"]
104 nw_rec["ip_address"] = [amc_net_info["ip_1g"]]
105 nw_rec["network_name"] = "Control"
106
107 sender_names = sid_counters[base_sid] if args.sid_suffix else name
108 dds = db.create_obj(class_name = "TdeAmcDetDataSender", uid = f"dds-{args.det_name}-amc-{sender_names}")
109 dds["port"] = 54321 + amc + 1
110 dds["control_host"] = f"np02-amc-{sid_counters[base_sid]}" # This should be the source ID
111 dds["contains"] = [ds] # This should be the DetStream object
112 dds["uses"] = nw_send
113 dds["control_endpoint"] = nw_rec
114 streams.append(dds)
115 resource["contains"] = streams
116 db.commit()
117 return
118
119
120if __name__ == "__main__":
121 parser = argparse.ArgumentParser("Generate configuration objects for TDE readout.")
122
123 parser.add_argument("-f", "--frontend", dest = "det_name", type = str, choices = ["tde", "tde-testcrate"], default = "tde", help = "frontend components to readout.")
124 parser.add_argument("-s", "--source-id", dest = "sid", type = int, default = 2, help = "base source ID number.")
125 parser.add_argument("-D", "--det_id", dest = "det_id", type = int, default = 11, help = "detector id.")
126 parser.add_argument("--sid_suffix", dest = "sid_suffix", action = "store_true", help = "use source ID as the suffix for the AMCDetDataSenders.")
127 parser.add_argument("-c", "--channel_map", dest = "channel_map", type = str, default = None, help = "ProtoDUNE channel map to infer the Crate/AMC mapping.")
128
129 args = parser.parse_args()
130 print(args)
131
get_mapping_from_channel_map(str channel_map)
calculate_amc_net_info(crate, slot)
pd.DataFrame get_mapping(str det_name, int base_sid)
conffwk.Configuration create_db(str oksfile, list[str] include_files)
create_det_connections(argparse.Namespace args)