def Scope_Parameters(oscilloscope): #oscilloscope.write('ACQuire:STATE RUN') #print('\nState: RUN') oscilloscope.write(f'SELECT:{cfg_scope.channel} ON') #print(f'\n{cfg_scope.channel} ON') oscilloscope.write(f'DATa:SOUrce {cfg_scope.channel}') #print(f'') oscilloscope.write(f'DATa:ENCdg {cfg_scope.encode_format}') #print(f'Encode Format: {cfg_scope.encode_format}') oscilloscope.write(f'DATa:WIDth {cfg_scope.width}') #print(f'Data Width: {cfg_scope.width}') oscilloscope.write(f'{cfg_scope.channel}:SCAle {cfg_scope.channel_scale}') # myprint(f'{cfg_scope.channel} scale: {cfg_scope.channel_scale}') oscilloscope.write( f'{cfg_scope.channel}:POSition {cfg_scope.channel_position}') # myprint(f'{cfg_scope.channel} position: {cfg_scope.channel_position}') oscilloscope.write(f'{cfg_scope.channel}:PRObe {cfg_scope.channel_probe}') #print(f'{cfg_scope.channel} probe: {cfg_scope.channel_probe}') oscilloscope.write(f'TRIGger:MAIn:LEVel {cfg_scope.trigger}') # myprint(f'Trigger: {1_000*cfg_scope.trigger} mV') oscilloscope.write(f'HORizontal:MAIn:SCAle {cfg_scope.horizontal_scale}') # myprint(f'Horizontal scale: {cfg_scope.horizontal_scale}') oscilloscope.write( f'HORizontal:MAIn:POSition {cfg_scope.horizontal_position_1};') #print(f'Horizontal Position: {cfg_scope.horizontal_position_1}') oscilloscope.write( f'HORizontal:MAIn:POSition {cfg_scope.horizontal_position_2};') # myprint(f'Horizontal Position: {cfg_scope.horizontal_position_2}') oscilloscope.write(f'DISplay:PERSistence {cfg_scope.persistence}') #print(f'Persistence: {cfg_scope.persistence}') oscilloscope.write(f'TRIGGER:MAIN:EDGE:SLOPE {cfg_scope.slope}') #print(f'Slope: {cfg_scope.slope}') myprint(f'\nSCOPE INFOs:\n{oscilloscope.query("WFMPre?")}\n' ) #Command to transfer waveform preamble information.
def Set_Scope_Parameters(oscilloscope): ''' Note: I don't now exactly why, but sometimes an error will occour in this part of the code. It's a runtime error. I THINK it's something to do with a problem on the communication between computer and oscilloscope. ''' try_set = True counter = 0 sleep(3) while try_set == True: sleep(1) try: Scope_Parameters(oscilloscope=oscilloscope) except: counter += 1 myprint(f'FAILED {counter} to write scope parameters.') if counter >= 3: myprint( 'FAILED TO WRITE scope parameters, even after three attempts.\nPlease, check connection with the oscilloscope and try again.' ) raise else: try_set = False myprint( f'\nOscilloscope informations: LOADED SUCESSFULLY after {counter} attempt(s). Check config file for more details.\n\n' )
def get_rnd_sample(oscilloscope, rnd_sample): '''Retrieve the conversion parameters from the oscilloscope''' converter = units_conversion_parameters(oscilloscope=oscilloscope) '''Create objects to fill''' df_data = pd.DataFrame() time_data = [] '''Acquisition of random samples''' for i in range(rnd_sample): try: event = np.array( oscilloscope.query_ascii_values('curve?')) #numpy-array except: myprint('error') else: event = convert_y_to_mV( event, converter) #convert event to mV, to compare with trigger df_data[f'{i}'] = event time_instant = time() time_data.append(time_instant) return (df_data, time_data)
def read_waveforms_csv(files, file_name, path, tag=''): """ This function reads all the step-DataFrames and concatenates them in a single one. While this process occours, all the step-DataFrames are deleted, in the end, the whole waveform-DataFrame is saved. Parameters ---------- files: list The list that contains all the names(paths) of the step-DataFrames files. file_name: string It's the name of the file to be saved in the end, the one which contains all the waveforms. It's not a path, but only a single string like '1134564322.34793'. The intention is to save the file_name as the time instant of the start of the acquisition. path: string Path to the folder where the csv files are stored. tag: string, Default '' A tag to put on the end of the file name. The default is the same as no tag. """ myprint('\nReading and assembling the csv files.') waveforms = [] for i in range(len(files)): df = pd.read_csv(files[i]) # os.remove(path=files[i]) # delete the partial files waveforms.append(df) Waveforms_df = pd.concat(waveforms, axis=1) Waveforms_df.columns = [('event_' + str(i)) for i in range(Waveforms_df.shape[1])] Waveforms_df.to_csv( f'{path}/{file_name}_{Waveforms_df.shape[1]}-events_{tag}.csv') return (Waveforms_df)
def check_parameters(oscilloscope): '''Check scope parameters''' try_info = True counter = 0 while try_info == True: try: trigger_info = oscilloscope.query('trigger:main?') y_scale_info = oscilloscope.query('ch1:scale?') except: counter += 1 if counter >= 3: myprint( 'FAILED TO QUERY scope parameters, even after three attempts.\nPlease, check connection with the oscilloscope and try again.' ) raise else: try_info = False trigger_value_mV = 1_000 * float(re.split(';', trigger_info)[-1]) trigger_slope = re.split(';', trigger_info)[5] y_scale_value = float(re.split('\n', y_scale_info)[0]) if trigger_value_mV != cfg_scope.trigger: myprint(f'Trigger changed: set to {trigger_value_mV} mV') else: myprint(f'Trigger ok.') if trigger_slope != cfg_scope.slope: myprint(f'Trigger slope changed: set to {trigger_slope}') else: myprint('Trigger slope ok.') if y_scale_value != cfg_scope.channel_scale: myprint(f'Scale changed: set to {y_scale_value}\n') else: myprint(f'Scale ok.\n') return (trigger_value_mV, trigger_slope, y_scale_value)
import pyvisa import pandas as pd from time import time, ctime, sleep from datetime import timedelta # Initial time and create storage folder #========================================================================================================== '''Initial time''' time_start = time() '''Create folder to store logging, waveforms and conversion file''' acquisition_type = Acquisition_Type(min_peaks=cfg_scope.min_peaks) folder_name = f'../documents/data/{acquisition_type}/{time_start}' Create_Folder(name=folder_name) #documents/data/{tag_name}/{time_start} '''Print local time and type of acquisition''' myprint( f'\nStarting acquisition... Local time: {ctime(time_start)}\nThis is a \"{acquisition_type}\" type of acquisition.\n' ) sleep(3) # Call oscilloscope and set the parameters #========================================================================================================== rm = pyvisa.ResourceManager() # Calling PyVisa library scope = rm.open_resource(str(cfg_scope.ScopeID)) # Connecting via USB Set_Scope_Parameters(oscilloscope=scope) # Print preamble of informations #========================================================================================================== # myprint(f'\nNumber of requested samples: {cfg_scope.necessarySamples}') # myprint(f'Minimal number of peaks: {cfg_scope.min_peaks}') if cfg_scope.email_me == True:
from acquisition.SaveOutputs.Send_Email import SendEmail import pyvisa import pandas as pd from time import time, ctime, sleep from datetime import timedelta # Initial time and create storage folder #========================================================================================================== '''Initial time''' time_start = time() '''Create folder to store logging, waveforms and conversion file''' folder_name = f'Documents/data/{time_start}' Create_Folder(name=folder_name) #Documents/data/time_start '''Print local time''' myprint(f'\nStarting acquisition... Local time: {ctime(time_start)} \n') sleep(3) # Call oscilloscope and set the parameters #========================================================================================================== rm = pyvisa.ResourceManager() # Calling PyVisa library scope = rm.open_resource(str(cfg_scope.ScopeID)) # Connecting via USB Set_Scope_Parameters(oscilloscope=scope) # Print preamble of informations #========================================================================================================== myprint(f'\nNumber of requested samples: {cfg_scope.necessarySamples}') myprint(f'Minimal number of peaks: {cfg_scope.min_peaks}') myprint( f'Progress tracker is {"ON" if cfg_scope.track_progress == True else "OFF"}' )
def print_scope_config(trigger_value, trigger_slope=cfg_scope.slope, y_scale=cfg_scope.channel_scale): ''' Parameters for the acquisition ''' myprint(f'\nAcquisition parameters:') myprint(f' Necessary samples: {cfg_scope.necessarySamples}') myprint(f' Samples per csv: {cfg_scope.samples}') myprint(f' Random samples: {cfg_scope.random_samples}') myprint(f' Minimal number of peaks: {cfg_scope.min_peaks}') myprint(f' Minimal separation: {cfg_scope.min_separation}') myprint(f' Email-me: {cfg_scope.email_me}') ''' Parameters to set on the oscilloscope ''' myprint(f'Ocilloscope parameters:') myprint(f' Oscilloscope: {cfg_scope.ScopeID}') myprint(f' Channel: {cfg_scope.channel}') myprint(f' Encode Format: {cfg_scope.encode_format}') myprint(f' Channel width: {cfg_scope.width}') myprint(f' Channel position: {cfg_scope.channel_position}') myprint(f' Probe: {cfg_scope.channel_probe}') myprint(f' Persistence: {cfg_scope.persistence}') myprint(f' Scope Resolution: {cfg_scope.scopeResolution}') myprint(f' Horizontal scale: {10E6*cfg_scope.horizontal_scale} micro-sec') myprint( f' Horizontal position: {10E6*cfg_scope.horizontal_position_2} micro-sec' ) ''' Special parameters for the acquisition ''' myprint(f' Ch1 scale (y_scale): {y_scale}') myprint(f' Trigger value: {trigger_value} mV') myprint(f' Trigger slope: {trigger_slope}\n')
min_peaks: int, default 2 . min_separation: int, default 10 """ trigger_value, trigger_slope, y_scale = check_parameters( oscilloscope=oscilloscope) acquired_samples = 0 # Total amount of samples collected saved_csv = 1 # Total of saved csv files files = [] # File names while acquired_samples < necessarySamples: myprint( f'Try number {saved_csv}. {round(100*acquired_samples/necessarySamples,2)}% ({acquired_samples}/{necessarySamples}).' ) waveforms = run_acquisition(oscilloscope=oscilloscope, samples=samples, rnd_sample=rnd_sample, min_peaks=min_peaks, min_separation=min_separation, trigger=trigger_value, trigger_slope=trigger_slope) file = f'{path}/file_{saved_csv}.csv' waveforms.to_csv(file) # save the partial waveforms DataFrame files.append(file) # add the name to the list acquired_samples += waveforms.shape[0]
def run_acquisition(oscilloscope, samples=100, rnd_sample=1000, height=0, min_peaks=2, min_separation=10): """ This function serves to the purpose of retrieving a useful sample with given lenght. Operation: - wait 2 seconds - define DataFrame and list to be filled after - while loop: -- retrieve a sample with lenght = min(100, 10*samples); neither too small nor too big -- analyze this sample with respect to the peaks -- store the useful events on the DataFrame and the times on the respective list -- repeat until get enought events - after filling all the requested samples, append the times to the DataFrame, change columns names, details etc. - finish - returns the DataFrame containing the times and the waveforms (on the columns) Parameters ---------- oscilloscope: instrument object Called by the pyvisa library. samples: int, default 100 The number of samples to retrieve. 'samples' is the total amount of 'good samples', i.e., the total amount of samples that pass on the min_peaks tests. Do not confuse with the rnd_sample. rnd_samples: int, default 1000 The number of samples with random goodness, i.e., the samples may be good, but may be not. After collecting, they will be analyzed and stored, if they are good, as specified. height: int, default 0 The height value to find the peaks on the waveform. It's called by scipy, on the find_peaks function min_peaks: int, default 2 'Quality test' for the waveform. If it contains at least the minimal peaks, it's a 'good sample'. """ sleep(1) waveformList = pd.DataFrame() timeList = [] counter = 1 while waveformList.shape[1] < samples: total_events = waveformList.shape[1] temp_df = pd.DataFrame() tempTime = [] print( f' Run {counter}. {round(100*total_events/samples , 1)}%. ({total_events}/{samples}).' ) '''Acquisition of random samples''' for i in range(rnd_sample): try: event = oscilloscope.query_ascii_values('curve?') #list except: myprint('error') else: temp_df[f'{i}'] = event time_instant = time() tempTime.append(time_instant) '''Analysis of the rnd_sample: find waveform if len(peaks) >= min_peaks and save''' for i in range(temp_df.shape[1]): event = temp_df[temp_df.columns[i]] peaks, _ = find_peaks(-1 * event, height=-1 * height) if (min_peaks >= 2) and (len(peaks) == min_peaks) and ( peaks[1] - peaks[0] >= min_separation): waveformList[ f'{counter}_{i}'] = event # counter_i will guarantee that the names on the df will not be replaced timeList.append(tempTime[i]) elif (min_peaks < 2) and ( len(peaks) == min_peaks ): # there's no separation when there's only 1 or none peaks waveformList[ f'{counter}_{i}'] = event # counter_i will guarantee that the names on the df will not be replaced timeList.append(tempTime[i]) '''If not finished yet, try again''' counter += 1 '''Add correct label to the columns and add the time column''' waveformList.columns = [('event_' + str(i)) for i in range(waveformList.shape[1])] # waveformList.index = [i for i in range(waveformList.shape[0])] df = waveformList.T #This command is only to add the timeList as a line in an easy way. This undone later df.insert(0, 'time_epoch', np.array(timeList)) return (df)