From f782183fe241f8486adc1f066c97c2811407c2cd Mon Sep 17 00:00:00 2001 From: "Peter C. Petersen" Date: Tue, 16 Sep 2025 08:50:09 +0200 Subject: [PATCH 01/16] Add new tutorials and update existing guides Added new tutorials covering behavioral paradigms, electrophysiology workflow, managing data storage, setting up lab infrastructure, and two-photon imaging workflow. Updated existing tutorials to reference new guides, expanded instructions for personal attributes, group and project management, and API usage. These changes improve documentation coverage and provide step-by-step guidance for users on experimental setup, data management, and programmatic access. --- docs/tutorials.md | 9 +- docs/tutorials/behavioral-paradigms.md | 61 ++ docs/tutorials/electrophysiology-workflow.md | 462 +++++++++++++ docs/tutorials/get_started.md | 41 +- docs/tutorials/managing-data-storage.md | 384 +++++++++++ docs/tutorials/managing-groups.md | 31 +- docs/tutorials/managing-projects.md | 10 + docs/tutorials/matlab-api-tool.md | 26 +- docs/tutorials/python-api-tool.md | 115 +++- .../setting-up-lab-infrastructure.md | 593 +++++++++++++++++ docs/tutorials/sharing-project-publicly.md | 8 + .../submit-resource-and-taxonomies.md | 63 +- docs/tutorials/two-photon-imaging-workflow.md | 610 ++++++++++++++++++ 13 files changed, 2388 insertions(+), 25 deletions(-) create mode 100644 docs/tutorials/behavioral-paradigms.md create mode 100644 docs/tutorials/electrophysiology-workflow.md create mode 100644 docs/tutorials/managing-data-storage.md create mode 100644 docs/tutorials/setting-up-lab-infrastructure.md create mode 100644 docs/tutorials/two-photon-imaging-workflow.md diff --git a/docs/tutorials.md b/docs/tutorials.md index 3ca5977..c64ef6a 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -12,9 +12,14 @@ has_toc: false BrainSTEM provides comprehensive tutorials to help users get started and make the most of the platform's features. These step-by-step guides cover everything from basic setup to advanced functionality. - [**Get started!**]({{site.baseurl}}/tutorials/get_started): A beginner's guide to help new users create accounts, join groups, and create their first project and experiments in BrainSTEM. -- [**Share data publicly**]({{site.baseurl}}/tutorials/sharing-project-publicly): Learn how to make your research data publicly available and accessible through BrainSTEM's public sharing features. +- [**Setting Up Lab Infrastructure**]({{site.baseurl}}/tutorials/setting-up-lab-infrastructure): Comprehensive guide to establishing your lab's foundational elements: setups, equipment, inventories, and consumable stocks. - [**Manage Groups**]({{site.baseurl}}/tutorials/managing-groups): Detailed instructions for creating and managing research groups, including setting permissions and organizing team members. - [**Manage Projects**]({{site.baseurl}}/tutorials/managing-projects): Guidelines for creating and organizing research projects, including best practices for data organization and collaboration. +- [**Managing Data Storage**]({{site.baseurl}}/tutorials/managing-data-storage): Comprehensive guide to setting up data storage locations, linking them to sessions, and enabling dynamic data access for analysis workflows. +- [**Share data publicly**]({{site.baseurl}}/tutorials/sharing-project-publicly): Learn how to make your research data publicly available and accessible through BrainSTEM's public sharing features. +- [**Behavioral Paradigms**]({{site.baseurl}}/tutorials/behavioral-paradigms): Complete guide to creating and managing behavioral paradigms for experiments, including environment types, stimulus presentations, and reward systems. +- [**Electrophysiology Workflow**]({{site.baseurl}}/tutorials/electrophysiology-workflow): Example experimental workflow for electrophysiology studies, from project setup and probe implantation to data collection and spatial analysis. +- [**Two-Photon Imaging Workflow**]({{site.baseurl}}/tutorials/two-photon-imaging-workflow): Example workflow for two-photon calcium imaging experiments, covering viral injections, surgical procedures, imaging sessions, and visual stimulus analysis. - [**Matlab API tool**]({{site.baseurl}}/tutorials/matlab-api-tool): Documentation for using BrainSTEM's Matlab API tools to programmatically access and manage your research data. - [**Python API tool**]({{site.baseurl}}/tutorials/python-api-tool): Guide to utilizing BrainSTEM's Python API interface for automated data management and analysis. -- [**Submit Resources & Taxonomies**]({{site.baseurl}}/tutorials/submit-resource-and-taxonomies): Instructions for contributing to BrainSTEM's shared resources and taxonomies to enhance the platform's capabilities. \ No newline at end of file +- [**Submit Resources & Taxonomies**]({{site.baseurl}}/tutorials/submit-resource-and-taxonomies): Instructions for contributing to BrainSTEM's shared resources and taxonomies to enhance the platform's capabilities. diff --git a/docs/tutorials/behavioral-paradigms.md b/docs/tutorials/behavioral-paradigms.md new file mode 100644 index 0000000..981de1c --- /dev/null +++ b/docs/tutorials/behavioral-paradigms.md @@ -0,0 +1,61 @@ +--- +layout: default +title: Behavioral Paradigms +parent: Tutorials +nav_order: 20 +--- + +# Behavioral Paradigms in BrainSTEM + +Behavioral paradigms are standardized experimental protocols or tasks (such as T-maze alternation, open field exploration, or Morris water maze) that are performed within a specific setup environment. Defining paradigms in BrainSTEM ensures consistency, reproducibility, and clear documentation of behavioral experiments across your lab. + +## What is a Behavioral Paradigm? + +A behavioral paradigm defines: +- The type of behavioral task or protocol (e.g., spatial memory, anxiety, locomotion) +- The required environment type (must match the setup's environment type) +- Key parameters or variables (e.g., trial structure, cues, reward schedules) + +## How Behavioral Paradigms Relate to Setups + +- Each behavioral paradigm is associated with a specific environment type (e.g., T-maze, Open field) +- Only setups with a matching environment type can be used for a given paradigm +- This ensures that experimental sessions are created with the correct physical and procedural context + +## Creating a Behavioral Paradigm + +1. Go to *Personal Attributes* → *Behavioral Paradigms* +2. Click *Add behavioral paradigm* +3. Fill in the required fields: + - **Name**: Descriptive name (e.g., "T-maze Alternation Task") + - **Setup Type**: Select the matching setup type (e.g., T-maze) + - **Description**: Briefly describe the protocol, goals, and any special requirements +4. Save the paradigm. It will now be available when creating sessions in compatible setups. + +### Example: Defining a T-maze Alternation Paradigm +```json +{ + "name": "T-maze Alternation Task", + "setup_type": "T-maze", + "description": "A spatial working memory task where the subject must alternate between left and right arms for reward." +} +``` + +## Best Practices +- Use clear, standardized names for paradigms +- Include enough detail in the description for reproducibility +- Link paradigms to the correct environment type to avoid confusion +- Update paradigms as protocols evolve, but keep a record of changes + +{: .note } +> Behavioral paradigms are critical for organizing and analyzing behavioral data. Defining them up front ensures your lab's experiments are well-documented and comparable across projects. + +## Next Steps + +Now that you have behavioral paradigms defined, you can begin documenting complete experiments: + +- **Document complete experiments**: Follow either the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials to see how behavioral paradigms integrate with full experimental documentation +- **Set up your infrastructure**: Configure the physical setups and equipment using [Setting Up Lab Infrastructure]({{site.baseurl}}/tutorials/setting-up-lab-infrastructure) to create the experimental environments where your behavioral paradigms will be executed +- **Set up data storage**: Configure [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to link your behavioral sessions to actual data files for analysis +- **Expand your resources**: Visit [Submit Resources & Taxonomies]({{site.baseurl}}/tutorials/submit-resource-and-taxonomies) to contribute new behavioral equipment or paradigm types to the BrainSTEM platform +- **Enable data sharing**: Make your behavioral paradigms publicly available through [Sharing Project Publicly]({{site.baseurl}}/tutorials/sharing-project-publicly) to promote reproducible research protocols diff --git a/docs/tutorials/electrophysiology-workflow.md b/docs/tutorials/electrophysiology-workflow.md new file mode 100644 index 0000000..26277d2 --- /dev/null +++ b/docs/tutorials/electrophysiology-workflow.md @@ -0,0 +1,462 @@ +--- +layout: default +title: Complete Electrophysiology Workflow - Theta Maze with Sleep Sessions +parent: Tutorials +nav_order: 9 +--- + +# Complete Electrophysiology Workflow: Theta Maze with Sleep Sessions +{: .no_toc} + +## Table of contents +{: .no_toc .text-delta } + +1. TOC +{:toc} + +## Introduction + +This tutorial walks through a complete electrophysiology experiment in BrainSTEM, from subject preparation to data analysis. We'll document a multi-day theta maze learning study with sleep sessions, demonstrating how to integrate subjects, procedures, behavioral paradigms, data acquisition, manipulations, and collections in a realistic research workflow. + +**Experimental Design Overview:** +- **Subjects**: Rat cohort for spatial learning study +- **Setup**: Theta maze with ceiling-mounted camera and OptiTrack 3D tracking +- **Sessions**: Pre-behavior sleep → Theta maze behavior → Post-behavior sleep +- **Data**: Neuropixels recordings, behavioral video, 3D position tracking +- **Analysis**: Learning curves, replay detection, place cell analysis + +{: .note } +> This tutorial assumes you have already set up your lab infrastructure (setups, equipment, inventories) as described in the [Setting Up Lab Infrastructure tutorial]({{site.baseurl}}/tutorials/setting-up-lab-infrastructure). + +## Part A: Project and Subject Setup + +### Step 1: Creating the Research Project + +First, we'll create a project to organize and provide context for our experimental work. + +1. **Navigate to Projects**: + - Go to *Projects* + - Click *Add project* + +**[SCREENSHOT NEEDED: Project creation interface]** + +2. **Configure Project Details**: + +| Field | Value | +|-------|-------| +| **Name** | Theta Maze Spatial Learning Study | +| **Description** | Investigating hippocampal place cell dynamics and memory consolidation during spatial learning using theta maze behavioral paradigm with simultaneous Neuropixels recordings in freely moving rats. | +| **Authenticated Groups** | Select groups that should have access to this project | +| **Public Access** | No (keep project private to lab) | + +{: .note } +> Additional project details like PI name, funding source, IACUC protocol numbers, and timeline information can be included in the project description or managed through your lab's separate project management systems. Authenticated groups will get contribute permissions. You can add additional groups or change permissions in the manage page: Go to *Project detail page* → *Manage* + +### Step 2: Adding Individual Subjects + +Now we'll add individual rats that will participate in our study. + +1. **Navigate to Add Subject**: + - Go to *Subjects* + - Click *Add subject* + +**[SCREENSHOT NEEDED: Subject creation form]** + +2. **Subject Configuration Example**: + +| Field | Value | +|-------|-------| +| **Name** | TM_R001 | +| **Projects** | Select: Theta Maze Spatial Learning Study | +| **Sex** | Male | +| **Species** | Select: Rattus norvegicus | +| **Strain** | Select: Long-Evans | +| **Description** | Male Long-Evans rat for theta maze spatial learning study with Neuropixels recordings | +| **Genetic Line** | Wild type | +| **Birth Date** | 2024-05-01 | +| **Subject Identifier** | Red-001 (ear tag number) | + +**Repeat this process to create additional subjects:** +- TM_R002, TM_R003, TM_R004 (for a cohort of 4 rats) +- Use similar configurations but update IDs, ear tags + +{: .note } +> The additional subjects can be duplicated from the first subject. Go to the *Subject detail page of the first subject* → *Duplicate* +> Fill in the new subject name and click Duplicate. After this you can alter other fields if necessary. + +### Step 2b: Document Initial Housing and Weight + +After creating subjects, document their housing conditions and initial weights using subject logs. + +1. **Create Housing Log**: + - Go to *Subject logs* (below Subjects) + - Click *Add subject log* + +**Housing Log Configuration:** +| Field | Value | +|-------|-------| +| **Type** | Housing log | +| **Subject** | Select: TM_R001 | +| **Description** | Initial housing assignment for experimental cohort | + +**Type-specific Details:** +| Field | Value | +|-------|-------| +| **Start and end time** | 2024-08-01 08:00:00 to 2024-12-31 18:00:00 | +| **Notes** | Pair-housed with TM_R002. Standard rat cages with enrichment. | +| **Location** | Animal Facility Room 204 | +| **Cage ID** | Cage_A1_pair | +| **Cage type** | NexGen Rat 1800 | +| **Light cycle** | 12:12 light-dark cycle (lights on 07:00) | +| **Enrichment** | Paper tubes, wooden chew blocks | + +{: .note } +> Only the start time is required, so you can leave the end time blank. + +2. **Create Initial Weighing Log**: + +**Weighing Log Configuration:** +| Field | Value | +|-------|-------| +| **Type** | Weighing log | +| **Subject** | Select: TM_R001 | + +**Type-specific Details:** +| Field | Value | +|-------|-------| +| **Weight (grams)** | 385 | +| **Date and time** | 2024-08-01 09:00:00 | +| **Notes** | Pre-experiment baseline weight. Animal healthy and active. | + +### Step 3: Creating the Experimental Cohort + +After creating individual subjects, we can group them into a cohort for experimental organization. + +1. **Navigate to Cohorts**: + - Go to *Cohorts* (below Subjects) + - Click *Add cohort* + +**[SCREENSHOT NEEDED: Cohort creation interface]** + +2. **Configure Cohort Details**: + +| Field | Value | +|-------|-------| +| **Name** | TM_Learning_Cohort_1 | +| **Project** | Select: Theta Maze Spatial Learning Study | +| **Subjects** | Select: TM_R001, TM_R002, TM_R003, TM_R004 | +| **Description** | First experimental cohort for theta maze spatial learning study. 4 male Long-Evans rats, age-matched littermates, trained on alternation task with Neuropixels recordings. Pair housed, 12:12 light cycle, food restricted to 85% body weight during training. | +| **Tags** | theta maze, spatial learning, neuropixels, male rats | + +**[ILLUSTRATION NEEDED: Flowchart showing project → subjects → cohort → experiment relationship]** + +### Step 4: Equipment and Setup Verification + +Verify your theta maze setup includes all necessary equipment: + +**[SCREENSHOT NEEDED: Equipment list view filtered by setup]** + +**Required Equipment**: +- Neuropixels recording system (IMEC basestation) +- Open Ephys acquisition board +- Ceiling-mounted behavior camera (Basler) +- OptiTrack motion capture system (6+ cameras) +- Theta maze apparatus +- Reward delivery system +- LED position markers + +### Step 5: Neuropixels Probe Implantation Procedure + +Document the surgical procedure for Neuropixels probe implantation. + +1. **Navigate to Procedures**: + - Go to *Procedures* (below Subjects) + - Click *Add procedure* + +**[SCREENSHOT NEEDED: Procedure creation interface]** + +2. **Procedure Configuration**: + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Type** | Silicon probe implant | +| **Subject** | Select: TM_R001 | +| **Date and Time** | 2024-08-15 10:00:00 | +| **Setup** | Select: Surgical Station | +| **Equipment** | Select: Stereotaxic Frame | +| **Inventory** | Select: Neural Electrode Inventory | +| **Consumable Stock** | Select: Neuropixels 1.0 probe (#001) | +| **Atlas** | Allen Mouse Brain Atlas | +| **Brain Region** | HIP: Hippocampal region | +| **Notes** | Chronic Neuropixels probe implantation targeting CA1/CA3 hippocampus. | +| **Coordinates System** | Stereotaxic Bregma-Based Surface Coordinates with Depth | + +**Coordinate Details (Type-specific fields):** +| Field | Value | +|-------|-------| +| **AP coordinate (mm)** | -3.5 | +| **ML coordinate (mm)** | +2.5 | +| **DV coordinate (mm)** | 2.0 (initial insertion depth) | +| **AP angle** | 0° | +| **ML angle** | 0° | +| **Rotation** | 0° | + +{: .note } +> Probe specifications (Neuropixels 1.0: 960 total sites, 384 recording sites, 20 μm spacing, etc.) are documented in the consumable stock entry, not in the procedure record. You can also document the Isoflurance anesthesia, Head fixation, Craniotomy, and the Headcap, but we will leave that out for brevity. + +``` +``` + +**[ILLUSTRATION NEEDED: Brain atlas diagram showing electrode placement coordinates]** + +## Part B: Multi-Session Experimental Workflow + +### Step 6: Pre-Behavior Sleep Session + +After recovery, we begin with a baseline sleep recording. + +1. **Navigate to Sessions**: + - Go to *Sessions* + - Click *Add session* + +**[SCREENSHOT NEEDED: Session creation form]** + +2. **Sleep Session Configuration**: + +**Basic Session Information:** +| Field | Value | +|-------|-------| +| **Name** | TM_R001_Day1_PreSleep_Baseline | +| **Projects** | Select: Theta Maze Spatial Learning Study | +| **Description** | Baseline sleep recording before theta maze training. 4-hour session to capture natural sleep-wake cycles and establish baseline neural activity patterns. | +| **Date_time_onset** | 2024-08-22 09:00:00 | +| **Tags** | baseline, sleep, pre-training, neuropixels | + +{: .note } +> Sessions don't have subject, setup, duration, or behavioral paradigm fields directly. These are specified in the Behavior, Data acquisition and Epoch tabs within the session. + +**Data Acquisition - Extracellular Recording:** +| Setting | Value | +|---------|-------| +| **Type** | Extracellular Electrophysiology | +| **Subject procedures** | Select: TM_R001 : Silicon probe implant : Neuropixels Implantation | +| **Setup** | Select: Sleep Recording Box | +| **Equipment** | Select: Neuropixels System | +| **File name** | TM_R001_Day1_PreSleep_Baseline.dat | +| **Format** | Binary | +| **Data-type** | int16 | +| **Number of channels** | 384 | +| **Sampling rate (Hz)** | 30000 | +| **Least significant bit (μV/bit)** | 0.195 | + +**Data Acquisition - Video:** +| Setting | Value | +|---------|-------| +| **Session** | Select: TM_R001_Day1_PreSleep | +| **Type** | Video Tracking | +| **Procedures** | Select: TM_R001 : Silicon probe implant : Neuropixels Implantation | +| **Setup** | Select: Sleep Recording Box | +| **Equipment** | Select: Sleep Box Camera | +| **Notes** | Sleep state monitoring | + +**Session Epochs:** +| Epoch Name | Start (min) | Duration (min) | Description | +|------------|-------------|----------------|-------------| +| **Habituation** | 0 | 30 | Adaptation to recording environment | +| **Baseline_recording** | 30 | 210 | Continuous sleep/wake recording (3.5 hours) | + +**[SCREENSHOT NEEDED: Session configuration interface showing data acquisition modules]** + +### Step 7: Theta Maze Behavioral Session + +The main experimental session combining behavior with neural recording. + +**[SCREENSHOT NEEDED: Behavioral paradigm selection interface]** + +1. **Behavioral Paradigm Setup**: + +| Field | Value | +|-------|-------| +| **Name** | Theta Maze Alternation Task | +| **Environment Type** | Theta maze | +| **Authenticated Groups** | Select your lab groups | +| **Description** | Forced alternation task in theta maze. Rats navigate alternating left/right arms to receive food rewards. Trial duration 180s, inter-trial interval 45s, total 40 trials per session. Performance criteria: 80% correct, minimum 15 trials for learning threshold. | +| **Public Access** | No | + +2. **Complete Session Configuration**: + +**Basic Session Information:** +| Field | Value | +|-------|-------| +| **Name** | TM_R001_Day1_ThetaMaze_Training1 | +| **Projects** | Select: Theta Maze Spatial Learning Study | +| **Description** | First day theta maze behavioral training with Neuropixels recording | +| **Date_time_onset** | 2024-08-22 14:00:00 | +| **Tags** | behavior, theta-maze, training, day1 | +| **Data_storage** | /data/neuropixels/tm_r001/ | + +**Data Acquisition - Extracellular Recording:** +| Setting | Value | +|---------|-------| +| **Session** | Select: TM_R001_Day1_Behavior | +| **Type** | Extracellular Electrophysiology | +| **Procedures** | Select: Neuropixels Implantation | +| **Setup** | Select: Theta Maze Rig | +| **Equipment** | Select: Neuropixels System | +| **Format** | Binary | +| **Data-type** | int16 | +| **Number of channels** | 384 | +| **Sampling rate (Hz)** | 30000 | +| **Number of samples** | 216000000 | +| **Least significant bit (μV/bit)** | 0.195 | + +**Data Acquisition - Video:** +| Setting | Value | +|---------|-------| +| **Session** | Select: TM_R001_Day1_Behavior | +| **Type** | Video | +| **Procedures** | Select: Neuropixels Implantation | +| **Setup** | Select: Theta Maze Rig | +| **Equipment** | Select: Ceiling Camera | +| **Notes** | Behavioral video recording with LED tracking | + +**Data Acquisition - Position Tracking:** +| Setting | Value | +|---------|-------| +| **Session** | Select: TM_R001_Day1_Behavior | +| **Type** | Behavioral Tracking | +| **Procedures** | Select: Neuropixels Implantation | +| **Setup** | Select: Theta Maze Rig | +| **Equipment** | Select: OptiTrack System | +| **Notes** | Head and body position tracking with LED markers | + +**Session Epochs:** +| Epoch Name | Start (min) | Duration (min) | Description | +|------------|-------------|----------------|-------------| +| **Pre_task_baseline** | 0 | 10 | Open field exploration before task | +| **Training_trials** | 10 | 60 | Forced alternation training trials (longer for rats) | +| **Free_choice_trials** | 70 | 40 | Free choice alternation test (longer for rats) | +| **Post_task_rest** | 110 | 10 | Rest period after task completion | + +**[SCREENSHOT NEEDED: Session interface showing multiple data acquisition modules and epochs]** + +### Step 8: Adding Manipulations (Optional) + +For experiments with optogenetic or pharmacological manipulations. + +**[SCREENSHOT NEEDED: Manipulation creation interface]** + +**Manipulation Configuration:** + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Session** | Select: TM_R001_Day1_Behavior | +| **Type** | Optogenetical stimulation | +| **Procedures** | Select: Neuropixels Implantation | +| **Setup** | Select: Theta Maze Rig | +| **Equipment** | Select: Yellow Laser System | +| **Notes** | PV interneuron silencing during choice trials | + +**Type-specific Details:** +| Parameter | Value | +|-----------|-------| +| **Power (mW)** | 10.0 | +| **Amplitude (A)** | 0.5 | +| **Stimulation profile** | Continuous | +| **Duration (s)** | 0.5 | +| **Duty cycle** | 1.0 | +| **Repetitions** | 40 | +| **Wavelength (nm)** | 589 | +| **Closed loop** | false | + +### Step 9: Post-Behavior Sleep Session + +Capture sleep-dependent replay and consolidation. + +**Post-Sleep Session Configuration:** + +**Basic Session Information:** +| Field | Value | +|-------|-------| +| **Name** | TM_R001_Day1_PostSleep_Consolidation | +| **Projects** | Select: Theta Maze Spatial Learning Study | +| **Description** | Post-behavior sleep session for memory consolidation recording | +| **Date_time_onset** | 2024-08-22 16:00:00 | +| **Tags** | postsleep, consolidation, replay | +| **Data_storage** | /data/neuropixels/tm_r001/ | + +**Data Acquisition - Extracellular Recording:** +| Setting | Value | +|---------|-------| +| **Session** | Select: TM_R001_Day1_PostSleep_Consolidation | +| **Type** | Extracellular Electrophysiology | +| **Procedures** | Select: Neuropixels Implantation | +| **Setup** | Select: Sleep Recording Box | +| **Equipment** | Select: Neuropixels System | +| **Format** | Binary | +| **Data-type** | int16 | +| **Number of channels** | 384 | +| **Sampling rate (Hz)** | 30000 | +| **Number of samples** | 648000000 | + +**Session Epochs:** +| Epoch Name | Start (min) | Duration (min) | Description | +|------------|-------------|----------------|-------------| +| **Post_behavior_rest** | 0 | 60 | Immediate post-behavior period | +| **Sleep_recording** | 60 | 300 | Extended sleep/replay recording (5 hours) | + +## Part C: Data Organization and API access + +### Step 10: Creating Collections + +Group related sessions for analysis and organization. + +**[SCREENSHOT NEEDED: Collection creation interface]** + +**Collection Configuration:** + +| Field | Value | +|-------|-------| +| **Name** | TM_R001_Learning_Week1 | +| **Project** | Select: Theta Maze Spatial Learning Study | +| **Sessions** | Select: TM_R001_Day1_PreSleep_Baseline, TM_R001_Day1_ThetaMaze_Training1, TM_R001_Day1_PostSleep_Consolidation | +| **Description** | First week of theta maze training for subject TM_R001. Collection includes presleep baseline, behavioral training session, and postsleep consolidation recording. | +| **Tags** | learning, spatial_memory, hippocampus, week1, place_cells | + +### Step 11: API Data Access for Analysis + +Access your experimental data programmatically for analysis. + +```python +from brainstem_api_client import BrainstemClient + +client = BrainstemClient() + +# Get all sessions for a subject +subject_sessions = client.load_model('session', + filters={'subject__name': 'TM_R001'}).json() + +# Get behavioral performance data +behavior_data = client.load_model('behavioralparadigm', + filters={'session__subject__name': 'TM_R001'}).json() + +# Get neural data file paths +neural_files = client.load_model('dataacquisition', + filters={'session__subject__name': 'TM_R001', + 'type': 'Extracellular'}).json() + +# Download specific session data +session_data = client.load_model('session', filters={'name': 'tm_r001_day1_behavior_id'}) +``` + +## Next Steps + +After completing this comprehensive electrophysiology workflow, consider these logical progressions: + +- **Explore complementary techniques**: Review the [Two-Photon Imaging Workflow tutorial]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) to learn how to combine electrophysiology with optical imaging approaches +- **Access data programmatically**: Master the [Python API tool]({{site.baseurl}}/tutorials/python-api-tool) or [MATLAB API tool]({{site.baseurl}}/tutorials/matlab-api-tool) to automate analysis workflows for your large-scale electrophysiology datasets +- **Understand behavioral documentation**: Review [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms) to understand how behavioral protocols are documented and standardized across experiments +- **Optimize data management**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to efficiently organize and access your large electrophysiology datasets with proper file linking +- **Enable data sharing**: Use [Sharing Project Publicly]({{site.baseurl}}/tutorials/sharing-project-publicly) to make your electrophysiology datasets available to the research community for collaborative analysis and meta-studies diff --git a/docs/tutorials/get_started.md b/docs/tutorials/get_started.md index 31830b9..db9e5d6 100644 --- a/docs/tutorials/get_started.md +++ b/docs/tutorials/get_started.md @@ -85,23 +85,48 @@ After joining or creating a group, you can start creating projects. Projects in ## Add your personal attributes -Next, create personal attributes relevant to your experiments. +Before creating subjects and sessions, set up personal attributes that describe your setups, inventories and behavioral paradigms. These provide standardized options for your experiments. ### Define behavioral paradigms to describe the behavioral conditions of your subjects {: .no_toc} +1. Navigate to *Personal Attributes* → *Behavioral paradigms* in the left menu +2. Click *Add behavioral paradigm* +3. Fill in the paradigm details (e.g., "Open Field Test", "Novel Object Recognition") +4. Add a description of the experimental protocol + ### Set up data storage locations to link to your data files {: .no_toc} +1. Go to *Personal Attributes* → *Data storage* +2. Click *Add data storage* +3. Define storage locations where your raw data files are kept (e.g., "Lab Server", "External Drive A") +4. Include relevant path information and access details + ### Create setups to define your physical experimental environments {: .no_toc} - - Configure the equipment in your setups +1. Navigate to *Personal Attributes* → *Setups* +2. Click *Add setup* +3. Describe your experimental setups (e.g., "Theta behavior maze", "Surgical table", "Head-fixed 2P Virtual environment", "Home cage") +4. **Configure the equipment in your setups:** + - Go to *Modules* → *Equipment* + - Add devices like "Intan RHD2000", "Behavior Camera", "LED Arrays" + - Associate equipment with appropriate setups ### Set up inventories to track your lab resources {: .no_toc} - - Add consumable stocks to your inventories +1. Go to *Personal Attributes* → *Inventories* +2. Click *Add inventory* +3. Create inventory categories (e.g., "Silicon Probes", "Virus stocks") +4. **Add consumable stocks to your inventories:** + - Navigate to *Modules* → *Consumable stocks* + - Add specific items like probe models, virus batches, drug concentrations + - Link them to appropriate inventories + +{: .note } +> These personal attributes will appear as selectable options when creating sessions, subjects, and experiments. Setting them up first streamlines your data entry process. Now that all your personal attributes are in place, you can continue and add your first subject. @@ -191,3 +216,13 @@ Personal Attributes: {: .important } > This order ensures dependent components are created first. For example, behaviors need setups and behavioral paradigms to be defined first. > Data acquisition are linked to subjects through procedures, and to setups through equipment, which should be created first. + +## Next Steps + +Now that you've completed the basic setup, here are the recommended next steps: + +- **Set up your lab infrastructure**: Follow the [Setting Up Lab Infrastructure tutorial]({{site.baseurl}}/tutorials/setting-up-lab-infrastructure) to properly configure your lab's setups, equipment, inventories, and consumable stocks +- **Learn project management**: Read [Managing Projects]({{site.baseurl}}/tutorials/managing-projects) to understand how to effectively organize and collaborate on research projects +- **Configure team access**: Review [Managing Groups]({{site.baseurl}}/tutorials/managing-groups) to set up proper permissions and team collaboration +- **Plan your experiments**: Explore [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms) to define standardized experimental protocols for your studies +- **Set up data storage**: Follow [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to link your metadata to actual data files for seamless analysis workflows diff --git a/docs/tutorials/managing-data-storage.md b/docs/tutorials/managing-data-storage.md new file mode 100644 index 0000000..3df2147 --- /dev/null +++ b/docs/tutorials/managing-data-storage.md @@ -0,0 +1,384 @@ +--- +layout: default +title: Managing Data Storage +parent: Tutorials +nav_order: 7 +--- + +# Managing Data Storage in BrainSTEM +{: .no_toc} + +## Table of contents +{: .no_toc .text-delta } + +1. TOC +{:toc} + +## Introduction + +Data storage in BrainSTEM provides a flexible way to link your metadata to actual data files stored on various platforms. This tutorial covers how to set up data storage locations, associate them with sessions, and configure dynamic data linking for seamless access to your raw data. + +## Understanding Data Storage Concepts + +BrainSTEM's data storage system consists of three key components: + +1. **Data Storage Locations**: Define where your data is physically stored (servers, cloud, local drives) +2. **Data Organization**: How your files are structured within the storage location +3. **Data Protocols**: How to access the data (paths, URLs, access methods) + +## Creating a Data Storage Location + +### Step 1: Navigate to Data Storage + +1. From your BrainSTEM dashboard, go to *Personal Attributes* → *Data storage* in the left navigation menu +2. Click the *Add data storage* button in the top right corner + +### Step 2: Configure Basic Information + +**Fill in the basic details:** + +| Field | Value/Instructions | +|-------|-------------------| +| **Name** | Give your data storage a descriptive name (e.g., "Lab Server 01", "Cloud Storage Main") | +| **Authenticated groups** | Select the groups that should have access to this data storage (**required**) | +| **Description** | Add details about what type of data is stored here and any access requirements | +| **Public access** | Set whether this data storage should be publicly accessible | + +{: .important } +> Permissions are directly set on data storages. Data storage has four permission levels: membership (read access), contributors, managers, and owners. + +{: .note } +> Choose names that clearly identify the storage location and its purpose. Other lab members will see these names when creating sessions. + +### Step 3: Define Data Organization + +Configure how your data is organized within the storage location. This defines the hierarchy of folders/directories: + +**Available organization elements:** +- Projects +- Collections +- Cohorts +- Subjects +- Sessions +- Years + +**Example organization structures:** + +``` +Subjects → Sessions → Data files +``` + +``` +Projects → Subjects → Sessions → Data files +``` + +Add organization elements that match your lab's file structure conventions using the available element types. + +### Step 4: Configure Data Storage Protocols + +Set up access methods for your data storage. Each protocol defines how to access the same data storage location: + +**Protocol Configuration Options:** + +| Storage Type | Protocol | Path Example | Public Status | +|--------------|----------|--------------|---------------| +| **Network/Server Storage** | Local harddrive | `/mnt/labserver/data/` or local mount path | false (internal lab access) | +| **Cloud Storage** | Dropbox (Cloud solution) | `data/myproject` or cloud folder path | Choose based on data sensitivity | +| **Local Storage** | Local harddrive | `/Users/researcher/data/` or `D:\Lab_Data\` | false | +| **Public Repositories** | Web | `https://dandiarchive.org/dandiset/123456/` or repository URL | true | + +{: .important } +> You can configure multiple protocols for the same data storage. This allows flexibility in how different users or systems access the same data. + +## Assigning Data Storage to Sessions + +### During Session Creation + +1. When creating a new session, locate the **Data storage** field +2. Select from your configured data storage locations in the dropdown +3. Optionally, specify a **Name used in storage** - this is the folder/file name used in your actual storage system + +### For Existing Sessions + +1. Navigate to the session you want to update +2. Click the *Edit* button +3. Select or change the **Data storage** field +4. Update the **Name used in storage** if needed +5. Save your changes + +{: .note } +> The "Name used in storage" field helps maintain consistent naming between BrainSTEM and your actual file system, making it easier to locate files programmatically. This is a session-level field, not a data storage field. + +## Dynamic Data Linking + +BrainSTEM's data storage system enables dynamic construction of file paths based on your metadata and organization structure. + +### How Dynamic Linking Works + +When you associate a data storage with a session, BrainSTEM can automatically construct file paths based on: + +1. **Data storage base path**: The root location defined in your data storage protocols +2. **Organization structure**: How you've defined data should be organized +3. **Session metadata**: Project names, subject names, session names, dates +4. **Custom storage name**: The specific name you've assigned for storage + +### Example Dynamic Path Construction + +**Data Storage Configuration:** +| Field | Value | +|-------|-------| +| **Name** | Lab Server Main | +| **Base path** | `/mnt/labserver/data/` | +| **Organization** | Projects → Subjects → Sessions → Data files | + +{: .note } +> Data files are implied be stored in the session folder. + +**Session Information:** +| Field | Value | +|-------|-------| +| **Project** | Memory_Study_2024 | +| **Subject** | Mouse_001 | +| **Session** | Baseline_Recording | +| **Name used in storage** | ses01_baseline | + +**Resulting Dynamic Path:** +``` +/mnt/labserver/data/Memory_Study_2024/Mouse_001/ses01_baseline/ +``` + +### API Access to Dynamic Paths + +Use the Python or MATLAB API to programmatically access your data paths: + +```python +from brainstem_api_client import BrainstemClient + +client = BrainstemClient() + +# Load session with data storage information +session_response = client.load_model('session', + id='your-session-id', + include=['datastorage']) + +session_data = session_response.json()['sessions'][0] +storage_info = session_data['datastorage'] + +# Access configured protocols and paths +for protocol in storage_info['data_protocols_json']: + print(f"Protocol: {protocol['protocol']}") + print(f"Base path: {protocol['path']}") + print(f"Public access: {protocol['is_public']}") +``` + +### Constructing Full Paths in Your Analysis Code + +```python +def construct_data_path(session_data): + """ + Construct full path to session data based on BrainSTEM metadata + """ + storage = session_data['datastorage'] + base_path = storage['data_protocols_json'][0]['path'] # First protocol + + # Extract organization elements + organization = storage['data_organization_json'] + + # Build path based on organization structure + path_components = [base_path] + + for element in organization: + if element['elements'] == 'Projects': + path_components.append(session_data['projects'][0]['name']) + elif element['elements'] == 'Subjects': + path_components.append(session_data['subject']['name']) + elif element['elements'] == 'Sessions': + storage_name = session_data.get('name_used_in_storage', + session_data['name']) + path_components.append(storage_name) + + return '/'.join(path_components) + +# Usage +full_path = construct_data_path(session_data) +print(f"Data location: {full_path}") +``` + +## Best Practices + +### Naming Conventions + +- **Data Storage Names**: Use descriptive names that indicate location and purpose +- **Storage Names**: Keep file/folder names consistent with your lab's conventions +- **Avoid Special Characters**: Use underscores or hyphens instead of spaces + +### Organization Strategies + +- **Standardize Early**: Establish organization patterns before accumulating lots of data +- **Document Conventions**: Create lab protocols for file naming and organization +- **Plan for Growth**: Design structures that scale with increasing data volumes + +### Security and Access + +- **Authenticated Groups**: Data storage requires authenticated groups (required field) +- **Public/Private Settings**: Use the `is_public` field appropriately for your data sensitivity +- **Project Permissions**: Data storage is shared through project groups - you can only add data storage associated with the same groups as the selected projects + +### Backup and Redundancy + +- **Multiple Protocols**: Configure both local and cloud access for important data +- **Document Locations**: Maintain clear records of where different data types are stored +- **Test Access**: Regularly verify that configured paths are accessible + +## Troubleshooting Common Issues + +### Cannot Access Data Storage in Sessions + +**Problem**: Data storage doesn't appear in session dropdown + +**Solutions**: +- Verify your user is a member of one of the authenticated groups for the data storage +- Check that the data storage is properly saved and configured + +### Path Construction Errors + +**Problem**: Generated paths don't match actual file locations + +**Solutions**: +- Review your data organization structure configuration +- Verify the base paths in your protocols are correct +- Check that "Name used in storage" matches your actual file/folder names + +### API Access Issues + +**Problem**: Cannot access data storage information via API + +**Solutions**: +- Ensure you're including 'datastorage' in your API include parameters +- Verify your API authentication is working +- Check that you have proper permissions to access the data storage +- Confirm you're using the correct session ID + +## Integration with Analysis Workflows + +### Loading Data in Python + +```python +import os +from brainstem_api_client import BrainstemClient + +def load_session_data(session_id): + """ + Load session metadata and construct data paths + """ + client = BrainstemClient() + + # Get session with data storage info + response = client.load_model('session', + id=session_id, + include=['datastorage', 'dataacquisition']) + + session = response.json()['sessions'][0] + + # Construct data path + data_path = construct_data_path(session) + + # Load actual data files + data_files = [] + if os.path.exists(data_path): + data_files = [f for f in os.listdir(data_path) + if f.endswith(('.dat', '.bin', '.h5'))] + + return { + 'session_metadata': session, + 'data_path': data_path, + 'data_files': data_files + } +``` + +### MATLAB Integration + +```matlab +function data_info = load_session_data(session_id) + % Load session metadata and construct data paths + + % Get session with data storage info + session_data = load_model('model', 'session', ... + 'id', session_id, ... + 'include', {'datastorage', 'dataacquisition'}); + + % Extract data storage information + storage = session_data.datastorage; + base_path = storage.data_protocols_json{1}.path; + + % Construct full path (simplified example) + project_name = session_data.projects{1}.name; + subject_name = session_data.subject.name; + storage_name = session_data.name_used_in_storage; + + full_path = fullfile(base_path, project_name, subject_name, storage_name); + + data_info.session_metadata = session_data; + data_info.data_path = full_path; + data_info.exists = exist(full_path, 'dir') == 7; +end +``` + +## Advanced Configuration + +### Multiple Protocol Setup + +For labs with complex data access needs: + +```json +{ + "data_protocols_json": [ + { + "protocol": "Local harddrive", + "path": "/mnt/labserver/data", + "is_public": false + }, + { + "protocol": "Dropbox (Cloud solution)", + "path": "lab_backup", + "is_public": false + }, + { + "protocol": "Web", + "path": "https://dandiarchive.org/dandiset/123456", + "is_public": true + } + ] +} +``` + +### Custom Organization Patterns + +For specialized data organization: + +```json +{ + "data_organization_json": [ + {"elements": "Projects"}, + {"elements": "Subjects"}, + {"elements": "Sessions"} + ] +} +``` + +This configuration would create paths like: +``` +/base_path/Memory_Study/Mouse_001/Baseline_Recording/ +``` + +By following this tutorial, you'll be able to effectively manage your data storage in BrainSTEM, creating seamless links between your metadata and actual data files for more efficient analysis workflows. + +## Next Steps + +With data storage configured, you can now effectively manage and analyze your research data: + +- **Start experimental workflows**: Follow complete experimental documentation with [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials that demonstrate data storage integration +- **Use API tools**: Access your data programmatically with [Python API tool]({{site.baseurl}}/tutorials/python-api-tool) or [MATLAB API tool]({{site.baseurl}}/tutorials/matlab-api-tool) for seamless integration with analysis workflows +- **Organize experiments**: Create structured [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms) that integrate with your data storage system for organized behavioral data +- **Enable collaboration**: Set up proper [Managing Projects]({{site.baseurl}}/tutorials/managing-projects) to share your organized data storage with lab members and collaborators +- **Enable open data**: Make your data publicly accessible through [Sharing Project Publicly]({{site.baseurl}}/tutorials/sharing-project-publicly) to promote open science and collaboration diff --git a/docs/tutorials/managing-groups.md b/docs/tutorials/managing-groups.md index 2e0d0bd..6770cc6 100644 --- a/docs/tutorials/managing-groups.md +++ b/docs/tutorials/managing-groups.md @@ -88,9 +88,32 @@ Visit the [permissions page]({{"datamodel/permissions/"|absolute_url}}) to learn ### Associating with Laboratory +Group owners can link their group to a laboratory: + +1. Access your group's settings page +2. Click the "Add Laboratory" button +3. Fill in details about the lab, including the PI, Institution, Website, City and Country +4. Click Save to apply the association + ### Renaming the Group -1. Access group settings -2. Locate the group name field -3. Enter the new name -4. Save the changes +Group owners can change the group name: + +1. Go to your group's main page +2. Click the "Edit" button +3. Locate the "Name" field at the top of the form +4. Enter the new group name +5. Click Save to confirm the changes + +{: .important } +> Choose group names carefully as they should clearly identify your lab or research team. Other users will see this name when collaborating on projects. + +## Next Steps + +After setting up your research groups, you're ready to organize your research: + +- **Create collaborative projects**: Use [Managing Projects]({{site.baseurl}}/tutorials/managing-projects) to organize your research and enable team collaboration +- **Set up your lab infrastructure**: Follow [Setting Up Lab Infrastructure]({{site.baseurl}}/tutorials/setting-up-lab-infrastructure) to configure equipment, setups, and inventories that your group can access +- **Configure data storage**: Set up [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) locations that your team can use for data management +- **Start documenting experiments**: Begin with [Get Started]({{site.baseurl}}/tutorials/get_started) to create your first subjects and sessions with proper group permissions +- **Plan for data sharing**: Learn about [Share Data Publicly]({{site.baseurl}}/tutorials/sharing-project-publicly) when you're ready to make research openly accessible diff --git a/docs/tutorials/managing-projects.md b/docs/tutorials/managing-projects.md index 51944b5..784b43b 100644 --- a/docs/tutorials/managing-projects.md +++ b/docs/tutorials/managing-projects.md @@ -87,3 +87,13 @@ Visit the [permissions page]({{"datamodel/permissions/"|absolute_url}}) to learn 1. Edit project details 2. Modify project configuration 3. Update project metadata + +## Next Steps + +With your projects properly configured, you can start documenting your research: + +- **Set up experimental protocols**: Define [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms) for standardized experimental procedures within your projects +- **Configure data management**: Set up [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to link project data to actual files for analysis workflows +- **Start documenting experiments**: Follow complete experimental workflows like [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) +- **Enable programmatic access**: Master the [Python API tool]({{site.baseurl}}/tutorials/python-api-tool) or [MATLAB API tool]({{site.baseurl}}/tutorials/matlab-api-tool) to programmatically access your project data +- **Enable open science**: Use [Sharing Project Publicly]({{site.baseurl}}/tutorials/sharing-project-publicly) to make your project data accessible to the research community \ No newline at end of file diff --git a/docs/tutorials/matlab-api-tool.md b/docs/tutorials/matlab-api-tool.md index 2e72547..63bd439 100644 --- a/docs/tutorials/matlab-api-tool.md +++ b/docs/tutorials/matlab-api-tool.md @@ -13,22 +13,35 @@ Download the BrainSTEM Matlab API tools repository from GitHub at [github.com/br ### Setup credentials/token: -Email and password will be requested +Email and password will be requested when running this function: -```m +```matlab get_token ``` The token is saved to a mat file (`brainstem_authentication.mat`) in the Matlab API tool folder. +{: .note } +> The authentication token expires periodically. If you encounter authentication errors, run `get_token` again to refresh your credentials. + +### Troubleshooting Authentication + +If authentication fails: +- Verify your email and password are correct +- Check that the API tools are properly added to your MATLAB path +- Ensure you have an active internet connection + ### Loading sessions `load_model` can be used to load any model: We just need to set the name of the model. -```m +```matlab output1 = load_model('model','session'); ``` +{: .important } +> Always check the returned structure for errors before accessing data. Failed requests will return error information in the output structure. + We can fetch a single session entry from the loaded models. ```m @@ -114,3 +127,10 @@ output4 = load_model('model','project','portal','public'); This tutorial in also available in the [Matlab API tool Github repository](https://github.com/brainstem-org/brainstem_matlab_api_tools). +## Next Steps + +After mastering the MATLAB API basics, consider these logical progressions: + +- **Complete Experimental Documentation**: Review the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials to understand how API data access fits into complete experimental workflows +- **Cross-Platform Integration**: If you work in mixed programming environments, check out the [Python API tool tutorial]({{site.baseurl}}/tutorials/python-api-tool) to learn complementary data access patterns +- **Data Management**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to optimize your MATLAB-based analysis workflows with proper data organization diff --git a/docs/tutorials/python-api-tool.md b/docs/tutorials/python-api-tool.md index b3456c2..cc03010 100644 --- a/docs/tutorials/python-api-tool.md +++ b/docs/tutorials/python-api-tool.md @@ -16,20 +16,33 @@ You can also install the package using `pip`: pip install brainstem_python_api_tools ### Load the client. User email and password will be requested. -``` +```python from brainstem_api_client import BrainstemClient client = BrainstemClient() ``` +{: .note } +> The client will prompt for your email and password. Your credentials are used to generate an authentication token that's stored locally for future use. + +### Troubleshooting Authentication + +If you encounter authentication issues: +- Ensure your email and password are correct +- Check that your account is active +- Try regenerating your authentication token + ### Loading sessions. load_model can be used to load any model: We just need to pass our settings and the name of the model. -``` +```python output1 = client.load_model('session').json() ``` +{: .important } +> Always check the response status before accessing data. If the request fails, the response will contain error information instead of your expected data. + We can fetch a single session entry from the loaded models. ``` @@ -38,16 +51,46 @@ session = output1["sessions"][0] We can also filter the models by providing a dictionary where the keys are the fields and the values the possible contents. In this example, it will just load sessions whose name is "yeah". -``` +```python output1 = client.load_model('session', filters={'name': 'yeah'}).json() ``` +{: .note } +> Filtering helps reduce data transfer and processing time. You can filter by any field available in the model. + Loaded models can be sorted by different criteria applying to their fields. In this example, sessions will be sorted in descending ordering according to their name. ``` +```python output1 = client.load_model('session', sort=['-name']).json() ``` +```python +output1 = client.load_model('session', include=['projects', 'dataacquisition', 'behaviors', 'manipulations']).json() +``` + +```python +dataacquisition = output1["sessions"][0]["dataacquisition"] +``` + +```python +output1 = client.load_model('session', filters={'name.icontains': 'Rat'}, sort=["-name"], include=['projects']).json() +``` + +### Error Handling Best Practices + +Always check if your requests were successful: + +```python +response = client.load_model('session') +if response.status_code == 200: + data = response.json() + sessions = data.get('sessions', []) +else: + print(f"Error: {response.status_code} - {response.text}") +``` +``` + In some cases models contain relations with other models, and they can be also loaded with the models if requested. In this example, all the projects, data acquisition, behaviors and manipulations related to each session will be included. ``` @@ -70,17 +113,20 @@ output1 = client.load_model('session', filters={'name.icontains': 'Rat'}, sort=[ We can make changes to a model and update it in the database. In this case, we changed the description of one of the previously loaded sessions. -``` +```python session = {} session["description"] = 'new description' output2 = client.save_model("session", id="0e39c1fd-f413-4142-95f7-f50185e81fa4", data=session).json() ``` +{: .warning } +> Be careful when updating data. Always verify the ID is correct and consider the impact of your changes on related data. + ### Creating a new session We can submit a new entry by defining a dictionary with the required fields. -``` +```python session = {} session["name"] = "New Session" session["projects"] = ['e7475834-7733-48cf-9e3b-f4f2d2d0305a'] @@ -88,15 +134,70 @@ session["description"] = 'description' ``` Submitting session -``` +```python output3 = client.save_model("session", data=session).json() ``` +{: .note } +> When creating new entries, ensure all required fields are included. Check the [data model documentation](/datamodel/) for field requirements. + ### Load public projects Request the public data by defining the portal to be public -``` +```python output4 = client.load_model("project", portal="public").json() ``` +{: .tip } +> Public data doesn't require authentication but has the same filtering and sorting capabilities as private data. + +### Complete Example Workflow + +Here's a complete example that demonstrates loading, filtering, and creating data: + +```python +from brainstem_api_client import BrainstemClient + +# Initialize client +client = BrainstemClient() + +try: + # Load projects to get a valid project ID + projects_response = client.load_model('project') + if projects_response.status_code == 200: + projects = projects_response.json()['projects'] + if projects: + project_id = projects[0]['id'] + + # Create a new session + new_session = { + "name": "Example Session", + "projects": [project_id], + "description": "Created via API tutorial" + } + + session_response = client.save_model("session", data=new_session) + if session_response.status_code == 201: + print("Session created successfully!") + session_data = session_response.json() + print(f"New session ID: {session_data['session']['id']}") + else: + print(f"Failed to create session: {session_response.text}") + else: + print("No projects available") + else: + print(f"Failed to load projects: {projects_response.text}") + +except Exception as e: + print(f"An error occurred: {e}") +``` + See the tutorial in the Python Github repository. + +## Next Steps + +After mastering the Python API basics, consider these logical progressions: + +- **Complete Experimental Workflows**: Review the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials to see how API data fits into complete experimental documentation +- **Data Storage Integration**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to optimize your API-based analysis workflows with proper data organization +- **MATLAB Integration**: If you work in mixed programming environments, check out the [MATLAB API tool tutorial]({{site.baseurl}}/tutorials/matlab-api-tool) for cross-platform data access patterns \ No newline at end of file diff --git a/docs/tutorials/setting-up-lab-infrastructure.md b/docs/tutorials/setting-up-lab-infrastructure.md new file mode 100644 index 0000000..021e49c --- /dev/null +++ b/docs/tutorials/setting-up-lab-infrastructure.md @@ -0,0 +1,593 @@ +--- +layout: default +title: Setting Up Lab Infrastructure +parent: Tutorials +nav_order: 8 +--- + +# Setting Up Lab Infrastructure in BrainSTEM +{: .no_toc} + +## Table of contents +{: .no_toc .text-delta } + +1. TOC +{:toc} + +## Introduction + +Before conducting experiments in BrainSTEM, we recommend you establish your lab's infrastructure. This tutorial covers creating and configuring the foundational elements that support your research workflows: setups with equipment and inventories with consumable stocks. Proper infrastructure setup ensures smooth experiment creation and maintains consistency across your lab. + +## Understanding Lab Infrastructure Components + +BrainSTEM's lab infrastructure consists of four interconnected components: + +1. **Setups**: Physical experimental environments (behavior rooms, recording rigs, surgical stations) +2. **Equipment**: Devices and instruments within your setups +3. **Inventories**: Organizational systems for tracking lab resources +4. **Consumable Stocks**: Specific items and materials in your inventories + +These components work together to provide the foundation for documenting procedures, behaviors, data acquisition, and manipulations. + +## Behavioral Paradigms + +Behavioral paradigms are standardized experimental protocols (such as T-maze alternation, open field exploration, etc.) that are performed within a specific setup environment. In BrainSTEM, these are managed under *Personal Attributes → Behavioral Paradigms*. + +For detailed instructions on creating, managing, and best practices for behavioral paradigms, see the dedicated tutorial: [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms). + +{: .note } +> When planning your infrastructure, ensure that your setups have the correct environment type for the behavioral paradigms you intend to use. + +## Planning Your Infrastructure + +### Before You Begin + +1. **Audit your physical spaces**: List experimental environments in your lab +2. **Inventory your equipment**: Document devices, instruments, and tools +3. **Catalog your supplies**: Identify consumables, probes, drugs, and other materials +4. **Define access permissions**: Determine which group members need access to what resources + +### Infrastructure Hierarchy + +Understanding the relationships between components: + +``` +Setup (Physical Environment) +├── Equipment (Devices in that environment) +│ ├── Hardware devices (specific models/brands) +│ └── Coordinates systems (for positioning) +└── Associated with → Procedures, Behaviors, Data acquisition + +Inventory (Storage/Organization System) +└── Consumable Stocks (Specific items) + └── Associated with → Procedures +``` + +## Creating Setups + +Setups represent your physical experimental environments. Each setup corresponds to a specific location or configuration where experiments are conducted. + +### Step 1: Navigate to Setups + +1. Go to *Personal Attributes* → *Setups* in the left navigation menu +2. Click the *Add setup* button + +### Step 2: Configure Basic Setup Information + +**Fill in the essential details:** + +| Field | Instructions | +|-------|-------------| +| **Name** | Use descriptive, standardized names (e.g., "Behavior Room A", "Surgery Station 1", "2P Imaging Rig", "Head-fixed Linear Track") | +| **Environment Type** | Select appropriate category: Behavioral environments (T-maze, Open field, Barnes maze, Linear track), Recording environments (Head-fixed disc, Homecage, Custom rigs), or Surgical environments (Surgical table) | +| **Authenticated Groups** | Select groups that should have access to this setup | +| **Description** | Provide comprehensive details including: Physical location (room number, building), Setup purpose and capabilities, Special requirements or restrictions, Contact person for technical issues | + +### Step 3: Define Physical Dimensions + +Add relevant measurements for your setup using the physical dimensions configuration. Common examples: + +**Behavioral mazes**: Arm lengths, corridor widths, platform sizes +**Recording rigs**: Stage dimensions, working distances +**Surgical stations**: Table dimensions, reach distances + +**Example Dimension Entry:** +| Dimension | Value | Unit | +|-----------|-------|------| +| **Length** | 20 | cm | +| **Width** | 50 | cm | + +### Step 4: Setup Examples by Type + +#### Behavioral Setup Example: "T-maze Behavior Room" + +**Basic Configuration:** +| Field | Value | +|-------|-------| +| **Name** | T-maze Behavior Room | +| **Setup Type** | T-maze (Environment type from BrainSTEM options) | +| **Description** | Behavioral testing room with automated T-maze system for spatial memory tasks. Located in Room 302B, Neuroscience Building | +| **Public Access** | No | + +**Physical Dimensions:** +| Dimension | Value | Unit | +|-----------|-------|------| +| **Arm Length** | 45 | cm | +| **Stem Length** | 50 | cm | +| **Corridor Width** | 10 | cm | + +#### Recording Setup Example: "2P Imaging Rig" + +**Basic Configuration:** +| Field | Value | +|-------|-------| +| **Name** | 2P Imaging Rig | +| **Setup Type** | Head-fixed disc | +| **Description** | Two-photon microscope with head-fixed recording capability and virtual reality system. Requires dark room conditions, temperature controlled. | +| **Public Access** | No | + +**Physical Dimensions:** +| Dimension | Value | Unit | +|-----------|-------|------| +| **Stage Travel** | 25 | mm | +| **Working Distance** | 2 | mm | +| **Field of View** | 512 | μm x 512 μm | + +#### Surgical Setup Example: "Surgical Table Station" + +**Basic Configuration:** +| Field | Value | +|-------|-------| +| **Name** | Surgical Table Station | +| **Setup Type** | Surgical setup | +| **Description** | Dedicated surgical table for anesthetized in vivo procedures, equipped with stereotaxic frame and warming pad. Located in Surgery Suite 2. | +| **Public Access** | No | + +**Physical Dimensions:** +| Dimension | Value | Unit | +|-----------|-------|------| +| **Table Length** | 120 | cm | +| **Table Width** | 60 | cm | +| **Height** | 90 | cm | + +{: .note } +> Use consistent naming conventions across your lab. This makes setups easier to find and select during experiment creation. + +## Adding Equipment to Setups + +Equipment represents the devices and instruments within your setups. Each piece of equipment belongs to a specific setup and can be used in procedures, data acquisition, and manipulations. + +### Step 1: Navigate to Equipment + +1. Go to *Modules* → *Equipment* +2. Click the *Add equipment* button + +### Step 2: Configure Equipment Basics + +| Field | Instructions | +|-------|-------------| +| **Name** | Use specific, identifiable names (Good: "Intan RHD2000 #1", "Behavior Camera Main", "LED Driver Ch1-4"; Avoid: "Recording device", "Camera", "Light") | +| **Setup** | Select the setup where this equipment is located | +| **Hardware Device** | Choose from the resources database or submit new devices | +| **Coordinates System** | Define how this equipment's position is measured (Common: "External_XYZ_Absolute") | + +### Step 3: Equipment Categories and Examples + +#### Data Acquisition Equipment + +**Electrophysiology**: +- Intan Recording Controllers (RHD2000, RHX series) +- Amplifiers (A-M Systems, Molecular Devices) +- Signal processors and filters + +**Imaging Systems**: +- Two-photon microscopes (Bruker, Thorlabs) +- Miniscopes (UCLA Miniscope) +- High-speed cameras (FLIR, Basler) + +**Behavioral Monitoring**: +- Overhead cameras for behavior tracking +- Force sensors and load cells +- Motion detection systems + +#### Stimulation Equipment + +**Optogenetics**: +- LED drivers and controllers +- Laser systems + +**Electrical Stimulation**: +- Stimulus isolators (A-M Systems, Grass) +- Function generators +- Current sources + +#### Surgical Equipment + +**Stereotaxic Systems**: +- Stereotaxic frames (David Kopf, Stoelting) +- Micromanipulators (Sutter, Luigs & Neumann) +- Drill systems and burr sets + +**Injection Systems**: +- Microsyringe pumps (Harvard Apparatus) +- Glass pipette pullers (Sutter P-1000) +- Injection needles and syringes + +### Step 4: Equipment Configuration Examples + +#### Example 1: Recording System +| Field | Value | +|-------|-------| +| **Name** | Intan RHD2000 System #1 | +| **Setup** | Select: Open Field Arena | +| **Hardware Device** | Intan RHD2000 USB interface board | +| **Type** | DataAcquisitionSystem | + +#### Example 2: Behavioral Camera +| Field | Value | +|-------|-------| +| **Name** | Overhead Behavior Camera | +| **Setup** | Select: Open Field Arena | +| **Hardware Device** | Basler acA1300-200uc | +| **Type** | Camera | + +#### Example 3: Optogenetic System +| Field | Value | +|-------|-------| +| **Name** | Opto driver | +| **Setup** | Select: Open Field Arena | +| **Hardware Device** | Tucker-Davis RZ10X Lux-I/O Processor | +| **Type** | DataAcquisitionSystem | + +{: .important } +> Link equipment to appropriate hardware devices in the resources database. If your specific model isn't available, submit it for approval first. + +## Setting Up Inventories + +Inventories help organize and track consumable resources in your lab. They provide structure for managing supplies and ensure proper accounting of materials used in experiments. + +### Step 1: Create Inventory Categories + +Navigate to *Personal Attributes* → *Inventories* and create logical groupings: + +#### Common Inventory Categories + +**By Material Type**: +- "Neural Probes" - Silicon probes, tetrodes, single electrodes +- "Viral Vectors" - AAV, lentivirus, optogenetic constructs +- "Pharmacological Agents" - Drugs, anesthetics, analgesics +- "Surgical Supplies" - Sutures, needles, glass pipettes + +**By Storage Location**: +- "Freezer -80°C" - Virus stocks, some drugs +- "Freezer -20°C" - Aliquoted solutions +- "Refrigerator 4°C" - Working solutions, antibodies +- "Room Temperature Storage" - Hardware, disposables + +**By Experiment Type**: +- "Electrophysiology Supplies" +- "Optogenetics Materials" +- "Behavioral Equipment" +- "Imaging Reagents" + +### Step 2: Configure Inventory Details + +**For each inventory:** + +| Field | Instructions | +|-------|-------------| +| **Name** | Clear, descriptive identification (Examples: "Silicon Probe Storage", "AAV Virus Stocks", "Behavioral Supplies RT") | +| **Description** | Include important details: Physical location and access requirements, Storage conditions and handling notes, Responsible person or contact, Special safety considerations | +| **Authenticated Groups** | Groups that can access and modify this inventory | +| **Public Access** | Usually False for lab inventories | + +### Step 3: Inventory Setup Examples + +#### Example 1: Probe Storage +| Field | Value | +|-------|-------| +| **Name** | Neural Electrode Inventory | +| **Description** | Storage for all neural recording electrodes and probes. Located in Room 302, Cabinet B. Handle with anti-static precautions. Contact: Lab Manager for restocking. | +| **Location** | Room 302, Cabinet B, ESD-safe storage | +| **Groups** | Electrophysiology Team, Lab Managers, Buzsaki Lab | + +#### Example 2: Virus Storage +| Field | Value | +|-------|-------| +| **Name** | Viral Vector Stocks -80°C | +| **Description** | AAV and lentiviral constructs for optogenetics and tracing. Stored in -80°C freezer, Bay 3. Biosafety Level 2 protocols required. Track aliquots and avoid freeze-thaw cycles. | +| **Location** | -80°C Freezer, Bay 3, Boxes V1-V10 | +| **Groups** | Surgery Team, Viral Core Users, Tsien Lab | + +## Adding Consumable Stocks + +Consumable stocks are the specific items within your inventories. These are the actual materials that get used in procedures and need to be tracked for experimental documentation. + +### Step 1: Navigate to Consumable Stocks + +1. Go to *Modules* → *Consumable stocks* +2. Click *Add consumable stock* + +### Step 2: Configure Stock Information + +| Field Category | Field | Description | +|----------------|--------|-------------| +| **Basic Information** | Name | Specific, identifiable descriptions | +| | Inventory | Select the appropriate inventory category | +| | Consumable | Choose from resources database or submit new items | +| **Tracking Details** | Lot number | Manufacturer's batch identifier | +| | Supplier | Where the item was purchased | +| | Cost | For budget tracking and planning | +| **Storage Information** | Storage location | Specific location within the inventory | +| | Storage conditions | Temperature, humidity, special requirements | +| | Expiration date | If applicable | +| **Usage Information** | Intended use | Specific experimental applications | +| | Notes | Special handling, preparation, or usage instructions | + +### Step 3: Consumable Stock Examples + +#### Example 1: Silicon Probe + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Type** | SiliconProbe | +| **Inventory** | Select: Neural Electrode Inventory | +| **Consumable** | NeuroNexus A1x32-Poly2 | +| **Acquisition Date** | 2024-01-15 | + +**Storage & Tracking:** +| Field | Value | +|-------|-------| +| **Storage Location** | Cabinet B, Slot 15, Anti-static tube #A1x32-15 | +| **Storage Conditions** | Room temperature, anti-static protection, desiccant pack | +| **Intended Use** | Chronic hippocampal recordings in behaving mice | +| **Cost** | $1,200 | + +**Additional Details:** +- **Probe ID**: NN2024-0456-A1x32-15 +- **Quantity**: 1 +- **Notes**: Pre-cleaned with 70% ethanol. Handle with non-magnetic forceps only. Sterilize with EtO gas before implantation. + +#### Example 2: Viral Vector + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Type** | VirusSolution | +| **Inventory** | Select: Viral Vector Stocks | +| **Consumable** | AAV-DJ-ChR2-EYFP | +| **Acquisition Date** | 2024-02-01 | +| **Expiration Date** | 2026-12-15 | + +**Storage & Tracking:** +| Field | Value | +|-------|-------| +| **Storage Location** | -80°C Freezer, Bay 3, Box V3, Position A4 | +| **Storage Conditions** | Store at -80°C, avoid freeze-thaw cycles, transport on dry ice | +| **Intended Use** | Optogenetic stimulation of excitatory neurons in mouse cortex | +| **Cost** | $450 | + +**Viral Vector Details:** +| Parameter | Value | +|-----------|-------| +| **Titer** | 1.2 × 10¹³ vg/mL | +| **Volume** | 1.0 mL | +| **Aliquot Count** | 20 | +| **Aliquot Volume** | 50 μL each | + +**Notes**: AAV-DJ-hSyn-ChR2(H134R)-EYFP from Stanford Gene Vector and Virus Core. Aliquoted on 2024-02-01. Each aliquot contains ~6 × 10¹¹ GC. Dilute in sterile PBS to desired injection concentration (typically 1:10 to 1:50). Thaw on ice 15-20 minutes before use. Never refreeze thawed aliquots. Biosafety Level 2 protocols required. Lot #VV2024-089. + +#### Example 3: Pharmaceutical + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Type** | ChemicalReagent | +| **Inventory** | Select: Controlled Substances Inventory | +| **Consumable** | Ketamine HCl | +| **Acquisition Date** | 2024-01-10 | +| **Expiration Date** | 2025-01-10 | + +**Storage & Tracking:** +| Field | Value | +|-------|-------| +| **Storage Location** | Controlled substances safe, refrigerated | +| **Storage Conditions** | Store at 2-8°C in locked safe | +| **Intended Use** | Anesthesia for surgical procedures | +| **Cost** | $85 | + +**Notes**: DEA Schedule III. Record all usage for compliance. 100mg/mL, 10mL vial. + +## Permission Management + +Proper permission management ensures that the right people have access to the right resources while maintaining security and organization. + +### Setup and Equipment Permissions + +**Four Permission Levels**: +1. **Members**: Read-only access, can view and select in experiments +2. **Contributors**: Can create and modify associated equipment +3. **Managers**: Can modify setup/equipment details and manage permissions +4. **Owners**: Full control including deletion and ownership transfer + +**Best Practices**: +- **Setup Owners**: PI, lab manager, or senior lab members with equipment responsibility +- **Setup Managers**: Postdocs or experienced graduate students who primarily use specific rigs +- **Contributors**: Lab members who regularly use the equipment for their research +- **Members**: All lab members who might occasionally need access + +### Inventory and Stock Permissions + +**Access Control Strategy**: +- **Expensive/Sensitive Equipment**: Limited to trained users (e.g., two-photon microscopes, specialized recording systems) +- **Common Lab Supplies**: Broad access for all lab members (basic consumables, standard tools) +- **Controlled Substances**: Restricted to authorized personnel only (drugs, viral vectors) +- **Technique-Specific Items**: Access based on training and project needs (electrophysiology probes, imaging dyes) +- **Shared Equipment**: Consider training requirements and scheduling protocols + +### Group-Based Access + +**Recommended Group Structure**: +``` +Lab Members (Basic access to most lab resources) +├── Graduate Students (Access to setups and equipment for their projects) +├── Postdocs (Broader access, can manage equipment in their research areas) +├── Lab Manager (Administrative access, inventory management) +├── PI and Senior Staff (Full ownership and administrative control) +└── Technique-Specific Groups (Optional, for specialized equipment) + ├── Electrophysiology Users (Access to recording equipment and probes) + ├── Imaging Users (Access to microscopes and imaging supplies) + └── Behavior Users (Access to behavioral setups and paradigms) +``` + +## Best Practices and Conventions + +### Naming Conventions + +**Setups**: +- Include location: "Room302_TmaxeBehavior", "Surgery_Station1" +- Be specific: "HeadFixed_2P_VR" not just "Microscope" + +**Equipment**: +- Include model and serial: "IntanRHD2000_SN1234" +- Use sequential numbering: "BehaviorCamera_01", "BehaviorCamera_02" + +**Inventories**: +- Clear categories: "Probes_RoomTemp", "Viruses_Minus80" +- Include storage info: "Drugs_ControlledSafe", "Disposables_Cabinet3" + +**Consumable Stocks**: +- Include lot numbers: "AAV_ChR2_Lot089" +- Specify concentrations: "Ketamine_100mgml_Vial3" + +### Documentation Standards + +**Equipment Descriptions Should Include**: +- Technical specifications (channels, resolution, power) +- Calibration status and procedures +- Maintenance schedules and contacts +- Safety considerations and restrictions + +**Inventory Descriptions Should Include**: +- Physical location with specific details +- Storage conditions and requirements +- Access procedures and restrictions +- Responsible persons and contacts + +### Maintenance and Updates + +**Regular Review Schedule**: +- **Monthly**: Update consumable stock levels and expirations +- **Quarterly**: Review equipment status and calibrations +- **Annually**: Audit inventory organization and permissions + +**Change Management**: +- Document equipment modifications or replacements +- Update permissions when lab members change roles +- Archive old/retired equipment rather than deleting +- Maintain chain of custody for controlled substances + +## Integration with Experimental Workflows + +### Using Infrastructure in Procedures + +When creating procedures, your infrastructure components become available: +- **Setups** provide the location context +- **Equipment** specifies tools used (stereotaxic frames, injection systems) +- **Consumable stocks** track materials consumed (probes, viruses, drugs) + +### Using Infrastructure in Sessions + +Your setup determines available: +- **Equipment** for data acquisition modules +- **Behavioral paradigms** compatible with the environment type +- **Associated consumables** for tracking usage + +### API Integration + +Access your infrastructure programmatically: + +```python +from brainstem_api_client import BrainstemClient + +client = BrainstemClient() + +# Get all setups for planning experiments +setups = client.load_model('setup').json() + +# Find equipment in a specific setup +equipment = client.load_model('equipment', + filters={'setup__name': 'Behavior Room A'}).json() + +# Check consumable stock levels +stocks = client.load_model('consumablestock', + filters={'inventory__name': 'Neural Probes'}).json() +``` + +## Troubleshooting Common Issues + +### Setup Not Available in Session Creation + +**Problem**: Cannot select setup when creating behaviors or data acquisition + +**Solutions**: +- Verify you are authenticated to use the setup +- Check that setup has appropriate environment type for your needs +- Ensure the setup is saved and properly configured + +### Equipment Missing from Dropdowns + +**Problem**: Equipment doesn't appear when creating procedures or modules + +**Solutions**: +- Confirm equipment is assigned to the correct setup +- Confirm the equipment type is aligned with the type of procedure, data acquisition or manipulation. +- Verify permissions match between session projects and equipment +- Check that hardware device is properly linked + +### Consumable Stock Access Issues + +**Problem**: Cannot access or modify consumable stocks + +**Solutions**: +- Verify group membership for inventory access +- Check owner/manager permissions for modification rights +- Ensure consumable is linked to correct inventory + +### Permission Synchronization + +**Problem**: Changes to permissions don't take effect immediately + +**Solutions**: +- Check group membership at multiple levels (setup, inventory, project) +- Contact administrators for permission inheritance issues + +## Advanced Configuration + +### Shared Resource Management + +For equipment shared across multiple labs: + +- Use group-based permissions for cross-lab access +- Create separate inventories for shared vs. lab-specific items +- Establish clear protocols for scheduling and maintenance + +### Custom Environment Types + +For specialized setups not covered by standard environment types: +- Submit any missing environment types to BrainSTEM administrators +- Use "Other" environment type with detailed descriptions +- Document custom specifications in setup descriptions + +By following this tutorial, you'll establish a robust infrastructure foundation that supports efficient experiment creation, accurate resource tracking, and seamless collaboration within your lab. Proper infrastructure setup is an investment that pays dividends in experimental productivity and data organization. + +## Next Steps + +With your lab infrastructure in place, you're ready to move on to experimental workflows: + +- **Start with experimental design**: Learn about [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms) to define standardized experimental protocols that use your setups +- **Set up data management**: Configure [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to link your metadata to actual data files stored on your systems +- **Organize team access**: Set up [Managing Groups]({{site.baseurl}}/tutorials/managing-groups) and [Managing Projects]({{site.baseurl}}/tutorials/managing-projects) to properly organize team access to your infrastructure +- **Explore complete workflows**: Follow either the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials for end-to-end experimental documentation +- **Contribute to the platform**: Use [Submit Resources & Taxonomies]({{site.baseurl}}/tutorials/submit-resource-and-taxonomies) to add any missing equipment or consumable types to the BrainSTEM database diff --git a/docs/tutorials/sharing-project-publicly.md b/docs/tutorials/sharing-project-publicly.md index 70dfa6f..fda9f8b 100644 --- a/docs/tutorials/sharing-project-publicly.md +++ b/docs/tutorials/sharing-project-publicly.md @@ -108,3 +108,11 @@ After making items public, verify their accessibility: 1. Visit the public dashboard at [www.brainstem.org/public](https://www.brainstem.org/public) 2. Search for your shared project or attributes 3. Verify that all components are accessible as expected + +## Next Steps + +After making your data publicly available, consider these additional steps: + +- **Enhance discoverability**: Use [Submit Resources & Taxonomies]({{site.baseurl}}/tutorials/submit-resource-and-taxonomies) to contribute standardized resources that make your data more findable and usable by the research community +- **Document methodologies**: Ensure your [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms) are well-documented and publicly accessible for protocol reproducibility +- **Optimize data accessibility**: Review your [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) configuration to ensure public data has appropriate access protocols \ No newline at end of file diff --git a/docs/tutorials/submit-resource-and-taxonomies.md b/docs/tutorials/submit-resource-and-taxonomies.md index d3541fa..f046421 100644 --- a/docs/tutorials/submit-resource-and-taxonomies.md +++ b/docs/tutorials/submit-resource-and-taxonomies.md @@ -33,19 +33,60 @@ Taxonomies that can be submitted: ## Submission Process -1. Navigate to the appropriate section in BrainSTEM +### Before Submitting + +1. **Check for existing entries:** Search the current lists to avoid duplicating existing resources or taxonomies +2. **Gather complete information:** Ensure you have all necessary details like specifications, supplier information, or scientific classifications +3. **Verify accuracy:** Double-check names, spellings, and technical details + +### Submitting New Entries + +1. Navigate to the appropriate section in BrainSTEM: + - For resources: Go to *Resources* → select the type (Consumables, Hardware devices, or Suppliers) + - For taxonomies: Go to *Taxonomies* → select the type (Setup types, Species, or Strains) + 2. Click the *Add* button for the resource or taxonomy type -3. Fill out the submission form with all required fields -4. Submit the form for review + +3. Fill out the submission form with all required fields: + - **For consumables:** Include product name, supplier, specifications + - **For hardware devices:** Provide manufacturer, model, specifications, interface details + - **For species/strains:** Include scientific names, common names, description + +4. Add detailed descriptions to help other users understand when to use this entry + +5. Submit the form for admin review {: .note } -> Review existing entries before submitting to avoid duplicates. Each resource/taxonomy type has specific required fields detailed in their respective documentation pages. +> Provide as much detail as possible in descriptions. This helps admins review submissions faster and helps other users select the correct entries. + +### Common Submission Guidelines + +- **Use standard nomenclature:** Follow established scientific naming conventions +- **Include references:** Add citations for taxonomies based on published atlases or classifications +- **Be specific:** "Silicon probe, 32-channel, A1x32-Poly2" is better than just "Silicon probe" +- **Check spelling:** Typos can lead to rejection or confusion ## Tracking Submissions +### Monitoring Status + 1. Go to [https://www.brainstem.org/private/approvals/](https://www.brainstem.org/private/approvals/) -2. View the status of your submissions -3. Respond to any admin feedback if needed +2. View the status of your submissions: + - **Pending:** Under admin review + - **Approved:** Accepted and available to all users + - **Rejected:** Declined with feedback for revision +3. Check the "Comments" field for admin feedback or revision requests + +### Responding to Feedback + +If your submission needs revision: +1. Read the admin comments carefully +2. Make the suggested changes +3. Resubmit following the same process +4. Reference the original submission in your revision notes + +{: .tip } +> Admins may request clarification on specifications, ask for additional references, or suggest naming improvements. Addressing feedback promptly helps speed up the approval process. ## After Approval @@ -53,3 +94,13 @@ Once approved: - The entry becomes available in dropdown menus across BrainSTEM - All users can select and use the approved entry - The entry can be referenced in new submissions + +## Next Steps + +After successfully contributing resources and taxonomies to BrainSTEM, consider these logical progressions: + +- **Set Up Your Lab Infrastructure**: Use your newly approved resources in the [Setting Up Lab Infrastructure tutorial]({{site.baseurl}}/tutorials/setting-up-lab-infrastructure) to configure your own experimental setups with the equipment and suppliers you've contributed +- **Begin Experimental Documentation**: Start documenting your research using the [Get Started tutorial]({{site.baseurl}}/tutorials/get_started) and incorporate your approved resources into real experimental workflows +- **Explore Specific Workflows**: Depending on your research focus, dive into detailed experimental tutorials like [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) that will use your contributed resources +- **Organize Your Team**: Use [Managing Projects]({{site.baseurl}}/tutorials/managing-projects) and [Managing Groups]({{site.baseurl}}/tutorials/managing-groups) to organize access to your contributed resources across your research team +- **Continue Contributing**: As you discover new equipment, suppliers, or taxonomic categories in your research, continue expanding the BrainSTEM resource database by submitting additional entries diff --git a/docs/tutorials/two-photon-imaging-workflow.md b/docs/tutorials/two-photon-imaging-workflow.md new file mode 100644 index 0000000..f924606 --- /dev/null +++ b/docs/tutorials/two-photon-imaging-workflow.md @@ -0,0 +1,610 @@ +--- +layout: default +title: Two-Photon Imaging Workflow - Visual Cortex Population Dynamics +parent: Tutorials +nav_order: 10 +--- + +# Complete Two-Photon Imaging Workflow: Visual Cortex Population Dynamics +{: .no_toc} + +## Table of contents +{: .no_toc .text-delta } + +1. TOC +{:toc} + +## Introduction + +This comprehensive tutorial walks through a complete two-photon calcium imaging experiment in BrainSTEM, from subject preparation to data analysis. We'll document a visual cortex population dynamics study with head-fixed mice, demonstrating how to integrate subjects, procedures, behavioral paradigms, data acquisition, manipulations, and collections in a realistic research workflow. + +**Experimental Design Overview:** +- **Subjects**: Mouse cohort for visual cortex population imaging +- **Setup**: Head-fixed two-photon microscope with visual stimulus presentation +- **Sessions**: Cranial window surgery → Habituation → Visual stimulus sessions +- **Data**: Two-photon calcium imaging, visual stimuli, eye tracking +- **Analysis**: Population dynamics, stimulus response, retinotopy mapping + +{: .note } +> This tutorial assumes you have already set up your lab infrastructure (setups, equipment, inventories) as described in the [Setting Up Lab Infrastructure tutorial]({{site.baseurl}}/tutorials/setting-up-lab-infrastructure). + +## Part A: Project and Subject Setup + +### Step 1: Creating the Research Project + +First, we'll create a project to organize our visual cortex imaging study. + +1. **Navigate to Projects**: + - Go to *Projects* + - Click *Add project* + +**[SCREENSHOT NEEDED: Project creation interface]** + +2. **Configure Project Details**: + +| Field | Value | +|-------|-------| +| **Name** | Visual Cortex Population Dynamics Study | +| **Description** | Investigating population-level neural dynamics in mouse visual cortex using two-photon calcium imaging during visual stimulus presentation. Study focuses on orientation selectivity, population correlations, and stimulus-response relationships in layer 2/3 neurons. | +| **Publications** | Related to ongoing visual cortex research | +| **Tags** | two-photon, visual-cortex, calcium-imaging, mice | +| **Authenticated Groups** | Select groups that should have access to this project | +| **Public Access** | No (keep project private to lab) | + +{: .note } +> For two-photon imaging studies, include information about the calcium indicator, imaging parameters, and visual stimulus paradigms in the project description. Authenticated groups will get contribute permissions. You can add additional groups or change permissions in the manage page: Go to *Project detail page* → *Manage* + +### Step 2: Adding Individual Subjects + +Now we'll add individual mice that will participate in our imaging study. + +1. **Navigate to Add Subject**: + - Go to *Subjects* + - Click *Add subject* + +**[SCREENSHOT NEEDED: Subject creation interface]** + +2. **Subject Configuration Example**: + +| Field | Value | +|-------|-------| +| **Name** | VC_M001 | +| **Projects** | Select: Visual Cortex Population Dynamics Study | +| **Sex** | Male | +| **Species** | Select: Mus musculus | +| **Strain** | Select: C57BL/6J | +| **Description** | Male C57BL/6J mouse for visual cortex two-photon calcium imaging study. Express GCaMP6f via viral injection. | +| **Genetic Line** | Wild type | +| **Birth Date** | 2024-06-15 | +| **Subject Identifier** | Ear punch: Left ear, position 2 | + +**Repeat this process to create additional subjects:** +- VC_M002, VC_M003, VC_M004 (for a cohort of 4 mice) +- Use similar configurations but update IDs and ear punch patterns + +{: .note } +> The additional subjects can be duplicated from the first subject. Go to the *Subject detail page of the first subject* → *Duplicate* +> Fill in the new subject name and click Duplicate. After this you can alter other fields if necessary. + +### Step 2b: Document Initial Housing and Weight + +After creating subjects, document their housing conditions and initial weights using subject logs. + +1. **Create Housing Log**: + - Go to *Modules* → *Subject logs* + - Click *Add subject log* + +**Housing Log Configuration:** +| Field | Value | +|-------|-------| +| **Type** | Housing log | +| **Subject** | Select: VC_M001 | +| **Description** | Standard housing for imaging cohort mice | +| **Start and end time** | 2024-07-01 08:00:00 to 2024-12-31 18:00:00 | +| **Notes** | Single housed post-surgery. Standard mouse cages with enrichment. | + +**Type-specific Details:** +| Field | Value | +|-------|-------| +| **Location** | Animal Facility Room 105 | +| **Cage ID** | Cage_B3_single | +| **Cage type** | Standard mouse cage (32×18×14 cm) | +| **Light cycle** | 12:12 light-dark cycle (lights on 06:00) | +| **Enrichment** | Paper nesting material, plastic igloo | + +2. **Create Initial Weighing Log**: + +**Weighing Log Configuration:** +| Field | Value | +|-------|-------| +| **Type** | Weighing log | +| **Subject** | Select: VC_M001 | +| **Description** | Baseline weight before surgical procedures | +| **Date and time** | 2024-07-01 09:00:00 | +| **Notes** | Pre-surgery baseline weight. Animal healthy and active. | + +**Type-specific Details:** +| Field | Value | +|-------|-------| +| **Weight (grams)** | 24.5 | + +### Step 3: Creating the Experimental Cohort + +After creating individual subjects, group them into a cohort for experimental organization. + +1. **Navigate to Cohorts**: + - Go to *Personal Attributes* → *Cohorts* + - Click *Add cohort* + +**[SCREENSHOT NEEDED: Cohort creation interface]** + +2. **Configure Cohort Details**: + +| Field | Value | +|-------|-------| +| **Name** | VC_Imaging_Cohort_1 | +| **Project** | Select: Visual Cortex Population Dynamics Study | +| **Subjects** | Select: VC_M001, VC_M002, VC_M003, VC_M004 | +| **Description** | First experimental cohort for visual cortex two-photon imaging study. 4 male C57BL/6J mice, age-matched, with viral GCaMP6f expression. Single housed post-surgery, 12:12 light cycle, standard chow ad libitum. | +| **Tags** | visual-cortex, two-photon, gcamp6f, male-mice | + +**[ILLUSTRATION NEEDED: Flowchart showing project → subjects → cohort → experiment relationship]** + +### Step 4: Equipment and Setup Verification + +Verify your two-photon imaging setup includes all necessary equipment: + +**[SCREENSHOT NEEDED: Equipment list view filtered by imaging setup]** + +**Required Equipment**: +- Two-photon microscope system (Bruker/Thorlabs) +- Ti:Sapphire laser (Mai Tai, Chameleon) +- High-speed scanning system (resonant/galvo) +- Photo-multiplier tubes (PMTs) +- Head-fixation apparatus +- Visual stimulus presentation system +- Eye tracking camera +- Temperature control system + +## Part B: Surgical Procedures and Preparation + +### Step 5: Viral Injection Procedure + +Document the viral injection for calcium indicator expression. + +1. **Navigate to Procedures**: + - Go to *Modules* → *Procedures* + - Click *Add procedure* + +**[SCREENSHOT NEEDED: Procedure creation interface]** + +2. **Viral Injection Configuration**: + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Type** | Virus injection | +| **Subject** | Select: VC_M001 | +| **Date and time** | 2024-07-15 10:00:00 | +| **Setup** | Select: Surgical Station | +| **Equipment** | Select: Stereotaxic Frame | +| **Inventory** | Select: Viral Vectors | +| **Consumable Stock** | Select: AAV1-syn-GCaMP6f | +| **Atlas** | Allen Mouse Brain Atlas | +| **Brain Region** | Visual cortex V1 | +| **Coordinate System** | Stereotaxic Bregma-Based Absolute Coordinates | +| **Notes** | Bilateral AAV injection for GCaMP6f expression in V1. Anesthesia: Isoflurane 2.0% for 45 minutes. Recovery: 3 weeks for expression. | + +**Coordinate Details (Type-specific fields):** +| Field | Value | +|-------|-------| +| **AP (mm)** | -3.0 | +| **ML (mm)** | ±2.5 (bilateral) | +| **DV (mm)** | -0.3 (layer 2/3) | +| **AP Angle** | 0° | +| **ML Angle** | 0° | + +**Injection Details:** +| Parameter | Value | +|-----------|-------| +| **Injection volume (nL)** | 500 | +| **Injection rate (nL/min)** | 100 | +| **Titer (units/mL)** | 1×10^13 | +| **Titer unit** | vg/mL | +| **Injection profile** | Bolus Injection | + +### Step 6: Cranial Window Surgery + +Document the cranial window implantation procedure. + +**Cranial Window Procedure Configuration:** + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Type** | Cranial window | +| **Subject** | Select: VC_M001 | +| **Date and time** | 2024-08-05 09:00:00 | +| **Setup** | Select: Surgical Station | +| **Equipment** | Select: Dental Drill, Stereotaxic Frame | +| **Inventory** | Select: Surgical Supplies | +| **Consumable Stock** | Select: Glass coverslip 3mm, Dental cement | +| **Atlas** | Allen Mouse Brain Atlas | +| **Brain Region** | Visual cortex V1 | +| **Notes** | 3mm diameter cranial window over binocular V1. Dura removed, sealed with 3mm glass coverslip. Dental cement head-plate attachment for head-fixation. | +| **Coordinate System** | Stereotaxic Bregma-Based Absolute Coordinates | + +**Window Specifications:** +| Parameter | Value | +|-----------|-------| +| **Method of cranial window** | Surgical drill | +| **Shape of cranial window** | Circular | +| **Length of cranial window (µm)** | 3000 | +| **Width of cranial window (µm)** | 3000 | +| **Thickness of cranial window (µm)** | 150 | +| **Orientation of cranial window** | 0° relative to midline | + +{: .note } +> Allow 1-2 weeks recovery before starting imaging sessions. Monitor for inflammation or coverslip clarity issues. + +**[ILLUSTRATION NEEDED: Cranial window placement diagram showing V1 location]** + +## Part C: Two-Photon Imaging Sessions + +### Step 7: Habituation Session + +Start with habituation to head-fixation and imaging setup. + +1. **Navigate to Sessions**: + - Go to *Modules* → *Sessions* + - Click *Add session* + +**[SCREENSHOT NEEDED: Session creation form for imaging]** + +2. **Habituation Session Configuration**: + +**Basic Session Information:** +| Field | Value | +|-------|-------| +| **Name** | VC_M001_Day1_Habituation | +| **Projects** | Select: Visual Cortex Population Dynamics Study | +| **Description** | Head-fixation habituation session. No imaging, just acclimatization to setup and handling procedures. | +| **Date_time_onset** | 2024-08-19 14:00:00 | +| **Tags** | habituation, head-fixation, baseline | +| **Data_storage** | /data/two-photon/vc_m001/ | + +**Behavioral Paradigm - Head Fixation:** +| Field | Value | +|-------|-------| +| **Name** | Head Fixation Habituation | +| **Environment Type** | Head-fixed setup | +| **Authenticated Groups** | Select your lab groups | +| **Description** | Habituation protocol for head-fixed two-photon imaging. 30-minute sessions with gradual increase in duration. Neutral gray screen, no visual stimuli. Water rewards for calm behavior. | +| **Public Access** | No | + +{: .note } +> Habituation sessions are crucial for reducing stress and motion artifacts in subsequent imaging sessions. + +### Step 8: Visual Stimulus Imaging Session + +The main experimental session combining visual stimulation with two-photon imaging. + +**[SCREENSHOT NEEDED: Two-photon imaging session interface]** + +1. **Visual Paradigm Setup**: + +| Field | Value | +|-------|-------| +| **Name** | Drifting Gratings Visual Stimuli | +| **Environment Type** | Head-fixed visual display | +| **Authenticated Groups** | Select your lab groups | +| **Description** | Drifting sine-wave gratings presented at 8 orientations (0°-315°, 45° steps). Each stimulus 2s duration, 4s inter-stimulus interval. 10 repeats per orientation, randomized presentation order. Screen distance 25cm, stimulus size 20° visual angle. | +| **Public Access** | No | + +2. **Complete Session Configuration**: + +**Basic Session Information:** +| Field | Value | +|-------|-------| +| **Name** | VC_M001_Day1_DriftingGratings | +| **Projects** | Select: Visual Cortex Population Dynamics Study | +| **Description** | Two-photon calcium imaging during drifting grating visual stimuli presentation | +| **Date_time_onset** | 2024-08-20 15:00:00 | +| **Tags** | imaging, visual-stimuli, drifting-gratings | +| **Data_storage** | /data/two-photon/vc_m001/ | + +**Data Acquisition - Two-Photon Imaging:** +| Setting | Value | +|---------|-------| +| **Session** | Select: VC_M001_Day1_DriftingGratings | +| **Type** | Two-Photon Microscopy | +| **Procedures** | Select: Cranial Window, Viral Injection | +| **Setup** | Select: 2P Imaging Rig | +| **Equipment** | Select: Two-Photon Microscope | +| **Notes** | Single plane imaging at 150μm depth in layer 2/3. GCaMP6f expression, 920nm excitation optimal for this indicator. | + +**Type-specific Details:** +| Field | Value | +|---------|-------| +| **Format** | TIFF | +| **Compression** | LZW | +| **Vertical resolution** | 512 | +| **Horizontal resolution** | 512 | +| **Frame rate (Hz)** | 15.5 | +| **Number of frames** | 46500 | +| **Laser power (mW)** | 25 | +| **Excitation wavelength (nm)** | 920 | +| **Imaging depth (μm)** | 150 | +| **Voxel size (X dimension)** | 0.65 | +| **Voxel size (Y dimension)** | 0.65 | +| **Voxel size (Z dimension)** | N/A | + +**Data Acquisition - Visual Stimuli:** +| Setting | Value | +|---------|-------| +| **Session** | Select: VC_M001_Day1_DriftingGratings | +| **Type** | General Time-Series | +| **Procedures** | Select: Cranial Window | +| **Setup** | Select: 2P Imaging Rig | +| **Equipment** | Select: Stimulus Computer | +| **Notes** | Visual stimulus timing and parameters. Drifting gratings, 8 orientations, 10 repeats each. | + +**Type-specific Details:** +| Field | Value | +|---------|-------| +| **Format** | CSV | +| **Data-type** | float32 | +| **Number of channels** | 3 | +| **Sampling rate (Hz)** | 60 | +| **Number of samples** | 108000 | + +**Data Acquisition - Eye Tracking:** +| Setting | Value | +|---------|-------| +| **Session** | Select: VC_M001_Day1_DriftingGratings | +| **Type** | Behavioral Tracking | +| **Procedures** | Select: Cranial Window | +| **Setup** | Select: 2P Imaging Rig | +| **Equipment** | Select: Eye Tracking Camera | +| **Notes** | Pupil tracking during visual stimulation. 60fps capture for pupil dilation analysis. | + +**Type-specific Details:** +| Field | Value | +|---------|-------| +| **Format** | AVI | +| **Compression** | H.264 | +| **Frame rate (Hz)** | 60 | +| **Number of frames** | 108000 | +| **Vertical resolution** | 480 | +| **Horizontal resolution** | 640 | + +**Session Epochs:** +| Epoch Name | Start (min) | Duration (min) | Description | +|------------|-------------|----------------|-------------| +| **Baseline** | 0 | 5 | Gray screen baseline recording | +| **Stimulus_presentation** | 5 | 25 | Drifting grating stimuli (8 orientations × 10 repeats) | +| **Post_stimulus** | 30 | 5 | Post-stimulus baseline recording | + +**[SCREENSHOT NEEDED: Two-photon imaging interface showing real-time calcium signals]** + +### Step 9: Retinotopy Mapping Session + +Create a session for visual field mapping. + +**Retinotopy Session Configuration:** + +**Basic Session Information:** +| Field | Value | +|-------|-------| +| **Name** | VC_M001_Day2_RetinotopyMapping | +| **Projects** | Select: Visual Cortex Population Dynamics Study | +| **Description** | Retinotopic mapping using moving bar stimuli to determine visual field organization | +| **Date_time_onset** | 2024-08-21 15:30:00 | +| **Tags** | retinotopy, mapping, visual-field | +| **Data_storage** | /data/two-photon/vc_m001/ | + +**Visual Paradigm:** +| Field | Value | +|-------|-------| +| **Name** | Retinotopic Bar Mapping | +| **Environment Type** | Head-fixed visual display | +| **Description** | Moving bar stimuli for retinotopic mapping. White bars on black background, 4 directions (horizontal/vertical), 2° width, 0.5°/s speed. Full screen sweep in each direction. | +| **Public Access** | No | + +**Data Acquisition - Two-Photon Imaging:** +| Setting | Value | +|---------|-------| +| **Session** | Select: VC_M001_Day2_RetinotopyMapping | +| **Type** | Two-Photon Microscopy | +| **Procedures** | Select: Cranial Window, Viral Injection | +| **Setup** | Select: 2P Imaging Rig | +| **Equipment** | Select: Two-Photon Microscope | +| **Notes** | Same imaging parameters as orientation session for consistency | + +**Type-specific Details:** +| Field | Value | +|---------|-------| +| **Format** | TIFF | +| **Compression** | LZW | +| **Vertical resolution** | 512 | +| **Horizontal resolution** | 512 | +| **Frame rate (Hz)** | 15.5 | +| **Number of frames** | 31000 | +| **Laser power (mW)** | 28 | +| **Excitation wavelength (nm)** | 920 | +| **Imaging depth (μm)** | 150 | +| **Voxel size (X dimension)** | 0.65 | +| **Voxel size (Y dimension)** | 0.65 | +| **Voxel size (Z dimension)** | N/A | + +## Part D: Advanced Imaging Features + +### Step 10: Multi-Depth Imaging Session + +Document sessions with z-stack or multiple imaging planes. + +**Multi-Depth Session Configuration:** + +**Basic Session Information:** +| Field | Value | +|-------|-------| +| **Name** | VC_M001_Day3_MultiDepth_Orientation | +| **Projects** | Select: Visual Cortex Population Dynamics Study | +| **Description** | Multi-depth two-photon imaging across cortical layers during orientation stimuli | +| **Date_time_onset** | 2024-08-22 14:00:00 | +| **Tags** | multi-depth, layers, orientation | +| **Data_storage** | /data/two-photon/vc_m001/ | + +**Data Acquisition - Layer 2/3:** +| Setting | Value | +|---------|-------| +| **Session** | Select: VC_M001_Day3_MultiDepth_Orientation | +| **Type** | Two-Photon Microscopy | +| **Procedures** | Select: Cranial Window, Viral Injection | +| **Setup** | Select: 2P Imaging Rig | +| **Equipment** | Select: Two-Photon Microscope | +| **Notes** | Layer 2/3 imaging plane | + +**Type-specific Details (Layer 2/3):** +| Field | Value | +|---------|-------| +| **Format** | TIFF | +| **Compression** | LZW | +| **Vertical resolution** | 512 | +| **Horizontal resolution** | 512 | +| **Frame rate (Hz)** | 15.5 | +| **Number of frames** | 46500 | +| **Laser power (mW)** | 25 | +| **Excitation wavelength (nm)** | 920 | +| **Imaging depth (μm)** | 150 | +| **Voxel size (X dimension)** | 0.65 | +| **Voxel size (Y dimension)** | 0.65 | +| **Voxel size (Z dimension)** | N/A | + +**Data Acquisition - Layer 4:** +| Setting | Value | +|---------|-------| +| **Session** | Select: VC_M001_Day3_MultiDepth_Orientation | +| **Type** | Two-Photon Microscopy | +| **Procedures** | Select: Cranial Window, Viral Injection | +| **Setup** | Select: 2P Imaging Rig | +| **Equipment** | Select: Two-Photon Microscope | +| **Notes** | Layer 4 imaging plane - increased laser power for deeper imaging | + +**Type-specific Details (Layer 4):** +| Field | Value | +|---------|-------| +| **Format** | TIFF | +| **Compression** | LZW | +| **Vertical resolution** | 512 | +| **Horizontal resolution** | 512 | +| **Frame rate (Hz)** | 15.5 | +| **Number of frames** | 46500 | +| **Laser power (mW)** | 35 | +| **Excitation wavelength (nm)** | 920 | +| **Imaging depth (μm)** | 250 | +| **Voxel size (X dimension)** | 0.65 | +| **Voxel size (Y dimension)** | 0.65 | +| **Voxel size (Z dimension)** | N/A | + +### Step 11: Adding Optogenetic Manipulations (Optional) + +For experiments combining imaging with optogenetic perturbations. + +**[SCREENSHOT NEEDED: Manipulation configuration for optogenetics]** + +**Optogenetic Manipulation Configuration:** + +**Basic Information:** +| Field | Value | +|-------|-------| +| **Session** | Select: VC_M001_Day4_OptoStim | +| **Type** | Optogenetic stimulation | +| **Procedures** | Select: Viral Injection (ChR2), Cranial Window | +| **Setup** | Select: 2P Imaging Rig | +| **Equipment** | Select: Blue LED System | +| **Notes** | ChR2 activation during visual stimuli presentation | + +**Type-specific Details:** +| Parameter | Value | +|-----------|-------| +| **Power (mW)** | 5.0 | +| **Amplitude (A)** | 0.2 | +| **Stimulation profile** | Biphasic | +| **Duration (s)** | 2.0 | +| **Duty cycle** | 0.5 | +| **Repetitions** | 20 | +| **Wavelength (nm)** | 473 | +| **Closed loop** | false | + +## Part E: Data Organization and Analysis Integration + +### Step 12: Subject Health Monitoring + +Track post-surgical recovery and imaging session performance. + +**[SCREENSHOT NEEDED: Subject log for imaging studies]** + +**Wellness Log Configuration:** +| Field | Value | +|-------|-------| +| **Type** | Wellness log | +| **Subject** | Select: VC_M001 | +| **Description** | Post-surgical recovery and imaging session monitoring | +| **Date and time** | 2024-08-20 18:00:00 | +| **Notes** | Excellent imaging session. Clear cranial window, strong GCaMP signals, minimal motion artifacts. Animal alert and responsive. | + +**Type-specific Details:** +| Field | Value | +|-------|-------| +| **Wellness** | Excellent - active, responsive, clear window | + +### Step 13: Creating Collections for Analysis + +Group related imaging sessions for comprehensive analysis. + +**[SCREENSHOT NEEDED: Collection creation for imaging data]** + +**Collection Configuration:** + +| Field | Value | +|-------|-------| +| **Name** | VC_M001_Orientation_Tuning_Week1 | +| **Project** | Select: Visual Cortex Population Dynamics Study | +| **Sessions** | Select: VC_M001_Day1_DriftingGratings, VC_M001_Day2_RetinotopyMapping, VC_M001_Day3_MultiDepth_Orientation | +| **Description** | First week orientation tuning and retinotopy sessions for VC_M001. Includes single-plane and multi-depth imaging with drifting gratings and retinotopic mapping stimuli. | +| **Tags** | orientation-tuning, retinotopy, calcium-imaging, week1 | + +### Step 14: API Data Access for Analysis + +Access your imaging data programmatically for analysis. + +```python +from brainstem_api_client import BrainstemClient +import numpy as np +import matplotlib.pyplot as plt + +client = BrainstemClient() + +# Get all imaging sessions for a subject +imaging_sessions = client.load_model('session', + filters={'projects__name': 'Visual Cortex Population Dynamics Study'}).json() + +# Get two-photon data acquisition details +imaging_data = client.load_model('dataacquisition', + filters={'session__projects__name': 'Visual Cortex Population Dynamics Study', + 'type': 'Two-Photon Microscopy'}).json() + +# Download specific imaging session data +session_data = client.download_session_data('vc_m001_day1_gratings_id') +``` + +## Next Steps + +After completing this comprehensive two-photon imaging workflow, consider these logical progressions: + +- **Cross-Modal Experiments**: Review the [Electrophysiology Workflow tutorial]({{site.baseurl}}/tutorials/electrophysiology-workflow) to learn how to combine two-photon imaging with simultaneous electrophysiology recordings for comprehensive neural circuit analysis +- **Data Storage Optimization**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to efficiently organize and access your large imaging datasets +- **API Integration**: Master the [Python API tool]({{site.baseurl}}/tutorials/python-api-tool) or [MATLAB API tool]({{site.baseurl}}/tutorials/matlab-api-tool) tutorials to programmatically access your imaging data for automated analysis workflows +- **Behavioral Integration**: Explore [Behavioral Paradigms]({{site.baseurl}}/tutorials/behavioral-paradigms) to understand how to combine imaging with more complex behavioral tasks +- **Data Sharing and Collaboration**: Learn about [Sharing Project Publicly]({{site.baseurl}}/tutorials/sharing-project-publicly) to make your imaging datasets available to the research community and enable collaborative analysis From 85a9242888c9a7bf76b036312c89cea95ed4ccfd Mon Sep 17 00:00:00 2001 From: MingzeDou Date: Tue, 30 Sep 2025 14:18:22 +0200 Subject: [PATCH 02/16] Update electrophysiology-workflow.md --- docs/tutorials/electrophysiology-workflow.md | 27 ++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/tutorials/electrophysiology-workflow.md b/docs/tutorials/electrophysiology-workflow.md index 26277d2..9ee6343 100644 --- a/docs/tutorials/electrophysiology-workflow.md +++ b/docs/tutorials/electrophysiology-workflow.md @@ -93,6 +93,7 @@ After creating subjects, document their housing conditions and initial weights u - Click *Add subject log* **Housing Log Configuration:** + | Field | Value | |-------|-------| | **Type** | Housing log | @@ -100,6 +101,7 @@ After creating subjects, document their housing conditions and initial weights u | **Description** | Initial housing assignment for experimental cohort | **Type-specific Details:** + | Field | Value | |-------|-------| | **Start and end time** | 2024-08-01 08:00:00 to 2024-12-31 18:00:00 | @@ -116,12 +118,14 @@ After creating subjects, document their housing conditions and initial weights u 2. **Create Initial Weighing Log**: **Weighing Log Configuration:** + | Field | Value | |-------|-------| | **Type** | Weighing log | | **Subject** | Select: TM_R001 | **Type-specific Details:** + | Field | Value | |-------|-------| | **Weight (grams)** | 385 | @@ -178,6 +182,7 @@ Document the surgical procedure for Neuropixels probe implantation. 2. **Procedure Configuration**: **Basic Information:** + | Field | Value | |-------|-------| | **Type** | Silicon probe implant | @@ -193,6 +198,7 @@ Document the surgical procedure for Neuropixels probe implantation. | **Coordinates System** | Stereotaxic Bregma-Based Surface Coordinates with Depth | **Coordinate Details (Type-specific fields):** + | Field | Value | |-------|-------| | **AP coordinate (mm)** | -3.5 | @@ -203,10 +209,7 @@ Document the surgical procedure for Neuropixels probe implantation. | **Rotation** | 0° | {: .note } -> Probe specifications (Neuropixels 1.0: 960 total sites, 384 recording sites, 20 μm spacing, etc.) are documented in the consumable stock entry, not in the procedure record. You can also document the Isoflurance anesthesia, Head fixation, Craniotomy, and the Headcap, but we will leave that out for brevity. - -``` -``` +> Probe specifications (Neuropixels 1.0: 960 total sites, 384 recording sites, 20 μm spacing, etc.) are documented in the consumable stock entry, not in the procedure record. You can also document the Isoflurane anesthesia, Head fixation, Craniotomy, and the Headcap, but we will leave that out for brevity. **[ILLUSTRATION NEEDED: Brain atlas diagram showing electrode placement coordinates]** @@ -225,6 +228,7 @@ After recovery, we begin with a baseline sleep recording. 2. **Sleep Session Configuration**: **Basic Session Information:** + | Field | Value | |-------|-------| | **Name** | TM_R001_Day1_PreSleep_Baseline | @@ -237,6 +241,7 @@ After recovery, we begin with a baseline sleep recording. > Sessions don't have subject, setup, duration, or behavioral paradigm fields directly. These are specified in the Behavior, Data acquisition and Epoch tabs within the session. **Data Acquisition - Extracellular Recording:** + | Setting | Value | |---------|-------| | **Type** | Extracellular Electrophysiology | @@ -251,6 +256,7 @@ After recovery, we begin with a baseline sleep recording. | **Least significant bit (μV/bit)** | 0.195 | **Data Acquisition - Video:** + | Setting | Value | |---------|-------| | **Session** | Select: TM_R001_Day1_PreSleep | @@ -261,6 +267,7 @@ After recovery, we begin with a baseline sleep recording. | **Notes** | Sleep state monitoring | **Session Epochs:** + | Epoch Name | Start (min) | Duration (min) | Description | |------------|-------------|----------------|-------------| | **Habituation** | 0 | 30 | Adaptation to recording environment | @@ -287,6 +294,7 @@ The main experimental session combining behavior with neural recording. 2. **Complete Session Configuration**: **Basic Session Information:** + | Field | Value | |-------|-------| | **Name** | TM_R001_Day1_ThetaMaze_Training1 | @@ -297,6 +305,7 @@ The main experimental session combining behavior with neural recording. | **Data_storage** | /data/neuropixels/tm_r001/ | **Data Acquisition - Extracellular Recording:** + | Setting | Value | |---------|-------| | **Session** | Select: TM_R001_Day1_Behavior | @@ -312,6 +321,7 @@ The main experimental session combining behavior with neural recording. | **Least significant bit (μV/bit)** | 0.195 | **Data Acquisition - Video:** + | Setting | Value | |---------|-------| | **Session** | Select: TM_R001_Day1_Behavior | @@ -322,6 +332,7 @@ The main experimental session combining behavior with neural recording. | **Notes** | Behavioral video recording with LED tracking | **Data Acquisition - Position Tracking:** + | Setting | Value | |---------|-------| | **Session** | Select: TM_R001_Day1_Behavior | @@ -332,6 +343,7 @@ The main experimental session combining behavior with neural recording. | **Notes** | Head and body position tracking with LED markers | **Session Epochs:** + | Epoch Name | Start (min) | Duration (min) | Description | |------------|-------------|----------------|-------------| | **Pre_task_baseline** | 0 | 10 | Open field exploration before task | @@ -350,16 +362,18 @@ For experiments with optogenetic or pharmacological manipulations. **Manipulation Configuration:** **Basic Information:** + | Field | Value | |-------|-------| | **Session** | Select: TM_R001_Day1_Behavior | -| **Type** | Optogenetical stimulation | +| **Type** | Optogenetic stimulation | | **Procedures** | Select: Neuropixels Implantation | | **Setup** | Select: Theta Maze Rig | | **Equipment** | Select: Yellow Laser System | | **Notes** | PV interneuron silencing during choice trials | **Type-specific Details:** + | Parameter | Value | |-----------|-------| | **Power (mW)** | 10.0 | @@ -378,6 +392,7 @@ Capture sleep-dependent replay and consolidation. **Post-Sleep Session Configuration:** **Basic Session Information:** + | Field | Value | |-------|-------| | **Name** | TM_R001_Day1_PostSleep_Consolidation | @@ -388,6 +403,7 @@ Capture sleep-dependent replay and consolidation. | **Data_storage** | /data/neuropixels/tm_r001/ | **Data Acquisition - Extracellular Recording:** + | Setting | Value | |---------|-------| | **Session** | Select: TM_R001_Day1_PostSleep_Consolidation | @@ -402,6 +418,7 @@ Capture sleep-dependent replay and consolidation. | **Number of samples** | 648000000 | **Session Epochs:** + | Epoch Name | Start (min) | Duration (min) | Description | |------------|-------------|----------------|-------------| | **Post_behavior_rest** | 0 | 60 | Immediate post-behavior period | From 67bafb6f7db194cdc8000acad80542e710b0deb7 Mon Sep 17 00:00:00 2001 From: "Peter C. Petersen" Date: Wed, 1 Oct 2025 18:08:12 +0200 Subject: [PATCH 03/16] Updated tutorials for ephys and 2p --- docs/tutorials/electrophysiology-workflow.md | 46 ++++++++----------- docs/tutorials/two-photon-imaging-workflow.md | 12 ++--- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/docs/tutorials/electrophysiology-workflow.md b/docs/tutorials/electrophysiology-workflow.md index 9ee6343..a24d84f 100644 --- a/docs/tutorials/electrophysiology-workflow.md +++ b/docs/tutorials/electrophysiology-workflow.md @@ -1,19 +1,13 @@ --- layout: default -title: Complete Electrophysiology Workflow - Theta Maze with Sleep Sessions +title: Ephys Workflow parent: Tutorials nav_order: 9 --- -# Complete Electrophysiology Workflow: Theta Maze with Sleep Sessions +# Ephys Workflow: Theta Maze with Sleep Sessions {: .no_toc} -## Table of contents -{: .no_toc .text-delta } - -1. TOC -{:toc} - ## Introduction This tutorial walks through a complete electrophysiology experiment in BrainSTEM, from subject preparation to data analysis. We'll document a multi-day theta maze learning study with sleep sessions, demonstrating how to integrate subjects, procedures, behavioral paradigms, data acquisition, manipulations, and collections in a realistic research workflow. @@ -32,7 +26,7 @@ This tutorial walks through a complete electrophysiology experiment in BrainSTEM ### Step 1: Creating the Research Project -First, we'll create a project to organize and provide context for our experimental work. +First, we'll create a project to organize and provide context for our experimental work. The project submission is split in two steps. First, you fill in required details, after which you can add other details. Required fields are highlighted with an asterix (*) in the web interface and this tutorial. 1. **Navigate to Projects**: - Go to *Projects* @@ -44,13 +38,13 @@ First, we'll create a project to organize and provide context for our experiment | Field | Value | |-------|-------| -| **Name** | Theta Maze Spatial Learning Study | +| **Name** * | Theta Maze Spatial Learning Study | | **Description** | Investigating hippocampal place cell dynamics and memory consolidation during spatial learning using theta maze behavioral paradigm with simultaneous Neuropixels recordings in freely moving rats. | | **Authenticated Groups** | Select groups that should have access to this project | | **Public Access** | No (keep project private to lab) | {: .note } -> Additional project details like PI name, funding source, IACUC protocol numbers, and timeline information can be included in the project description or managed through your lab's separate project management systems. Authenticated groups will get contribute permissions. You can add additional groups or change permissions in the manage page: Go to *Project detail page* → *Manage* +> Once submitted other details can be added. Additional project details like PI name, funding source, IACUC protocol numbers, and timeline information can be included in the project description or managed through your lab's separate project management systems. Authenticated groups will get contribute permissions. You can add additional groups or change permissions in the manage page: Go to *Project detail page* → *Manage* ### Step 2: Adding Individual Subjects @@ -66,11 +60,11 @@ Now we'll add individual rats that will participate in our study. | Field | Value | |-------|-------| -| **Name** | TM_R001 | -| **Projects** | Select: Theta Maze Spatial Learning Study | -| **Sex** | Male | -| **Species** | Select: Rattus norvegicus | -| **Strain** | Select: Long-Evans | +| **Name** * | TM_R001 | +| **Projects** * | Select: Theta Maze Spatial Learning Study | +| **Sex** * | Male | +| **Species** * | Select: Rattus norvegicus | +| **Strain** * | Select: Long-Evans | | **Description** | Male Long-Evans rat for theta maze spatial learning study with Neuropixels recordings | | **Genetic Line** | Wild type | | **Birth Date** | 2024-05-01 | @@ -161,21 +155,17 @@ Verify your theta maze setup includes all necessary equipment: **[SCREENSHOT NEEDED: Equipment list view filtered by setup]** **Required Equipment**: -- Neuropixels recording system (IMEC basestation) -- Open Ephys acquisition board -- Ceiling-mounted behavior camera (Basler) -- OptiTrack motion capture system (6+ cameras) -- Theta maze apparatus -- Reward delivery system -- LED position markers +- Neuropixels data acquisition system (IMEC - Neuropixels OneBox) +- Ceiling-mounted camera for behavioral tracking (Basler - acA640-90uc) +- OptiTrack motion capture system for 3D head tracking (6+ cameras OptiTrack - Flex 13) ### Step 5: Neuropixels Probe Implantation Procedure Document the surgical procedure for Neuropixels probe implantation. 1. **Navigate to Procedures**: - - Go to *Procedures* (below Subjects) - - Click *Add procedure* + - Go to *Subjects* (below Subjects) + - Click Edit for subject *TM_R001* **[SCREENSHOT NEEDED: Procedure creation interface]** @@ -191,13 +181,13 @@ Document the surgical procedure for Neuropixels probe implantation. | **Setup** | Select: Surgical Station | | **Equipment** | Select: Stereotaxic Frame | | **Inventory** | Select: Neural Electrode Inventory | -| **Consumable Stock** | Select: Neuropixels 1.0 probe (#001) | +| **Consumable Stock** | Select: Neuropixels 2.0 probe | | **Atlas** | Allen Mouse Brain Atlas | | **Brain Region** | HIP: Hippocampal region | | **Notes** | Chronic Neuropixels probe implantation targeting CA1/CA3 hippocampus. | | **Coordinates System** | Stereotaxic Bregma-Based Surface Coordinates with Depth | -**Coordinate Details (Type-specific fields):** +**Coordinate Details:** | Field | Value | |-------|-------| @@ -209,7 +199,7 @@ Document the surgical procedure for Neuropixels probe implantation. | **Rotation** | 0° | {: .note } -> Probe specifications (Neuropixels 1.0: 960 total sites, 384 recording sites, 20 μm spacing, etc.) are documented in the consumable stock entry, not in the procedure record. You can also document the Isoflurane anesthesia, Head fixation, Craniotomy, and the Headcap, but we will leave that out for brevity. +> Probe specifications (Neuropixels 2.0: 960 total sites, 384 recording sites, 20 μm spacing, etc.) are documented in the consumable stock entry, not in the procedure record. You can also document the Isoflurane anesthesia, Head fixation, Craniotomy, and the Headcap, but we will leave that out for brevity. **[ILLUSTRATION NEEDED: Brain atlas diagram showing electrode placement coordinates]** diff --git a/docs/tutorials/two-photon-imaging-workflow.md b/docs/tutorials/two-photon-imaging-workflow.md index f924606..bc0c71e 100644 --- a/docs/tutorials/two-photon-imaging-workflow.md +++ b/docs/tutorials/two-photon-imaging-workflow.md @@ -1,20 +1,14 @@ --- layout: default -title: Two-Photon Imaging Workflow - Visual Cortex Population Dynamics +title: 2P Imaging Workflow parent: Tutorials nav_order: 10 --- -# Complete Two-Photon Imaging Workflow: Visual Cortex Population Dynamics +# Draft: Two-Photon Workflow: Visual Cortex Population Dynamics {: .no_toc} -## Table of contents -{: .no_toc .text-delta } - -1. TOC -{:toc} - -## Introduction +## Introduction - Note: this tutorial is still in a drafting state This comprehensive tutorial walks through a complete two-photon calcium imaging experiment in BrainSTEM, from subject preparation to data analysis. We'll document a visual cortex population dynamics study with head-fixed mice, demonstrating how to integrate subjects, procedures, behavioral paradigms, data acquisition, manipulations, and collections in a realistic research workflow. From 49d4f0226743a8e1e6408d07cdf24804718a23d1 Mon Sep 17 00:00:00 2001 From: MingzeDou Date: Thu, 2 Oct 2025 12:23:53 +0200 Subject: [PATCH 04/16] updated api tool doc --- docs/api-tools/python-api-tool.md | 198 ++++++++++++++++++++--- docs/tutorials/behavioral-paradigms.md | 9 +- docs/tutorials/managing-data-storage.md | 11 +- docs/tutorials/matlab-api-tool.md | 133 +--------------- docs/tutorials/python-api-tool.md | 200 +----------------------- 5 files changed, 199 insertions(+), 352 deletions(-) diff --git a/docs/api-tools/python-api-tool.md b/docs/api-tools/python-api-tool.md index 3207074..2860649 100644 --- a/docs/api-tools/python-api-tool.md +++ b/docs/api-tools/python-api-tool.md @@ -7,48 +7,202 @@ nav_order: 2 # Python API tool {: .no_toc} -### Installation +## Table of contents +{: .no_toc .text-delta } -Download the BrainSTEM Python API tools repository from GitHub at [github.com/brainstem-org/brainstem_python_api_tools](https://github.com/brainstem-org/brainstem_python_api_tools). +1. TOC +{:toc} -You can also install the package using `pip`: +## Overview - pip install brainstem_python_api_tools +The BrainSTEM Python API tool (`brainstem_python_api_tools`) provides a thin wrapper around the REST endpoints documented in the [STEM API reference]({{ "/api/stem/" | absolute_url }}). This page mirrors the structure of those docs while expanding on hands-on usage. Every snippet below has been tested against the public API; replace placeholders (for example, IDs) with values you can access in your own account. -### Tutorial -Please see the dedicated [tutorial]({{"/tutorials/python-api-tool/"|absolute_url}}) with examples on usage. The main functions are described below. +## Installation -| Function | Description | -|:-------------|:-------------| -| `BrainstemClient` | The Brainstem API client | -| `brainstem_api_tutorial` | Tutorial script | +Install the published package from PyPI (recommended) or clone the GitHub repository. +```bash +pip install brainstem_python_api_tools +``` -### Filters -You can use filters, using fields and relationships by providing cell array with paired filters. Below example will just load the session with the name: - +```bash +git clone https://github.com/brainstem-org/brainstem_python_api_tools.git ``` -from brainstem_api_client import BrainstemClient +## Authentication + +Initializing `BrainstemClient` prompts for your BrainSTEM email and password unless you supply a saved token. Tokens are stored locally in the API tool cache and reused automatically. + +```python +from brainstem_api_tools import BrainstemClient + +# Prompts for credentials the first time and caches a token client = BrainstemClient() +``` + +```python +# Use a saved token instead of prompting for credentials +token = "YOUR_TOKEN" +client = BrainstemClient(token=token) + +# Or load a token from a .env file (keep .env gitignored) +from dotenv import load_dotenv +import os +from brainstem_api_tools import BrainstemClient + +load_dotenv() +client = BrainstemClient(token=os.getenv("BRAINSTEM_API_TOKEN")) +``` + +If you receive a `401 Unauthorized` response, run `BrainstemClient()` again to refresh the cached token or pass a newly generated token explicitly. + +## Quick start + +Load projects using the private portal (default) or specify the public portal for open datasets. Response payloads follow the schema described in `docs/api/stem/project.md`. + +```python +public_projects = client.load_model("project", portal="public").json() + +projects = public_projects.get('projects', []) +print(f"Loaded {len(projects)} public projects") +if projects: + print(projects[0]["name"]) +``` + +Private data uses the default portal. Ensure the authenticated user has the necessary permissions, as outlined in the API docs. + +```python +private_sessions = client.load_model("session").json() + +sessions = private_sessions.get('sessions', []) +if sessions: + print(sessions[0]["name"]) +``` + +## Filtering requests + +Filters map directly onto the query parameters documented in the STEM API. Common case-insensitive modifiers include `.icontains`, `.iexact`, `.istartswith`, and `.iendswith`. + +```python +filtered = client.load_model( + "project", + portal="public", + filters={"name.icontains": "visual"} +).json()["projects"] -output1 = client.load_model('session', filters={'name': 'yeah'}).json() +print(f"Matches: {len(filtered)}") ``` -### Change sorting -Loaded models can be sorted by different criteria applying to their fields. In below example, sessions will be sorted in descending order according to their name. +Multiple filters apply AND logic. +```python +filtered = client.load_model( + "project", + portal="public", + filters={ + "name.icontains": "allen", + "description.icontains": "neuropixels" + } +).json()["projects"] + +print(f"Matches: {len(filtered)}") ``` -output1 = client.load_model('session', sort=['-name']).json() + +## Sorting results + +Provide field names in `sort`. Prefix a field with `-` for descending order, mirroring the API convention. + +```python +# Sort projects alphabetically by name +alpha_projects = client.load_model( + "project", + portal="public", + sort=['name'] # Ascending alphabetical order +).json() + +print("Alphabetically sorted projects:") +for i, project in enumerate(alpha_projects.get('projects', [])[:3]): + print(f"{i+1}. {project.get('name')}") + +# Sort projects reverse-alphabetically by name +reverse_alpha = client.load_model( + "project", + portal="public", + sort=['-name'] # Descending alphabetical order +).json() + +print("Reverse alphabetically sorted projects:") +for i, project in enumerate(reverse_alpha.get('projects', [])[:3]): + print(f"{i+1}. {project.get('name')}") ``` -### Include related models +## Creating records + +Write operations require contributor permissions on the target project or resource. Use `save_model` with the required fields documented in the relevant API page (for example, `docs/api/stem/session.md`). + +**Important**: The `projects` field must be a list (array) of project IDs, not a single string. -In some cases models contain relations with other models, and they can be also loaded with the models if requested. +```python +payload = { + "name": "Example Session", + "projects": ["your-project-uuid"], # Must be a list, not a string! + "description": "Created via API tool" +} -In below example, all the projects, data acquisition, behaviors and manipulations related to each session will be included. +created = client.save_model("session", data=payload).json() +if 'session' in created: + session_id = created["session"]["id"] + print(f"Created session with ID: {session_id}") +else: + print(f"Error creating session: {created}") ``` -output1 = client.load_model('session', include=['projects', 'dataacquisition', 'behaviors', 'manipulations']).json() +## Updating records + +Fetch the target record, modify the fields you want to change, and resubmit the partial payload. + +```python +# First load a session you have permission to modify +filtered_session = client.load_model( + 'session', + filters={'name.iexact': 'your session'} +).json() + +# Update the description +filtered_session['description'] = 'Updated via API' + +# Pass the whole filtered_session object to save_model +updated_session = client.save_model( + 'session', + id=filtered_session['sessions'][0]['id'], + data=filtered_session +).json() + +print("Session updated successfully") +``` + +## Deleting records + +Use `delete_model` with the record ID. A successful delete returns status code `204 No Content`. + +```python +response = client.delete_model("session", id="your-session-uuid") +if response.status_code == 204: + print("Session deleted") ``` + +## Troubleshooting + +- **401 Unauthorized**: Re-run `BrainstemClient()` to generate a fresh token or confirm credentials. +- **403 Forbidden**: Verify you have the necessary permissions (see the permission tables in the STEM API docs). +- **404 Not Found**: Make sure the ID exists and is within the selected portal. +- **Validation errors (400)**: Match the required fields and value formats listed in the model-specific documentation. + +For a notebook-style walk-through, open `brainstem_api_tutorial.ipynb` in the API tools repository. + +## Next Steps + +- **Complete Experimental Workflows**: Review the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials to see how API data fits into complete experimental documentation +- **Data Storage Integration**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to optimize your API-based analysis workflows with proper data organization +- **MATLAB Integration**: If you work in mixed programming environments, check out the [MATLAB API tool tutorial]({{site.baseurl}}/tutorials/matlab-api-tool) for cross-platform data access patterns diff --git a/docs/tutorials/behavioral-paradigms.md b/docs/tutorials/behavioral-paradigms.md index 981de1c..fb34d6e 100644 --- a/docs/tutorials/behavioral-paradigms.md +++ b/docs/tutorials/behavioral-paradigms.md @@ -4,8 +4,15 @@ title: Behavioral Paradigms parent: Tutorials nav_order: 20 --- - # Behavioral Paradigms in BrainSTEM +{: .no_toc} + +## Table of contents +{: .no_toc .text-delta } + +1. TOC + +## Introduction Behavioral paradigms are standardized experimental protocols or tasks (such as T-maze alternation, open field exploration, or Morris water maze) that are performed within a specific setup environment. Defining paradigms in BrainSTEM ensures consistency, reproducibility, and clear documentation of behavioral experiments across your lab. diff --git a/docs/tutorials/managing-data-storage.md b/docs/tutorials/managing-data-storage.md index 3df2147..d6d078c 100644 --- a/docs/tutorials/managing-data-storage.md +++ b/docs/tutorials/managing-data-storage.md @@ -90,6 +90,8 @@ Set up access methods for your data storage. Each protocol defines how to access {: .important } > You can configure multiple protocols for the same data storage. This allows flexibility in how different users or systems access the same data. +Protocol names must match the options provided in the BrainSTEM UI (e.g., "Local harddrive", "Dropbox (Cloud solution)", "Web"). + ## Assigning Data Storage to Sessions ### During Session Creation @@ -132,7 +134,7 @@ When you associate a data storage with a session, BrainSTEM can automatically co | **Organization** | Projects → Subjects → Sessions → Data files | {: .note } -> Data files are implied be stored in the session folder. +> Data files are implied to be stored in the session folder. **Session Information:** | Field | Value | @@ -179,7 +181,10 @@ def construct_data_path(session_data): Construct full path to session data based on BrainSTEM metadata """ storage = session_data['datastorage'] - base_path = storage['data_protocols_json'][0]['path'] # First protocol + + # Use the first configured protocol by default. + # Update this selection if your storage relies on a specific protocol. + base_path = storage['data_protocols_json'][0]['path'] # Extract organization elements organization = storage['data_organization_json'] @@ -309,6 +314,8 @@ function data_info = load_session_data(session_id) % Extract data storage information storage = session_data.datastorage; + + % Use the first configured protocol; adjust if a specific protocol is required. base_path = storage.data_protocols_json{1}.path; % Construct full path (simplified example) diff --git a/docs/tutorials/matlab-api-tool.md b/docs/tutorials/matlab-api-tool.md index 63bd439..a0235c1 100644 --- a/docs/tutorials/matlab-api-tool.md +++ b/docs/tutorials/matlab-api-tool.md @@ -1,136 +1,9 @@ --- layout: default -title: Matlab API tool +title: MATLAB API tool parent: Tutorials nav_order: 5 --- -# Tutorial for the Matlab API tool -{: .no_toc} +# MATLAB API tool -### Installation - -Download the BrainSTEM Matlab API tools repository from GitHub at [github.com/brainstem-org/brainstem_matlab_api_tools](https://github.com/brainstem-org/brainstem_matlab_api_tools) and add it to your Matlab setpath. - -### Setup credentials/token: - -Email and password will be requested when running this function: - -```matlab -get_token -``` - -The token is saved to a mat file (`brainstem_authentication.mat`) in the Matlab API tool folder. - -{: .note } -> The authentication token expires periodically. If you encounter authentication errors, run `get_token` again to refresh your credentials. - -### Troubleshooting Authentication - -If authentication fails: -- Verify your email and password are correct -- Check that the API tools are properly added to your MATLAB path -- Ensure you have an active internet connection - -### Loading sessions - -`load_model` can be used to load any model: We just need to set the name of the model. - -```matlab -output1 = load_model('model','session'); -``` - -{: .important } -> Always check the returned structure for errors before accessing data. Failed requests will return error information in the output structure. - -We can fetch a single session entry from the loaded models. - -```m -session = output1.sessions(1); -``` - -We can also filter the models by providing cell array with paired filters In this example, it will just load sessions whose name is "yeah". - -```m -output1_1 = load_model('model','session','filter',{'name','yeah'}); -``` - -Loaded models can be sorted by different criteria applying to their fields. In this example, sessions will be sorted in descending ordering according to their name. - -```m -output1_2 = load_model('model','session','sort',{'-name'}); -``` - -In some cases models contain relations with other models, and they can be also loaded with the models if requested. In this example, all the projects, data acquisition, behaviors and manipulations related to each session will be included. - -```m -output1_3 = load_model('model','session','include',{'projects','dataacquisition','behaviors','manipulations'}); -``` - -The list of related data acquisition can be retrieved from the returned dictionary. - -```m -dataacquisition = output1_3.dataacquisition; -``` - -Get all subjects with related procedures and subject state changes - -```m -output1_4 = load_model('model','subject','include',{'procedures'}); -``` - -Get all projects with related subjects and sessions - -```m -output1_5 = load_model('model','project','include',{'sessions','subjects'}); -``` - -All these options can be combined to suit the requirements of the users. For example, we can get only the session that contain the word "Rat" in their name, sorted in descending order by their name and including the related projects. - -```m -output1_6 = load_model('model','session', 'filter',{'name.icontains', 'Rat'}, 'sort',{'-name'}, 'include',{'projects'}); -``` - -### Updating a session - -We can make changes to a model and update it in the database. In this case, we change the description of one of the previously loaded sessions. - -```m -session = output1.sessions(1); -session.description = 'new description'; -output2 = save_model('data',session,'model','session'); -``` - -### Creating a new session - -We can submit a new entry by defining a struct with the required fields. - -```m -session = {}; -session.name = 'New session85'; -session.description = 'new session description'; -session.projects = {'0c894095-2d16-4bde-ad50-c33b7680417d'}; -``` - -Submitting session - -```m -output3 = save_model('data',session,'model','session'); -``` - -### Load public projects - -Request the public data by defining the portal to be public - -```m -output4 = load_model('model','project','portal','public'); -``` - -This tutorial in also available in the [Matlab API tool Github repository](https://github.com/brainstem-org/brainstem_matlab_api_tools). - -## Next Steps - -After mastering the MATLAB API basics, consider these logical progressions: - -- **Complete Experimental Documentation**: Review the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials to understand how API data access fits into complete experimental workflows -- **Cross-Platform Integration**: If you work in mixed programming environments, check out the [Python API tool tutorial]({{site.baseurl}}/tutorials/python-api-tool) to learn complementary data access patterns -- **Data Management**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to optimize your MATLAB-based analysis workflows with proper data organization +BrainSTEM supports programmatic API access so you can interact with the platform from your own scripts and tools. You can find the complete guide in the [API tools section]({{"/api-tools/matlab-api-tool/"|absolute_url}}). diff --git a/docs/tutorials/python-api-tool.md b/docs/tutorials/python-api-tool.md index cc03010..d374636 100644 --- a/docs/tutorials/python-api-tool.md +++ b/docs/tutorials/python-api-tool.md @@ -4,200 +4,6 @@ title: Python API tool parent: Tutorials nav_order: 6 --- -# Tutorial for the Python API tool -{: .no_toc} - -### Installation - -Download the BrainSTEM Python API tools repository from GitHub at [github.com/brainstem-org/brainstem_python_api_tools](https://github.com/brainstem-org/brainstem_python_api_tools). - -You can also install the package using `pip`: - - pip install brainstem_python_api_tools - -### Load the client. User email and password will be requested. -```python -from brainstem_api_client import BrainstemClient - -client = BrainstemClient() -``` - -{: .note } -> The client will prompt for your email and password. Your credentials are used to generate an authentication token that's stored locally for future use. - -### Troubleshooting Authentication - -If you encounter authentication issues: -- Ensure your email and password are correct -- Check that your account is active -- Try regenerating your authentication token - -### Loading sessions. - -load_model can be used to load any model: We just need to pass our settings and the name of the model. - -```python -output1 = client.load_model('session').json() -``` - -{: .important } -> Always check the response status before accessing data. If the request fails, the response will contain error information instead of your expected data. - -We can fetch a single session entry from the loaded models. - -``` -session = output1["sessions"][0] -``` - -We can also filter the models by providing a dictionary where the keys are the fields and the values the possible contents. In this example, it will just load sessions whose name is "yeah". - -```python -output1 = client.load_model('session', filters={'name': 'yeah'}).json() -``` - -{: .note } -> Filtering helps reduce data transfer and processing time. You can filter by any field available in the model. - -Loaded models can be sorted by different criteria applying to their fields. In this example, sessions will be sorted in descending ordering according to their name. - -``` -```python -output1 = client.load_model('session', sort=['-name']).json() -``` - -```python -output1 = client.load_model('session', include=['projects', 'dataacquisition', 'behaviors', 'manipulations']).json() -``` - -```python -dataacquisition = output1["sessions"][0]["dataacquisition"] -``` - -```python -output1 = client.load_model('session', filters={'name.icontains': 'Rat'}, sort=["-name"], include=['projects']).json() -``` - -### Error Handling Best Practices - -Always check if your requests were successful: - -```python -response = client.load_model('session') -if response.status_code == 200: - data = response.json() - sessions = data.get('sessions', []) -else: - print(f"Error: {response.status_code} - {response.text}") -``` -``` - -In some cases models contain relations with other models, and they can be also loaded with the models if requested. In this example, all the projects, data acquisition, behaviors and manipulations related to each session will be included. - -``` -output1 = client.load_model('session', include=['projects', 'dataacquisition', 'behaviors', 'manipulations']).json() -``` - -The list of related data acquisition can be retrieved from the returned dictionary. - -``` -dataacquisition = output1["sessions"][0]["dataacquisition"] -``` - -All these options can be combined to suit the requirements of the users. For example, we can get only the session that contain the word "Rat" in their name, sorted in descending order by their name and including the related projects. - -``` -output1 = client.load_model('session', filters={'name.icontains': 'Rat'}, sort=["-name"], include=['projects']).json() -``` - -### Updating a session - -We can make changes to a model and update it in the database. In this case, we changed the description of one of the previously loaded sessions. - -```python -session = {} -session["description"] = 'new description' -output2 = client.save_model("session", id="0e39c1fd-f413-4142-95f7-f50185e81fa4", data=session).json() -``` - -{: .warning } -> Be careful when updating data. Always verify the ID is correct and consider the impact of your changes on related data. - -### Creating a new session - -We can submit a new entry by defining a dictionary with the required fields. - -```python -session = {} -session["name"] = "New Session" -session["projects"] = ['e7475834-7733-48cf-9e3b-f4f2d2d0305a'] -session["description"] = 'description' -``` - -Submitting session -```python -output3 = client.save_model("session", data=session).json() -``` - -{: .note } -> When creating new entries, ensure all required fields are included. Check the [data model documentation](/datamodel/) for field requirements. - -### Load public projects - -Request the public data by defining the portal to be public -```python -output4 = client.load_model("project", portal="public").json() -``` - -{: .tip } -> Public data doesn't require authentication but has the same filtering and sorting capabilities as private data. - -### Complete Example Workflow - -Here's a complete example that demonstrates loading, filtering, and creating data: - -```python -from brainstem_api_client import BrainstemClient - -# Initialize client -client = BrainstemClient() - -try: - # Load projects to get a valid project ID - projects_response = client.load_model('project') - if projects_response.status_code == 200: - projects = projects_response.json()['projects'] - if projects: - project_id = projects[0]['id'] - - # Create a new session - new_session = { - "name": "Example Session", - "projects": [project_id], - "description": "Created via API tutorial" - } - - session_response = client.save_model("session", data=new_session) - if session_response.status_code == 201: - print("Session created successfully!") - session_data = session_response.json() - print(f"New session ID: {session_data['session']['id']}") - else: - print(f"Failed to create session: {session_response.text}") - else: - print("No projects available") - else: - print(f"Failed to load projects: {projects_response.text}") - -except Exception as e: - print(f"An error occurred: {e}") -``` - -See the tutorial in the Python Github repository. - -## Next Steps - -After mastering the Python API basics, consider these logical progressions: - -- **Complete Experimental Workflows**: Review the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials to see how API data fits into complete experimental documentation -- **Data Storage Integration**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to optimize your API-based analysis workflows with proper data organization -- **MATLAB Integration**: If you work in mixed programming environments, check out the [MATLAB API tool tutorial]({{site.baseurl}}/tutorials/matlab-api-tool) for cross-platform data access patterns \ No newline at end of file +# Python API tool + +BrainSTEM supports programmatic API access so you can interact with the platform from your own scripts and tools. You can find the complete guide in the [API tools section]({{"/api-tools/python-api-tool/"|absolute_url}}). From 9b9d49886ee88c54501711f731c7603e862c4a85 Mon Sep 17 00:00:00 2001 From: MingzeDou Date: Thu, 2 Oct 2025 12:39:42 +0200 Subject: [PATCH 05/16] Update matlab-api-tool.md --- docs/api-tools/matlab-api-tool.md | 159 +++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 47 deletions(-) diff --git a/docs/api-tools/matlab-api-tool.md b/docs/api-tools/matlab-api-tool.md index 9651b2c..a9c3e81 100644 --- a/docs/api-tools/matlab-api-tool.md +++ b/docs/api-tools/matlab-api-tool.md @@ -1,79 +1,144 @@ --- layout: default -title: Matlab API tool +title: MATLAB API tool parent: API tools nav_order: 1 --- -# Matlab API tool +# MATLAB API tool {: .no_toc} -You can download the BrainSTEM Matlab API tools repository from GitHub at [github.com/brainstem-org/brainstem_matlab_api_tools](https://github.com/brainstem-org/brainstem_matlab_api_tools) and add it to your Matlab setpath. +## Table of contents +{: .no_toc .text-delta } -Please see the dedicated [tutorial]({{"/tutorials/matlab-api-tool/"|absolute_url}}) with examples on usage. The main functions are described below. +1. TOC +{:toc} -| Function | Description | -|:-------------|:-------------| -| `get_token` | Get and save authentication token | -| `load_model` | Load data from any model | -| `save_model` | Save data to any model | -| `load_settings` | Local settings: API token, url to the server, and local storage. | -| `load_project` | Load project(s). Convenience function for handling projects. Extra parameters: `id`,`name`,`description`,`sessions`,`subjects`,`tags`,`is_public`. Included relational data: `sessions`,`subjects`,`collections`. | -| `load_subject` | Load subject(s). Convenience function for handling subjects. Extra parameters: `id`,`name`,`description`,`projects`,`strain`,`sex`,`tags`. Included relational data: `procedures`,`subjectlogs`. | -| `load_session` | Load session(s). Convenience function for handling sessions. Extra parameters: `id`,`name`,`description`,`projects`,`datastorage`,`tags`. Included relational data: `dataacquisition`,`behaviors`,`manipulations`,`epochs`. | -| `brainstem_api_tutorial` | Tutorial script. | +## Installation -### Filters -You can use filters, using fields and relationships by providing cell array with paired filters. Below example will just load the session with the id: +Clone the MATLAB helper package and add it to your MATLAB path: -```m -output = load_session('filter', {'id', 'ee57e766-fc0c-42e1-9277-7d40d6e9353a'}); +```matlab +git clone https://github.com/brainstem-org/brainstem_matlab_api_tools.git +addpath(genpath('brainstem_matlab_api_tools')) ``` -### Change sorting -Loaded models can be sorted by different criteria applying to their fields. In below example, sessions will be sorted in descending order according to their name. +## Authentication -```m -output = load_model('model', 'session', 'sort', {'-name'}); +Run `get_token` once to create and store an authentication token. Subsequent API calls reuse the cached credentials. + +```matlab +get_token ``` -### Include related models +Tokens expire periodically; re-run `get_token` if you see HTTP 401 responses. -In some cases models contain relations with other models, and they can be also loaded with the models if requested. +## Loading data -In below example, all the projects, data acquisition, behaviors and manipulations related to each session will be included. +`load_model` mirrors the REST endpoints documented under [STEM API]({{ "/api/stem/" | absolute_url }}). All arguments map directly onto their HTTP counterparts, and the helper infers the correct `app` when you omit it. -```m -output = load_model('model', 'session', 'include', {'projects', 'dataacquisition', 'behaviors', 'manipulations'}); +```matlab +sessions = load_model('model', 'session'); +disp(numel(sessions.sessions)) ``` -### Convenience functions -For the three primary data models (projects, subjects and sessions), you can use convenience functions to ease commonly performed tasks. The convenience functions have the fields of the models accessible as input parameters providing convenient filters and the calls include relational data as well: +Convenience wrappers include the correct `app` and default `include` lists for common models: + +- `load_project`: includes `sessions`, `subjects`, `collections`, `cohorts` +- `load_subject`: includes `procedures`, `subjectlogs` +- `load_session`: includes `dataacquisition`, `behaviors`, `manipulations`, `epochs` -__load_session__ -```m -output = load_session('name','mysession'); +They expose a small set of shorthand arguments (for example, `name`, `projects`, `tags`) that expand into the appropriate filter entries internally. + +```matlab +project = load_project('name', 'Allen Institute: Visual Coding – Neuropixels'); +subject = load_subject('name', 'Mouse'); +session = load_session('name', 'Example Session'); ``` -Performs the same API call as: -```m -output = load_model('app', 'stem', 'model', 'session', 'filter', {'name', 'mysession'}, 'include', {'dataacquisition', 'behaviors', 'manipulations', 'epochs'}); + +## Filtering + +Filters accept cell arrays of key–value pairs. The modifier syntax (`.icontains`, `.iexact`, etc.) matches the API documentation. + +```matlab +filtered = load_model( + 'model', 'project', ... + 'filter', {'name.icontains', 'Allen'}); + +disp(numel(filtered.projects)) ``` -__load_project__ +Multiple filter conditions can be specified as pairs in the same cell array: -```m -output = load_project('name','myproject'); +```matlab +filtered = load_model( + 'model', 'session', ... + 'filter', {'name.icontains', 'Rat', 'description.icontains', 'demo'}); ``` -Performs the same API call as: -```m -output = load_model('app', 'stem', 'model', 'project', 'filter', {'name', 'myproject'}, 'include', {'sessions', 'subjects', 'collections'}); + +## Sorting + +Pass a cell array of field names in `sort`. Prefix with `-` for descending order. + +```matlab +descending_sessions = load_model( + 'model', 'session', ... + 'sort', {'-start_time'}); +``` + +## Including related records + +Request related models (for example, `projects`, `datastorage`, `dataacquisition`) in a single call by supplying `include`. Each entry automatically expands to `.*`, mirroring the REST include syntax. + +```matlab +with_related = load_model( + 'model', 'session', ... + 'include', {'projects', 'datastorage', 'dataacquisition'}); + +project_names = arrayfun(@(p) p.name, with_related.projects, 'UniformOutput', false); ``` -__load_subject__ +## Creating records + +Use `save_model` with the required fields from the STEM API reference. The example below assumes you have contributor access to the project ID provided. Note that `tags` is a required field and can be set to an empty array if no tags are needed. + +```matlab +payload = struct(); +payload.name = 'Example Session'; +payload.description = 'Created via MATLAB API tool'; +payload.projects = {'your-project-uuid'}; +payload.tags = []; -```m -output = load_subject('name','mysubject'); +created = save_model('model', 'session', 'data', payload); +session_id = created.session.id; ``` -Performs the same API call as: -```m -output = load_model('app', 'stem', 'model', 'subject', 'filter', {'name','mysubject'}, 'include', {'procedures', 'subjectlogs'}); + +## Updating records + +Update existing records by placing the record ID inside the payload struct. `save_model` detects the `id` field, switches to `PUT`, and replaces the stored record with the data you supply. Remember to include the `tags` field even when updating. + +```matlab +update_data = struct( + 'id', 'your-session-uuid', ... + 'description', 'Updated via MATLAB API tool', ... + 'tags', []); + +updated = save_model( + 'model', 'session', ... + 'data', update_data); ``` + +## Troubleshooting + +- **401 Unauthorized**: Regenerate your token with `get_token`. +- **403 Forbidden**: Check that your user or group has the required permissions listed in the STEM API documentation. +- **404 Not Found**: Confirm the record exists in the selected portal (public/private). +- **Validation errors (400)**: Ensure your payload matches the field definitions in the API reference. Remember that `tags` is a required field for sessions (can be an empty array). +- **Delete operations**: The MATLAB helpers focus on read and write actions. Use the Python client or direct REST calls if you need to delete records. + +The repository ships with `brainstem_api_tutorial.m`, a tutorial script demonstrating common workflows. + +## Next Steps + +- **Complete Experimental Documentation**: Review the [Electrophysiology Workflow]({{site.baseurl}}/tutorials/electrophysiology-workflow) or [Two-Photon Imaging Workflow]({{site.baseurl}}/tutorials/two-photon-imaging-workflow) tutorials to understand how API data access fits into complete experimental workflows +- **Cross-Platform Integration**: If you work in mixed programming environments, explore the [Python API tool tutorial]({{site.baseurl}}/tutorials/python-api-tool) for complementary examples +- **Data Management**: Learn about [Managing Data Storage]({{site.baseurl}}/tutorials/managing-data-storage) to keep file locations synchronized with metadata returned by the API From c9450b0a7328fd0690b24a12e38ad52ef1243764 Mon Sep 17 00:00:00 2001 From: MingzeDou Date: Thu, 2 Oct 2025 13:51:25 +0200 Subject: [PATCH 06/16] pointing to the github repo --- docs/api-tools/matlab-api-tool.md | 18 ++++++++++++++++++ docs/api-tools/python-api-tool.md | 2 ++ 2 files changed, 20 insertions(+) diff --git a/docs/api-tools/matlab-api-tool.md b/docs/api-tools/matlab-api-tool.md index a9c3e81..0e906ce 100644 --- a/docs/api-tools/matlab-api-tool.md +++ b/docs/api-tools/matlab-api-tool.md @@ -13,6 +13,14 @@ nav_order: 1 1. TOC {:toc} +## Overview + +The BrainSTEM MATLAB API tool (`brainstem_matlab_api_tools`) provides a thin wrapper around the REST endpoints documented in the [STEM API reference]({{ "/api/stem/" | absolute_url }}). This page mirrors the structure of those docs while expanding on hands-on usage. Every snippet below has been tested against the public API; replace placeholders (for example, IDs) with values available to your account. + +Helper functions such as `get_token`, `load_model`, `load_project`, `load_session`, and `save_model` streamline typical MATLAB workflows while mapping their arguments directly onto the underlying HTTP parameters. + +> **Repository & tutorial:** Source code and examples live in [brainstem-org/brainstem_matlab_api_tools](https://github.com/brainstem-org/brainstem_matlab_api_tools). The repository includes the `brainstem_api_tutorial.m` script that mirrors this guide with runnable sections. + ## Installation Clone the MATLAB helper package and add it to your MATLAB path: @@ -75,6 +83,16 @@ filtered = load_model( 'filter', {'name.icontains', 'Rat', 'description.icontains', 'demo'}); ``` +The convenience functions also support multiple filter conditions through their shorthand parameters: + +```matlab +% Filter projects by name and tags +project = load_project('name', 'Allen', 'tags', '1'); + +% Filter subjects by name and sex +subject = load_subject('name', 'Mouse', 'sex', 'M'); +``` + ## Sorting Pass a cell array of field names in `sort`. Prefix with `-` for descending order. diff --git a/docs/api-tools/python-api-tool.md b/docs/api-tools/python-api-tool.md index 2860649..ad9333c 100644 --- a/docs/api-tools/python-api-tool.md +++ b/docs/api-tools/python-api-tool.md @@ -17,6 +17,8 @@ nav_order: 2 The BrainSTEM Python API tool (`brainstem_python_api_tools`) provides a thin wrapper around the REST endpoints documented in the [STEM API reference]({{ "/api/stem/" | absolute_url }}). This page mirrors the structure of those docs while expanding on hands-on usage. Every snippet below has been tested against the public API; replace placeholders (for example, IDs) with values you can access in your own account. +> **Repository & notebooks:** Source code and examples live in [brainstem-org/brainstem_python_api_tools](https://github.com/brainstem-org/brainstem_python_api_tools). The repository includes the `brainstem_api_tutorial.ipynb` notebook that mirrors this guide with runnable cells. + ## Installation Install the published package from PyPI (recommended) or clone the GitHub repository. From 74ce775a8e9c333a8e724bb11f5596c2633fda62 Mon Sep 17 00:00:00 2001 From: MingzeDou Date: Sat, 4 Oct 2025 17:36:06 +0200 Subject: [PATCH 07/16] Create import-tool.md --- docs/api-tools/import-tool.md | 219 ++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 docs/api-tools/import-tool.md diff --git a/docs/api-tools/import-tool.md b/docs/api-tools/import-tool.md new file mode 100644 index 0000000..8dc5998 --- /dev/null +++ b/docs/api-tools/import-tool.md @@ -0,0 +1,219 @@ +--- +layout: default +title: Import tool +parent: API tools +nav_order: 4 +--- +# Import tool +{: .no_toc} + +## Table of contents +{: .no_toc .text-delta } + +1. TOC +{:toc} + +## Overview + +The BrainSTEM import tool helps you add data to BrainSTEM by uploading CSV files. Instead of creating CSV files from scratch, you download pre-built templates for each data type, edit them with your data, and upload them. + +**🎯 How it works**: Download template → Edit with your data → Upload → Review results + +## Getting Started + +### Quick Start + +1. Go to the import tool page +2. Select your data type (e.g., "subjects", "procedures") +3. Click "Download CSV Template" +4. Open the downloaded file and replace the example data with your data +5. Upload the modified CSV file +6. Check the results for any errors + +### Why Use Templates? + +✅ **No mistakes** - Templates have correct column names and formatting + +✅ **Faster** - All required fields are already included + +✅ **Better examples** - Shows you exactly how to format your data + +### Finding Your UUIDs + +Some templates need IDs from your existing BrainSTEM data. These are marked as `YOUR_*_ID` in the templates: + +| Template ID | Where to find it | +| --- | --- | +| `YOUR_PROCEDURE_ID` | Admin → Procedures → Click edit → Copy ID from URL | +| `YOUR_EQUIPMENT_ID` | Admin → Equipment → Click edit → Copy ID from URL | +| `YOUR_CONSUMABLESTOCK_ID` | Admin → Consumable Stock → Click edit → Copy ID from URL | +| `YOUR_SETUP_ID` | Admin → Setup → Click edit → Copy ID from URL | +| `YOUR_BEHAVIORAL_PARADIGM_ID` | Admin → Behavioral Paradigm → Click edit → Copy ID from URL | + +**💡 Tip**: The ID is the long string of letters and numbers in the URL when you're editing a record. + +## Input conventions +- Column headers must follow the pattern `__` and match exactly; unrecognised columns are ignored. +- CSVs are read with `pandas.read_csv`, so values may be wrapped in double quotes or left bare—both are accepted. +- Trimming happens automatically, but lookups remain case-sensitive. Keep names ≤200 characters to stay within model limits. +- Boolean fields accept `true/false`, `yes/no`, `1/0`, `on/off`, or `enabled/disabled` in any casing (for example `TRUE`, `0`). Blank values resolve to `false`. +- Datetimes accept ISO-8601 (`2024-05-01T14:30`), spaced formats (`2024-05-01 14:30[:45]`), and regional variants (`05/01/2024`, `01/05/2024 14:30`). Dates accept the same patterns without a time component. +- List-style columns must use comma-separated values with no brackets (for example `behavior, imaging, ephys`). The importer splits on commas and trims whitespace. +- JSON columns must contain valid JSON objects; malformed JSON raises a warning and the field is skipped. Example: `{"laserPower": 5, "units": "mW"}`. +- Rich-text fields (project, subject, session, cohort, collection descriptions) are backed by CKEditor and therefore accept HTML. Because inline scripts and event handlers will render, keep inputs to simple formatting (paragraphs, bold, italics, links) to avoid introducing interactive content. + +## Data Type Details + +## Projects CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `project__name` | Yes | Text (e.g. `Auditory Cortex Project`) | No | Must be unique across BrainSTEM; importer creates the project when it does not exist. | +| `project__description` | No | Plain text or limited HTML (e.g. `

Two-photon recordings.

`) | No | Stored in the rich-text description field; avoid interactive markup. | +| `project__is_public` | No | Boolean keywords (e.g. `true`, `no`, `0`) | No | Parsed via `parse_boolean`; blank values become `false`. | +| `project__tags` | No | Comma-separated tags (e.g. `vision, cortex`) | Yes | Converted into an array of individual tag names. | + +## Subjects CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `project__name` | Yes | Existing project name (e.g. `Auditory Cortex Project`) | No | Projects must exist before importing subjects. | +| `subject__name` | Yes | Text (e.g. `Mouse_001`) | No | Subject names are globally unique. | +| `subject__sex` | No | `M`, `F`, `U` | No | Defaults to `U` (Unknown) when omitted. | +| `subject__description` | No | Plain text or limited HTML (e.g. `

WT male.

`) | No | Stored in the subject's rich-text description; avoid interactive markup. | +| `subject__strain` | No | Strain name (e.g. `C57BL/6J`) | No | Looks up the strain taxonomy; missing strains trigger warnings. | +| `subject__genetic_line` | No | Text (e.g. `Thy1-GCaMP6s`) | No | Free-form genetic line entry. | +| `subject__subject_identifier` | No | Text (e.g. `EarTag-123`) | No | External identifier. | +| `subject__supplier` | No | Supplier name (e.g. `Charles River Laboratories`) | No | Looks up existing suppliers; missing suppliers trigger warnings. | +| `subject__birth_date` | No | Date (e.g. `2023-02-14`) | No | Parsed and serialised to ISO date. | +| `subject__death_date` | No | Date (e.g. `2024/03/01`) | No | Parsed and serialised to ISO date. | +| `subject__tags` | No | Comma-separated tags (e.g. `training, cohortA`) | Yes | Split into a tag list. | +| `subject__name_used_in_storage` | No | Text (e.g. `mouse_001_data`) | No | Optional alternate storage label. | + + +## Procedures CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `subject__name` | Yes | Existing subject name (e.g. `Mouse_001`) | No | Subjects must exist before importing procedures. | +| `procedure__type` | Yes | Procedure type code (e.g. `VirusInjection`) | No | Must match an API choice. | +| `procedure__notes` | No | Plain text (e.g. `Injected 200 nL AAV.`) | No | Stored as free-form notes (500 characters). | +| `procedure__date_time` | No | Datetime (e.g. `2024-04-12 09:30`) | No | Parsed and stored as ISO-8601. | +| `procedure__atlas` | No | Atlas identifier (e.g. `AllenCCFv3`) | No | Used to scope brain-region lookups. | +| `procedure__brain_region` | No | Brain-region UUID or name (e.g. `VISp`) | No | Resolves within the supplied atlas first; warns and drops the field if unresolved. | +| `procedure__brain_region_acronym` | No | Atlas acronym (e.g. `VISp`) | No | Fallback lookup when the name is absent or ambiguous. | +| `procedure__coordinates` | No | Coordinate system key (e.g. `Stereotaxic_BregmaBrainSurface`) | No | Defaults when omitted. | +| `procedure__coordinates_data` | No | JSON object (e.g. `{"apCoordinate": -3.2}`) | No | Parsed into `coordinates_json`. | +| `procedure__consumablestock` | No | Consumable stock UUID (e.g. `6ac4...`) | No | Must reference an existing consumable stock record. | +| `procedure__equipment` | No | Comma-separated equipment UUIDs (e.g. `7f1b...,d2c9...`) | Yes | Each UUID is validated individually; invalid IDs raise warnings. | +| `procedure__details` | No | JSON object (e.g. `{"virus": "AAV9"}`) | No | Parsed into `type_json`; schema defaults are loaded if omitted. | + +## Subject Logs CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `subject__name` | Yes | Existing subject name (e.g. `Mouse_001`) | No | Subjects must exist before logging entries. | +| `subject_log__type` | Yes | Subject-log type code (e.g. `TrainingSession`) | No | Example values: `Housing`, `WaterDeprivation`, `Handling`. | +| `subject_log__description` | No | Plain text (e.g. `Habituation to head-fix.`) | No | Stored on the log record (500 characters). | +| `subject_log__entry_datetime` | Conditional | Datetime (e.g. `2024-05-02 10:00`) | No | Required for single-point logs (anything not in the start/end list below). | +| `subject_log__entry_start_datetime` | Conditional | Datetime (e.g. `2024-05-02 10:00`) | No | Required for `Housing`, `FoodDeprivation`, `WaterDeprivation`, `Habituation`, `Handling`, `TrainingSession`. | +| `subject_log__entry_end_datetime` | No | Datetime (e.g. `2024-05-02 11:00`) | No | Optional for the start/end list; defaults to one hour after the start when omitted. | +| `subject_log__entry_notes` | No | Plain text (e.g. `Handled by J.D.`) | No | Saved with the log entry. | +| `subject_log__entry_data` | No | JSON object (e.g. `{"task": "Go/No-Go"}`) | No | Parsed into the entry `details` field. | + +The importer finds or creates a `SubjectLog` for the subject/type pair, then adds a log entry when any entry timestamps are present. Duplicate entries for the same timestamp receive warnings and are counted as existing records. + +## Sessions CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `project__name` | Yes | Existing project name (e.g. `Auditory Cortex Project`) | No | Projects must exist before importing sessions. | +| `session__name` | Yes | Text (e.g. `Session_001`) | No | Session names are globally unique. | +| `session__description` | No | Plain text or limited HTML (e.g. `

Baseline recording.

`) | No | Stored in the session's rich-text description; avoid interactive markup. | +| `session__date_time` | No | Datetime (e.g. `2024-05-10T13:45`) | No | Parsed and stored as ISO-8601. | +| `session__tags` | No | Comma-separated tags (e.g. `baseline, imaging`) | Yes | Converted into a tag list. | +| `session__data_storage` | No | Data-storage name (e.g. `NAS Array 01`) | No | Looks up a matching Personal Attribute › Data Storage record; warnings are emitted when not found. | +| `session_name_in_data_storage` | No | Text (e.g. `2024-05-10_baseline`) | No | Optional alias for storage systems. | + + +## Behaviors CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `session__name` | Yes | Existing session name (e.g. `Session_001`) | No | Sessions must exist before importing behaviors. | +| `subject__name` | Yes | Existing subject name (e.g. `Mouse_001`) | No | Subjects must exist before importing behaviors. | +| `behavior__setup` | Yes | Setup UUID (e.g. `d3d0...`) | No | Validated via the Setup endpoint. | +| `behavior__behavioral_paradigm` | Yes | Behavioral paradigm UUID (e.g. `f6d4...`) | No | Validated via the Behavioral Paradigm endpoint. | + + +## Data Acquisition CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `session__name` | Yes | Existing session name (e.g. `Session_001`) | No | Sessions must exist before importing data acquisition records. | +| `data_acquisition__type` | Yes | Data-acquisition type code (e.g. `FiberPhotometry`) | No | Must match an API choice. | +| `data_acquisition__procedures` | Yes | Comma-separated procedure UUIDs (e.g. `9f50...,aa21...`) | Yes | At least one procedure is required; each UUID is validated before linking. | +| `data_acquisition__equipment` | No | Comma-separated equipment UUIDs (e.g. `7f1b...,d2c9...`) | Yes | Each UUID is validated and attached when found. | +| `data_acquisition__notes` | No | Plain text (e.g. `Laser at 10 mW.`) | No | Stored as free-form notes (500 characters). | +| `data_acquisition__details` | No | JSON object (e.g. `{"samplingRate": 30000}`) | No | Parsed into the `details` field; defaults are pulled from the schema when omitted. | + +## Manipulations CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `session__name` | Yes | Existing session name (e.g. `Session_001`) | No | Sessions must exist before importing manipulations. | +| `manipulation__type` | Yes | Manipulation type code (e.g. `OptogeneticStimulation`) | No | Must match an API choice. | +| `manipulation__procedures` | Yes | Comma-separated procedure UUIDs (e.g. `9f50...,aa21...`) | Yes | At least one procedure is required; each UUID is validated. | +| `manipulation__equipment` | No | Comma-separated equipment UUIDs (e.g. `7f1b...,d2c9...`) | Yes | Each UUID is validated before linking. | +| `manipulation__notes` | No | Plain text (e.g. `Blue light, 20 Hz.`) | No | Stored as free-form notes (500 characters). | +| `manipulation__details` | No | JSON object (e.g. `{"pulseWidthMs": 10}`) | No | Parsed into `type_json`; schema defaults apply when omitted. | + +## Cohorts CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `project__name` | Yes | Existing project name (e.g. `Auditory Cortex Project`) | No | Projects must exist before importing cohorts. | +| `cohort__name` | Yes | Text (e.g. `Training Cohort A`) | No | Names are enforced per project by the API. | +| `cohort__subjects` | Yes | Comma-separated subject names (e.g. `Mouse_001, Mouse_002`) | Yes | Each subject must already exist; missing subjects trigger warnings. | +| `cohort__description` | No | Plain text or limited HTML (e.g. `

For pilot sessions.

`) | No | Stored in the cohort's rich-text description; avoid interactive markup. | +| `cohort__tags` | No | Comma-separated tags (e.g. `pilot, cohortA`) | Yes | Split into a tag list. | + +## Collections CSV + +| Field | Required | Accepted Input | Multiple? | Notes | +| --- | --- | --- | --- | --- | +| `project__name` | Yes | Existing project name (e.g. `Auditory Cortex Project`) | No | Projects must exist before importing collections. | +| `collection__name` | Yes | Text (e.g. `Baseline Series`) | No | Names are enforced per project by the API. | +| `collection__sessions` | Yes | Comma-separated session names (e.g. `Session_001, Session_002`) | Yes | Each session must already exist; missing sessions trigger warnings. | +| `collection__description` | No | Plain text or limited HTML (e.g. `

Includes pilot days.

`) | No | Stored in the collection's rich-text description; avoid interactive markup. | +| `collection__tags` | No | Comma-separated tags (e.g. `baseline, imaging`) | Yes | Split into a tag list. | + +## Error handling +- Missing required fields stop the current row and record an error; later rows are still evaluated. +- Lookup failures on required relationships raise errors; missing optional lookups generate warnings and skip only the unresolved relationship. +- Invalid JSON, date, or datetime values raise warnings and the affected field is removed before the API call. +- Duplicate Subject Log entries and other unique-constraint hits are reported as warnings and counted as existing records. + +## Tips for Success + +### Before You Import + +1. **Download the right template** for your data type +2. **Check existing data** to avoid duplicates (especially for projects, subjects, sessions) +3. **Find your UUIDs** if the template needs them (see guide above) +4. **Back up your data** before bulk imports + +### Common Issues + +- **Missing required fields** - The template will show you which fields are required +- **Wrong date format** - Use `YYYY-MM-DD` format +- **Invalid JSON** - Copy the exact format from template examples +- **UUID not found** - Double-check that the ID exists in your system + +### After Import + +- Review the results for any errors or warnings +- Fix any issues in your CSV and re-upload +- Check that your data appears correctly in BrainSTEM + +**💡 Remember**: Templates are your best friend - they prevent most common import errors! \ No newline at end of file From a98dba5d7e4e713952def05f479157bfd769f3d3 Mon Sep 17 00:00:00 2001 From: MingzeDou Date: Sat, 4 Oct 2025 23:45:37 +0200 Subject: [PATCH 08/16] Add import tool guide and update documentation links Added a new section in the getting started tutorial to highlight the import tool for quick data entry. Moved and updated the import tool guide to the web interface docs, adjusted navigation metadata, and improved formatting and clarity in the import tool documentation. --- docs/tutorials/get_started.md | 18 ++++++++++++++++++ .../{api-tools => webinterface}/import-tool.md | 14 +++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) rename docs/{api-tools => webinterface}/import-tool.md (97%) diff --git a/docs/tutorials/get_started.md b/docs/tutorials/get_started.md index db9e5d6..a8e7424 100644 --- a/docs/tutorials/get_started.md +++ b/docs/tutorials/get_started.md @@ -162,6 +162,24 @@ After adding subjects, you can create sessions to record your experimental data. {: .important } > Sessions inherit permissions from their associated projects. Make sure to select the correct project to enable proper access for your team members. +## Already Have Data? Import It Quickly! + +**Don't want to enter everything manually?** If you already have your research data in spreadsheets, our powerful import tool can save you hours of manual data entry! + +**Why use the import tool?** + +- **Save time** - Import dozens or hundreds of records at once +- **Easy to use** - Download a template, fill in your data, and upload +- **Comprehensive** - Supports all major data types (subjects, sessions, procedures, and more!) + +**Get started in 3 simple steps:** + +1. **Download a template** for your data type +2. **Fill in your data** following the provided examples +3. **Upload and review** - we'll check for errors and show you the results + +**Ready to import?** Check out our complete [Import Tool Guide]({{site.baseurl}}/webinterface/import-tool/) for detailed instructions and templates! + ## Build Your Own Experiment BrainSTEM uses Personal Attributes and Modules to document your experimental procedures. Below is a recommended order for setting up your experiment components. diff --git a/docs/api-tools/import-tool.md b/docs/webinterface/import-tool.md similarity index 97% rename from docs/api-tools/import-tool.md rename to docs/webinterface/import-tool.md index 8dc5998..84ec213 100644 --- a/docs/api-tools/import-tool.md +++ b/docs/webinterface/import-tool.md @@ -1,8 +1,8 @@ --- layout: default title: Import tool -parent: API tools -nav_order: 4 +parent: Web interface +nav_order: 6 --- # Import tool {: .no_toc} @@ -17,7 +17,7 @@ nav_order: 4 The BrainSTEM import tool helps you add data to BrainSTEM by uploading CSV files. Instead of creating CSV files from scratch, you download pre-built templates for each data type, edit them with your data, and upload them. -**🎯 How it works**: Download template → Edit with your data → Upload → Review results +**How it works**: Download template → Edit with your data → Upload → Review results ## Getting Started @@ -32,11 +32,11 @@ The BrainSTEM import tool helps you add data to BrainSTEM by uploading CSV files ### Why Use Templates? -✅ **No mistakes** - Templates have correct column names and formatting +**No mistakes** - Templates have correct column names and formatting -✅ **Faster** - All required fields are already included +**Faster** - All required fields are already included -✅ **Better examples** - Shows you exactly how to format your data +**Better examples** - Shows you exactly how to format your data ### Finding Your UUIDs @@ -145,7 +145,6 @@ The importer finds or creates a `SubjectLog` for the subject/type pair, then add | `behavior__setup` | Yes | Setup UUID (e.g. `d3d0...`) | No | Validated via the Setup endpoint. | | `behavior__behavioral_paradigm` | Yes | Behavioral paradigm UUID (e.g. `f6d4...`) | No | Validated via the Behavioral Paradigm endpoint. | - ## Data Acquisition CSV | Field | Required | Accepted Input | Multiple? | Notes | @@ -189,6 +188,7 @@ The importer finds or creates a `SubjectLog` for the subject/type pair, then add | `collection__tags` | No | Comma-separated tags (e.g. `baseline, imaging`) | Yes | Split into a tag list. | ## Error handling + - Missing required fields stop the current row and record an error; later rows are still evaluated. - Lookup failures on required relationships raise errors; missing optional lookups generate warnings and skip only the unresolved relationship. - Invalid JSON, date, or datetime values raise warnings and the affected field is removed before the API call. From ff81aeacbdc83f38dba566850b5696c54a9404c6 Mon Sep 17 00:00:00 2001 From: MingzeDou Date: Sun, 5 Oct 2025 08:59:19 +0200 Subject: [PATCH 09/16] Create two-factor-authentication.md --- .../webinterface/two-factor-authentication.md | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 docs/webinterface/two-factor-authentication.md diff --git a/docs/webinterface/two-factor-authentication.md b/docs/webinterface/two-factor-authentication.md new file mode 100644 index 0000000..791d376 --- /dev/null +++ b/docs/webinterface/two-factor-authentication.md @@ -0,0 +1,91 @@ +--- +layout: default +title: Two-Factor Authentication +parent: Web interface +nav_order: 7 +--- + +# Two-Factor Authentication (2FA) + +2FA adds an extra layer of security to your BrainSTEM account by requiring a second verification step beyond your password. + +## Quick Setup (3 steps) + +1. **Avatar → Two-factor authentication** (or visit `/account/two_factor/`) +2. **Choose your method:** + - **Email** – Instant setup, receive 6-digit codes via email + - **Authenticator app** – Scan QR code with Google Authenticator, etc. +3. **Important:** Log out and log back in using 2FA before generating backup tokens + +## Method Details + +### Email Verification +- **Setup:** Click **Activate Email Authentication** → Done +- **Login:** Check email from `noreply@mg.brainstem.org` for 6-digit code (5-minute expiry) +- **Good for:** Quick setup, no app required + +### Authenticator Apps (TOTP) +- **Setup:** Click **Add Authentication App** → Scan QR code OR click secret key to copy → Enter 6-digit code +- **Login:** Open app, enter current 6-digit code (changes every 30 seconds) +- **Supported apps:** Google Authenticator, Microsoft Authenticator, Authy, 1Password +- **Good for:** Most secure, works offline + +### Backup Tokens +- **Setup:** Requires completing at least one 2FA login first → Click **Generate Tokens** → Save securely +- **Use:** Click **Use Backup Token** at login when locked out +- **Important:** Each token works once, automatically deleted if you remove all primary methods + +## Using 2FA + +**Normal login:** Username/password → Enter code from your default method → Done + +**Switch methods:** Click alternate method button or **Use Backup Token** at login + +**Troubleshooting:** +- **Email codes expired?** Wait 1 minute before requesting new code +- **Too many attempts?** Switch to backup token or alternate method +- **Locked out?** Contact administrator after trying all recovery options + +## Managing Methods + +**Add/Remove:** Visit `/account/two_factor/` +- **Email:** Activate/Disable (may be restricted by organization) +- **Apps:** Add multiple, Delete individually (add new before removing old) +- **Tokens:** Generate new set anytime (requires verified 2FA session) + +**Default method:** First method you enable becomes default, shown with green badge + +## Security Features + +| Feature | Details | +|---------|----------| +| **Email code expiry** | 5 minutes | +| **Cooldown period** | 1 minute between email requests | +| **Rate limiting** | Prevents brute-force attacks | +| **Automatic cleanup** | Backup tokens deleted when last primary method removed | + +## Organization Policies + +**Restricted domains** (e.g., @company.org): +- 2FA automatically enabled when you verify email +- Cannot disable 2FA completely +- Can still switch between email and authenticator apps + +**Check if affected:** Try disabling all 2FA methods – if blocked by policy, your domain requires 2FA + +## Best Practices + +✅ **DO:** +- Use authenticator apps (more secure than email) +- Set up multiple methods for backup +- Save backup tokens securely offline +- Test new methods before removing old ones + +❌ **DON'T:** +- Share backup tokens +- Rely on only one authentication method +- Ignore emails from `noreply@mg.brainstem.org` + +## Need Help? + +**Locked out of all methods?** Use the [contact form on the landing page](https://brainstem.org/#Get-in-touch) for assistance. Our IT team will help verify your identity and reset your access. From 8a2f40fb67d0fec94ea0d9ff0bb78ca489de9b68 Mon Sep 17 00:00:00 2001 From: "Peter C. Petersen" Date: Mon, 6 Oct 2025 09:12:57 +0200 Subject: [PATCH 10/16] Add images and update documentation for tutorials and import tool Added new images for the electrophysiology workflow and web interface tutorials. Updated 'electrophysiology-workflow.md' to include screenshots for project, subject, cohort creation, equipment list, and procedure view. Expanded 'import-tool.md' with an interface overview, new screenshot, and reorganized CSV field documentation for clarity. Improved 'two-factor-authentication.md' for conciseness, clarified setup steps, and updated security and troubleshooting sections. --- .../images/tutorials/ephys/add_cohort.png | Bin 0 -> 1227767 bytes .../images/tutorials/ephys/add_project.png | Bin 0 -> 1209506 bytes .../images/tutorials/ephys/add_subject.png | Bin 0 -> 1242404 bytes .../images/tutorials/ephys/equipment_list.png | Bin 0 -> 1042598 bytes .../ephys/subject_procedure_form.png | Bin 0 -> 1258971 bytes .../ephys/subject_procedure_view.png | Bin 0 -> 1247973 bytes .../Screenshot 2025-10-06 at 09.03.39.png | Bin 0 -> 800576 bytes .../images/webinterface/import_tool.png | Bin 0 -> 375418 bytes docs/tutorials/electrophysiology-workflow.md | 10 +- docs/webinterface/import-tool.md | 306 ++++++++++-------- .../webinterface/two-factor-authentication.md | 106 +++--- 11 files changed, 217 insertions(+), 205 deletions(-) create mode 100644 docs/assets/images/tutorials/ephys/add_cohort.png create mode 100644 docs/assets/images/tutorials/ephys/add_project.png create mode 100644 docs/assets/images/tutorials/ephys/add_subject.png create mode 100644 docs/assets/images/tutorials/ephys/equipment_list.png create mode 100644 docs/assets/images/tutorials/ephys/subject_procedure_form.png create mode 100644 docs/assets/images/tutorials/ephys/subject_procedure_view.png create mode 100644 docs/assets/images/webinterface/Screenshot 2025-10-06 at 09.03.39.png create mode 100644 docs/assets/images/webinterface/import_tool.png diff --git a/docs/assets/images/tutorials/ephys/add_cohort.png b/docs/assets/images/tutorials/ephys/add_cohort.png new file mode 100644 index 0000000000000000000000000000000000000000..58b44a0b8bbd0a52f188372fd1112bd58ca0ffee GIT binary patch literal 1227767 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