Back

Laser Delay Control Program

This program controls laser delay lines using PyVISA to interface with SDG2000x and DG535 delay generators. It provides functionality for setting parameters, saving/loading profiles, and automated/manual data collection.

import numpy as np
import json
import os
import pyvisa
rm = pyvisa.ResourceManager()

class LaserDelayControl:
    def __init__(self):
        self.max_delay_SDG = None
        self.min_delay = None
        self.num_photos_per_cycle = None
        self.delay_increment = None

    def push_SDG2000x_delay(self,channel,delay):
        sdg = rm.open_resource('USB0::0xF4EC::0xEE38::SDG2XCAC1R0015::INSTR')
        sdg.write(f"C{channel}:BSWV DLY,{delay}")
        print(f'successfully pushed delay of {delay} to SDG2000x.')
        print()
        return
    
    def push_DG535_delay(target_channel,reference_channel,delay):
        dg535 = rm.open_resource("GPIB0::GPIB_ADDRESS::INSTR")
        dg535.write(f'DT {target_channel},{reference_channel},{delay}')
        print(f'successfully pushed delay of {delay} to DG535.')
        print()
        return
    
    def set_parameters(self):
        self.num_photos_per_cycle = self.get_int_input("Enter desired number of photos per cycle:")
        self.delay_increment = self.get_int_input("Enter desired delay increment:")
        self.min_delay = self.get_int_input("Enter desired minimum delay:")
        self.max_delay_SDG = self.get_int_input("Enter desired starting delay for SDG2000x:")
        print('-'*50, "PARAMETERS SUCCESSFULLY INITIALIZED", '-'*50)
        self.print_current_parameters()
        return self.max_delay_SDG, self.min_delay, self.num_photos_per_cycle, self.delay_increment
    
    def get_int_input(self, prompt):
        while True:
            try:
                return int(input(prompt))
            except ValueError:
                print(self.error_msg)
                print()

    def begin_data_collection(self):
        sdg = rm.open_resource('USB0::0xF4EC::0xEE38::SDG2XCAC1R0015::INSTR')
        dg535 = rm.open_resource("GPIB0::GPIB_ADDRESS::INSTR")
        rm = pyvisa.ResourceManager()
        if not all([self.max_delay_SDG, self.min_delay, self.num_photos_per_cycle, self.delay_increment]):
            print("Error: Try again after you've set the parameters or loaded one of the profiles.")
            return 

        delay_array = np.linspace(self.min_delay, self.max_delay_SDG, self.delay_increment)
        delay_difference = 10
        total_photos = int(len(delay_array))
        current_delay = self.max_delay_SDG
        is_automatic = input("automatic data collection? (y/n):")
        if is_automatic == 'y':
            while current_delay > self.min_delay:
                current_delay = current_delay - self.delay_increment
                self.push_SDG2000x_delay(1, current_delay)
                self.push_DG535_delay(2,3,current_delay + delay_difference)
        else:
            while current_delay > self.min_delay:
                go_next = input("input anything to continue to next shot. Type 'exit' to terminate program.")
                if go_next == "exit":
                    return
                else:
                    current_delay = current_delay - self.delay_increment
                    self.push_SDG2000x_delay(1, current_delay)
                    self.push_DG535_delay(2,3,current_delay + np.abs(delay_difference))
   
        sdg.close()
        dg535.close()
        print("Data Collection Complete!")
        return

    def save_profile(self):
        if not all([self.max_delay_SDG, self.min_delay, self.num_photos_per_cycle, self.delay_increment]):
            print("Error: Try again after you've set the parameters or loaded one of the profiles.")
            return

        self.print_current_parameters()
        
        while True:
            yn = input("Save This Profile? (y/n): ").lower()
            if yn in ['y', 'yes', 'n', 'no']:
                break
            print("Invalid Input. Please enter 'y' or 'n'.")
        
        if yn in ['y', 'yes']:
            profile_name = input("Enter desired profile name: ")
            profile_data = {
                "name": profile_name,
                "data": [self.max_delay_SDG, self.min_delay, self.num_photos_per_cycle, self.delay_increment]
            }
            
            with open('profiles.txt', 'a') as file:
                file.write(json.dumps(profile_data) + '\n')
            
            print('-'*50)
            print(f'PROFILE "{profile_name}" SUCCESSFULLY SAVED')
            print('-'*50)
        else:
            print('-'*50)
            print("SAVE PROFILE OPERATION CANCELLED")
            print('-'*50)

    def load_profile(self):
        try:
            with open('profiles.txt', 'r') as file:
                lines = file.readlines()
            
            print("PROFILES:")
            for index, line in enumerate(lines):
                profile = json.loads(line.strip())
                print(f"{index}: {profile['name']} - {profile['data']}")
            
            while True:
                try:
                    which_profile = int(input("Select Profile to Load (enter index): "))
                    if 0 <= which_profile < len(lines):
                        break
                    else:
                        print("Invalid index. Please try again.")
                except ValueError:
                    print("Please enter a valid number.")
            
            selected_profile = json.loads(lines[which_profile].strip())
            self.max_delay_SDG, self.min_delay, self.num_photos_per_cycle, self.delay_increment = selected_profile['data']
            
            print(f"Loaded profile: {selected_profile['name']}")
            self.print_current_parameters()
            
        except FileNotFoundError:
            print("profiles.txt file not found.")
        except json.JSONDecodeError:
            print("Error decoding JSON from the file. Make sure the file is properly formatted.")

    def print_current_parameters(self):
        print("Current Parameters:")
        print(f"Initial Delay of SDG2000x: {self.max_delay_SDG}")
        print(f"Minimum Delay of SDG2000x: {self.min_delay}")
        print(f"Number of Photos Per Cycle: {self.num_photos_per_cycle}")
        print(f"Delay Increment: {self.delay_increment}")
        print()

    def run(self):
        self.error_msg = "Error: Please Try Again"

        print("Welcome to the laser delay-line control program!")
        print("Please follow the directions below.")
        print()

        while True:
            print('-'*50, "MAIN MENU", '-'*50)
            print("(1) SET PARAMETERS")
            print("(2) BEGIN DATA COLLECTION")
            print("(3) SAVE PROFILE")
            print("(4) LOAD PROFILE")
            print("(5) PRINT CURRENT PARAMETERS")
            print("(6) EXIT")

            token = self.get_int_input("Enter Token:")
            
            if token == 1:
                self.set_parameters()
            elif token == 2:
                self.begin_data_collection()
            elif token == 3:
                self.save_profile()
            elif token == 4:
                self.load_profile()
            elif token == 5:
                self.print_current_parameters()
            elif token == 6:
                print("Exiting program")
                break
            else:
                print("Invalid token. Please try again.")

begin_script = LaserDelayControl()
begin_script.run()

Documentation (HTML) formatted with assistance from Anthropic's Claude, an LLM