Binary transfer of eye diagram data
This Python example, binary-transfer-eye.py, performs a binary transfer of an eye diagram waveform. The resulting data is shown in a matplotlib window. If you do not wish to import matplotlib library, comment out the draw_graph() function.
The main purpose of this program is to demonstrate how to return binary eye diagram data with the graph used as a visual confirmation that the data was correctly interpreted. The example works with Infiniium offline and installs simulated instruments. No hardware is required. This script imports matplotlib for the graph.
As shown in the following code, query_binary_values() method, is used to return the data.
eye_data = Infiniium.query_binary_values(message,
datatype='L',
container=list,
is_big_endian=False,
header_fmt='ieee')
As described in :WAVeform:CGRade:INTeger:DATA?, the returned data is 391,271 points (1,565,084 bytes). This array corresponds to the graticule display, where each point contains a sample hit count. The array is transferred column by column, starting with the lower left corner of the graticule.
The following picture shows an example of the displayed graph.
Example Script
waveform-cgrade-integer-data.py
#!python3
"""This program illustrates, in the Infiniium XR8
oscilloscope, the transfer of binary eye data to the PC.
The draw_graph() function shows a graph of the data in a
matplotlib GUI window. If you do not wish to import matplotlib
library, comment out this function.
"""
# Import modules.
import pyvisa
import sys
import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import EngFormatter
import platformdirs
# Global variables.
oscilloscope_visa_address = "TCPIP0::localhost::hislip0,4880::INSTR"
timeout = 60000 # 60 seconds.
# Save Locations
base_file_name = "my_cggs"
local_base_directory = f"{platformdirs.user_documents_dir()}\\"
def draw_graph(bin_data, datasize, labels, source):
"""Plots binary data and saves graphics file to show
that we received the data from Infiniium. Data is not
amplitude and time values but rather, for each database
row and column, an integer count of number of hits.
A 0 value indicates not hits for the point.
"""
print("Drawing graph.")
# Matplotlib commands:
plt.title(f"{source} Eye Diagram")
plt.ylabel("Voltage")
plt.xlabel("Time")
# For grid that is 10 divisions wide and 8 divisions tall.
plt.grid(visible=True, color="gray", linewidth=0.33, linestyle="-")
# Columns go from 0 to datasize["columns"]-1.
xtick_locations = np.linspace(0, datasize["columns"] - 1, 11, dtype=int)
plt.xticks(
xtick_locations,
[labels["xmin"], "", "", "", "", "", "", "", "", "", labels["xmax"]],
)
# Rows go from datasize["rows"]-1 to 0.
ytick_locations = np.linspace(datasize["rows"] - 1, 0, 9, dtype=int)
plt.yticks(
ytick_locations, [labels["ymin"], "", "", "", "", "", "", "", labels["ymax"]]
)
plt.imshow(bin_data.T, cmap="hot")
plt.colorbar()
svg_filename = f"{local_base_directory}{base_file_name}_{source}.svg"
plt.savefig(svg_filename)
plt.show()
plt.clf() # Clear the current figure.
print(f"Color grade data written to {svg_filename}.")
def get_binary_eye_data():
"""Returns the data points for an eye diagram by
transferring binary data to computer.
"""
print("Getting eye waveform data.")
# Waveform data set up.
Infiniium.write(":SYSTem:BORDer LENDian")
# Get the number of waveform points.
wfmpts = int(Infiniium.query(":WAVeform:CGRade:POINts?"))
print(f" Points in eye waveform: {wfmpts}")
# Get eye waveform data.
message = ":WAVeform:CGRade:INTeger:DATA?"
uint32_values = Infiniium.query_binary_values(message, datatype="L", container=list)
# Get the number of data values.
num_of_uint32_values = len(uint32_values)
print(f" Number of eye waveform data values: {num_of_uint32_values}")
return uint32_values
def get_eye_info(source):
"""Returns information about eye diagram."""
eng_s = EngFormatter(unit="s", places=1, sep=" ")
eng_V = EngFormatter(unit="V", places=1, sep=" ")
datasize = {}
labels = {}
print("Information on real-time eye:")
Infiniium.write(f":WAVeform:SOURce {source}")
# Number of data rows and columns.
datasize["columns"] = int(Infiniium.query(":WAVeform:CGRade:COLumns?"))
print(f" Number of Columns: {datasize["columns"]}")
datasize["rows"] = int(Infiniium.query(":WAVeform:CGRade:ROWS?"))
print(f" Number of Rows: {datasize["rows"]}")
# Xmin label on graph.
xmin = float(Infiniium.query(":WAVeform:CGRade:XORigin?"))
labels["xmin"] = eng_s(xmin)
print(f" X origin: {labels["xmin"]}")
# Ymin label on graph.
ymin = float(Infiniium.query(":WAVeform:CGRade:YORigin?"))
labels["ymin"] = eng_V(ymin)
print(f" Y origin: {labels["ymin"]}")
# Time spacing is delta time between columns.
timespacing = float(Infiniium.query(":WAVeform:CGRade:XINCrement?"))
print(f" Time Spacing: {eng_s(timespacing)}")
# Row spacing is delta amplitude between rows.
rowspacing = float(Infiniium.query(":WAVeform:CGRade:YINCrement?"))
print(f" Row Spacing: {eng_V(rowspacing)}")
# Calculate x and y max labels on graph.
xmax = xmin + (timespacing * datasize["columns"])
labels["xmax"] = eng_s(xmax)
ymax = ymin + (rowspacing * datasize["rows"])
labels["ymax"] = eng_V(ymax)
return datasize, labels
def exit_program():
"""Exit program."""
# Close connection to oscilloscope.
sys.stdout.write("Closing oscilloscope connection.\n")
Infiniium.write(":SYSTem:GTLocal") # Unlock GUI.
Infiniium.clear() # Clear oscilloscope communications interface.
Infiniium.close() # Close communications interface to oscilloscope.
rm.close() # Close resource manager.
print("End of program.")
sys.exit()
def check_error_queue(when):
"""Check error queue."""
errors_found = False
while True:
# Keep reading errors until "No error".
error_string = Infiniium.query(":SYSTem:ERRor:NEXT? DIAGnostic")
if error_string: # If there is an error string value.
if error_string.find("0,", 0, 2) == -1: # Not "No error".
errors_found = True
print(f"ERROR: {error_string}")
else: # "No error"
break
else: # :SYSTem:ERRor:NEXT? DIAGnostic should always return string.
errors_found = True
print("ERROR: :SYSTem:ERRor:NEXT? DIAGnostic returned nothing.")
break
if errors_found:
print(f"Exited because error(s) found when: '{when}'")
exit_program()
# ==========================================================
# Main program:
# ==========================================================
# Connect and initialize oscilloscope.
rm = pyvisa.ResourceManager("C:\\Windows\\System32\\visa64.dll")
try:
Infiniium = rm.open_resource(oscilloscope_visa_address)
except Exception:
print(
f"Unable to connect to oscilloscope at {oscilloscope_visa_address}. Aborting program."
)
sys.exit()
Infiniium.timeout = timeout # Set global timeout.
Infiniium.clear() # Clear the instrument bus.
# Lock GUI happens automatically.
# Default Setup.
print("Default Setup.")
Infiniium.write(":SYSTem:DEFault")
# # Use auto-scale to automatically set up oscilloscope.
# print("Autoscale.")
# Infiniium.query(":SYSTem:AUToscale;*OPC?")
# Stop acquisitions and clear the display.
Infiniium.write(":ACQuire:STOP")
Infiniium.write(":ACQuire:CDISplay") # Clear display.
# Turn on CHANnel1 real-time eye.
source = "CHANnel1"
eye_source = "ECHannel1"
Infiniium.query(f":{source}:EYE:DISPlay ON;*OPC?")
# Make 100 acquisitions.
Infiniium.write(":LTESt:ACQuire:CTYPe:WAVeforms 100")
Infiniium.write(":LTESt:ACQuire:STATe ON")
Infiniium.query(":ACQuire:RUN;*OPC?") # *OPC? required when limit testing.
Infiniium.write(":LTESt:ACQuire:STATe OFF")
# Get real-time eye information.
datasize, labels = get_eye_info(eye_source)
# Get real-time eye data.
uint32_values = get_binary_eye_data()
bin_data = np.array(uint32_values, dtype=np.uint32)
bin_data = np.reshape(bin_data, (datasize["columns"], datasize["rows"]))
# Plot real-time eye data received.
draw_graph(bin_data, datasize, labels, eye_source)
# Check error queue.
check_error_queue("End of program")
# Exit program.
exit_program()