From 5224d1a3f66a706007feb922ee2c5ec7f015d589 Mon Sep 17 00:00:00 2001 From: rly Date: Wed, 2 Jul 2025 10:26:02 -0700 Subject: [PATCH 1/7] Add first try at Plexon2RecordingInterface --- src/supported_interfaces.json | 3 +- .../Plexon2RecordingInterface.json | 34 +++++++++++++++++++ stories/pages/SourceData.stories.js | 9 +++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 stories/inputs/interface_schemas/Plexon2RecordingInterface.json diff --git a/src/supported_interfaces.json b/src/supported_interfaces.json index db1023f39c..5f8ee2e132 100644 --- a/src/supported_interfaces.json +++ b/src/supported_interfaces.json @@ -44,5 +44,6 @@ "BrukerTiffSinglePlaneConverter", "BrukerTiffMultiPlaneConverter", "MiniscopeConverter", - "CellExplorerRecordingInterface" + "CellExplorerRecordingInterface", + "Plexon2RecordingInterface" ] diff --git a/stories/inputs/interface_schemas/Plexon2RecordingInterface.json b/stories/inputs/interface_schemas/Plexon2RecordingInterface.json new file mode 100644 index 0000000000..19ae4fb0ce --- /dev/null +++ b/stories/inputs/interface_schemas/Plexon2RecordingInterface.json @@ -0,0 +1,34 @@ +{ + "required": [], + "properties": { + "Plexon2RecordingInterface": { + "properties": { + "file_path": { + "format": "file-path", + "type": "string", + "description": "Path to the .pl2 file." + }, + "verbose": { + "default": true, + "type": "boolean" + }, + "es_key": { + "default": "ElectricalSeries", + "type": "string" + } + }, + "required": [ + "file_path" + ], + "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/stories/pages/SourceData.stories.js b/stories/pages/SourceData.stories.js index 841007cf22..8b43dafe00 100644 --- a/stories/pages/SourceData.stories.js +++ b/stories/pages/SourceData.stories.js @@ -44,6 +44,7 @@ import BrukerTiffSinglePlaneConverterSchema from "../inputs/interface_schemas/Br import BrukerTiffMultiPlaneConverterSchema from "../inputs/interface_schemas/BrukerTiffMultiPlaneConverter.json"; import MiniscopeConverterSchema from "../inputs/interface_schemas/MiniscopeConverter.json"; import CellExplorerRecordingInterfaceSchema from "../inputs/interface_schemas/CellExplorerRecordingInterface.json"; +import Plexon2RecordingInterfaceSchema from "../inputs/interface_schemas/Plexon2RecordingInterface.json"; export default { title: "Pages/Guided Mode/Source Data", @@ -142,6 +143,8 @@ globalStateCopy.schema.source_data.properties.MiniscopeConverter = MiniscopeConverterSchema.properties.MiniscopeConverter; globalStateCopy.schema.source_data.properties.CellExplorerRecordingInterface = CellExplorerRecordingInterfaceSchema.properties.CellExplorerRecordingInterface; +globalStateCopy.schema.source_data.properties.Plexon2RecordingInterface = + Plexon2RecordingInterfaceSchema.properties.Plexon2RecordingInterface; const results = globalStateCopy.results; for (let sub in results) { @@ -424,3 +427,9 @@ const CellExplorerRecordingInterfaceGlobalCopy = JSON.parse(JSON.stringify(globa CellExplorerRecordingInterfaceGlobalCopy.interfaces.interface = CellExplorerRecordingInterface; CellExplorerRecordingInterfaceGlobalCopy.schema.source_data = CellExplorerRecordingInterfaceSchema; CellExplorerRecordingInterface.args = { activePage, globalState: CellExplorerRecordingInterfaceGlobalCopy }; + +export const Plexon2RecordingInterface = PageTemplate.bind({}); +const Plexon2RecordingInterfaceGlobalCopy = JSON.parse(JSON.stringify(globalState)); +Plexon2RecordingInterfaceGlobalCopy.interfaces.interface = Plexon2RecordingInterface; +Plexon2RecordingInterfaceGlobalCopy.schema.source_data = Plexon2RecordingInterfaceSchema; +Plexon2RecordingInterface.args = { activePage, globalState: Plexon2RecordingInterfaceGlobalCopy }; From afa1002aa6492890062066fa3fb75934dd713b41 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 14:00:09 +0000 Subject: [PATCH 2/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/electron/frontend/core/components/Table.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/electron/frontend/core/components/Table.js b/src/electron/frontend/core/components/Table.js index 3882fea2ab..7199c7f90b 100644 --- a/src/electron/frontend/core/components/Table.js +++ b/src/electron/frontend/core/components/Table.js @@ -670,11 +670,11 @@ export class Table extends LitElement { let message = ""; let theme = ""; if (warnings.length) { - (theme = "warning"), (message = warnings.map((error) => error.message).join("\n")); + ((theme = "warning"), (message = warnings.map((error) => error.message).join("\n"))); } else cell.removeAttribute("warning"); if (errors.length) { - (theme = "error"), (message = errors.map((error) => error.message).join("\n")); // Class switching handled automatically + ((theme = "error"), (message = errors.map((error) => error.message).join("\n"))); // Class switching handled automatically } else cell.removeAttribute("error"); if (theme) cell.setAttribute(theme, ""); From d464bf07f1a5de7fad317d21dac4c06cfae0d01e Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Wed, 4 Mar 2026 08:43:59 -0500 Subject: [PATCH 3/7] Restrict Plexon2RecordingInterface to Windows only The Plexon2 SDK only supports Windows, so exclude the interface on other platforms in both the backend API and frontend UI. Co-Authored-By: Claude Opus 4.6 --- src/electron/frontend/core/globals.js | 9 ++++++++- src/pyflask/manageNeuroconv/manage_neuroconv.py | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/electron/frontend/core/globals.js b/src/electron/frontend/core/globals.js index 8bebbaaf29..94c274394d 100644 --- a/src/electron/frontend/core/globals.js +++ b/src/electron/frontend/core/globals.js @@ -2,7 +2,14 @@ import { os, path, crypto, isElectron, isTestEnvironment } from "../utils/electr import paths from "../../../paths.config.json" assert { type: "json" }; -import supportedInterfaces from "../../../supported_interfaces.json" assert { type: "json" }; +import allSupportedInterfaces from "../../../supported_interfaces.json" assert { type: "json" }; + +// Interfaces that are only supported on specific platforms +const windowsOnlyInterfaces = ["Plexon2RecordingInterface"]; +const isWindows = os && os.platform() === "win32"; +const supportedInterfaces = allSupportedInterfaces.filter( + (name) => !windowsOnlyInterfaces.includes(name) || isWindows +); export { isTestEnvironment }; diff --git a/src/pyflask/manageNeuroconv/manage_neuroconv.py b/src/pyflask/manageNeuroconv/manage_neuroconv.py index 3e990696be..e8d54aacd8 100644 --- a/src/pyflask/manageNeuroconv/manage_neuroconv.py +++ b/src/pyflask/manageNeuroconv/manage_neuroconv.py @@ -7,6 +7,7 @@ import math import os import re +import sys import traceback import zoneinfo from datetime import datetime, timedelta @@ -342,6 +343,10 @@ def get_all_interface_info() -> dict: "SimaSegmentationInterface", ] + # Plexon2 is only supported on Windows + if sys.platform != "win32": + exclude_interfaces_from_selection.append("Plexon2RecordingInterface") + return { getattr(interface, "display_name", interface.__name__) or interface.__name__: derive_interface_info(interface) for interface in interface_list From e7f806e1ecfda3e696dc5f6c1f6df4bfcb7c09fc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 13:46:37 +0000 Subject: [PATCH 4/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/electron/frontend/core/globals.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/electron/frontend/core/globals.js b/src/electron/frontend/core/globals.js index 94c274394d..220e32cba3 100644 --- a/src/electron/frontend/core/globals.js +++ b/src/electron/frontend/core/globals.js @@ -7,9 +7,7 @@ import allSupportedInterfaces from "../../../supported_interfaces.json" assert { // Interfaces that are only supported on specific platforms const windowsOnlyInterfaces = ["Plexon2RecordingInterface"]; const isWindows = os && os.platform() === "win32"; -const supportedInterfaces = allSupportedInterfaces.filter( - (name) => !windowsOnlyInterfaces.includes(name) || isWindows -); +const supportedInterfaces = allSupportedInterfaces.filter((name) => !windowsOnlyInterfaces.includes(name) || isWindows); export { isTestEnvironment }; From e623b5e08fb83615515bf4a9625e35384554430e Mon Sep 17 00:00:00 2001 From: rly <310197+rly@users.noreply.github.com> Date: Thu, 5 Mar 2026 11:18:03 -0800 Subject: [PATCH 5/7] Remove autogenerated interface_schemas from tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This directory is already in .gitignore — autogenerated schemas should not be stored in the repo. Co-Authored-By: Claude Opus 4.6 --- .../Plexon2RecordingInterface.json | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 stories/inputs/interface_schemas/Plexon2RecordingInterface.json diff --git a/stories/inputs/interface_schemas/Plexon2RecordingInterface.json b/stories/inputs/interface_schemas/Plexon2RecordingInterface.json deleted file mode 100644 index 19ae4fb0ce..0000000000 --- a/stories/inputs/interface_schemas/Plexon2RecordingInterface.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "required": [], - "properties": { - "Plexon2RecordingInterface": { - "properties": { - "file_path": { - "format": "file-path", - "type": "string", - "description": "Path to the .pl2 file." - }, - "verbose": { - "default": true, - "type": "boolean" - }, - "es_key": { - "default": "ElectricalSeries", - "type": "string" - } - }, - "required": [ - "file_path" - ], - "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" -} From 11eaddacfbba39b6099f27522def670defcf7567 Mon Sep 17 00:00:00 2001 From: rly <310197+rly@users.noreply.github.com> Date: Thu, 5 Mar 2026 11:26:28 -0800 Subject: [PATCH 6/7] Show Plexon2 as "Windows only" instead of hiding it on non-Windows Instead of excluding Plexon2RecordingInterface from the backend on non-Windows, let it appear in the search list as disabled with a "Windows only" label. This informs users about the platform requirement rather than silently hiding the option. - Remove backend sys.platform check in get_all_interface_info() - Export windowsOnlyInterfaces from globals - Pass disabledReason to Search options for per-item disabled labels - Support per-item --disabled-label override in Search component Co-Authored-By: Claude Opus 4.6 --- src/electron/frontend/core/components/Search.js | 6 +++++- .../pages/guided-mode/data/GuidedStructure.js | 10 ++++++++-- src/electron/frontend/core/globals.js | 2 +- src/pyflask/manageNeuroconv/manage_neuroconv.py | 5 ----- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/electron/frontend/core/components/Search.js b/src/electron/frontend/core/components/Search.js index f348b4b265..51ade27e92 100644 --- a/src/electron/frontend/core/components/Search.js +++ b/src/electron/frontend/core/components/Search.js @@ -397,7 +397,11 @@ export class Search extends LitElement { this.#onSelect(option); }); - if (disabled) listItemElement.setAttribute("disabled", ""); + if (disabled) { + listItemElement.setAttribute("disabled", ""); + if (option.disabledReason) + listItemElement.style.setProperty("--disabled-label", `"${option.disabledReason}"`); + } const container = document.createElement("div"); diff --git a/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js b/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js index 09cd85d489..7830e502f5 100644 --- a/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js +++ b/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js @@ -3,7 +3,7 @@ import { Page } from "../../Page.js"; // For Multi-Select Form import { Button } from "../../../Button.js"; -import { supportedInterfaces } from "../../../../globals"; +import { supportedInterfaces, windowsOnlyInterfaces } from "../../../../globals"; import { Search } from "../../../Search.js"; import { Modal } from "../../../Modal"; import { List } from "../../../List"; @@ -129,13 +129,19 @@ export class GuidedStructurePage extends Page { suffixes: value.suffixes ?? [], }; + const isSupported = supportedInterfaces.includes(interfaceName); + const disabledReason = !isSupported && windowsOnlyInterfaces.includes(interfaceName) + ? "Windows only" + : undefined; + return { ...value, // Contains label and name already (extra metadata) key: displayName, value: interfaceName, structuredKeywords, category, - disabled: !supportedInterfaces.includes(interfaceName), + disabled: !isSupported, + disabledReason, }; }); diff --git a/src/electron/frontend/core/globals.js b/src/electron/frontend/core/globals.js index 220e32cba3..587afe7592 100644 --- a/src/electron/frontend/core/globals.js +++ b/src/electron/frontend/core/globals.js @@ -49,4 +49,4 @@ export const ENCRYPTION_IV = isElectron ? crypto.randomBytes(IV_LENGTH) : ""; // Storybook export const isStorybook = window.location.href.includes("iframe.html"); -export { supportedInterfaces }; +export { supportedInterfaces, windowsOnlyInterfaces }; diff --git a/src/pyflask/manageNeuroconv/manage_neuroconv.py b/src/pyflask/manageNeuroconv/manage_neuroconv.py index 320530acfc..882aea8b95 100644 --- a/src/pyflask/manageNeuroconv/manage_neuroconv.py +++ b/src/pyflask/manageNeuroconv/manage_neuroconv.py @@ -7,7 +7,6 @@ import math import os import re -import sys import traceback import zoneinfo from datetime import datetime, timedelta @@ -370,10 +369,6 @@ def get_all_interface_info() -> dict: "SimaSegmentationInterface", ] - # Plexon2 is only supported on Windows - if sys.platform != "win32": - exclude_interfaces_from_selection.append("Plexon2RecordingInterface") - return { getattr(interface, "display_name", interface.__name__) or interface.__name__: derive_interface_info(interface) for interface in interface_list From 3bf270831726f0c94d7c3f530db559313d1e6624 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 19:26:59 +0000 Subject: [PATCH 7/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../components/pages/guided-mode/data/GuidedStructure.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js b/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js index 7830e502f5..c49f1f06f3 100644 --- a/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js +++ b/src/electron/frontend/core/components/pages/guided-mode/data/GuidedStructure.js @@ -130,9 +130,8 @@ export class GuidedStructurePage extends Page { }; const isSupported = supportedInterfaces.includes(interfaceName); - const disabledReason = !isSupported && windowsOnlyInterfaces.includes(interfaceName) - ? "Windows only" - : undefined; + const disabledReason = + !isSupported && windowsOnlyInterfaces.includes(interfaceName) ? "Windows only" : undefined; return { ...value, // Contains label and name already (extra metadata)