Skip to main content

pysnirf2

pip install snirf

testing lazydocs PyPI version DOI

Dynamically generated Python library for reading, writing, and validating Shared Near Infrared Spectroscopy Format (SNIRF) files.

Developed and maintained by the Boston University Neurophotonics Center.

Documentation

Documentation is generated from source using lazydocs

Installation

pip install snirf

pysnirf2 requires Python > 3.6.

Features

pysnirf2 explicitly implements all SNIRF fields so as to provide an extensible object-oriented foundation for SNIRF applications.

Open a SNIRF file

Snirf(<path>, <mode>) opens a SNIRF file at <path> or creates a new one if it doesn't exist. Use mode 'w' to create a new file, 'r' to read a file, and 'r+' to edit an existing file.

from snirf import Snirf
snirf = Snirf(r'some\path\subj1_run01.snirf', 'r+')

Create a SNIRF file object

Snirf() with no arguments creates a temporary file which can be written later using save().

snirf = Snirf()

Closing a SNIRF file

A Snirf instance wraps a file on disk. It should be closed when you're done reading from it or saving.

snirf.close()

Use a with statement to ensure that the file is closed when you're done with it:

with Snirf(r'some\path\subj1_run01.snirf', 'r+') as snirf:
     # Read/write
     snirf.save()

Copy a SNIRF file object

Any Snirf object can be copied to a new instance in memory, after which the original can be closed.

snirf2 = snirf.copy()
snirf.close()
# snirf2 is free for manipulation

View or retrieve a file's contents

>>> snirf

Snirf at /
filename: 
C:\Users\you\some\path\subj1_run01.snirf
formatVersion: v1.0
nirs: <iterable of 2 <class 'pysnirf2.NirsElement'>>
>>> snirf.nirs[0].probe

Probe at /nirs1/probe
correlationTimeDelayWidths: [0.]
correlationTimeDelays: [0.]
detectorLabels: ['D1' 'D2']
detectorPos2D: [[30.  0.]
 [ 0. 30.]]
detectorPos3D: [[30.  0.  0.]
 [ 0. 30.  0.]]
filename: 
C:\Users\you\some\path\subj1_run01.snirf
frequencies: [1.]
landmarkLabels: None
landmarkPos2D: None
landmarkPos3D: None
location: /nirs/probe
momentOrders: None
sourceLabels: ['S1']
sourcePos2D: [[0. 0.]]
sourcePos3D: [[0.]
 [0.]
 [0.]]
timeDelayWidths: [0.]
timeDelays: [0.]
useLocalIndex: None
wavelengths: [690. 830.]
wavelengthsEmission: None

Edit a SNIRF file

Assign a new value to a field

>>> snirf.nirs[0].metaDataTags.SubjectID = 'subj1'
>>> snirf.nirs[0].metaDataTags.SubjectID

'subj1'
>>> snirf.nirs[0].probe.detectorPos3D[0, :] = [90, 90, 90]
>>> snirf.nirs[0].probe.detectorPos3D

array([[90.,  90.,  90.],
      [  0.,  30.,   0.]])

Note: assignment via slicing is not possible in dynamic_loading mode.

Indexed groups

Indexed groups are defined by the SNIRF file format as groups of the same type which are indexed via their name + a 1-based index, i.e. data1, data2, ... or stim1, stim2, stim3, ...

pysnirf2 provides an iterable interface for these groups using Pythonic 0-based indexing, i.e. data[0], data[1], ... or stim[0], stim[1]], stim[2], ...

>>> snirf.nirs[0].stim


<iterable of 0 <class 'pysnirf2.StimElement'>>

>>> len(nirs[0].stim)

0

To add an indexed group, use the appendGroup() method of any IndexedGroup class. Indexed groups are created automatically. nirs is an indexed group.

>>> snirf.nirs[0].stim.appendGroup()
>>> len(nirs[0].stim)

1

>>> snirf.nirs[0].stim[0]

StimElement at /nirs/stim2
data: None
dataLabels: None
filename: 
C:\Users\you\some\path\subj1_run01.snirf
name: None

To remove an indexed group

del snirf.nirs[0].stim[0]

Save a SNIRF file

Overwrite the open file

snirf.save()

Save As in a new location

snirf.save(r'some\new\path\subj1_run01_edited.snirf')

The save() function can be called for any group or indexed group:

snirf.nirs[0].metaDataTags.save('subj1_run01_edited_metadata_only.snirf')

Dynamic loading mode

For larger files, it may be useful to load data dynamically: data will only be loaded on access, and only changed datasets will be written on save(). When creating a new Snirf instance, set dynamic_loading to True (Default False).

snirf = Snirf(r'some\path\subj1_run01.snirf', 'r+', dynamic_loading=True)

Note: in dynamic loading mode, array data cannot be modified with indices like in the example above:

>>> snirf = Snirf(TESTPATH, 'r+', dynamic_loading=True)
>>> snirf.nirs[0].probe.detectorPos3D

array([[30.,  0.,  0.],
      [ 0., 30.,  0.]])

>>> snirf.nirs[0].probe.detectorPos3D[0, :] = [90, 90, 90]
>>> snirf.nirs[0].probe.detectorPos3D

array([[30.,  0.,  0.],
       [ 0., 30.,  0.]])

To modify an array in dynamic_loading mode, assign it, modify it, and assign it back to the Snirf object.

>>> detectorPos3D = snirf.nirs[0].probe.detectorPos3D
>>> detectorPos3D[0, :] = [90, 90, 90]
>>> snirf.nirs[0].probe.detectorPos3D = detectorPos3D

array([[90.,  90.,  90.],
       [ 0.,   30.,  0.]])

Validating a SNIRF file

pysnirf2 features functions for validating SNIRF files against the specification and generating detailed error reports.

Validate a Snirf object you have created

result = snirf.validate()

Validate a SNIRF file on disk

To validate a SNIRF file on disk

from snirf import validateSnirf
result = validateSnirf(r'some\path\subj1_run01.snirf')
assert result, 'Invalid SNIRF file!\n' + result.display()  # Crash and display issues if the file is invalid.

Validation results

The validation functions return a ValidationResult instance which contains details about the SNIRF file. To view the validation result:

>>> result.display(severity=3)  # Display all fatal errors

<pysnirf2.pysnirf2.ValidationResult object at 0x000001C0CCF05A00>
/nirs1/data1/measurementList103/dataType                 FATAL   REQUIRED_DATASET_MISSING
/nirs1/data1/measurementList103/dataTypeIndex            FATAL   REQUIRED_DATASET_MISSING
/nirs1/data1                                             FATAL   INVALID_MEASUREMENTLIST 

Found 668 OK      (hidden)
Found 635 INFO    (hidden)
Found 204 WARNING (hidden)
Found 3 FATAL  

File is INVALID

To look at a particular result:

>>> result.errors[2]

<pysnirf2.pysnirf2.ValidationIssue object at 0x000001C0CB502F70>
location: /nirs1/data1
severity: 3   FATAL  
name:     8   INVALID_MEASUREMENTLIST
message:  The number of measurementList elements does not match the second dimension of dataTimeSeries

The full list of validation results result.issues can be explored programatically.

Code generation

The interface and validator are generated via metacode that downloads and parses the latest SNIRF specification.

See \gen for details.

Metadata

Release files for snirf 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for snirf 0.8.0
File Size Uploaded
snirf-0.8.0.tar.gz 57.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for snirf 0.8.0
File Interpreter ABI Platform
snirf-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 113.1 kB

Release files / snirf-0.8.0.tar.gz

Download URL snirf-0.8.0.tar.gz
Size 57.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e78f207608b986ab2df773bba3475895a792ee699451423ca5f0cfad50a17b8a
BLAKE2b-256 checksum
How to use checksums
94183ce90a74443e9d598473f28a18fbbbffa6b7cb30ea6eb58b56dc5530dcc0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.0.0 CPython/3.12.3

Release files / snirf-0.8.0-py3-none-any.whl

Download URL snirf-0.8.0-py3-none-any.whl
Size 55.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
85eed4f9e7bb1d98f3afb4751607da20dd216bdcb159090a212abc9815b12cbe
BLAKE2b-256 checksum
How to use checksums
f48c10fe07c52104f2be8efec7dac377248a9f5be3096d50b1418f115242cbd0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/5.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

0.7.4

2 release files

0.7.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page