3 This module provides connectivity information about DUNE APAs 4 (protoDUNE or nominal DUNE FD design, and not 35t prototype) 6 See the Plex class for a convenient one-stop user shop. 9 from wirecell
import units
12 from collections
import namedtuple, Counter, defaultdict
29 chip_channel_layer_spot_matrix = numpy.array([
30 [(
'u', 19), ('u', 17), ('u', 15), ('u', 13), ('u', 11), ('v', 19),
31 (
'v', 17), (
'v', 15), (
'v', 13), (
'v', 11), (
'w', 23), (
'w', 21),
32 (
'w', 19), (
'w', 17), (
'w', 15), (
'w', 13)],
33 [(
'u', 9), ('u', 7), ('u', 5), ('u', 3), ('u', 1), ('v', 9),
34 (
'v', 7), (
'v', 5), (
'v', 3), (
'v', 1), (
'w', 11), (
'w', 9),
35 (
'w', 7), (
'w', 5), (
'w', 3), (
'w', 1)],
36 [(
'w', 14), (
'w', 16), (
'w', 18), (
'w', 20), (
'w', 22), (
'w', 24),
37 (
'v', 12), (
'v', 14), (
'v', 16), (
'v', 18), (
'v', 20), (
'u', 12), 38 ('u', 14), ('u', 16), ('u', 18), ('u', 20)], 39 [('w', 2), (
'w', 4), (
'w', 6), (
'w', 8), (
'w', 10), (
'w', 12),
40 (
'v', 2), (
'v', 4), (
'v', 6), (
'v', 8), (
'v', 10), (
'u', 2), 41 ('u', 4), ('u', 6), ('u', 8), ('u', 10)], 42 [('u', 29), ('u', 27), ('u', 25), ('u', 23), ('u', 21), ('v', 29),
43 (
'v', 27), (
'v', 25), (
'v', 23), (
'v', 21), (
'w', 35), (
'w', 33),
44 (
'w', 31), (
'w', 29), (
'w', 27), (
'w', 25)],
45 [(
'u', 39), ('u', 37), ('u', 35), ('u', 33), ('u', 31), ('v', 39),
46 (
'v', 37), (
'v', 35), (
'v', 33), (
'v', 31), (
'w', 47), (
'w', 45),
47 (
'w', 43), (
'w', 41), (
'w', 39), (
'w', 37)],
48 [(
'w', 26), (
'w', 28), (
'w', 30), (
'w', 32), (
'w', 34), (
'w', 36),
49 (
'v', 22), (
'v', 24), (
'v', 26), (
'v', 28), (
'v', 30), (
'u', 22), 50 ('u', 24), ('u', 26), ('u', 28), ('u', 30)], 51 [('w', 38), (
'w', 40), (
'w', 42), (
'w', 44), (
'w', 46), (
'w', 48),
52 (
'v', 32), (
'v', 34), (
'v', 36), (
'v', 38), (
'v', 40), (
'u', 32), 53 ('u', 34), ('u', 36), ('u', 38), ('u', 40)]], dtype=object) 56 chip_channel_spot = chip_channel_layer_spot_matrix[:,:,1].astype(numpy.int32)
57 chip_channel_layer = numpy.asarray([
"uvw".
index(i)
for i
in chip_channel_layer_spot_matrix[:,:,0].flat]).reshape(chip_channel_layer_spot_matrix.shape[:2]).astype(numpy.int32)
62 Flatten an ASIC channel X number matrix to a dictionary keyed by 63 (plane letter, local wire attachment number (1-48 or 1-40). Value 64 is a tuple (ichip, ich) with ichip:{1-8} and ich:{1-16} 70 ret[cell] = (ichip+1, ich+1)
74 FaceParams = namedtuple(
"FaceParams", [
"nlayers",
"nboards"]);
75 BoardParams = namedtuple(
"BoardParams", [
"nchips",
"nchanperchip"])
76 DaqParams = namedtuple(
"DaqParams", [
"nwibs",
"nconnperwib"])
77 GeomParams = namedtuple(
"GeomParams", [
"width",
"height",
"pitch",
"angle",
"offset",
"planex"])
78 Params = namedtuple(
"ApaParams", [
"nfaces",
"anode_loc",
"crate_addr",
79 "face",
"board",
"daq",
"geom"])
81 plane_separation = 4.71*units.mm
91 width = 2295*units.mm,
92 height = 5920*units.mm,
93 pitch = 4.669*units.mm,
94 angle = +35.707*units.deg,
95 offset = 0.3923*units.mm,
96 planex = 3*plane_separation
99 width = 2295*units.mm,
100 height = 5920*units.mm,
101 pitch = 4.669*units.mm,
102 angle = -35.707*units.deg,
103 offset = 0.3923*units.mm,
104 planex = 2*plane_separation
107 width = 2295*units.mm,
108 height = 5920*units.mm,
109 pitch = 4.790*units.mm,
111 offset = 0.295*units.mm,
112 planex = plane_separation
117 GeomPoint = namedtuple(
"GeomPoint", [
"x",
"y",
"z"])
118 GeomWire = namedtuple(
"GeomWire", [
"ploc",
"wip",
"spot",
"seg",
"p1" ,
"p2"])
122 Provide data methods to describe an APA and enumerate its connectivity. 141 bi = numpy.array(range(self.
nboards))
146 ci = numpy.array(range(self.
nchips))
155 self.p.board.nchips, self.p.board.nchanperchip)
160 for k,v
in self.
ccls:
178 for iplane, geom
in enumerate(self.p.geom):
181 raw_wires = generator.wrapped_from_top_oneside(geom.offset, geom.angle, geom.pitch, rect)
183 gwires_front = list()
185 for wip, raw_wire
in enumerate(raw_wires):
186 ap, side, spot, seg, zy1, zy2 = raw_wire
188 p1 =
GeomPoint(geom.planex, zy1[1], zy1[0])
189 self.points.append(p1)
191 p2 =
GeomPoint(geom.planex, zy2[1], zy2[0])
192 self.points.append(p2)
193 wf =
GeomWire(ap, wip, spot, seg, ip1, ip2)
194 wb =
GeomWire(ap, wip, spot, seg, ip1, ip2)
195 gwires_front.append(wf)
196 gwires_back.append(wb)
207 Return a tuple of a global wire index and the gwire 215 Return the global conductor index based on the face, plane and spot. 218 board_in_face = spot_in_plane//nch
219 spot_in_layer = spot_in_plane%nch
225 Given the paramers return information about the associated 226 conductor as a triple: 228 - iconductor :: the apa-global index for the conductor 230 - chip :: the board-local index for the chip 232 - chan :: the chip-local index for the channel 235 nchip,nch = self.
ccls[(
"uvw"[layer_in_face], wire_spot_in_layer+1)]
237 ichip,ich = nchip-1, nch-1
239 return (icond, ichip, ich)
243 Given a global board index, return tuple of: 245 - iface :: the apa-global face index 246 - board : the face-local board index 248 if not iboard
in range(self.
nboards):
249 raise ValueError(
"iboard is out of range: %d" % iboard)
250 iface = iboard//self.p.face.nboards
251 board = iboard%self.p.face.nboards
255 'Return global plane index given global face and plane in face' 257 return iface*self.p.face.nlayers + plane_in_face
274 Parts = namedtuple(
"Parts",
275 [
"detector",
"apa",
"face",
"plane",
276 "wib",
"board",
"chip",
"conductor",
277 "channel",
"wire",
"point" 282 n = getattr(ac,
'n'+typename+
's')
283 except AttributeError:
284 G.add_node(typename, type=typename)
288 name =
"%s%d" % (typename, ind)
289 G.add_node(name, type=typename, index=ind)
296 Return a directed graph expressing the connectivity and 297 containment given the apa.Description object. 299 G = networkx.DiGraph()
301 p =
Parts(*[
maker(G, desc, typename)
for typename
in Parts._fields])
303 def join(n1, n2, link, relationship = "containment", **params):
305 if relationship
in [
"peer",
"sibling"]:
306 G.add_edge(n1, n2, relationship=relationship, link=link, **params)
307 G.add_edge(n2, n1, relationship=relationship, link=link, **params)
309 if relationship
in [
"direct",
"simple"]:
310 G.add_edge(n1, n2, relationship=relationship, link=link, **params)
313 G.add_edge(n1, n2, relationship=
"children", link=link, **params)
314 G.add_edge(n2, n1, relationship=
"parent", link=link, **params)
321 join(p.detector, p.apa,
'submodule', anode_lcr = desc.p.anode_loc)
325 for gi_wib
in range(desc.nwibs):
328 join(p.apa, wib,
'slot', slot=gi_wib)
331 for i_wibconn
in range(desc.p.daq.nconnperwib):
332 gi_board = desc.iboard_by_conn_slot[i_wibconn, gi_wib]
333 board = p.board[gi_board]
335 join(wib, board,
'cable', connector = i_wibconn)
337 gi_face, iboard_in_face = desc.iface_board(gi_board)
339 for ilayer_in_face, ispots_in_layer
in enumerate(desc.nch_in_board_by_layer):
340 for ispot_in_layer
in range(ispots_in_layer):
341 gi_cond, ichip_on_board, ichan_in_chip \
342 = desc.iconductor_chip_chan(gi_face, iboard_in_face,
343 ilayer_in_face, ispot_in_layer)
345 conductor = p.conductor[gi_cond]
346 join(board, conductor,
'trace', layer=ilayer_in_face, spot=ispot_in_layer)
348 gi_chip = desc.ichip_by_face_board_chip[gi_face, iboard_in_face, ichip_on_board]
349 chip = p.chip[gi_chip]
353 join(board, chip,
'place', spot=ichip_on_board)
356 channel = p.channel[gi_cond]
357 join(chip, channel,
'address', address=ichan_in_chip)
359 join(channel, conductor,
'channel', relationship=
"peer")
362 G.node[point][
'pos'] = desc.points[ipoint]
364 for gi_face
in range(desc.nfaces):
365 face = p.face[gi_face]
366 join(p.apa, face,
'side', side=gi_face)
368 for iboard_in_face
in range(desc.p.face.nboards):
369 gi_board = desc.iboard_by_face_board[gi_face, iboard_in_face]
370 board = p.board[gi_board]
371 join(face, board,
'spot', spot = iboard_in_face)
373 for iplane_in_face, wires
in enumerate(desc.wires_by_face_plane[gi_face]):
375 gi_plane = desc.iplane(gi_face, iplane_in_face)
376 plane = p.plane[gi_plane]
377 join(face, plane,
'plane', plane=iplane_in_face)
379 for wip
in range(desc.nwires_by_plane[iplane_in_face]):
380 gi_wire, gwire = desc.wire_index_by_wip(gi_face, iplane_in_face, wip)
381 wire = p.wire[gi_wire]
382 join(plane, wire,
'wip', wip=wip)
383 G.node[wire][
'pitchloc'] = gwire.ploc
386 spot_face = (gi_face + gwire.seg%2)%2
388 gi_conductor = desc.iconductor_by_face_plane_spot(spot_face, iplane_in_face, gwire.spot)
389 conductor = p.conductor[gi_conductor]
390 join(conductor, wire,
'segment', segment=gwire.seg)
392 tail = p.point[gwire.p1]
393 join(wire, tail,
'pt', endpoint=0)
394 head = p.point[gwire.p2]
395 join(wire, head,
'pt', endpoint=1)
401 protodun_lcr = (1,2,3)
407 Return a channel address tuple associated with the given wire. 409 The tuple is intended to be directly passed to channel_hash(). 413 from .graph
import parent
415 conductor =
parent(G, wire,
'conductor')
416 channel =
parent(G, conductor,
'channel')
417 chip =
parent(G, channel,
'chip')
418 board =
parent(G, chip,
'board')
419 box =
parent(G, board,
'face')
420 wib =
parent(G, board,
'wib')
421 apa =
parent(G, wib,
'apa')
423 islot = G[apa][wib][
'slot']
424 iconn = G[wib][board][
'connector']
425 ichip = G[board][chip][
'spot']
426 iaddr = G[chip][channel][
'address']
427 return (iconn, islot, ichip, iaddr)
431 Hash a channel address tuple into a single integer. 433 See also channel_tuple(). 435 return int(
"%d%d%d%02d" % (iconn+1, islot+1, ichip+1, iaddr+1))
439 Return tuple used to produce the given hash. 442 return tuple([
int(n)-1
for n
in [a[0], a[1], a[2], a[3:5]]])
447 Return an identifier number for the channel attached to the given wire. 455 Provide an instance of a Plex that provides some convenient 456 mappings on the connection graph. 458 This assumes the given graph was created using conventions 459 expressed in parent module. 461 The term "Plex" for this role was invented by MINOS. 470 Return a generator of plane numbers, one for each chanidents. 472 for chid
in chanidents:
474 yield chip_channel_layer[ichip, iaddr]
def iplane(self, iface, plane_in_face)
wires_by_face_plane
wires ###
def graph(desc, maker=maker)
def flatten_cclsm(mat=chip_channel_layer_spot_matrix)
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
def wire_index_by_wip(self, face, plane, wip)
def __init__(self, params=default_params)
def channel_tuple(G, wire)
def iconductor_by_face_plane_spot(self, face, plane_in_face, spot_in_plane)
def iface_board(self, iboard)
def channel_plane(self, chanidents)
def maker(G, ac, typename)
def iconductor_chip_chan(self, face, board_in_face, layer_in_face, wire_spot_in_layer)
def parent(G, child, parent_type)
iconductor_by_face_board_chip_chan
def channel_ident(G, wire)
def channel_unhash(chident)
def channel_hash(iconn, islot, ichip, iaddr)