Skip to content

Commit

Permalink
Merge pull request #300 from simonzihlmann/feat_Tektronix_FCA3110
Browse files Browse the repository at this point in the history
Tektronix FCA3100 counter driver
  • Loading branch information
astafan8 authored Mar 4, 2024
2 parents b372037 + bca31e9 commit 92bda46
Show file tree
Hide file tree
Showing 2 changed files with 333 additions and 0 deletions.
151 changes: 151 additions & 0 deletions docs/examples/Tektronix_FCA3100.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from qcodes_contrib_drivers.drivers.Tektronix.FCA3100 import FCA3100"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Connected to: TEKTRONIX FCA3000 (serial:579249, firmware:V1.32 26 May 2022 09:54) in 0.13s\n"
]
}
],
"source": [
"counter = FCA3100('counter', 'USB0::0x0699::0x3000::579249::INSTR', timeout=10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# overview over all parameters"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"counter:\n",
"\tparameter value\n",
"--------------------------------------------------------------------------------\n",
"IDN :\t{'vendor': 'TEKTRONIX', 'model': 'FCA3000', 'serial': '57924...\n",
"counter_axis :\t[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.] (#)\n",
"samples_number :\t11 \n",
"threshold_A :\t0 (V)\n",
"threshold_B :\t0.036 (V)\n",
"time_array :\tNot available (s)\n",
"timeout :\t10 (s)\n",
"timestats :\tNot available (('s', 's', 's', 's'))\n"
]
}
],
"source": [
"counter.print_readable_snapshot(update=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Usage of the two main parameters"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's get an example of the time statistics parameter (will return mean, stdev, min and max of a statistics containing samples_number number of samples)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(0.01862650541, 7.4022264e-05, 0.01851450451, 0.01873824896)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"counter.timestats()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's get an example of the time array parameter (will return an array of timestamps of length samples_number)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.01856394, 0.01875304, 0.01868165, 0.01846251, 0.01853304,\n",
" 0.01867947, 0.01863655, 0.0185761 , 0.01863821, 0.01867253,\n",
" 0.01866243])"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"counter.time_array()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
},
"nbsphinx": {
"execute": "never"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
182 changes: 182 additions & 0 deletions src/qcodes_contrib_drivers/drivers/Tektronix/FCA3100.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import logging
import numpy as np
from typing import Any, Tuple
from qcodes.instrument import VisaInstrument
from qcodes.parameters import MultiParameter, Parameter, ParameterWithSetpoints
from qcodes.validators import Arrays, Ints

log = logging.getLogger(__name__)

class TimeStatistics(MultiParameter):
"""
Returns the statistical values of a timing statistics.
"""
def __init__(self,
name:str,
instrument:"FCA3100",
**kwargs: Any
) -> None:
"""
Statistical values of a timing statistics.
Args:
name: name of the timing statistics
instrument: Instrument to which the timing statistic is bound to.
"""

super().__init__(name=name,
instrument=instrument,
names=(
f"{instrument.short_name}_{name}_mean",
f"{instrument.short_name}_{name}_stddev",
f"{instrument.short_name}_{name}_minval",
f"{instrument.short_name}_{name}_maxval"),
shapes=((), (),(),()),
labels=(
f"{instrument.short_name} {name} mean time",
f"{instrument.short_name} {name} standard deviation",
f"{instrument.short_name} {name} min value",
f"{instrument.short_name} {name} max value"),
units=('s', 's', 's', 's'),
setpoints=((), (), (), ()),
**kwargs)

def get_raw(self) -> Tuple[float, float, float, float]:
"""
Gets data from the instrument
Returns:
Tuple: Statistical values of the time statistic
"""
assert isinstance(self.instrument, FCA3100)
self.instrument.write('CALCulate:AVERage:STAT 1')
self.instrument.write('INIT') # start measurement
self.instrument.ask('*OPC?') # wait for it to complete
reply = self.instrument.ask("CALCulate:AVERage:ALL?")
mean, stddev, minval, maxval, _ = reply.split(",")

return float(mean), float(stddev), float(minval), float(maxval)

class CompleteTimeStatistics(ParameterWithSetpoints):
def __init__(self,
name:str,
instrument:"FCA3100",
**kwargs: Any
) -> None:
"""
Parameter for a complete time statistics containing all measured switching times.
Args:
name: name of the complete time statistics
instrument: Instrument to which the complete time statistic is bound to.
"""
super().__init__(name=name,
instrument=instrument,
label='Times till switching',
unit='s',
docstring='Arrays of switching times',
**kwargs)

def get_raw(self) -> np.ndarray:
"""
Gets the data from the instrument.
Returns:
np.ndarray: Array of swithing times
"""
assert isinstance(self.instrument, FCA3100)
self.instrument.write('CALCulate:AVERage:STATe 0')
self.instrument.write('ARM:COUN {}'.format(self.instrument.samples_number.get_latest()))
data_str=self.instrument.ask("READ:ARRay? {}".format(self.instrument.samples_number.get_latest()))
data = np.array(data_str.rstrip().split(",")).astype("float64")
return data

class GeneratedSetPoints(Parameter):
"""
A parameter that generates a setpoint array from start, stop and num points
parameters.
"""
def __init__(self, numpointsparam, *args, **kwargs):
super().__init__(*args, **kwargs)
self._numpointsparam = numpointsparam

def get_raw(self):
return np.arange(self._numpointsparam())


class FCA3100(VisaInstrument):
"""
This is the qcodes driver for the FCA3100 counter
"""

def __init__(self,
name: str,
address: str,
terminator : str="\n",
timeout : int=10,
**kwargs) -> None:
"""
Qcodes driver for the Textronix FCA3100 frequency counter.
Args:
name: Name of the instrument
address: Address of the instrument
terminator (optional): Terminator character of
the string reply. Defaults to "\\n".
timeout (optional): VISA timeout is set purposely
to a long time to allow long measurements. Defaults to 10.
"""

super().__init__(name = name,
address = address,
terminator = terminator,
timeout = timeout,
device_clear = False,
**kwargs)

self.write('INIT:CONT 0')

self.add_parameter(name='timestats',
parameter_class=TimeStatistics)

self.add_parameter(name='samples_number',
label='samples_number',
get_cmd='CALCulate:AVERage:COUNt?',
set_cmd='CALCulate:AVERage:COUNt {}',
get_parser=float,
vals=Ints(2, int(2e9)),
docstring='Number of samples in the current statistics sampling'
)

self.add_parameter('counter_axis',
unit='#',
label='Counter Axis',
parameter_class=GeneratedSetPoints,
numpointsparam=self.samples_number,
vals=Arrays(shape=(self.samples_number.get_latest,)))

self.add_parameter(name='threshold_A',
label='threshold_A',
get_cmd='INPut1:LEVel?',
set_cmd='INPut1:LEVel {}',
get_parser=float,
unit='V',
docstring='Absolute voltage trigger threshold channel A'
)

self.add_parameter(name='threshold_B',
label='threshold_B',
get_cmd='INPut2:LEVel?',
set_cmd='INPut2:LEVel {}',
get_parser=float,
unit='V',
docstring='Absolute voltage trigger threshold channel B'
)

self.add_parameter(name='time_array',
parameter_class=CompleteTimeStatistics,
setpoints=(self.counter_axis,),
vals=Arrays(shape=(self.samples_number.get_latest,))
)

self.connect_message()

0 comments on commit 92bda46

Please sign in to comment.