Skip to content

Commit

Permalink
Merge pull request #122 from pnewstein/master
Browse files Browse the repository at this point in the history
allow more adc channels than dac channels
  • Loading branch information
swharden committed Jul 19, 2021
2 parents 04db89e + d691c30 commit 19969f8
Show file tree
Hide file tree
Showing 9 changed files with 495 additions and 18 deletions.
Binary file added data/abfs/test_0001.abf
Binary file not shown.
430 changes: 430 additions & 0 deletions data/headers/test_0001.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Access ABF sweep data:
import pyabf
abf = pyabf.ABF("demo.abf")
abf.setSweep(sweepNumber: 3, channel: 0)
abf.setSweep(sweepNumber=3, channel=0)
print(abf.sweepY) # displays sweep data (ADC)
print(abf.sweepX) # displays sweep times (seconds)
print(abf.sweepC) # displays command waveform (DAC)
Expand Down
2 changes: 1 addition & 1 deletion src/pyabf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Documentation and code examples, and more can be found at:
https://github.com/swharden/pyABF
"""
__version__ = '2.3.2'
__version__ = '2.3.3'

import sys
import os
Expand Down
37 changes: 28 additions & 9 deletions src/pyabf/abf.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import numpy as np
from pathlib import PureWindowsPath
import hashlib
from typing import Union, List
from typing import Union, List, Tuple


class ABF:
Expand Down Expand Up @@ -604,18 +604,19 @@ def setSweep(self,
with open(self.abfFilePath, 'rb') as fb:
self._loadAndScaleData(fb)

adcName, adcUnits = self._getAdcNameAndUnits(channel)
dacName, dacUnits = self._getDacNameAndUnits(channel)

# sweep information
self.sweepNumber = sweepNumber
self.sweepChannel = channel
self.sweepUnitsY = self.adcUnits[channel]
self.sweepUnitsC = self.dacUnits[channel]
self.sweepUnitsY = adcUnits
self.sweepUnitsC = dacUnits
self.sweepUnitsX = "sec"

# standard labels
self.sweepLabelY = "{} ({})".format(
self.adcNames[channel], self.adcUnits[channel])
self.sweepLabelC = "{} ({})".format(
self.dacNames[channel], self.dacUnits[channel])
self.sweepLabelY = f"{adcName} ({adcUnits})"
self.sweepLabelC = f"{dacName} ({dacUnits})"
self.sweepLabelX = "Time (seconds)"
self.sweepLabelD = "Digital Output (V)"

Expand Down Expand Up @@ -673,8 +674,24 @@ def setSweep(self,
assert (self.sweepPointCount == len(self.sweepY))

# prepare the stimulus waveform table for this sweep/channel
epochTable = pyabf.waveform.EpochTable(self, channel)
self.sweepEpochs = epochTable.epochWaveformsBySweep[sweepNumber]
if (channel < len(self.holdingCommand)):
epochTable = pyabf.waveform.EpochTable(self, channel)
self.sweepEpochs = epochTable.epochWaveformsBySweep[sweepNumber]
else:
epochTable = None
self.sweepEpochs = None

def _getAdcNameAndUnits(self, adcIndex: int) -> Tuple[str, str]:
if (adcIndex < len(self.adcNames)):
return [self.adcNames[adcIndex], self.adcUnits[adcIndex]]
else:
return [None, None]

def _getDacNameAndUnits(self, dacIndex: int) -> Tuple[str, str]:
if (dacIndex < len(self.dacNames)):
return [self.dacNames[dacIndex], self.dacUnits[dacIndex]]
else:
return [None, None]

@property
def sweepC(self):
Expand Down Expand Up @@ -713,6 +730,8 @@ def sweepC(self, sweepData=None):
def sweepD(self, digOutNumber=0):
"""Generate a waveform for the given digital output."""
assert isinstance(self, pyabf.ABF)
if (self.sweepChannel >= len(self.holdingCommand)):
return None
epochTable = pyabf.waveform.EpochTable(self, self.sweepChannel)
sweepWaveform = epochTable.epochWaveformsBySweep[self.sweepNumber]
sweepD = sweepWaveform.getDigitalWaveform(digOutNumber)
Expand Down
2 changes: 1 addition & 1 deletion src/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# standard pypi stuff
setup(
name='pyabf',
version='2.3.2',
version='2.3.3',
author='Scott W Harden',
author_email='SWHarden@gmail.com',
python_requires='>=3.6',
Expand Down
22 changes: 16 additions & 6 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,25 @@ def test_ABF_properties(abfPath):
abf.setSweep(sweep, channel)
assert isinstance(abf.sweepChannel, int)
assert isinstance(abf.sweepNumber, int)
assert isinstance(abf.sweepLabelC, str)

# time units are manually defined
assert isinstance(abf.sweepUnitsX, str)
assert abf.sweepUnitsX == "sec"

# labels are pyabf inventions and will always be present
assert isinstance(abf.sweepLabelX, str)
assert isinstance(abf.sweepLabelY, str)
assert isinstance(abf.sweepUnitsC, str)
assert isinstance(abf.sweepUnitsX, str)
assert isinstance(abf.sweepUnitsY, str)
assert isinstance(abf.sweepLabelC, str)

# ADC labels are likely available for every channel
if (abf.sweepLabelY is not None):
assert isinstance(abf.sweepUnitsY, str)

sweepD = abf.sweepD(0) # digital output generation
assert isinstance(sweepD, np.ndarray)
# DAC labels are likely available for every channel
# but may not if there are more ADCs than DACs
if (abf.sweepUnitsC is not None):
assert isinstance(abf.sweepUnitsC, str)
assert isinstance(abf.sweepD(0), np.ndarray)


def test_uuid_isExpectedValue():
Expand Down
17 changes: 17 additions & 0 deletions tests/test_sweepHashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2643,3 +2643,20 @@
knownAbfSweepValues["user-list-durations.abf SW1 CH1"] = "51612, -35.00000000, -35.00000000, 39.15184402"
knownAbfSweepValues["user-list-durations.abf SW2 CH0"] = "51612, -44.68749619, -49.68749619, 211.29635620"
knownAbfSweepValues["user-list-durations.abf SW2 CH1"] = "51612, -35.00000000, -35.00000000, 35.34297180"

knownAbfSweepValues["test_0001.abf SW0 CH0"] = "12896, -0.24414062, -0.24414062, 0.01767103"
knownAbfSweepValues["test_0001.abf SW0 CH1"] = "12896, -0.36621094, -0.33569336, 0.01851589"
knownAbfSweepValues["test_0001.abf SW0 CH2"] = "12896, 0.18310547, 0.15258789, 0.01685126"
knownAbfSweepValues["test_0001.abf SW0 CH3"] = "12896, -0.18310547, -0.15258789, 0.01687169"
knownAbfSweepValues["test_0001.abf SW0 CH4"] = "12896, -0.15258789, -0.15258789, 0.01728301"
knownAbfSweepValues["test_0001.abf SW0 CH5"] = "12896, -0.00610352, -0.00610352, 0.00167757"
knownAbfSweepValues["test_0001.abf SW0 CH6"] = "12896, -0.06103516, -0.03051758, 0.01647715"
knownAbfSweepValues["test_0001.abf SW0 CH7"] = "12896, -0.00274658, -0.00274658, 0.00016622"
knownAbfSweepValues["test_0001.abf SW0 CH8"] = "12896, -0.00274658, -0.00274658, 0.00016532"
knownAbfSweepValues["test_0001.abf SW0 CH9"] = "12896, -0.00213623, -0.00244141, 0.00017623"
knownAbfSweepValues["test_0001.abf SW0 CH10"] = "12896, -0.00305176, -0.00305176, 0.00016586"
knownAbfSweepValues["test_0001.abf SW0 CH11"] = "12896, 0.00213623, 0.00213623, 0.00016889"
knownAbfSweepValues["test_0001.abf SW0 CH12"] = "12896, -0.00122070, -0.00122070, 0.00017642"
knownAbfSweepValues["test_0001.abf SW0 CH13"] = "12896, 0.00152588, 0.00183105, 0.00016845"
knownAbfSweepValues["test_0001.abf SW0 CH14"] = "12896, -0.21362305, -0.18310547, 0.01735568"
knownAbfSweepValues["test_0001.abf SW0 CH15"] = "12896, 0.00000000, 0.00000000, 0.00191588"
1 change: 1 addition & 0 deletions tests/test_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
FIRSTVALUES['sine sweep magnitude 20'] = [0.00000]
FIRSTVALUES['user-list-durations'] = [-69.68749, -35.00000]
FIRSTVALUES['vc_drug_memtest'] = [-7.20215]
FIRSTVALUES["test_0001"] = [-0.24414062, -0.36621094, 0.18310547, -0.18310547, -0.15258789, -0.0061035156, -0.061035156, -0.002746582, -0.002746582, -0.0021362305, -0.0030517578, 0.0021362305, -0.0012207031, 0.0015258789, -0.21362305, 0.0]


@pytest.mark.parametrize("abfPath", glob.glob("data/abfs/*.abf"))
Expand Down

0 comments on commit 19969f8

Please sign in to comment.