Example 4. Identify Measurement Dictionary
This example shows that the dependent measurement's name, "ΔT[+1Mid,-1Mid]", is used as the dictionary key for the measurement results dictionary:
measList = variables['MeasData'] # get list of meas dictionaries
for measDict in measList: # Loop thru list of dictionaries
if 'ΔT[+1Mid,-1Mid]' in measDict['Name']:
do_something()
This example also shows that the xml file's <Dependent>
element is not required, but is recommended. If this element is present and the measurement is not currently running, FlexDCA attempts to run the measurement before the user measurement script runs. If the measurement fails to start, an error occurs . Since the DeltaTime-setup.py script starts the measurement for us, the script will still run.
This script also shows that you can define additional functions in your user measurement scripts.
This script simply returns the results of the "ΔT[+1Mid,-1Mid]" measurement and does not perform its own custom user measurement.
After you've been successful with this example, run Example 5. A User Measurement which demonstrate a complete user measurement!
Required Files
DeltaTime-setup.py
This script configures FlexDCA to the state required for the example script. The script installs a simulated module, selects the proper FlexDCA mode, and turns on a delta time measurement.
DeltaTime-setup.py
import pyvisa as visa # import VISA library
visa_address = 'TCPIP0::localhost::hislip0,4880::INSTR'
CHANNEL = '1A'
TIMEOUT = 10000
def open_flexdca_connection(address):
""" Opens visa connection to FlexFlexDCA. """
print('Connecting to Flexdca ...')
try:
rm = visa.ResourceManager()
connection = rm.open_resource(address)
connection.timeout = TIMEOUT # Set connection timeout to 20s
connection.read_termination = '\n'
connection.write_termination = '\n'
inst_id = connection.query('*IDN?')
print('\nFlexDCA connection established to:\n' + inst_id, flush=True)
connection.write(':SYSTem:DEFault')
connection.query('*OPC?')
except (visa.VisaIOError, visa.InvalidSession):
print('\nVISA ERROR: Cannot open instrument address.\n', flush=True)
return None
except Exception as other:
print('\nVISA ERROR: Cannot connect to instrument:', other, flush=True)
print('\n')
return None
return connection
def all_channels_off(FlexDCA):
""" Turns all available channels off. """
for slot in '12345678':
for letter in 'ABCD':
channel = slot + letter
FlexDCA.write(':CHANnel' + channel + ':DISPlay OFF')
def install_simulated_module(FlexDCA, channel, model, signal='NRZ'):
""" Simplified installation of a simulated FlexDCA module.
model
Type of simulated module. "DEM" is a dual-electrical module.
"QEM" is a quad-electrical module. "DOM" is a dual-optical
module. "QEM" is a electrical-optical module.
signal
Format of signal. NRZ or PAM4.
"""
slot = channel[0]
FlexDCA.write(':EMODules:SLOT' + slot + ':SELection ' + model)
if signal in 'NRZ':
FlexDCA.write(':SOURce' + channel + ':FORMat NRZ')
else:
FlexDCA.write(':SOURce' + channel + ':FORMat PAM4')
FlexDCA.write(':SOURce' + channel + ':DRATe 9.95328E+9')
FlexDCA.write(':SOURce' + channel + ':WTYPe DATA')
FlexDCA.write(':SOURce' + channel + ':PLENgth 127')
FlexDCA.write(':SOURce' + channel + ':AMPLitude 90E-3')
FlexDCA.write(':SOURce' + channel + ':NOISe:RN 3.0E-6')
FlexDCA.write(':SOURce' + channel + ':JITTer:RJ 4.0E-12')
FlexDCA.write(':CHANnel' + channel + ':DISPlay ON')
def return_scalar(FlexDCA, query):
""" Returns a FlexDCA scalar measurement result. """
import time
class ScalarMeasQuestionableException(Exception):
""" A scalar measurement result is questionable. """
pass
class ScalarMeasTimeOutException(Exception):
""" A scalar measurement has timed out. """
pass
timeout = FlexDCA.timeout / 1000 # convert ms to s
query = query.strip('?')
start_time = time.time() # time in seconds
while(True):
time.sleep(0.2)
status = FlexDCA.query(query + ':STATus?')
if 'CORR' in status: # valid measurement result
return FlexDCA.query(query + '?') # get measurement
elif 'QUES' in status: # questionable results
s = query + '\nReason: ' + FlexDCA.query(query + ':STATus:REASon?')
raise ScalarMeasQuestionableException(s)
elif (int(time.time() - start_time)) > timeout: # IO timout
s = query + '\nReason: ' + FlexDCA.query(query + ':STATus:REASon?')
raise ScalarMeasTimeOutException(s)
flexdca = open_flexdca_connection(visa_address)
flexdca.query(':SYSTem:DEFault;*OPC?')
all_channels_off(flexdca)
install_simulated_module(flexdca, CHANNEL, 'DEM')
flexdca.write(':ACQuire:RUN')
flexdca.query(':SYSTem:MODE OSCilloscope;*OPC?') # Switch to Eye/Mask mode
flexdca.query(':TRIGger:PLOCk ON;*OPC?')
flexdca.write(':TIMebase:SCALe 2.0000E-10')
flexdca.query(':SYSTEM:AUToscale;*OPC?')
flexdca.write(':ACQuire:SMOothing AVERage')
flexdca.write(':MEASure:OSCilloscope:DELTatime:ENUMber2 1')
flexdca.write(':MEASure:OSCilloscope:DELTatime:EDIRection1 RISing')
flexdca.write(':MEASure:OSCilloscope:DELTatime:EDIRection2 FALLing')
flexdca.write(':MEASure:OSCilloscope:DELTatime:ETHReshold1 MIDDle')
flexdca.write(':MEASure:OSCilloscope:DELTatime:ETHReshold2 MIDDle')
flexdca.write(':MEASure:OSCilloscope:DELTatime')
flexdca.write(':MEASure:OSCilloscope:DELTatime')
meas = return_scalar(flexdca, ':MEASure:OSCilloscope:DELTatime?')
flexdca.write(':SYSTem:GTLocal')
flexdca.close()
DeltaTime.xml
Installs user measurement.
DeltaTime.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- DeltaTimeTest.xml -->
<Measurement>
<Name>Delta T Modified</Name>
<Abbreviation>DT+</Abbreviation>
<Comments>In Scope mode, modified delta time measurement.</Comments>
<Script>DeltaTime.py</Script>
<MeasurementType>1 Source</MeasurementType>
<ValidMode>Scope</ValidMode>
</Measurement>
DeltaTime.py
User measurement script. Notice that this script includes a handy print_to_show_window()
function that increases the reliability of writing to the Show Output window. This function replaces Unicode characters, which cause an error, with the equivalent XML character entity. For example, the Δ symbol in the name of the "Δ Time" measurement is replaced with the entity string.
DeltaTime.py
def algorithm(variables):
# Initialize the four variables that are returned to FlexDCA.
Result = 0.0
Units = 's'
ErrorMsg = ''
Status = 'Invalid'
# Initialize local function variables with variables from FlexDCA.
measList = variables['MeasData'] # get list of meas dictionaries
# Find measurement results in MeasData:
for measDict in measList: # Loop thru list of dictionaries
if 'ΔT[+1Mid,-1Mid]' in measDict['Name'] and 'Correct' in measDict['Status']:
print_to_show_window('\nDependent measurement found and is correct!')
print_to_show_window('\tMeasurement name: ' + measDict['Name'])
Status = 'Correct'
Result = measDict['Result']
break
else:
print_to_show_window('Measurement is missing or incorrect!')
Status = 'Invalid'
ErrorMsg += ' ΔT input measurement is not correct.'
if ErrorMsg:
s = 'ErrorMsg: ' + ErrorMsg
print_to_show_window(s)
if 'Invalid' in ErrorMsg:
return { 'Result': Result,
'Status': Status,
'ErrorMsg': ErrorMsg
}
else:
Result = perform_measurement(Result)
s = 'Result: ' + str(Result)
print_to_show_window(s)
s = 'Status: ' + measDict['Status']
print_to_show_window(s)
return { 'Result': Result,
'Units': Units,
'Resolution': 0.01e-15,
'ValueFormat': 'Engineering',
'Status': measDict['Status']
}
def perform_measurement(measurement):
measurement *= 1.5
return measurement
def print_to_show_window(message):
""" FlexDCA's Show Output window for user measurements and operators
causes a error if a Unicode character is in the printed string.
Removes all Unicode characters. It also removes any '\n' and '\t'
characters.
"""
message = message.replace('\n', '1banana')
message = message.replace('\t', '2squirrels')
asciiString = message.encode('ascii', 'xmlcharrefreplace')
cleanMessage = asciiString.decode('utf-8')
cleanMessage = cleanMessage.replace('1banana', '\n')
cleanMessage = cleanMessage.replace('2squirrels', '\t')
print(cleanMessage)