Data IO flow and multi-test support
This document captures the assumptions shared between the data containers, dataloaders, and CLI entry points. Refer to it when wiring a new dataset or troubleshooting evaluation.
Containers
MoviesTrainTestSplitstores the continuous training movie plus named test stimuli intest_dict. Provide either a single test array (it will automatically become{"test": array}) or a dictionary such as{"frozen_a": array_a, "frozen_b": array_b}.ResponsesTrainTestSplitmirrors that structure viatest_dictfor the averaged test responses andtest_by_trial_dictfor per-trial traces (shapetrials × neurons × time). When only one test stimulus exists you may passtest_by_trialinstead of the dictionary, but multi-test datasets must populatetest_by_trial_dictwith matching keys.check_matching_stimulusasserts that the movie and response dictionaries share the exact same keys and time bins, making downstream iteration safe.
Splitting into dataloaders
multiple_movies_dataloadersslices the training stimulus/response pairs into training and validation clips (optionally reusing user-provided validation indices).- It wraps responses with
NeuronDataSplit, which: - Transposes train/validation responses into
[time, neurons]. - Exposes
response_dict_test[name] = {"avg": tensor, "by_trial": tensor}for every key defined inResponsesTrainTestSplit.test_dict. - For every
name, movieinMoviesTrainTestSplit.test_dict.items()we create a dedicated PyTorchDataLoaderwhose dataset contains both the averaged responses and the per-trial tensor (if available). As a consequence,dataloaderscontains entries such as"train","validation","test"(default name), and"frozen_b"if a second test sequence exists.
MovieDataSet automatically stores dataset.test_responses_by_trial whenever its
responses argument is a dictionary with the keys "avg" and "by_trial". The
per-trial tensor is optional; if missing we propagate an empty tensor so evaluation code
can fall back gracefully.
Training / evaluation scripts
openretina/cli/train.pyconsumes the dictionary returned bymultiple_movies_dataloaders. Lightning sees only the"train"and"validation"loaders during fitting, while all entries (train/val/test/custom) are passed totrainer.testafter training so you get metrics for every split.openretina/cli/eval.pyinstantiates the same dataloader config but evaluates exactly one split specified viacfg.evaluation.data_split(default:"test"). This lets you reuse the script to benchmark on"train","validation", or any additional frozen stimulus without changing code. The output dataframe includes adata_splitcolumn so you can aggregate within or across stimuli later.- If
cfg.evaluation.compute_dataset_statisticsis enabled (default), evaluation also iterates through all dataloader splits to compute frame/transition fingerprints. This is useful for diagnostics but can add runtime for large datasets.
Adding a new dataset
- Implement
load_all_stimuli()andload_all_responses()that return dictionaries of the two split classes defined above. The dictionary keys represent session names and must match between stimuli and responses. - Populate
MoviesTrainTestSplit.test_dictwith one entry per frozen test stimulus. Use descriptive names (e.g."flicker_repeat_0"). - Populate
ResponsesTrainTestSplit.test_dictwith matching keys. If per-trial repeats are available for a stimulus, add them totest_by_trial_dict[key]. - Point a Hydra config at those two functions so that
openretina/cli/train.pyandopenretina/cli/eval.pycan instantiate them. No further wiring is required to gain multi-test handling in training, testing, and evaluation.
Following these conventions keeps the entire stack (data containers, dataloaders, Lightning training, and evaluation) synchronized and capable of handling multiple test movies plus their trial repetitions.