diff --git a/docs/assets/tutorials/multiple/intro-page.png b/docs/assets/tutorials/multiple/intro-page.png deleted file mode 100644 index fe0915b3a..000000000 Binary files a/docs/assets/tutorials/multiple/intro-page.png and /dev/null differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-filled.png b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-filled.png index 39802e9d4..654cd70ca 100644 Binary files a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-filled.png and b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-filled.png differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-open.png b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-open.png index fe62f406d..cbbf30273 100644 Binary files a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-open.png and b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-open.png differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png index 8eb2f1a1b..c01e49315 100644 Binary files a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png and b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-basepath.png b/docs/assets/tutorials/multiple/pathexpansion-basepath.png index 74d3ea158..fbcb01f0b 100644 Binary files a/docs/assets/tutorials/multiple/pathexpansion-basepath.png and b/docs/assets/tutorials/multiple/pathexpansion-basepath.png differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-completed.png b/docs/assets/tutorials/multiple/pathexpansion-completed.png index 37bfd3a4c..c01e49315 100644 Binary files a/docs/assets/tutorials/multiple/pathexpansion-completed.png and b/docs/assets/tutorials/multiple/pathexpansion-completed.png differ diff --git a/docs/assets/tutorials/single/intro-page.png b/docs/assets/tutorials/single/intro-page.png deleted file mode 100644 index 2b88e6204..000000000 Binary files a/docs/assets/tutorials/single/intro-page.png and /dev/null differ diff --git a/docs/tutorials/dataset.rst b/docs/tutorials/dataset.rst index 0995f918d..079492639 100644 --- a/docs/tutorials/dataset.rst +++ b/docs/tutorials/dataset.rst @@ -9,7 +9,7 @@ To get you started as quickly as possible, we’ve created a way to generate thi The **Phy** data format stores spike sorting results. -Navigate to the **Settings** page using the main sidebar. Then press the **Generate** button in the top-right corner to initiate the dataset creation. +Navigate to the **Settings** page using the button at the bottom of the main sidebar. Then press the **Generate** button in the top-right corner to initiate the dataset creation. .. figure:: ../assets/tutorials/dataset-creation.png :align: center @@ -17,7 +17,7 @@ Navigate to the **Settings** page using the main sidebar. Then press the **Gener Press the Generate button on the Settings page to create the dataset. -The generated data will populate in the ``~/NWB_GUIDE/test_data`` directory and include a ``data`` folder with the original data as well as a ``dataset`` folder that duplicates this ``data`` across multiple subjects and sessions. +The generated data will populate in the ``~/NWB_GUIDE/test_data`` directory, where ``~`` is the home directory of your system. This includes a ``data`` folder with the original data as well as a ``dataset`` folder that duplicates this ``data`` across multiple subjects and sessions. .. code-block:: bash diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst index baa5e2c0d..406bcc9bb 100644 --- a/docs/tutorials/index.rst +++ b/docs/tutorials/index.rst @@ -1,12 +1,15 @@ Tutorials ======================================= The NWB Graphical User Interface for Data Entry (GUIDE) is a desktop tool for converting neurophysiological data -to the Neurodata Without Borders (NWB) format and uploading to the DANDI Archive. In these tutorials, we detail this -process from initial setup to final upload. +to the Neurodata Without Borders (NWB) format and uploading to the DANDI Archive. + +In these tutorials, you'll follow along on a :doc:`local installation of the GUIDE ` as we detail the conversion process from initial setup to final upload. Before you begin these tutorials, **you'll need to generate the tutorial dataset** using the instructions on the Dataset page. + + .. toctree:: :maxdepth: 2 diff --git a/docs/tutorials/multiple_sessions.rst b/docs/tutorials/multiple_sessions.rst index 5fed0db8b..cee658e13 100644 --- a/docs/tutorials/multiple_sessions.rst +++ b/docs/tutorials/multiple_sessions.rst @@ -3,6 +3,8 @@ Managing Multiple Sessions Now, let’s say that you’ve already run some of your experiments and now you want to convert them all at the same time. This is where a multi-session workflow will come in handy. +Begin a new conversion on the **Convert** page and provide a name for your pipeline. + Workflow Configuration ---------------------- @@ -12,7 +14,9 @@ On the Workflow page, confirm that this pipeline will be run on multiple session :align: center :alt: Workflow page with multiple sessions and locate data selected -Complete the first section of the GUIDE as normal until you reach a new **Locate Data** page after the Data Formats page. +Data Formats +------------ +As before, specify **SpikeGLX Recording** and **Phy Sorting** as the data formats for this conversion. Locate Data ----------- @@ -91,6 +95,7 @@ We should also indicate the ``sex`` of each subject since this is a requirement You’ll be able to specify Global Metadata on the Source Data and File Metadata pages as well. +Advance to the next page when you have entered subject metadata for all subjects. Source Data Information ----------------------- diff --git a/docs/tutorials/single_session.rst b/docs/tutorials/single_session.rst index 727a7e088..d3b071bf4 100644 --- a/docs/tutorials/single_session.rst +++ b/docs/tutorials/single_session.rst @@ -83,9 +83,9 @@ Data Entry Source Data Information ^^^^^^^^^^^^^^^^^^^^^^^ -On this page, specify the relevant **.bin** (Spikeglx) file and **phy** folder so that the GUIDE can find this source data to complete the conversion. +On this page, specify the **.ap.bin** (SpikeGLX) file and **phy** folder so that the GUIDE can find this source data to complete the conversion. -As discussed in the :doc:`Dataset Generation ` tutorial, these can be found in the ``~/NWB_GUIDE/test-data/data`` directory. +As discussed in the :doc:`Dataset Generation ` tutorial, these can be found in the ``~/NWB_GUIDE/test-data/data`` directory, where **~** is the home directory of your system. You can either click the file selector to navigate to the file or drag-and-drop into the GUIDE from your file navigator. @@ -93,6 +93,7 @@ You can either click the file selector to navigate to the file or drag-and-drop :align: center :alt: Source Data page with source locations specified +Advance to the next page to extract metadata from the source data. Session Metadata ^^^^^^^^^^^^^^^^ @@ -104,6 +105,7 @@ The Session Start Time in the **General Metadata** section is already specified :align: center :alt: Metadata page with invalid Subject information +While the **General Metadata** section is complete, take some time to fill out additional information such as the **Institutional Info** box and the **Experimenter** field. However, we still need to add the Subject information—as noted by the red accents around that item. Let’s say that our subject is a male mouse with an age of P25W, which represents 25 weeks old. @@ -137,7 +139,7 @@ The Inspector Report page allows you to validate the preview file against the la :align: center :alt: NWB Inspector report - +Advance to the next page when you are satisfied with the Inspector Report. Conversion Preview ^^^^^^^^^^^^^^^^^^ diff --git a/src/renderer/src/pages.js b/src/renderer/src/pages.js index 6029ac0a9..3f15cb90c 100644 --- a/src/renderer/src/pages.js +++ b/src/renderer/src/pages.js @@ -2,7 +2,6 @@ import { GettingStartedPage } from "./stories/pages/getting-started/GettingStart import { DocumentationPage } from "./stories/pages/documentation/Documentation"; import { ContactPage } from "./stories/pages/contact-us/Contact"; import { GuidedHomePage } from "./stories/pages/guided-mode/GuidedHome"; -import { GuidedStartPage } from "./stories/pages/guided-mode/GuidedStart"; import { GuidedNewDatasetPage } from "./stories/pages/guided-mode/setup/GuidedNewDatasetInfo"; import { GuidedStructurePage } from "./stories/pages/guided-mode/data/GuidedStructure"; import { sections } from "./stories/pages/globals"; @@ -85,10 +84,6 @@ const pages = { label: "Convert", icon: guidedIcon, pages: { - start: new GuidedStartPage({ - label: "Start", - }), - details: new GuidedNewDatasetPage({ title: "Project Setup", label: "Project details", 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 74e1103c1..8ea3ee24a 100644 --- a/src/renderer/src/stories/pages/guided-mode/data/GuidedPathExpansion.js +++ b/src/renderer/src/stories/pages/guided-mode/data/GuidedPathExpansion.js @@ -265,6 +265,7 @@ export class GuidedPathExpansionPage extends Page { workflow = { subject_id: {}, session_id: {}, + base_directory: {}, locate_data: { skip: () => { this.#initialize(); @@ -432,9 +433,15 @@ export class GuidedPathExpansionPage extends Page { // Require properties for all sources const generatedSchema = { type: "object", properties: {}, additionalProperties: false }; const controls = {}; + + const baseDirectory = this.workflow.base_directory.value; + const globals = (structureState.globals = {}); + for (let key in this.info.globalState.interfaces) { generatedSchema.properties[key] = { type: "object", ...pathExpansionSchema }; + if (baseDirectory) globals[key] = { base_directory: baseDirectory }; + controls[key] = { format_string_path: [ new Button({ @@ -450,8 +457,6 @@ export class GuidedPathExpansionPage extends Page { } structureState.schema = generatedSchema; - // this.optional.requestUpdate(); - const form = (this.form = new JSONSchemaForm({ ...structureState, onThrow, diff --git a/src/renderer/src/stories/pages/guided-mode/setup/Preform.js b/src/renderer/src/stories/pages/guided-mode/setup/Preform.js index 8956a7a12..90b02ba31 100644 --- a/src/renderer/src/stories/pages/guided-mode/setup/Preform.js +++ b/src/renderer/src/stories/pages/guided-mode/setup/Preform.js @@ -43,6 +43,18 @@ const questions = { }, default: false, }, + + base_directory: { + type: "string", + format: "directory", + title: "Where is your data located?", + description: + "A single directory where all data is contained. Can override for specific data formats.
Leave blank if unknown", + dependencies: { + locate_data: {}, + }, + }, + upload_to_dandi: { type: "boolean", title: "Would you like to upload your data to DANDI?", @@ -81,6 +93,7 @@ const projectWorkflowSchema = { return acc; }, {}), order: Object.keys(questions), + additionalProperties: false, }; // ---------------------------------------------------------------------- diff --git a/tests/e2e/workflow.ts b/tests/e2e/workflow.ts index 051e6d383..f3b4390c6 100644 --- a/tests/e2e/workflow.ts +++ b/tests/e2e/workflow.ts @@ -88,11 +88,6 @@ export default async function runWorkflow(name, workflow, identifier) { test('Create new pipeline by specifying a name', async () => { - // Advance to instructions page - await toNextPage('start') - - await takeScreenshot(join(identifier, 'intro-page'), 500) - // Advance to general information page await toNextPage('details') @@ -209,8 +204,6 @@ export default async function runWorkflow(name, workflow, identifier) { baseInput.updateData(basePath) }) - dashboard.main.querySelector('main > section').scrollTop = 200 // Scroll down to see all interfaces - }, testInterfaceInfo, testDatasetPath @@ -218,17 +211,20 @@ export default async function runWorkflow(name, workflow, identifier) { await takeScreenshot(join(identifier, 'pathexpansion-basepath'), 300) - const name = Object.keys(testInterfaceInfo.common)[0] - const interfaceId = testInterfaceInfo.common[name].id - const autocompleteInfo = testInterfaceInfo.multi[name].autocomplete - await evaluate(id => { + const interfaceId = await evaluate(() => { const dashboard = document.querySelector('nwb-dashboard') const form = dashboard.page.form + const id = Object.keys(form.accordions)[0] const formatInput = form.getFormElement([id, 'format_string_path']) const autocompleteButton = formatInput.controls[0] autocompleteButton.onClick() - }, interfaceId) + return id + }) + + // Use autocomplete on first interface + const name = Object.entries(testInterfaceInfo.common).find(([name, info]) => info.id === interfaceId)![0] + const autocompleteInfo = testInterfaceInfo.multi[name].autocomplete await takeScreenshot(join(identifier, 'pathexpansion-autocomplete-open'), 300) @@ -258,16 +254,16 @@ export default async function runWorkflow(name, workflow, identifier) { const dashboard = document.querySelector('nwb-dashboard') const form = dashboard.page.form + const accordionKeys = Object.keys(form.accordions) + // Fill out the path expansion information for non-autocompleted interfaces - Object.entries(common).slice(1).forEach(([ name, info ]) => { - const id = info.id + accordionKeys.slice(1).forEach(id => { + const name = Object.entries(common).find(([_, info]) => info.id === id)![0] const { format } = multi[name] const formatInput = form.getFormElement([id, 'format_string_path']) formatInput.updateData(format) }) - dashboard.main.querySelector('main > section').scrollTop = 200 - }, testInterfaceInfo)