async def on_b_set_picowatt_config(self, sid, config):
        with db.connection_context():
            ConfigurationParameter.overwrite_config_value(
                'picowatt_delay', config['Delay'])

        await self.cryo_namespace.on_c_get_picowatt_delay(1)
        await self.cryo_namespace.config_avs47b(config)
    async def on_c_got_temperatures(self, sid, temperatures):
        # Keep track of how many temperatures we have received
        self.received_temperatures += 1

        # Ensure a connection to the database
        with db.connection_context():
            # Check if we want to save the temperatures
            if ConfigurationParameter.read_config_value('is_saving_cryo_temperatures') and \
                self.received_temperatures % ConfigurationParameter.read_config_value('save_every_n_temperatures') == 0:
                # Save the temperatures
                TemperatureDataPoint(
                    cryo_data_point=1,
                    t_upper_hex=temperatures['t_upper_hex'],
                    t_lower_hex=temperatures['t_lower_hex'],
                    t_he_pot=temperatures['t_he_pot'],
                    t_1st_stage=temperatures['t_1st_stage'],
                    t_2nd_stage=temperatures['t_2nd_stage'],
                    t_inner_coil=temperatures['t_inner_coil'],
                    t_outer_coil=temperatures['t_outer_coil'],
                    t_switch=temperatures['t_switch'],
                    t_he_pot_2=temperatures['t_he_pot_2'],
                    t_still=temperatures['t_still'],
                    t_mixing_chamber_1=temperatures['t_mixing_chamber_1'],
                    t_mixing_chamber_2=temperatures['t_mixing_chamber_2']
                ).save()

                # Reset the counter so we don't get very large numbers (there is no need)
                self.received_temperatures = 1

        # Actually send the temperatures
        await self.browser_namespace.send_temperatures(temperatures)
    async def on_c_got_step_results(self, sid, results):
        with db.connection_context():
            # Get the datapoint associated with the step (should be generated when step is sent)
            datapoint = DataPoint.select().where(
                DataPoint.step == results['step_id']).order_by(
                    DataPoint.created).get()

            # Then we save the datapoint
            if datapoint is not None:
                datapoint.save_cryo_data(results)
예제 #4
0
    def on_disconnect(self, sid):
        with db.connection_context():
            try:
                # Find the type and remove from the connected clients list
                session = Session.get(Session.sid == sid)
                self.remove_client_from_all_namespaces(sid, session.type)

                # Alert the user to the disconnect
                print(session.type, 'disconnected')
            except Session.DoesNotExist:
                print('disconnect ', sid)
    async def on_b_get_n_points_total(self, sid):
        with db.connection_context():
            if ExperimentConfiguration.select().count() > 0:
                # get the latest config from the database
                latest_config = ExperimentConfiguration.select().order_by(
                    ExperimentConfiguration.id.desc()).get()

                # Compute the number of points taken
                n_points_total = ExperimentStep.select() \
                    .where(ExperimentStep.experiment_configuration == latest_config.id) \
                    .count()

                # Send it to the user
                await self.emit('b_n_points_total', n_points_total, room=sid)
예제 #6
0
    async def on_mark_step_as_done(self, sid, step):
        # Add the id of the step to the done list
        step_id = step['id']
        self.steps_done.append(step_id)

        # Check if the step is done both places
        if self.magnetism_namespace.is_step_done(
                step_id) and self.cryo_namespace.is_step_done(step_id):
            # Both are done, so we should mark it as done in the database
            with db.connection_context():
                ExperimentStep.update(step_done=True).where(
                    ExperimentStep.id == step_id).execute()

            # Next we should push the next step to the clients (if applicable)
            await self.browser_namespace.push_next_step_to_clients()
    async def on_b_set_experiment_config(self, sid, data):
        with db.connection_context():
            # First we get the session of the current user
            user = Session.get(Session.sid == sid)

            # Parse out the numbers from the client
            data['sr830_sensitivity'] = float(data['sr830_sensitivity'])
            data['sr830_frequency'] = float(data['sr830_frequency'])
            data['sr830_buffersize'] = int(data['sr830_buffersize'])
            data['n9310a_sweep_steps'] = int(data['n9310a_sweep_steps'])
            data['n9310a_min_frequency'] = float(data['n9310a_min_frequency'])
            data['n9310a_max_frequency'] = float(data['n9310a_max_frequency'])
            data['n9310a_min_amplitude'] = float(data['n9310a_min_amplitude'])
            data['n9310a_max_amplitude'] = float(data['n9310a_max_amplitude'])
            data['magnet_min_field'] = float(data['magnet_min_field'])
            data['magnet_max_field'] = float(data['magnet_max_field'])
            data['magnet_sweep_steps'] = int(data['magnet_sweep_steps'])
            data['oscope_resistor'] = 84.5  # Not configurable any more
            data['data_wait_before_measuring'] = float(
                data['data_wait_before_measuring'])
            data['data_points_per_measurement'] = int(
                data['data_points_per_measurement'])

            # Save the new configuration
            ec = ExperimentConfiguration.create(**data, created_by_id=user)
            ec.save()

            # Set all previous steps to be done
            ExperimentStep.update(step_done=True).where(
                ExperimentStep.step_done == False).execute()

            # Generate a new set of steps
            n_steps = ec.generate_steps()

            # Alert the user
            print(f'Generated {n_steps} new steps')

            # Push new configuration to all users
            await self.emit('b_latest_experiment_config', data)
            await self.emit('b_experiment_configuration_saved', room=sid)

            # Push next step to client
            await self.push_next_step_to_clients()
    async def on_b_get_experiment_list(self, sid, data):
        # Grab the page we want
        page = data['page']

        # Open connection to database
        with db.connection_context():
            # Count number of experiments
            experiment_count = ExperimentConfiguration.select().count()

            # If no experiments exist, we send that to the client, otherwise we paginate
            experiments = []
            if experiment_count > 0:
                # Paginate the experiments
                experiments = list(ExperimentConfiguration \
                                   .select() \
                                   .order_by(ExperimentConfiguration.id.desc()) \
                                   .paginate(page, 10) \
                                   .dicts())

            # Parse the dates out
            # Add number of datapoints collected
            # Add the total number of datapoints in the run
            for e in experiments:
                e['created'] = e['created'].isoformat()

                # Compute the number of points taken
                e['n_points_taken'] = ExperimentStep.select() \
                    .where(ExperimentStep.experiment_configuration == e['id']) \
                    .where(ExperimentStep.step_done == True) \
                    .count()

                # Compute the number of points taken
                e['n_points_total'] = ExperimentStep.select() \
                    .where(ExperimentStep.experiment_configuration == e['id']) \
                    .count()

            await self.emit('b_got_experiment_list', {
                'list': experiments,
                'count': experiment_count,
                'page': page
            })
예제 #9
0
    async def on_idn(self, sid, data):
        # Figure out what type of client we have
        client_type = data.split('_')[0]
        is_old = 'Old'

        # Connect to the database
        with db.connection_context():
            # Register sid with session
            try:
                # First check if the session exists, then we update
                Session.get(Session.idn == data).update(sid=sid).where(
                    Session.idn == data).execute()
            except Session.DoesNotExist:
                # if it does not exist, we just create it
                Session.create(idn=data, sid=sid, type=client_type).save()
                is_old = 'New'

        # Add the connection to a category for easy lookup
        self.add_client_to_all_namespaces(sid, client_type)

        print(f'{is_old} client connected with idn: {data}, and sid: {sid}')
    async def on_b_get_latest_experiment_config(self, sid):
        experiment_config = get_default_experiment_configuration()

        with db.connection_context():
            if ExperimentConfiguration.select().count() > 0:
                # Use the config from the database
                latest_config = ExperimentConfiguration.select().order_by(
                    ExperimentConfiguration.id.desc()).get()
                experiment_config['sr830_sensitivity'] = float(
                    latest_config.sr830_sensitivity)
                experiment_config['sr830_frequency'] = float(
                    latest_config.sr830_frequency)
                experiment_config['sr830_buffersize'] = int(
                    latest_config.sr830_buffersize)
                experiment_config['n9310a_sweep_steps'] = int(
                    latest_config.n9310a_sweep_steps)
                experiment_config['n9310a_min_frequency'] = float(
                    latest_config.n9310a_min_frequency)
                experiment_config['n9310a_max_frequency'] = float(
                    latest_config.n9310a_max_frequency)
                experiment_config['n9310a_min_amplitude'] = float(
                    latest_config.n9310a_min_amplitude)
                experiment_config['n9310a_max_amplitude'] = float(
                    latest_config.n9310a_max_amplitude)
                experiment_config['magnet_min_field'] = float(
                    latest_config.magnet_min_field)
                experiment_config['magnet_max_field'] = float(
                    latest_config.magnet_max_field)
                experiment_config['magnet_sweep_steps'] = int(
                    latest_config.magnet_sweep_steps)
                experiment_config['oscope_resistor'] = float(
                    latest_config.oscope_resistor)
                experiment_config['data_wait_before_measuring'] = float(
                    latest_config.data_wait_before_measuring)
                experiment_config['data_points_per_measurement'] = int(
                    latest_config.data_points_per_measurement)

        await self.emit('b_latest_experiment_config',
                        experiment_config,
                        room=sid)
예제 #11
0
    async def get_next_step(self):
        with db.connection_context():
            try:
                # Get the next step
                step = ExperimentStep.select().where(
                    ExperimentStep.step_done == False).order_by(
                        ExperimentStep.id).first()

                # Check if the step is none, and skip to the catch clause if it is
                if step is None:
                    raise DoesNotExist('Step does not exist')

                # Check if the step has an associated datapoint
                if DataPoint.select().where(
                        ExperimentStep == step).count() < 1:
                    step.generate_datapoint()

                # Convert step to dict
                step_d = model_to_dict(step)

                # Set the experiment id (different from the step id)
                step_d['experiment_configuration_id'] = step_d[
                    'experiment_configuration']['id']

                # Remove datetime and experiment configuration from the dict
                # They are not needed in the client, and they are not directly serializable to json (due to missing datetime format)
                del (step_d['created'])
                del (step_d['experiment_configuration'])

                # Return the step if it exists
                return step_d
            # Check if the step even exists
            except DoesNotExist:
                # It is OK if it does not exist, we should just stop measuring
                print('No more steps ready')

                # Return None if no step exists
                return None
 async def on_c_get_picowatt_delay(self, sid):
     # Grab the delay from the config database and send it to the client
     with db.connection_context():
         picowatt_delay = ConfigurationParameter.read_config_value(
             'picowatt_delay')
         await self.emit('c_got_picowatt_delay', picowatt_delay)
 async def on_b_get_is_saving_temperatures(self, sid):
     with db.connection_context():
         saving = ConfigurationParameter.read_config_value(
             'is_saving_cryo_temperatures')
         await self.emit('b_got_is_saving_temperatures', saving)
예제 #14
0
async def export_data(request):
    # Check id exists
    if 'id' not in request.query:
        return web.Response(text='Could not find the requested id',
                            content_type='text/html')

    # Grab the id
    config_id = request.query['id']

    # Now we want to start the export
    # Open connection to database
    with db.connection_context():
        # Grab the configuration first
        ecl = ExperimentConfiguration.select().where(
            ExperimentConfiguration.id == config_id).dicts()

        # Check if we have a result
        if len(ecl) > 0:
            # Grab the first result (There should only be one when we query by id)
            ec = ecl[0]

            # Convert date format
            ec['created'] = ec['created'].isoformat()

            # Compute the number of points taken
            ec['n_points_taken'] = ExperimentStep.select() \
                .where(ExperimentStep.experiment_configuration == ec['id']) \
                .where(ExperimentStep.step_done == True) \
                .count()

            # Compute the number of points taken
            ec['n_points_total'] = ExperimentStep.select() \
                .where(ExperimentStep.experiment_configuration == ec['id']) \
                .count()

            # Add an empty array to contain steps
            ec['steps'] = []

            # Now we're done processing the configuration
            # Next we get all the datapoints that were saved
            # We start by iterating over all the steps in the experiment
            for step in ExperimentStep.select().where(
                    ExperimentStep.experiment_configuration ==
                    ec['id']).dicts():
                # Convert date format
                step['created'] = step['created'].isoformat()

                # Add an empty array to contain datapoints
                step['datapoints'] = []

                # And we iterate through all the datapoints for the step
                for dp in DataPoint.select().where(
                        DataPoint.step == step['id']):
                    # Create a dict to contain the collected information
                    datapoint_dict = {
                        'id': dp.id,
                        'created': dp.created.isoformat(),
                        'magnetism_datapoints': [],
                        'temperature_datapoints': [],
                        'pressure_datapoints': []
                    }

                    # Next we find the magnetism datapoint
                    for mdp in MagnetismDataPoint.select().where(
                            MagnetismDataPoint.datapoint == dp):
                        # For this we find the magnetism measurements (where we actually store the data)
                        mdps = MagnetismMeasurement.select().where(
                            MagnetismMeasurement.magnetism_data_point == mdp)

                        # Save it to the datapoint dict
                        for magnetism_datapoint in list(mdps.dicts()):
                            datapoint_dict['magnetism_datapoints'].append(
                                magnetism_datapoint)

                    # And we find the cryodatapoint
                    for cdp in CryogenicsDataPoint.select().where(
                            CryogenicsDataPoint.datapoint == dp):
                        # Similarly we find pressure and temperature datapoints
                        pdps = PressureDataPoint.select().where(
                            PressureDataPoint.cryo_data_point == cdp)
                        tdps = TemperatureDataPoint.select().where(
                            TemperatureDataPoint.cryo_data_point == cdp)

                        # Save them to the datapoint dict
                        for pressure_datapoint in list(pdps.dicts()):
                            datapoint_dict['pressure_datapoints'].append(
                                pressure_datapoint)

                        for temperature_datapoint in list(tdps.dicts()):
                            # Convert date format
                            temperature_datapoint[
                                'created'] = temperature_datapoint[
                                    'created'].isoformat()

                            # Append the temperature
                            datapoint_dict['temperature_datapoints'].append(
                                temperature_datapoint)

                    # Save the datapoint to the step
                    step['datapoints'].append(datapoint_dict)

                # Save the step to the configuration
                ec['steps'].append(step)

            # And finally we send the response data
            return web.json_response(
                headers={'Content-Disposition': f'Attachment'},
                body=json.dumps(ec))
        else:
            return web.Response(text='Attempted to export ' + str(config_id) +
                                ' but no such config found',
                                content_type='text/html')
예제 #15
0
async def plot_saved_temperatures(request):
    # Open connection to database
    with db.connection_context():
        # Create a timedelta for the query (based on the config)
        period_delta = datetime.timedelta(
            hours=ConfigurationParameter.read_config_value('max_timeperiod'))
        period = datetime.datetime.today() - period_delta

        # Get the temperatures
        temperatures = TemperatureDataPoint\
            .select()\
            .where(TemperatureDataPoint.created > period)\
            .order_by(TemperatureDataPoint.created)\
            .dicts()

        # Determine the shape of the arrays in our output
        if len(temperatures) > 0:
            temp_shape = (len(temperatures), 1)
        else:
            temp_shape = (1, 1)

        # Create empty arrays to hold the data
        times = np.zeros(shape=temp_shape)
        t_upper_hex = np.zeros(shape=temp_shape)
        t_lower_hex = np.zeros(shape=temp_shape)
        t_he_pot = np.zeros(shape=temp_shape)
        t_1st_stage = np.zeros(shape=temp_shape)
        t_2nd_stage = np.zeros(shape=temp_shape)
        t_inner_coil = np.zeros(shape=temp_shape)
        t_outer_coil = np.zeros(shape=temp_shape)
        t_switch = np.zeros(shape=temp_shape)
        t_he_pot_2 = np.zeros(shape=temp_shape)
        t_still = np.zeros(shape=temp_shape)
        t_mixing_chamber_1 = np.zeros(shape=temp_shape)
        t_mixing_chamber_2 = np.zeros(shape=temp_shape)

        # Sort the data into the relevant arrays
        for idx, t_obj in enumerate(temperatures):
            times[idx] = t_obj['created'].timestamp(
            )  # Convert the datetime to seconds
            t_upper_hex[idx] = t_obj['t_upper_hex']
            t_lower_hex[idx] = t_obj['t_lower_hex']
            t_he_pot[idx] = t_obj['t_he_pot']
            t_1st_stage[idx] = t_obj['t_1st_stage']
            t_2nd_stage[idx] = t_obj['t_2nd_stage']
            t_inner_coil[idx] = t_obj['t_inner_coil']
            t_outer_coil[idx] = t_obj['t_outer_coil']
            t_switch[idx] = t_obj['t_switch']
            t_he_pot_2[idx] = t_obj['t_he_pot_2']
            t_still[idx] = t_obj['t_still']
            t_mixing_chamber_1[idx] = t_obj['t_mixing_chamber_1']
            t_mixing_chamber_2[idx] = t_obj['t_mixing_chamber_2']

        # Create the plot
        plt.subplots(figsize=(8, 3.5))

        # Plot the data
        plt.plot(times, t_upper_hex, label='Upper HEx')
        plt.plot(times, t_lower_hex, label='Lower HEx')
        plt.plot(times, t_he_pot, label='He Pot')
        plt.plot(times, t_he_pot_2, label='He Pot CCS')
        plt.plot(times, t_1st_stage, label='1st stage')
        plt.plot(times, t_2nd_stage, label='2nd stage')
        plt.plot(times, t_inner_coil, label='Inner coil')
        plt.plot(times, t_outer_coil, label='Outer coil')
        plt.plot(times, t_switch, label='Switch')
        plt.plot(times, t_still, label='Still')
        plt.plot(times, t_mixing_chamber_1, label='Mixing chamber 1')
        plt.plot(times, t_mixing_chamber_2, label='Mixing chamber 2')

        # Pretty up the plot
        plt.xlabel('Time [seconds]')
        plt.ylabel('Temperature [kelvin]')
        plt.grid()
        plt.legend(loc='lower left')
        plt.tight_layout()

        # Save the plot to a buffer
        buffer = io.BytesIO()
        plt.savefig(buffer, format='png', dpi=100)
        plt.close()

        # Reset the buffer placement, and send the response
        buffer.seek(0)
        return web.Response(body=buffer,
                            headers={
                                'Content-Type': 'image/png',
                                'Cache-Control': 'max-age=0,no-store'
                            })
예제 #16
0
        return web.Response(body=buffer,
                            headers={
                                'Content-Type': 'image/png',
                                'Cache-Control': 'max-age=0,no-store'
                            })


# Setup the http routes
app.router.add_static('/static', 'static')
app.router.add_get('/export', export_data)
app.router.add_get('/get_plot', plot_saved_temperatures)
app.router.add_get('/', index)

if __name__ == '__main__':
    # Ensure the database tables are created
    with db.connection_context():
        db.create_tables([
            Session, ExperimentConfiguration, ExperimentStep, StationStatus,
            DataPoint, MagnetismDataPoint, MagnetismMeasurement,
            CryogenicsDataPoint, PressureDataPoint, TemperatureDataPoint,
            ConfigurationParameter
        ])

    # Create a default configuration object
    default_config = default_config_parameters.get_default_configuration_parameters(
    )

    # Now we load any missing keys into the database
    for key in default_config.keys():
        ConfigurationParameter.read_config_value(key, default_config[key])
 async def on_b_end_save_temperatures(self, sid):
     with db.connection_context():
         ConfigurationParameter.overwrite_config_value(
             'is_saving_cryo_temperatures', False)
         await self.emit('b_got_is_saving_temperatures', False)
 async def got_picowatt_config(self, config):
     with db.connection_context():
         config['Delay'] = ConfigurationParameter.read_config_value(
             'picowatt_delay')
         await self.emit('b_got_picowatt_config', config)