Skip to content

feat(dloc): extend the DSM converter to the layouts of the EBRAINS datasets - #147

Draft
ehennestad wants to merge 5 commits into
dsm-to-nansen-converterfrom
dsm-converter-ebrains-follow-ups
Draft

ehennestad wants to merge 5 commits into
dsm-to-nansen-converterfrom
dsm-converter-ebrains-follow-ups

Conversation

@ehennestad

@ehennestad ehennestad commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Mechanism

The DSM converter maps each file pattern of the session level to one NANSEN variable, named by the pattern. A NANSEN variable name is unique within a project, and NANSEN reads a session ID from one folder level with one rule.

Problem

Converting the DSM configs of 21 EBRAINS datasets hit four limits. A pattern name used in several data locations failed at the second insert into the variable model. A session identified by two levels (<experiment>/<day>) got no session ID. A pattern with a character class (\d+) has no wildcard equivalent and was dropped. Every level below the session level was dropped, so a dataset with its files in a fixed folder of the session (<day>/funct/*.nii.gz) got no variables. Separately, nansen.load and nansen.save did not find an adapter for an extension of several parts such as .nii.gz.

Changes

  • A pattern name used in several data locations becomes <location>_<name>. A name used more than once within one data location, in the session folder and in a subfolder, also gets the subfolder (funct_sidecar); names still equal after that are numbered. Each rename is reported.
  • A session entity with identifierRefs gets a Session ID rule that joins the folder names of the levels its parts are read from (SubfolderLevel array, Separator '_'), including the levels of its ancestor entities. A fixed part is left out. A part that cannot be read leaves the ID unset, with one report that gives the reason.
  • convertFilePatternToWildcard turns \d, \w, \s, [...] and unescaped . with their quantifier into * and flags the result as approximate; a result that would match every file is refused. The report names each approximated pattern, and where cardinality: many means NANSEN uses the first file.
  • Fixed-name folder levels below the session become the Subfolder of the variables made from the file patterns reached through them; the first level that is neither a fixed folder nor a level of files ends the walk, and it and the levels below it are reported. An extension of several parts (\.nii\.gz$) gives the file type .nii.gz, and listFileAdapters removes only the leading dot.
  • detectFileAdapterForFilepath matches the end of the file name against each adapter's SupportedFileTypes and prefers the longest match (nii.gz over gz), ignoring case as listFileAdapters does. The adapter list can be passed in.
  • Tests: Dsm2DataLocationModelTest, Dsm2DataLocationFilesBelowSessionTest (including the same name in the session folder and a subfolder, and nested fixed folders), ImportDatasetStructureModelTest, DetectFileAdapterForFilepathTest; fixtures scanning-days.json, runs-below-session.json.

🤖 Generated with Claude Code

ehennestad and others added 5 commits September 19, 2026 18:34
A Dataset Structure Model names file patterns per layout level, so two
data locations may both have a pattern called "original" (the same
recording as Igor Pro in one location and NWB in the other, as in the
EBRAINS datasets of Dorst et al. and Carannante et al.). A NANSEN
variable name is unique within a project, and importing such a model
failed when the second variable was inserted.

dsm2DataLocationModel now renames every variable whose name occurs in
more than one data location to <data location>_<name>, and reports each
rename. Names used in one location are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A Dataset Structure Model may identify a session by several fields,
for example the experiment and the day number when day numbers restart
in each experiment (the raw fMRI of the EBRAINS dataset of Murris et
al.). The converter left the Session ID unset for such a model, and
NANSEN then found no sessions to match.

NANSEN can join the names of several folder levels before it applies
one extraction rule. For a composite identity whose parts are each
read from one level at or above the session level, the Session ID now
joins the whole names of those levels with '_'. The levels of the
session's ancestor entities are joined too: a model's identity is
unique within its parents, a NANSEN Session ID within the project, and
without the subject day 1 of two monkeys would be one session. A part
given by a fixed rule is not in the path and is left out; both cases
are reported. Single-field identities are mapped as before.

convertMetadata receives the layout instead of its level names, and
the level lookup it already did moved into levelIndexOf so the new
function can use it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NANSEN resolves a variable's FileNameExpression with dir, so * is its
only wildcard. The converter refused every file pattern with a
character class, which dropped the only data file of some EBRAINS
datasets (Bos et al.: _{session_id}__\d{4}-\d{2}-\d{2}\.pkl$) and most
of the files of others (Blackstad et al.: ^TT\d+\.ntt$, ^CSC\d+\.ncs$).

A character class (\d, \w, \s, [...]) or a . with its quantifier now
becomes *, and the report says the variable was approximated. An
approximation that keeps no literal text but dots would match every
file in the folder and is still refused. Tokens naming the subject's
identity become * like the session's, since the files of a session
belong to one subject (Kanter et al.: ^{subject_id}_{session_id}\.nwb$).
A cardinality 'many' pattern is reported, because a NANSEN variable
holds one file and NANSEN uses the first match.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The DSM converter dropped every layout level below the session level,
so a dataset whose files sit in a folder of the session, such as the
runs in each scanning day's funct folder in murris-2021, got no
variables. A NANSEN variable can name a subfolder of the session
folder. Folder levels with a fixed name below the session now become
the Subfolder of the variables made from the file patterns reached
through them. The first level that is neither a fixed folder nor a
level of files, and the levels below it, are still dropped and
reported. Where a session has several files of a level, the report
says that NANSEN uses the first.

With levels below the session, one data location can have two file
patterns of the same name, in the session folder and in a subfolder.
Such a name is now also prefixed with the variable's subfolder
(funct_sidecar), where before both became <location>_<name> and the
second insert into the variable model failed. Names still equal after
that, from two levels in the same folder, are numbered.

An extension of several parts, such as \.nii\.gz$, now gives the file
type .nii.gz, and listFileAdapters removes only the leading dot of an
extension, so such a type can match an adapter that lists nii.gz.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nansen.load and nansen.save choose an adapter with
detectFileAdapterForFilepath, which took the extension from fileparts
(.gz for run.nii.gz) and compared it with ismember, so an adapter that
lists nii.gz was never found. The DSM converter, which asks
listFileAdapters, already found it.

An adapter now supports a file whose name ends with one of its
SupportedFileTypes. Where several adapters support the file, one with
the longest matching type is used, so nii.gz wins over gz. Case is
ignored, as in listFileAdapters. The adapter list can be passed in, so
the choice can be tested without a project.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ehennestad
ehennestad added this pull request to stack #122 September 19, 2026 16:41
@ehennestad ehennestad changed the title dsm converter ebrains follow ups feat(dloc): extend the DSM converter to the layouts of the EBRAINS datasets Sep 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant