driftless-bundle-photometry 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. driftless_bundle_photometry-0.2.1.dist-info/METADATA +305 -0
  2. driftless_bundle_photometry-0.2.1.dist-info/RECORD +51 -0
  3. driftless_bundle_photometry-0.2.1.dist-info/WHEEL +4 -0
  4. driftless_bundle_photometry-0.2.1.dist-info/entry_points.txt +3 -0
  5. driftless_bundle_photometry-0.2.1.dist-info/licenses/LICENSE +21 -0
  6. driftless_photometry/__init__.py +10 -0
  7. driftless_photometry/__main__.py +3 -0
  8. driftless_photometry/acquisition.py +408 -0
  9. driftless_photometry/cli.py +309 -0
  10. driftless_photometry/config.py +384 -0
  11. driftless_photometry/desktop.py +36 -0
  12. driftless_photometry/diagnostics.py +49 -0
  13. driftless_photometry/domain.py +143 -0
  14. driftless_photometry/faults.py +27 -0
  15. driftless_photometry/gui/__init__.py +5 -0
  16. driftless_photometry/gui/app.py +34 -0
  17. driftless_photometry/gui/assets/__init__.py +1 -0
  18. driftless_photometry/gui/assets/driftless-photometry.png +0 -0
  19. driftless_photometry/gui/branding.py +14 -0
  20. driftless_photometry/gui/main_window.py +2208 -0
  21. driftless_photometry/gui/plot_interaction.py +94 -0
  22. driftless_photometry/gui/trace_display.py +118 -0
  23. driftless_photometry/gui/worker.py +107 -0
  24. driftless_photometry/hardware/__init__.py +41 -0
  25. driftless_photometry/hardware/base.py +23 -0
  26. driftless_photometry/hardware/controller_protocol.py +174 -0
  27. driftless_photometry/hardware/controller_serial.py +124 -0
  28. driftless_photometry/hardware/simulator.py +144 -0
  29. driftless_photometry/hardware/thorlabs.py +56 -0
  30. driftless_photometry/live_trace.py +96 -0
  31. driftless_photometry/provenance.py +84 -0
  32. driftless_photometry/roi.py +119 -0
  33. driftless_photometry/rwd/__init__.py +77 -0
  34. driftless_photometry/rwd/acquisition.py +244 -0
  35. driftless_photometry/rwd/capture.py +477 -0
  36. driftless_photometry/rwd/client.py +286 -0
  37. driftless_photometry/rwd/domain.py +142 -0
  38. driftless_photometry/rwd/protocol.py +301 -0
  39. driftless_photometry/rwd/timing.py +266 -0
  40. driftless_photometry/settings.py +382 -0
  41. driftless_photometry/state.py +55 -0
  42. driftless_photometry/storage/__init__.py +82 -0
  43. driftless_photometry/storage/capacity.py +155 -0
  44. driftless_photometry/storage/frames.py +32 -0
  45. driftless_photometry/storage/nwb.py +1162 -0
  46. driftless_photometry/storage/recovery.py +125 -0
  47. driftless_photometry/storage/rwd_nwb.py +772 -0
  48. driftless_photometry/storage/rwd_recovery.py +117 -0
  49. driftless_photometry/storage/rwd_spool.py +591 -0
  50. driftless_photometry/storage/spool.py +659 -0
  51. driftless_photometry/timing.py +78 -0
@@ -0,0 +1,305 @@
1
+ Metadata-Version: 2.5
2
+ Name: driftless-bundle-photometry
3
+ Version: 0.2.1
4
+ Summary: Trace-first multichannel fiber photometry acquisition and NWB recording
5
+ Project-URL: Homepage, https://github.com/mohebi-n-associates/DriftlessBundlePhotometry
6
+ Project-URL: Repository, https://github.com/mohebi-n-associates/DriftlessBundlePhotometry
7
+ Project-URL: Issues, https://github.com/mohebi-n-associates/DriftlessBundlePhotometry/issues
8
+ Project-URL: Changelog, https://github.com/mohebi-n-associates/DriftlessBundlePhotometry/blob/main/WHATS_NEW.md
9
+ Author: Driftless Bundle Photometry contributors
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: NWB,acquisition,fiber photometry,neuroscience
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Win32 (MS Windows)
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Operating System :: Microsoft :: Windows
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Scientific/Engineering
24
+ Requires-Python: <3.14,>=3.11
25
+ Requires-Dist: h5py<4,>=3.12
26
+ Requires-Dist: ndx-fiber-photometry<0.3,>=0.2.3
27
+ Requires-Dist: numpy<3,>=2.0
28
+ Requires-Dist: nwbinspector<1,>=0.6
29
+ Requires-Dist: platformdirs<5,>=4.3
30
+ Requires-Dist: pydantic<3,>=2.10
31
+ Requires-Dist: pynwb<5,>=4.0
32
+ Requires-Dist: pyserial<4,>=3.5
33
+ Provides-Extra: dev
34
+ Requires-Dist: pyqtgraph<0.15,>=0.13.7; extra == 'dev'
35
+ Requires-Dist: pyside6<6.9,>=6.8; extra == 'dev'
36
+ Requires-Dist: pytest-cov<7,>=6; extra == 'dev'
37
+ Requires-Dist: pytest-qt<5,>=4.4; extra == 'dev'
38
+ Requires-Dist: pytest<9,>=8.3; extra == 'dev'
39
+ Requires-Dist: ruff<1,>=0.11; extra == 'dev'
40
+ Provides-Extra: gui
41
+ Requires-Dist: pyqtgraph<0.15,>=0.13.7; extra == 'gui'
42
+ Requires-Dist: pyside6<6.9,>=6.8; extra == 'gui'
43
+ Provides-Extra: release
44
+ Requires-Dist: build<2,>=1.2; extra == 'release'
45
+ Requires-Dist: pillow<13,>=11; extra == 'release'
46
+ Requires-Dist: pyinstaller<7,>=6.16; extra == 'release'
47
+ Requires-Dist: twine<8,>=7; extra == 'release'
48
+ Description-Content-Type: text/markdown
49
+
50
+ # Driftless Bundle Photometry
51
+
52
+ **Version 0.2.1** · [What's new](WHATS_NEW.md)
53
+
54
+ A Python-based, trace-first multichannel fiber-photometry acquisition system.
55
+
56
+ The application supports up to nine circular fiber ROIs, interleaved 405/470/565 nm
57
+ excitation, four edge-recording TTL inputs, optional lossless raw frames, and one
58
+ self-contained NWB-HDF5 output per ROI and animal. Windows is the physical-hardware
59
+ target; the simulator and GUI demo are cross-platform.
60
+
61
+ ## Current implementation
62
+
63
+ - Immutable validation for sessions, channels, circular ROIs, camera settings, and
64
+ TTL inputs.
65
+ - Deterministic simulator and a shared headless acquisition engine with explicit
66
+ lifecycle states.
67
+ - Bounded, checksummed, chunked session spools that survive interruption and disk or
68
+ finalizer errors.
69
+ - Pre-arm storage-capacity checks and structured live diagnostics for queue pressure,
70
+ write latency, dropped frames, clock residuals, and NWB finalization stages.
71
+ - Typed acquisition faults are committed as system events and invalid-time markers
72
+ before an incomplete spool closes whenever committed samples can be recovered.
73
+ - Canonical NWB finalization using PyNWB, `ndx-fiber-photometry`, and
74
+ `ndx-ophys-devices`, including a separate subject, brain region, sensor type, and
75
+ validated file for every ROI.
76
+ - Exact per-exposure commanded voltage, controller sequence/tick, camera frame ID,
77
+ host receipt time, per-ROI saturation QC, explicit excitation events, and marked
78
+ invalid continuous spans in every independently interpretable animal file.
79
+ - Trace-first PySide6/pyqtgraph desktop demo with a separate calibration image and
80
+ draggable circular fiber ROIs, plus separate live camera panels for 405, 470, and
81
+ 565 nm exposures.
82
+ - Selectable 15 s, 1 min, 10 min, 1 h, and Full trace horizons with display-only
83
+ extrema-preserving decimation, keeping long recordings responsive without changing
84
+ acquired or stored samples.
85
+ - One live plot row per ROI with overlaid 405, 470, and 565 nm traces, independent
86
+ wavelength visibility controls, and Absolute or display-only dF/F views with a
87
+ configurable per-ROI/per-wavelength median baseline window.
88
+ - Optional display-only trailing-mean smoothing uses elapsed seconds, works with
89
+ asynchronously sampled channels, and never changes acquired or stored values.
90
+ - Independent enable/disable controls for each ROI; disabled definitions remain in
91
+ saved settings but are excluded from extraction, live traces, and NWB output.
92
+ - A required non-writing acquisition preview that validates timing, explicit
93
+ wavelength coverage, commanded voltages, camera frames, ROI extraction, and
94
+ saturation before enabling each recording.
95
+ - Synchronized numeric time axes across all ROI rows, horizontal/vertical drag-box
96
+ zoom, double-click zoom reset, and page scrolling—not graph zoom—under the mouse
97
+ wheel.
98
+ - Clean numeric entry fields without embedded increment/decrement stepper buttons.
99
+ - Versioned, human-readable JSON settings with GUI actions to save, load, set startup
100
+ defaults, and restore the complete setup from a previous DBF NWB recording.
101
+ - Settings v2 discriminate the native camera/controller source from the planned RWD
102
+ read-only bridge and migrate v1 files explicitly to native with a visible warning.
103
+ - A raw uint16 reference frame and fixed-scale ROI-annotated diagnostic view for
104
+ every wavelength observed in a recording are saved inside each ROI NWB file.
105
+ - Versioned/checksummed controller protocol, fail-safe lifecycle guard, and
106
+ single-owner serial transport that sends a best-effort `STOP` on close.
107
+ - Lazy Thorlabs SDK detection that does not break simulator mode on macOS.
108
+
109
+ The CS505MU camera transport, serial controller transport, controller firmware, and
110
+ LED intensity electronics are not yet physically validated. Those require the real
111
+ Windows rig, vendor SDK, trigger cabling, DAC/driver hardware, and bench timing and
112
+ safety measurements. Simulator success is not evidence of physical validation.
113
+
114
+ The RWD bridge currently has a documented wire contract, validated source settings,
115
+ typed raw domain records, a fixture-tested incremental fluorescence/event parser,
116
+ and a synthetic-data trace-only recovery/NWB path. The RWD spool retains checksummed
117
+ mixed records, exact raw ticks/values and scales, named ON/OFF events, connection
118
+ identity, faults, and invalid spans. Recovery creates one independently validated NWB
119
+ per mapped fiber without inventing camera frames, LED commands, native exposures, or
120
+ numbered TTL inputs. A headless single-owner TCP client now provides bounded
121
+ recording, timeout/disconnect/malformed-stream faults, prompt stop, storage preflight,
122
+ and machine-readable CLI output. The GUI workflow is still being implemented, and
123
+ the desktop setup now begins with a native/simulator or RWD read-only system choice,
124
+ hides camera/LED controls in RWD mode, retains per-fiber animal metadata, and routes
125
+ both sources through the same bounded live-trace presentation contract. Every RWD
126
+ fiber has an explicit device-channel number and an independent operator label. Live
127
+ status reports connection state, decoder counts, spool pressure, committed records,
128
+ and named event activity; raw, elapsed-time-smoothed, and dF/F views remain
129
+ presentation-only.
130
+ The TCP path has only synthetic local-server validation; current builds must not be
131
+ described as a physically validated RWD connection. See
132
+ [the RWD streaming contract](docs/rwd-streaming-protocol.md) and
133
+ [the RWD operator and bench-validation guide](docs/rwd-operator-guide.md).
134
+
135
+ The historical MATLAB, Arduino, and Bonsai sources remain under `old mescoscope/`
136
+ for reference and are not runtime dependencies.
137
+
138
+ ## Saving and restoring settings
139
+
140
+ The Configuration panel provides **Save JSON**, **Load JSON**, **Load NWB**, and
141
+ **Set as default**. A settings file includes all session metadata, recording duration,
142
+ output location, native/RWD source selection, source-specific connection settings,
143
+ camera and retention settings, excitation states and voltages, TTL configuration,
144
+ live-display preferences, and every fiber's animal metadata. Settings v1 files are
145
+ accepted only through an explicit migration to the native source because they
146
+ predate system selection.
147
+
148
+ On Windows, DBF resolves the same Documents folder used by Explorer, including
149
+ OneDrive or other redirected locations, and uses its `Driftless Bundle Photometry`
150
+ folder for settings. **Set as default** writes `default_settings.json` there; DBF
151
+ loads that file automatically at startup. Save and Load dialogs open in the same
152
+ folder by default.
153
+
154
+ Every newly recorded per-ROI NWB file embeds the complete settings snapshot, so any
155
+ one of those files can restore the whole multi-ROI setup. DBF can also import older
156
+ per-ROI DBF NWBs: it gathers matching sibling files to recover all available ROIs and
157
+ warns when an old file never recorded a setting that must use a safe default.
158
+ Each file also embeds a separate runtime provenance snapshot with the application,
159
+ Python, operating-system, dependency, adapter, and protocol versions that governed
160
+ acquisition or recovery.
161
+
162
+ ## Installation choices
163
+
164
+ End users on 64-bit Windows should use the standalone installer. Developers should
165
+ use the repository's Conda environment. PyPI is also available for users who already
166
+ manage Python environments. The standalone installer includes Python and all normal
167
+ application dependencies; it does not require Conda or a separate Python install.
168
+
169
+ ### Windows installer for end users
170
+
171
+ 1. Open the [latest GitHub release](https://github.com/mohebi-n-associates/DriftlessBundlePhotometry/releases/latest).
172
+ 2. Download `Driftless-Bundle-Photometry-<version>-Windows-x64-Setup.exe`.
173
+ 3. Optionally compare its SHA-256 digest with `SHA256SUMS.txt` from the same release.
174
+ 4. Run the installer, then launch **Driftless Bundle Photometry** from the Start menu.
175
+
176
+ The installer is per-user, supports clean uninstall through Windows Settings, and
177
+ does not require administrator access. Current installers are not code-signed, so
178
+ Windows SmartScreen may show an unrecognized-publisher warning. The application can
179
+ run the simulator and RWD read-only path, but the physical Thorlabs/controller path
180
+ must not be treated as validated until the documented Windows bench gates pass.
181
+
182
+ ### Conda environment for developers
183
+
184
+ Clone the repository and let `environment.yml` create the `dbf` environment plus an
185
+ editable install with GUI, test, lint, build, and release tools:
186
+
187
+ ```bash
188
+ git clone https://github.com/mohebi-n-associates/DriftlessBundlePhotometry.git
189
+ cd DriftlessBundlePhotometry
190
+ conda env create --file environment.yml
191
+ conda activate dbf
192
+ python -m pytest
193
+ ```
194
+
195
+ After pulling dependency changes, synchronize the existing environment with:
196
+
197
+ ```bash
198
+ conda env update --file environment.yml --prune
199
+ ```
200
+
201
+ ### PyPI installation
202
+
203
+ Inside an existing Python 3.11–3.13 environment, install the desktop application
204
+ from PyPI and launch it with:
205
+
206
+ ```bash
207
+ python -m pip install "driftless-bundle-photometry[gui]"
208
+ dbf --version
209
+ dbf --demo
210
+ ```
211
+
212
+ The distribution name is `driftless-bundle-photometry`, the short command and Conda
213
+ environment are `dbf`, and Python imports use `driftless_photometry`. The long
214
+ `driftless-photometry` command remains available. On macOS, use Conda or PyPI for the
215
+ simulator, replay, NWB, analysis, and GUI-demo paths.
216
+
217
+ ## Running developer workflows
218
+
219
+ Run a headless simulated acquisition:
220
+
221
+ ```bash
222
+ dbf --headless --duration 5 --raw
223
+ ```
224
+
225
+ Run the headless read-only RWD bridge from a validated settings-v2 file:
226
+
227
+ ```bash
228
+ dbf --rwd-settings path/to/rwd.settings.json --duration 60
229
+ ```
230
+
231
+ RWD must already be recording and listening on the host/port stored in that file.
232
+ DBF does not send hardware commands. It makes one connection for one session and
233
+ never reconnects automatically after a fault, because joining records across TCP
234
+ connections could hide a gap or changed device state.
235
+
236
+ Capture a checksummed exact-wire artifact during a physical bench run, inspect it,
237
+ and replay it unpaced through the production parser/recovery/NWB path:
238
+
239
+ ```bash
240
+ dbf --rwd-settings path/to/rwd.settings.json --duration 300 \
241
+ --rwd-wire-capture path/to/bench-001.rwd-wire
242
+ dbf --inspect-rwd-capture path/to/bench-001.rwd-wire
243
+ dbf --rwd-settings path/to/replay.settings.json \
244
+ --rwd-replay path/to/bench-001.rwd-wire
245
+ ```
246
+
247
+ Replay settings must preserve the capture's parsing scales, wavelengths, expected
248
+ machine, and channel/fiber mappings, but should use a new session ID and empty output
249
+ directory. Exact-wire captures can contain experimental data and must not be
250
+ committed to the repository.
251
+
252
+ Run the GUI demo:
253
+
254
+ ```bash
255
+ dbf --demo
256
+ ```
257
+
258
+ Recover all committed data from a complete or interrupted spool:
259
+
260
+ ```bash
261
+ dbf --recover-spool path/to/session.photometry-spool
262
+ dbf --recover-spool path/to/session.rwd-spool
263
+ ```
264
+
265
+ Inspect direct child spools without creating or removing files:
266
+
267
+ ```bash
268
+ dbf --inspect-spools path/to/output-directory
269
+ ```
270
+
271
+ Inspection recognizes native `*.photometry-spool` and RWD `*.rwd-spool` children,
272
+ verifies checksums, and reports source-specific counts plus completeness, invalid
273
+ times, system events, schema, and output-file count. It deliberately does not recurse
274
+ into unrelated directories. Successful recovery validates the complete
275
+ NWB set before removing the spool; add `--keep-spool` for forensic retention.
276
+ Recovery is idempotent and can resume if a process stopped after validating partials
277
+ or while promoting the multi-ROI set. Existing canonical files must match the spool
278
+ exactly and are never overwritten silently. Incomplete acquisitions are explicitly
279
+ marked in the NWB system event table. Legacy schema-v1 spools remain recoverable, but
280
+ the resulting invalid-time record identifies the per-frame host receipt and commanded
281
+ intensity provenance that those older spools never persisted.
282
+
283
+ The storage estimate uses configured duration, total frame rate, image dimensions,
284
+ raw-retention policy, enabled ROI count, and a 64 MiB reserve. CI correctness tests
285
+ exercise non-realtime simulator sessions at 300 frames/s trace-only and 60 frames/s
286
+ with raw 32 × 24 frames for one ROI. These small-fixture bounds test queue/data
287
+ integrity; they are not throughput claims for the CS505MU or any physical rig.
288
+
289
+ Run the release gates:
290
+
291
+ ```bash
292
+ python -m pytest --cov=driftless_photometry --cov-report=term-missing
293
+ python -m ruff check .
294
+ python -m ruff format --check .
295
+ python -m build
296
+ python -m twine check --strict dist/*
297
+ ```
298
+
299
+ The complete release procedure and one-time Trusted Publisher setup are in
300
+ [the release guide](docs/releasing.md).
301
+
302
+ See [the architecture](docs/architecture.md) and the synchronized agent contracts
303
+ in `AGENTS.md` and `CLAUDE.md`. The planned hardware wire contract is documented in
304
+ [the controller protocol](docs/controller-protocol.md). Development priorities,
305
+ dependencies, and phase exit criteria are maintained in [the roadmap](roadmap.md).
@@ -0,0 +1,51 @@
1
+ driftless_photometry/__init__.py,sha256=JiFLe2u0UlrfEt7wPfOV3Gy7nRo9ydOr--Ezp0PReZY,321
2
+ driftless_photometry/__main__.py,sha256=ctZbfzzWWjM6Cl2o6a-aMnQOe5SSsdroVSc3NMCa23s,68
3
+ driftless_photometry/acquisition.py,sha256=7vkRQ4CWBOeIdlHeJ4xkZ1-avhwuGTNfN-LDj4uEJmo,17491
4
+ driftless_photometry/cli.py,sha256=oDf4EVzaRIPuuChU1lITzq9jebeiNQ3GIB1LkDpJSUc,12660
5
+ driftless_photometry/config.py,sha256=SR_-YEILFMEYvuFXWVdDwOXDqYQCo_aeM7voi-SAvJ0,14038
6
+ driftless_photometry/desktop.py,sha256=KLTJvbmlfmpYfEDo7uzLTRxwXQWlKz0cNrZTjU2jhV4,1090
7
+ driftless_photometry/diagnostics.py,sha256=V5QRGHpRUGwuOctCckUc3J2zJ4lYnOCWuPC8MaSIgK8,1262
8
+ driftless_photometry/domain.py,sha256=VEzAxES68UFdQqwW0Kd8KPStPqzHlhBwdeHA9Dd-Rr0,5078
9
+ driftless_photometry/faults.py,sha256=K-YjiQui63SkpzWNm7k8c59tzwaD-wknqG3tk1b64k4,964
10
+ driftless_photometry/live_trace.py,sha256=UbCQmZTL5_cyW336m6po_HKSA4GBCz1QVsJHXmaS7lo,3654
11
+ driftless_photometry/provenance.py,sha256=Mq03d6_yXedUuaAWRlBdlgTaMp49FGQDxSXhHyoDrLE,2764
12
+ driftless_photometry/roi.py,sha256=8gM904uByot1FJye8EuW4Hdo8Mckvyg7__cd5zsBUs8,4397
13
+ driftless_photometry/settings.py,sha256=WTVXZWJGSxeUlSpf6DJgj2CV-oYf1t2q40yJh1iGrts,15145
14
+ driftless_photometry/state.py,sha256=5ueNf5a72SxjuObMxq24V-PEwk-IvXsGE8hiihLwcm8,1658
15
+ driftless_photometry/timing.py,sha256=sKWteMiLsGdn-s5TuEXv24PNbtKwuKK7d7gd-TZybpU,3198
16
+ driftless_photometry/gui/__init__.py,sha256=la7LdUfxMGuDMOLg0UL7RTFc902h6L8PsERXQZ-N4Fk,82
17
+ driftless_photometry/gui/app.py,sha256=wt6zqHejJJAOgPeIH_dRO8YIutPlyh3UWOdET5hflz4,908
18
+ driftless_photometry/gui/branding.py,sha256=jYpQHuJUaHpXVgSKUmTNrrrqBh77LlzsNv2WZJOO5fA,471
19
+ driftless_photometry/gui/main_window.py,sha256=svPWXUM9PtuDN1MU-26jewTozOITfYGFKuw36i6blM0,99678
20
+ driftless_photometry/gui/plot_interaction.py,sha256=l1JcCjqQX2s7FYMwzXy_wcIIJMVpmlaA8qCepwQhNts,3314
21
+ driftless_photometry/gui/trace_display.py,sha256=3RoX0sAYuo7JNKeeE2m4kJVo3h0GqCTakW9hlQ1vltQ,4405
22
+ driftless_photometry/gui/worker.py,sha256=p2RBTlbd6-1q07-z4vrXVhIQqiDYOG9C_kf_kR5Srdo,3495
23
+ driftless_photometry/gui/assets/__init__.py,sha256=RCK733cC69sUQedSkfn9yBB-yt9qw2PJDpj3IRc4cfQ,57
24
+ driftless_photometry/gui/assets/driftless-photometry.png,sha256=B4_zSGXN8-IGmEu2e-Ko6AkcADOm6u1KyfgMaIU0dzo,968032
25
+ driftless_photometry/hardware/__init__.py,sha256=_GXGNduouBjfZJtWTKNVHAIU3RiJ_Xt86OOkoSVmKx8,1049
26
+ driftless_photometry/hardware/base.py,sha256=ADoKueRSEDMPxpkLUiRcIvWmS0cYGj0LVO2mAbXwuJI,666
27
+ driftless_photometry/hardware/controller_protocol.py,sha256=DIDjxtMe9VEbQ7jWAEJaGhMFJ6LBBYduf9-enfKAiwk,6424
28
+ driftless_photometry/hardware/controller_serial.py,sha256=jd9JOd19VVwMH0kxuZj2gwU0apRRLU4K764mNLp0oZE,3840
29
+ driftless_photometry/hardware/simulator.py,sha256=SNlltxaEwCkyzXM9icN4jC4ZZuUY3xPbKhvWDIkpmt8,5588
30
+ driftless_photometry/hardware/thorlabs.py,sha256=SWp7EMyiEExTpPNDDY1RNd9CTH444bxZeQ6szRmhMik,1812
31
+ driftless_photometry/rwd/__init__.py,sha256=avpiDuAfHQ-YcrP7uL6iKVyEhPlnWEOSV9IEA69LbQE,1837
32
+ driftless_photometry/rwd/acquisition.py,sha256=_00p1TaaYVnPq5DjZErYqgS6a4HVX_QDaRYU-3lze2w,9743
33
+ driftless_photometry/rwd/capture.py,sha256=TvT6o8ziS-rWAx7G1NQPEinYRe0M54K-EOLNswRDcxA,18481
34
+ driftless_photometry/rwd/client.py,sha256=o1Qh1qpuQM26XI1zOKMa6PUFTHlO5V2_J-GVvAkRL3M,10889
35
+ driftless_photometry/rwd/domain.py,sha256=jnTIny5GfnOLXKH6-g42t4125oEo7CHY-yNnkkdF5ow,5049
36
+ driftless_photometry/rwd/protocol.py,sha256=DDWoVtawQljUZD3mCmqksUyoKrH35gC01J6m6mqqMmQ,11451
37
+ driftless_photometry/rwd/timing.py,sha256=CAXKv7rbI1KTinkhhOkRsck4-YIoQeEOuL_V0XbGX2Y,10171
38
+ driftless_photometry/storage/__init__.py,sha256=skzT8Rh_WJzcHUP7Y19EHKG-t31RcI1czSSm9f-r0c8,2041
39
+ driftless_photometry/storage/capacity.py,sha256=AlE6brimw-6lfF43cHqfLHgYr7kWCXbNZdToStSXEhQ,5754
40
+ driftless_photometry/storage/frames.py,sha256=4AFHb_sh3f3kY1qBTXDsfiYfSqgXRC2ROhHcSgBGu9s,1087
41
+ driftless_photometry/storage/nwb.py,sha256=Hxxvnd5IJ-Cq2FZV06j_kcqIwD7NIa40_HOxWvsC2kc,47835
42
+ driftless_photometry/storage/recovery.py,sha256=uMd5VfP9IjDBM6zrq6gmW0zlOQtOW06AyFE-pdu5z-k,4361
43
+ driftless_photometry/storage/rwd_nwb.py,sha256=8TWKTj32Aeh2IaX_ho4F41QOQZWGo1NoJWRmIjAcKJQ,32050
44
+ driftless_photometry/storage/rwd_recovery.py,sha256=y0kvGsUnCT8gnl61Bp2_aSyaL8k-X00BoTKYkEzzEsQ,3881
45
+ driftless_photometry/storage/rwd_spool.py,sha256=sa4qufpsIFHmocFMiMxPjUG-bUg87UeOT1pQ08ZHhTw,23429
46
+ driftless_photometry/storage/spool.py,sha256=O6iTDOkvFF_5jidtJhsqT1_1UeN4a8LAap3S7IF4Rv0,27448
47
+ driftless_bundle_photometry-0.2.1.dist-info/METADATA,sha256=mXqGI8H64zywHt0O3AcUNhp9zpKSwT76eX6FgAAt6ug,15113
48
+ driftless_bundle_photometry-0.2.1.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
49
+ driftless_bundle_photometry-0.2.1.dist-info/entry_points.txt,sha256=X30Htb92rCOZvJE5j2T-J5teNUk0Mc0BMNcBeqRFz4g,107
50
+ driftless_bundle_photometry-0.2.1.dist-info/licenses/LICENSE,sha256=OaPdYunm8rR02fJ-R_7m5i7FiziNUOxqgXTiDUbiRtA,1097
51
+ driftless_bundle_photometry-0.2.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ dbf = driftless_photometry.cli:main
3
+ driftless-photometry = driftless_photometry.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Driftless Bundle Photometry contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,10 @@
1
+ """Driftless Bundle Photometry acquisition package."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("driftless-bundle-photometry")
7
+ except PackageNotFoundError: # pragma: no cover - source tree without installation
8
+ __version__ = "0+unknown"
9
+
10
+ __all__ = ["__version__"]
@@ -0,0 +1,3 @@
1
+ from driftless_photometry.cli import main
2
+
3
+ raise SystemExit(main())