sarpy.BRUKERIO package

Submodules

sarpy.BRUKERIO.AData_classes module

Class definitions for the analysed data structures

class sarpy.BRUKERIO.AData_classes.AData(**kwargs)[source]

Bases: object

data = None[source]
export2nii(filename)[source]

Export AData content to a named Nifti1 file using the visu_pars-defined geometry of the associated parent processed data (PData)

Parameters

filename (string) – where to write the file, what did you think?

Example:
>>> import sarpy
>>> scn = sarpy.Scan('PhantomOrientation.iY1/2')
>>> scn.store_adata(key='times2',data=scn.pdata[0].data*2, force=True)
>>> scn.adata['times2'].export2nii('/tmp/PhantomOrientation-times2.nii.gz')
classmethod fromdata(parent=None, data=None, **kwargs)[source]

This creates an AData object from an array (maybe somehing else later) It does not store it on disk. This would typically be done by the ADataDict on assignment to a key.

Parameters
  • parent (BRUKER_classes.PDATA_file) – A parent has to be an object that provides a UID and has a visu_pars attribute. Typically a PDATA_file

  • data (array) – sourcedata

  • meta (dict(optional)) – meta information in the form of a dictionary. The following keys will be added to it: parent_uid, created_datetime, parent_filename, compressed.

classmethod fromfile(filename, parent=None, lazy=True)[source]

classmethod that can be used to initiatlize the AData object by reading the content from file. To use, issue:

>>> import glob, os
>>> adata_dir = glob.glob(adataroot+'/*/*')[0] # take the first dir
>>> adata_dir_short = re.sub(adataroot+os.path.sep, '', adata_dir)
>>> AData.fromfile(adata_dir_short)  
Analysed data ('...') based on PDATA (uid=...)
  created on ...
  parent: ...

Admittedly this will rarely be required and most likely be done from some other constructor.

Parameters

filename (string) – points to the adataroot/uid/uid.*/ directory

visu_pars = None[source]
class sarpy.BRUKERIO.AData_classes.ADataDict(*args, **kwargs)[source]

Bases: collections.abc.MutableMapping

A dictionary which perfoms some magic on value-by-key assignment

Pre-existing keys are bein checked against the new key. This is inspired by an answer on stackoverflow to the question of how to perfectly override a dict.

sarpy.BRUKERIO.AData_classes.load_AData(pdatas, dirname)[source]
sarpy.BRUKERIO.AData_classes.mkdir_p(path)[source]

feature that allows the creation of the intermediate directories. it mimics the system call of mkdir -p

sarpy.BRUKERIO.AData_classes.silentremove(filename)[source]

remove files and don’t get upset if they don’t exist

sarpy.BRUKERIO.BRUKER_classes module

Class Definitions for BRUKER data

class sarpy.BRUKERIO.BRUKER_classes.AttrDict(**kwargs)[source]

Bases: object

a class that behaves like a dict but gives you access to its attributes directly

iteritems()[source]
keys()[source]
values()[source]
class sarpy.BRUKERIO.BRUKER_classes.Experiment(root=None, absolute_root=False)[source]

Bases: sarpy.BRUKERIO.BRUKER_classes.StudyCollection

An Experiment is not BRUKER terminology. It is a grouping of several studies (that have scans themselves) by various criteria. Typically, the patient name contains a root pointing to a common goal of the performed scans. It is a bit like a patient with the relaxation of the requirement of having identical SUBJECT_ids.

find_studies(root=None, absolute_root=False)[source]
classmethod from_filter(filterstring)[source]
classmethod from_masterlist(masterlistname)[source]
masterlist_df = None[source]
masterlist_filename = None[source]
study_masterlist_df = None[source]
class sarpy.BRUKERIO.BRUKER_classes.JCAMP_file(filename)[source]

Bases: sarpy.BRUKERIO.BRUKER_classes.AttrDict

Represents a JCAMP encoded parameter file.

Parameters become attributes in this class

class sarpy.BRUKERIO.BRUKER_classes.PDATA_file(filename)[source]

Bases: object

Initialize a processed data set that usually sits in */pdata/[1-9].

constructor expects a directory name (filename). It will look for the 2dseq file, the d3proc and th reco file.

d3proc = None[source]
data = None[source]
dimcomment = None[source]
dimdesc = None[source]
export2nii(filename, rescale=None, std_mod=None)[source]

Export the data originating from a 2dseq (BRUKER) reconstruction to a Nifti file format.

Parameters

filename (string) – where to write the file

A lot of the magic happens in visu_pars_2_Nift1Header in order to figure out geometry.

Examples:
>>> import tempfile
>>> scn = Scan(os.path.join('readfidTest.ix1','3'))
>>> fname = os.path.join(tempfile.gettempdir(),'readfid.nii')
>>> print('writing tempfile %s' % fname) 
writing tempfile ...readfid.nii
>>> scn.pdata[0].export2nii(fname)
reco = None[source]
store_adata(*args, **kwargs)[source]

Store some secondary data for this PData scan.

See call signature of AData_classes.AData.fromdata

This triggers an update in the adata dictionary of the parent object (Scan).

uid()[source]
visu_pars = None[source]
class sarpy.BRUKERIO.BRUKER_classes.Patient(patient_name)[source]

Bases: sarpy.BRUKERIO.BRUKER_classes.StudyCollection

A Patient is a special Collection of studies in that the subject_id has to agree from one study to the next

class sarpy.BRUKERIO.BRUKER_classes.Scan(root, absolute_root=False)[source]

Bases: object

Object to represent a BRUKER scan consisting, typically, of FID_file and PDATA_file(s).

The __init__() method expects the filename to be a directory. It will try around a bit (filenames inside the directory) before throwing an exception. It will also give up if it can’t find any of the acqp, method, fid or one 2dseq file.

Simple Example:

>>> import os
>>> exp3 = Scan('readfidTest.ix1/3')
>>> dir(exp3)    
['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
 '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
 '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'acqp',
 'adata', 'dirname', 'fid', 'method', 'pdata', 'pdata_uids',
 'shortdirname', 'store_adata']
>>> exp3.acqp.ACQ_protocol_name
'FLASH_bas(modified)'
>>> exp3.acqp.ORIGIN
'Bruker BioSpin MRI GmbH'
>>> exp3.acqp.DATE
'Thu Feb 21 19:01:26 2013 PST (UT-8h)'

Also, Scan has a pretty way of falling over when no fid file is detected:

>>> Scan('readfidTest.ix1/9') 
Traceback (most recent call last):
    ...
IOError:...

Scan should be able to read spectro scans:

>>> Scan('VFAT1phant1.mo1/8').fid.shape
(2048, 30)
>>> Scan('VFAT1phant1.mo1/9').fid.shape
(2048, 30)
acqp = None[source]
adata = None[source]
fftfid = None[source]
fid = None[source]
masterlist_attr(attr, level=None)[source]

look up attr in the hierarchy of dictionaries of the masterlist config file. As a rule, the attribute stored at the more specific (deeper) level takes precedence.

level = ‘Experiment’, ‘Patient’, ‘Study’, ‘Scan’, None

method = None[source]
pdata = None[source]
pdata_uids = None[source]
rm_adata(key)[source]

delete adata set

store_adata(pdata_idx=0, force=False, **kwargs)[source]

Store an AData set for one of the processed children of this scan. Typically the first one (pdata_idx=0)

Parameters
  • force (boolean) – overwrite pre-existing AData sets, (default False)

  • compressed (boolean) – compress adata files on write to disk, (default True)

class sarpy.BRUKERIO.BRUKER_classes.Study(root, absolute_root=False)[source]

Bases: object

A study in BRUKER parlance is a collection of scans performed on on subject (typically within a day, without interruption). A study directory is expected to contain a JCAMP file ‘subject’ and have one or more subdirectories which are scans.

find_adata_scans()[source]

All keys AND SCANS of adata sets attached to scans in this study

find_scan_by_protocol(protocol_name)[source]
masterlist_filename = None[source]
rm_adata(key)[source]

Remove adata with given key by iterating over the lot

scan_finder(**kwargs)[source]

This is the non-generator version and is provided for convenience. See difference between range and xrange

scans = None[source]
xscan_finder(**kwargs)[source]

Generator of all scans in urrent study that fit the criteria as given by kwargs.

All possible keys are listed and associated to a comparison function in the submodule JCAMP_comparison.

class sarpy.BRUKERIO.BRUKER_classes.StudyCollection[source]

Bases: object

A StudyCollection can have multiple studies (in BRUKER speak) which can in turn have multiple scans. It can be initialised by pointing it to a scan or study. This should be a superclass too (?), e.g. the Patient and the Experiment class.

add_study(study=None, by_name=None, by_uid=None)[source]

search through database to find anything that matches root

Parameters
  • study (Study) – add the indicated study

  • by_name (string) – search through database with the indicated string

  • by_uid (string) – search through database by UID. This is potentially very slow

find_adata_scans(flatten=False)[source]
find_scan_by_protocol(protocol_name)[source]
get_SUBJECT_id()[source]
rm_adata(key)[source]

Remove adata with given key by iterating over all studies

scan_finder(**kwargs)[source]

This is the non-generator version and is provided for convenience. See difference between range and xrange

xscan_finder(**kwargs)[source]

Generator to yield all scans that match te criteria given in kwargs.

The meat of the code is in Study.xscan_finder()

sarpy.BRUKERIO.BRUKER_classes.find_all_patients_in_masterlists()[source]
sarpy.BRUKERIO.BRUKER_classes.last_path_components(absdirname, depth=1)[source]

Return the last two parts of a path. Should be platform independent and fairly immune to trailing ‘/’ and other irregularities. Used to determine the shortdirname in Scan and Study.

>>> last_path_components('~/bdata/stefan/nmr/readfidTest.ix1/9')
'9'
>>> last_path_components('~/bdata/stefan/nmr/readfidTest.ix1/9/')
'9'
>>> last_path_components('~/bdata/stefan/nmr/readfidTest.ix1/9/', depth=2)
'readfidTest.ix1/9'
sarpy.BRUKERIO.BRUKER_classes.strip_all_but_classname(obj, class_str)[source]

Nicely format the class_str that is used in some of the __str__ calls

sarpy.BRUKERIO.JCAMP_comparison module

Copyright: SARlab members, UBC, Vancouver, 2013

sarpy.BRUKERIO.JCAMP_comparison.arr_comp(a, b)[source]
sarpy.BRUKERIO.JCAMP_comparison.int_comp(a, b)[source]
sarpy.BRUKERIO.JCAMP_comparison.list_param_by_type(type_=<class 'str'>, exp_names=['NecS3'], fname=None)[source]

create part of the soure code in this module: sort JCAMP parameter names into types (str, array and other) and create a dictionary that associate frozensets of these parameters with the corresponding compare function

sarpy.BRUKERIO.JCAMP_comparison.regex_comp(a, b)[source]

sarpy.BRUKERIO.JCAMP_dict module

sarpy.BRUKERIO.bulk_analyze module

sarpy.BRUKERIO.check_fid_acqp_method module

Quick check for the presence of all sorts of BRUKER files in the entire dataroot. A fully stocked scan should have acqp, method, fid, 2dseq. This results in a score of 1 + 2 + 4 + 8 = 15. If one is missing, the score is less.

sarpy.BRUKERIO.check_nii_vs_visu_pars module

sarpy.BRUKERIO.compare_JCAMP_readers module

sarpy.BRUKERIO.congrid module

Rebinning example from he SciPy.org Cookbook

sarpy.BRUKERIO.congrid.congrid(a, newdims, method='linear', centre=False, minusone=False)[source]

Arbitrary resampling of source array to new dimension sizes. Currently only supports maintaining the same number of dimensions. To use 1-D arrays, first promote them to shape (x,1).

Parameters
  • a (numpy.ndarray) – input array

  • newdims (list) – new dimensions

  • method (string) – neighbour - closest value from original data nearest and linear - uses n x 1-D interpolations using scipy.interpolate.interp1d (see Numerical Recipes for validity of use of n 1-D interpolations) spline - uses ndimage.map_coordinates

  • centre (boolean) – True - interpolation points are at the centres of the bins False - points are at the front edge of the bin

  • minusone (boolean) – For example- inarray.shape = (i,j) & new dimensions = (x,y) False - inarray is resampled by factors of (i/x) * (j/y) True - inarray is resampled by(i-1)/(x-1) * (j-1)/(y-1) This prevents extrapolation one element beyond bounds of input array.

Uses the same parameters and creates the same co-ordinate lookup points as IDL’’s congrid routine, which apparently originally came from a VAX/VMS routine of the same name.

sarpy.BRUKERIO.descriptortest module

Created on Thu Feb 28 13:19:35 2013

@author: stefan

class sarpy.BRUKERIO.descriptortest.C[source]

Bases: object

a = 'forty two'[source]
class sarpy.BRUKERIO.descriptortest.Cnew[source]

Bases: object

data = [42, 42, 42][source]
class sarpy.BRUKERIO.descriptortest.D[source]

Bases: object

class sarpy.BRUKERIO.descriptortest.Dnew[source]

Bases: object

class sarpy.BRUKERIO.descriptortest.dict_plus[source]

Bases: dict

class sarpy.BRUKERIO.descriptortest.lazy_property_desc(fget)[source]

Bases: object

class sarpy.BRUKERIO.descriptortest.tryout(someval)[source]

Bases: object

adata = None[source]
getname()[source]
property name[source]
setname(value)[source]

sarpy.BRUKERIO.dict_walk_minimal_example module

sarpy.BRUKERIO.lazy_property module

Created on Thu Mar 21 16:06:35 2013

@author: stefan

class sarpy.BRUKERIO.lazy_property.lazy_property(fget)[source]

Bases: object

Meant to be used for lazy evaluation of an object attribute. property should represent non-mutable data, as it replaces itself.

An example illustrates the use. First define a class that contains a lazy_property. That call it and observe how the calculation is only performed once.

>>> class Test(object):
...     @lazy_property
...     def results(self):
...         calcs = 42 # do a lot of calculation here
...         print('phew, this took a lot of effort - glad I do this so rarely...')
...         return calcs
>>> A=Test()
>>> A.__dict__
{}
>>> A.results
phew, this took a lot of effort - glad I do this so rarely...
42
>>> A.results  # on a second call the calculation is not needed !
42
>>> A.__dict__  # see how results is no a proper attribute
{'results': 42}

sarpy.BRUKERIO.lowlevel module

Collection of BRUKER input routines

Handy functions to read BRUKER data and header files.

The logging is set up so that if the library user does nothing, all will be silent. Details in :py:mod: SARlogger

sarpy.BRUKERIO.lowlevel.convert_int_float_string(param)[source]
sarpy.BRUKERIO.lowlevel.dict2string(d)[source]

convert dictionary to nicely looking multi-line string

Parameters

d (dict) – input dictionary

Returns

list of strings

Return type

list

This might be useful when turning the JCAMP-style dictionaries into something that goes into a text display. Example use would be:

>>> d={'TE':2.3}
>>> print(dict2string(d))
                  TE : 2.3
sarpy.BRUKERIO.lowlevel.fftbruker(array, encoding=None, DCoffset=False)[source]

wrapper to fft bruker FIDs

returns the fft of a multi-dimensional BRUKER FID. It uses the parameter ‘encoding’ to decide over which dimensions to Fourier transform. Typically, a 2D only needs FFT over 1st and 2nd dimension (encoding = [1, 1, 0, 0]) whereas 3D files get a FT over three dimensions (encoding = [1, 1, 1, 0]). The 4th dimension (repetitions) doesn’t usually get FTed.

sarpy.BRUKERIO.lowlevel.fftfid(fptr=None, readfidresult=None, AxisFlip=True, PEshift=True, **kwargs)[source]

Take filename, retrieve fid and FT as best as you can

This relies on the FT-able axis to be in he 1st three positions.

Parameters
  • fptr – input fid file (handed through to readfid)

  • AxisFlip – Flip axis to achieve display in agreement with radiological convention (default: True)

  • PEshift – find out shifts of slice packs and apply in the PE directions (default: True)

  • squeezed – squeeze FT array before returning (default: true)

  • kwargs – handed through to readfid (only squeezed is handled internally)

Returns

complex-valued array from FT of fid

Return type

ndarray

Remarks: It does not account for the possibility of several slice packs with different orientations etc. As a result, tripilot scans are not treated properly.

sarpy.BRUKERIO.lowlevel.inner_value(somelist)[source]

Return somelist[0] a one-element list or the whole list otherwise

Parameters

somelist (list) – list that might contain only one element

Returns

element of somelist or somelist

>>> inner_value([42])
42
>>> inner_value([42,43])
[42, 43]
>>> inner_value([[42]])
42
>>> inner_value([[42,43]])
[42, 43]
>>> inner_value('spam')
'spam'
>>> inner_value(['spam'])
'spam'
>>> inner_value(['s'])
's'
>>> inner_value(['spam','eggs','bacon'])
['spam', 'eggs', 'bacon']

Warning

This method does not work for dictionaries (KeyError)

sarpy.BRUKERIO.lowlevel.pairwise(iterable)[source]

This is a solution to the problem of looking ahead in a for loop mentioned in on stackoverflow:

“s -> (s0,s1), (s1,s2), (s2, s3), …”

sarpy.BRUKERIO.lowlevel.read2dseq(scandirname, visu_pars=None)[source]

Returns BRUKER’s 2dseq file as a properly dimensioned array

Parameters
  • scandirname (string) – filename of the scan directory

  • visu_pars (dict reco, d3proc,) – parameter files (as dict) that can be provided by caller default: None which means they will be loaded by this function

Returns

dictionary with data, and header information. The data is an array of BRUKER-reconstructed image data in the respecive proc directory.

Return type

dict with ‘data’:numpy array ‘header’:dict{‘recpo’:…, ‘d3proc’:…}

Raises

IOERROR if directory non-existent

This relies on numpy’s array functionality

sarpy.BRUKERIO.lowlevel.readJCAMP(filename)[source]

Parse text file in JCAMP format

Parameters

filename (string) – filename of fid file

Returns

Dictionary of labelled data records (LDR) with LDR-names as keys and their content as values.

Return type

dict

Raises

IOERROR if opening file fails or passes on any other error

The JCAMP format is a self-documenting, ASCII text file format that is maintained by IUPAC (see a report here). It consists of labelled data records (LDR) that start with a ## and end when the next record begins. They can span several lines. The data label is enclosed between ‘##’ and ‘=’. If it starts with a $, we are dealing with a private LDR.

The issue of reading these is complicated due to the various types of data (integers, floats, strings, arrays and nested structures) that can be present.

~/bdata/readfidTest.ix1/subject:

##$SUBJECT_name_string=( 64 )
<Moosvi, readfidTest>
##$SUBJECT_name=(<Moosvi>, <readfidTest>)

>>> import os
>>> datapath = os.path.join(os.path.expanduser(dataroot),'stefan','nmr','readfidTest.ix1')
>>> a=readJCAMP(os.path.join(datapath,'subject'))
>>> a['SUBJECT_name']
['<Moosvi>', '<readfidTest>']
>>> a['SUBJECT_name_string']
'Moosvi, readfidTest'

~/bdata/readfidTest.ix1/1/acqp:

##$ACQ_user_filter=No
##$ACQ_dim_desc=( 2 )
Spatial Spatial
##$NR=1
##$D=( 64 )
0.00502257333333333 0 0.00066296 0.000114 0.000114 0 0.001886 0 2.5e-05 0
0.000886 0.000886 0.000368 0 0 0 0 0 0 0 1e-05 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##$TPQQ=( 16 )
(<hermite.exc>, 17.9862515696541, 0) (<>, 30, 0) (<>, 30, 0) (<>, 30, 0) (<>,
30, 0) (<>, 30, 0) (<>, 30, 0) (<>, 30, 0) (<>, 30, 0) (<>, 30, 0) (<>, 30, 0)
 (<>, 30, 0) (<>, 30, 0) (<>, 30, 0) (<>, 30, 0) (<>, 30, 0)
##$ACQ_grad_matrix=( 15, 3, 3 )
1 0 -0 0 1 0 0 -0 1 1 0 -0 0 1 0 0 -0 1 1 0 -0 0 1 0 0 -0 1 -0 0 1 -0 1 -0 1
0 0 -0 0 1 -0 1 -0 1 0 0 0 0 1 1 -0 0 0 1 -0 0 0 1 1 -0 0 0 1 -0 0 0 1 1 -0 0
0 1 -0 1 0 -0 0 1 0 0 -0 1 1 0 -0 0 1 0 0 -0 1 -0 0 1 -0 1 -0 1 0 0 -0 0 1 -0
1 -0 1 0 0 -0 0 1 -0 1 -0 1 0 0 0 0 1 1 -0 0 0 1 -0 0 0 1 1 -0 0 0 1 -0

>>> import os
>>> a=readJCAMP(os.path.join(datapath,'1','acqp'))
>>> a['ACQ_user_filter']
'No'
>>> a['ACQ_dim_desc']
['Spatial', 'Spatial']
>>> a['NR']
1
>>> a['D'][0:4]
[0.00502257333333333, 0, 0.00066296, 0.000114]
>>> a['TPQQ'][0:4]
[['<hermite.exc>', 17.9862515696541, 0], ['<>', 30, 0], ['<>', 30, 0], ['<>', 30, 0]]
>>> a['TPQQ'][0]
['<hermite.exc>', 17.9862515696541, 0]
>>> a['TPQQ'][0][1]
17.9862515696541
>>> a['ACQ_grad_matrix'][0]
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]])
sarpy.BRUKERIO.lowlevel.readRFshape(filename)[source]

reads BRUKERS RF shape files spnam0 etc that are stored with experiments

returns a dictionary with ready-to-use attributes for amplitude, phase, bandwidth etc.

sarpy.BRUKERIO.lowlevel.readfid(fptr=None, acqp=None, method=None, untouched=False, squeezed=True, resetNR=False)[source]

Returns BRUKER’s fid file as a properly dimensioned & rearranged array.

Parameters
  • fptr (FileType,str) – filename of fid file or filehandle to open fid file

  • acqp (dict) – dictionary of acqp parameters (default None: parameter file will be loaded)

  • method (dict) – dictionary of method parameters (default None: parameter file will be loaded)

  • untouched (boolean) – do not rearrange/reshape data (default: False)

  • squeezed (boolean) – squeeze dimension of length 1 (default: True)

  • resetNR (boolean) – for incomplete scans, reset NR if needed (default: False)

Returns

Flat (untouched = True) or Rearranged and assembled array of the acquire k-space

Return type

numpy array

Raises

IOERROR if filesize and matrix description appear to be inconsistent

BRUKER manual D.14 File Formats (Raw data files)

The reconstruction assumes that the raw data to be reconstructed will be located in a file named either fid or ser in the EXPNO directory. Any averaging of the raw data must be done before the data is written to the file, no post-acquisition averag- ing is done by the reconstruction.

K-format

The raw data file must be written in K-format to be processed by the TOPSPIN processing software. This means that every profile must be written to the file at a posi- tion which is a multiple of 1K-bytes (1024 bytes). Datasets which are imported may need to be reformatted. Both little-endian and big-endian word formats are sup- ported, the BYTORDA parameter in the acqp parameter file is assumed to correctly specify the format of the raw data file. Finally, the raw data file is assumed to contain data only, without any headers.

Packed format

Data to be processed with ParaVision can also be stored in packed format. For this purpose the parameter GO_block_size must be set to continuous.

Integer formats

By default, raw data is stored in 32-bit signed integer format, real and imaginary points of the complex signal interleaved. For applications where the data range may not exceed 16-bit, e.g. when accumulation and oversampling are disabled in analog mode, data can be stored as 16-bit short integers, setting the parameter GO_raw_data_format to GO_16BIT_SGN_INT. A warning message is displayed if an overflow occurs during data acquisition.

Floating point format

Alternatively, data can be stored in floating point format: GO_raw_data_format = GO_32BIT_FLOAT. Note, that data not acquired in the default 32-bit signed integer format cannot be processed with TOPSPIN but only by the ParaVision reconstruction.

Order of data storage

The raw data file usually contains the data in the order of acquisition. There is only one exception: in case a pipeline filter (AU) is used to process the raw data, the order of data storage is defined by the output order of the filter.

For raw datasets acquired by ParaVision methods, ordering and size of the data are described by the ACQP parameters contained in the file acqp:

  • ACQ_dim - Spatial/spectroscopic dimension of the experiment.

  • ACQ_size[ ] - Array of length ACQ_dim with length of the given dimensions. ACQ_size[0] counts real valued data and for this it must be an even number. Real and imaginary data is stored shuffled. For experiments acquired with multiple receivers (ACQ_experiment_mode == ParallelExperiment) the scans from different receivers are appended. The number of active receivers is derived from the number of selected receivers in the parameter array GO_ReceiverSelect.

  • NI - Number of objects. e.g. slices, but not purely!, could be slices*echoes

  • ACQ_obj_order - Permutation of the order of the acquired objects.

  • ACQ_phase_factor - Number of subsequent scans in the raw dataset belonging to the same Object. Typically, this parameter is set to 1 which will keep the cod- ing constant within a Multiplex step. If ACQ_phase_factor > 1, this parameter will give the number of consecutively acquired phase encoding steps that belong to a single Object. Concerning phase increment: see ACQ_rare_factor.

  • ACQ_phase_enc_mode[ ] - Ordering scheme for scans within the k-space.

    Note

    parameter seems to be renamed to ACQ_phase_encoding_mode

  • ACQ_phase_enc_start[ ] - For positioning of first scan in phase encoding scheme.

  • ACQ_rare_factor - For positioning of the ACQ_phase_factor scans within the k-space. In the case of ACQ_phase_factor > 1 the phase encoding increment is determined by ACQ_size[1] / ACQ_rare_factor. ACQ_rare_factor = ACQ_phase_factor is used for RARE experiments.

  • NR - Number of repeated experiments within the dataset.

These salient parameters are printed using the following code: [‘%s: %s’ % (k,acqp[k]) for k in [‘ACQ_dim’,’ACQ_size’,’GO_block_size’,’NI’,’ACQ_obj_order’,’ACQ_phase_factor’,’ACQ_phase_encoding_mode’,’ACQ_phase_enc_start’,’ACQ_rare_factor’,’NR’,’NSLICES’,’ACQ_spatial_phase_1’,’ACQ_spatial_size_1’]]

Examples:

>>> import os
>>> datapath = os.path.join(os.path.expanduser(dataroot),'stefan','nmr','readfidTest.ix1')
>>> fid = readfid(os.path.join(datapath,'1','fid'))
>>> fid['data'].shape   # TriPilot multi
(128, 128, 15)
>>> fid = readfid(os.path.join(datapath,'2','fid'))
>>> fid['data'].shape   # FLASH 2D
(133, 105, 5)
>>> fid = readfid(os.path.join(datapath,'3','fid'))
>>> fid['data'].shape   # FLASH 3D
(133, 105, 25)
>>> fid = readfid(os.path.join(datapath,'4','fid'))
>>> fid['data'].shape   # MSME 2D
(133, 105, 5)
>>> fid = readfid(os.path.join(datapath,'5','fid'))
>>> fid['data'].shape   # MSME 3D
(133, 105, 25)
>>> fid = readfid(os.path.join(datapath,'6','fid'))
>>> fid['data'].shape   # MSME 2D-TURBO
(256, 256, 5, 3)
>>> fid = readfid(os.path.join(datapath,'7','fid'))
>>> fid['data'].shape  # FLASH 2D (NR=25, NI=5, NSLICES=5)
(133, 105, 5, 25)
>>> fid = readfid(os.path.join(datapath,'8','fid'))
>>> fid['data'].shape  # FLASH 2D, partial acq. NR auto reset to 5
(133, 105, 5, 5)
>>> fid = readfid(os.path.join(datapath,'9','fid')) 
Traceback (most recent call last):
...
FileNotFoundError: ...
>>> # fid file 9 was missing due to incomplete scans
>>> fid = readfid(os.path.join(datapath,'10','fid'))
>>> fid['data'].shape # FLASH 2D (MATRIX 32 X 32)
(32, 32, 5)
>>> fid = readfid(os.path.join(datapath,'11','fid'))
>>> fid['data'].shape # FLASH 3D (MATRIX 32 X 32)
(32, 32, 5)
>>> fid = readfid(os.path.join(datapath,'12','fid'))
... 
... # 1-segment EPI - FIXME, this should be easy but somehow ACQ_size=(8192,1) 
... # and ACQ_scan_size=ACQ_phase_factor_scans (instead of One_Scan)
... # this should be an easy 64x64x5slice single shot EPI...
Traceback (most recent call last):
...
IndexError: ...
>>> fid = readfid(os.path.join(datapath,'13','fid'))
... 
... # 16 segment EPI - FIXME
Traceback (most recent call last):
...
IndexError: ...
>>> fid = readfid(os.path.join(datapath,'14','fid'))
>>> fid['data'].shape # DTI Standard
(133, 105, 5, 2)
>>> fid = readfid(os.path.join(datapath,'15','fid'))
... 
... # DTI SPIRAL - FIXME
Traceback (most recent call last):
...
TypeError: ...
>>> fid = readfid(os.path.join(datapath,'16','fid'))
>>> fid['data'].shape # UTE 2D
(64, 402, 5)
>>> fid = readfid(os.path.join(datapath,'17','fid')) # UTE 3D
... 
... # FIXME: once we know how to read this data it should be added to
... #        the testdata submodule
Traceback (most recent call last):
...
FileNotFoundError: ...
>>> fid = readfid(os.path.join(datapath,'18','fid')) # ZTE 3D
... 
... #FIXME: once we know how to read this data it should be added to
... #       the testdata submodule
Traceback (most recent call last):
...
FileNotFoundError: ...
>>> fid = readfid(os.path.join(datapath,'99','fid'))
... 
... # interrupted FLASH DCE, mismatch in filesize causes IOError
... # this is desired (and expected) behaviour
Traceback (most recent call last):
...
ValueError: ...
>>> fid = readfid(os.path.join(datapath,'99','fid'), resetNR=True)
>>> fid['data'].shape # interrupted FLASH DCE (NR=7 from formerly 25)
(133, 105, 5, 7)
sarpy.BRUKERIO.lowlevel.readfidspectro(fptr=None, acqp=None, method=None, untouched=False)[source]

Returns BRUKER’s fid file as a properly dimensioned & rearranged array

Parameters
  • fptr (string or FileType) – filename of fid file or filehandle to open fid file

  • untouched (boolean) – Do not rearrange lines into slices and echos and such in the fid in its form as found on disk

Returns

array of kspace data

Return type

numpy.array

Raises

AssertError for various inconsistencies in data size or simply misunderstandings of how the data is to be interpreted.

sarpy.BRUKERIO.masterlist module

sarpy.BRUKERIO.obj2dict module

Created on Sat Mar 16 22:28:37 2013

@author: stefan

sarpy.BRUKERIO.obj2dict.obj2dict(obj)[source]
sarpy.BRUKERIO.obj2dict.show_tree(obj)[source]

sarpy.BRUKERIO.oldtest_BRUKER_classes module

sarpy.BRUKERIO.oldtest_SARlogger module

sarpy.BRUKERIO.oldtest_lowlevel module

Test Routines for lowlevel

class sarpy.BRUKERIO.oldtest_lowlevel.Test(methodName='runTest')[source]

Bases: unittest.case.TestCase

Unit tests for readfid.

test_doctests()[source]

Run the doctests

test_read2dseq()[source]
test_readJCAMP()[source]

Test readJCAMP for exceptions by reading variety of acqp and method files

test_readfid()[source]

lowlevel.io.readfid()

sarpy.BRUKERIO.oldtest_lowlevel.stresstest_read2dseq(*path_filter)[source]
sarpy.BRUKERIO.oldtest_lowlevel.stresstest_readJCAMP(*path_filter)[source]
sarpy.BRUKERIO.oldtest_lowlevel.stresstest_readfid(skip=[9, 13, 15])[source]

sarpy.BRUKERIO.oldtest_write2nii module

sarpy.BRUKERIO.parseJCAMP module

sarpy.BRUKERIO.test_lowlevel module

sarpy.BRUKERIO.visu_pars_2_Nifti1Header module

Created on Mon Apr 1 00:36:03 2013

@author: stefan

sarpy.BRUKERIO.visu_pars_2_Nifti1Header.visu_pars_2_Nifti1Header(visu_pars)[source]

Take visu_pars header and extract all useful information for Nifti1Header. This attempts to get all the geometry information out without requiring any special flip etc in the data beyond the initial column-major-to-row- major flip when reading in the 2dseq file.

param dict visu_pars

visu_pars structure as previded by readJCAMP

Note: this results in a headr that’s different from the one obtained by exporting BRUKER data to dicom. Not clear why that is…

`Original Header information <http://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/`_ But this site is by far the best resource for info on the Nifti header: <http://brainder.org/2012/09/23/the-nifti-file-format/>

There are 3 different methods by which continuous coordinates can be attached to voxels. We are using method 2: METHOD 2 (used when qform_code > 0, which should be the “normal” case): Ref: ——————————————————————— The (x,y,z) coordinates are given by the pixdim[] scales, a rotation matrix, and a shift. This method is intended to represent “scanner-anatomical” coordinates, which are often embedded in the image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030), and (0018,0050)), and represent the nominal orientation and location of the data. This method can also be used to represent “aligned” coordinates, which would typically result from some post-acquisition alignment of the volume to a standard orientation (e.g., the same subject on another day, or a rigid rotation to true anatomical orientation from the tilted position of the subject in the scanner). The formula for (x,y,z) in terms of header parameters and (i,j,k) is:

[ x ] [ R11 R12 R13 ] [ pixdim[1] * i ] [ qoffset_x ] [ y ] = [ R21 R22 R23 ] [ pixdim[2] j ] + [ qoffset_y ] [ z ] [ R31 R32 R33 ] [ qfac pixdim[3] * k ] [ qoffset_z ]

In methods 2 and 3, the (x,y,z) axes refer to a subject-based coordinate system,

with +x = Right +y = Anterior +z = Superior. This is a right-handed coordinate system. However, the exact direction these axes point with respect to the subject depends on qform_code

Examples:
>>> import tempfile
>>> scn = Scan(os.path.join('readfidTest.ix1','3'))
>>> fname = os.path.join(tempfile.gettempdir(),'readfid.nii')
>>> print('writing tempfile %s' % fname) 
writing tempfile ...readfid.nii
>>> scn.pdata[0].write2nii(fname)
sarpy.BRUKERIO.visu_pars_2_Nifti1Header.visu_pars_2_matrix_size(visu_pars, reco=None)[source]

Returns the matrix size as calculated from visu_pars

Parameters

visu_pars (dict) – parameter files (as dict) that can be provided by caller

Returns

array of size

Return type

array

This relies on numpy’s array functionality. The whole routine is quite the contortion since we are swapping the x y dimensional size (because of the row-major, column major confusion). As a result the outut here corresponds to the shape produced by read2dseq and also results in images which when shown with imshow will have x-axis along the horizontal…

sarpy.BRUKERIO.watch_sdata module

sarpy.BRUKERIO.write_parameter_stack module

sarpy.BRUKERIO.write_parameter_stack.write_parameter_stack(pat_name, params, masterlist, slice=None, rootdir='/tmp', loglevel=10)[source]

For one patient, collects all images and adatas that are listed in paramdict. The format of paramdict uses scan labels and adata labels as a(n ordered) dictionary. Typically, parameter stacks are written to /tmp separately for all slices unless the keyword parameter slice is set to a slice number

# identify adata (referred to by its label) for a given scan (referred to by its scanlabel) params = [(‘roi-0h’, [‘’,’roi’]),

(‘dce-0ha_HPG’, [‘auc60’, ‘auc300’, ‘auc600’]), (‘dce-0ha_Gd’, [‘auc60’]), (‘LL-0h+2’, [‘deltaR1_HPG2’]), (‘LL-0h+3’, [‘deltaR1_Gd’])

]

expname = ‘HerS11’ masterlist = json.load(open(os.path.expanduser(os.path.join(

‘~’, ‘sdata’, expname, expname+’.json’)),’r’))

write_parameter_stack(‘HerS11Bs05’, params, masterlist, slice=4)

or, to get all slices for all patients: for patname in masterlist:

for sl in arange(6): write_parameter_stack(patname, params, masterlist, slice=sl)

Module contents