Skip to content

Commit

Permalink
Merge pull request #2 from dvm-shlee/main
Browse files Browse the repository at this point in the history
prototyped snippets
  • Loading branch information
dvm-shlee authored May 1, 2024
2 parents f409711 + 9e256ef commit 1311811
Show file tree
Hide file tree
Showing 13 changed files with 466 additions and 2 deletions.
126 changes: 126 additions & 0 deletions bids-recipes/bids-recipes_v1.2.2_brkraw.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
startup:
- 'import numpy as np'

dataset:
Name: ''
BIDSVersion: 1.2.2
License: ''
Authors:
- ''
Acknowledgements: ''
HowToAsknowledge: ''
Funding:
- ''
EthicApprovals: ''
ReferenceAndLinks: ''
DatasetDOI: ''

common:
Manufacturer: visu_pars.VisuManufacturer
ManufacturersModelName: visu_pars.VisuStation
DeviceSerialNumber: visu_pars.VisuSystemOrderNumber
StationName: visu_pars.VisuStation
SoftwareVersion: visu_pars.VisuAcqSoftwareVersion
MagneticFieldStrength:
Freq: visu_pars.VisuAcqImagingFrequency
script: Freq / 42.576
ReceiveCoilName: visu_pars.VisuCoilReceiveName
ReceiveCoilActiveElements: visu_pars.VisuCoilReceiveType
GradientSetType: acqp.ACQ_status
MRTransmitCoilSequence:
Name: visu_pars.VisuCoilTransmitName
Manufacture: visu_pars.VisuCoilTransmitManufacturer
Type: visu_pars.VisuCoilTransmitType
CoilConfigName: acqp.ACQ_coil_config_file
MatrixCoilMode: acqp.ACQ_experiment_mode
CoilCombinationMethod: null
PulseSequenceType: acqp.PULPROG
ScanningSequence: visu_pars.VisuAcqSequenceName
SequenceVariant: visu_pars.VisuAcqEchoSequenceType
ScanOptions:
RG: visu_pars.VisuRespSynchUsed
CG: visu_pars.VisuCardiacSynchUsed
PFF:
key: visu_pars.VisuAcqPartialFourier
idx: 0
PFP:
key: visu_pars.VisuAcqPartialFourier
idx: 1
FC: visu_pars.VisuAcqFlowCompensation
SP: method.PVM_FovSatOnOff
FP: visu_pars.VisuAcqSpectralSuppression
SequenceName:
- visu_pars.VisuAcquisitionProtocol
- acqp.ACQ_protocol_name
PulseSequenceDetails: acqp.ACQ_scan_name
NonlinearGradientCorrection: visu_pars.VisuAcqKSpaceTraversal
NumberShots: visu_pars.VisuAcqKSpaceTrajectoryCnt
ParallelReductionFactorInPlane: acqp.ACQ_phase_factor
ParallelAcquisitionTechnique: null
PartialFourier: visu_pars.VisuAcqPartialFourier
PartialFourierDirection: null
PhaseEncodingDirection:
- key: visu_pars.VisuAcqGradEncoding
where: phase_enc
- visu_pars.VisuAcqImagePhaseEncDir
EffectiveEchoSpacing:
BWhzPixel: visu_pars.VisuAcqPixelBandwidth
MatSizePE:
key: method.PVM_EncMatrix
idx:
- key: visu_pars.VisuAcqGradEncoding
where: phase_enc
- 1
ACCfactor: acqp.ACQ_phase_factor
script: (1 / (MatSizePE * BWhzPixel)) / ACCfactor
TotalReadoutTime:
ETL: visu_pars.VisuAcqEchoTrainLength
BWhzPixel: visu_pars.VisuAcqPixelBandwidth
ACCfactor: acqp.ACQ_phase_factor
script: (1 / BWhzPixel) / ACCfactor
EchoTime:
TE: visu_pars.VisuAcqEchoTime
Equation: np.array(TE)/1000
InversionTime: visu_pars.VisuAcqInversionTime
SliceTiming:
TR: visu_pars.VisuAcqRepetitionTime
Order: acqp.ACQ_obj_order
script: np.linspace(0, TR/1000, len(Order) + 1)[Order]
SliceEncodingDirection:
- key: visu_pars.VisuAcqGradEncoding
where: slice_enc
- EncSeq: visu_pars.VisuAcqGradEncoding
script: len(EncSeq)
DwellTime:
BWhzPixel: visu_pars.VisuAcqPixelBandwidth
script: 1/BWhzPixel
FlipAngle: visu_pars.VisuAcqFlipAngle
MultibandAccerlationFactor: null
AnatomicalLandmarkCoordinates: null
InstitutionName: visu_pars.VisuInstitution
InstitutionAddress: null
InstitutionalDepartmentName: null

fmri:
RepetitionTime:
TR: visu_pars.VisuAcqRepetitionTime
script: TR/1000
VolumeTiming:
TR: visu_pars.VisuAcqRepetitionTime
NR: method.PVM_NRepetitions
script: (np.arange(NR)*(TR/1000)).tolist()
TaskName: null
NumberOfVolumesDiscardedByScanner: method.PVM_DummyScans
NumberOfVolumesDiscardedByUser: null
DelayTime: null
AcquisitionDuration:
TR: method.PVM_ScanTime
script: TR/1000
DelayAfterTrigger: null
Instructions: null
TaskDescription: null
CogAtlasID: https://www.cognitiveatlas.org/fillYourID
CogPOID: http://www.cogpo.org/fillYourID

fieldmap:
IntendedFor: ''
75 changes: 75 additions & 0 deletions bids-spec/bids-spec_v1.2.2_brkraw.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
brkraw:
path:
type: string
pattern: '^[a-zA-Z0-9_/]{1,100}$' # Assuming paths can be longer and include slashes
description: "Path to the data file or directory"
scan-id:
type: int
description: "Numerical identifier for the scan"
reco-id:
type: int
description: "Reconstruction identifier for the scan"
offset:
type: int
description: "Offset value for the data read"
num-frames:
type: int
description: "Number of frames in the scan"
preset:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Name of preset configurations for the tonifti conversion"

bids-filename:
sub:
type: string
pattern: '^[a-zA-Z0-9]{1,13}$'
description: "Subject identifier, alphanumeric"
ses:
type: string
pattern: '^[a-zA-Z0-9]{1,13}$'
description: "Session identifier, alphanumeric"
task:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Task label"
acq:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Acquisition label"
ce:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Contrast enhancement label"
rec:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Reconstruction label"
dir:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Direction label"
run:
type: string
pattern: '^[0-9]{1,2}$'
description: "Run identifier, zero-padded if numerical, e.g., 'run-01'"
inv:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Inversion label"
flip:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Flip angle"
mt:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Magnetization transfer label"
part:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Participant label"
modality:
type: string
pattern: '^[a-zA-Z0-9]{1,20}$'
description: "Imaging modality"
29 changes: 29 additions & 0 deletions plugin/bids/CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
cff-version: 1.2.0
title: "bids"
version: ""
abstract: ""
message: ""
repository-code: "https://github.com/BrkRaw/brkraw-plugin/plugin/bids"

identifiers:
- description: ""
type: doi
value: "/"

contact:
- email: shlee@unc.edu
family-names: SungHo
given-names: Lee

authors:
- email: shlee@unc.edu
family-names: SungHo
given-names: Lee

license:

keywords:
- Bruker
- BIDS
- converter
- plugin
15 changes: 15 additions & 0 deletions plugin/bids/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Copyright © [year] [affiliation]

All rights reserved.

This software, MyPlugIn, is developed by [author or team]. This plugin for BrkRaw is licensed under the [specific license] License.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of [alliiation] the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 change: 1 addition & 0 deletions plugin/bids/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# BrkRaw ToNifTi App Plugin for BIDS conversions
137 changes: 137 additions & 0 deletions plugin/bids/bids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
"""This module defines MyPlugIn, a custom plugin for the nifti application within the BrkRaw framework.
The MyPlugIn class extends the BasePlugin class and is tailored to enhance the functionality of
BrkRaw's conversion process by allowing specific customizations for NIfTI conversions.
Key Features:
- Allows custom handling of data objects, affine transformations, and NIfTI headers based on
specific scan, reconstruction, or file data.
- Includes methods for inspecting data compatibility and setting parameters based on the provided
PvObj instances (PvScan, PvReco, PvFiles).
- Supports the integration of additional processing needs by overriding mandatory and optional methods.
The plugin architecture is designed to facilitate easy additions and modifications to the data processing
pipeline, making it adaptable to various research requirements.
Author: SungHo Lee
Created: 2024-04-30
"""


from __future__ import annotations
from brkraw.app.tonifti import BasePlugin
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from numpy.typing import NDArray
from typing import Union, Optional
from nibabel.nifti1 import Nifti1Header
from brkraw.app.tonifti import PvScan, PvReco, PvFiles


class Bids(BasePlugin):
""" Boilerplate code for a plugin for the nifti app in BrkRaw.
The BasePlugin class extends the Scan class in brkraw.api.data. Refer to any compatible methods from
brkraw.api.data.scan.Scan for further guidance.
Mandatory methods that must be implemented:
- get_dataobj(self, reco_id: Optional[int] = None) -> NDArray:
This method returns a data object in numpy ndarray format. Include custom code for data processing as needed.
'reco_id' is required when accessing data under the pdata folder (such as '2dseq').
- get_affine(self, reco_id: Optional[int] = None, subj_type: Optional[str] = None, subj_position: Optional[str] = None) -> NDArray:
This method returns an affine matrix. Include custom rotations as necessary.
'reco_id', 'subj_type', and 'subj_position' are optional parameters to support type and position overrides.
- get_nifti1header(self, reco_id: Optional[int] = None) -> Nifti1Header:
This method returns a modified NIfTI header. Make any necessary updates to the NIfTI Header here.
Optional internal methods:
- _inspect(self):
This method should be implemented to check whether the given data is compatible with the plugin.
- _set_params(self):
This method should be implemented to set parameter data or map binary files to class attributes.
"""

def __init__(self, pvobj: Union['PvScan', 'PvReco', 'PvFiles'],
# --- start of custom arguments ---
dti: Optional[bool],
msme: Optional[bool],
# --- end of custom arguments ---
**kwargs
) -> None:
"""Initialize the plugin with a PvObj class instance.
Args:
pvobj (PvScan | PvReco | PvFiles): Primitive class for PvObj (PvStudy is not supported).
option (bool): If true, multiply dataobj by 2
"""
super().__init__(pvobj, **kwargs)
# --- start of mapping custom argumentss ---
self.dti = dti
self.msme = msme
# --- end of mapping custom arguments ---
self._inspect()
self._set_params()

def _inspect(self):
"""Inspect the provided data to ensure compatibility with this plugin.
Example checks might include verifying parameters in 'acqp', 'method', and 'visu_pars' files.
"""
pass

def _set_params(self):
"""Set parameter values or file objects as attributes of this class.
Access parameter files and read necessary binary data.
"""
self.acqp = self.pvobj.acqp
self.method = self.pvobj.method
self.visu_pars = self.pvobj.get_visu_pars() # this will get visu_pars from first pdata available to the dataset

with self.pvobj.get_fid() as f:
self.fid = f.read()
with self.pvobj.get_2dseq() as f: # this will get 2dseq from first pdata available to the dataset
self.dataarray = f.read()


def get_dataobj(self, reco_id: Optional[int] = None) -> NDArray:
"""Retrieve the data object, optionally filtered by reco_id.
Args:
reco_id (Optional[int]): Specifies the reconstruction ID to filter the data.
Returns:
NDArray: The data object as a numpy ndarray.
"""
dataobj = super().get_dataobj(scanobj=self,
reco_id=reco_id)
if self.option:
dataobj *= 2
return dataobj

def get_affine(self, reco_id:Optional[int]=None,
subj_type:Optional[str]=None,
subj_position:Optional[str]=None) -> NDArray:
"""Retrieve the affine transformation matrix.
Args:
reco_id (Optional[int]): Reconstruction ID if specific data access is needed.
subj_type (Optional[str]): Subject type for custom processing.
subj_position (Optional[str]): Subject position for custom processing.
Returns:
NDArray: Affine transformation matrix.
"""
return super().get_affine(scanobj=self,
reco_id=reco_id,
subj_type=subj_type,
subj_position=subj_position)

def get_nifti1header(self) -> Nifti1Header:
"""Retrieve the NIfTI header updated as necessary for this plugin.
Returns:
Nifti1Header: The updated NIfTI header.
"""
return super().get_nifti1header(self)
Loading

0 comments on commit 1311811

Please sign in to comment.