Esempio n. 1
0
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)
Esempio n. 2
0
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.')
Esempio n. 3
0
            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)
Esempio n. 4
0
    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()
Esempio n. 5
0

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
Esempio n. 6
0
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.')