def spectrometer_thread(): spectrometer = OceanFX() with create_server('spectrometer') as publisher: while True: trans = {} rough = {} try: spectrometer.capture() except Exception as e: print('Spectrometer capture failed!', e) continue spectrum = spectrometer.intensities (I0, roughness, beta_0, beta_2, beta_4, chisq) = spectrometer.roughness_full trans['spec'] = deconstruct(spectrometer.transmission_scalar) trans['unexpl'] = deconstruct(I0) rough['surf'] = deconstruct(roughness) rough['zero-order'] = deconstruct(beta_0) rough['second-order'] = deconstruct(beta_2) rough['fourth-order'] = deconstruct(beta_4) rough['chisq'] = chisq data = { 'wavelengths': list(spectrometer.wavelengths), 'intensities': { 'nom': list(nom(spectrum)), 'std': list(std(spectrum)), }, 'intercepts': { 'nom': list(nom(spectrometer._intercepts)), 'std': list(std(spectrometer._intercepts)), }, 'fit': { 'num-points': list(nom(spectrometer._points)), 'chisq-array': list(spectrometer._chisqs), 'chisq': deconstruct(spectrometer.chisq), }, 'rough': rough, 'trans': trans, } publisher.send(data)
def calibrate( name, time_limit=60, show_plot=False, ): print(f'Calibrating OceanFX {name} for {time_limit} seconds...') # connect to publisher monitor_socket = connect_to('spectrometer') samples = [] start_time = time.monotonic() for i in itertools.count(): _, data = monitor_socket.blocking_read() print(f'\rSample {Style.BRIGHT}{i+1}{Style.RESET_ALL}', end='') wavelengths = data['wavelengths'] spectrum = data['intensities'] samples.append(uarray(spectrum['nom'], spectrum['std'])) if time.monotonic() - start_time > time_limit: break monitor_socket.socket.close() spectrum = sum(samples) / len(samples) print() if show_plot: print('Plotting...') plot(wavelengths, spectrum, continuous=True) plt.xlim(300, 900) plt.xlabel('Wavelength (nm)') plt.ylabel('Intensity (%)') plt.title(name) plt.show() print(f'Saving {name} OceanFX calibration...') np.savetxt(f'calibration/{name}.txt', [nom(spectrum), std(spectrum)]) print('Done.')
model_pred = np.exp(roughness_model(wavelengths, beta_0, beta_2, beta_4)) plt.plot(wavelengths, model_pred, alpha=0.5, color='C1', zorder=20) plt.ylabel('Transmission (%)') if LOG_SCALE: plt.ylim(1e-3, 110) plt.yscale('log') else: plt.ylim(0, 110) else: # Intensity plot(wavelengths, intensities, continuous=True) plt.ylabel('Intensity (counts/μs)') if LOG_SCALE: plt.yscale('log') plt.ylim(1e-2, 1e3) else: hene_mask = (wavelengths < 610) | (wavelengths > 650) saturation = max(nom(intensities)[hene_mask]) plt.ylim(0, 1.1*saturation) plt.xlim(350, 1000) plt.xlabel('Wavelength (nm)') fig.canvas.draw() fig.canvas.flush_events() time.sleep(0.5)
osa.sweep_mode = 'repeat' # continuously sweep (for logging) #osa.trigger() # trigger once # Display configuration print('Getting configuration...') print() # Wait for trigger, then plot trace #osa.quick_plot() #osa.live_plot() # Get some averaged spectra if True: for i in itertools.count(): if True: wavelengths, power = osa.average_spectra(n=1, delay=10) data = np.array([wavelengths, nom(power), std(power)]) np.savetxt( f'spectra/{SAVE_NAME}-{i:04d}.txt', data.T, header='wavelength (nm)\tpower (dB)\tpower uncertainty (dB)' ) print(f'Saved as spectra/{SAVE_NAME}-{i:04d}.txt') plot(wavelengths, power, continuous=True) plt.xlabel('Wavelength (nm)') plt.ylabel('Power (dB)') plt.show()
def format_array(arr): return ' '.join(f'{x:.6f}' for x in arr) with open(log_file, 'a') as f: print(format_array(OCEANFX_WAVELENGTHS), file=f) for n in itertools.count(1): samples = [] # Average a few samples for i in range(N): print( f'\r{Fore.YELLOW}Capture {n}{Style.RESET_ALL}: {100*(i+1)/N:.0f}%', end='') _, data = monitor_socket.blocking_read() sample = data['intensities'] samples.append(uarray(sample['nom'], sample['std'])) print(f' [{Fore.GREEN}SAVED{Style.RESET_ALL}]') spectrum = sum(samples) / len(samples) print(time.time(), format_array(nom(spectrum)), format_array(std(spectrum)), file=f) if DURATION is not None and time.monotonic( ) - start_time > DURATION * 3600: break
async def run_publisher(): print('Initializing devices...') pressure_gauge = FRG730() thermometers = [(CTC100(31415), ['saph', 'coll', 'bott hs', 'cell'], ['heat saph', 'heat coll']), (CTC100(31416), ['srb4k', 'srb45k', '45k plate', '4k plate'], ['srb45k out', 'srb4k out'])] labjack = Labjack('470022275') mfc = MFC(31417) wm = WM( publish=False ) #wavemeter class used for reading frequencies from high finesse wavemeter pt = PulseTube() camera = Camera(1) camera.init() try: camera.start() except: pass camera.GainAuto = 'Off' camera.Gain = 10 camera.ExposureAuto = 'Off' camera_publisher = create_server('camera') turbo = TurboPump() pt_last_off = time.monotonic() heaters_last_safe = time.monotonic() try: cbs_cam = Ximea(exposure=1e6) cbs_cam.set_roi(500, 500, 700, 700) except: cbs_cam = None print(f'{Fore.RED}ERROR: Ximea camera is unplugged!{Style.RESET_ALL}') cbs_publisher = create_server('cbs-camera') spectrometer_monitor = connect_to('spectrometer') print('Starting publisher') publisher_start = time.monotonic() loop = asyncio.get_running_loop() run_async = lambda f: loop.run_in_executor(None, f) try: with create_server('edm-monitor') as publisher: rough = {} trans = {} for loop_iteration in itertools.count(1): loop_start = time.monotonic() async_getters = [] times = {} ##### Read pressure gauge (Async) ##### chamber_pressure = None def pressure_getter(): nonlocal chamber_pressure, times with Timer('pressure', times): chamber_pressure = pressure_gauge.pressure async_getters.append(run_async(pressure_getter)) ##### Read CTC100 Temperatures + Heaters (Async) ##### temperatures = {} heaters = {} async def CTC_getter(thermometer): """Record data from the given thermometer.""" obj, temp_channels, heater_channels = thermometer with Timer(f'CTC{obj._address[1]}', times): for channel in temp_channels: temperatures[channel] = await obj.async_read( channel) for channel in heater_channels: heaters[channel] = await obj.async_read(channel) async_getters.extend( [CTC_getter(thermometer) for thermometer in thermometers]) ##### Read MFC Flows (Async) ##### flows = {} async def flow_getter(): """Record the flow rates from the MFC.""" with Timer('MFC', times): flows['cell'] = deconstruct( await mfc.async_get_flow_rate_cell()) flows['neon'] = deconstruct( await mfc.async_get_flow_rate_neon_line()) async_getters.append(flow_getter()) ##### Read wavemeter frequencies (Async) ##### frequencies = {} async def frequency_getter(): """Record the frequencies from the wavemeter.""" with Timer('wavemeter', times): frequencies['baf'] = await with_uncertainty( lambda: wm.read_frequency(8)) frequencies['calcium'] = await with_uncertainty( lambda: wm.read_frequency(6)) async_getters.append(frequency_getter()) ##### Read Camera (Async) ##### center = {} refl = {} png = {} def camera_getter(): camera_samples = [] with Timer('camera', times): exposure = camera.ExposureTime image = None while True: capture_start = time.monotonic() sample = camera.get_array() capture_time = time.monotonic() - capture_start camera_samples.append(fit_image(sample)) if image is None: image = sample # Clear buffer (force new acquisition) if capture_time > 20e-3: break # Track fringes fringe_model.update(image, exposure) center_x, center_y, cam_refl, saturation = [ unweighted_mean(arr) for arr in np.array(camera_samples).T ] cam_refl *= 1500 / exposure # Downsample if 16-bit if isinstance(image[0][0], np.uint16): image = (image / 256 + 0.5).astype(np.uint8) # Save images png['raw'] = cv2.imencode('.png', image)[1].tobytes() png['fringe'] = cv2.imencode( '.png', fringe_model.scaled_pattern)[1].tobytes() png['fringe-annotated'] = cv2.imencode( '.png', fringe_model.annotated_pattern)[1].tobytes() # Store data center['x'] = deconstruct(center_x) center['y'] = deconstruct(center_y) center['saturation'] = deconstruct(saturation) center['exposure'] = exposure refl['cam'] = deconstruct(2 * cam_refl) refl['ai'] = deconstruct(fringe_model.reflection) if saturation.n > 99: camera.ExposureTime = exposure // 2 if saturation.n < 30: camera.ExposureTime = exposure * 2 async_getters.append(run_async(camera_getter)) ##### Read turbo status (Async) ##### pt_on = pt.is_on() running = {'pt': pt_on} async def turbo_getter(): """Record the operational status of the turbo pump.""" with Timer('turbo', times): status = await turbo.async_operation_status() running['turbo'] = (status == 'normal') async_getters.append(turbo_getter()) ##### Read labjack (Async) ##### intensities = {} def labjack_getter(): with Timer('labjack', times): intensities['broadband'] = deconstruct( labjack.read('AIN0')) # intensities['hene'] = deconstruct(labjack.read('AIN1')) intensities['LED'] = deconstruct(labjack.read('AIN2')) async_getters.append(run_async(labjack_getter)) # Await all async data getters. # Tasks will run simultaneously. gather_task = asyncio.gather(*async_getters) try: await asyncio.wait_for(gather_task, timeout=15) except: raise ValueError(gather_task.exception()) ##### Read CBS camera (Sync) ##### cbs_png = None cbs_info = {'data': None, 'fit': None} with Timer('CBS Camera', times): if cbs_cam is not None and cbs_cam.capture(): cbs_png = cv2.imencode('.png', cbs_cam.image)[1].tobytes() try: r, I, (peak, width, background), chisq = fit_cbs(cbs_cam.image) cbs_info['data'] = { 'radius': list(r), 'intensity': { 'nom': list(nom(I)), 'std': list(std(I)), } } if max(width.s, peak.s) > 100 or min(width.n, peak.n) < 0: raise ValueError cbs_info['fit'] = { 'peak': deconstruct(peak), 'width': deconstruct(width), 'background': deconstruct(background), 'chisq': chisq, } except: pass # Read spectrometer thread. _, spec_data = spectrometer_monitor.grab_json_data() if spec_data is not None: rough = spec_data['rough'] trans = spec_data['trans'] rough['hdr-chisq'] = spec_data['fit']['chisq'] ### Update models ### saph_temp = temperatures['saph'] growth_model.update(ufloat(*flows['neon']), ufloat(*flows['cell']), saph_temp) fringe_counter.update(refl['ai'][0], grow=(growth_model._growth_rate.n > 0)) if saph_temp > 13: fringe_counter.reset() # Construct final data packet times['loop'] = round(1e3 * (time.monotonic() - loop_start)) uptime = (time.monotonic() - publisher_start) / 3600 data_dict = { 'pressure': deconstruct(chamber_pressure), 'flows': flows, 'temperatures': temperatures, 'heaters': heaters, 'center': center, 'cbs': cbs_info['fit'], 'rough': rough, 'trans': trans, 'refl': refl, 'fringe': { 'count': fringe_counter.fringe_count, 'ampl': fringe_counter.amplitude, }, 'model': { 'height': deconstruct(growth_model.height), }, 'freq': frequencies, 'intensities': intensities, 'running': running, 'debug': { 'times': times, 'uptime': uptime if loop_iteration > 1 else None, 'memory': memory_usage(), 'system-memory': round(psutil.virtual_memory().used / 1024), 'cpu': psutil.cpu_percent(), } } print_tree(data_dict) ### Limit publishing speed ### target_end = PUBLISH_INTERVAL * loop_iteration + publisher_start time.sleep(max(target_end - time.monotonic(), 0)) publisher.send(data_dict) camera_publisher.send(png) if cbs_png is not None: cbs_publisher.send({ 'image': cbs_png, **cbs_info, }) print() print() # Restart if pressure gauge cuts out if data_dict['pressure'] is None: pressure_gauge.close() pressure_gauge = FRG730() finally: print( f'{Fore.RED}{Style.BRIGHT}Crashed, cleaning up...{Style.RESET_ALL}' ) tb = traceback.format_exc() print(tb) print('Stopping fringe camera...') camera.stop() camera.close() camera_publisher.close() print('Stopping CBS camera...') cbs_cam.close() cbs_publisher.close() print('Stopping miscellaneous equipment...') pressure_gauge.close() mfc.close() turbo.close() print('Done.')