LUMETRIC Architecture Diagrams
1. High-Level Acquisition Lifecycle
flowchart TD
A([Script Start]) --> B[Build GUI\nJFrame + 3 Tabs]
B --> C{Auto-load\nlast config?}
C -- yes --> D[config.loadFromFile\nupdateSettingsDisplay]
C -- no --> E[GUI shown\nframe.setVisible]
D --> E
E --> F([User: OK - Start Acquisition])
F --> G[validateSequence]
G -- fail --> E
G -- pass --> H[captureFromGUI\nsnapshot all GUI state into\nconfig.acqSettings]
H --> I[frame.dispose]
I --> J[[Background Thread]]
J --> K[createExperimentFolder\nExperiment_timestamp/images/]
K --> L{Visualization\nneeded?}
L -- yes --> M[setupVisualizationROIs\nsnap image, crop half if Spatial\nuser draws ROIs, save RoiSet.zip]
L -- no --> N
M --> N[exportTableToCSV\nAquisitionSettings.csv\nAquisitionSettings_Arduino.csv]
N --> O[[EDT: createInlineAcquisitionWindow\nbuild chart panels, send table to Arduino]]
O --> P{Mode?}
P -- Circular Buffer\nhardware triggered --> Q[[runCircularBufferAcquisition]]
P -- Simple Snap\nor Advanced Sequence --> R[[runAcquisition]]
Q --> S([User: Quit])
R --> S
S --> T[Send byte 66 to Arduino\nstop trigger]
T --> U[exportGraphDataToCSV\none CSV per active graph]
U --> V[exportEventTimesToCSV\nEvent-Data.csv]
V --> W{convertToStack?}
W -- yes --> X[convertTiffsToStack\nbuild Image_Stack.tif\ndelete individual TIFFs]
W -- no --> Y
X --> Y([Done])
2. Circular Buffer Acquisition Path (Hardware TTL)
flowchart TD
A([runCircularBufferAcquisition]) --> B[setupCircularBuffer\n75% JVM max memory]
B --> C[Pre-arm cleanup\nbyte 66 → stop Arduino\nsetAutoShutter false\nclearCircularBuffer]
C --> D[setConfig cameraTriggerConfig\nsleep 1500ms]
D --> E[startSequenceAcquisition\n1000 frames, DCAM mode]
E --> F[sleep 500ms\nflush stale frames]
F --> G[Send byte 61\nArduino starts TTL pulses]
G --> H{Frame\navailable?}
H -- yes --> I[popNextTaggedImage\nconvert to ImageProcessor]
I --> J[saveImageAsTiff\nFrame_NNNNN.tif]
J --> K[measureROIs\nmean intensity per ROI]
K --> L[buildDataRow\nframe, timestamp, roi values]
L --> M{250ms\nthrottle?}
M -- yes --> N[updateLiveView\nscaled image + ROI overlay]
M -- no --> O
N --> O[updateGraphs\nsee Graph Update detail]
O --> H
H -- sequence done\nor running=false --> P
P[byte 66 → stop Arduino\nrelease-kicker pulse\nstopSequenceAcquisition\nsetConfig cameraSnapConfig\nsetAutoShutter true]
P --> Q{convertToStack?}
Q -- yes --> R[convertTiffsToStack]
Q -- no --> S
R --> S([acqFrame.dispose])
3. Software Snap Acquisition Path
flowchart TD
A([runAcquisition]) --> B{useSimpleSnapMode?}
B -- Simple Snap --> C[setConfig cameraSnapConfig\nsetAutoShutter true]
C --> D{running?}
D -- yes --> E[mm.live.snap\nblocking]
E --> F[saveImageAsTiff]
F --> G[measureROIs]
G --> H[buildDataRow]
H --> I[updateLiveView\nthrottled 250ms]
I --> J[updateGraphs\nthrottled 250ms]
J --> K[sleep\nframeInterval - elapsed ms]
K --> D
D -- stopped --> L[convertTiffsToStack\nif requested]
L --> M([acqFrame.dispose])
B -- Advanced Sequence --> N[Walk sequenceRows\nby currentStepIndex]
N --> O[Set channel + exposure\nvia setConfig]
O --> P[snap N frames loop\nsame as Simple Snap]
P --> Q{loopGoto\nor next row?}
Q -- continue --> N
Q -- done --> L
4. Graph Update Logic
flowchart TD
A([updateGraphs\nframe, time, roiValues]) --> B{For each\ngraph row}
B --> C[shouldProcessFrame\ncheck: every / odd / even\n/ custom interval + offset]
C -- skip --> B
C -- process --> D{graphType?}
D -- Intensity --> E[append roiValues\ndirectly to XYSeries\nvia SwingUtilities.invokeLater]
D -- Frame Ratio\ne.g. Ch1/Ch2 --> F{N-frame\ncycle?}
F -- every 2nd\nodd/even --> G[cacheFrameData\nstore in even or odd slot]
G --> H{Both slots\nfilled?}
H -- no --> B
H -- yes --> I[calculateFrameRatio\nnumerator ROIs / denominator ROIs]
I --> J[append ratio to XYSeries]
F -- N-frame\ncycle --> K[cacheFrameDataAtPosition\np1...pN]
K --> L{All N positions\nfilled?}
L -- no --> B
L -- yes --> I
D -- Split Ratio\nSpatial mode --> M[calculateSpatialRatio\nsplit roiValues into\nsource half / mirror half]
M --> N[compute per-pair ratio\nUp/Down, Left/Right etc.]
N --> O[append to XYSeries\nvia SwingUtilities.invokeLater]
E --> B
J --> B
O --> B
flowchart LR
subgraph MainWindow["Main Window (JFrame)"]
subgraph T1["Tab 1: Setup Configuration"]
LC[loadConfigButton\n→ config.loadFromFile\n→ updateSettingsDisplay]
RC[reloadConfigButton\n→ config.loadFromFile]
SC[saveConfigButton\n→ config.saveToFile]
HB[readFromHubButton\n→ config.loadFromHub]
end
subgraph T2["Tab 2: Acquisition Settings"]
ADD[addButton\n→ tableModel.addRow]
REM[removeButton\n→ tableModel.removeRow]
VAL[validateButton\n→ validateSequence]
SAV[saveSettingsButton\n→ saveSettingsToCSV]
LOD[loadSettingsButton\n→ loadSettingsFromCSV\n→ parseCSVLine]
FLD[selectFolderButton\n→ update prefs + label]
OK[okButton\nOK - Start Acquisition]
end
subgraph T3["Tab 3: Data Visualization"]
VIZ[vizStartButton\nOK - Start Acquisition\n same path as okButton]
PMC[processingModeCombo\n→ vizTableModel.setProcessingMode\n→ typeEditor.setProcessingMode]
SAX[splitAxisCombo\n→ repopulate roiSourceCombo\n→ typeEditor.setProcessingMode]
RSC[roiSourceCombo\n→ typeEditor.setProcessingMode]
end
end
OK --> ACQ
VIZ --> ACQ
subgraph ACQ["Acquisition Window (inline JFrame)"]
EVT[eventButton\n→ add ValueMarker to plots\n→ log timestamp]
LSW[loopSwitchButton\n→ send byte 67 to Arduino]
RZ[resetAllButton / resetXButton\n→ chart.restoreAutoBounds]
QT[quitButton\n→ byte 66 to Arduino\n→ exportGraphDataToCSV\n→ exportEventTimesToCSV\n→ acqFrame.dispose]
end
subgraph ROIWin["ROI Setup Mini-Window"]
DONE[doneButton\n→ lock.notifyAll done=true]
CNC[cancelButton\n→ lock.notifyAll cancelled=true]
end