Skip to content

Commit

Permalink
Merge pull request #31 from alexcraven/patch-1
Browse files Browse the repository at this point in the history
Various performance enhancements
  • Loading branch information
wtclarke authored Jul 7, 2023
2 parents fc321cd + 6a7ad51 commit 7c9c113
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 199 deletions.
351 changes: 180 additions & 171 deletions mapvbvd/mapVBVD.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,21 @@ def loop_mdh_read(fid, version, Nscans, scan, measOffset, measLength, print_prog
t = tqdm(total=measLength, unit='B', unit_scale=True, unit_divisor=1024,
desc='Scan %d/%d, read all mdhs' % (scan + 1, Nscans), leave=False,
file=stdout)

while True:
# Read mdh as binary (uint8) and evaluate as little as possible to know...
# ... where the next mdh is (ulDMALength / ushSamplesInScan & ushUsedChannels)
# ... whether it is only for sync (MDH_SYNCDATA)
# ... whether it is the last one (MDH_ACQEND)
# evalMDH() contains the correct and readable code for all mdh entries.
try:
# read everything and cut out the mdh
data_u8 = np.fromfile(fid, dtype=np.uint8, count=int(ulDMALength))
if data_u8.size < int(ulDMALength):
# read only the MDH part
# Note, mhdStart is NEGATIVE offset relative to end of this block
fid.seek(int(ulDMALength) + mdhStart, 1)
# fid.read might be faster...
data_u8 = np.fromfile(fid, dtype=np.uint8, count=-mdhStart)
if data_u8.size < -mdhStart:
raise EOFError
data_u8 = data_u8[mdhStart:]

except EOFError:
import warnings
Expand Down Expand Up @@ -311,7 +314,8 @@ def mapVBVD(filename, quiet=False, **kwargs):
# bReadRefPCScan = kwargs.get('bReadRefPCScan', True)
# bReadRTfeedback = kwargs.get('bReadRTfeedback', True)
# bReadPhaseStab = kwargs.get('bReadPhaseStab', True)
# bReadHeader = kwargs.get('bReadHeader', True)
bReadHeader = kwargs.get('bReadHeader', True)
bReadMDH = kwargs.get('bReadMDH', True)

# ignoreROoffcenter = kwargs.get('ignoreROoffcenter', False)

Expand Down Expand Up @@ -368,174 +372,179 @@ def mapVBVD(filename, quiet=False, **kwargs):

currTwixObj = AttrDict()
currTwixObjHdr = twix_hdr()
# rstraj = 0
# read header
currTwixObjHdr, rstraj = read_twix_hdr(fid, currTwixObjHdr)
currTwixObj.update({'hdr': currTwixObjHdr})

# declare data objects:
def mytmo(dtype):
return twix_map_obj(dtype, filename, version, rstraj, **kwargs)
currTwixObj.update({'image': mytmo('image')})
currTwixObj.update({'noise': mytmo('noise')})
currTwixObj.update({'phasecor': mytmo('phasecor')})
currTwixObj.update({'phasestab': mytmo('phasestab')})
currTwixObj.update({'phasestab_ref0': mytmo('phasestab_ref0')})
currTwixObj.update({'phasestab_ref1': mytmo('phasestab_ref1')})
currTwixObj.update({'refscan': mytmo('refscan')})
currTwixObj.update({'refscanPC': mytmo('refscanPC')})
currTwixObj.update({'refscan_phasestab': mytmo('refscan_phasestab')})
currTwixObj.update({'refscan_phasestab_ref0': mytmo('refscan_phasestab_ref0')})
currTwixObj.update({'refscan_phasestab_ref1': mytmo('refscan_phasestab_ref1')})
currTwixObj.update({'rtfeedback': mytmo('rtfeedback')})
currTwixObj.update({'vop': mytmo('vop')})

# TODO: print reader version information
# if s == 0:
# # print(f'Reader version: {currTwixObj['image'].readerVersion})
# print('UTC: TODO')

# jump to first mdh
cPos += hdr_len
# print(cPos[0])
fid.seek(cPos[0], 0)

# print(f'Scan {s + 1}/{NScans}, read all mdhs:')

mdh_blob, filePos, isEOF = loop_mdh_read(fid, version, NScans, s, measOffset[s],
measLength[s], print_prog=not quiet) # uint8; size: [ byteMDH Nmeas ]

cPos = filePos[-1]
# filePos = filePos[:-1]

# get mdhs and masks for each scan, no matter if noise, image, RTfeedback etc:
[mdh, mask] = evalMDH(mdh_blob, version)

# Assign mdhs to their respective scans and parse it in the correct twix objects.

# MDH_IMASCAN
isCurrScan = mask.MDH_IMASCAN.astype(bool)
if isCurrScan.any():
currTwixObj.image.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('image', None)

# MDH_NOISEADJSCAN
isCurrScan = mask.MDH_NOISEADJSCAN.astype(bool)
if isCurrScan.any():
currTwixObj.noise.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('noise', None)

# MDH_PATREFSCAN refscan
isCurrScan = \
(mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)\
& ~(mask.MDH_PHASCOR
| mask.MDH_PHASESTABSCAN
| mask.MDH_REFPHASESTABSCAN
| mask.MDH_RTFEEDBACK
| mask.MDH_HPFEEDBACK)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan', None)

# MDH_RTFEEDBACK
isCurrScan = (mask.MDH_RTFEEDBACK | mask.MDH_HPFEEDBACK) & ~mask.MDH_VOP
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.rtfeedback.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('rtfeedback', None)

# VOP
isCurrScan = (mask.MDH_RTFEEDBACK & mask.MDH_VOP)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.vop.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('vop', None)

# MDH_PHASCOR
isCurrScan = mask.MDH_PHASCOR & (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasecor.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasecor', None)

# refscanPC
isCurrScan = mask.MDH_PHASCOR & (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscanPC.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscanPC', None)

# phasestab MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_PHASESTABSCAN & ~mask.MDH_REFPHASESTABSCAN)\
& (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasestab.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasestab', None)

# refscanPS MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_PHASESTABSCAN & ~mask.MDH_REFPHASESTABSCAN)\
& (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan_phasestab.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan_phasestab', None)

# phasestabRef0 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & ~mask.MDH_PHASESTABSCAN)\
& (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasestab_ref0.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasestab_ref0', None)

# refscanPSRef0 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & ~mask.MDH_PHASESTABSCAN)\
& (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan_phasestab_ref0.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan_phasestab_ref0', None)

# phasestabRef1 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & mask.MDH_PHASESTABSCAN)\
& (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasestab_ref1.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasestab_ref1', None)

# refscanPSRef1 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & mask.MDH_PHASESTABSCAN)\
& (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan_phasestab_ref1.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan_phasestab_ref1', None)

if isEOF:
# recover from read error
for keys in currTwixObj:
if keys != 'hdr':
currTwixObj[keys].tryAndFixLastMdh()
if bReadHeader:
currTwixObjHdr, rstraj = read_twix_hdr(fid, currTwixObjHdr)
currTwixObj.update({'hdr': currTwixObjHdr})
else:
for keys in currTwixObj:
if keys != 'hdr':
currTwixObj[keys].clean()
rstraj = 0

if bReadMDH:

# declare data objects:
def mytmo(dtype):
return twix_map_obj(dtype, filename, version, rstraj, **kwargs)
currTwixObj.update({'image': mytmo('image')})
currTwixObj.update({'noise': mytmo('noise')})
currTwixObj.update({'phasecor': mytmo('phasecor')})
currTwixObj.update({'phasestab': mytmo('phasestab')})
currTwixObj.update({'phasestab_ref0': mytmo('phasestab_ref0')})
currTwixObj.update({'phasestab_ref1': mytmo('phasestab_ref1')})
currTwixObj.update({'refscan': mytmo('refscan')})
currTwixObj.update({'refscanPC': mytmo('refscanPC')})
currTwixObj.update({'refscan_phasestab': mytmo('refscan_phasestab')})
currTwixObj.update({'refscan_phasestab_ref0': mytmo('refscan_phasestab_ref0')})
currTwixObj.update({'refscan_phasestab_ref1': mytmo('refscan_phasestab_ref1')})
currTwixObj.update({'rtfeedback': mytmo('rtfeedback')})
currTwixObj.update({'vop': mytmo('vop')})

# TODO: print reader version information
# if s == 0:
# # print(f'Reader version: {currTwixObj['image'].readerVersion})
# print('UTC: TODO')

# jump to first mdh
cPos += hdr_len
# print(cPos[0])
fid.seek(cPos[0], 0)

# print(f'Scan {s + 1}/{NScans}, read all mdhs:')

mdh_blob, filePos, isEOF = loop_mdh_read(fid, version, NScans, s, measOffset[s],
measLength[s], print_prog=not quiet)
# uint8; size: [ byteMDH Nmeas ]

cPos = filePos[-1]
# filePos = filePos[:-1]

# get mdhs and masks for each scan, no matter if noise, image, RTfeedback etc:
[mdh, mask] = evalMDH(mdh_blob, version)

# Assign mdhs to their respective scans and parse it in the correct twix objects.

# MDH_IMASCAN
isCurrScan = mask.MDH_IMASCAN.astype(bool)
if isCurrScan.any():
currTwixObj.image.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('image', None)

# MDH_NOISEADJSCAN
isCurrScan = mask.MDH_NOISEADJSCAN.astype(bool)
if isCurrScan.any():
currTwixObj.noise.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('noise', None)

# MDH_PATREFSCAN refscan
isCurrScan = \
(mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)\
& ~(mask.MDH_PHASCOR
| mask.MDH_PHASESTABSCAN
| mask.MDH_REFPHASESTABSCAN
| mask.MDH_RTFEEDBACK
| mask.MDH_HPFEEDBACK)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan', None)

# MDH_RTFEEDBACK
isCurrScan = (mask.MDH_RTFEEDBACK | mask.MDH_HPFEEDBACK) & ~mask.MDH_VOP
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.rtfeedback.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('rtfeedback', None)

# VOP
isCurrScan = (mask.MDH_RTFEEDBACK & mask.MDH_VOP)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.vop.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('vop', None)

# MDH_PHASCOR
isCurrScan = mask.MDH_PHASCOR & (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasecor.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasecor', None)

# refscanPC
isCurrScan = mask.MDH_PHASCOR & (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscanPC.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscanPC', None)

# phasestab MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_PHASESTABSCAN & ~mask.MDH_REFPHASESTABSCAN)\
& (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasestab.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasestab', None)

# refscanPS MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_PHASESTABSCAN & ~mask.MDH_REFPHASESTABSCAN)\
& (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan_phasestab.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan_phasestab', None)

# phasestabRef0 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & ~mask.MDH_PHASESTABSCAN)\
& (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasestab_ref0.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasestab_ref0', None)

# refscanPSRef0 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & ~mask.MDH_PHASESTABSCAN)\
& (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan_phasestab_ref0.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan_phasestab_ref0', None)

# phasestabRef1 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & mask.MDH_PHASESTABSCAN)\
& (~mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.phasestab_ref1.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('phasestab_ref1', None)

# refscanPSRef1 MDH_PHASESTABSCAN
isCurrScan = (mask.MDH_REFPHASESTABSCAN & mask.MDH_PHASESTABSCAN)\
& (mask.MDH_PATREFSCAN | mask.MDH_PATREFANDIMASCAN)
isCurrScan = isCurrScan.astype(bool)
if isCurrScan.any():
currTwixObj.refscan_phasestab_ref1.readMDH(mdh, filePos, isCurrScan)
else:
currTwixObj.pop('refscan_phasestab_ref1', None)

if isEOF:
# recover from read error
for keys in currTwixObj:
if keys != 'hdr':
currTwixObj[keys].tryAndFixLastMdh()
else:
for keys in currTwixObj:
if keys != 'hdr':
currTwixObj[keys].clean()

twix_obj.append(myAttrDict(currTwixObj))

Expand Down
Loading

0 comments on commit 7c9c113

Please sign in to comment.