pysnirf2

Python package for reading, writing and validating Shared Near Infrared Spectroscopy Format (SNIRF) files

https://github.com/bunpc/pysnirf2

Science Score: 46.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
    Links to: zenodo.org
  • Committers with academic emails
    1 of 6 committers (16.7%) from academic institutions
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (11.7%) to scientific vocabulary

Keywords

brain-imaging fnirs near-infrared-spectroscopy nirs openfnirs snirf
Last synced: 7 months ago · JSON representation

Repository

Python package for reading, writing and validating Shared Near Infrared Spectroscopy Format (SNIRF) files

Basic Info
  • Host: GitHub
  • Owner: BUNPC
  • License: gpl-3.0
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 32 MB
Statistics
  • Stars: 19
  • Watchers: 2
  • Forks: 15
  • Open Issues: 7
  • Releases: 4
Topics
brain-imaging fnirs near-infrared-spectroscopy nirs openfnirs snirf
Created over 4 years ago · Last pushed 8 months ago
Metadata Files
Readme License Citation

README.md

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.9.

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. python 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(). python 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. python snirf.close() Use a with statement to ensure that the file is closed when you're done with it: python 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. ```python snirf2 = snirf.copy() snirf.close()

snirf2 is free for manipulation

```

View or retrieve a file's contents

```python

snirf

Snirf at / filename: C:\Users\you\some\path\subj1_run01.snirf formatVersion: v1.0 nirs: > python

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 ```python

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

'subj1' python

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], ...

```python

snirf.nirs[0].stim

>

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. python

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 python del snirf.nirs[0].stim[0] ```

Save a SNIRF file

Overwrite the open file python snirf.save() Save As in a new location python snirf.save(r'some\new\path\subj1_run01_edited.snirf') The save() function can be called for any group or indexed group: python 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). python 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: ```python

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. python

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

python result = snirf.validate()

Validate a SNIRF file on disk

To validate a SNIRF file on disk python 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: ```python

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

/nirs1/data1/measurementList103/dataType FATAL REQUIREDDATASETMISSING /nirs1/data1/measurementList103/dataTypeIndex FATAL REQUIREDDATASETMISSING /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: python

result.errors[2]

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 resultsresult.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.

Owner

  • Name: BUNPC
  • Login: BUNPC
  • Kind: organization

GitHub Events

Total
  • Create event: 2
  • Release event: 1
  • Issues event: 2
  • Watch event: 4
  • Issue comment event: 8
  • Push event: 6
  • Pull request event: 7
  • Fork event: 2
Last Year
  • Create event: 2
  • Release event: 1
  • Issues event: 2
  • Watch event: 4
  • Issue comment event: 8
  • Push event: 6
  • Pull request event: 7
  • Fork event: 2

Committers

Last synced: about 3 years ago

All Time
  • Total Commits: 115
  • Total Committers: 6
  • Avg Commits per committer: 19.167
  • Development Distribution Score (DDS): 0.122
Top Committers
Name Email Commits
stephen scott tucker s****r@b****u 101
github-actions[bot] 4****]@u****m 6
andyzjc 8****c@u****m 3
Eric Larson l****d@g****m 2
Robert Luke 7****e@u****m 2
dependabot[bot] 4****]@u****m 1
Committer Domains (Top 20 + Academic)
bu.edu: 1

Issues and Pull Requests

Last synced: 9 months ago

All Time
  • Total issues: 21
  • Total pull requests: 38
  • Average time to close issues: 2 months
  • Average time to close pull requests: 3 days
  • Total issue authors: 9
  • Total pull request authors: 8
  • Average comments per issue: 2.43
  • Average comments per pull request: 1.18
  • Merged pull requests: 33
  • Bot issues: 0
  • Bot pull requests: 2
Past Year
  • Issues: 5
  • Pull requests: 4
  • Average time to close issues: 4 months
  • Average time to close pull requests: about 1 month
  • Issue authors: 4
  • Pull request authors: 4
  • Average comments per issue: 1.2
  • Average comments per pull request: 1.0
  • Merged pull requests: 2
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • rob-luke (6)
  • fangq (2)
  • zEdS15B3GCwq (2)
  • sstucker (2)
  • Carlafrenzel (1)
  • samuelpowell (1)
  • emmaspeh (1)
  • EwanMahe (1)
  • Edouard2laire (1)
Pull Request Authors
  • sstucker (23)
  • rob-luke (6)
  • larsoner (3)
  • emiddell (2)
  • HanBnrd (2)
  • Edouard2laire (2)
  • dependabot[bot] (2)
  • sreekanthkura7 (1)
Top Labels
Issue Labels
question (1) bug (1) enhancement (1)
Pull Request Labels
dependencies (2)

Packages

  • Total packages: 2
  • Total downloads:
    • pypi 2,922 last-month
  • Total dependent packages: 2
    (may contain duplicates)
  • Total dependent repositories: 4
    (may contain duplicates)
  • Total versions: 16
  • Total maintainers: 1
pypi.org: snirf

Interface and validator for SNIRF files

  • Versions: 3
  • Dependent Packages: 1
  • Dependent Repositories: 1
  • Downloads: 2,836 Last month
Rankings
Downloads: 3.5%
Dependent packages count: 4.7%
Average: 11.8%
Forks count: 11.9%
Stargazers count: 17.1%
Dependent repos count: 21.7%
Maintainers (1)
Last synced: 8 months ago
pypi.org: pysnirf2

Interface and validator for SNIRF files

  • Versions: 13
  • Dependent Packages: 1
  • Dependent Repositories: 3
  • Downloads: 86 Last month
Rankings
Dependent packages count: 4.7%
Dependent repos count: 9.0%
Forks count: 11.9%
Average: 12.6%
Stargazers count: 17.1%
Downloads: 20.0%
Maintainers (1)
Last synced: 8 months ago

Dependencies

gen/requirements.txt pypi
  • Jinja2 ==3.0.3
  • MarkupSafe ==2.0.1
  • Unidecode ==1.3.2
  • certifi ==2021.10.8
  • charset-normalizer ==2.0.7
  • idna ==3.3
  • pathlib ==1.0.1
  • pylint ==2.14.4
  • requests ==2.26.0
  • urllib3 ==1.26.7
  • yapf ==0.32.0
requirements.txt pypi
  • colorama ==0.4.4
  • h5py ==3.1.0
  • numpy ==1.19.5
  • pip ==21.3.1
  • setuptools ==40.8.0
  • termcolor ==1.1.0
setup.py pypi
  • colorama *
  • h5py >=3.1.0
  • numpy *
  • pip *
  • setuptools *
  • termcolor *
.github/workflows/lazydocs.yml actions
  • actions/checkout v2 composite
  • actions/setup-python v1 composite
  • ad-m/github-push-action v0.6.0 composite
.github/workflows/release.yml actions
  • actions/checkout v2 composite
  • actions/setup-python v5 composite
  • pypa/gh-action-pypi-publish release/v1 composite
.github/workflows/test.yml actions
  • actions/checkout v3 composite
  • actions/setup-python v4 composite
  • codecov/codecov-action v3 composite
pyproject.toml pypi