Goal
Promote timing_source from a dependent attribute to part of the PsychophysicalKernel primary key, remove the mixed value, and rename nidaq to nidq.
A kernel row is one fit from one clock. Comparing NIDQ timing against Bpod timing is then a query over two rows, not a stored third row.
Today timing_source sits below the --- divider, so only one row can exist per analysis set x subject x condition x fit config, and it carries whichever clock happened to populate it. The same fit config under two clocks collides instead of coexisting, and mixed exists as a workaround for not being able to store the pair.
Plan
labdata_plugin/analysisschema.py - move timing_source above the --- divider in PsychophysicalKernel, so the key becomes BehaviorAnalysisSet x Subject x trialset_description x PsychophysicalKernelFitConfig x timing_source. Set the enum to exactly enum('nidq', 'bpod').
labdata_plugin/analysisschema.py - add timing_source to key_source so populate produces one row per available timing source rather than whichever one the loader returned.
src/behavior_analyses/kernel_timing.py - fetch_pooled_kernel_inputs takes the requested timing source as an argument and raises when the selected trialsets cannot supply it. It must not infer a source, and must not silently pool across sources. Update the value it returns from nidaq to nidq.
- Grep the repo for
nidaq and update the remaining references.
- Add a test that fits one session under both timing sources and asserts two distinct rows sharing a fit config.
Do not touch: the fit math in src/behavior_analyses/kernels.py, the PsychophysicalKernelFitConfig contents, or the psychometric tables. Do not add any table, attribute, or row that stores a NIDQ-versus-Bpod difference; that is a query, not a measurement.
Validation
uvx ruff check .
uvx ruff format --check .
- Run the test suite under Python 3.11. Python 3.10 hits the known SciPy
_spropack import problem locally.
- Populate one GRB006 session under both timing sources and confirm two rows differing only in
timing_source.
Expect: two rows, clean lint, tests pass.
Done when
Notes
- This is a key change, so the table must be dropped and re-declared. Check the live row count and any existing
mixed rows first. The nidaq to nidq rename comes free with the re-declaration.
- Populating requires the lab DataJoint connection, so the live validation step cannot run in a cloud agent.
- Context: ephys PR #35 removed the duplicate session-level kernel on 2026-08-03, making this table the single canonical kernel surface.
Goal
Promote
timing_sourcefrom a dependent attribute to part of thePsychophysicalKernelprimary key, remove themixedvalue, and renamenidaqtonidq.A kernel row is one fit from one clock. Comparing NIDQ timing against Bpod timing is then a query over two rows, not a stored third row.
Today
timing_sourcesits below the---divider, so only one row can exist per analysis set x subject x condition x fit config, and it carries whichever clock happened to populate it. The same fit config under two clocks collides instead of coexisting, andmixedexists as a workaround for not being able to store the pair.Plan
labdata_plugin/analysisschema.py- movetiming_sourceabove the---divider inPsychophysicalKernel, so the key becomesBehaviorAnalysisSetxSubjectxtrialset_descriptionxPsychophysicalKernelFitConfigxtiming_source. Set the enum to exactlyenum('nidq', 'bpod').labdata_plugin/analysisschema.py- addtiming_sourcetokey_sourcesopopulateproduces one row per available timing source rather than whichever one the loader returned.src/behavior_analyses/kernel_timing.py-fetch_pooled_kernel_inputstakes the requested timing source as an argument and raises when the selected trialsets cannot supply it. It must not infer a source, and must not silently pool across sources. Update the value it returns fromnidaqtonidq.nidaqand update the remaining references.Do not touch: the fit math in
src/behavior_analyses/kernels.py, thePsychophysicalKernelFitConfigcontents, or the psychometric tables. Do not add any table, attribute, or row that stores a NIDQ-versus-Bpod difference; that is a query, not a measurement.Validation
_spropackimport problem locally.timing_source.Expect: two rows, clean lint, tests pass.
Done when
timing_sourceis part of the primary keynidqandbpodNotes
mixedrows first. Thenidaqtonidqrename comes free with the re-declaration.