aboutsummaryrefslogtreecommitdiff
path: root/qolab/hardware
diff options
context:
space:
mode:
authorEugeniy E. Mikhailov <evgmik@gmail.com>2021-12-12 14:33:15 -0500
committerEugeniy E. Mikhailov <evgmik@gmail.com>2021-12-12 14:33:15 -0500
commitba880155abe63aef046f941b238f905e8b1c52cf (patch)
tree8ceccddb10bb727b6f983e29916dee97ecc601c2 /qolab/hardware
parentfd715c5edfd06fcb106ddbb3c9eadd79a96a37a7 (diff)
downloadpyExpControl-ba880155abe63aef046f941b238f905e8b1c52cf.tar.gz
pyExpControl-ba880155abe63aef046f941b238f905e8b1c52cf.zip
scope now can decimate points with smoothing
Diffstat (limited to 'qolab/hardware')
-rw-r--r--qolab/hardware/scope/__init__.py10
-rw-r--r--qolab/hardware/scope/sds1104x.py32
2 files changed, 30 insertions, 12 deletions
diff --git a/qolab/hardware/scope/__init__.py b/qolab/hardware/scope/__init__.py
index c573edf..ae311d1 100644
--- a/qolab/hardware/scope/__init__.py
+++ b/qolab/hardware/scope/__init__.py
@@ -25,16 +25,16 @@ class Scope(BasicInstrument):
# i.e. VoltsPerDiv -> getChanVoltsPerDiv(chNum) and setSampleRate(chNum, value)
self.channelProperties = ['VoltsPerDiv', 'Offset', ]
- def getTrace(self, chNum, availableNpnts=None, maxRequiredPoints=None):
+ def getTrace(self, chNum, availableNpnts=None, maxRequiredPoints=None, decimate=True):
# Should work with minimal arguments list
# but might be faster if parameters provided: less IO requests
warnings.warn( 'this function is not implemented' )
- def getAllTraces(self, availableNpnts=None, maxRequiredPoints=None):
+ def getAllTraces(self, availableNpnts=None, maxRequiredPoints=None, decimate=True):
allTraces=TraceSetSameX('scope traces')
allTraces.config['tags']['DAQ']=self.getConfig()
for chNum in range(1, self.numberOfChannels+1):
- allTraces.addTrace( self.getTrace(chNum, availableNpnts, maxRequiredPoints) )
+ allTraces.addTrace( self.getTrace(chNum, availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints, decimate=decimate) )
return( allTraces )
def plot(self, **kwargs):
@@ -63,8 +63,8 @@ class Scope(BasicInstrument):
return header
- def save(self, fname=None, item_format='e', availableNpnts=None, maxRequiredPoints=None, extention='dat'):
- allTraces = self.getAllTraces(availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints)
+ def save(self, fname=None, item_format='e', availableNpnts=None, maxRequiredPoints=None, decimate=True, extention='dat'):
+ allTraces = self.getAllTraces(availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints, decimate=decimate)
if fname is None:
fname = get_next_data_file(self.config['FnamePrefix'], self.config['SavePath'], extention=extention)
allTraces.save(fname, item_format=item_format)
diff --git a/qolab/hardware/scope/sds1104x.py b/qolab/hardware/scope/sds1104x.py
index 1b9b39e..63895f6 100644
--- a/qolab/hardware/scope/sds1104x.py
+++ b/qolab/hardware/scope/sds1104x.py
@@ -6,6 +6,7 @@ from qolab.hardware.scope import ScopeSCPI
from qolab.hardware.scpi import response2numStr
from qolab.data.trace import Trace, TraceXY
import numpy as np
+import scipy.signal
class SDS1104X(ScopeSCPI):
""" Siglent SDS1104x scope """
@@ -58,14 +59,24 @@ class SDS1104X(ScopeSCPI):
Npnts = int(np.floor(availableNpnts/sparsing))
return(sparsing, Npnts, availableNpnts, maxRequiredPoints)
- def getRawWaveform(self, chNum, availableNpnts=None, maxRequiredPoints=None):
+ def getRawWaveform(self, chNum, availableNpnts=None, maxRequiredPoints=None, decimate=True):
+ """
+ If decimate is used, we get all available points and then low-pass filter them.
+ The result is less noisy. But transfer time from the instrument is longer.
+ If decimate=False we might see aliasing, if there is a high frequency noise
+ and sparsing > 1
+ """
+
(sparsing, Npnts, availableNpnts, maxRequiredPoints) = self.calcSparsingAndNumPoints(availableNpnts, maxRequiredPoints)
- if sparsing == 1 and Npnts == availableNpnts:
+ if (sparsing == 1 and Npnts == availableNpnts) or decimate:
# we are getting all of it
cstr = f'WAVEFORM_SETUP NP,0,FP,0,SP,{sparsing}'
# technically when we know Npnts and sparsing
# we can use command from the follow up 'else' clause
else:
+ # we just ask every point with 'sparsing' interval
+ # fast to grab but we could do better with more advance decimate
+ # method, which allow better precision for the price of longer acquisition time
cstr = f'WAVEFORM_SETUP SP,{sparsing},NP,{Npnts},FP,0'
# Note: it is not enough to provide sparsing (SP),
# number of points (NP) needed to be calculated properly too!
@@ -91,7 +102,11 @@ class SDS1104X(ScopeSCPI):
# expected full reply: 'C1:WF DAT2,#9000000140.........'
trRaw = Trace(f'Ch{chNum}')
trRaw.values = wfRaw.reshape(wfRaw.size,1)
- trRaw.unit = 'count'
+ if decimate and sparsing != 1:
+ numtaps = 3; # not sure it is the best case
+ trRaw.values = scipy.signal.decimate(trRaw.values, sparsing, 3, axis=0)
+ trRaw.config['unit'] = 'Count'
+ trRaw.config['tags']['Decimate'] = decimate
return(trRaw, availableNpnts, Npnts)
def getChanVoltsPerDiv(self, chNum):
@@ -133,8 +148,11 @@ class SDS1104X(ScopeSCPI):
return(float(numberString))
- def getWaveform(self, chNum, availableNpnts=None, maxRequiredPoints=None):
- trRaw, availableNpnts, Npnts = self.getRawWaveform(chNum, availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints)
+ def getWaveform(self, chNum, availableNpnts=None, maxRequiredPoints=None, decimate=True):
+ """
+ For decimate use see getRawWaveform. In short decimate=True is slower but more precise.
+ """
+ trRaw, availableNpnts, Npnts = self.getRawWaveform(chNum, availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints, decimate=decimate)
VoltageOffset = self.getChanOffset(chNum)
VoltsPerDiv = self.getChanVoltsPerDiv(chNum)
tr = trRaw
@@ -165,8 +183,8 @@ class SDS1104X(ScopeSCPI):
t.config['tags']['Sparsing'] = sparsing
return(t)
- def getTrace(self, chNum, availableNpnts=None, maxRequiredPoints=None):
- wfVoltage, availableNpnts = self.getWaveform( chNum, availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints)
+ def getTrace(self, chNum, availableNpnts=None, maxRequiredPoints=None, decimate=True):
+ wfVoltage, availableNpnts = self.getWaveform( chNum, availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints, decimate=decimate)
t = self.getTimeTrace(availableNpnts=availableNpnts, maxRequiredPoints=maxRequiredPoints)
tr = TraceXY( f'Ch{chNum}' )
tr.x = t