aboutsummaryrefslogtreecommitdiff
path: root/qolab/hardware/scope
diff options
context:
space:
mode:
authorEugeniy E. Mikhailov <evgmik@gmail.com>2024-07-16 21:52:09 -0400
committerEugeniy E. Mikhailov <evgmik@gmail.com>2024-07-16 21:52:09 -0400
commit2e6e889a01c19ba30010e68ad8e1ea34e7e877ab (patch)
treeb712779961a0016d4b5efb93da178cc9b8eb6ad8 /qolab/hardware/scope
parent6c7b08d9bd42be05d545d277f74029aa86ab41fe (diff)
downloadqolab-2e6e889a01c19ba30010e68ad8e1ea34e7e877ab.tar.gz
qolab-2e6e889a01c19ba30010e68ad8e1ea34e7e877ab.zip
refactor scopes to avoid circular loads
Diffstat (limited to 'qolab/hardware/scope')
-rw-r--r--qolab/hardware/scope/__init__.py123
-rw-r--r--qolab/hardware/scope/_basic.py123
-rw-r--r--qolab/hardware/scope/sds1104x.py2
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