Fiber Photometry#

Base Fiber Photometry#

Base interface for single-series fiber photometry data.

A BaseFiberPhotometryInterface writes exactly one FiberPhotometryResponseSeries to an NWBFile, assembled from one or more input streams (atomic source signals, e.g. TDT stores or Doric datasets). All the shared containers (device models, devices, optical fibers, indicators, viral vectors/injections, the FiberPhotometryTable, and any CommandedVoltageSeries) live under metadata["FiberPhotometry"] as name-keyed lists and are built once per file — the first interface to run assembles them from the (converter-merged) metadata and subsequent interfaces reuse them. Multiple response series therefore means multiple interfaces sharing one table, exactly like several ecephys recording interfaces sharing one electrodes table.

Child interfaces implement only the format-reading seam:

  • get_available_streams(...) — discover atomic source streams (a classmethod/staticmethod so a converter can be authored before construction).

  • _get_stream_data(stream_name) — return time-major data for one stream.

  • _get_stream_timestamps(stream_name) — return the timestamps for one stream.

  • get_metadata — enrich the base metadata with whatever the format embeds (e.g. session start time).

class BaseFiberPhotometryInterface(*, stream_names: str | list[str], metadata_key: str | None = None, stream_indices: list[int] | None = None, verbose: bool = False, **source_data)[source]#

Bases: BaseTemporalAlignmentInterface

Base class for single-series fiber photometry interfaces (one FiberPhotometryResponseSeries).

Initialize a single-series fiber photometry interface.

Parameters:
  • stream_names (str or list of str) – The input stream(s) — atomic source signals (e.g. TDT stores) — whose samples are column-stacked into this interface’s single FiberPhotometryResponseSeries.

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"] holding this interface’s response-series metadata. When None (default), it is generated from stream_names (e.g. stream "_405R" gives "fiber_photometry_405r"), so multiple interfaces over different streams already get distinct keys. Pass an explicit value to override.

  • stream_indices (list of int, optional) – Column indices selecting which columns of the (column-stacked) stream data to keep. None (default) keeps all columns.

  • verbose (bool, default: False) – Whether to print status messages.

  • **source_data – Format-specific source arguments (e.g. folder_path or file_path).

keywords: tuple[str] = ('fiber photometry',)#
get_original_timestamps() ndarray[source]#

Return the original (unaligned) timestamps of this interface’s primary stream.

get_timestamps() ndarray[source]#

Return the times this interface’s response series will be written on.

Deprecated since version Use: interface.alignment[key].get_times(), which reads the object it names rather than assuming the interface writes one. Removed in v0.12.0.

set_aligned_timestamps(aligned_timestamps: ndarray) None[source]#

Replace this interface’s timestamps with externally aligned values.

Deprecated since version Use: interface.alignment[key].set_times(aligned_timestamps), which does the same thing and names the object it lands on. Removed in v0.12.0.

set_aligned_starting_time(aligned_starting_time: float) None[source]#

Shift this interface’s times by aligned_starting_time seconds.

Deprecated since version Use: interface.alignment.shift_times(delta), which is the same rigid shift under a name that says so. Removed in v0.12.0.

align_by_interpolation(unaligned_timestamps: ndarray, aligned_timestamps: ndarray) None[source]#

Re-time this interface against a reference clock through synchronization pulses.

Deprecated since version Use: interface.alignment.remap_times(local_sync_times=..., reference_sync_times=...), whose argument names say which clock each set of pulses came off. Removed in v0.12.0.

get_metadata() DeepDict[source]#

Child DataInterface classes should override this to match their metadata.

Returns:

The metadata dictionary containing basic NWBFile metadata.

Return type:

DeepDict

get_metadata_template() DeepDict[source]#

Return the full fiber photometry provenance chain, sized to this interface’s traces.

The counterpart to get_metadata(), which reports only what the source recorded and so leaves a user no indication of what else the file needs. This returns those same values wrapped in the structure the writer expects. Fill in the blanks and pass the result to add_to_nwbfile or run_conversion; a blank still None at write time is an error rather than a value.

One FiberPhotometryTable row per trace, one optical fiber per row, and a shared excitation source, photodetector and indicator, since one interface writes one series and ndx-fiber-photometry recommends one series per excitation/emission wavelength with one column per fiber.

The wiring is done for you: every *_metadata_key cross-reference is resolved and the series’ fiber_photometry_table_region already lists the row keys in column order. What is left None is what only the experimenter can supply, the brain region each fiber sits in, the two wavelengths, the indicator’s label and the fiber insertion geometry. Rename the keys to suit the recording; they are handles, not names in the file.

get_metadata_schema() dict[source]#

Return a permissive schema for the FiberPhotometry block.

The device registries are declared centrally in base_metadata_schema.json, so only FiberPhotometry still needs an escape hatch here, until it gets a declaration of its own.

add_to_nwbfile(nwbfile: NWBFile, metadata: dict | None = None, *, stub_test: bool = False, stub_samples: int = 100, always_write_timestamps: bool = False, parent_container: Literal['acquisition', 'processing/ophys'] = 'acquisition') None[source]#

Add this interface’s FiberPhotometryResponseSeries (and, once, the shared containers).

With the default metadata (see get_metadata()) this writes only a bare FiberPhotometryResponseSeries — no devices, indicators, or FiberPhotometryTable are fabricated. When the full provenance chain is supplied in the metadata, the shared containers (devices, indicators, table, commanded voltage) are added through idempotent helpers: the first interface to run builds them and subsequent interfaces reuse them. Timing is written as starting_time + rate when the timestamps are regular, otherwise as an explicit timestamps array.

Parameters:
  • nwbfile (NWBFile) – The in-memory NWBFile to add the data to.

  • metadata (dict, optional) – Metadata dictionary; defaults to self.get_metadata().

  • stub_test (bool, default: False) – If True, add only the first stub_samples samples of each series for testing purposes.

  • stub_samples (int, default: 100) – The number of samples to write when stub_test is True.

  • always_write_timestamps (bool, default: False) – If True, always write an explicit timestamps array even when the series is regularly sampled.

  • parent_container ({“acquisition”, “processing/ophys”}, default: “acquisition”) – The NWBFile container to add the FiberPhotometryResponseSeries to. Use "processing/ophys" when the series represents processed data rather than raw acquisition.

Doric Fiber Photometry#

Interface for Doric Neuroscience Studio fiber photometry data (.doric HDF5 or DoricStudio CSV files).

class DoricFiberPhotometryInterface(*, file_path: Annotated[pathlib._local.Path, PathType(path_type='file')], stream_names: str | list[str], metadata_key: str | None = None, stream_indices: list[int] | None = None, verbose: bool = False)[source]#

Bases: BaseFiberPhotometryInterface

Interface for fiber photometry data from Doric Neuroscience Studio.

Reads either of the two formats produced by Doric Neuroscience Studio (compatible with BBC300, BBC600, FPC, and other Doric acquisition hardware) and writes a single FiberPhotometryResponseSeries to NWB using the ndx-fiber-photometry extension, assembled from one or more input streams; use multiple interfaces (with distinct metadata_key values) in a converter to write several series sharing one FiberPhotometryTable.

  • .doric (HDF5): stream names are auto-discovered by walking DataAcquisition for groups that contain a Time sibling dataset. Each non-Time 1-D dataset found this way becomes a stream whose name is the path relative to DataAcquisition with / replaced by _ (e.g. BBC300_ROISignals_Series0001_CAM1EXC1_ROI01). Older “EPConsole”-style exports that instead nest each stream under Traces/<console>/<stream>/<stream> (with a sibling Traces/<console>/Time(s)/... group holding the shared timestamps) are also supported.

  • .csv (DoricStudio CSV export): one shared time column (matched case-insensitively against "Time(s)"/"time") plus one or more data columns; each data column is a stream named after its column header (e.g. sig, ref). The time column may be on the first or second line (older exports prepend a channel/device “group” line above the real header), and trailing unnamed (empty) columns are ignored.

Call get_available_streams() to discover stream names for either format.

Initialize the DoricFiberPhotometryInterface.

Parameters:
  • file_path (FilePath) – Path to the .doric HDF5 file or DoricStudio .csv export.

  • stream_names (str or list of str) – The input stream(s) whose samples are assembled into this interface’s single FiberPhotometryResponseSeries. Call get_available_streams() to discover them.

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"] holding this interface’s response-series metadata. When None (default), it is generated from stream_names.

  • stream_indices (list of int, optional) – Column indices selecting which channels of the (column-stacked) stream data to keep.

  • verbose (bool, default: False) – Whether to print status messages.

display_name: str | None = 'DoricFiberPhotometry'#
info: str | None = 'Data Interface for converting fiber photometry data from Doric Neuroscience Studio.'#
associated_suffixes: tuple[str] = ('doric', 'csv')#
classmethod get_available_streams(file_path) list[str][source]#

Return the names of the streams available in a Doric .doric or .csv file.

Parameters:

file_path (FilePath) – Path to the .doric HDF5 file or DoricStudio CSV export.

Returns:

Sorted list of stream names.

Return type:

list[str]

get_metadata() DeepDict[source]#

Child DataInterface classes should override this to match their metadata.

Returns:

The metadata dictionary containing basic NWBFile metadata.

Return type:

DeepDict

TDT Fiber Photometry#

class TDTFiberPhotometryInterface(folder_path: Annotated[pathlib._local.Path, PathType(path_type='dir')], *, stream_names: str | list[str] | None = None, metadata_key: str | None = None, stream_indices: list[int] | None = None, verbose: bool = False)[source]#

Bases: BaseTemporalAlignmentInterface

Data Interface for converting fiber photometry data from a TDT output folder.

Each interface writes a single FiberPhotometryResponseSeries, assembled from one or more input streams (TDT stores); use multiple interfaces (with distinct metadata_key values) in a converter to write several series sharing one FiberPhotometryTable. Call get_available_streams() to discover stream names.

Deprecated since version Constructing: without stream_names routes to the deprecated multi-series implementation, which writes every stream at once and will be removed on or after February 2027. Pass stream_names to use the single-series interface.

Initialize the TDTFiberPhotometryInterface.

Parameters:
  • folder_path (DirectoryPath) – The path to the folder containing the TDT data.

  • stream_names (str or list of str, optional) – The input stream(s) (TDT stores) whose samples are assembled into this interface’s single FiberPhotometryResponseSeries. If omitted, the deprecated multi-series behavior is used (see class docstring).

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"] holding this interface’s response-series metadata. When None (default), it is generated from stream_names.

  • stream_indices (list of int, optional) – Column indices selecting which channels of the (column-stacked) stream data to keep.

  • verbose (bool, default: False) – Whether to print status messages.

keywords: tuple[str] = ('fiber photometry',)#
display_name: str | None = 'TDTFiberPhotometry'#
info: str | None = 'Data Interface for converting fiber photometry data from TDT files.'#
associated_suffixes: tuple[str] = ('Tbk', 'Tdx', 'tev', 'tin', 'tsq')#
classmethod get_available_streams(folder_path: Annotated[Path, PathType(path_type=dir)]) list[str][source]#

Return the names of the stream stores available in a TDT tank.

get_metadata() DeepDict[source]#

Child DataInterface classes should override this to match their metadata.

Returns:

The metadata dictionary containing basic NWBFile metadata.

Return type:

DeepDict

get_metadata_schema() dict[source]#

Retrieve JSON schema for metadata.

Returns:

The JSON schema defining the metadata structure.

Return type:

dict

get_conversion_options_schema() dict[source]#

Infer the JSON schema for the conversion options from the method signature (annotation typing).

Returns:

The JSON schema for the conversion options.

Return type:

dict

get_original_timestamps(*args, **kwargs)[source]#

Retrieve the original unaltered timestamps for the data in this interface.

This function should retrieve the data on-demand by re-initializing the IO.

Returns:

timestamps – The timestamps for the data stream.

Return type:

numpy.ndarray

get_timestamps(*args, **kwargs)[source]#

Retrieve the timestamps for the data in this interface.

Returns:

timestamps – The timestamps for the data stream.

Return type:

numpy.ndarray

set_aligned_timestamps(*args, **kwargs) None[source]#

Replace all timestamps for this interface with those aligned to the common session start time.

Must be in units seconds relative to the common ‘session_start_time’.

Parameters:

aligned_timestamps (numpy.ndarray) – The synchronized timestamps for data in this interface.

set_aligned_starting_time(*args, **kwargs) None[source]#

Align the starting time for this interface relative to the common session start time.

Must be in units seconds relative to the common ‘session_start_time’.

Parameters:

aligned_starting_time (float) – The starting time for all temporal data in this interface.

add_to_nwbfile(nwbfile: NWBFile, metadata: dict | None = None, **conversion_options) None[source]#

Define a protocol for mapping the data from this interface to NWB neurodata objects.

These neurodata objects should also be added to the in-memory pynwb.NWBFile object in this step.

Parameters:
  • nwbfile (pynwb.NWBFile) – The in-memory object to add the data to.

  • metadata (dict) – Metadata dictionary with information used to create the NWBFile.

  • **conversion_options – Additional keyword arguments to pass to the .add_to_nwbfile method.

CSV Fiber Photometry#

Interface for fiber photometry data stored in a CSV file.

class CSVFiberPhotometryInterface(file_path: Annotated[pathlib._local.Path, PathType(path_type='file')], *, data_columns: str | int | list[str | int], timestamps_column: str | int, demux_configuration: Annotated[neuroconv.datainterfaces.fiber_photometry.csv._demux.ColumnDemux | neuroconv.datainterfaces.fiber_photometry.csv._demux.StrideDemux, FieldInfo(annotation=NoneType, required=True, discriminator='by')] | None = None, time_unit: Literal['seconds', 'milliseconds', 'microseconds'] = 'seconds', metadata_key: str | None = None, read_kwargs: dict | None = None, verbose: bool = False)[source]#

Bases: BaseFiberPhotometryInterface

Data Interface for converting raw fiber photometry data from a CSV file.

This is a general-purpose CSV fiber photometry reader: the caller points at one CSV file, names the column holding the timestamps in seconds (timestamps_column), and names the data column(s) whose fluorescence samples become this interface’s single FiberPhotometryResponseSeries (data_columns). Columns are addressed by name (for a CSV with a header row) or by 0-based positional index (for a header-less CSV).

The channels of the response series are data_columns read from the file, in column order, column-stacked into one series. This covers two layouts with the same knobs:

  • One data column (the GuPPy acquisition format’s <stream>.csv with timestamps and data columns) – one single-channel series.

  • Several data columns – one multi-channel series sharing the file’s timestamps_column.

To aggregate several per-channel CSV files (e.g. GuPPy’s per-region CSVs) into one series, use MultiFileCSVFiberPhotometryInterface. To write several separate series (e.g. a signal and an isosbestic control) sharing one FiberPhotometryTable, use one interface per series (with distinct metadata_key values) in a converter.

For an interleaved file, where the excitation channels are multiplexed frame-by-frame down the rows, pass a demux_configuration selecting the one channel this interface reads: {"by": "column", ...} when a column labels each row’s channel (e.g. a Neurophotometrics LedState), or {"by": "stride", ...} when the channels cycle in a fixed order in a header-less file. So one interleaved file yields one channel per interface; instantiate one per channel and compose them in a converter.

Notes

CSV recordings carry no embedded recording-start timestamp, so get_metadata() does NOT populate NWBFile/session_start_time. The user must supply it via editable metadata.

Initialize the CSVFiberPhotometryInterface.

Parameters:
  • file_path (FilePath) – The CSV file holding the fiber photometry data.

  • data_columns (str, int, or list of str or int) – The data column(s) whose samples are column-stacked into this interface’s single FiberPhotometryResponseSeries. A column name (for a CSV with a header row) or a positional index (0-based, for a header-less CSV).

  • timestamps_column (str or int) – The column holding the timestamps (in time_unit, seconds by default) for the series’ time axis. A column name for a CSV with a header row, or a positional index (0-based) for a header-less CSV.

  • demux_configuration (ColumnDemux, StrideDemux, or None, optional) – For an interleaved file (excitation channels multiplexed frame-by-frame down the rows), a configuration selecting the one channel this interface reads. Two shapes: ColumnDemux(column=<col>, values=<v>, skip_rows=<n>) reads the rows a label column (e.g. a Neurophotometrics LedState) marks as this channel’s, after dropping n leading rows; v is that channel’s label, or a list of them when more than one label names it. StrideDemux(channels=<k>, index=<i>, skip_rows=<n>) reads every k-th row starting at i after dropping n leading rows. Default None reads every row (no demux). Compose one interface per channel in a converter.

  • time_unit ({“seconds”, “milliseconds”, “microseconds”}, optional) – The unit of timestamps_column; the timestamps are scaled to seconds on read. Default is “seconds” (no scaling).

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"] holding this interface’s response-series metadata. When None (default), it is generated from the file name.

  • read_kwargs (dict, optional) – Additional keyword arguments forwarded to pandas.read_csv to handle format quirks such as sep, encoding, decimal, or skiprows. Any value given here overrides the interface’s own defaults (header and float_precision). Default is None.

  • verbose (bool, default: False) – Whether to print status messages.

display_name: str | None = 'CSVFiberPhotometry'#
info: str | None = 'Data Interface for converting fiber photometry data from a CSV file.'#
associated_suffixes: tuple[str] = ('csv',)#
classmethod get_available_columns(file_path: Annotated[Path, PathType(path_type=file)], read_kwargs: dict | None = None) list[str][source]#

Return the header column names of a CSV file (empty for a header-less file).

A convenience for picking data_columns / timestamps_column on a headered file; a header-less file is addressed by positional integer indices instead.

Parameters:
  • file_path (FilePath) – The CSV file to read the header from.

  • read_kwargs (dict, optional) – Additional keyword arguments forwarded to pandas.read_csv (e.g. sep, encoding, skiprows) so the header is parsed with the same dialect the interface will read the file with. Pass the same value you would give the interface’s read_kwargs. Default is None.

Multi-File CSV Fiber Photometry#

Interface aggregating several per-channel CSV files into one fiber photometry response series.

class MultiFileCSVFiberPhotometryInterface(file_paths: list[Annotated[pathlib._local.Path, PathType(path_type='file')]], *, data_columns: str | int | list[str | int], timestamps_column: str | int, time_unit: Literal['seconds', 'milliseconds', 'microseconds'] = 'seconds', metadata_key: str | None = None, read_kwargs: dict | None = None, verbose: bool = False)[source]#

Bases: CSVFiberPhotometryInterface

Data Interface aggregating several per-channel CSV files into one fiber photometry series.

Some acquisition formats write one CSV file per channel/region rather than one wide CSV – GuPPy, for instance, stores each region in its own file whose channel identity lives in the filename. This interface reads data_columns from each file, in file-then-column order, and column-stacks them into this interface’s single FiberPhotometryResponseSeries. The channels share one time axis, taken from the first file’s timestamps_column.

Because only channels on a common timebase can share one series, the first file must contain the timestamps_column. Secondary files may omit it (their timestamps would be redundant); when a secondary file does contain it, the interface asserts it matches the first file’s timestamps, and when it omits it the interface asserts its row count matches, so files that do not share a timebase fail loudly instead of producing a silently mis-timed series.

For the common single-file case, use CSVFiberPhotometryInterface instead. To write several separate series (e.g. a signal and an isosbestic control) sharing one FiberPhotometryTable, use one interface per series (with distinct metadata_key values) in a converter.

Notes

CSV recordings carry no embedded recording-start timestamp, so get_metadata() does NOT populate NWBFile/session_start_time. The user must supply it via editable metadata.

Initialize the MultiFileCSVFiberPhotometryInterface.

Parameters:
  • file_paths (list of FilePath) – The per-channel CSV files, each contributing its data_columns as further channels of the single response series, in file-then-column order. The channels share the first file’s time axis.

  • data_columns (str, int, or list of str or int) – The data column(s), read from every file, whose samples are column-stacked into this interface’s single FiberPhotometryResponseSeries. A column name (for CSVs with a header row) or a positional index (0-based, for header-less CSVs).

  • timestamps_column (str or int) – The column holding the timestamps (in time_unit, seconds by default) for the series’ time axis, read from the first file. A column name for CSVs with a header row, or a positional index (0-based) for header-less CSVs.

  • time_unit ({“seconds”, “milliseconds”, “microseconds”}, optional) – The unit of timestamps_column; the timestamps are scaled to seconds on read. Default is “seconds” (no scaling).

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"] holding this interface’s response-series metadata. When None (default), it is generated from the file names.

  • read_kwargs (dict, optional) – Additional keyword arguments forwarded to pandas.read_csv to handle format quirks such as sep, encoding, decimal, or skiprows. Any value given here overrides the interface’s own defaults (header and float_precision). Default is None.

  • verbose (bool, default: False) – Whether to print status messages.

display_name: str | None = 'MultiFileCSVFiberPhotometry'#
info: str | None = 'Data Interface aggregating several per-channel CSV files into one fiber photometry series.'#
associated_suffixes: tuple[str] = ('csv',)#

NPM Fiber Photometry#

class NPMFiberPhotometryInterface(file_path: Annotated[pathlib._local.Path, PathType(path_type='file')], *, excitation_wavelength_in_nm: Literal[415, 470, 560], regions: str | list[str], timestamps_column: Literal['Timestamp', 'SystemTimestamp', 'ComputerTimestamp'] = 'Timestamp', time_unit: Literal['seconds', 'milliseconds', 'microseconds'] = 'seconds', metadata_key: str | None = None, read_kwargs: dict | None = None, verbose: bool = False)[source]#

Bases: CSVFiberPhotometryInterface

Interface for a Neurophotometrics CSV file (a Flags/LedState-labeled acquisition).

The NPM file is a header-bearing CSV whose channel multiplexing is driven by a Flags or LedState column: each row records which excitation LEDs were on, one flag per LED in the three lowest bits of that column’s packed word. This interface reads the one excitation channel given by excitation_wavelength_in_nm – every row whose word has that wavelength’s bit set – and writes the selected region column(s) as one FiberPhotometryResponseSeries.

A frame that strobes two LEDs at once therefore belongs to both of their channels, and the caller picks the region columns carrying the emission band of interest: in a LedState 6 frame (470 nm and 560 nm together) the 470 nm measurement is in the green columns and the 560 nm measurement is in the red ones, sharing a timestamp.

Use get_available_excitation_wavelengths() to discover the channels and get_available_regions() to discover the regions.

Header-less Neurophotometrics output has no NPM-specific structure and should be read with CSVFiberPhotometryInterface directly.

Initialize the NPMFiberPhotometryInterface.

Parameters:
  • file_path (FilePath) – The raw NPM CSV file.

  • excitation_wavelength_in_nm ({415, 470, 560}) – The excitation LED identifying the one channel this interface reads.

  • regions (str or list of str) – The region column name(s) whose samples are column-stacked into this interface’s single FiberPhotometryResponseSeries (see get_available_regions()).

  • timestamps_column ({“Timestamp”, “SystemTimestamp”, “ComputerTimestamp”}, default: “Timestamp”) – The timestamps column to use for the series’ time axis. Single-timestamp NPM files name it Timestamp (the default). A file with both SystemTimestamp and ComputerTimestamp has no Timestamp column, so the default fails loudly there and you must pick one explicitly. For any other column name, use CSVFiberPhotometryInterface directly.

  • time_unit ({“seconds”, “milliseconds”, “microseconds”}, optional) – The unit of the selected timestamp column, default = “seconds”.

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"] for this interface’s response-series metadata. When None (default), a key distinct per (excitation_wavelength_in_nm, regions) is generated, so several interfaces reading the same file do not collide.

  • read_kwargs (dict, optional) – Additional keyword arguments forwarded to pandas.read_csv to handle format quirks (e.g. sep, encoding, decimal). Default is None.

  • verbose (bool, default: False) – Whether to print status messages.

display_name: str | None = 'NPMFiberPhotometry'#
info: str | None = 'Interface for raw fiber photometry data from Neurophotometrics files.'#
associated_suffixes: tuple[str] = ('csv',)#
classmethod get_available_excitation_wavelengths(file_path: Annotated[Path, PathType(path_type=file)], read_kwargs: dict | None = None) list[int][source]#

Return the excitation wavelengths (nm) present in the file, sorted.

A wavelength is present when any frame has its excitation bit set, so a frame that strobes two LEDs at once (e.g. LedState 6) reports both of them. A leading startup frame is not a measurement and does not contribute; see _read_state_values().

classmethod get_available_regions(file_path: Annotated[Path, PathType(path_type=file)], read_kwargs: dict | None = None) list[str][source]#

Return the region column names present in the file, in file order.

The columns NPM writes around the regions – the clock and frame index, the excitation/TTL word, the digital lines – are a closed set, so the regions are what is left once they are subtracted. The result is directly usable as regions, unlike the inherited get_available_columns(), which lists the whole header.

Parameters:
  • file_path (FilePath) – The NPM CSV file to read the header from.

  • read_kwargs (dict, optional) – Additional keyword arguments forwarded to pandas.read_csv (e.g. sep, encoding) so the header is parsed with the same dialect the interface will read the file with. Pass the same value you would give the interface’s read_kwargs. Default is None.

pyPhotometry Fiber Photometry#

class PyPhotometryFiberPhotometryInterface(file_path: Annotated[pathlib._local.Path, PathType(path_type='file')], *, stream_name: str | None = None, metadata_key: str | None = None, verbose: bool = False)[source]#

Bases: BaseFiberPhotometryInterface

Interface for one signal of a pyPhotometry .ppd recording.

A .ppd holds every signal the board recorded and no two of them were sampled at the same instant, so one interface reads one signal. Combine several in a converter to write them into one file.

Streams are named for the photodetector read and the excitation source lit, as in detector_1_excitation_2, and a shared detector prefix means those signals came off one fiber. Use get_available_streams() to list what a file holds.

Initialize the interface for one signal of a .ppd file.

Parameters:
  • file_path (path) – The .ppd file.

  • stream_name (str, optional) – Which signal to read, as named by get_available_streams(). Defaults to the first signal, which is only unambiguous on a file that holds one.

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"] for this interface’s response series. Defaults to one derived from the stream name.

  • verbose (bool, default: False) – Whether to print status messages.

display_name: str | None = 'pyPhotometry Fiber Photometry'#
associated_suffixes: tuple[str] = ('.ppd',)#
info: str | None = 'Interface for pyPhotometry fiber photometry recordings.'#
classmethod get_available_streams(file_path: Annotated[Path, PathType(path_type=file)]) list[str][source]#

Return the names of the signals in a file, in the order the words interleave them.

get_metadata() DeepDict[source]#

Add what the header states about the session and the subject, and what it omits about timing.

add_to_nwbfile(nwbfile: NWBFile, metadata: dict | None = None, *, stub_test: bool = False, stub_samples: int = 100, always_write_timestamps: bool = False, **conversion_options) None[source]#

Write the response series, and the raw pair beside it when the file carries one.

From header version 1.1 a strobed recording stores the LED-on sample and the LED-off baseline it was measured against. The response series carries their difference, which is what earlier firmware wrote itself, and both measurements are written beside it.

RawLEDOn references the same FiberPhotometryTable row as the difference. RawBaseline references none, since a row states an excitation source and wavelength and a measurement taken in the dark had neither.

class PyPhotometryConverter(file_path: Annotated[pathlib._local.Path, PathType(path_type='file')], *, detection_configuration: dict | None = None, verbose: bool = False)[source]#

Bases: ConverterPipe

Convert a pyPhotometry .ppd recording whole, its fluorescence and its digital lines together.

One call writes every fluorescence signal as its own FiberPhotometryResponseSeries and every digital line as its own EventsTable. How many of each a recording holds depends on how it was acquired, and get_available_streams lists them before you build anything.

Each series is named after the stream its signal came off, FiberPhotometryResponseSeriesDetector1Excitation1, so several of them can sit in one file. The FiberPhotometry metadata (devices, indicators, table rows, per-series regions) is yours to supply, exactly as for one interface on its own.

Build an interface for every signal and line of a .ppd file.

Parameters:
  • file_path (FilePath) – The .ppd file.

  • detection_configuration (dict, optional) – Forwarded to PyPhotometryEventsInterface, which documents it. It names the lines to read as well as how to read them, so it is also how a line is left out. When None (default) every line the file carries is read as a high_period.

  • verbose (bool, default: False) – Whether to print status messages.

display_name: str | None = 'pyPhotometry Converter'#
keywords: tuple[str] = ('fiber photometry', 'events', 'pyPhotometry')#
associated_suffixes: tuple[str] = ('.ppd',)#
info: str | None = 'Converts every fluorescence signal and digital line of a pyPhotometry recording.'#
classmethod get_available_streams(file_path: Annotated[Path, PathType(path_type=file)]) list[str][source]#

Return every signal and line a file holds: the fluorescence signals first, then the lines.

get_metadata() DeepDict[source]#

Merge the sub-interfaces’ metadata, giving each response series a name of its own.

Every single-series interface defaults to the same FiberPhotometryResponseSeries, which is unique only in a file holding one signal, so each is suffixed here with the slot it came off.

GuPPy Fiber Photometry#

class GuppyInterface(folder_path: Annotated[pathlib._local.Path, PathType(path_type='dir')], *, metadata_key: str | None = None, verbose: bool = False)[source]#

Bases: BaseDataInterface

Data Interface for converting GuPPy (Guided Photometry Analysis in Python) processed outputs.

This interface writes the derived products that GuPPy computes as dedicated ndx-guppy neurodata types:

  • control-fit / ΔF/F / z-score traces

  • transient peaks and their per-(recording_site, trace_type) summary

  • peri-event PSTHs and peak / AUC summaries, including those GuPPy’s spontaneous mode aligned to its own detected transients instead of to external TTLs

  • recording-site-pair cross-correlations

  • bootstrap significance of the PSTHs, where that optional GuPPy step was run

  • whole-session time-binned metrics, and the behavioral covariates binned onto and correlated against them, where those optional GuPPy steps were run

  • per-epoch tonic means, where GuPPy’s optional tonic analysis was run

plus the GuPPy parameters (GuppyParameters), the GuppyValidSignalIntervals object, and the two registry tables (GuppyRecordingSitesTable, GuppyEventsTable) that give each recording_site and event a single structured identity referenced by every product.

add_to_nwbfile() takes no linkage arguments – it writes only what the GuPPy output defines. The events registry’s events DynamicTableRegion references an EventsTable of GuPPy’s own analyzed onsets, written into nwbfile.events, so every peri-event product reaches the occurrences it was built from however this interface is run.

The recording sites registry carries the one outward link the GuPPy output cannot supply itself, fiber_photometry_table_region into the acquisition FiberPhotometryTable. How much of that can be filled in depends on what the NWBFile already holds when this runs:

  • A converter authored the registry. GuppyConverter owns the acquisition interfaces for a session being converted from raw, so it builds the recording sites registry itself, in full, before this interface runs; it is reused as it stands.

  • The NWBFile already holds the acquisition. A session GuPPy processed out of an existing NWB file is converted by handing that file here: GuPPy’s storesList.csv store ids were derived from its contents, so they address its response series directly and the registry is built linked into the table already there. Nothing is copied or rewritten.

  • Neither, or only some of GuPPy’s stores address the file. The registry is built in its minimal link-free form – one row per recording site, name only – since the interface has no acquisition provenance to invent, and a partial resolution is reported as a warning naming the stores that did not resolve.

A converter reaches the parsed identifiers it needs to build that registry itself, and to keep its raw events to the stores GuPPy processed, through the recording_sites, recording_site_to_store_ids, and event_store_to_event_name read-only views.

All products are placed in a ProcessingModule named guppy.

Initialize the GuppyInterface.

Parameters:
  • folder_path (DirectoryPath) – Path to the GuPPy output folder (the <session>_output_<N> directory containing storesList.csv, the per-recording_site derived .hdf5 files, and the GuPPyParamtersUsed.json provenance file). GuPPy always writes GuPPyParamtersUsed.json into this folder, so it is discovered automatically; if it is missing the folder is not a valid GuPPy output and construction fails.

  • metadata_key (str, optional) – Key under metadata["FiberPhotometry"]["Guppy"] that scopes everything this interface writes, so two GuPPy interfaces in one conversion do not collide. Defaults to the GuPPy output folder’s name, which is unique per output.

  • verbose (bool, optional) – Whether to print status messages, default = False.

keywords: tuple[str] = ('fiber photometry', 'GuPPy', 'processed')#
display_name: str | None = 'Guppy'#
info: str | None = 'Data Interface for converting fiber photometry data processed by GuPPy.'#
associated_suffixes: tuple[str] = ('hdf5', 'csv', 'h5', 'json')#
property recording_sites: list[str]#

The discovered recording-site names, in the canonical GuppyRecordingSitesTable row order.

property event_names: list[str]#

The discovered event names, in the canonical GuppyEventsTable row order.

property analyzed_event_onsets: dict[str, ndarray]#

The onsets GuPPy kept for each event, keyed by event name.

These are the onsets GuPPy built trials around, which are what every peri-event product covers: an occurrence the raw acquisition recorded but GuPPy discarded is not here.

property recording_site_to_store_ids: dict[str, dict[str, str]]#

{recording_site: {"signal": <store_id>, "control": <store_id>}} from storesList.csv.

property event_store_to_event_name: dict[str, str]#

{store_id: event_name} for the behavioral event stores listed in storesList.csv.

A converter that also writes the raw acquisition’s events needs this to keep exactly the stores GuPPy processed and give each the human-readable name recorded there (e.g. the PrtR store becomes the port_entries event type).

get_metadata() DeepDict[source]#

Return metadata pre-populated from the GuPPy outputs and parameters file.

get_metadata_schema() dict[source]#

Return the metadata schema for this interface.

add_to_nwbfile(nwbfile: NWBFile, metadata: dict, *, stub_test: bool = False, always_write_timestamps: bool = False) None[source]#

Add GuPPy-derived fiber photometry products to an NWBFile as ndx-guppy neurodata types.

Builds the GuppyParameters lab metadata, the GuppyRecordingSitesTable and GuppyEventsTable registries, the per-product objects (traces, transients, summary, cross-correlation, PSTH, peak/AUC, binned metrics, binned covariates, covariate correlations) each referencing its registry rows, the GuppyValidSignalIntervals object, and, where GuPPy’s optional tonic analysis and PSTH significance testing were run, the GuppyTonicEpochs and GuppyPSTHSignificance objects. Products are written on the timestamps GuPPy emits. Each behavioral covariate’s scored values are written as a TimeSeries that the two covariate products reference.

This method takes no linkage arguments: it writes only what the GuPPy output defines. The events registry references an EventsTable of GuPPy’s own analyzed onsets, written into nwbfile.events. A spontaneous-mode event is registered once per recording site, since each site stood its own detected transients in for the TTLs. The recording sites registry’s acquisition fiber_photometry_table_region is the one link the GuPPy output cannot supply: a converter that owns the acquisition authors that registry before this method runs and the table found in the processing module is reused as it stands (see GuppyConverter); failing that, the link is resolved against the FiberPhotometryTable the nwbfile already holds, and standalone the registry is written link-free.

Parameters:
  • nwbfile (NWBFile) – The in-memory NWBFile to add the data to.

  • metadata (dict) – Metadata dictionary; must contain metadata["FiberPhotometry"]["Guppy"][self.metadata_key].

  • stub_test (bool, optional) – If True, only a short slice of each large product is written. Default = False.

  • always_write_timestamps (bool, optional) – If True, always write the explicit timestamps vector on each derived trace instead of the starting_time + rate representation used when the timestamps are regularly sampled. Default = False.

class GuppyConverter(fiber_photometry_folder_path: Annotated[pathlib._local.Path, PathType(path_type='dir')], events_folder_path: Annotated[pathlib._local.Path, PathType(path_type='dir')], guppy_folder_path: Annotated[pathlib._local.Path, PathType(path_type='dir')], *, acquisition_format: Literal['tdt', 'csv', 'doric', 'npm'], verbose: bool = False)[source]#

Bases: ConverterPipe

Bundle a GuPPy session’s raw acquisition, raw events, and GuPPy-derived processing outputs.

Combines the three parts of a GuPPy session: the raw acquisition (added to nwbfile.acquisition via the ndx-fiber-photometry extension), the raw discrete events (added to nwbfile.events as pynwb.event.EventsTable objects), and the GuPPy interface (derived traces, transient tables, and cross-correlations added to a guppy ProcessingModule).

Everything the converter does with a GuPPy session is independent of how the session was recorded: storesList.csv names the stores as opaque ids, and the converter groups them, links them, and writes them without knowing what produced them. Format is confined to acquisition_format and the methods that dispatch on it; the reading itself lives in a <format>_utils module per format, which is where support for further GuPPy-readable formats is added.

A session’s traces come from one acquisition format, since a series column-stacks one store per recording site onto a single timestamps vector. Its events need not: GuPPy’s custom-event import writes the events it imported back out as one-column timestamps CSVs, which then sit in the session folder beside whatever the rig recorded. Those files are found by scanning events_folder_path, so an event store that has a CSV of its own is read from it and every other store is read from acquisition_format – a mixed session needs nothing declared.

The stores are discovered from the GuPPy storesList.csv – each recording site contributes its signal and (optional) control store – so the converter builds exactly the acquisition channels GuPPy processed. Those stores are grouped by role rather than written one per series: each role is an excitation wavelength, and one acquisition interface per role column-stacks that role’s store from every recording site into a single FiberPhotometryResponseSeries. A two-site isosbestic session therefore yields two acquisition series, not four.

As with every fiber photometry interface, the FiberPhotometry metadata chain (devices, indicators, the FiberPhotometryTable and its rows, and each series’ fiber_photometry_table_region) is supplied by the user; the converter does not invent it. Each acquisition series reads its own block at metadata["FiberPhotometry"][metadata_key], where metadata_key is the role ("signal" or "control"). The FiberPhotometryTable still carries one row per store – the grouping changes, not the rows – and each series’ region lists its stacked stores’ rows in column order, which is how the converter recovers the row belonging to each GuPPy recording site.

That cross-interface knowledge makes the converter the author of the GuppyRecordingSitesTable registry: it is the only side that can link each recording site to its acquisition fiber rows, so it builds that registry complete and the GuPPy interface reuses it. The events registry belongs to the GuPPy interface, which references its own analyzed onsets; the raw events are written as they are, each type its own EventsTable, exactly as adding those events interfaces directly would write them.

GuPPy and the acquisition share a single origin (recording start = session_start_time): GuPPy emits timestamps in seconds since recording start, the same clock the raw streams use, so both interfaces write on that shared clock.

Initialize the GuPPy converter.

Parameters:
  • fiber_photometry_folder_path (DirectoryPath) – Path to the folder holding the raw acquisition traces – for TDT, the tank folder containing the Tbk, Tdx, tev, tin and tsq files; for CSV, the folder holding one <store>.csv per channel; for Doric, the folder holding the single .doric or DoricStudio .csv export. For NPM this must be the GuPPy session folder itself, since GuPPy’s file<N> store names index that folder’s CSVs in sorted order.

  • events_folder_path (DirectoryPath) – Path to the folder holding the raw discrete events. GuPPy writes a session’s traces and events into one folder, so for TDT this is the same tank folder as fiber_photometry_folder_path; the two are named separately because other acquisition formats read them through different interfaces. This folder is also scanned for the one-column timestamps CSVs GuPPy’s custom-event import writes, which is how a session whose events did not come from the acquisition system is read.

  • guppy_folder_path (DirectoryPath) – Path to the GuPPy <session>_output_<N> folder containing storesList.csv, the per-recording-site derived .hdf5 files, and the GuPPyParamtersUsed.json provenance file (discovered automatically by the GuPPy interface).

  • acquisition_format ({“tdt”, “csv”, “doric”, “npm”}) – The format the session’s traces were recorded in, selecting which interfaces read fiber_photometry_folder_path. "doric" covers all three Doric layouts – modern and legacy .doric HDF5 and DoricStudio .csv exports – resolved from the one acquisition file in the folder, and "npm" covers both the state-column and header-less Neurophotometrics layouts. One format per session: a series column-stacks one store per recording site onto a single timestamps vector, which stores from two acquisition systems do not share. The events side is not tied to it: an event store GuPPy’s custom-event import wrote a CSV for is read from that CSV, whatever the traces were recorded in.

  • verbose (bool, optional) – Whether to print status messages, default = False.

Notes

The raw events stored are exactly the behavioral event stores GuPPy listed in storesList.csv – i.e. only the epocs GuPPy actually processed – each given the human-readable name from that file (e.g. the PrtR store becomes the port_entries EventsTable). Stores present in the source but absent from storesList.csv (and the fiber signal/control stores) are excluded by get_metadata.

display_name: str | None = 'GuPPy Fiber Photometry'#
keywords: tuple[str] = ('fiber photometry', 'GuPPy', 'processed', 'events')#
associated_suffixes: tuple[str] = ('hdf5', 'csv', 'h5', 'json', 'Tbk', 'Tdx', 'tev', 'tin', 'tsq', 'doric')#
info: str | None = "Converter that bundles a GuPPy session's raw acquisition with its GuPPy-derived processing outputs."#
get_metadata()[source]#

Merge sub-interface metadata into a single coherent fiber photometry conversion.

Gives each acquisition series a distinct default name and keeps only the behavioral event stores GuPPy listed.

The FiberPhotometry chain itself (devices, indicators, table rows, per-series regions) is the user’s to supply, exactly as for a bare acquisition interface.

get_metadata_schema() dict[source]#

Allow the FiberPhotometry block to carry the Guppy sub-schema alongside the base schemas.

add_to_nwbfile(nwbfile: NWBFile, metadata: dict | None = None, conversion_options: dict | None = None) None[source]#

Add the raw acquisition and GuPPy-derived data to the provided NWBFile.

The recording sites registry carries a link only this converter can compute, since it owns the acquisition FiberPhotometryTable, so it authors that registry itself. The sequence is therefore spelled out by name rather than looped over data_interface_objects: the acquisition interfaces build the shared FiberPhotometryTable, the registry links into it, and the GuPPy interface reuses it for the products that reference its rows.