import os from glob import glob from pathlib import Path from configparser import ConfigParser from frappy.errors import ConfigError class Rack: configbase = Path('/home/l_samenv/.config/frappy_instruments') def __init__(self, modfactory, **kwds): self.modfactory = modfactory instpath = self.configbase / os.environ['Instrument'] sections = {} self.config = {} files = glob(str(instpath / '*.ini')) for filename in files: parser = ConfigParser() parser.optionxform = str parser.read([filename]) for section in parser.sections(): prev = sections.get(section) if prev: raise ConfigError(f'duplicate {section} section in {filename} and {prev}') sections[section] = filename self.config.update(parser.items(section)) if 'rack' not in sections: raise ConfigError(f'no rack found in {instpath}') self.props = {} # dict (, ) of value self.mods = {} # dict (, ) of list of def set_props(self, mod, **kwds): for prop, method in kwds.items(): value = self.props.get((prop, method)) if value is None: # add mod to the list of cfgs to be fixed self.mods.setdefault((prop, method), []).append(mod) else: # set prop in current module if not mod.get(prop): # do not override given and not empty property mod[prop] = value def fix_props(self, method, **kwds): for prop, value in kwds.items(): if (prop, method) in self.props: raise ConfigError(f'duplicate call to {method}()') self.props[prop, method] = value # set property in modules to be fixed for mod in self.mods.get((prop, method), ()): mod[prop] = value def lakeshore(self, ls_uri=None, io='ls_io', dev='ls', model='336', **kwds): Mod = self.modfactory self.fix_props('lakeshore', io=io, device=dev) self.ls_model = model self.ls_dev = dev ls_uri = ls_uri or self.config.get('ls_uri') Mod(io, cls=f'frappy_psi.lakeshore.IO{self.ls_model}', description='comm. to lakeshore in cc rack', uri=ls_uri) self.dev = Mod(dev, cls=f'frappy_psi.lakeshore.Device{self.ls_model}', description='lakeshore in cc rack', io=io, curve_handling=True) def sensor(self, name, channel, calcurve, **kwds): Mod = self.modfactory kwds.setdefault('cls', f'frappy_psi.lakeshore.Sensor{self.ls_model}') kwds.setdefault('description', f'T sensor {name}') mod = Mod(name, channel=channel, calcurve=calcurve, device=self.ls_dev, **kwds) self.set_props(mod, io='lakeshore', dev='lakeshore') def loop(self, name, channel, calcurve, output_module, **kwds): Mod = self.modfactory kwds.setdefault('cls', f'frappy_psi.lakeshore.Loop{self.ls_model}') kwds.setdefault('description', f'T loop {name}') Mod(name, channel=channel, calcurve=calcurve, output_module=output_module, device=self.ls_dev, **kwds) self.fix_props(f'heater({output_module})', description=f'heater for {name}') def heater(self, name, output_no, max_heater, resistance, **kwds): Mod = self.modfactory if output_no == 1: kwds.setdefault('cls', f'frappy_psi.lakeshore.MainOutput{self.ls_model}') elif output_no == 2: kwds.setdefault('cls', f'frappy_psi.lakeshore.SecondaryOutput{self.ls_model}') else: return kwds.setdefault('description', '') mod = Mod(name, max_heater=max_heater, resistance=resistance, **kwds) self.set_props(mod, io='lakeshore', device='lakeshore', description=f'heater({name})') def ccu(self, ccu_uri=None, ccu_io='ccu_io', he=None, n2=None, **kwds): Mod = self.modfactory self.ccu_io = ccu_io ccu_uri = ccu_uri or self.config.get('ccu_uri') # self.devname = ccu_devname Mod(ccu_io, 'frappy_psi.ccu4.IO', 'comm. to CCU4', uri=ccu_uri) if he: if not isinstance(he, str): # e.g. True he = 'He_lev' Mod(he, cls='frappy_psi.ccu4.HeLevel', description='the He Level', io=self.ccu_io) if n2: if isinstance(n2, str): n2 = n2.split(',') else: # e.g. True n2 = [] n2, valve, upper, lower = n2 + ['N2_lev', 'N2_valve', 'N2_upper', 'N2_lower'][len(n2):] print(n2, valve, upper, lower) Mod(n2, cls='frappy_psi.ccu4.N2Level', description='the N2 Level', io=ccu_io, valve=valve, upper=upper, lower=lower) Mod(valve, cls='frappy_psi.ccu4.N2FillValve', description='LN2 fill valve', io=ccu_io) Mod(upper, cls='frappy_psi.ccu4.N2TempSensor', description='upper LN2 sensor') Mod(lower, cls='frappy_psi.ccu4.N2TempSensor', description='lower LN2 sensor') def hepump(self, hepump_uri=None, hepump_type=None, hepump_io='hepump_io', hepump='hepump', hepump_mot='hepump_mot', hepump_valve='hepump_valve', flow_sensor='flow_sensor', pump_pressure='pump_pressure', nv='nv', ccu_io='ccu_io', **kwds): Mod = self.modfactory hepump_type = hepump_type or self.config.get('hepump_type', 'no') Mod(nv, 'frappy_psi.ccu4.NeedleValveFlow', 'flow from flow sensor or pump pressure', flow_sensor=flow_sensor, pressure=pump_pressure, io=ccu_io) Mod(pump_pressure, 'frappy_psi.ccu4.Pressure', 'He pump pressure', io=ccu_io) if hepump_type == 'no': print('no pump, no flow meter - using flow from pressure alone') return hepump_uri = hepump_uri or self.config['hepump_uri'] Mod(hepump_io, 'frappy.io.BytesIO', 'He pump connection', uri=hepump_uri) Mod(hepump, 'frappy_psi.hepump.HePump', 'He pump', pump_type=hepump_type, valvemotor=hepump_mot, valve=hepump_valve, flow=nv) Mod(hepump_mot, 'frappy_psi.hepump.Motor', 'He pump valve motor', io=hepump_io, maxcurrent=2.8) Mod(hepump_valve, 'frappy_psi.butterflyvalve.Valve', 'He pump valve', motor=hepump_mot) Mod(flow_sensor, 'frappy_psi.sensirion.FlowSensor', 'Flow Sensor', io=hepump_io, nsamples=160)