Repository navigation
Port the vhlab-library-matlab functions NDI-matlab depends on: 7 missing, 2 already done #6
Description
Companion to #4 (the bridge convention). That issue is about recording the mapping; this one is the concrete work list it would have made obvious.
NDI-python is porting NDI-matlab, and NDI-matlab calls into vhlab-library-matlab directly. Every such call is a function that has to exist here before the corresponding NDI-python port can complete. One is blocking right now (Waltham-Data-Science/NDI-python#134).
How this list was derived
Not from the existing table alone. NDI-matlab/src/ndi/docs/developer_notes/vhlabLibraryMatlab.md lists eleven names, but it mixes genuine calls with file-format conventions and does not say what is already ported, so I re-derived it:
- Collected the 892 function names defined in
vhlab-library-matlab. - Dropped the 32 also defined in NDI-matlab or
vhlab-toolbox-matlab, so a name that resolves elsewhere is not attributed to the library. - Scanned NDI-matlab's
.msources for word-boundary call sites, separating free calls fromobj.method(...)calls. - Hand-filtered the result. The raw scan flagged
delete,extract,parameters,reference,tuning_curve,thresholds,spikedata,clockandsetparameters— all MATLAB builtins, NDI's own function definitions, or local variables, not library calls. - Checked what is already ported here by symbol, not filename — which matters, since
findassociateand friends live insidevhlib/md/, not in files of their own.
Tier 1 — free functions, port these
| function | MATLAB path | status |
|---|---|---|
neural_response_significance |
AnalysisTools/ResponsesFitsIndexesPlotting/response_stats/ |
missing — blocking |
vhintan_importcells |
SpikeDataExtraction/SpikeImporters/VH-Intan/ |
missing |
vhintan_clusternameref |
SpikeDataExtraction/Intan_VHLAnalogInput_Analysis/ |
missing |
cellname2nameref |
AnalysisTools/CellDatabaseManagement/ |
✅ vhlib/CDM/cellname2nameref.py |
read_stimtimes_txt |
StimulusDecoding/ |
✅ vhlib/StimDecode/read_stimtimes_txt.py |
Start with neural_response_significance — it is a leaf and it unblocks a port today
ndi.app.oridirtuning.calculate_oridir_indexes cannot be finished without it (Waltham-Data-Science/NDI-python#134; the tuning-curve half shipped in #145 with the index half explicitly deferred to this).
It has no library dependencies at all — checked, not assumed. It needs colvec (already in vhlab-toolbox-python) and anova1 (MATLAB Statistics Toolbox → scipy.stats.f_oneway). The whole function is ~15 lines:
function [sigp,sigpb] = neural_response_significance(resp)
% SIGP - P value of an ANOVA across all stimulus conditions.
% SIGPB - the same, including the blank if available; identical to SIGP if not.sigp is a one-way ANOVA over the groups in resp.ind; sigpb adds resp.blankind as one more group. oridirtuning.m:206 maps them as visual_response_anova_p = sigpb, across_stimuli_anova_p = sigp.
Tier 2 — method calls, so the class is what is needed
These appear as obj.method(...), so porting the bare function name would be wrong.
| call | class | MATLAB path | status |
|---|---|---|---|
get_intervals |
@measureddata |
AnalysisTools/MeasuredData/ |
class ported, method missing |
get_data |
@cksfiltereddata, @cksmultipleunit |
SpikeDataExtraction/SpikeImporters/OldSpikeImporters/ |
missing |
getparameters |
@autocluster, @windowdiscriminator |
SpikeDataExtraction/SpikeImporters/OldSpikeImporters/ |
missing |
vhlib/md/measureddata.py already has MeasuredData with associate, findassociate, getassociate, numassociates, disassociate, associates2struct and update — but not get_data, get_intervals or set_intervals. Adding those three to the existing class is likely the smallest useful next step after Tier 1.
Both get_data and getparameters have several MATLAB definitions across different @class folders, so the porting decision needs to name which class NDI-matlab's call site actually reaches. All three call sites are in NDI-matlab/src/ndi/+ndi/+setup/+conv/+vhlab/importMeasuredDataCells.m and +ndi/+daq/+metadatareader/NewStimStims.m.
A name to be careful with: getstimscript
vhlabLibraryMatlab.md lists it, and my scan excluded it — because it is defined in both vhlab-library-matlab/StimulusDecoding/ and vhlab-toolbox-matlab. Whichever is on the MATLAB path first wins, so which one NDI-matlab actually calls is genuinely ambiguous from the source. That needs a human answer before porting, and it is exactly the kind of thing a bridge decision_log (#4) exists to record once.
Transitive dependencies
BFS from the nine call sites pulls in 17 more library functions, almost all in two clusters:
@measureddataand its analysis objects —associate,disassociate,findassociate,getassociate,numassociates,set_intervals,spikedata,contextmenu,repairhandles,verifywhere,delete. Four of these are already ported insidevhlib/md/.- The old spike importers —
cksmultipleunit,cksmeasureddata,get_data_par,loaddata,vhintan_loadcell.
Worth noting before anyone starts on Tier 2: the second cluster lives under OldSpikeImporters/, and vhintan_importcells reaches it. Whether that whole lineage should be ported at all, or whether NDI-matlab's two call sites are themselves legacy, is a decision rather than a task — NDI-matlab/+ndi/+gui/gui.m (the vhintan_* caller) and importMeasuredDataCells.m are both conversion/legacy paths.
Not calls — conventions only
vhlabLibraryMatlab.md also lists testdirinfo, vhintan_channelgrouping, vhintan_intan2spike2time and vhspike2_channelgrouping. Its own Comment column marks these "Reference to file format convention" — NDI-matlab names them in strings or comments rather than calling them. They need no port, and are listed here so the next person does not re-derive that.
Suggested order
neural_response_significance— leaf, ~15 lines, unblocks NDI-python #134.get_intervals/get_data/set_intervalson the existingMeasuredData.- Decide on
getstimscript(which repo's definition is authoritative). - Decide whether the
OldSpikeImporters/vhintan_*lineage is in scope at all.
If #4 lands first, each of these gets a bridge entry as it is ported, and the "already done" column above stops needing to be re-derived by scanning.
🤖 Generated with Claude Code
Activity
stevevanhooser commentedon Sep 2, 2026
Update on the open questions, with #8 implementing what they unblock.
getstimscriptis needed, and it is this repository's definition (step 3 of the suggested order). It is not actually a path-order question: the name is defined three times, but onlyvhlab-library-matlab/StimulusDecoding/getstimscript.mis a free function taking a directory name. The other two —vhlab-toolbox-matlab/file/@dirstruct/getstimscript.mand this library'sOldSpikeImporters/@cksdirstruct/getstimscript.m— are class methods,GETSTIMSCRIPT(DS, THEDIR), dispatched on a dirstruct or cksdirstruct object. NDI-matlab's call sites (+ndi/+daq/+metadatareader/NewStimStims.m:35,+ndi/+setup/+daq/+reader/+mfdaq/+stimulus/vhlabvisspike2.m:116) both pass a char path, so they reach the free function whatever is first on the path. Ported in #8 asvhlib.StimDecode.getstimscript, with the reasoning in the bridgedecision_log.It returns
saveScriptas the.matloader produces it. MATLAB writes it as a NewStimstimscriptobject, so anything that reads stimulus parameters off it still needs a NewStim port — the port settles the file, the variables and the failure modes, not the object model.Tier 2 also moved, and two rows of its table were wrong. I re-derived the call sites against NDI-matlab
18ff517:get_intervals— ported in Port getstimscript and the measureddata interval accessors (#6) #8, onMeasuredDataand as a dict/.mat-struct-tolerant module function, sinceimportMeasuredDataCells.m:23calls it on cells read from an experiment file.set_intervalscame with it.getparameters— not this repository's function. The only call site isNewStimStims.m:37,getparameters(get(ss,i)), wheressis the stimscript returned bygetstimscript; bothgetparametersandgetare NewStim methods there, not@autocluster/@windowdiscriminatormethods. That call site waits on a Python NewStim, and nothing in this repository unblocks it.get_data— the call site (importMeasuredDataCells.m:61) passes cells from an experiment file, so it reaches a data-bearing subclass, not the@measureddatabase-class bounds check. Porting the base method alone returns nothing that caller can use.Step 4 is still a decision, and I have not made it.
get_data,vhintan_importcells(+ndi/+gui/gui.m:150) andvhintan_clusternameref(gui.m:154) all land in theOldSpikeImporters/vhintan_*lineage.vhintan_clusternamerefin particular drivescluster_spikewaves_gui— an interactive spike-sorting GUI that writes cluster files back into the recording directories — so a faithful port is a GUI question, not a function port. Whether that lineage is in scope at all is yours to call; it is recorded as open indownstream_requirementsin the top-level bridge.That bridge section now lists every NDI-matlab call into this library with its call site and status, so the "already done" column here should not need re-deriving by scanning again.
Remaining after #8: the OldSpikeImporters decision, and then
get_data/vhintan_importcells/vhintan_clusternamerefif it goes that way.Generated by Claude Code
Merge pull request #8 from VH-Lab/claude/issue-6-getstimscript-mvx456