Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changes/newsfragments/7865.improved_driver
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add convenience methods to Tektronix DPO7200xx (``single``, ``download_waveforms``, ``get_timebase``) and AWG70000A (``upload_seqx``) drivers for streamlined waveform acquisition and sequence upload workflows.
4 changes: 2 additions & 2 deletions docs/examples/basic_examples/Station.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -621,14 +621,14 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import sys\n",
"\n",
"from qcodes.utils.installation import register_station_schema_with_vscode\n",
"from qcodes.extensions import register_station_schema_with_vscode\n",
"\n",
"# if statement for CI only\n",
"if sys.platform == \"win32\" and os.path.exists(\n",
Expand Down
26 changes: 26 additions & 0 deletions src/qcodes/instrument_drivers/tektronix/AWG70000A.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,32 @@ def stop(self) -> None:
"""
self.write("AWGControl:STOP")

def upload_seqx(self, seqx_input, sequence_name="seq") -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def upload_seqx(self, seqx_input, sequence_name="seq") -> None:
def upload_seqx(self, seqx_input: notsurewhatthetypeisherepleascheck, sequence_name: str ="seq") -> None:

"""
A convenience function to upload a sequence to the instrument's memory and add it to the
sequence list. Enable outputs and put awg in play mode.

Args:
seqx_input: The input needed to make a seqx file, preferably the
output of makeSEQXFileInput.
sequence_name: The name of the sequence (as it appears in the sequence list, not the file name).
If a sequence with the same name already exists, it will be overwritten.

"""

seqx = self.makeSEQXFile(*seqx_input)
self.sendSEQXFile(seqx, sequence_name + ".seqx")
# Load the sequence file from local AWG storage to playback memory
self.loadSEQXFile(sequence_name + ".seqx")
self.ch1.setSequenceTrack(sequence_name, 1)
self.ch2.setSequenceTrack(sequence_name, 2)
# Turn on outputs and play
self.ch1.state(1) # Enable channel 1 output
self.ch2.state(1) # Enable channel 2 output
# Make sure all output is on (in case it was turned off globally)
self.all_output_off(0)
self.play()

@property
def sequenceList(self) -> list[str]:
"""
Expand Down
58 changes: 58 additions & 0 deletions src/qcodes/instrument_drivers/tektronix/DPO7200xx.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,64 @@ def ask_raw(self, cmd: str) -> str:
self.visa_log.debug(f"Response: {response}")
return response

def single(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def single(self):
def single(self) -> None:

"""
Set scope into single acquisition mode and wait for triggered acquisition
"""
self.acquisition.stop_after("SEQUENCE")
self.acquisition.state("RUN")
timeout_val = self.timeout()
timeout = timeout_val if timeout_val is not None else 10.0
start_time = time.time()
while True:
acq_state = self.acquisition.state().strip()
trigger_state = self.trigger.ready().strip()
# logger.info(f"Trigger: {trigger_state}, Acquisition: {acq_state}")
if (acq_state == "1") and (trigger_state == "1"):
break

if time.time() - start_time > timeout:
break
time.sleep(0.1)

def download_waveforms(self) -> tuple:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def download_waveforms(self) -> tuple:
def download_waveforms(self) -> tuple[np.ndarray, ..,]:

If I understand correctly the tuple contains numpy arrays

"""
Wait for acquisition of a triggered waveform to complete and then
download acquired waveforms from the enabled channels the Tektronix scope.
"""
timeout_val = self.timeout()
timeout = timeout_val if timeout_val is not None else 60.0
start_time = time.time()
while True:
acq_state = self.acquisition.state().strip()
if acq_state == "0":
break
if time.time() - start_time > timeout:
break
time.sleep(0.1)

# Only download waveforms from enabled channels
wfms = ()
for ch in self.channel:
if self.ask(f"SELect:{ch._identifier}?").strip() == "1":
ch.set_trace_length(self.horizontal.record_length())
wfms += (
ch.waveform.trace(),
) # This will trigger the actual download of the waveform
return wfms

def get_timebase(self) -> tuple:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def get_timebase(self) -> tuple:
def get_timebase(self) -> tuple[str,np.ndarray]:

"""
Get the timebase of the scope in seconds per division

Returns:
Tuple of time unit (str) and time axis values (np.ndarray)

"""
time_unit = self.channel[0].waveform.trace_axis
time_axis = self.channel[0].waveform.trace_axis()
return time_unit.unit, time_axis


class TektronixDPOData(InstrumentChannel):
"""
Expand Down
Loading