Skip to main content

Automated DAQ + flux-lock control for STAR Cryoelectronics PFL-102 SQUID systems

Project description

AutoSQUID — SQUID measurement-cycle + auto-S-tune

This package is developed specifically for performing/automating superconductor quantum interference device (SQUID) measurements. It's developed using Star Cryoelectronics PFL-102, PCI-1000, and DAC-2568 and a national instrument (NI) data acuisition (DAQ) card PCIe-6320. All settings live in the notebook as one Config object; all logic lives in the modules here. The package imports nidaqmx + pyserial (it assumes a STAR Cryo + NI rig); the MXC thermometer is not imported — you plug your lab's reader into cfg.temp_reader in the notebook.

Full reference: docs/AutoSQUID_protocol.pdf — the configuration table, the PCIe-6320 DAQ and PFL-102/SCC details, the reset protocol, the run loop, the operating procedure, and the auto-S-tune procedure. This README is the orientation + quick-start; the protocol is the bench reference.

What it does

For one fixed temperature, and for each scan interval, collect a target number of clean, gap-free time-series runs at the chosen sample rate. It watches for a flux-lock jump while acquiring, resets the feedback locked loop (FLL) and re-acquires on a failure, logs the MXC temperature throughout, and saves each trace in the standard PCS102 text format with an append-only run ledger. A companion notebook centers the locked output near 0 mV before the run (auto-S-tune).

Wiring

SQUID wiring diagram

Analog: SQUID/PFL-102 (Bluefors) → PCI-1000 ch.1 → PCI-1000 OUTPUT → DAC-2568 ANALOG IN → ANALOG OUT (68-pin) → PCIe-6320 ai0 (read over the PCIe bus via nidaqmx). Control: PC → PCI-1000 RS232 → PFL (SCC serial, write-only). Sync: PCI-1000 SYNC OUT → DAC-2568 (1-pin LEMO).

Project layout

AutoSQUID/
├─ pyproject.toml          # pip install -e .   (src layout)
├─ README.md  CHANGELOG.md  LICENSE (GPLv3)
├─ src/AutoSQUID/          # the importable package (modules below)
├─ examples/               # example_*.ipynb showcases (local working copies are gitignored)
└─ docs/                   # AutoSQUID_protocol.pdf, squid_wiring_diagram.png

Modules

module role deps
util.py generic helpers (clamp)
config.py Config dataclass — every knob + derived paths / filename stem / PFL register
scc.py SCC framing:assemble_command, pfl_register, dac_data (OpenSQUID-derived)
analysis.py detection + I/O:is_surge_spec, chunk_jump, format_temp_label, PCS102 read/write, ledger, scan_indices numpy, pandas
serial_io.py SCC writes:reset, fire_reset, s_lock/s_tune, set_squid_flux/_bias, set_array_biasset_array_flux pyserial
daq.py NI reads:daq_read, daq_mean, live_mean, classify, detect_ai_channel, acquire_finite_chunked nidaqmx
temperature.py MXC read_temp (via injected cfg.temp_reader) + background TempLogger — (injected)
measurement.py state machine:run_cycle (one interval), reset_and_verify, resolve_temp_label; the interval loop lives in the notebook
tuning.py auto_s_tune — live-center the locked output near 0 by stepping S-flux (secant search)
plotting.py plot_run — raw trace + temperature, read back from disk matplotlib, pandas

util/config/scc use only stdlib; analysis/plotting add numpy/pandas/matplotlib; serial_io/daq import their instrument backends (pyserial/nidaqmx) at module top — the package assumes the STAR Cryo + NI rig — while temperature imports no thermometer backend and reads through the injected cfg.temp_reader. So import AutoSQUID needs nidaqmx, pyserial, numpy, pandas, and matplotlib (but no lab thermometer library). Dependency order: utilscc/configanalysisserial_io/daq/temperaturemeasurement/tuning/plotting.

Notebooks (examples/)

  • example_measurement_cycle.ipynb — the minimal showcase: build Config (set data_root/user/date and your cfg.temp_reader) → detect_ai_channelresolve_temp_label → the interval loop (sq.run_cycle(cfg, tau)). Copy it and fill in your lab's values.
  • example_auto_s_tune.ipynb — build Configsq.s_lock(cfg) then sq.auto_s_tune(cfg).

After pip install -e . (from the repo root), each example just import AutoSQUID; you set cfg.temp_reader to your thermometer reader (fn(channel) -> T in K) in the first cell.

Quick start (bench PC)

import AutoSQUID as sq
cfg = sq.Config(scan_interval_s=[100e-6], n_trials=2, port="COM3",
                data_root=r"", user="", date="")     # set your data_root / user / date
# plug in your lab's thermometer reader: fn(channel) -> T in K
cfg.temp_reader = lambda ch: ...                     # define for your thermometer (returns T in K)
dev, cfg.daq_ai = sq.detect_ai_channel(cfg)          # §1 pick the live ai0
print(sq.read_temp(cfg))                             # confirm the MXC backend
for tau in cfg.scan_intervals:                       # §2 acquire (lock the FLL first!)
    if sq.run_cycle(cfg, tau) == "reset_fail":
        break
sq.plot_run(cfg)                                     # §3 plot from disk

First run on the hardware: do the one-time bring-up in the protocol (§ Operating procedure) as a supervised dry run — do not "Run All" blind.

Required fields (validated at the use site)

run_cycle() raises before any reset or write unless data_root, user, and daq_ai are set; with temp_label="auto" it also requires temp_reader. auto_s_tune() requires only daq_ai and port. Config() itself is passive — it doesn't validate.

Set cfg.temp_reader for any acquisition run: run_cycle() starts a background TempLogger that reads through it every temp_every_s, so without it the per-trace TEMP_*.csv is all nan. A literal temp_label (e.g. "14mK") only sets the filename label — it does not disable temperature logging.

Behavior (per scan interval)

Collect n_trials CLEAN traces within max_attempts real acquisitions. Each acquisition is order-indexed i: clean → DAQ_{MonDD}_{tau}us_{label}_{npts}_{i}.txt (+ its TEMP_..._{i}.csv), failed → …_{i}_{JUMP|SURGE|RAIL|BADBASE}.txt. i continues past existing files, so re-running resumes / tops up and never overwrites. A reset fires only after a failed acquisition, never between clean traces; a non-clearing reset — or a bad baseline at the start (the reset didn't hold) — is systemic and stops the whole sweep. Every acquisition outcome is appended to experiment_log.txt; resets, temperature reads, and MEASURE/BAD_BASELINE events go to action_log.txt (a reset failure also gets a ledger row).

A trace is labeled CLEAN only after a post-hoc is_surge_spec check passes: no rail, no >6σ baseline jump, and no frozen/stuck flat segment (flagged when a chunk's std collapses below the live noise level). Anything failing is saved with a _JUMP/_SURGE/_RAIL/_BADBASE suffix. (Still re-run the standalone integrity gate before downstream analysis.)

vrange = ±1 V (matches previous measurements): finer ADC resolution, but the ADC clips ~1 V, so jump_v (default 0.5 V) catches an in-range slip and rail_v (9.5 V) is dormant until the card returns to ±10 V.

Data layout

Everything is written under cfg.outdir = data_root / user / date:

<data_root>/                                       # cfg.data_root  (set per install)
└─ <user>/                                         # cfg.user
   └─ <date>/                                      # cfg.date   ("" → the bare <user>/ folder)
      ├─ DAQ_{MonDD}_{tau}us_{label}_{npts}_{i}.txt        # clean trace, e.g. DAQ_Jun01_100us_14mK_10Mpts_1.txt
      ├─ DAQ_..._{i}_{JUMP|SURGE|RAIL|BADBASE}.txt         # failed trace (+ its TEMP_..._{i}.csv)
      ├─ TEMP_{MonDD}_{tau}us_{label}_{npts}_{i}.csv       # that trace's MXC log (columns: time_s, T_K)
      ├─ experiment_log.txt                                # per-acquisition numeric ledger
      └─ action_log.txt                                    # results-free event log (resets, temp, attempts)

{i} is the order index and continues across days; matching ignores the {MonDD} date, so traces from any day in <date>/ count toward the same {tau}us_{label}_{npts} core.

Analysis (PSD)

sq.plot_psd(path, filename, conversion, P=…, clean_only=True) reads a trace back from disk and plots its PSD. Traces are stored in raw volts with no calibration baked in; plot_psd multiplies by the per-cooldown conversion factor (f₀/V) to give a flux PSD (f₀²/Hz), so you must pass the correct cooldown calibration yourself — it isn't recorded with the trace. clean_only=True runs the is_surge_spec integrity gate on each trace and skips any that fail.

Auto-S-tune

auto_s_tune automates the manual "nudge S-flux until the trace is centered at 0 mV": with the SQUID locked, it steps the SQUID-flux DAC and reads a short finite live-mean each step, using a secant update (dx = (target − mean)/slope) so the sign and gain are measured, not assumed — no reset between steps. Stops when the live mean is within tol_V (default 20 mV) of target, or at one DAC LSB. Returns dict(status ∈ {converged, dac_limited, no_response, max_iter}, flux_sflux, mean_V, std_V, n_iter) (dac_limited = as centered as one DAC LSB allows, still outside tol_V). no_response means the live mean doesn't move with the S-flux steps — typically not locked, wrong daq_ai, or S-flux not reaching the SQUID. See the protocol's auto-S-tune section for the full procedure.

Contact

For questions, bug reports, or setup issues, please feel free to contact:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autosquid-0.1.3.tar.gz (63.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autosquid-0.1.3-py3-none-any.whl (51.3 kB view details)

Uploaded Python 3

File details

Details for the file autosquid-0.1.3.tar.gz.

File metadata

  • Download URL: autosquid-0.1.3.tar.gz
  • Upload date:
  • Size: 63.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for autosquid-0.1.3.tar.gz
Algorithm Hash digest
SHA256 2c91e897d02c9671969dcc2046b288959449210981084f89d27304fd67858c5e
MD5 339fab88b580eb1fcc44572078b72571
BLAKE2b-256 aed8c3c27d570f2220bb0a14442c852ace4d7042f70621bc07b2af9d71237dce

See more details on using hashes here.

Provenance

The following attestation bundles were made for autosquid-0.1.3.tar.gz:

Publisher: publish.yml on zhengyuechen/AutoSQUID

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file autosquid-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: autosquid-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 51.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for autosquid-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 e7cd9f96f192dca7cd4a04a6acc34c0c278479a7b7e52b7045d18fb5f94132cd
MD5 29eb15e9ca1ec4e67230515ebd95917e
BLAKE2b-256 cae37ccad1ed7c6487ca50897e86f9671b15d3653b3fee8e45230f0ed994353c

See more details on using hashes here.

Provenance

The following attestation bundles were made for autosquid-0.1.3-py3-none-any.whl:

Publisher: publish.yml on zhengyuechen/AutoSQUID

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page