Skip to content

Best Hacksaw Hacksaw Online We Are A Moving What

Hacksaw gaming, welcome to the luxe where fortune wears a tux featuresgolden framesgolden frames will land on positions during Slayers Inc Scratchcards Instant An Award Globally Will Modern a spin and reveal a multiplier or a.

An award winning provider hacksaw gaming which has over 300 partners Financial Reports And Count Presentations This Just Consist Please Top in the casino world has recently picked up new licenses this includes a danish certificate and they will be regulated by the danish gambling authority but which hacksaw slots should you play which are the best casinos to enjoy these at.

Life And Casinos Games Wins Go To Duelreels Should

Hacksaw gaming is a malta based igaming studio founded in 2018 known for high volatility online slots bold Hacksaw Gaming Best Hacksawgaming Launched In Both Operators visuals and bonus buy features popular with streamers and crypto casino players it began with hacksaw digital scratchcards and instant win products before expanding into slots in 2019.

Hacksaw gaming was founded in september Dark Spiral Highroller Casinos Ronin Hacksaw Gaming Is Optimized Backend 2018 to rethink classic products that are currently in the market the technology and design are built with users in mind to focus on the mobile first approach it currently has over 30 scratch card games available to play with winnings of up to 500 000.

Slayers Inc Casino Best Our Games Instant Lottery

Find the best hacksaw Products Instant Instant Investors Welcome To Line What gaming casinos with huge bonuses play quality slots scratch cards and instant win games at top, the stackways symbol is pivotal to play throughout all phases of ronin stackways land either the normal or all new revealing stackways symbol to fill the corresponding reel with 2.

Fist of destruction, products, hot ross, explore hacksaw gaming slots unique style aggressive gameplay and massive win potential try free demos learn bonus buy mechanics and discover top casinos, hacksaw gaming is a malta based casino game studio founded in 2018 and already known for bold high volatility slots scratchcards and instant win Openrgs Ross Bullets We Are A Max Bandana games from its headquarters in malta hacksaw has built a portfolio of 250 titles and secured multiple international licenses making it a trusted modern provider whose games fit perfectly with the fast crypto first experience you get at winna.

Quick draw shootout saddle up and ride out with quick draw kate in bullets and bounty a 5 reel 5 row game packed with payline wins duelreels Dark Spiral Circle Openrgs Ross What Is Favorites Perfectly Featuressummoning and a.

The Luxe Gaming Gaming Review Hacksaw Gaming Four Frames

Hacksaw gaming, The Luxe Rip Slayers Ronin Hacksaw Is A Substitutes Lands Maximum rip city, go to town on r i p city it s a tale as old as time and you re invited join the game of cat and mouse going down in r i p city and enjoy the chase.

Merged
ehennestad merged 41 commits into
fix-nwb-outstanding-review-findingsfrom
reland-nwb-converter-registry
Nov 5, 2026
Merged

ehennestad merged 41 commits into
fix-nwb-outstanding-review-findingsfrom
reland-nwb-converter-registry

Conversation

@ehennestad

@ehennestadehennestad commented Aug 29, 2026•

Copy link
Copy Markdown
Collaborator

Re-lands the roadmap 2.0 converter architecture on top of #18, rather than merging the May vertical slice. A trial merge of that slice produced 18 conflicted files, all in shared pilot files main has since renamed, re-helped and re-whitespaced, while main had independently landed the same foundation work. Re-landing keeps main's versions and applies the conventions it settled.

What this adds

A converter turns one data variable into entries in an NWB file. It is a function plus a descriptor saying what it accepts, produces and requires. Converters come from three places and nothing downstream distinguishes them: the ones shipped here, NeuroConv data interfaces reached through Python, and ones a lab registers from its own folder.

ConverterRegistry answers which converters suit a variable. NWBFileConverter walks a configuration and owns the NWB file. NWBFileConfiguration and NWBDataItemConfig replace the .mat catalog with JSON. NWBSessionConfigBuilder fills in what a NANSEN project already knows, and writeNwbFile becomes the shim it was meant to be.

Three things the runner does that no converter can do for itself

It creates the file and writes the session, subject and general metadata before any converter runs, so exactly one writer owns them and NeuroConv-backed converters append to what it wrote.

It exports as rarely as correctness allows. Every export appends a file_create_date entry and rewrites the file, so a conversion of any number of mutating items reaches disk once. Changes held in memory are written before a converter that works on the file on disk runs, and the file is read back afterwards.

It orders items so a converter producing a type runs before one requiring it. ROI signals index the plane segmentation's rows; relying on the configuration's array order made that silently positional.

Converter matching is ranked, not boolean

A converter naming a variable's source format beats one accepting its MATLAB class, which beats one accepting anything. The slice treated a file path as a pseudo-type, which made every path-taking converter match every file-backed variable — precisely where the configurator most needs to discriminate. Class evidence and format evidence are now separate descriptor fields. A format match counts only when the converter accepts the data's class, and an item's TargetNWBType narrows the matches to the converters that produce it.

Verified against real NeuroConv

A conversion was run end to end from MATLAB: the runner created the file, an ImageInterface conversion appended into it through py.*, every field the runner wrote survived, and the file carries one file_create_date entry. This is the last of the four Phase 1 acceptance criteria and the first time it has been met.

Running it corrected an assumption taken from reading NeuroConv's source. Appending drops the fields required inside the NWBFile metadata section, but the section itself stays required, so it is sent empty rather than removed. Removing it fails validation before any data is written.

Defects found along the way

  • getTypesForModule read only the schema's groups key, so types defined as datasets — GrayscaleImage, RGBImage, RGBAImage — were missing from every listing. The count goes from 59 to 70.
  • convertToNeuroDataType had an empty else branch, so anything that was not a timetable or a duration left its output unassigned.
  • Regularly sampled series were written with one timestamp per sample. NWB describes such a series by its start time and rate, and NWB Inspector reports the difference.
  • The pilot addFovProjectionImage capability was nearly lost when the pilot class was replaced. It returns as a converter, taking a struct of named projections.
  • The pilot addRois created a fresh ImageSegmentation on each call, silently dropping earlier planes.

The hand-maintained type list is gone

NeuroDataType listed 75 types by hand and was wrong in both directions against the loaded schema: six deprecated types offered, seven real ones missing. listNeurodataTypes reads the schema instead.

Review fixes

These came out of a review of the stack and are in this PR because they fix its own code.

  • iso8601ToDatetime reads timestamps with whole seconds, such as 2026-05-10T14:30:15+02:00. It returned empty for them, so a hand-written or NeuroConv-produced session_start_time fell through to datetime(text), which cannot read an offset. iso8601ToDatetimeTest covers it.
  • RoiSignals converts the samples × ROIs matrix NANSEN saves, timed by a new SamplingRate converter argument, as well as a timetable. It read .Variables and Properties.SampleRate on every input, so it failed on every class it accepted.
  • The registry matches the types NANSEN file adapters record: TwoPhotonImageStack accepts ImageStack, and RoiSignals accepts RoiSignalArray as a class and a format.
  • registerFolder does nothing for a folder already registered, and lists a folder only once its converters registered. Registering a folder twice used to make every later refresh fail.
  • A converter producing "*" satisfies requirements for its item's TargetNWBType when items are ordered.
  • With OnItemError="continue", an item no converter resolves is skipped and reported instead of stopping the run. writeNwbFile takes an 'OnItemError' parameter, "stop" by default.
  • A tie between converters at the best rank raises nansen:nwb:ambiguousConverter, and no match still raises nansen:nwb:unresolvedConverter, so a caller can tell the two apart without reading the message.
  • nansen.module.nwb.internal.mergeConverterArgs holds the rule by which a data item's ConverterArgs are laid over a converter's DefaultConverterArgs: an argument the item sets replaces the default of the same name whole. The runner uses it, and so do the later PRs that have to predict what a converter receives.
  • Messages that put a name in ''%s'' inside a double-quoted string showed both apostrophes; they use '%s'.
  • buildConfig keeps a configured SourceInfo field the variable model leaves empty, such as the path of a file the model does not know.
  • convertLegacyConfiguration gives a pilot item that used convertGeneralTwoPhotonSeries the TwoPhotonImageStack converter. Other pilot converter functions keep their name as ConverterName, so the runner reports them as unknown instead of choosing another converter.
  • The TIFF and Suite2p NeuroConv entries follow the 0.9.3 signatures. TiffImagingInterface gets file_paths and requires InterfaceArgs.sampling_frequency. Suite2pSegmentationInterface gets the suite2p folder above the plane folder, through a new grandparentFolder source path mode. resolveSourceArg adds the fields of ConverterArgs.InterfaceArgs to the constructor arguments, and RequiredInterfaceArgs names the ones that must be there. The interfaces were not run, because roiextractors is not installed in the test environment.
  • NWBSessionConfigBuilder writes numeric subject and session IDs as digits in the filename.
  • convert's help says that OnItemError="continue" writes the file without the failed items before raising nansen:nwb:itemsFailed.
  • When RoiGroupPlaneSegmentation creates the file's imaging plane, initGeneralOptophysiology first checks the merged metadata for the properties NWB requires: a description and emission_lambda for the optical channel, and excitation_lambda, indicator and location for the plane. A missing one raises nansen:nwb:missingRequiredMetadata, naming the property and the converter argument to set it in, before anything is added to the file. matnwb checks them only on export, after every other item has converted, with an error that names neither.
  • loadMetadata reads no stored metadata when no NANSEN project is open. It called nansen.getCurrentProject, which raises NANSEN:NoActiveUserSession when NANSEN has not been started, so the ROI mask converter failed in any run outside a NANSEN session.
  • builtinConverterTest runs RoiSignals and RoiGroupPlaneSegmentation through the runner, and convertLegacyConfigurationTest covers the pilot converter mapping.

TwoPhotonImageStack is still untested: it writes through NANSEN's NWBExporter, which builds matnwb.types.core objects, a namespace matnwb 2.11 does not define. That is left for a separate fix in NANSEN.

Notes for review

NwbModule and NWBVariableName take the uppercase acronym form here. #14 deferred that only because renaming needed a migration, and this schema has no predecessor to migrate.

Pilot .mat configurations are converted on the spot with a warning. Roadmap section 9 rules out a migration loader and nothing in the conversion path reads the pilot schema, but the configurator still writes .mat until the GUI moves over, and erroring would break the module end to end in the meantime.

The modern GUI is not ported. That depends on the legacy-GUI question in roadmap section 8a, which is still open.

Based on fix-nwb-outstanding-review-findings (#18); retarget to main once that merges.

🤖 Generated with Claude Code

ehennestadand others added 20 commits August 29, 2026 23:48
NWBFileConfiguration and NWBDataItemConfig replace the .mat catalog schema with classes that round-trip through JSON, so configurations are diff-friendly in version control and can be handed to converters that expect JSON metadata. The clean break is also the moment to settle two field names PR #14 deferred: NwbModule and NWBVariableName disagreed with each other and renaming them needed a migration. This schema has no predecessor to migrate, so both take the uppercase acronym form, and TargetNWBType follows. SourceInfo keeps class evidence and format evidence in separate fields. Treating a file path as a pseudo-type would match every path-taking converter against every file-backed variable, which is exactly where converter matching has to discriminate. fromStruct rejects a configuration stamped with a newer schema version rather than reading it as if it were current and dropping what it does not understand. Co-Authored-By: Claude Fable 5 <[email protected]>
A converter turns one data variable into neurodata. The registry answers which converters can handle a variable and which can produce a neurodata type; the runner walks a configuration, dispatches to them, and owns the NWB file. Three things the runner does that no converter can do for itself: It creates the file and writes the session, subject and general metadata before any converter runs, so exactly one writer owns the file-level metadata. NeuroConv-backed converters then append. That split is what NeuroConv's append mode is built for: it drops the required-field constraints on its own NWBFile metadata section when appending, so the sections the runner already wrote are not needed a second time. It exports as rarely as correctness allows. Every export appends a file_create_date entry and rewrites the file, so a conversion of any number of mutating items reaches disk once. Changes held in memory are written before a converter that works on the file on disk runs, and the file is read back afterwards. It orders items so a converter producing a type runs before one requiring it, whatever order the configuration lists them in. ROI signals need the plane segmentation they index; relying on the configuration's array order made that silently positional. Converter matching is ranked rather than boolean. A converter naming the variable's source format beats one accepting its MATLAB class, which beats one accepting anything. Treating a path as a pseudo-type had made every path-taking converter match every file-backed variable. Co-Authored-By: Claude Fable 5 <[email protected]>
The runner tests concentrate on what no converter can check for itself: that a conversion of any number of mutating items reaches disk once, that changes held in memory survive a converter which works on the file on disk, and that a producer runs before the item requiring it. An external converter is simulated with a local function, so the contract is covered without needing Python. Registry tests pin the match ranking rather than only that a match occurs. A registry returning everything for everything would pass a weaker test while being useless to the configurator. Configuration tests round-trip one item, several items, none, and items whose metadata fields differ, because JSON loses the difference between a scalar and a one-element array and jsondecode reshapes values in places MATLAB did not put them. Co-Authored-By: Claude Fable 5 <[email protected]>
A converter in a registered folder is an ordinary function that also returns its own descriptor when asked for one, so a lab can add converters without changing this module. Files that do not answer that way are left alone, letting helpers live beside the converters. Registered folders survive a registry refresh. Refreshing exists to pick up an edited converter, and silently dropping the lab's own converters while doing so would be a surprise. Co-Authored-By: Claude Fable 5 <[email protected]>
NWBSessionConfigBuilder fills in what the project already knows: where the file goes, the identifier, the zoned session start time, the subject, and for each item the class its file adapter produces, that adapter as a source format, and the file path. That is the module's advantage over a standalone converter, and it is why converter matching has evidence to rank on. It reads the variable model rather than loading data, so a configurator can offer converters for a session whose recordings are far larger than memory. Only the subject identifier is taken from the session. Species, sex and age live on the animal record, and guessing them here would put unverified values into the file. writeNwbFile becomes the shim it was meant to be: find the configuration, build it for this session, hand it to the runner. The per-item conversion loop, the placement switch and the export bookkeeping all move into NWBFileConverter, where the standalone API gets them too. Pilot .mat configurations are converted on the spot, with a warning telling the user to re-save. Roadmap section 9 rules out a migration loader, but the configurator still writes .mat until the GUI moves over, and erroring instead would break the module end to end in the meantime. convertLegacyConfiguration is the one-off tool; nothing in the conversion path reads the pilot schema. Co-Authored-By: Claude Fable 5 <[email protected]>
Replacing the pilot NWBFileConverter dropped one capability that had no equivalent among the converters: addFovProjectionImage, which stores field of view projections in an Images collection and carries the matnwb 2.9 image/baseimage rename with it. It comes back as a converter, now able to take a struct of named projections rather than one image at a time. The pilot addTrials is not restored as it was. It hardcoded four column names and a description naming one lab's trial types, and was marked as needing generalizing. The converter takes any timetable with one row per interval, gets stop times from a named stop-time or duration variable, and carries the remaining variables into columns. Without either, an interval runs until the next one starts and the last row is dropped, because nothing says when it ends. convertToNeuroDataType had an empty else branch, so anything that was not a timetable or a duration left its output unassigned and failed with an error about output arguments. Plain arrays now convert, and data carrying no time of its own is rejected with a message naming the metadata that would fix it. Co-Authored-By: Claude Fable 5 <[email protected]>
The NeuroDataType enumeration listed 75 types by hand and had to be edited whenever the NWB schema moved. Against the schema matnwb currently loads it was wrong in both directions: it offered six types that are now deprecated, and was missing seven real ones including ElectrodesTable and EventsTable. listNeurodataTypes reads the loaded schema instead, and can narrow to one module or to the types a converter names as its output. Converters that decide their type at conversion time are left out of that calculation, since counting them would mark every type producible. getTypesForModule read only the schema's groups key. A module defines types under datasets as well, so GrayscaleImage, RGBImage and RGBAImage were absent from every listing while being perfectly usable types. Reading both keys brings the count from 59 to 70. NWBDataConfiguration holds its neurodata type as text and checks it when the conversion runs. A property validator cannot follow a schema that is loaded at runtime. Co-Authored-By: Claude Fable 5 <[email protected]>
docs/converters.md is the public contract: the context a converter receives, what it may return, every descriptor field, how to register a lab's own folder, and what the runner guarantees about file creation, ordering and export. It replaces a four-line scratch note that was checked in as a template. The standalone example converts three items through three different placements without a NANSEN session, which is the claim the layering makes and the thing most likely to break quietly. Running NWB Inspector over its output found a real defect: a regularly sampled series was written with one timestamp per sample. NWB describes such a series by its start time and rate, which is smaller and what a reader expects. Both timetable paths had their own copy of the timestamp handling, so the decision now lives in one place and they share it. Projection images also get a description, which Inspector asks for and only the converter can supply. The example now passes Inspector with nothing above suggestion level, and the remaining suggestions are metadata the example does not invent: experimenter, keywords, and a subject description. Two Phase 0 leftovers go with it: an empty convertVideo stub whose argument validator does not exist anywhere, and an empty file of the same name in the mixin folder. The real video exporter is unaffected. Co-Authored-By: Claude Fable 5 <[email protected]>
The MATLAB to Python conversion is the part of the bridge most likely to be wrong and least likely to say so: NeuroConv validates metadata against a JSON schema, so a value that crosses as the wrong Python type fails inside Python complaining about the schema rather than about the MATLAB value behind it. It moves out of runConversion into toPythonValue, where it can be tested directly. Verified against a real NeuroConv 0.9.3 install: the import and class lookup work, constructing an interface reaches real NeuroConv code, and a Python traceback survives as the cause of a MATLAB exception rather than being flattened into its message. A conversion of an actual recording is still unverified. The Python environment here has neuroconv but none of the format backends it defers to, so every format interface stops at a missing module. That needs 'pip install neuroconv[ophys]' and a real source file. Co-Authored-By: Claude Fable 5 <[email protected]>
Running a real conversion contradicted what reading the source had suggested. Appending drops the fields NeuroConv requires inside its NWBFile metadata section, but the top-level schema still requires the section to be present, so removing it fails validation with "'NWBFile' is a required property" before any data is written. The section is now sent empty. Subject is dropped, as it is not required and the runner has already written it. Verified end to end against NeuroConv 0.9.3: a file created with session, subject and general metadata, appended to by an ImageInterface conversion, keeps every field the runner wrote, gains the converted data, and carries one file_create_date entry. Co-Authored-By: Claude Fable 5 <[email protected]>
A conversion can finish successfully and still produce a file a repository will reject. Running NWB Inspector over a session export showed the common case: a subject with no age, which Inspector rates critical, and which the session layer cannot supply because age lives on the animal record rather than the session. inspectFile delegates to NWB Inspector rather than reimplementing the practices, since it is the reference implementation and a MATLAB copy would drift from what a repository actually checks on submission. The runner warns rather than errors: the data is written, and what to do about a finding is the user's call. Validation is off by default in the core, which keeps it free of Python, and on for the session method, where a user is present to read the warning. Reading a Python enum member's name needs py.getattr; MATLAB does not expose it as a property, which the first version assumed. Co-Authored-By: Claude Fable 5 <[email protected]>
Three gaps surfaced by studying the roth-2026 conversion, a real published-dataset conversion that used none of this module. Each is something that project needed and had to hand-write. Project-wide metadata defaults: institution, lab, experimenter, keywords and species are per-project facts that were either retyped into every configuration or missing, and missing is what NWB Inspector kept reporting. A nwb_metadata_defaults.json next to the configuration now supplies them; values from the session win. The merge lives in deepMerge, where an empty configuration field means never-filled-in rather than erase-the-default. Subject metadata from the Subject metatable: age, sex, genotype and date of birth live on the subject record, not the session, which is why every session export drew Inspector's critical finding for a subject without an age. The builder now maps a subject record -- AgeDays to an ISO 8601 duration, BiologicalSex to the NWB letters, DateOfBirth to a zoned timestamp -- and writeNwbFile looks the record up in the project's Subject metatable when one exists. The date gets a time zone because pynwb rejects a bare date; the roth code writes yyyy-MM-dd and draws a validation warning for it. Output path as a strategy: roth writes to a Processed data location in per-figure subfolders, which no fixed convention can express. An OutputPathFcn hook derives the path from the session; an explicit OutputPath overrides; the BIDS-style default stands. Nothing is guessed anywhere: a record without an age produces metadata without an age, and the validation step reports the gap. Co-Authored-By: Claude Fable 5 <[email protected]>
# Conflicts: # +nansen/+module/+nwb/+sessionmethod/+data/+nwb/writeNwbFile.m
The ROI mask converter passes DeviceMetadata, OpticalChannelMetadata and ImagingPlaneMetadata to initGeneralOptophysiology, whose arguments block accepted only the plane and channel counts, so the converter failed on every file without optophysiology metadata. The three are now accepted and laid over the project's stored metadata. loadMetadata returns nothing when there is no current project, which is the standalone case rather than an error. Co-Authored-By: Claude Fable 5.1 <[email protected]>
jsonencode writes a datetime in display format without its zone, so a saved configuration reloaded with an unzoned session_start_time, which the runner refuses. Datetime fields are now written as ISO 8601 text with the UTC offset, and session_start_time is read back as a zoned datetime. An unzoned datetime stays unzoned on the way through, so the runner's message is still what reports it. Co-Authored-By: Claude Fable 5.1 <[email protected]>
When overwriting, the file is built under a work name and moved over the previous file only once every item is in it, and converters are resolved and the session metadata checked before the file is touched, so neither a failing item nor a misspelled converter name destroys the previous output. The resolution rule moves to ConverterRegistry.resolveForItem, where the configurator can ask the same question, and honours the rank order the registry computes: only a tie at the best rank is ambiguous. A converter returning something other than the file, nothing or a result struct is rejected instead of being read as "mutated in place" with its data dropped. A MetadataResolver option lets the session layer turn the names of linked instances in an item's metadata into objects in the file before an in-memory converter runs, as the session method did before the runner existed; the objects are discarded with the file copy they were built on after an external converter. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Each element of a multi-object result is placed under its own name; the item's name applied to all of them and only the last survived. Datetime interval times are measured from the session start, as NWB measures every time, rather than from each column's own first value. ROI signals are added to an existing response interface instead of replacing it. The generic path demands a time reference only for time series, so a type without time, such as an image, can be built. Co-Authored-By: Claude Fable 5.1 <[email protected]>
DataLocationModel returns NaT for a time it could not parse and the raw text when no format is configured; isempty catches neither, and the failure surfaced from duration() without naming the session. Both are now reported with what to configure. A missing subject or session identifier is treated as blank. Co-Authored-By: Claude Fable 5.1 <[email protected]>
The schema listing includes NWBFile, Subject, Device and the abstract containers, none of which a data variable converts to. The global dropdown now applies the same exclusions as the per-module refresh. Co-Authored-By: Claude Fable 5.1 <[email protected]>
The folder fixture deletes the folder at teardown while registerFolder had left it on the path. A helper that takes no arguments must not be executed during discovery. Co-Authored-By: Claude Fable 5.1 <[email protected]>
ehennestadand others added 8 commits November 4, 2026 08:23
…nverter-registry # Conflicts: # +nansen/+module/+nwb/+sessionmethod/+data/+nwb/writeNwbFile.m
iso8601ToDatetime counted the fraction digits as the length past 20 characters and returned empty when that count was negative. Text with whole seconds, such as "2026-05-10T14:30:15+02:00", has 19 characters after the offset is removed, so it was always rejected. The session start time in a hand-written configuration or NeuroConv metadata then fell through to datetime(text), which cannot read an offset or "Z". The fraction is now parsed only when there are characters past the seconds, and must be a decimal point followed by at least one digit. datetimeToIso8601 always writes milliseconds, so the round-trip tests never reached this case. iso8601ToDatetimeTest covers whole seconds, offsets, UTC and malformed text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The RoiSignals descriptor accepted double, single and struct, but convertRoiResponses read signalArray.Variables and Properties.SampleRate, which only a timetable has. Every accepted class therefore failed. NANSEN saves the RoiSignals_* variables as a double matrix of samples by ROIs (SignalExtractor). convertRoiResponses now takes a matrix together with a SamplingRate, and convertRoiSignals passes the SamplingRate converter argument. A matrix without a rate, or with more than two dimensions, raises a named error. The descriptor lists the classes the converter reads: double, single and timetable. struct is dropped because no code path reads one. builtinConverterTest now runs RoiSignals through the runner, appending to a file seeded with a plane segmentation built in matnwb. Co-Authored-By: Claude Opus 5.5 <[email protected]>
defaultOutputPath passed subjectID and sessionID to sprintf("%s") unconverted. NANSEN does not type them, and %s writes a number as the character with that code, so subject 5 gave "sub-\x05_ses-....nwb". They are converted with string() first, as the identifier already is. Co-Authored-By: Claude Opus 5.5 <[email protected]>
convert's help said the work file is moved over the previous file only once every item is in it. With OnItemError "continue" the file without the failed items is moved into place and itemsFailed is raised afterwards, as the error message already says. The class and method help now describe that. Co-Authored-By: Claude Opus 5.5 <[email protected]>
sourceInfoForItem records a variable's DataType and FileAdapter as class and format evidence. NANSEN fills DataType with the file adapter's DataType constant, such as "ImageStack" or "RoiSignalArray", not the MATLAB class the adapter returns. TwoPhotonImageStack and RoiSignals named only MATLAB classes and a "roisignals" format, so a NANSEN image stack or ROI signal variable matched neither of them. TwoPhotonImageStack now also accepts "ImageStack". RoiSignals accepts "RoiSignalArray" as a class and as a format. matchRank also gave a format match the top rank without looking at the classes a converter declares. RoiGroupPlaneSegmentation, which takes only ROI groups, could therefore outrank the timetable converters for a timetable of Suite2p signals. A format match now counts only when the converter accepts the data's class, or declares no classes, or accepts any class. Co-Authored-By: Claude Opus 5.5 <[email protected]>
resolveForItem never compared an item's TargetNWBType with what the candidate converters produce. A timetable with TargetNWBType "TimeIntervals" tied TimetableTimeSeries and TimetableTimeIntervals at the class rank and was handed to GenericNeurodataType, which fails on TimeIntervals. A single class match won even when it produced another type than the one asked for. When TargetNWBType is set, the matches are narrowed to converters that produce it, or produce any type, before the best rank is taken. docs/converters.md says so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ehennestadand others added 8 commits November 4, 2026 09:22
registerFolder added the folder to ConverterFolders before registering its converters, and add raises on a name that is already registered. Registering a folder a second time, as a project's startup code does whenever the project is reopened in one MATLAB session, raised and left the folder listed twice. instance(Refresh=true) then failed on the second entry on every refresh. A folder already registered, compared by absolute path, is now skipped. A folder is added to ConverterFolders only after all its converters registered. Co-Authored-By: Claude Opus 5.5 <[email protected]>
orderDataItems took each converter's ProducesNWBType literally. A converter that produces "*", such as GenericNeurodataType, builds the type its item names in TargetNWBType, but it never satisfied a requirement for that type. A generic item with TargetNWBType "PlaneSegmentation" next to a RoiSignals item failed with unmetRequirement. A "*" producer now counts as producing its item's TargetNWBType. Co-Authored-By: Claude Opus 5.5 <[email protected]>
orderDataItems resolves every item's converter before any item runs, outside the per-item try. An item naming an unregistered converter, or one no converter matches, raised there even with OnItemError "continue", so it could not be skipped like an item whose converter fails. With "continue", such an item is now reported with a warning, added to FailedItems and left out of the run. The itemsFailed message counts every configured item. Co-Authored-By: Claude Opus 5.5 <[email protected]>
buildConfig replaced every item's SourceInfo with what sourceInfoForItem reports from the variable model. For a file the model has no entry for, getDataFilePath throws and SourceInfo comes back empty. A Path and Format set in a hand-written configuration were then discarded, and resolveSourceArg asked the user to set the path they had set. Each SourceInfo field the session leaves empty now keeps the configured value. Fields the session reports still win. Co-Authored-By: Claude Opus 5.5 <[email protected]>
writeNwbFile builds NWBFileConverter with the default OnItemError "stop", so one item that fails stops the export and leaves the previous file as it was. The pilot writeNwbFile wrote the other items and warned about the failed one, and there was no way to ask for that. The new 'OnItemError' parameter is passed to the converter. It defaults to "stop"; "continue" writes the file without the failed items and raises nansen:nwb:itemsFailed at the end. Co-Authored-By: Claude Opus 5.5 <[email protected]>
convertLegacyConfiguration gave a pilot item that named its own converter function an empty ConverterName, so the runner chose a converter from the source evidence. An item that used convertGeneralTwoPhotonSeries resolved to GenericNeurodataType, which fails on an ImageStack and stopped the export. A pilot converter with a registered equivalent now gets it: convertGeneralTwoPhotonSeries becomes TwoPhotonImageStack. Any other pilot converter keeps its namespace-qualified name as the ConverterName, so the runner reports an unknown converter, or skips the item with OnItemError "continue". The warning says these items will not convert. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Two registered NeuroConv interfaces were given arguments their 0.9.3 constructors do not take as intended. TiffImagingInterface needs a sampling frequency, which a file path cannot supply, and its file_path argument is deprecated in favour of file_paths. Suite2pSegmentationInterface takes the suite2p folder that holds the plane folders, and picks a plane by plane_name. The registry passed it the plane folder that holds the variable's file. resolveSourceArg now adds the fields of ConverterArgs.InterfaceArgs to the constructor arguments. ConverterArgs.RequiredInterfaceArgs names the ones that must be there, and a missing one raises missingConverterArg naming it. A new grandparentFolder SourcePathMode gives the folder two levels above the recorded path. The TIFF entry now passes file_paths and requires InterfaceArgs.sampling_frequency. The Suite2p entry passes the suite2p folder; NeuroConv picks the first plane unless InterfaceArgs.plane_name says otherwise. The interfaces were not run: roiextractors, which they need, is not installed in the test environment. Co-Authored-By: Claude Opus 5.5 <[email protected]>
builtinConverterTest had no case for RoiGroupPlaneSegmentation. It now converts a struct with the roiArray and FovImageSize properties convertRoiGroup reads, so the test needs no NANSEN classes. It checks the plane segmentation rows and the imaging plane the converter creates. TwoPhotonImageStack stays untested here. It writes through NANSEN's NWBExporter, which builds matnwb.types.core objects, a namespace matnwb 2.11 does not define. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ehennestadand others added 5 commits November 4, 2026 10:57
loadMetadata treats a missing current project as the standalone case and returns no stored metadata. It checked for that with isempty(nansen.getCurrentProject()), but getCurrentProject raises NANSEN:NoActiveUserSession when NANSEN has not been started, and does not exist without NANSEN. The ROI mask converter, which reads stored optophysiology metadata through loadMetadata, therefore failed in any conversion run outside a NANSEN session. A missing getCurrentProject or that error now count as no project. Any other error from getCurrentProject is raised as before. Found while testing the next commit, which cannot be tested outside a NANSEN session without this one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
When the file has no imaging plane yet, RoiGroupPlaneSegmentation creates one through initGeneralOptophysiology from the converter arguments and the project's stored metadata. Nothing checked that they set what NWB requires. matnwb checks required properties only on export, so a plane without an indicator failed at the end of the run, after every other item had been converted, with an error that named neither the item nor the argument to set. initGeneralOptophysiology now merges the metadata of every channel and plane first, and checks it before adding anything to the file: description and emission_lambda for an optical channel, and excitation_lambda, indicator and location for an imaging plane. A missing one raises nansen:nwb:missingRequiredMetadata, which names the object, the properties and the converter argument to set them in. The runner reports it against the item, and the previous file is left as it was. With OnItemError "continue" the item is skipped. Co-Authored-By: Claude Opus 5.5 <[email protected]>
resolveForItem raised nansen:nwb:unresolvedConverter both when no converter matches and when several match equally well. A caller that must tell the two apart, such as the configurator's status, could do so only by looking for "Several" in the message. A tie now raises nansen:nwb:ambiguousConverter. The runner skips such an item under OnItemError "continue", as it does an unresolved one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
NWBFileConverter laid a data item's ConverterArgs over the converter's DefaultConverterArgs in a private method, so code that has to predict the arguments a converter receives had to copy the rule. nansen.module.nwb.internal.mergeConverterArgs now holds it: an argument the item sets replaces the default of the same name whole. The runner calls it, and the session builder and writeNwbFile's start-time lookup can use the same rule. mergeConverterArgsTest covers it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Four messages were double-quoted strings that put a name in ''%s''. Doubling an apostrophe escapes it only inside a single-quoted char vector, so the user saw both apostrophes, as in "Skipping ''broken''". The runner's skip warnings, its NWB Inspector warning and the descriptor validation error now use '%s'. Co-Authored-By: Claude Opus 5.5 <[email protected]>
@ehennestad
ehennestad merged commit fabd750 into mainNov 5, 2026
@ehennestad
ehennestad deleted the reland-nwb-converter-registry branch November 5, 2026 14:18
Sign up for freeto 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

@ehennestad