diff --git a/guideGlobalMetadata.json b/guideGlobalMetadata.json index 640a8c9c5..97eb59b34 100644 --- a/guideGlobalMetadata.json +++ b/guideGlobalMetadata.json @@ -15,6 +15,8 @@ "KiloSortSortingInterface", "Spike2RecordingInterface", "BrukerTiffSinglePlaneImagingInterface", + "ExtractSegmentationInterface", + "CnmfeSegmentationInterface", "BrukerTiffMultiPlaneImagingInterface", "MicroManagerTiffImagingInterface", "ScanImageImagingInterface", @@ -27,6 +29,11 @@ "PlexonRecordingInterface", "PlexonSortingInterface", "AxonaRecordingInterface", - "NeuralynxRecordingInterface" + "NeuralynxRecordingInterface", + "AlphaOmegaRecordingInterface", + "DeepLabCutInterface", + "SLEAPInterface", + "FicTracDataInterface", + "AudioInterface" ] } diff --git a/schemas/json/generated/AlphaOmegaRecordingInterface.json b/schemas/json/generated/AlphaOmegaRecordingInterface.json new file mode 100644 index 000000000..420bf7378 --- /dev/null +++ b/schemas/json/generated/AlphaOmegaRecordingInterface.json @@ -0,0 +1,33 @@ +{ + "required": [], + "properties": { + "AlphaOmegaRecordingInterface": { + "required": [ + "folder_path" + ], + "properties": { + "folder_path": { + "format": "directory", + "type": "string" + }, + "verbose": { + "type": "boolean", + "default": true + }, + "es_key": { + "type": "string", + "default": "ElectricalSeries" + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "source.schema.json", + "title": "Source data schema", + "description": "Schema for the source data, files and directories", + "version": "0.1.0" +} diff --git a/schemas/json/generated/AudioInterface.json b/schemas/json/generated/AudioInterface.json new file mode 100644 index 000000000..9ffca2ef0 --- /dev/null +++ b/schemas/json/generated/AudioInterface.json @@ -0,0 +1,28 @@ +{ + "required": [], + "properties": { + "AudioInterface": { + "required": [ + "file_paths" + ], + "properties": { + "file_paths": { + "type": "array" + }, + "verbose": { + "type": "boolean", + "default": false + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "source.schema.json", + "title": "Source data schema", + "description": "Schema for the source data, files and directories", + "version": "0.1.0" +} diff --git a/schemas/json/generated/CnmfeSegmentationInterface.json b/schemas/json/generated/CnmfeSegmentationInterface.json new file mode 100644 index 000000000..381a6c3a7 --- /dev/null +++ b/schemas/json/generated/CnmfeSegmentationInterface.json @@ -0,0 +1,29 @@ +{ + "required": [], + "properties": { + "CnmfeSegmentationInterface": { + "required": [ + "file_path" + ], + "properties": { + "file_path": { + "format": "file", + "type": "string" + }, + "verbose": { + "type": "boolean", + "default": true + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "source.schema.json", + "title": "Source data schema", + "description": "Schema for the source data, files and directories", + "version": "0.1.0" +} diff --git a/schemas/json/generated/DeepLabCutInterface.json b/schemas/json/generated/DeepLabCutInterface.json new file mode 100644 index 000000000..29cbcd0bd --- /dev/null +++ b/schemas/json/generated/DeepLabCutInterface.json @@ -0,0 +1,38 @@ +{ + "required": [], + "properties": { + "DeepLabCutInterface": { + "required": [ + "file_path", + "config_file_path" + ], + "properties": { + "file_path": { + "format": "file", + "type": "string" + }, + "config_file_path": { + "format": "file", + "type": "string" + }, + "subject_name": { + "type": "string", + "default": "ind1" + }, + "verbose": { + "type": "boolean", + "default": true + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "source.schema.json", + "title": "Source data schema", + "description": "Schema for the source data, files and directories", + "version": "0.1.0" +} diff --git a/schemas/json/generated/ExtractSegmentationInterface.json b/schemas/json/generated/ExtractSegmentationInterface.json new file mode 100644 index 000000000..6d488ff38 --- /dev/null +++ b/schemas/json/generated/ExtractSegmentationInterface.json @@ -0,0 +1,36 @@ +{ + "required": [], + "properties": { + "ExtractSegmentationInterface": { + "required": [ + "file_path", + "sampling_frequency" + ], + "properties": { + "file_path": { + "format": "file", + "type": "string" + }, + "sampling_frequency": { + "type": "number" + }, + "output_struct_name": { + "type": "string" + }, + "verbose": { + "type": "boolean", + "default": true + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "source.schema.json", + "title": "Source data schema", + "description": "Schema for the source data, files and directories", + "version": "0.1.0" +} diff --git a/schemas/json/generated/FicTracDataInterface.json b/schemas/json/generated/FicTracDataInterface.json new file mode 100644 index 000000000..47804a267 --- /dev/null +++ b/schemas/json/generated/FicTracDataInterface.json @@ -0,0 +1,29 @@ +{ + "required": [], + "properties": { + "FicTracDataInterface": { + "required": [ + "file_path" + ], + "properties": { + "file_path": { + "format": "file", + "type": "string" + }, + "verbose": { + "type": "boolean", + "default": true + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "source.schema.json", + "title": "Source data schema", + "description": "Schema for the source data, files and directories", + "version": "0.1.0" +} diff --git a/schemas/json/generated/SLEAPInterface.json b/schemas/json/generated/SLEAPInterface.json new file mode 100644 index 000000000..57242afdc --- /dev/null +++ b/schemas/json/generated/SLEAPInterface.json @@ -0,0 +1,36 @@ +{ + "required": [], + "properties": { + "SLEAPInterface": { + "required": [ + "file_path" + ], + "properties": { + "file_path": { + "format": "file", + "type": "string" + }, + "video_file_path": { + "format": "file", + "type": "string" + }, + "verbose": { + "type": "boolean", + "default": true + }, + "frames_per_second": { + "type": "number" + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "source.schema.json", + "title": "Source data schema", + "description": "Schema for the source data, files and directories", + "version": "0.1.0" +} diff --git a/src/renderer/assets/css/global.css b/src/renderer/assets/css/global.css index 31734949f..936161b96 100755 --- a/src/renderer/assets/css/global.css +++ b/src/renderer/assets/css/global.css @@ -14,7 +14,7 @@ } .notyf__message { - word-wrap: break-word; + word-break: break-all; } /* Tippy */ diff --git a/src/renderer/src/stories/FileSystemSelector.js b/src/renderer/src/stories/FileSystemSelector.js index fc94871fe..8eab4c6e1 100644 --- a/src/renderer/src/stories/FileSystemSelector.js +++ b/src/renderer/src/stories/FileSystemSelector.js @@ -126,7 +126,7 @@ export class FilesystemSelector extends LitElement { }; #checkType = (value) => { - const isLikelyFile = fs ? fs.lstatSync(value).isFile() : value.split(".").length; + const isLikelyFile = fs ? fs.statSync(value).isFile() : value.split(".").length; if ((this.type === "directory" && isLikelyFile) || (this.type === "file" && !isLikelyFile)) this.#onThrow("Incorrect filesystem object", `Please provide a ${this.type} instead.`); }; diff --git a/src/renderer/src/stories/JSONSchemaForm.js b/src/renderer/src/stories/JSONSchemaForm.js index 195d6cbfb..73199dd63 100644 --- a/src/renderer/src/stories/JSONSchemaForm.js +++ b/src/renderer/src/stories/JSONSchemaForm.js @@ -514,7 +514,13 @@ export class JSONSchemaForm extends LitElement { const res = entries .map(([key, value]) => { if (!value.properties && key === "definitions") return false; // Skip definitions - if (this.ignore.includes(key)) return false; + if ( + this.ignore.find((v) => { + if (typeof v === "string") return v === key; + else return v.test(key); + }) + ) + return false; if (this.showLevelOverride >= path.length) return isRenderable(key, value); if (required[key]) return isRenderable(key, value); if (this.#getLink([...this.base, ...path, key])) return isRenderable(key, value); @@ -620,7 +626,6 @@ export class JSONSchemaForm extends LitElement { // For non-links, throw a basic requirement error if the property is required if (!errors.length && isRequired && !parent[name]) { const schema = this.getSchema(localPath); - console.log(schema); errors.push({ message: `${schema.title ?? header(name)} is a required property.`, type: "error", diff --git a/src/renderer/src/stories/pages/Page.js b/src/renderer/src/stories/pages/Page.js index 016764081..08e49c592 100644 --- a/src/renderer/src/stories/pages/Page.js +++ b/src/renderer/src/stories/pages/Page.js @@ -56,8 +56,9 @@ export class Page extends LitElement { }; notify = (...args) => { - const note = notify(...args); - this.#notifications.push(note); + const ref = notify(...args); + this.#notifications.push(ref); + return ref }; to = async (transition) => { diff --git a/src/renderer/src/stories/pages/guided-mode/SourceData.stories.js b/src/renderer/src/stories/pages/guided-mode/SourceData.stories.js index 002750aa9..c42265336 100644 --- a/src/renderer/src/stories/pages/guided-mode/SourceData.stories.js +++ b/src/renderer/src/stories/pages/guided-mode/SourceData.stories.js @@ -14,6 +14,8 @@ import CellExplorerSortingInterfaceSchema from "../../../../../../schemas/json/g import KiloSortSortingInterfaceSchema from "../../../../../../schemas/json/generated/KiloSortSortingInterface.json"; import Spike2RecordingInterfaceSchema from "../../../../../../schemas/json/generated/Spike2RecordingInterface.json"; import BrukerTiffSinglePlaneImagingInterfaceSchema from "../../../../../../schemas/json/generated/BrukerTiffSinglePlaneImagingInterface.json"; +import ExtractSegmentationInterfaceSchema from "../../../../../../schemas/json/generated/ExtractSegmentationInterface.json"; +import CnmfeSegmentationInterfaceSchema from "../../../../../../schemas/json/generated/CnmfeSegmentationInterface.json"; import BrukerTiffMultiPlaneImagingInterfaceSchema from "../../../../../../schemas/json/generated/BrukerTiffMultiPlaneImagingInterface.json"; import MicroManagerTiffImagingInterfaceSchema from "../../../../../../schemas/json/generated/MicroManagerTiffImagingInterface.json"; import ScanImageImagingInterfaceSchema from "../../../../../../schemas/json/generated/ScanImageImagingInterface.json"; @@ -27,6 +29,11 @@ import PlexonRecordingInterfaceSchema from "../../../../../../schemas/json/gener import PlexonSortingInterfaceSchema from "../../../../../../schemas/json/generated/PlexonSortingInterface.json"; import AxonaRecordingInterfaceSchema from "../../../../../../schemas/json/generated/AxonaRecordingInterface.json"; import NeuralynxRecordingInterfaceSchema from "../../../../../../schemas/json/generated/NeuralynxRecordingInterface.json"; +import AlphaOmegaRecordingInterfaceSchema from "../../../../../../schemas/json/generated/AlphaOmegaRecordingInterface.json"; +import DeepLabCutInterfaceSchema from "../../../../../../schemas/json/generated/DeepLabCutInterface.json"; +import SLEAPInterfaceSchema from "../../../../../../schemas/json/generated/SLEAPInterface.json"; +import FicTracDataInterfaceSchema from "../../../../../../schemas/json/generated/FicTracDataInterface.json"; +import AudioInterfaceSchema from "../../../../../../schemas/json/generated/AudioInterface.json"; export default { title: "Pages/Guided Mode/Source Data", @@ -68,6 +75,10 @@ globalStateCopy.schema.source_data.properties.Spike2RecordingInterface = Spike2RecordingInterfaceSchema.properties.Spike2RecordingInterface; globalStateCopy.schema.source_data.properties.BrukerTiffSinglePlaneImagingInterface = BrukerTiffSinglePlaneImagingInterfaceSchema.properties.BrukerTiffSinglePlaneImagingInterface; +globalStateCopy.schema.source_data.properties.ExtractSegmentationInterface = + ExtractSegmentationInterfaceSchema.properties.ExtractSegmentationInterface; +globalStateCopy.schema.source_data.properties.CnmfeSegmentationInterface = + CnmfeSegmentationInterfaceSchema.properties.CnmfeSegmentationInterface; globalStateCopy.schema.source_data.properties.BrukerTiffMultiPlaneImagingInterface = BrukerTiffMultiPlaneImagingInterfaceSchema.properties.BrukerTiffMultiPlaneImagingInterface; globalStateCopy.schema.source_data.properties.MicroManagerTiffImagingInterface = @@ -94,6 +105,14 @@ globalStateCopy.schema.source_data.properties.AxonaRecordingInterface = AxonaRecordingInterfaceSchema.properties.AxonaRecordingInterface; globalStateCopy.schema.source_data.properties.NeuralynxRecordingInterface = NeuralynxRecordingInterfaceSchema.properties.NeuralynxRecordingInterface; +globalStateCopy.schema.source_data.properties.AlphaOmegaRecordingInterface = + AlphaOmegaRecordingInterfaceSchema.properties.AlphaOmegaRecordingInterface; +globalStateCopy.schema.source_data.properties.DeepLabCutInterface = + DeepLabCutInterfaceSchema.properties.DeepLabCutInterface; +globalStateCopy.schema.source_data.properties.SLEAPInterface = SLEAPInterfaceSchema.properties.SLEAPInterface; +globalStateCopy.schema.source_data.properties.FicTracDataInterface = + FicTracDataInterfaceSchema.properties.FicTracDataInterface; +globalStateCopy.schema.source_data.properties.AudioInterface = AudioInterfaceSchema.properties.AudioInterface; const results = globalStateCopy.results; for (let sub in results) { @@ -197,6 +216,18 @@ BrukerTiffSinglePlaneImagingInterface.args = { globalState: BrukerTiffSinglePlaneImagingInterfaceGlobalCopy, }; +export const ExtractSegmentationInterface = PageTemplate.bind({}); +const ExtractSegmentationInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +ExtractSegmentationInterfaceGlobalCopy.interfaces.interface = ExtractSegmentationInterface; +ExtractSegmentationInterfaceGlobalCopy.schema.source_data = ExtractSegmentationInterfaceSchema; +ExtractSegmentationInterface.args = { activePage, globalState: ExtractSegmentationInterfaceGlobalCopy }; + +export const CnmfeSegmentationInterface = PageTemplate.bind({}); +const CnmfeSegmentationInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +CnmfeSegmentationInterfaceGlobalCopy.interfaces.interface = CnmfeSegmentationInterface; +CnmfeSegmentationInterfaceGlobalCopy.schema.source_data = CnmfeSegmentationInterfaceSchema; +CnmfeSegmentationInterface.args = { activePage, globalState: CnmfeSegmentationInterfaceGlobalCopy }; + export const BrukerTiffMultiPlaneImagingInterface = PageTemplate.bind({}); const BrukerTiffMultiPlaneImagingInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); BrukerTiffMultiPlaneImagingInterfaceGlobalCopy.interfaces.interface = BrukerTiffMultiPlaneImagingInterface; @@ -274,3 +305,33 @@ const NeuralynxRecordingInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalSt NeuralynxRecordingInterfaceGlobalCopy.interfaces.interface = NeuralynxRecordingInterface; NeuralynxRecordingInterfaceGlobalCopy.schema.source_data = NeuralynxRecordingInterfaceSchema; NeuralynxRecordingInterface.args = { activePage, globalState: NeuralynxRecordingInterfaceGlobalCopy }; + +export const AlphaOmegaRecordingInterface = PageTemplate.bind({}); +const AlphaOmegaRecordingInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +AlphaOmegaRecordingInterfaceGlobalCopy.interfaces.interface = AlphaOmegaRecordingInterface; +AlphaOmegaRecordingInterfaceGlobalCopy.schema.source_data = AlphaOmegaRecordingInterfaceSchema; +AlphaOmegaRecordingInterface.args = { activePage, globalState: AlphaOmegaRecordingInterfaceGlobalCopy }; + +export const DeepLabCutInterface = PageTemplate.bind({}); +const DeepLabCutInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +DeepLabCutInterfaceGlobalCopy.interfaces.interface = DeepLabCutInterface; +DeepLabCutInterfaceGlobalCopy.schema.source_data = DeepLabCutInterfaceSchema; +DeepLabCutInterface.args = { activePage, globalState: DeepLabCutInterfaceGlobalCopy }; + +export const SLEAPInterface = PageTemplate.bind({}); +const SLEAPInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +SLEAPInterfaceGlobalCopy.interfaces.interface = SLEAPInterface; +SLEAPInterfaceGlobalCopy.schema.source_data = SLEAPInterfaceSchema; +SLEAPInterface.args = { activePage, globalState: SLEAPInterfaceGlobalCopy }; + +export const FicTracDataInterface = PageTemplate.bind({}); +const FicTracDataInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +FicTracDataInterfaceGlobalCopy.interfaces.interface = FicTracDataInterface; +FicTracDataInterfaceGlobalCopy.schema.source_data = FicTracDataInterfaceSchema; +FicTracDataInterface.args = { activePage, globalState: FicTracDataInterfaceGlobalCopy }; + +export const AudioInterface = PageTemplate.bind({}); +const AudioInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +AudioInterfaceGlobalCopy.interfaces.interface = AudioInterface; +AudioInterfaceGlobalCopy.schema.source_data = AudioInterfaceSchema; +AudioInterface.args = { activePage, globalState: AudioInterfaceGlobalCopy }; diff --git a/src/renderer/src/stories/pages/guided-mode/data/GuidedMetadata.js b/src/renderer/src/stories/pages/guided-mode/data/GuidedMetadata.js index e0807f79c..3fe49cc04 100644 --- a/src/renderer/src/stories/pages/guided-mode/data/GuidedMetadata.js +++ b/src/renderer/src/stories/pages/guided-mode/data/GuidedMetadata.js @@ -110,7 +110,14 @@ export class GuidedMetadataPage extends ManagedPage { results, globals: aggregateGlobalMetadata, - ignore: ["Ophys", "subject_id", "session_id"], + ignore: [ + "Ophys", // Always ignore ophys metadata (for now) + "Icephys", // Always ignore icephys metadata (for now) + "Behavior", // Always ignore behavior metadata (for now) + new RegExp("ndx-.+"), // Ignore all ndx extensions + "subject_id", + "session_id", + ], conditionalRequirements: [ { diff --git a/src/renderer/src/stories/pages/guided-mode/data/GuidedPathExpansion.js b/src/renderer/src/stories/pages/guided-mode/data/GuidedPathExpansion.js index c1b4e2e72..f259b7c9a 100644 --- a/src/renderer/src/stories/pages/guided-mode/data/GuidedPathExpansion.js +++ b/src/renderer/src/stories/pages/guided-mode/data/GuidedPathExpansion.js @@ -166,10 +166,7 @@ export class GuidedPathExpansionPage extends Page { const subjects = Object.keys(results); if (subjects.length === 0) { const message = "No subjects found with the current configuration. Please try again."; - notyf.open({ - type: "error", - message, - }); + this.notify(message, "error"); throw message; } @@ -197,10 +194,7 @@ export class GuidedPathExpansionPage extends Page { if (!this.optional.toggled) { const message = "Please select a path expansion option."; - notyf.open({ - type: "error", - message, - }); + this.notify(message, "error"); throw new Error(message); } diff --git a/src/renderer/src/stories/pages/settings/SettingsPage.js b/src/renderer/src/stories/pages/settings/SettingsPage.js index 3aff44476..b824b1872 100644 --- a/src/renderer/src/stories/pages/settings/SettingsPage.js +++ b/src/renderer/src/stories/pages/settings/SettingsPage.js @@ -35,9 +35,9 @@ export class SettingsPage extends Page { #notification; - #openNotyf = (opts) => { + #openNotyf = (message, type) => { if (this.#notification) notyf.dismiss(this.#notification); - return (this.#notification = notyf.open(opts)); + return (this.#notification = this.notify(message,type)); }; beforeSave = () => { @@ -51,10 +51,7 @@ export class SettingsPage extends Page { merge(this.form.resolved, global.data); global.save(); // Save the changes, even if invalid on the form - this.#openNotyf({ - type: "success", - message: "Global settings changes saved", - }); + this.#openNotyf("Global settings changes saved", "success"); }; render() { @@ -64,7 +61,7 @@ export class SettingsPage extends Page { label: "Save Changes", onClick: async () => { if (!this.unsavedUpdates) - return this.#openNotyf({ type: "success", message: "All changes were already saved" }); + return this.#openNotyf("All changes were already saved", "success"); this.save(); }, }); diff --git a/src/renderer/src/stories/pages/uploads/UploadsPage.js b/src/renderer/src/stories/pages/uploads/UploadsPage.js index 7039bbb9f..0c53b7b7b 100644 --- a/src/renderer/src/stories/pages/uploads/UploadsPage.js +++ b/src/renderer/src/stories/pages/uploads/UploadsPage.js @@ -48,20 +48,11 @@ export async function uploadToDandi(info, type = "project" in info ? "project" : }, { title: "Uploading to DANDI" } ).catch((e) => { - notyf.open({ - type: "error", - message: e.message, - }); + this.notify(e.message, 'error'); throw e; }); - if (result) - notyf.open({ - type: "success", - message: `${ - info.project ?? `${info[folderPathKey].length} filesystem entries` - } successfully uploaded to Dandiset ${dandiset_id}`, - }); + if (result) this.notify(`${info.project ?? `${info[folderPathKey].length} filesystem entries`} successfully uploaded to Dandiset ${dandiset_id}`, "success"); return result; }