diff options
author | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2024-07-16 21:52:09 -0400 |
---|---|---|
committer | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2024-07-16 21:52:09 -0400 |
commit | 2e6e889a01c19ba30010e68ad8e1ea34e7e877ab (patch) | |
tree | b712779961a0016d4b5efb93da178cc9b8eb6ad8 /qolab/hardware | |
parent | 6c7b08d9bd42be05d545d277f74029aa86ab41fe (diff) | |
download | qolab-2e6e889a01c19ba30010e68ad8e1ea34e7e877ab.tar.gz qolab-2e6e889a01c19ba30010e68ad8e1ea34e7e877ab.zip |
refactor scopes to avoid circular loads
Diffstat (limited to 'qolab/hardware')
-rw-r--r-- | qolab/hardware/scope/__init__.py | 123 | ||||
-rw-r--r-- | qolab/hardware/scope/_basic.py | 123 | ||||
-rw-r--r-- | qolab/hardware/scope/sds1104x.py | 2 |
3 files changed, 128 insertions, 120 deletions
diff --git a/qolab/hardware/scope/__init__.py b/qolab/hardware/scope/__init__.py index 2fe35da..9c9e844 100644 --- a/qolab/hardware/scope/__init__.py +++ b/qolab/hardware/scope/__init__.py @@ -1,123 +1,8 @@ """ -Provide basic class to operate scope - -Created by Eugeniy E. Mikhailov 2021/11/29 +Provide basic classes to operate scopes """ -from qolab.hardware.scpi import SCPIinstr -from qolab.hardware.basic import BasicInstrument -from qolab.data.trace import TraceSetSameX - - -class Scope(BasicInstrument): - """Minimal class to implement a scope. - - Intended to be used as a parent for hardware aware scopes. - - Provide a minimal set of methods to be implemented by a scope. - """ - - def __init__(self, *args, **kwds): - BasicInstrument.__init__(self, *args, **kwds) - self.config["Device type"] = "Scope" - self.config["Device model"] = "Generic Scope Without Hardware interface" - self.config["FnamePrefix"] = "scope" - self.numberOfChannels = 0 - # deviceProperties must have 'get' and preferably 'set' methods available, - # i.e. 'SampleRate' needs getSampleRate() and love to have setSampleRate(value) - # they will be used to obtain config and set device according to it - self.deviceProperties.update( - {"SampleRate", "TimePerDiv", "TrigDelay", "TriggerMode", "Roll", "Run"} - ) - # same is applied to channelProperties - # but we need setter/getter with channel number - # i.e. VoltsPerDiv must provide - # getChanVoltsPerDiv(chNum) and setSampleRate(chNum, value) - self.channelProperties = { - "VoltsPerDiv", - "VoltageOffset", - } - - 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 - # old_trg_mode = self.getTriggerMode() - # self.setTriggerMode('STOP'); # to get synchronous channels - raise NotImplementedError("getTrace function is not implemented") - # if old_trg_mode != "STOP": - # short speed up here with this check - # self.setTriggerMode(old_trg_mode) - - def getTriggerMode(self): - # we expect NORM, AUTO, SINGLE, STOP - raise NotImplementedError("getTriggerMode function is not implemented") - - def setTriggerMode(self, mode): - # we expect NORM, AUTO, SINGLE, STOP - raise NotImplementedError("setTriggerMode function is not implemented") - - def getAllTraces(self, availableNpnts=None, maxRequiredPoints=None, decimate=True): - allTraces = TraceSetSameX("scope traces") - allTraces.config["tags"]["DAQ"] = self.getConfig() - old_trg_mode = self.getTriggerMode() - self.setTriggerMode("STOP") - # to get synchronous channels - for chNum in range(1, self.numberOfChannels + 1): - allTraces.addTrace( - self.getTrace( - chNum, - availableNpnts=availableNpnts, - maxRequiredPoints=maxRequiredPoints, - decimate=decimate, - ) - ) - # restore scope to the before acquisition mode - if old_trg_mode != "STOP": - # short speed up here with this check - self.setTriggerMode(old_trg_mode) - return allTraces - - def plot(self, **kwargs): - allTraces = self.getAllTraces(**kwargs) - allTraces.plot() - - def save( - self, - fname=None, - item_format="e", - availableNpnts=None, - maxRequiredPoints=None, - decimate=True, - extension="dat", - ): - allTraces = self.getAllTraces( - availableNpnts=availableNpnts, - maxRequiredPoints=maxRequiredPoints, - decimate=decimate, - ) - allTraces.config["item_format"] = item_format - if fname is None: - fname = self.getNextDataFile(extension=extension) - allTraces.save(fname) - print(f"Data saved to: {fname}") - return fname - - -class ScopeSCPI(SCPIinstr, Scope): - """SCPI aware scope. - - Use as a parent for a hardware aware scope classes. - - Example - ------- - - >>> rm = pyvisa.ResourceManager() - >>> ScopeSCPI(rm.open_resource('TCPIP::192.168.0.2::INSTR')) - """ +from .sds1104x import SDS1104X # noqa: F401 unused import +from .sds2304x import SDS2304X # noqa: F401 unused import - def __init__(self, resource, *args, **kwds): - SCPIinstr.__init__(self, resource) - Scope.__init__(self, *args, **kwds) - self.config["DeviceId"] = str.strip(self.idn) +__all__ = ["SDS1104X", "SDS2304X"] diff --git a/qolab/hardware/scope/_basic.py b/qolab/hardware/scope/_basic.py new file mode 100644 index 0000000..1ceecbc --- /dev/null +++ b/qolab/hardware/scope/_basic.py @@ -0,0 +1,123 @@ +""" +Provide basic class to build an operational scope + +Created by Eugeniy E. Mikhailov 2021/11/29 +""" + +from qolab.hardware.scpi import SCPIinstr +from qolab.hardware.basic import BasicInstrument +from qolab.data.trace import TraceSetSameX + + +class Scope(BasicInstrument): + """Minimal class to implement a scope. + + Intended to be used as a parent for hardware aware scopes. + + Provide a minimal set of methods to be implemented by a scope. + """ + + def __init__(self, *args, **kwds): + BasicInstrument.__init__(self, *args, **kwds) + self.config["Device type"] = "Scope" + self.config["Device model"] = "Generic Scope Without Hardware interface" + self.config["FnamePrefix"] = "scope" + self.numberOfChannels = 0 + # deviceProperties must have 'get' and preferably 'set' methods available, + # i.e. 'SampleRate' needs getSampleRate() and love to have setSampleRate(value) + # they will be used to obtain config and set device according to it + self.deviceProperties.update( + {"SampleRate", "TimePerDiv", "TrigDelay", "TriggerMode", "Roll", "Run"} + ) + # same is applied to channelProperties + # but we need setter/getter with channel number + # i.e. VoltsPerDiv must provide + # getChanVoltsPerDiv(chNum) and setSampleRate(chNum, value) + self.channelProperties = { + "VoltsPerDiv", + "VoltageOffset", + } + + 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 + # old_trg_mode = self.getTriggerMode() + # self.setTriggerMode('STOP'); # to get synchronous channels + raise NotImplementedError("getTrace function is not implemented") + # if old_trg_mode != "STOP": + # short speed up here with this check + # self.setTriggerMode(old_trg_mode) + + def getTriggerMode(self): + # we expect NORM, AUTO, SINGLE, STOP + raise NotImplementedError("getTriggerMode function is not implemented") + + def setTriggerMode(self, mode): + # we expect NORM, AUTO, SINGLE, STOP + raise NotImplementedError("setTriggerMode function is not implemented") + + def getAllTraces(self, availableNpnts=None, maxRequiredPoints=None, decimate=True): + allTraces = TraceSetSameX("scope traces") + allTraces.config["tags"]["DAQ"] = self.getConfig() + old_trg_mode = self.getTriggerMode() + self.setTriggerMode("STOP") + # to get synchronous channels + for chNum in range(1, self.numberOfChannels + 1): + allTraces.addTrace( + self.getTrace( + chNum, + availableNpnts=availableNpnts, + maxRequiredPoints=maxRequiredPoints, + decimate=decimate, + ) + ) + # restore scope to the before acquisition mode + if old_trg_mode != "STOP": + # short speed up here with this check + self.setTriggerMode(old_trg_mode) + return allTraces + + def plot(self, **kwargs): + allTraces = self.getAllTraces(**kwargs) + allTraces.plot() + + def save( + self, + fname=None, + item_format="e", + availableNpnts=None, + maxRequiredPoints=None, + decimate=True, + extension="dat", + ): + allTraces = self.getAllTraces( + availableNpnts=availableNpnts, + maxRequiredPoints=maxRequiredPoints, + decimate=decimate, + ) + allTraces.config["item_format"] = item_format + if fname is None: + fname = self.getNextDataFile(extension=extension) + allTraces.save(fname) + print(f"Data saved to: {fname}") + return fname + + +class ScopeSCPI(SCPIinstr, Scope): + """SCPI aware scope. + + Use as a parent for a hardware aware scope classes. + + Example + ------- + + >>> rm = pyvisa.ResourceManager() + >>> ScopeSCPI(rm.open_resource('TCPIP::192.168.0.2::INSTR')) + """ + + def __init__(self, resource, *args, **kwds): + SCPIinstr.__init__(self, resource) + Scope.__init__(self, *args, **kwds) + self.config["DeviceId"] = str.strip(self.idn) diff --git a/qolab/hardware/scope/sds1104x.py b/qolab/hardware/scope/sds1104x.py index 0b9bd32..c79c591 100644 --- a/qolab/hardware/scope/sds1104x.py +++ b/qolab/hardware/scope/sds1104x.py @@ -3,7 +3,7 @@ Created by Eugeniy E. Mikhailov 2021/11/29 """ from qolab.hardware.basic import BasicInstrument -from qolab.hardware.scope import ScopeSCPI +from ._basic import ScopeSCPI from qolab.hardware.scpi import response2numStr from qolab.data.trace import Trace, TraceXY import numpy as np |