pysnirf2
Python package for reading, writing and validating Shared Near Infrared Spectroscopy Format (SNIRF) files
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
Repository
Python package for reading, writing and validating Shared Near Infrared Spectroscopy Format (SNIRF) files
Basic Info
Statistics
- Stars: 19
- Watchers: 2
- Forks: 15
- Open Issues: 7
- Releases: 4
Topics
Metadata Files
README.md
pysnirf2 `pip install snirf`
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_loadingmode.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, ... orstim1,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.pythondetectorPos3D = 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
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]
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
- Repositories: 9
- Profile: https://github.com/BUNPC
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 | 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)
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
Pull Request Labels
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
- Homepage: https://github.com/BUNPC/pysnirf2
- Documentation: https://snirf.readthedocs.io/
- License: GPLv3
-
Latest release: 0.8.0
published almost 2 years ago
Rankings
Maintainers (1)
pypi.org: pysnirf2
Interface and validator for SNIRF files
- Homepage: https://github.com/BUNPC/pysnirf2
- Documentation: https://pysnirf2.readthedocs.io/
- License: GPLv3
-
Latest release: 0.7.3
published over 3 years ago
Rankings
Maintainers (1)
Dependencies
- 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
- colorama ==0.4.4
- h5py ==3.1.0
- numpy ==1.19.5
- pip ==21.3.1
- setuptools ==40.8.0
- termcolor ==1.1.0
- colorama *
- h5py >=3.1.0
- numpy *
- pip *
- setuptools *
- termcolor *
- actions/checkout v2 composite
- actions/setup-python v1 composite
- ad-m/github-push-action v0.6.0 composite
- actions/checkout v2 composite
- actions/setup-python v5 composite
- pypa/gh-action-pypi-publish release/v1 composite
- actions/checkout v3 composite
- actions/setup-python v4 composite
- codecov/codecov-action v3 composite