db.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 '''
3 Organize the connectivity of the parts of protoDUNE and DUNE FD
4 single-phase detectors.
5 
6 FIXME: only TPC related parts are supported for now!
7 
8 FIXME: this design is currently ambigous as to whether each part is
9 "logical" or "touchable" (in the Geant4 sense of these words). It
10 allows for both and it is up to the user to determine interpretation.
11 Future development may provide explicit interpretation.
12 
13 This organization separates into the following conceptual parts:
14 
15  - part identifiers :: the database provides a table for each type
16  of detector part relevant to identifiers that may be present in
17  its data.
18 
19  - part connectivity :: relationships between part tables and join
20  tables form edges in an overall connectivity graph.
21 
22  - connectivity ordering :: edges in the connectivity graph have a
23  scalar ordering based on one or more table columns or class
24  attributes.
25 
26  - numbering convention :: the database does not assume any
27  particular numbering convention except in so much as it can be
28  expressed in terms of the connectivity ordering attributes.
29 
30 A part table has relationships to others which fall into one of these
31 categories:
32 
33  - child :: a part may have a child sub-part which is considered
34  contained by the part.
35 
36  - parent :: a part may itself be a child and maintain a connection
37  to its parent part.
38 
39  - peer :: two parts may reference each other
40 
41  - simple :: a table may simply reference another in a
42  unidirectional manner.
43 
44  - special :: a relationship of convenience
45 
46 The child and parent connectivity is maintened, in part, through a
47 join table ("link") which allows specifying one or more connectivity
48 ordering attributes. These conections are expressed in two
49 relationships as rows/attributes on the part table/class. they take
50 names after the "other" part:
51 
52  - parts :: a sequence of the other connected parts with has no
53  explicit order.
54 
55  - part_links :: a sequence of links from the part to its children
56  or its parent(s). When referencing children, the links are
57  ordered by the connectivit ordering attributes held in the link
58  objects. Each link object gives access to both parent and child
59  parts.
60 
61 As a convenience, a child part may be associated to a parent part
62 through the parent's `add_<part>()` method. These methods accept an
63 existing child object and all connection ordering parameters. A join
64 object is constructed and returned (but can usually be ignored).
65 
66 Note, in detector description limited to a single detector where each
67 part is considered "touchable" (see FIXME above) the parent-child
68 relationship is one-to-many. OTOH, multiple connections from one
69 child back to multiple parents are supported. As an example, a
70 database may contain descriptions for both protoDUNE and DUNE where
71 with two Detector objects and where the former merely references six
72 anodes of the latter.
73 
74 The branches of the parent-child tree terminate at the channels leaf,
75 although channels have "peer" links to conductors (see below).
76 Conceptually, if one considers a containment tree, the tree also
77 terminates at wire leafs. However, there are cycles in relationship.
78 Wires are contained both by conductors which connect up through
79 electronics back to the detector and in planes which connect up
80 through structural elements to the detector. Likewise boards are
81 conceptually "in" both WIBs and Faces.
82 
83 The "peer" relationship is a simple one-to-one connection. Each part
84 on either end of the connection has an attribute named after the
85 "other" part. These are used to directly express a connection which
86 either can not be expressed or which would require traversal up and
87 down many intermeidate branches of the parent/child tree. For example
88 a Channel has a "conductor" and a Conductor has a "channel". Also,
89 Crates and Anodes share a peer relationship. To indirectly associate
90 the two would require redundancy in the join tables and require
91 complex queries. Instead, an explicit relationship is formed which
92 represents a physical soldering of a conductor to a wire board layer
93 and spot. A side effect benefit is that mistakes in such physical
94 connections can be represented.
95 
96 The "peer" relationships must be set explicitly set either at the time
97 of constructing the final end point object or later by setting the
98 corresponsing attribute on one (not both) of the end point objects.
99 
100 A "simple" relationship is used to compose compound values such as
101 referencing rays which themselves reference points. In some cases
102 "special" relationships are provided. For example, a Point can
103 determine which Rays refer to it, but other tables may reference a
104 Point and no back reference will exist.
105 '''
106 
107 
108 
109 from sqlalchemy import Column, ForeignKey, Float, Integer, String, CheckConstraint
110 from sqlalchemy.ext.declarative import declarative_base
111 from sqlalchemy.orm import relationship
112 
113 Base = declarative_base()
114 metadata = Base.metadata
115 
116 class Detector(Base):
117  '''
118  One detector, eg protoDUNE/SP, DUNE FD SP module.
119  '''
120  __tablename__ = "detectors"
121  id = Column(Integer, primary_key=True)
122 
123  crates = relationship('Crate',
124  secondary='detector_crate_links')
125  crate_links = relationship('DetectorCrateLink',
126  order_by='DetectorCrateLink.address',
127  back_populates="detector")
128 
129  anodes = relationship('Anode',
130  secondary='detector_anode_links')
131  anode_links = relationship('DetectorAnodeLink',
132  order_by='DetectorAnodeLink.layer, '
133  'DetectorAnodeLink.column, '
134  'DetectorAnodeLink.row',
135  back_populates = "detector")
136 
137  def add_anode(self, anode, row, column, layer):
138  '''
139  Add an anode at a given address, return the DetectorAnodeLink.
140  '''
141  return DetectorAnodeLink(detector=self, anode=anode,
142  row=row, column=column, layer=layer)
143 
144  def add_crate(self, cr, address):
145  '''
146  Add a create at a given address, return the DetectorCrateLink.
147  '''
148  return DetectorCrateLink(detector=self, crate=cr, address=address)
149 
150  def __repr__(self):
151  return "<Detector: %s>" % self.id
152 
153 class Anode(Base):
154  '''
155  An anode (APA, anode plane assembly) is in a detector and has two faces.
156  '''
157  __tablename__ = 'anodes'
158  id = Column(Integer, primary_key=True)
159 
160  # Note, this is in general a collection. For example, a user may
161  # define protoDUNE as a subset of DUNE anodes in which case some
162  # anodes may have two detectors.
163  detectors = relationship('Detector',
164  secondary='detector_anode_links')
165  detector_links = relationship('DetectorAnodeLink',
166  back_populates = "anode")
167 
168  faces = relationship('Face',
169  secondary = 'anode_face_links')
170  face_links = relationship('AnodeFaceLink',
171  order_by='AnodeFaceLink.side',
172  back_populates = 'anode')
173 
174  def add_face(self, face, side):
175  '''
176  Add a face to this anode on the given side.
177  '''
178  return AnodeFaceLink(anode=self, face=face, side=side)
179 
180  # origin_id = Column(Integer, ForeignKey('points.id'))
181  # ... link directly to crate
182  def __repr__(self):
183  return "<Anode: %s>" % self.id
184 
185 
186 class Face(Base):
187  '''
188  An anode face contains boards and planes.
189  '''
190  __tablename__ = 'faces'
191  id = Column(Integer, primary_key=True)
192 
193  anodes = relationship('Anode',
194  secondary='anode_face_links')
195  anode_links = relationship('AnodeFaceLink',
196  back_populates = "face")
197 
198  boards = relationship('Board',
199  secondary = 'face_board_links')
200  board_links = relationship('FaceBoardLink',
201  order_by = 'FaceBoardLink.spot',
202  back_populates = 'face')
203 
204  planes = relationship('Plane',
205  secondary = 'face_plane_links')
206  plane_links = relationship('FacePlaneLink',
207  order_by = 'FacePlaneLink.layer',
208  back_populates = 'face')
209 
210  def add_board(self, board, spot):
211  '''
212  Add a board at a spot into this face.
213  '''
214  return FaceBoardLink(face=self, board=board, spot=spot)
215 
216  def add_plane(self, plane, layer):
217  '''
218  Add a plane at a layer into this face.
219  '''
220  return FacePlaneLink(face=self, board=board, layer=layer)
221 
222  # ...drift dir
223  def __repr__(self):
224  return "<Face: %s>" % self.id
225 
226 
227 class Plane(Base):
228  '''
229  A plane is in a face and has wires.
230  '''
231  __tablename__ = 'planes'
232  id = Column(Integer, primary_key=True)
233 
234  faces = relationship('Face',
235  secondary='face_plane_links')
236  face_links = relationship('FacePlaneLink',
237  back_populates = "plane")
238 
239  wires = relationship('Wire',
240  secondary = 'plane_wire_links')
241  wire_links = relationship('PlaneWireLink',
242  order_by = 'PlaneWireLink.spot',
243  back_populates = 'plane')
244 
245  def add_wire(self, wire, spot):
246  '''
247  Add a wire in a particular spot in the plane.
248  '''
249  return PlaneWireLink(plane=self, wire=wire, spot=spot)
250 
251  #... wiredir, pitchdir, origin
252 
253  def __repr__(self):
254  return "<Plane: %s>" % self.id
255 
256 class Crate(Base):
257  '''
258  One crate of a detector holding WIBs.
259  '''
260  __tablename__ = "crates"
261  id = Column(Integer, primary_key=True)
262 
263  detectors = relationship('Detector',
264  secondary='detector_crate_links')
265  detector_links = relationship('DetectorCrateLink',
266  back_populates = "crate")
267 
268  wibs = relationship('Wib',
269  secondary = 'crate_wib_links')
270  wib_links = relationship('CrateWibLink',
271  order_by = 'CrateWibLink.slot',
272  back_populates = 'crate')
273 
274  def add_wib(self, wib, slot):
275  '''
276  Add a WIB into the slot of this crate.
277  '''
278  return CrateWibLink(crate=self, wib=wib, slot=slot)
279 
280  def __repr__(self):
281  return "<Crate: %s>" % self.id
282 
283 
284 class Wib(Base):
285  '''
286  A WIB (warm interface board) sits in a crate and connects to a
287  four (electronics wire) boards.
288  '''
289  __tablename__ = "wibs"
290  id = Column(Integer, primary_key=True)
291 
292  crates = relationship("Crate",
293  secondary = 'crate_wib_links')
294  crate_links = relationship('CrateWibLink',
295  back_populates = 'wib')
296 
297  boards = relationship('Board',
298  secondary = 'wib_board_links')
299  board_links = relationship('WibBoardLink',
300  order_by = 'WibBoardLink.connector',
301  back_populates = 'wib')
302  def add_board(self, board, connector):
303  '''
304  Add an cold electronics wire board to this WIB
305  '''
306  return WibBoardLink(wib=self, board=board, connector=connector)
307 
308  def __repr__(self):
309  return "<Wib: %s>" % self.id
310 
311 
312 class Board(Base):
313  '''
314  An (electronics wire) board sits on top (or bottom) of an APA
315  frame and holds 8 pairs of FE/ADC ASIC chips and connects to three
316  rows of 40, 40 and 48 conductors.
317  '''
318  __tablename__ = "boards"
319  id = Column(Integer, primary_key=True)
320 
321  # up links
322  wibs = relationship("Wib",
323  secondary = "wib_board_links")
324  wib_links = relationship("WibBoardLink",
325  back_populates = "board")
326 
327  faces = relationship("Face",
328  secondary = "face_board_links")
329  face_links = relationship("FaceBoardLink",
330  back_populates = "board")
331 
332  # downlinks
333  conductors = relationship("Conductor",
334  secondary = "board_conductor_links")
335  conductor_links = relationship("BoardConductorLink",
336  order_by = 'BoardConductorLink.layer, '
337  'BoardConductorLink.spot',
338  back_populates = "board")
339  chips = relationship("Chip",
340  secondary = "board_chip_links")
341  chip_links = relationship("BoardChipLink",
342  order_by = 'BoardChipLink.spot',
343  back_populates = "board")
344 
345  def add_conductor(self, conductor, spot, layer):
346  '''
347  Add a conductor to this board at the given spot of a layer.
348  '''
349  return BoardConductorLink(board=self, conductor=conductor, spot=spot, layer=layer)
350 
351  def add_chip(self, chip, spot):
352  '''
353  Add a chip to this board at the given spot.
354  '''
355  return BoardChipLink(board=self, chip=chip, spot=spot)
356 
357  def __repr__(self):
358  return "<Board: %s>" % self.id
359 
360 
361 class Chip(Base):
362  '''
363  A chip is a pair of FE/ADC asics with 16 channels
364  '''
365  __tablename__ = "chips"
366  id = Column(Integer, primary_key=True)
367 
368  boards = relationship("Board",
369  secondary = "board_chip_links")
370  board_links = relationship("BoardChipLink",
371  back_populates = "chip")
372 
373  channels = relationship("Channel",
374  secondary = "chip_channel_links")
375  channel_links = relationship("ChipChannelLink",
376  order_by = 'ChipChannelLink.address',
377  back_populates = "chip")
378 
379  def add_channel(self, channel, address):
380  '''
381  Add a channel to this chip at the given address.
382  '''
383  return ChipChannelLink(chip=self, channel=channel, address=address)
384 
385  def __repr__(self):
386  return "<Chip: %s>" % self.id
387 
389  '''
390  A conductor is a length of wire segments connecting to a board at
391  a given position indicated by plane and spot .
392  '''
393  __tablename__ = "conductors"
394  id = Column(Integer, primary_key=True)
395 
396  boards = relationship("Board",
397  secondary = "board_conductor_links")
398  board_links = relationship("BoardConductorLink",
399  back_populates = "conductor")
400 
401  wires = relationship("Wire",
402  secondary = "conductor_wire_links")
403  wire_links = relationship("ConductorWireLink",
404  order_by = 'ConductorWireLink.segment',
405  back_populates = "conductor")
406 
407  channel_id = Column(Integer, ForeignKey('channels.id'))
408  channel = relationship('Channel', back_populates='conductor')
409 
410  def add_wire(self, wire, segment):
411  '''
412  Add a wire to this conductor as the given segment.
413  '''
414  return ConductorWireLink(conductor=self, wire=wire, segment=segment);
415 
416  def __repr__(self):
417  return "<Conductor: %s>" % self.id
418 
419 
420 class Channel(Base):
421  '''
422  An electronics channel.
423  '''
424  __tablename__ = 'channels'
425  id = Column(Integer, primary_key=True)
426 
427  chips = relationship("Chip",
428  secondary = "chip_channel_links")
429  chip_links = relationship("ChipChannelLink",
430  back_populates = "channel")
431 
432  # Direct relationship to one and only attached conductor
433  conductor = relationship('Conductor', uselist=False,
434  back_populates='channel')
435  def __repr__(self):
436  return "<Channel: %s>" % self.id
437 
438 
439 class Wire(Base):
440  '''
441  A wire segment.
442  '''
443  __tablename__ = 'wires'
444  id = Column(Integer, primary_key=True)
445 
446  conductors = relationship("Conductor",
447  secondary = "conductor_wire_links")
448  conductor_links = relationship("ConductorWireLink",
449  back_populates = "wire")
450 
451  planes = relationship("Plane",
452  secondary = "plane_wire_links")
453  plane_links = relationship("PlaneWireLink",
454  back_populates = "wire")
455 
456 
457  ray_id = Column(Integer, ForeignKey('rays.id'))
458  ray = relationship('Ray')
459 
460  def __repr__(self):
461  return "<Wire %d>" % self.id
462 
463 
464 class Ray(Base):
465  '''
466  Two endpoints and a microphone.
467  '''
468  __tablename__ = "rays"
469 
470  id = Column(Integer, primary_key=True)
471 
472  # Endpoint tail point
473  tail_id = Column(Integer, ForeignKey('points.id'))
474  tail = relationship("Point", foreign_keys = [tail_id])
475 
476  # Endpoint head point
477  head_id = Column(Integer, ForeignKey('points.id'))
478  head = relationship("Point", foreign_keys = [head_id])
479 
480  # The wire segments which have this ray as their endpoints
481  wires = relationship("Wire",
482  primaryjoin='Ray.id == Wire.ray_id')
483  def __repr__(self):
484  return "<Ray %d>" % self.id
485 
486 
487 class Point(Base):
488  '''
489  A point in some unspecified 3-space coordinate system.
490  '''
491  __tablename__ = "points"
492 
493  id = Column(Integer, primary_key=True)
494  x = Column(Float)
495  y = Column(Float)
496  z = Column(Float)
497 
498  # the ray tails using this point
499  tails = relationship("Ray",
500  primaryjoin='Point.id == Ray.tail_id')
501  # the ray heads using this point
502  heads = relationship("Ray",
503  primaryjoin='Point.id == Ray.head_id')
504  # the rays using this point (union of tails and heads)
505  rays = relationship("Ray",
506  primaryjoin='or_(Point.id == Ray.head_id, Point.id == Ray.tail_id)')
507 
508  def __repr__(self):
509  return "<Point %d x:%f y:%f z:%f>" % (self.id, self.x, self.y, self.z)
510 
511 
512 
513 # Association pattern
514 # http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#association-object
515 
517  '''
518  A join table for detector-crate association.
519  '''
520  __tablename__ = "detector_crate_links"
521 
522  detector_id = Column(Integer, ForeignKey('detectors.id'), primary_key=True)
523  crate_id = Column(Integer, ForeignKey('crates.id'), primary_key=True)
524  detector = relationship('Detector', back_populates='crate_links')
525  crate = relationship('Crate', back_populates='detector_links')
526 
527  address = Column(Integer)
528 
529  def __repr__(self):
530  return "<DetectorCrateLink address:%s [%s %s]> " % \
531  (self.address, self.detector, self.crate)
532 
534  '''
535  A join table for crate-WIB association
536  '''
537  __tablename__ = "crate_wib_links"
538  crate_id = Column(Integer, ForeignKey('crates.id'), primary_key=True)
539  wib_id = Column(Integer, ForeignKey('wibs.id'), primary_key=True)
540 
541  crate = relationship('Crate', back_populates='wib_links')
542  wib = relationship('Wib', back_populates='crate_links')
543 
544  slot = Column(Integer)
545 
546  def __repr__(self):
547  return "<CrateWibLink slot:%s [%s %s]> " % \
548  (self.address, self.crate, self.wib)
549 
551  '''
552  A join table for WIB-board association.
553  '''
554  __tablename__ = 'wib_board_links'
555 
556  wib_id = Column(Integer, ForeignKey('wibs.id'), primary_key = True)
557  board_id = Column(Integer, ForeignKey('boards.id'), primary_key = True)
558 
559  wib = relationship('Wib', back_populates='board_links')
560  board = relationship('Board', back_populates='wib_links')
561 
562  # wibs have their data connectors arranged on a 2x2 grid but are
563  # identified in the design with a single dimensional connector
564  # number and well defined so the identifier is kept scalar.
565  connector = Column(Integer)
566 
567  def __repr__(self):
568  return "<WibBoardLink slot:%s [%s %s]> " % \
569  (self.connector, self.wib, self.board)
570 
571 
573  '''
574  A join table for board-conductor association.
575  '''
576  __tablename__ = 'board_conductor_links'
577 
578  board_id = Column(Integer, ForeignKey('boards.id'), primary_key = True)
579  conductor_id = Column(Integer, ForeignKey('conductors.id'), primary_key = True)
580 
581  board = relationship('Board', back_populates='conductor_links')
582  conductor = relationship('Conductor', back_populates='board_links')
583 
584  # A conductor is attached to a wire board in one of three possible
585  # conceptual lines, one for each plane layer. The number of
586  # conductors is not the same for each layer. The spot identifies
587  # a conductor in its layer.
588  layer = Column(Integer)
589  spot = Column(Integer)
590 
591  def __repr__(self):
592  return "<BoardConductorLink layer:%s spot:%s [%s %s]> " % \
593  (self.plane, self.layer, self.board, self.conductor)
594 
596  '''
597  A join table for board-chip association.
598  '''
599  __tablename__ = 'board_chip_links'
600 
601  board_id = Column(Integer, ForeignKey('boards.id'), primary_key = True)
602  chip_id = Column(Integer, ForeignKey('chips.id'), primary_key = True)
603 
604  board = relationship('Board', back_populates='chip_links')
605  chip = relationship('Chip', back_populates='board_links')
606 
607  spot = Column(Integer)
608 
609  def __repr__(self):
610  return "<BoardChipLink spot:%s [%s %s]> " % \
611  (self.spot, self.board, self.chip)
612 
613 
615  '''
616  A join table for chip-channel association.
617  '''
618  __tablename__ = 'chip_channel_links'
619 
620  chip_id = Column(Integer, ForeignKey('chips.id'), primary_key = True)
621  channel_id = Column(Integer, ForeignKey('channels.id'), primary_key = True)
622 
623  chip = relationship('Chip', back_populates='channel_links')
624  channel = relationship('Channel', back_populates='chip_links')
625 
626  address = Column(Integer)
627 
628  def __repr__(self):
629  return "<ChipOffsetLink address:%s [%s %s]> " % \
630  (self.address, self.chip, self.channel)
631 
633  '''
634  A join table for conductor-wire association.
635  '''
636  __tablename__ = 'conductor_wire_links'
637 
638  conductor_id = Column(Integer, ForeignKey('conductors.id'), primary_key = True)
639  wire_id = Column(Integer, ForeignKey('wires.id'), primary_key = True)
640 
641  conductor = relationship('Conductor', back_populates='wire_links')
642  wire = relationship('Wire', back_populates='conductor_links')
643 
644  segment = Column(Integer)
645 
646  def __repr__(self):
647  return "<ConductorWireLink segment:%s [%s %s]> " % \
648  (self.segment, self.conductor, self.wire)
649 
650 
652  '''
653  A join table for detector-anode association
654  '''
655  __tablename__ = 'detector_anode_links'
656 
657  detector_id = Column(Integer, ForeignKey('detectors.id'), primary_key = True)
658  anode_id = Column(Integer, ForeignKey('anodes.id'), primary_key = True)
659 
660  detector = relationship('Detector', back_populates='anode_links')
661  anode = relationship('Anode', back_populates='detector_links')
662 
663  # APAs with their edges touching form a row.
664  row = Column(Integer)
665  # A column of APAs are formed along direction or anti-direction of the drift
666  column = Column(Integer)
667  # A layer of APAs are formed when one is stacked on top of another
668  # along the top or bottom of their frames. protoDUNE has only one
669  # layer, DUNE has two.
670  layer = Column(Integer)
671 
672  def __repr__(self):
673  return "<DetectorAnodeLink apanum:%s [%s %s]> " % \
674  (self.apanum, self.detecotr, self.anode)
675 
677  '''
678  A join table for anode-face association
679  '''
680  __tablename__ = 'anode_face_links'
681 
682  anode_id = Column(Integer, ForeignKey('anodes.id'), primary_key = True)
683  face_id = Column(Integer, ForeignKey('faces.id'), primary_key = True)
684 
685  anode = relationship('Anode', back_populates='face_links')
686  face = relationship('Face', back_populates='anode_links')
687 
688  # Enumerate on which side of the anode this face resides.
689  side = Column(Integer)
690 
691  def __repr__(self):
692  return "<AnodeFaceLink side:%s [%s %s]> " % \
693  (self.side, self.anode, self.face)
694 
696  '''
697  A join table for face-baord association
698  '''
699  __tablename__ = 'face_board_links'
700 
701  face_id = Column(Integer, ForeignKey('faces.id'), primary_key = True)
702  board_id = Column(Integer, ForeignKey('boards.id'), primary_key = True)
703 
704  face = relationship('Face', back_populates='board_links')
705  board = relationship('Board', back_populates='face_links')
706 
707  spot = Column(Integer)
708 
709  def __repr__(self):
710  return "<FaceBoardLink spot:%s [%s %s]> " % \
711  (self.spot, self.anode, self.face)
712 
714  '''
715  A join table for face-plane association
716  '''
717  __tablename__ = 'face_plane_links'
718 
719  face_id = Column(Integer, ForeignKey('faces.id'), primary_key = True)
720  plane_id = Column(Integer, ForeignKey('planes.id'), primary_key = True)
721 
722  face = relationship('Face', back_populates='plane_links')
723  plane = relationship('Plane', back_populates='face_links')
724 
725  layer = Column(Integer)
726 
727  def __repr__(self):
728  return "<FacePlaneLink layer:%s [%s %s]> " % \
729  (self.layer, self.anode, self.face)
730 
732  '''
733  A join table for plane-wire association
734  '''
735  __tablename__ = 'plane_wire_links'
736 
737  plane_id = Column(Integer, ForeignKey('planes.id'), primary_key = True)
738  wire_id = Column(Integer, ForeignKey('wires.id'), primary_key = True)
739 
740  plane = relationship('Plane', back_populates='wire_links')
741  wire = relationship('Wire', back_populates='plane_links')
742 
743  # wire in some spot of the plane.
744  spot = Column(Integer)
745 
746  def __repr__(self):
747  return "<PlaneWireLink index:%s [%s %s]> " % \
748  (self.index, self.plane, self.wire)
749 
750 
751 
752 from sqlalchemy import create_engine
753 from sqlalchemy.orm import sessionmaker
754 def session(dburl="sqlite:///:memory:"):
755  '''
756  Return a DB session
757  '''
758  engine = create_engine(dburl)
759  Base.metadata.create_all(engine)
760  Session = sessionmaker(bind=engine)
761  return Session()
def add_wire(self, wire, spot)
Definition: db.py:245
def __repr__(self)
Definition: db.py:385
def add_board(self, board, spot)
Definition: db.py:210
def add_anode(self, anode, row, column, layer)
Definition: db.py:137
def add_crate(self, cr, address)
Definition: db.py:144
def add_face(self, face, side)
Definition: db.py:174
def __repr__(self)
Definition: db.py:483
def add_conductor(self, conductor, spot, layer)
Definition: db.py:345
def add_board(self, board, connector)
Definition: db.py:302
def session(dburl="sqlite:///:memory:")
Definition: db.py:754
def add_channel(self, channel, address)
Definition: db.py:379
def add_plane(self, plane, layer)
Definition: db.py:216
def add_wire(self, wire, segment)
Definition: db.py:410
def add_chip(self, chip, spot)
Definition: db.py:351
def __repr__(self)
Definition: db.py:223
def __repr__(self)
Definition: db.py:308
def __repr__(self)
Definition: db.py:460
def add_wib(self, wib, slot)
Definition: db.py:274