Repository navigation
DAQ light safety fixes (main stays 0.2.7-DEV) - #94
Merged
Merged
Conversation
… add lights_off CrystaLaser, VortranLaser and DaqTrLight no longer record a light off when the switch-off failed, no longer light through setpower while recorded off, and save the requested level in volts. Failed writes throw; lights_off switches every light off and then raises every failure. Named-channel and daq keywords are additive. No hardware run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n stated Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s keep 1.0 V; panel and export fixes Review round. light_on after light_off stays at 1.0 V unless setpower ran while off, so no working sequence changes. A textbox entry commands once even when the slider does not move. export_state reads the DAQ outside the lock. gui(::LightSource) returns its Screen again. Caller-supplied properties are left alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… section, known issues Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d enable; panels poll the driver Main review of PR 94. is_on reports; line_enabled gates the line, so neither fault shows on any failure walk. Panels follow a light changed from another window. PIStage moves throw when refused, stage step boxes refuse a non-positive or non-finite step, and a fresh light exports NaN. CHANGELOG gains a Callers list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…I Home is guarded Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ailed second light_on Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… in this PR Keith: we accumulate in the dev version, then decide when to make a tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uts, save_h5, MCL returns, stale stage position Every confirmed bug gets fixed (Keith, relayed 2026-11-03), so the known issues PR 94 carried go into it: - DCAM4Camera: failed exposure, width and height read-backs throw, in the normal constructor too, instead of taking 0. - ThorCamCSCCamera: a poll timeout returns nothing from getlastframe and throws in capture and sequence, never an all-zero frame; the timeout follows the exposure unless set explicitly (keyword, setter or field); a refused timeout write keeps the accepted value. - save_h5: snapshots what it writes before returning; writes in place as before; every task failure logs once and rethrows; no partial file after a failure (a file it created is removed, an existing one truncated to zero bytes); the path is anchored once at call time. - MCLStage: negative Madlib returns throw and keep cached positions and ranges. - Stage export_state reads the position at save time when connected and adds position_fresh; a failed read warns and exports the last-read values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A ThorCamCSCCamera capture or sequence whose frame wait times out now throws (PR 94); the panel's Capture and Sequence buttons log it and the window keeps working. Admiral's caller check, 2026-11-03. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…est assumed POSIX .. - csc_failures.jl: the refused-timeout testset captured from a default 1440 x 1080 camera while the fake SDK holds an 8 x 6 frame, so the copy read past the buffer (Windows: access violation; Linux read it silently). The camera now states the fake's sensor. - h5_saving.jl: Windows resolves .. in the path text, so missing\..\frames.h5 anchors to the directory; the expectation follows the platform. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An attribute value HDF5 cannot store fails the save after the file exists, so the removal of a new file, the truncation of an existing one, and the removal of a symlink's new target are tested on Windows too, where the file-size-limit tests are skipped (admiral, 2026-11-03). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…spath On Windows ispath is true for a symlink whose target does not exist yet, so a failed save through such a link emptied the new target instead of removing it (found by the hosted Windows run). h5_landing_path follows each link's text from the link's directory; whether that file existed decides removal or truncation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DAQ light safety fixes into
main.mainstays0.2.7-DEV: this is not a release, andTagOnMergeskips a-DEVmerge. The entries sit under[Unreleased]in the CHANGELOG. When to tag 0.2.7 is a separate decision (Keith, 2026-11-03: "we accumulate in the dev version, then decide when to make a tag").Why
A review on 2026-11-02 found that the DAQ voltage lights on the adaptive microscope can report a laser off while it emits, and light the 561 nm laser through
setpowerwhile the driver says off. This PR fixes both, and every other confirmed item from that review, plus a stale stage position found in real files (Keith's rule, relayed 2026-11-03: a bug confirmed with a valid input is fixed whether or not lab code calls it).No instrument loads this code. The adaptive microscope pins
v0.3.0-rc4, and no release candidate follows it (Keith, 2026-11-02: release candidates are for Ship of Tools only). It gets these fixes by moving to a released main version. That move needs MicroscopeAdapt to drive its 642 nm laser through themodulatorfield and to handle the new errors. Its 642 MOD IN is on a Triggerscope DAC, so the move also waits for a Triggerscope modulator (branchtriggerscope-modulator) and the Triggerscope fixes (#92), unless the cable goes back to an NI output.What changes
CrystaLaser,VortranLaser,DaqTrLightinitialize,light_off,shutdown) recordsis_on = true: off cannot be claimed.is_onreports, and a newline_enableddecides whether a level goes to the line: it is set only by a successfullight_on.setpowerotherwise stages the level for the nextlight_on. Without a staged level,light_onwrites 1.0 V as it always did.shutdownandinitializeclear a staged level.level_requested, never inproperties.power, because MicroscopeAdapt writes a percent there. It readsNaNuntil something is requested.export_statereports it in volts, withpower_requestedadded.setpowerwith NaN or an out-of-range value throwsArgumentError. One lock per light serializes each write and record.initializewrites 0 V on the Crysta and the DaqTrLight. New keywordsdaq,channel,ao_channel,do_channel.lights_off(lights)is new and exported: it attempts every light, then throws oneLightsOffErrornaming each failure.Light panels work in the light's own unit and range, show a refused command, and poll the driver every 0.5 s, so a panel follows a light changed from another window. Opening a panel issues no command, and a poll never commands.
Also:
PIStagemoves throw whenPI_MOVrefuses and do not record the target, with the stage panel catching and restoring; stage step boxes refuse a non-positive or non-finite step; the camera panel menus work;ThorCamCSCCameraandMLSLMgainexport_state(attributes only);roi_originis recorded.Drivers and saving:
DCAM4Camera: a failed exposure, width or height read-back throws, in the normal constructor too, instead of taking 0.ThorCamCSCCamera: a poll timeout returnsnothingfromgetlastframeand throws incaptureand sequences, never an all-zero frame. The timeout follows the exposure unless set explicitly (constructor keyword, setter or field); a refused timeout write keeps the accepted value.save_h5: copies what it writes before returning; writes in place as before (overwrite unchanged); every failure in the task logs@erroronce and rethrows, sowaitthrows; no partial file after a failure (a file the save created is removed, an existing one is truncated to zero bytes in place); the path is anchored once at call time.MCLStage: negative Madlib returns throw and keep the cached positions and ranges.export_state(PIStage,MCLStage,N472,MCS2Stage, simulated stages) reads the position at save time when connected and addsposition_fresh; a failed read warns and exports the last-read values. A read never moves a stage.Callers of the CSC change (each program's session, from its code): MicroscopeControl's live view already skips
nothing; MicroscopeAdapt reaches a CSC only from four legacy calibration tools on a side branch (not run on quickbeam); MicroscopeSeqSR has no CSC; MicroscopeMinFlux's main has no MicroscopeControl use, and student scripts on a side branch would now raise instead of using a zero frame. Not breaking: a zero frame on a timeout was fabricated data.Memory during a save (the snapshot doubles it while writing): quickbeam 127.1 GB; the largest
save_h5file on record is one 43.0 GB stack (100,000 frames of 840 x 256, 2025-07), 86.0 GB at the peak plus 12.3 GB for the running program, which fits; today's sequences are 5 to 400 frames. The longest full-sensor stack that fits falls from about 10,800 to about 5,400 frames. The SeqSR PC (31.9 GB) and MINFLUX save no images throughsave_h5.Windows:
h5_saving,csc_failures,stage_exportsanddriver_readbackon hostedwindows-latestat this head, Julia 1.13.3: 768 pass, 0 fail, 3 skipped (Linux-only failure injection; a cross-platform failed-save test passed). Branchwincheck(never merged) holds the workflow. The Windows runs found a CSC test reading past its fake frame, a POSIX-only path expectation, and one real fault: on Windowsispathis true for a dangling symlink, so a failed save through it emptied the new target; the save now follows link text to find the file it lands on.Callers
light_off,setpowerandinitializenow throw. Teardown moves tolights_off.setpower(2.5); light_onended at 1.0 V and now ends at 2.5 V. Asetpowerwith nolight_onmoved the line and now moves nothing.propertiesare V and the voltage range, not mW and 0-100. Savedpower,min_powerandmax_powerare volts.Evidence
A metadata harvest of 2,350 real HDF5 files (1,041 with driver state on two instruments), the NAS logs, a survey of MicroscopeAdapt's call sites, and DAQmx.jl's source. No hardware was touched.
setpowerlights the 561 while offpowerreads 0.0 mW while MicroscopeAdapt recorded 15.DCAMERR_TIMEOUTsave_h5The first four are real code defects that have not appeared in saved files, which is a different finding from not being real. Each is reproduced by a test on a valid input that fails at
c9d66a1and passes here.Tests: every three-step failure walk of the commands, on all three lights, from a dark line and a line left high: 1,500,282 walks show no light emitting while the driver says off, and no emission rising except on
light_on. The suite keeps every two-step walk and a fixed three-step sample. The fakeDAQnever reaches DAQmx. Reviews: Codex over the diff, then main's review of record (2 must fix, 7 should fix, all taken), then Codex over the fixes: merge as is. The five driver and saving fixes went through seven Codex review rounds;save_h5first used a temporary file and a rename, and each round found another way a replacement differs from an in-place write (file modes, symlinks, sticky directories, owners and ACLs, hard links), so it writes in place as before.Tradeoffs
setpowerwhile off gives no light on the 561 and the lamp;setpower(2.5); light_onreads the 2.5 V level;light_offwith the DAQ unplugged throws and the panel says on; restarting with the 561 left lit goes dark atinitialize;lights_offwith one line unplugged darkens the other lights.deletetaskis not retained. It is loud andis_onstays true. DAQmx.jl's finalizer retries the clear at garbage collection, so the operator's steps areGC.gc(),light_off, then restart Julia, whereinitializewrites 0. Whether the channel stays reserved at all is untested on hardware.initializeon a light with no DAQ channel now throws, so a system's startup stops on a host with no DAQ.setpowerdarkens the light, so a transient error during a run ends that light's emission on purpose.light_onafterlight_offwrites 1.0 V.🤖 Generated with Claude Code