Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion +file/+internal/processDocstring.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
end

docstring = strtrim(docstring);
lines = strsplit(docstring, newline);
% CollapseDelimiters must be false: schema docs can have blank lines
% separating paragraphs, and the default (true) silently merges them
% away, losing structure the reST docs pipeline depends on to tell
% paragraphs/lists apart.
lines = strsplit(docstring, newline, 'CollapseDelimiters', false);
lines = strip(lines, 'right');
docstring = char(strjoin(lines, [newline char(continuationPrefix)]));
end
2 changes: 1 addition & 1 deletion +file/fillConstructor.m
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@
catch
description = 'No description';
end
description = file.internal.processDocstring(description, "% ");
description = file.internal.processDocstring(description, "% ");

docString = [docString, ...
sprintf("%% - %s (%s) - %s", propName, valueType, description), ...
Expand Down
57 changes: 32 additions & 25 deletions +types/+core/OnePhotonSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,38 @@
% - control_description (char) - Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.
%
% - data (numeric) - Time-series of microscopy data indexed as data[time, width, height].
% Indexing convention:
% - width: first spatial axis (horizontal direction, columns)
% - height: second spatial axis (vertical direction, rows)
% For raster-scanning systems (two-photon, confocal, one-photon laser scanning):
% - width: fast scan direction (horizontal)
% - height: slow scan direction (vertical)
% Coordinate system diagram::
% height ^
% (slow) |
% | +-----------------+
% | | |
% | | Image plane |
% | | |
% | +-----------------+
% |
% 0 ----------------------> width (fast)
% For non-raster systems (wide-field, light-sheet, random-access), width and height
% are arbitrary coordinates of the image plane.
% Note: This indexing convention conflicts with standard matrix[row, column] notation
% for array access where the first index moves vertically through rows and the second moves horizontally
% through columns. In the schema, data[time, width, height] means that the first spatial
% index moves horizontally (width) through columns and the second spatial index moves
% vertically (height) through rows. In summary, incrementing the first spatial index
% moves you horizontally across the image, while in matrix notation it would move you
% vertically across the rows of the image.
%
% Indexing convention:
% - width: first spatial axis (horizontal direction, columns)
% - height: second spatial axis (vertical direction, rows)
%
% For raster-scanning systems (two-photon, confocal, one-photon laser scanning):
% - width: fast scan direction (horizontal)
% - height: slow scan direction (vertical)
%
% Coordinate system diagram::
%
% height ^
% (slow) |
% | +-----------------+
% | | |
% | | Image plane |
% | | |
% | +-----------------+
% |
% 0 ----------------------> width (fast)
%
%
% For non-raster systems (wide-field, light-sheet, random-access), width and height
% are arbitrary coordinates of the image plane.
%
% Note: This indexing convention conflicts with standard matrix[row, column] notation
% for array access where the first index moves vertically through rows and the second moves horizontally
% through columns. In the schema, data[time, width, height] means that the first spatial
% index moves horizontally (width) through columns and the second spatial index moves
% vertically (height) through rows. In summary, incrementing the first spatial index
% moves you horizontally across the image, while in matrix notation it would move you
% vertically across the rows of the image.
%
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable. For storing instantaneous event information, it is recommended to use an EventsTable instead of a TimeSeries with continuity set to "instantaneous".
%
Expand Down
53 changes: 30 additions & 23 deletions +types/+core/TwoPhotonSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,36 @@
% - control_description (char) - Description of each control value. Must be present if control is present. If present, control_description[0] should describe time points where control == 0.
%
% - data (numeric) - Time-series of microscopy data indexed as data[time, width, height].
% Indexing convention:
% - width: first spatial axis (horizontal direction, columns)
% - height: second spatial axis (vertical direction, rows)
% For raster-scanning systems (two-photon, confocal, one-photon laser scanning):
% - width: fast scan direction (horizontal)
% - height: slow scan direction (vertical)
% Coordinate system diagram::
% height ^
% (slow) |
% | +-----------------+
% | | |
% | | Image plane |
% | | |
% | +-----------------+
% |
% 0 ----------------------> width (fast)
% For non-raster systems (wide-field, light-sheet, random-access), width and height
% are arbitrary coordinates of the image plane.
% Note: This indexing convention conflicts with standard matrix[row, column] notation
% for array access where the first index moves vertically through rows and the second moves horizontally
% through columns. In the schema, data[time, width, height] means that the first spatial
% index moves horizontally (width) through columns and the second spatial index moves
% vertically (height) through rows.
%
% Indexing convention:
% - width: first spatial axis (horizontal direction, columns)
% - height: second spatial axis (vertical direction, rows)
%
% For raster-scanning systems (two-photon, confocal, one-photon laser scanning):
% - width: fast scan direction (horizontal)
% - height: slow scan direction (vertical)
%
% Coordinate system diagram::
%
% height ^
% (slow) |
% | +-----------------+
% | | |
% | | Image plane |
% | | |
% | +-----------------+
% |
% 0 ----------------------> width (fast)
%
%
% For non-raster systems (wide-field, light-sheet, random-access), width and height
% are arbitrary coordinates of the image plane.
%
% Note: This indexing convention conflicts with standard matrix[row, column] notation
% for array access where the first index moves vertically through rows and the second moves horizontally
% through columns. In the schema, data[time, width, height] means that the first spatial
% index moves horizontally (width) through columns and the second spatial index moves
% vertically (height) through rows.
%
% - data_continuity (char) - Optionally describe the continuity of the data. Can be "continuous", "instantaneous", or "step". For example, a voltage trace would be "continuous", because samples are recorded from a continuous process. An array of lick times would be "instantaneous", because the data represents distinct moments in time. Times of image presentations would be "step" because the picture remains the same until the next timepoint. This field is optional, but is useful in providing information about the underlying data. It may inform the way this data is interpreted, the way it is visualized, and what analysis methods are applicable. For storing instantaneous event information, it is recommended to use an EventsTable instead of a TimeSeries with continuity set to "instantaneous".
%
Expand Down
50 changes: 50 additions & 0 deletions .github/workflows/build_docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Build docs

on:
pull_request:
branches:
- main
paths:
- "docs/**"
- "+**/*.m"
- ".github/workflows/build_docs.yml"
push:
branches:
- main
paths:
- "docs/**"
- "+**/*.m"
- ".github/workflows/build_docs.yml"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build_docs:
name: Build Sphinx docs
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Remove folders not needed for docs build
run: rm -rf +tests tools tutorials # not part of published API docs; fewer .m files for autodoc to scan

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.10"

- name: Install dependencies
run: |
python -m pip install -U pip
pip install -r docs/requirements.txt

- name: Apply RTD-equivalent pre-build customizations
run: python docs/source/sphinx_extensions/copy_files.py

- name: Build docs (fail on any warning)
run: sphinx-build -b html -W --keep-going docs/source docs/build/html
2 changes: 2 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ build:
python: "3.10"
jobs:
pre_build:
- rm -rf +tests tools tutorials # not part of published API docs; fewer .m files for autodoc to scan
- python docs/source/sphinx_extensions/copy_files.py

post_build:
Expand All @@ -17,3 +18,4 @@ python:

sphinx:
configuration: docs/source/conf.py
fail_on_warning: true
4 changes: 2 additions & 2 deletions docs/source/pages/concepts/file_read/untyped.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ DataStubs and DataPipes
When working with NWB files, datasets can be very large (gigabytes or more). Loading all this data into memory at once would be impractical or impossible. MatNWB uses two types to handle on-disk data efficiently: **DataStubs** and **DataPipes**.

DataStubs (Read only)
^^^^^^^^^^^^^^^^^^^^^
---------------------

A **DataStub** (``types.untyped.DataStub``) represents a read-only reference to data stored in an NWB file. When you read an NWB file, non-scalar and multi-dimensional datasets are automatically represented as DataStubs rather than loaded into memory.

Expand All @@ -102,7 +102,7 @@ Key characteristics:
You'll encounter DataStubs whenever you read existing NWB files containing non-scalar or multi-dimensional datasets.

DataPipes (read and write)
^^^^^^^^^^^^^^^^^^^^^^^^^^
---------------------------

A **DataPipe** (``types.untyped.DataPipe``) extends the concept of lazy data access to support **writing** as well as reading. While DataStubs are created automatically when reading files, you create DataPipes explicitly when writing data.

Expand Down
5 changes: 5 additions & 0 deletions docs/source/pages/getting_started/how_to_cite.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.. This page is linked to directly (e.g. from overview.rst) but is not part
of any toctree, so :orphan: suppresses the "not included in toctree" warning.

:orphan:

Citing MatNWB
=============

Expand Down
28 changes: 28 additions & 0 deletions docs/source/sphinx_extensions/docstring_processors.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Patches generated MATLAB docstrings so they parse as valid reST. Fixes
# rendering only — never change what fillConstructor.m embeds in the
# generated .m source, since that text also serves plain `help` output.
import os
import re
from _util import list_neurodata_types
Expand All @@ -11,6 +14,31 @@ def process_matlab_docstring(app, what, name, obj, options, lines):
_make_syntax_examples_code_literals(lines)
_format_input_arguments(lines)
_split_and_format_example_lines(lines)
_escape_role_end_before_invalid_char(lines)


# Characters allowed to directly follow an inline markup end-string in reST.
# See: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#inline-markup-recognition-rules
_ALLOWED_CHARS_AFTER_ROLE = re.compile(r"[\s'\")\]}>\-.,:;!?/\\]")

# Matches the closing backtick of an explicit-title role reference, e.g.
# ":attr:`format <types.core.ImageSeries.format>`", so a "\ " escape can be
# inserted when matlab_auto_link places such a reference directly before
# punctuation from the original schema text (e.g. "format='raw'" or
# "control_description[0]"), which would otherwise break reST parsing.
_ROLE_END_PATTERN = re.compile(r"(<[^<>`]+>)`")


def _escape_role_end_before_invalid_char(lines):
def _insert_escape(match):
end = match.end()
next_char = match.string[end:end + 1]
if next_char and not _ALLOWED_CHARS_AFTER_ROLE.match(next_char):
return match.group(0) + "\\ "
return match.group(0)

for i, line in enumerate(lines):
lines[i] = _ROLE_END_PATTERN.sub(_insert_escape, line)


def _format_matlab_type_as_code_literal(lines):
Expand Down