# Save Eye Measurement Results to an HTML File

This Python example, measure-eye-results-to-html.py, returns the values shown on Infiniium's Results table and creates an HTML topic that contains the results. You can open this file in your web browser or import the HTML file into Microsoft Excel. The file is saved in the script's folder. The script uses the `:MEASure:RESults?` query to return the values.

## Example Script

measure-eye-results-to-html.py

    #!python3

    """This program makes several eye measurements and outputs the
    results to a table in an HTML file. This program:
        1. Uses :MEASure:RESults? to return all measurement results.
        2. Creates an HTML topic that contains the results.
        3. Places html topic in the script's folder.
        4. You can open and view the HTML topic in a web browser or import the
           topic into Microsoft Excel.
    """

    # Import modules.
    import pyvisa
    import sys
    from matplotlib.ticker import EngFormatter
    import pandas as pd

    # Global variables.
    oscilloscope_visa_address = "TCPIP0::localhost::hislip0,4880::INSTR"
    timeout = 60000  # 60 seconds.
    eng_s = EngFormatter(unit="s", places=3, sep=" ")
    eng_V = EngFormatter(unit="V", places=3, sep=" ")
    eng_bps = EngFormatter(unit="b/s", places=3, sep=" ")
    meas_fmttr_dict = {
        "Eye Rise Time": eng_s,
        "Eye Fall Time": eng_s,
        "One Level": eng_V,
        "Zero Level": eng_V,
        "Eye Width[Sec Data]": eng_s,
        "Eye Height[Data]": eng_V,
        "Eye Ampl": eng_V,
        "Bit Rate": eng_bps,
        "DCD[Time]": eng_s,
        "Crossing Time": eng_s,
    }
    html_out_file = "Eye_measurements.html"

    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."""

        num_errors = int(Infiniium.query(":SYSTem:ERRor:COUNt?"))
        if num_errors:
            for _ in range(num_errors):
                error_string = Infiniium.query(":SYSTem:ERRor:NEXT? DIAGnostic").strip()
                print(f"ERROR: {error_string}")

            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?")

    # Turn on eye measurements.
    eye_measurements = [
        "RTIMe",
        "FTIMe",
        "OLEVel",
        "ZLEVel",
        "EWIDth",
        "EHEight",
        "AMPlitude",
        "BITRate",
        "DCDistortion",
        "ECTime",
    ]
    for eye_meas in eye_measurements:
        Infiniium.write(f":MEASure:EYE:{eye_meas}:SOURce {eye_source}")
        if eye_meas == "EWIDth":
            Infiniium.write(":MEASure:EYE:EWIDth:FORMat SECond")
            Infiniium.write(":MEASure:EYE:EWIDth:THReshold AUTomatic")
            Infiniium.write(":MEASure:EYE:EWIDth:ALGorithm MDATa")
        elif eye_meas == "EHEight":
            Infiniium.write(":MEASure:EYE:EHEight:ALGorithm MDATa")
        elif eye_meas == "DCDistortion":
            Infiniium.write(":MEASure:EYE:DCDistortion:FORMat TIME")
        Infiniium.write(f":MEASure:EYE:{eye_meas}")

    # 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")

    # Read results into a pandas DataFrame from a list of dicts
    # for each measurement.
    list_of_dicts = []
    results = (
        Infiniium.query(":MEASure:RESults? STANdard").strip().replace(",Name", "\nName")
    )
    meas_list = results.split("\n")
    for meas in meas_list:
        meas_dict = {}
        name_val_list = meas.split(",")
        for name_val in name_val_list:
            (name, value) = name_val.split("=")
            if name == "Name":
                if value in meas_fmttr_dict:
                    fmttr = meas_fmttr_dict[value]
            if name in ["Current", "Mean", "StdDev", "Min", "Max"]:
                meas_dict[name] = fmttr(float(value))
            else:
                meas_dict[name] = value
        list_of_dicts.append(meas_dict)
    meas_df = pd.DataFrame(list_of_dicts)

    # Output DataFrame to HTML file.
    html_table = meas_df.to_html(index=False, border=1)
    with open(html_out_file, "w", encoding="utf-8") as f:
        f.write(html_table)
    print(f"HTML table saved to: {html_out_file}")

    # Check error queue.
    check_error_queue("End of program")

    # Exit program.
    exit_program()