def __init__(self, config): """Constructor :param config: configuration data (from JSON) :type config: dict """ Stage.__init__(self, config) try: self._group = PlaceConfig().get_config_value( self.__class__.__name__, 'group_name') except PlaceConfigError: raise RuntimeError( 'Cannot find the group name for the {} '.format( self.__class__.__name__) + 'in ~/.place.cfg\nPlease determine the group name and ' + 'add it to this file.\n(See the XPS Controller ' + 'documentation for more details.') try: self._positioner = PlaceConfig().get_config_value( self.__class__.__name__, 'positioner_name') except PlaceConfigError: raise RuntimeError( 'Cannot find the positioner name for the {} '.format( self.__class__.__name__) + 'in ~/.place.cfg\nPlease determine the positioner name and ' + 'add it to this file.\n(See the XPS Controller ' + 'documentation for more details.')
def _configure_controller(self): """Send all the starting configurations to the picomotors.""" name = self.__class__.__name__ ip_address = PlaceConfig().get_config_value(name, "ip_address") port = PlaceConfig().get_config_value(name, "port") self._controller = PMot() self._controller.connect(ip_address, int(port)) self._controller.set_velocity(pmot.PX, 1700) self._controller.set_velocity(pmot.PY, 1700) self._controller.set_axis_displacement(pmot.PX, 1) self._controller.set_axis_displacement(pmot.PY, 1) self._controller.set_following_error(pmot.PX, 200) self._controller.set_following_error(pmot.PY, 200) self._controller.set_cl(pmot.PX, 0.1) self._controller.set_cl(pmot.PY, 0.1) self._controller.set_mm(pmot.PX, 1) self._controller.set_mm(pmot.PY, 1) self._controller.set_sm()
def config(self, metadata, total_updates): """Configure the vibrometer. :param metadata: scan metadata :type metadata: dict :param total_updates: number of updates for the scan :type total_updates: int """ name = self.__class__.__name__ self._serial = Serial( port=PlaceConfig().get_config_value(name, "port"), baudrate=PlaceConfig().get_config_value(name, "baudrate"), timeout=10, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) if self._config['dd_300']: self._setup_decoder(metadata, 'dd_300') if self._config['dd_900']: self._setup_decoder(metadata, 'dd_900') if self._config['vd_08']: self._setup_decoder(metadata, 'vd_08') if self._config['vd_09']: self._setup_decoder(metadata, 'vd_09') if self._config['plot']: plt.figure(self.__class__.__name__) plt.clf() plt.ion()
def config(self, metadata, total_updates): """Configure the mfli. :param metadata: experiment metadata :type metadata: dict :param total_updates: number of updates for the experiment :type total_updates: int """ name = self.__class__.__name__ self.mfli = MFLIDriver( PlaceConfig().get_config_value(name, "device_name"), PlaceConfig().get_config_value(name, "device_ip"), port=8004) self.total_updates = total_updates if self._config["mode"] == "lockin_amp": self._config_sigin() self._config_extref() self._config_demod() self._config_acquisition() metadata["mfli_actual_sampling_rate"] = self.actual_sampling_rate self.mfli.start_acquisition(wait=False)
def config(self, metadata, total_updates): """Configure the vibrometer. :param metadata: experiment metadata :type metadata: dict :param total_updates: number of updates for the experiment :type total_updates: int """ name = self.__class__.__name__ self._serial = Serial( port=PlaceConfig().get_config_value(name, "port"), baudrate=PlaceConfig().get_config_value(name, "baudrate"), timeout=10, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) self.controller_name = self._get_controller_name() metadata['polytec_controller'] = self.controller_name if self.controller_name == "OFV-5000 Vibrometer Controller": self.prefixd = 'dd' self.prefixv = 'vd' elif self.controller_name == "OFV-5000Xtra Vibrometer Controller": self.prefixd = 'dx' self.prefixv = 'vx' if self._config['{}_300'.format(self.prefixd)]: self._setup_decoder(metadata, '{}_300'.format(self.prefixd)) if self._config['{}_900'.format(self.prefixd)]: self._setup_decoder(metadata, '{}_900'.format(self.prefixd)) try: if self._config['{}_08'.format(self.prefixv)]: self._setup_decoder(metadata, '{}_08'.format(self.prefixv)) except: pass if self._config['{}_09'.format(self.prefixv)]: self._setup_decoder(metadata, '{}_09'.format(self.prefixv)) if self._config['autofocus'] == 'custom': curr_set = self._write_and_readline( 'GetDevInfo,SensorHead,0,Focus\n') curr_min, curr_max = ast.literal_eval(curr_set) self.min_used = max(curr_min, self._config['area_min']) self.max_used = min(curr_max, self._config['area_max']) metadata['actual_area_min'] = self.min_used metadata['actual_area_max'] = self.max_used
def config(self, metadata, total_updates): """Configure the pre-amp. The pre-amp is entirely configured at the beginning of the scan. Due to the small number of configuration options, this module requires values be specified for all the options and no defaults are assumed. :param metadata: metadata for the experiment :type metadata: dict :param total_updates: the number of update steps that will be in this experiment :type total_updates: int """ serial_port = PlaceConfig().get_config_value(self.__class__.__name__, 'serial_port', '/dev/ttys0') preamp = SR560Driver(serial_port) preamp.set_defaults() preamp.set_blanking(self._config['blanking']) preamp.set_coupling(self._config['coupling']) preamp.set_reserve(self._config['reserve']) preamp.set_filter_mode(self._config['filter_mode']) preamp.set_gain(self._config['gain']) preamp.set_highpass_filter(self._config['highpass_filter']) preamp.set_lowpass_filter(self._config['lowpass_filter']) preamp.set_signal_invert_sense(self._config['signal_invert_sense']) preamp.set_input_source(self._config['input_source']) preamp.set_vernier_gain_status(self._config['vernier_gain_status']) preamp.set_vernier_gain(self._config['vernier_gain'])
def config(self, metadata, total_updates): """Configuration for IQ demodulation IQ demodulation requires the following configuration data (accessible as self._config['*key*']): ========================= ============== ================================================ Key Type Meaning ========================= ============== ================================================ field_ending string the ending of the field to be post-processed plot bool true if the post-processed data should be plotted remove_trace_data bool true if the original trace data should be removed (saving space); false if all data should be retained y_shift float an amount to shift all data points to put the zero point at zero (mostly used for data that is unsigned) ========================= ============== ================================================ """ try: self.sampling_rate = metadata['sampling_rate'] except KeyError: raise RuntimeError( "'sampling_rate' is not available in the metadata - " + "IQ demodulation postprocessing cannot be performed") self.updates = total_updates name = self.__class__.__name__ self.lowpass_cutoff = float(PlaceConfig().get_config_value( name, 'lowpass_cutoff', '10e6')) metadata['demodulation'] = 'IQ' if self._config['plot']: plt.figure(self.__class__.__name__) plt.clf() plt.ion()
def _set_up_moku_sweep(self, sweep): ip_address = PlaceConfig().get_config_value(self.__class__.__name__, 'ip_address') ch1_amp = self._config['ch1_amp'] ch2_amp = self._config['ch2_amp'] self.moku = Moku(ip_address) self.bode = self.moku.deploy_or_connect(BodeAnalyzer) try: # or self._config['data_points'] % 2 != 0: self.bode.set_xmode('sweep') self.bode.set_output(1, ch1_amp) self.bode.set_output(2, ch2_amp) self.bode.set_frontend(channel=1, ac=True, atten=False, fiftyr=False) self.bode.set_frontend(channel=2, ac=True, atten=False, fiftyr=False) except: self.moku.close() raise self.bode.set_sweep(sweep[0] * 1000, sweep[-1] * 1000, len(sweep), False, self._config['averaging_time'], self._config['settling_time'], self._config['averaging_cycles'], self._config['settling_cycles']) self.bode.start_sweep(single=self._config['single_sweep'])
def config(self, metadata, total_updates): """Configure the oscilloscope. :param metadata: metadata for the experiment :type metadata: dict :param total_updates: the number of update steps that will be in this experiment :type total_updates: int :raises OSError: if unable to connect to oscilloscope """ name = self.__class__.__name__ self._updates = total_updates self._ip_address = PlaceConfig().get_config_value(name, "ip_address") self._scope = socket(AF_INET, SOCK_STREAM) self._scope.settimeout(5.0) try: self._scope.connect((self._ip_address, 4000)) except OSError: self._scope.close() del self._scope raise self._channels = [self._is_active( x+1) for x in range(self._get_num_analog_channels())] self._record_length = self._get_record_length() metadata[name + '-record_length'] = self._record_length self._x_zero = [None for _ in self._channels] self._x_increment = [None for _ in self._channels] metadata[name + '-active_channels'] = self._channels self._samples = self._get_sample_rate() metadata[name + '-sample_rate'] = self._samples for channel, active in enumerate(self._channels): if not active: continue self._send_config_msg(channel+1) self._x_zero[channel] = self._get_x_zero(channel+1) self._x_increment[channel] = self._get_x_increment(channel+1) metadata[name + '-ch{:d}_x_zero'.format(channel+1)] = self._x_zero[channel] metadata[name + '-ch{:d}_x_increment'.format( channel+1)] = self._x_increment[channel] metadata[name + '-ch{:d}_y_zero'.format(channel+1)] = self._get_y_zero(channel+1) metadata[name + '-ch{:d}_y_offset'.format(channel+1)] = self._get_y_offset(channel+1) metadata[name + '-ch{:d}_y_multiplier'.format( channel+1)] = self._get_y_multiplier(channel+1) self._scope.close() if self._config['plot']: for channel, active in enumerate(self._channels): if not active: continue width, height = DEFAULT_FIGSIZE plt.figure( name + '-ch{:d}'.format(channel+1), figsize=(width, height*2), # two subplots dpi=DEFAULT_DPI ) plt.clf()
def start(): """Target for the `place_server` command""" os.environ.setdefault("DJANGO_SETTINGS_MODULE", "placeweb.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: raise ImportError( "Couldn't import Django. Are you sure it's installed and " "available on your PYTHONPATH environment variable? Did you " "forget to activate a virtual environment?" ) from exc config = PlaceConfig() ip_addr = config.get_config_value('Django', 'ip_address', '127.0.0.1') port = config.get_config_value('Django', 'port', '8000') address = '{}:{}'.format(ip_addr, port) print(INTRO) execute_from_command_line(['', 'runserver', address])
def _connect_to_server(self): ip_address = PlaceConfig().get_config_value('XPS', "ip_address") port = 5001 timeout = 3 self._socket = self._controller.TCP_ConnectToServer( ip_address, port, timeout) if self._socket == -1: raise RuntimeError(__name__ + ": connection failed")
def __init__(self, config): """Constructor :param config: configuration data (from JSON) :type config: dict """ Stage.__init__(self, config) self._group = PlaceConfig().get_config_value(self.__class__.__name__, 'group_name', 'ROT_STAGE')
def _get_calibration(self): '''Function which sets the calibration between ms of a pulse to the servo and degrees of rotation''' self.servo_min = float(PlaceConfig().get_config_value( self.name, 'servo_min')) #Minimum pulse length which causes servo rotation self.servo_min_deg = float(PlaceConfig().get_config_value( self.name, 'servo_min_deg')) #Position in degrees corresponding to servo_min servo_max = float(PlaceConfig().get_config_value( self.name, 'servo_max')) #Maximum pulse length which causes servo rotation self.servo_max_deg = float(PlaceConfig().get_config_value( self.name, 'servo_max_deg')) #Position in degrees corresponding to servo_max self.deg_to_ms = (servo_max - self.servo_min) / (self.servo_max_deg - self.servo_min_deg)
def config(self, metadata, total_updates): """Configure the vibrometer. :param metadata: experiment metadata :type metadata: dict :param total_updates: number of updates for the experiment :type total_updates: int """ name = self.__class__.__name__ self._serial = Serial( port=PlaceConfig().get_config_value(name, "port"), baudrate=PlaceConfig().get_config_value(name, "baudrate"), timeout=10, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) if self._config['dd_300']: self._setup_decoder(metadata, 'dd_300') if self._config['dd_900']: self._setup_decoder(metadata, 'dd_900') if self._config['vd_08']: self._setup_decoder(metadata, 'vd_08') if self._config['vd_09']: self._setup_decoder(metadata, 'vd_09') if self._config['autofocus'] == 'custom': curr_set = self._write_and_readline( 'GetDevInfo,SensorHead,0,Focus\n') curr_min, curr_max = ast.literal_eval(curr_set) self.min_used = max(curr_min, self._config['area_min']) self.max_used = min(curr_max, self._config['area_max']) metadata['actual_area_min'] = self.min_used metadata['actual_area_max'] = self.max_used
def config(self, metadata, total_updates): """ Called by PLACE at the beginning of the experiment to get everything up and running. """ self.total_updates = total_updates name = self.__class__.__name__ tsn_str = PlaceConfig().get_config_value(name, 'time_safety_net', '3.0') self.time_safety_net = float(tsn_str) metadata['MokuLab-predicted-update-time'] = self._predicted_sweep_time( ) self.sweeps = _calc_sweeps(f_start=self._config['f_start'], f_end=self._config['f_end'], n_pts=self._config['data_points'])
def _setup_decoder(self, metadata, name): """Set the range for the decoder and obtain metadata :param metadata: experiment metadata :type metadata: dict :param name: the name to use for the decoder :type name: str """ id_ = PlaceConfig().get_config_value(self.__class__.__name__, name) self._set_range(id_, self._config[name + '_range']) if name == 'vd_08' or name == 'vd_09': metadata[name + '_time_delay'] = self._get_delay(id_) metadata[name + '_maximum_frequency'] = self._get_maximum_frequency(id_)
def config(self, metadata, total_updates): name = self.__class__.__name__ self.serial_port = PlaceConfig().get_config_value(name, 'serial_port') start = self._config['start'] step = self._config['increment'] end = start + (step * total_updates) self.arduino = serial.Serial(self.serial_port, timeout=0.5) self.arduino.flush() wait = _read_serial(self.arduino) #Waits for ready code from Arduino self.arduino.write(bytes('i\n','ascii')) id_string = _read_serial(self.arduino) self._position = _get_position(self.arduino) metadata['ArduinoStage-id-string'] = id_string.strip()
def config(self, metadata, total_updates): """PLACE module for reading data from the DS345 function generator. Currently, this module is only designed to record the settings on the function generator. :param metadata: metadata for the experiment :type metadata: dict :param total_updates: the number of update steps that will be in this experiment :type total_updates: int """ serial_port = PlaceConfig().get_config_value(self.__class__.__name__, 'serial_port', '/dev/ttys0') function_gen = DS345Driver(serial_port) metadata['DS345-output_amplitude'] = function_gen.ampl()[0] metadata['DS345-output_frequency'] = function_gen.freq() metadata['DS345-sampling_frequency'] = function_gen.fsmp() metadata['DS345-output_function'] = function_gen.func() metadata['DS345-inversion_status'] = function_gen.invt() metadata['DS345-DC_offset'] = function_gen.offs() metadata['DS345-modulation_waveform'] = function_gen.mdwf() metadata['DS345-burst_count'] = function_gen.bcnt() metadata['DS345-modulation_depth'] = function_gen.dpth() metadata['DS345-span'] = function_gen.fdev() metadata['DS345-modulation_enabled'] = function_gen.mena() metadata['DS345-mark_freq_start'] = function_gen.mrkf('START') metadata['DS345-mark_freq_stop'] = function_gen.mrkf('STOP') metadata['DS345-mark_freq_center'] = function_gen.mrkf('CENTER') metadata['DS345-mark_freq_span'] = function_gen.mrkf('SPAN') metadata['DS345-modulation_type'] = function_gen.mtyp() metadata['DS345-phase_mod_span'] = function_gen.pdev() metadata['DS345-modulation_rate'] = function_gen.rate() metadata['DS345-sweep_span'] = function_gen.span() metadata['DS345-sweep_center'] = function_gen.spcf() metadata['DS345-sweep_stop'] = function_gen.spfr() metadata['DS345-sweep_start'] = function_gen.stfr() metadata['DS345-trigger_rate'] = function_gen.trat() metadata['DS345-trigger_source'] = function_gen.tsrc() metadata['DS345-divider'] = function_gen.amrt() if (metadata['DS345-modulation_type'] not in [ 'LIN SWEEP', 'LOG SWEEP', 'FM', 'PHI_M' ] and metadata['DS345-output_function'] not in ['NOISE', 'ARBITRARY']): metadata['DS345-output_phase'] = function_gen.phse()
def config(self, metadata, total_updates): """Configure the amplifier. Typically, the amplifier will be configured at the beginning of an experiment, so the majority of the activity will happen in this method. :param metadata: metadata for the experiment :type metadata: dict :param total_updates: the number of update steps that will be in this experiment :type total_updates: int """ serial_port = PlaceConfig().get_config_value(self.__class__.__name__, 'serial_port', '/dev/ttys0') metadata['sr850_settings'] = { 'serial_port': serial_port, }
def config(self, metadata, total_updates): """PLACE module for reading data from the DS345 function generator. Currently, this module is only designed to record the settings on the function generator. :param metadata: metadata for the experiment :type metadata: dict :param total_updates: the number of update steps that will be in this experiment :type total_updates: int """ name = self.__class__.__name__ serial_port = PlaceConfig().get_config_value(name, "port") self.function_gen = DS345Driver(serial_port) self.vary_amplitude = self._config["vary_amplitude"] if self._config["mode"] == "freq_sweep": self.function_gen.func(function_type="SINE") self.function_gen.stfr(frequency=self._config["start_freq"]) self.function_gen.spfr(frequency=self._config["stop_freq"]) self.function_gen.offs(dc_offset=0.0) self.function_gen.ampl(amplitude=self._config["start_amplitude"]) self.function_gen.rate(rate=1. / self._config["sweep_duration"]) self.function_gen.tsrc(source="SINGLE") self.function_gen.mtyp(modulation="LIN SWEEP") self.function_gen.mdwf(waveform="SINGLE SWEEP") self.function_gen.mena(modulation=True) time.sleep(3) #Future comms seem to fail without a pause metadata['DS345_start_freq'] = self._config["start_freq"] metadata['DS345_stop_freq'] = self._config["stop_freq"] metadata['DS345_sweep_duration'] = self._config["sweep_duration"] if total_updates > 1: self.amplitude_increment = ( self._config["stop_amplitude"] - self._config["start_amplitude"]) / (total_updates - 1) self.current_amplitude = self._config["start_amplitude"] self._read_settings()
def _setup_decoder(self, metadata, name): """Set the range for the decoder and obtain metadata :param metadata: experiment metadata :type metadata: dict :param name: the name to use for the decoder :type name: str """ id_ = PlaceConfig().get_config_value(self.__class__.__name__, name) self._set_range(id_, self._config[name + '_range']) if name == '{}_08'.format(self.prefixv) or name == '{}_09'.format( self.prefixv): metadata[name + '_time_delay'] = self._get_delay(id_) metadata[name + '_maximum_frequency'] = self._get_maximum_frequency(id_) calibration, calibration_units = self._get_range(name, id_) metadata[name + '_calibration'] = calibration metadata[name + '_calibration_units'] = calibration_units
def config(self, metadata, total_updates): self.name = self.__class__.__name__ self.serial_port = PlaceConfig().get_config_value( self.name, 'serial_port') self._get_calibration( ) #Get the calibration of the servo from ms to deg self._get_positions( total_updates ) #Get the start, end, and increment parameters for this scan self.arduino = serial.Serial( self.serial_port, timeout=0.5) #Initialise serial communication self.arduino.flush() wait = _read_serial(self.arduino) #Waits for ready code from Arduino self.arduino.write(bytes('i\n', 'ascii')) #Get id from Arduino id_string = _read_serial(self.arduino) self.initial_position = _get_position(self.arduino) metadata['ArduinoStage-id-string'] = id_string.strip()
"""The PLACE plotting module""" import os.path from random import random import numpy as np from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas from matplotlib.figure import Figure from placeweb.settings import MEDIA_ROOT from place.config import PlaceConfig DATA_POINT_LIMIT = int(PlaceConfig().get_config_value( 'Plots', 'maximum points for network transfer', "10000")) DEFAULT_FIGSIZE = (7.29, 4.17) DEFAULT_DPI = 96 class PlacePlotter: """A plotter for making common PLACE plots Each plugin will get its own plotting object, which is aware of the storage directory and progress dictionary. """ def __init__(self, progress, directory): self.progress = progress self.directory = directory def view1(self, title, ydata1, xdata1=None): """Make a line chart
""" Django settings for PLACE webapp project. Generated by 'django-admin startproject' using Django 2.0.5. For more information on this file, see https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os from place.config import PlaceConfig config = PlaceConfig() # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MEDIA_ROOT = config.get_config_value('Django', 'experiment_root', os.path.expanduser('~/.place')) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '768y90xswp36e=3x8y4r7twt#d4q+o&obfs13*^t+m9hoi$u-=' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True
def config(self, metadata, total_updates): """ Configure the EPR-3000 electronic pressure regulator. """ self.name = self.__class__.__name__ # Initialise configuration variables _place_config = PlaceConfig() self.serial_port = _place_config.get_config_value( self.name, 'serial_port') self.max_p = float( _place_config.get_config_value(self.name, 'maximum_pressure')) self.min_p = float( _place_config.get_config_value(self.name, 'minimum_pressure')) self.tolerance = float( _place_config.get_config_value(self.name, 'tolerance')) self.press_incrs_min = float( _place_config.get_config_value(self.name, 'pressure_increase_minimum')) self.press_incrs_min_time_period = float( _place_config.get_config_value( self.name, 'pressure_increase_minimum_time_period')) self.press_decrs_min = float( _place_config.get_config_value(self.name, 'pressure_decrease_minimum')) self.press_decrs_min_time_period = float( _place_config.get_config_value( self.name, 'pressure_decrease_minimum_time_period')) self.max_adjustment_wait_time = float( _place_config.get_config_value(self.name, 'max_adjustment_wait_time')) metadata[self.name + '-units'] = self._config['units'] # Initialise serial self.reg = serial.Serial(self.serial_port, baudrate=19200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE) self.reg.flushOutput() self.reg.flushInput() self.reg.write(bytes('*@=A\r'.encode('ascii'))) #Set to polling mode # Go to the starting pressure self.starting_press = self._config['start_pressure'] self._set_pressure(self.starting_press, monitor=True)
""" Django settings for PLACE webapp project. Generated by 'django-admin startproject' using Django 2.0.5. For more information on this file, see https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os from place.config import PlaceConfig config = PlaceConfig() # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MEDIA_ROOT = config.get_config_value( 'Django', 'experiment_root', os.path.expanduser('~/.place')) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '768y90xswp36e=3x8y4r7twt#d4q+o&obfs13*^t+m9hoi$u-='