Source code for measurements.sweepIV

import time
import numpy as np

[docs]def create_list(logger, cycle, max_val, min_val, step): """ Create a list of values based on the specified cycle type and parameters. Args: logger (logging.Logger): The logger object to use for logging messages. cycle (str): The cycle type. Valid values are '+', '-', '+-', '-+'. max_val (float): The maximum value for the list. min_val (float): The minimum value for the list. step (float): The step size between consecutive values. Returns: numpy.ndarray: The generated list of values, rounded to 5 decimal places. Raises: ValueError: If the cycle type is invalid. """ list_positive = np.concatenate((np.arange(0, max_val, step), [max_val], np.flip(np.arange(0, max_val, step)))) list_negative = np.concatenate((np.arange(0, min_val, -step), [min_val], np.flip(np.arange(0, min_val, -step)))) try: match cycle: case '+': return np.round(list_positive,5) case '-': return np.round(list_negative,5) case '+-': return np.round((np.concatenate((list_positive, list_negative))),5) case '-+': return np.round(np.concatenate((list_negative, list_positive)),5) except: logger.critical('Invalid cycle type!') quit()
[docs]class Measurement: def __init__(self, logger, config, instrument): """ Initialize the Measurement class. Args: logger (logging.Logger): Logger to use for logging messages. config (dict): Dictionary containing configuration parameters. instrument (Instrument): Instrument object to use for measurement. """ self.name = 'sweepIV' self.nparams = ['cycle', 'n_cycles', 'v+', 'v-', 'v_step','ccplc+', 'ccplc-', 't_sweep', 'nplc'] self.headers = ['Voltage [V]', 'Current [A]', 'Resistance [Ω]', 'Timer [s]', 'Datetime'] self.params = dict(config.items()) self.vals = create_list( logger, self.params.get(self.name).get('cycle'), self.params.get(self.name).get('v+'), self.params.get(self.name).get('v-'), self.params.get(self.name).get('v_step')) self.set_plot_parameters(self.params.get(self.name).get('cycle')) self.initialize_instrument(logger, instrument)
[docs] def set_plot_parameters(self, cycle_type): """ Set parameters for the plot based on the type of cycle. Args: cycle_type (str): Type of the cycle which could be '1' or '2'. """ match len(cycle_type): case 1: self.plot_grid = (2, 2) self.plot_titles = [[f'Cycle I-V {cycle_type}', 'Resistance vs Time'], ['Resistance vs Voltage', 'Voltage vs Time']] self.plot_labels = [ [['Voltage [V]', 'Current [A]'], ['Time [s]', 'Resistance [Ω]']], [['Voltage [V]', 'Resistance [Ω]'], ['Time [s]', 'Voltage [V]']]] self.plot_clear = [[True, False], [True, False]] case 2: self.plot_grid = (2, 3) self.plot_titles = [['Cycle I-V +', 'Cycle I-V -', 'Resistance vs Time'], ['Resistance vs Voltage +', 'Resistance vs Voltage -', 'Voltage vs Time']] self.plot_labels = [ [['Voltage [V]', 'Current [A]'], ['Voltage [V]', 'Current [A]'], ['Time [s]', 'Resistance [Ω]']], [['Voltage [V]', 'Resistance [Ω]'], ['Voltage [V]', 'Resistance [Ω]'], ['Time [s]', 'Voltage [V]']]] self.plot_clear = [[True, True, False], [True, True, False]]
[docs] def initialize_instrument(self, logger, instrument): """ Initialize the instrument with initial parameters. Args: logger (logging.Logger): Logger to use for logging messages. instrument (Instrument): Instrument object to use for setting parameters. """ logger.debug('Setting instrument initial parameters') instrument.reset(logger) instrument.set_mode_fixed(logger, func='Voltage') instrument.set_src_func(logger, func='Voltage') instrument.set_sense_func(logger, func='Voltage') instrument.set_func_range(logger, func='Voltage') instrument.set_sense_func(logger, func='Current') instrument.set_func_range(logger, func='Current') instrument.set_func_nplc(logger, func='Current', value=self.params.get(self.name).get('nplc')) logger.debug('Instrument parameters set!')
[docs] def measure_val(self, logger, instrument, val): """ Measure the output for a given voltage and return the result along with the plots. Args: logger (logging.Logger): Logger to use for logging messages. instrument (Instrument): Instrument object to use for measurement. val (float): The voltage value to measure. Returns: list: A list containing the result of measurement and the plots. """ if val>0: instrument.set_func_cplc(logger, func="Current", value=self.params.get(self.name).get('ccplc+')) else: instrument.set_func_cplc(logger, func="Current", value=self.params.get(self.name).get('ccplc-')) instrument.set_output_value(logger, 'Voltage', val) result_sweep = instrument.read(logger) time.sleep(self.params.get(self.name).get('t_sweep')) result = [ val, # Voltage [0] result_sweep[1], # Current [1] val / result_sweep[1], # Resistance [2] result_sweep[3], # Timer [3] time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # Datetime [4] ] match len(self.params.get(self.name).get('cycle')): case 1: result_plots = [ [[result[0], result[1]], # [Voltage, Current] Cycle I-V [result[3], result[2]]], # [Time, Resistance] Resistance vs Time [[result[0], result[2]], # [Voltage, Resistance] Resistance vs Voltage [result[3], result[0]]] # [Time, Voltage] Voltage vs Time ] case 2: if val >= 0: result_plots = [ [[result[0], result[1]], # [Voltage, Current] Cycle I-V + [np.nan, np.nan], # [NaN, Nan] Cycle I-V - [result[3], result[2]]], # [Time, Resistance] Resistance vs Time [[result[0], result[2]], # [Voltage, Resistance] Resistance vs Voltage + [np.nan, np.nan], # [NaN, NaN] Resistance vs Voltage - [result[3], result[0]]] # [Time, Voltage] Voltage vs Time ] else: result_plots = [ [[np.nan, np.nan], # [NaN, NaN] Cycle I-V + [result[0], result[1]], # [Voltage, Current] Cycle I-V - [result[3], result[2]]], # [Time, Resistance] Resistance vs Time [[np.nan, np.nan], # [NaN, NaN] Resistance vs Voltage + [result[0], result[2]], # [Voltage, Resistance] Resistance vs Voltage - [result[3], result[0]]] # [Time, Voltage] Voltage vs Time ] return [result, result_plots]