From 54a2948d0b49f7f839bf0ae379344aa5a9e0e59b Mon Sep 17 00:00:00 2001 From: rtan Date: Wed, 28 Aug 2024 12:53:28 +0200 Subject: [PATCH] progreess on b_field_rotation; TODO: finish the tail end of the func, copy from b_val_sweep --- 20240709SerdarModScript.py | 112 +++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 28 deletions(-) diff --git a/20240709SerdarModScript.py b/20240709SerdarModScript.py index ce8f9e7..935f1e5 100644 --- a/20240709SerdarModScript.py +++ b/20240709SerdarModScript.py @@ -8,7 +8,7 @@ Lightfield + Positioner # Packages from Ryan import re import math -from threading import Thread +import threading import pyvisa # from pyvisa import ResourceManager, constants @@ -672,9 +672,6 @@ def b_field_rotation(instr1:pyvisa.resources.Resource, instr2:pyvisa.resources.R clockwise (bool): determines the direction of rotation of the B-field. Defaults to True. sweepdown (bool, optional): after finishing the rotation, both B-field components should be set to 0 T. Defaults to False. """ - - def wait_for_b_val_helper_func(instr,): - pass if path_save =='': path_save = datetime.datetime.now().strftime("%Y_%m_%d_%H%M_hrs_") # TODO: add path_save, base_file_name in the function header @@ -702,7 +699,9 @@ def b_field_rotation(instr1:pyvisa.resources.Resource, instr2:pyvisa.resources.R # initialise the sweep angle list as well as the sweep limits and directions for each instrument instr1_lim, instr2_lim = 'LLIM', 'ULIM' instr1_sweep, instr2_sweep = 'DOWN', 'UP' - angles, cartesian_coords = polar_to_cartesian(Babs, startangle, endangle, angle_stepsize, clockwise=clockwise) # create lists of angles and discrete Cartesian coordinates + + # create lists of angles and discrete Cartesian coordinates + angles, cartesian_coords = polar_to_cartesian(Babs, startangle, endangle, angle_stepsize, clockwise=clockwise) if clockwise: # NOTE: old conditional was: startangle > endangle see if this works.... # reverse sweep limits and directions for the clockwise rotation @@ -733,29 +732,86 @@ def b_field_rotation(instr1:pyvisa.resources.Resource, instr2:pyvisa.resources.R # TODO: begin the rotation of the B-field, saving the spectrum for each angle, including the start- and end angles # NOTE: implement PID control, possibly best option to manage the b field DO THIS LATER ON, WE DO DISCRETE B VALUES RN - # bug fix for polar_to_cartesian (27.08.2024, 15:52 hrs) - # TODO: write the for loop for the rotation here, implement threading => create a helper function to enter into the threads - for idx, angle in enumerate(angles): - pass - # # we acquire with the LF - # acquire_name_spe = f'{base_file_name}_{bval}T' - # AcquireAndLock(acquire_name_spe) #this creates a .spe file with the scan name. - - # # read the .spe file and get the data as loaded_files - # cwd = os.getcwd() # save original directory - # os.chdir(path_save) #change directory - # loaded_files = sl.load_from_files([acquire_name_spe + '.spe']) # get the .spe file as a variable - # os.chdir(cwd) # go back to original directory - - # # Delete the created .spe file from acquiring after getting necessary info - # spe_file_path = os.path.join(path_save, acquire_name_spe + '.spe') - # os.remove(spe_file_path) - - # points_left = total_points - i - 1 # TODO: SEE IF THIS IS CORRECT - # print('Points left in the scan: ', points_left) - - # #append the intensity data as it is (so after every #of_wl_points, the spectrum of the next point begins) - # intensity_data.append(loaded_files.data[0][0][0]) + # TODO: define the helper functions for threading here, write the commented code inside this function and call the function below + the other + # functionalities in b_val_sweep later on.... + # SEE ThreadTest2.py for the helper functions + # Helper function that listens to a device + def listen_to_device(device_id, target_value, shared_values, lock, all_targets_met_event): + while not all_targets_met_event.is_set(): # Loop until the event is set + # value = 0 # Simulate receiving a float from the device INSERT QUERY NO ECHO HERE TO ASK FOR DEVICE IMAG + if '2301034' in device_id: + value = sep_num_from_units(query_no_echo(instr1, 'IMAG?'))[0]*0.1 # convert kG to T + elif '2101014' in device_id: + value = sep_num_from_units(query_no_echo(instr2, 'IMAG?'))[0]*0.1 # convert kG to T + print(f"Device {device_id} reports value: {value} T") + + with lock: + shared_values[device_id] = value + # Check if both devices have met their targets + if all(shared_values.get(device) is not None and abs(shared_values[device] - target_value[device]) <= 0.0001 + for device in shared_values): # TODO: MODIFY THE IF CONDITIONAL HERE TO THAT IN B VAL SWEEP + print(f"Both devices reached their target values: {shared_values}") + all_targets_met_event.set() # Signal that both targets are met + + # time.sleep(1) # Simulate periodic data checking + + # Main function to manage threads and iterate over target values + def monitor_devices(device_target_values, angles_lst): + for iteration, target in enumerate(device_target_values): + print(f"\nStarting iteration {iteration+1} for target values: {target}") + # Shared dictionary to store values from devices + shared_values = {device: None for device in target.keys()} + # Event to signal when both target values are reached + all_targets_met_event = threading.Event() + + # Lock to synchronize access to shared_values + lock = threading.Lock() + + # Create and start threads for each device + threads = [] + for device_id in target.keys(): + thread = threading.Thread(target=listen_to_device, args=(device_id, target, shared_values, lock, all_targets_met_event)) + threads.append(thread) + thread.start() + + # Wait until both devices meet their target values + all_targets_met_event.wait() + print(f"Both target values for iteration {iteration+1} met. Performing action...") + + # Perform some action after both targets are met + # we acquire with the LF + acquire_name_spe = f'{base_file_name}_{angles_lst[iteration]}°' # NOTE: save each intensity file with the given angle + AcquireAndLock(acquire_name_spe) #this creates a .spe file with the scan name. + + # read the .spe file and get the data as loaded_files + cwd = os.getcwd() # save original directory + os.chdir(path_save) #change directory + loaded_files = sl.load_from_files([acquire_name_spe + '.spe']) # get the .spe file as a variable + os.chdir(cwd) # go back to original directory + + # Delete the created .spe file from acquiring after getting necessary info + spe_file_path = os.path.join(path_save, acquire_name_spe + '.spe') + os.remove(spe_file_path) + + # points_left = total_points - i - 1 # TODO: SEE IF THIS IS CORRECT + # print('Points left in the scan: ', points_left) + + #append the intensity data as it is (so after every #of_wl_points, the spectrum of the next point begins) + intensity_data.append(loaded_files.data[0][0][0]) + + # Clean up threads + for thread in threads: + thread.join() + + print(f"Threads for iteration {iteration+1} closed.\n") + + # modify cartesian_coords to suite the required data struct in monitor_devices + cartesian_coords = [{'2301034': t[0], '2101014': t[1]} for t in cartesian_coords] + + monitor_devices(cartesian_coords, angles) + + # TODO: add the end functionalities for saving the intensity data (see b-val_sweep), modify if necessary + # SEE LINES 554 TO 577 in code (version on 28.08.2024, 12.49 hrs) ################################################################# END OF FUNCTION DEFS ###########################################################################################