Skip to content

Port the vhlab-library-matlab functions NDI-matlab depends on: 7 missing, 2 already done #6

Closed

Description

@stevevanhooser

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:

  1. Collected the 892 function names defined in vhlab-library-matlab.
  2. Dropped the 32 also defined in NDI-matlab or vhlab-toolbox-matlab, so a name that resolves elsewhere is not attributed to the library.
  3. Scanned NDI-matlab's .m sources for word-boundary call sites, separating free calls from obj.method(...) calls.
  4. Hand-filtered the result. The raw scan flagged delete, extract, parameters, reference, tuning_curve, thresholds, spikedata, clock and setparameters — all MATLAB builtins, NDI's own function definitions, or local variables, not library calls.
  5. Checked what is already ported here by symbol, not filename — which matters, since findassociate and friends live inside vhlib/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:

  • @measureddata and its analysis objects — associate, disassociate, findassociate, getassociate, numassociates, set_intervals, spikedata, contextmenu, repairhandles, verifywhere, delete. Four of these are already ported inside vhlib/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

  1. neural_response_significance — leaf, ~15 lines, unblocks NDI-python #134.
  2. get_intervals / get_data / set_intervals on the existing MeasuredData.
  3. Decide on getstimscript (which repo's definition is authoritative).
  4. 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

https://claude.ai/code/session_01CqrNhfGnhKGcQvNiP2LNXK

Activity

  1. stevevanhooser commented on Sep 2, 2026

    @stevevanhooser
    ContributorAuthor

    Update on the open questions, with #8 implementing what they unblock.

    getstimscript is 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 only vhlab-library-matlab/StimulusDecoding/getstimscript.m is a free function taking a directory name. The other two — vhlab-toolbox-matlab/file/@dirstruct/getstimscript.m and this library's OldSpikeImporters/@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 as vhlib.StimDecode.getstimscript, with the reasoning in the bridge decision_log.

    It returns saveScript as the .mat loader produces it. MATLAB writes it as a NewStim stimscript object, 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, on MeasuredData and as a dict/.mat-struct-tolerant module function, since importMeasuredDataCells.m:23 calls it on cells read from an experiment file. set_intervals came with it.
    • getparameters — not this repository's function. The only call site is NewStimStims.m:37, getparameters(get(ss,i)), where ss is the stimscript returned by getstimscript; both getparameters and get are NewStim methods there, not @autocluster / @windowdiscriminator methods. 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 @measureddata base-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) and vhintan_clusternameref (gui.m:154) all land in the OldSpikeImporters / vhintan_* lineage. vhintan_clusternameref in particular drives cluster_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 in downstream_requirements in 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_clusternameref if it goes that way.


    Generated by Claude Code

  2. added a commit that references this issue on Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions