Object Model

The objects used to wrangle dfmuxes, mezzanines, SQUID controllers, wafers, bolometers, LC boards, and LC channels are all managed by a tool called an Object-Relational Mapper (ORM), and are internally managed in an SQL database. This provides a ton of flexibility and a very efficient means to access relationships between data in the system.

The downside of using an ORM is occasionally jargon-heavy error messages. If you are seeing these messages and want a short-cut deciphering them, feel free to contact Graeme Smecher <gsmecher@threespeedlogic.com>.

Overview

We define four chains of structures:

  1. Readout hardware: IceCrate, Dfmux, MGMEZZ04, ReadoutModule, and ReadoutChannel;
  2. The “SQUID controller” chain: MGMEZZ04, SQUIDController, and SQUID;
  3. The “Wafer” chain: Wafer and Bolometer, and
  4. The LC chain: LCBoard and LCChannel.

The interconnections between these structures are shown in Objects in a Dfmux Hardware Map..

../_images/objects1.svg

Objects in a Dfmux Hardware Map.

These objects and linkages are all physically motivated (i.e. they’re things you can poke, and the linkages between them generally match cables.) At the end of each of these chains is some object (a readout channel, a SQUID, a bolometer, and an LC channel) that we want to bundle together to define a single end-to-end chain of physical connections. We do this using a ChannelMapping.

Important

You do not need to construct these objects yourself! Instead, you are encouraged to use the YAML loader in pydfmux.core.session. For documentation, consult Hardware Map.

Readout Chain

The “Readout Chain” consists of the warm electronics living in the readout crates – IceBoards running dfmux firmware, and the complement of readout modules and channels living in the FPGA and controlled by software.

The readout chain consists of four objects:

These classes are all primarily focused with “firmware” tasks (controlling the resources within the FPGA, such as channel frequencies.) Each of these classes are described in the following sections.

Note that “firmware” functions (e.g. Dfmux.set_frequency()) are not shown in this documentation, since Sphinx cannot automatically extract them.

IceCrate objects

IceCrate objects represent a backplane (presumably in a crate) with IceBoards slotted into it.

Dfmux Objects

Dfmux objects represent an IceBoard running in a dfmux configuration (i.e. with dfmux hardware and software.) Under the hood, the Dfmux object inherits from an IceBoard object.

MGMEZZ04 Objects

A Dfmux object has up to 2 mezzanines, typically accessed via dfmux.mezzanine[1] or dfmux.mezzanine[2]. For dfmux experiments, these mezzanines are MGMEZZ04s represented by the MGMEZZ04 class (which inherits from FMCMezzanine).

SQUID Chain

The SQUID chain is a little odd, since it’s connected at both ends. On the left side, an MGMEZZ04 mezzanine defines the control path (i.e. for setting SQUID bias parameters.) On the right side, the data path specifies which bolometers, LC channels, and readout channels a SQUID belongs with.

Each of these classes are described in the following sections.

Wafer Chain

Objects in the Wafer Chain

Each of these classes are described in the following sections.

LC Chain

Objects in the LC Chain

Each of these classes are described in the following sections.

Pathstrings

Some Dfmux objects can be described by a unique pathstring that determines its location in the readout chain. For example, the pathstring for ReadoutChannel 42 located on module 2 of mezzanine 1 on the IceBoard with serial 0137 is: 0137/1/2/42. If the parent IceBoard is located in slot 5 of the IceCrate with serial 003, then the pathstring is instead 003/5/1/2/42.

Each Dfmux object with a pathstring (and by extension, each query of Dfmux objects with pathstrings) also has a pstring() method for polling for the pathstring. The result of each poll is cached in the hardware map as a _pstring column attribute.

Creating Experiment-Specific Extensions

The pydfmux package is intended to support multiple experiments. To do so, we allow the object model to be specialized through inheritance.

For example, the pydfmux.Dfmux class (which controls IceBoard hardware running Dfmux firmware) inherits from an IceBoard class, which is firmware-agnostic.

Inheritance is also a great way to specialize a given dfmux deployment. For example, one experiment might wish to add a “date_checked” field to its pydfmux.Bolometer class as follows. We begin with some imports:

>>> import pydfmux
>>> from sqlalchemy import Column, Date, Integer, ForeignKey
>>> from datetime import date

We’re now ready to define our new Bolometer implementation, which inherits from pydfmux.Bolometer. The three (unfortunate) lines beginning with underscores (_) are SQLAlchemy boilerplate describing how to handle inheritence in the database. The date_checked line does what we’re interested in (namely, defining a new field that stores a date.)

>>> class SpecialBolometer(pydfmux.Bolometer):
...     __tablename__ = 'special_bolometers'
...     __mapper_args__ = {'polymorphic_identity': 'special_bolometer'}
...     _pk = Column(Integer, ForeignKey('bolometers._pk'), primary_key=True)
...
...     date_checked = Column(Date)

We can now use the new class in a hardware map:

>>> hwm = pydfmux.HardwareMap()

>>> bs = [pydfmux.Bolometer(name='Frank'),
...       SpecialBolometer(name='Bernice', date_checked=date(2014,11,27)),
...       SpecialBolometer(name='Andy', date_checked=date(2013,10,5))]
>>> hwm.add_all(bs)
>>> hwm.commit()

Our hardware map hwm now contains one pydfmux.Bolometer and two instances of SpecialBolometer. Queries that search for all pydfmux.Bolometer will include the new class. Searches for just the new class don’t return instances of the old one.

>>> # Search for all Bolometers
>>> print hwm.query(pydfmux.Bolometer).all()
[None.Bolometer(u'Frank'), None.SpecialBolometer(u'Bernice'), None.SpecialBolometer(u'Andy')]

>>> # Search for only SpecialBolometers; retrieve the date_checked column
>>> print hwm.query(SpecialBolometer).date_checked
[datetime.date(2014, 11, 27), datetime.date(2013, 10, 5)]

Note

To take advantage of this querying behaviour, algorithms should be written using the “core” found in pydfmux.core.dfmux. Hardware maps should be constructed using specialized classes.