Beispiel #1
0
    def modify_document(self, doc):
        self.tb.lock()
        sink = bokehgui.vec_sink_f_proc(self.tb.get_num_channels(), "", 1)
        self.tb.connect((self.mag_to_zW, 0), (sink, 0))
        self.tb.unlock()

        log_cds = ColumnDataSource(data=self.lw.get_table())
        blw = BokehLogWatcher(doc, log_cds)
        logging.getLogger().addHandler(blw)

        def cleanup_session(session_context):
            self.tb.lock()
            self.tb.disconnect((self.mag_to_zW, 0), (sink, 0))
            self.tb.unlock()
            logging.getLogger().removeHandler(blw)

        doc.on_session_destroyed(cleanup_session)

        doc.title = "Gal Scan GUI"

        plot_lst = []

        plot = vec_sink_f(doc, plot_lst, sink, is_message=False)

        plot.initialize(update_time=100, legend_list=[''])
        plot.get_figure().aspect_ratio = 2
        plot.set_y_axis([0, 10])
        plot.set_y_label("Power at feed (zW / Hz)")
        plot.set_x_label("Frequency (MHz)")

        def set_x_values():
            plot.set_x_values(
                np.linspace(
                    self.tb.get_sdr_frequency() -
                    (self.tb.get_output_vector_bandwidth() / 2),
                    self.tb.get_sdr_frequency() +
                    (self.tb.get_output_vector_bandwidth() / 2),
                    self.tb.get_num_channels()) / 1e6)

        set_x_values()
        plot.enable_axis_labels(True)
        plot.set_layout(1, 0)
        plot.enable_max_hold()
        plot.format_line(0, "blue", 1, "solid", None, 1.0)

        azimuth = Knob(title="Azimuth", max=360, min=0, unit="°")
        elevation = Knob(title="Elevation", max=360, min=0, unit="°")
        rx_power = Knob(title="Average RX Power",
                        digits=4,
                        decimals=1,
                        unit="dB(mW/Hz)")
        plot.stream.js_on_change(
            "streaming",
            CustomJS(
                args=dict(rx_power=rx_power),
                code="""
            const data = cb_obj.data
            const average = data['y0'].reduce((a,b) => a+b)/data['y0'].length
            rx_power.value = (10*Math.log10(average))-180
            """,
            ))

        log_table = SortedDataTable(
            source=log_cds,
            columns=[
                TableColumn(field="asctime", title="Time", width=140),
                TableColumn(field="levelname", title="Level", width=60),
                TableColumn(field="message", title="Message", width=1500),
            ],
            autosize_mode="none",
            aspect_ratio=2,
            sizing_mode="stretch_width",
            sortable=True,
        )

        gain = Slider(title="gain",
                      value=self.tb.get_sdr_gain(),
                      start=0,
                      end=65)
        gain.on_change('value', lambda name, old, new: self.set_gain(new))

        rx = ActiveButton(label="RX enabled")
        rx.on_click(lambda: self.set_rx(not rx.active))

        frequency = Knob(title="center frequency",
                         writable=True,
                         value=self.tb.get_sdr_frequency(),
                         digits=10,
                         decimals=0,
                         unit="Hz")
        frequency.on_change('value',
                            lambda name, old, new: self.set_frequency(new))

        bandwidth = Knob(title="filter bandwidth",
                         writable=False,
                         value=self.tb.get_bandwidth(),
                         digits=7,
                         decimals=0,
                         unit="Hz")
        bandwidth.on_change('value',
                            lambda name, old, new: self.set_bandwidth(new))

        reset = Button(label="Reset")

        def on_reset():
            gain.value = run.flowgraph_defaults['sdr_gain']
            frequency.value = run.flowgraph_defaults['sdr_frequency']
            bandwidth.value = run.flowgraph_defaults['bandwidth']

        reset.on_click(on_reset)

        manual = Panel(title="Manual",
                       child=column(
                           row(rx, gain),
                           row(frequency, bandwidth),
                           reset,
                       ))

        run_models = {}
        automated_panels = []
        for group, args in run.arg_groups.items():
            # TODO: show grouping
            panel_models = []
            for key, arg in args.items():
                key = key.replace('-', '_')
                bokeh_args = arg.get('bokeh', {})
                bokeh_args['name'] = key
                bokeh_args['tags'] = ['args']
                if 'default' in arg:
                    bokeh_args['value'] = arg['default']
                if 'help' in arg:
                    bokeh_args['title'] = arg['help']
                    if 'metavar' in arg:
                        bokeh_args['title'] += " (%s)" % (arg['metavar'])
                type = TextInput
                if arg.get('type') in (float, int):
                    type = Spinner
                    if 'bokeh' in arg and 'start' in arg[
                            'bokeh'] and 'end' in arg['bokeh']:
                        type = Slider
                    if 'step' not in bokeh_args:
                        if arg['type'] == int:
                            bokeh_args['step'] = 1
                        else:
                            bokeh_args['step'] = 0.01
                    if arg.get('metavar') == 'Hz':
                        if 'digits' not in bokeh_args:
                            bokeh_args['digits'] = 10
                            if bokeh_args.get('max'):
                                bokeh_args['digits'] = len("%d" %
                                                           bokeh_args['max'])
                        type = functools.partial(Knob,
                                                 decimals=0,
                                                 unit=arg['metavar'])
                        del bokeh_args['step']
                        del bokeh_args['tags']
                        if 'writable' not in bokeh_args:
                            bokeh_args['writable'] = True
                elif 'choices' in arg:
                    type = Select
                    bokeh_args['options'] = [str(x) for x in arg['choices']]
                    if 'value' in bokeh_args:
                        bokeh_args['value'] = str(bokeh_args['value'])
                elif arg.get('action') in ('store_true', 'store_false'):
                    type = Select
                    bokeh_args['options'] = [('0', 'False'), ('1', 'True')]
                    bokeh_args['value'] = str(int(bokeh_args['value']))
                    bokeh_args['tags'] = ['boolean'] + bokeh_args.get(
                        'tags', [])
                if group.startswith("mode="):
                    # Make this smarter if we ever have a mode=gal tab
                    bokeh_args['disabled'] = True
                m = type(**bokeh_args)
                run_models[key] = m
                panel_models.append(m)
            automated_panels.append(
                Panel(title=group, child=grid(panel_models, ncols=2)))
        for panel in automated_panels:
            if panel.title.startswith("mode="):
                mode_str = panel.title.split('=')[1]
                run_models['mode'].js_on_change(
                    'value',
                    CustomJS(
                        args=dict(panel=panel, mode=mode_str),
                        code=
                        """panel.select(Bokeh.require("models/widgets/control").Control).forEach(c => c.disabled = (this.value != mode))""",
                    ))

        plan_p = Paragraph(sizing_mode="stretch_width", )

        load = UploadButton(name="load-settings",
                            accept=".json,application/json",
                            label="Load settings")

        def on_load(attr, old, new):
            data = json.loads(base64.b64decode(new))
            for key, value in data.items():
                if isinstance(run_models[key], Select):
                    value = str(value)
                run_models[key].value = value

        load.on_change('value', on_load)

        save = DownloadButton(label="Save settings",
                              filename="gal_scan_settings.json",
                              mime_type="application/json",
                              data=CustomJS(args=dict(run_models=run_models),
                                            code="""
                const out = {}
                for (let k in run_models) {
                  if (!run_models[k].disabled) {
                    out[k] = run_models[k].value
                    const tags = run_models[k].tags
                    if (tags && tags.indexOf("boolean") >= 0) {
                      out[k] = parseInt(out[k])
                    }
                  }
                }
                return JSON.stringify(out, null, 2);
                """))
        start = Button(label="Start scan")

        def get_args(output_dir):
            return run.parse_args(
                [output_dir],
                {
                    k: int(v.value) if "boolean" in v.tags else v.value
                    for k, v in run_models.items() if not v.disabled
                },
            )

        def on_start():
            try:
                output_dir = os.path.join(
                    self.runs_dir, "run_" +
                    datetime.datetime.now().replace(microsecond=0).isoformat())
                args = get_args(output_dir)
                self.enqueue_run(args)
            except SystemExit:
                pass

        start.on_click(on_start)
        automated = Panel(title="Plan",
                          child=column(Tabs(tabs=automated_panels), plan_p,
                                       row(load, save, start)))

        # TODO: Show cancel buttons for active or queued actions
        queue_cds = ColumnDataSource(data=self.get_queue_data())
        action_column = ActionMenuColumn(
            field="id",
            title="Action",
            menu=[
                ("Cancel", "cancel"),
            ],
        )

        def on_action_menu_click(event):
            if event.item == "cancel":
                self.cancel_action(event.value)
            else:
                logging.warn("Unknown action clicked: %s", event.item)

        action_column.on_event(ActionMenuClick, on_action_menu_click)
        queue_table = SortedDataTable(
            source=queue_cds,
            columns=[
                TableColumn(
                    field="time",
                    title="Time",
                    formatter=DateFormatter(format="%Y-%m-%d %H:%M:%S"),
                ),
                TableColumn(field="user", title="User"),
                TableColumn(field="name", title="Job"),
                action_column,
            ],
            highlight_field="active",
            sort_ascending=True,
            autosize_mode="fit_viewport",
            aspect_ratio=2,
            sizing_mode="stretch_width",
        )
        queue = Panel(title="Queue", child=queue_table)

        results_cds = ColumnDataSource(data={"name": [], "mtime": []})
        results_table = SortedDataTable(
            source=results_cds,
            columns=[
                TableColumn(
                    field="mtime",
                    title="Time",
                    formatter=DateFormatter(format="%Y-%m-%d %H:%M:%S"),
                ),
                TableColumn(
                    field="name",
                    title="Name",
                    formatter=HTMLTemplateFormatter(
                        template=
                        '<a href="/runs/<%= value %>/" target="_blank"><%= value %></a>'
                    )),
            ],
            autosize_mode="fit_viewport",
            aspect_ratio=2,
            sizing_mode="stretch_width",
            sortable=True,
        )
        results = Panel(title="Results", child=results_table)

        tabs = Tabs(tabs=[manual, automated, queue, results])

        status_p = Paragraph(sizing_mode="stretch_width", )

        controls = column(row(azimuth, elevation, rx_power), status_p, tabs,
                          log_table)

        def get_survey_data():
            pointers = {
                'ra': [],
                'dec': [],
                'label': [],
                'colour': [],
            }
            for o in self.messier:
                pointers['ra'].append(o['ra'])
                pointers['dec'].append(o['dec'])
                pointers['label'].append(o['label'])
                pointers['colour'].append('')
            survey = self.active_action.get('survey')
            out = {
                'pointers': pointers,
                'status_message': 'Idle',
                'plan_message': 'Invalid parameters'
            }
            if survey:
                groups = survey.coord_groups
                i = 0
                for sc, colour in zip(reversed(groups),
                                      ('rgb(0, 192, 0)', 'rgb(192, 0, 0)')):
                    sc = sc.icrs
                    for sc in sc:
                        pointers['ra'].append(sc.ra.to(u.degree).value)
                        pointers['dec'].append(sc.dec.to(u.degree).value)
                        pointers['label'].append(str(i + 1))
                        pointers['colour'].append(colour)
                        i += 1
                out['status_message'] = 'Time remaining on current survey: %s' % (
                    survey.time_remaining.to_datetime())
            survey = None
            try:
                survey = run.Survey(get_args('bogus'))
                out['plan_message'] = 'Estimated runtime: %s' % (
                    survey.time_remaining.to_datetime())
                if tabs.tabs[tabs.active] == automated:
                    # TODO: Use the underlying numpy arrays
                    sc = survey.iterator.coords_now.icrs
                    for i, sc in enumerate(sc[:1000]):
                        pointers['ra'].append(sc.ra.to(u.degree).value)
                        pointers['dec'].append(sc.dec.to(u.degree).value)
                        pointers['label'].append(str(i + 1))
                        pointers['colour'].append('rgb(148,0,211)')
            except:
                logging.getLogger('stderr').exception('Invalid parameters')
            return out

        sd = get_survey_data()
        pointers_cds = ColumnDataSource(data=sd['pointers'])

        def update_pointers(attr, old, new):
            logging.debug('Updating pointers')
            sd = get_survey_data()
            pointers_cds.data = sd['pointers']
            plan_p.text = sd['plan_message']
            status_p.text = sd['status_message']

        update_pointers(None, None, None)

        log_cds.on_change('data', update_pointers)
        tabs.on_change('active', update_pointers)
        for m in run_models.values():
            m.on_change('value', update_pointers)

        skymap = Skymap(
            height=600,
            sizing_mode="stretch_height",
            pointer_data_source=pointers_cds,
        )
        skymap.on_event(Tap, lambda event: self.point(event.x, event.y))

        doc.add_root(row(
            column(
                skymap,
                plot.get_figure(),
            ),
            controls,
        ), )

        async def update_status(last_status={}):
            set_x_values()
            status = self.client.status
            skymap.latlon = (status['Latitude'], status['Longitude'])
            skymap.azel = (status['AzPos'], status['ElPos'])
            if status['CommandAzFlags'] == 'POSITION' or status[
                    'CommandElFlags'] == 'POSITION':
                skymap.targetAzel = (status['CommandAzPos'],
                                     status['CommandElPos'])
            else:
                skymap.targetAzel = None
            azimuth.value = status['AzPos']
            elevation.value = status['ElPos']
            rx_active = status['Sequencer']['Bands'][0]['CommandRX']
            if not last_status or rx_active != last_status['Sequencer'][
                    'Bands'][0]['CommandRX']:
                if rx_active:
                    rx.label = "RX enabled"
                else:
                    rx.label = "RX disabled (50Ω load)"
                rx.active = rx_active
            queue_data = self.get_queue_data()
            if queue_cds.data != queue_data:
                queue_cds.data = queue_data
            with os.scandir(self.runs_dir) as it:
                files = list(
                    sorted(it, reverse=True, key=lambda f: f.stat().st_mtime))
                results_data = {
                    "name": [f.name for f in files],
                    "mtime": [int(f.stat().st_mtime * 1000) for f in files],
                }
                if results_data != results_cds.data:
                    results_cds.data = results_data
            last_status.update(status)

        doc.add_periodic_callback(update_status, 200)
Beispiel #2
0
    update_legend_color_bar(select_feature.value, day)


def update_src_after_day_change(attr, old, new):
    day = ts_to_day(new)
    geosource.geojson = create_sample(day).to_json()


# def update_label_figures_after_feature_change(attr, old, new):
#     label_figures.text = new


TOOLTIPS = [('Область', '@ADM1_UA'),
            (select_feature.value, '@{' + str(select_feature.value) + '}')]

plot.add_tools(HoverTool(tooltips=TOOLTIPS))

tabs.on_change('active', update_tabs)

select_feature.on_change('value', update_color_mapper_and_legend_color_bar_after_feature_change)
select_feature.on_change('value', update_tooltips_after_feature_change)
select_feature.js_link('value', plot.title, 'text')

# select_feature.on_change('value', update_label_figures_after_feature_change)

slider_time.on_change('value_throttled', update_src_after_day_change)
slider_time.on_change('value_throttled', update_color_mapper_and_legend_color_bar_after_day_change)


curdoc().add_root(column(tabs))
curdoc().title = 'Ukraine | Hospitals | Supply'
Beispiel #3
0
def create():
    doc = curdoc()
    config = pyzebra.AnatricConfig()

    def _load_config_file(file):
        config.load_from_file(file)

        logfile_textinput.value = config.logfile
        logfile_verbosity.value = config.logfile_verbosity

        filelist_type.value = config.filelist_type
        filelist_format_textinput.value = config.filelist_format
        filelist_datapath_textinput.value = config.filelist_datapath
        filelist_ranges_textareainput.value = "\n".join(
            map(str, config.filelist_ranges))

        crystal_sample_textinput.value = config.crystal_sample
        lambda_textinput.value = config.crystal_lambda
        zeroOM_textinput.value = config.crystal_zeroOM
        zeroSTT_textinput.value = config.crystal_zeroSTT
        zeroCHI_textinput.value = config.crystal_zeroCHI
        ub_textareainput.value = config.crystal_UB

        dataFactory_implementation_select.value = config.dataFactory_implementation
        if config.dataFactory_dist1 is not None:
            dataFactory_dist1_textinput.value = config.dataFactory_dist1
        if config.dataFactory_dist2 is not None:
            dataFactory_dist2_textinput.value = config.dataFactory_dist2
        if config.dataFactory_dist3 is not None:
            dataFactory_dist3_textinput.value = config.dataFactory_dist3
        reflectionPrinter_format_select.value = config.reflectionPrinter_format

        if config.algorithm == "adaptivemaxcog":
            algorithm_params.active = 0
            threshold_textinput.value = config.threshold
            shell_textinput.value = config.shell
            steepness_textinput.value = config.steepness
            duplicateDistance_textinput.value = config.duplicateDistance
            maxequal_textinput.value = config.maxequal
            aps_window_textinput.value = str(
                tuple(map(int, config.aps_window.values())))

        elif config.algorithm == "adaptivedynamic":
            algorithm_params.active = 1
            adm_window_textinput.value = str(
                tuple(map(int, config.adm_window.values())))
            border_textinput.value = str(
                tuple(map(int, config.border.values())))
            minWindow_textinput.value = str(
                tuple(map(int, config.minWindow.values())))
            reflectionFile_textinput.value = config.reflectionFile
            targetMonitor_textinput.value = config.targetMonitor
            smoothSize_textinput.value = config.smoothSize
            loop_textinput.value = config.loop
            minPeakCount_textinput.value = config.minPeakCount
            displacementCurve_textinput.value = "\n".join(
                map(str, config.displacementCurve))

        else:
            raise ValueError("Unknown processing mode.")

    def upload_button_callback(_attr, _old, new):
        with io.BytesIO(base64.b64decode(new)) as file:
            _load_config_file(file)

    upload_div = Div(text="Open .xml config:")
    upload_button = FileInput(accept=".xml", width=200)
    upload_button.on_change("value", upload_button_callback)

    # General parameters
    # ---- logfile
    def logfile_textinput_callback(_attr, _old, new):
        config.logfile = new

    logfile_textinput = TextInput(title="Logfile:", value="logfile.log")
    logfile_textinput.on_change("value", logfile_textinput_callback)

    def logfile_verbosity_callback(_attr, _old, new):
        config.logfile_verbosity = new

    logfile_verbosity = TextInput(title="verbosity:", width=70)
    logfile_verbosity.on_change("value", logfile_verbosity_callback)

    # ---- FileList
    def filelist_type_callback(_attr, _old, new):
        config.filelist_type = new

    filelist_type = Select(title="File List:",
                           options=["TRICS", "SINQ"],
                           width=100)
    filelist_type.on_change("value", filelist_type_callback)

    def filelist_format_textinput_callback(_attr, _old, new):
        config.filelist_format = new

    filelist_format_textinput = TextInput(title="format:", width=290)
    filelist_format_textinput.on_change("value",
                                        filelist_format_textinput_callback)

    def filelist_datapath_textinput_callback(_attr, _old, new):
        config.filelist_datapath = new

    filelist_datapath_textinput = TextInput(title="datapath:")
    filelist_datapath_textinput.on_change(
        "value", filelist_datapath_textinput_callback)

    def filelist_ranges_textareainput_callback(_attr, _old, new):
        ranges = []
        for line in new.splitlines():
            ranges.append(re.findall(r"\b\d+\b", line))
        config.filelist_ranges = ranges

    filelist_ranges_textareainput = TextAreaInput(title="ranges:", rows=1)
    filelist_ranges_textareainput.on_change(
        "value", filelist_ranges_textareainput_callback)

    # ---- crystal
    def crystal_sample_textinput_callback(_attr, _old, new):
        config.crystal_sample = new

    crystal_sample_textinput = TextInput(title="Sample Name:", width=290)
    crystal_sample_textinput.on_change("value",
                                       crystal_sample_textinput_callback)

    def lambda_textinput_callback(_attr, _old, new):
        config.crystal_lambda = new

    lambda_textinput = TextInput(title="lambda:", width=100)
    lambda_textinput.on_change("value", lambda_textinput_callback)

    def ub_textareainput_callback(_attr, _old, new):
        config.crystal_UB = new

    ub_textareainput = TextAreaInput(title="UB matrix:", height=100)
    ub_textareainput.on_change("value", ub_textareainput_callback)

    def zeroOM_textinput_callback(_attr, _old, new):
        config.crystal_zeroOM = new

    zeroOM_textinput = TextInput(title="zeroOM:", width=100)
    zeroOM_textinput.on_change("value", zeroOM_textinput_callback)

    def zeroSTT_textinput_callback(_attr, _old, new):
        config.crystal_zeroSTT = new

    zeroSTT_textinput = TextInput(title="zeroSTT:", width=100)
    zeroSTT_textinput.on_change("value", zeroSTT_textinput_callback)

    def zeroCHI_textinput_callback(_attr, _old, new):
        config.crystal_zeroCHI = new

    zeroCHI_textinput = TextInput(title="zeroCHI:", width=100)
    zeroCHI_textinput.on_change("value", zeroCHI_textinput_callback)

    # ---- DataFactory
    def dataFactory_implementation_select_callback(_attr, _old, new):
        config.dataFactory_implementation = new

    dataFactory_implementation_select = Select(
        title="DataFactory implement.:",
        options=DATA_FACTORY_IMPLEMENTATION,
        width=145,
    )
    dataFactory_implementation_select.on_change(
        "value", dataFactory_implementation_select_callback)

    def dataFactory_dist1_textinput_callback(_attr, _old, new):
        config.dataFactory_dist1 = new

    dataFactory_dist1_textinput = TextInput(title="dist1:", width=75)
    dataFactory_dist1_textinput.on_change(
        "value", dataFactory_dist1_textinput_callback)

    def dataFactory_dist2_textinput_callback(_attr, _old, new):
        config.dataFactory_dist2 = new

    dataFactory_dist2_textinput = TextInput(title="dist2:", width=75)
    dataFactory_dist2_textinput.on_change(
        "value", dataFactory_dist2_textinput_callback)

    def dataFactory_dist3_textinput_callback(_attr, _old, new):
        config.dataFactory_dist3 = new

    dataFactory_dist3_textinput = TextInput(title="dist3:", width=75)
    dataFactory_dist3_textinput.on_change(
        "value", dataFactory_dist3_textinput_callback)

    # ---- BackgroundProcessor

    # ---- DetectorEfficency

    # ---- ReflectionPrinter
    def reflectionPrinter_format_select_callback(_attr, _old, new):
        config.reflectionPrinter_format = new

    reflectionPrinter_format_select = Select(
        title="ReflectionPrinter format:",
        options=REFLECTION_PRINTER_FORMATS,
        width=145,
    )
    reflectionPrinter_format_select.on_change(
        "value", reflectionPrinter_format_select_callback)

    # Adaptive Peak Detection (adaptivemaxcog)
    # ---- threshold
    def threshold_textinput_callback(_attr, _old, new):
        config.threshold = new

    threshold_textinput = TextInput(title="Threshold:", width=145)
    threshold_textinput.on_change("value", threshold_textinput_callback)

    # ---- shell
    def shell_textinput_callback(_attr, _old, new):
        config.shell = new

    shell_textinput = TextInput(title="Shell:", width=145)
    shell_textinput.on_change("value", shell_textinput_callback)

    # ---- steepness
    def steepness_textinput_callback(_attr, _old, new):
        config.steepness = new

    steepness_textinput = TextInput(title="Steepness:", width=145)
    steepness_textinput.on_change("value", steepness_textinput_callback)

    # ---- duplicateDistance
    def duplicateDistance_textinput_callback(_attr, _old, new):
        config.duplicateDistance = new

    duplicateDistance_textinput = TextInput(title="Duplicate Distance:",
                                            width=145)
    duplicateDistance_textinput.on_change(
        "value", duplicateDistance_textinput_callback)

    # ---- maxequal
    def maxequal_textinput_callback(_attr, _old, new):
        config.maxequal = new

    maxequal_textinput = TextInput(title="Max Equal:", width=145)
    maxequal_textinput.on_change("value", maxequal_textinput_callback)

    # ---- window
    def aps_window_textinput_callback(_attr, _old, new):
        config.aps_window = dict(
            zip(("x", "y", "z"), re.findall(r"\b\d+\b", new)))

    aps_window_textinput = TextInput(title="Window (x, y, z):", width=145)
    aps_window_textinput.on_change("value", aps_window_textinput_callback)

    # Adaptive Dynamic Mask Integration (adaptivedynamic)
    # ---- window
    def adm_window_textinput_callback(_attr, _old, new):
        config.adm_window = dict(
            zip(("x", "y", "z"), re.findall(r"\b\d+\b", new)))

    adm_window_textinput = TextInput(title="Window (x, y, z):", width=145)
    adm_window_textinput.on_change("value", adm_window_textinput_callback)

    # ---- border
    def border_textinput_callback(_attr, _old, new):
        config.border = dict(zip(("x", "y", "z"), re.findall(r"\b\d+\b", new)))

    border_textinput = TextInput(title="Border (x, y, z):", width=145)
    border_textinput.on_change("value", border_textinput_callback)

    # ---- minWindow
    def minWindow_textinput_callback(_attr, _old, new):
        config.minWindow = dict(
            zip(("x", "y", "z"), re.findall(r"\b\d+\b", new)))

    minWindow_textinput = TextInput(title="Min Window (x, y, z):", width=145)
    minWindow_textinput.on_change("value", minWindow_textinput_callback)

    # ---- reflectionFile
    def reflectionFile_textinput_callback(_attr, _old, new):
        config.reflectionFile = new

    reflectionFile_textinput = TextInput(title="Reflection File:", width=145)
    reflectionFile_textinput.on_change("value",
                                       reflectionFile_textinput_callback)

    # ---- targetMonitor
    def targetMonitor_textinput_callback(_attr, _old, new):
        config.targetMonitor = new

    targetMonitor_textinput = TextInput(title="Target Monitor:", width=145)
    targetMonitor_textinput.on_change("value",
                                      targetMonitor_textinput_callback)

    # ---- smoothSize
    def smoothSize_textinput_callback(_attr, _old, new):
        config.smoothSize = new

    smoothSize_textinput = TextInput(title="Smooth Size:", width=145)
    smoothSize_textinput.on_change("value", smoothSize_textinput_callback)

    # ---- loop
    def loop_textinput_callback(_attr, _old, new):
        config.loop = new

    loop_textinput = TextInput(title="Loop:", width=145)
    loop_textinput.on_change("value", loop_textinput_callback)

    # ---- minPeakCount
    def minPeakCount_textinput_callback(_attr, _old, new):
        config.minPeakCount = new

    minPeakCount_textinput = TextInput(title="Min Peak Count:", width=145)
    minPeakCount_textinput.on_change("value", minPeakCount_textinput_callback)

    # ---- displacementCurve
    def displacementCurve_textinput_callback(_attr, _old, new):
        maps = []
        for line in new.splitlines():
            maps.append(re.findall(r"\d+(?:\.\d+)?", line))
        config.displacementCurve = maps

    displacementCurve_textinput = TextAreaInput(
        title="Displ. Curve (2θ, x, y):", width=145, height=100)
    displacementCurve_textinput.on_change(
        "value", displacementCurve_textinput_callback)

    def algorithm_tabs_callback(_attr, _old, new):
        if new == 0:
            config.algorithm = "adaptivemaxcog"
        else:
            config.algorithm = "adaptivedynamic"

    algorithm_params = Tabs(tabs=[
        Panel(
            child=column(
                row(threshold_textinput, shell_textinput, steepness_textinput),
                row(duplicateDistance_textinput, maxequal_textinput,
                    aps_window_textinput),
            ),
            title="Peak Search",
        ),
        Panel(
            child=column(
                row(adm_window_textinput, border_textinput,
                    minWindow_textinput),
                row(reflectionFile_textinput, targetMonitor_textinput,
                    smoothSize_textinput),
                row(loop_textinput, minPeakCount_textinput,
                    displacementCurve_textinput),
            ),
            title="Dynamic Integration",
        ),
    ])
    algorithm_params.on_change("active", algorithm_tabs_callback)

    def process_button_callback():
        with tempfile.TemporaryDirectory() as temp_dir:
            temp_file = temp_dir + "/config.xml"
            config.save_as(temp_file)
            pyzebra.anatric(temp_file,
                            anatric_path=doc.anatric_path,
                            cwd=temp_dir)

            with open(os.path.join(temp_dir, config.logfile)) as f_log:
                output_log.value = f_log.read()

            with open(os.path.join(temp_dir,
                                   config.reflectionPrinter_file)) as f_res:
                output_res.value = f_res.read()

    process_button = Button(label="Process", button_type="primary")
    process_button.on_click(process_button_callback)

    output_log = TextAreaInput(title="Logfile output:",
                               height=320,
                               width=465,
                               disabled=True)
    output_res = TextAreaInput(title="Result output:",
                               height=320,
                               width=465,
                               disabled=True)
    output_config = TextAreaInput(title="Current config:",
                                  height=320,
                                  width=465,
                                  disabled=True)

    general_params_layout = column(
        row(column(Spacer(height=2), upload_div), upload_button),
        row(logfile_textinput, logfile_verbosity),
        row(filelist_type, filelist_format_textinput),
        filelist_datapath_textinput,
        filelist_ranges_textareainput,
        row(crystal_sample_textinput, lambda_textinput),
        ub_textareainput,
        row(zeroOM_textinput, zeroSTT_textinput, zeroCHI_textinput),
        row(
            dataFactory_implementation_select,
            dataFactory_dist1_textinput,
            dataFactory_dist2_textinput,
            dataFactory_dist3_textinput,
        ),
        row(reflectionPrinter_format_select),
    )

    tab_layout = row(
        general_params_layout,
        column(output_config, algorithm_params, row(process_button)),
        column(output_log, output_res),
    )

    async def update_config():
        output_config.value = config.tostring()

    doc.add_periodic_callback(update_config, 1000)

    return Panel(child=tab_layout, title="hdf anatric")
Beispiel #4
0
def extensionsDropdownChanged(event):
    global extension
    extension = event.item


extensionsDropdown.on_event(MenuItemClick, extensionsDropdownChanged)


# Tabs
def panelActive(attr, old, new):
    global automatico, primer_ciclo
    '''
    Get excecuted when the other tab is selected
    Changes the operation mode if a tab is changed
    '''
    if tabs.active == 0:
        automatico = True
        primer_ciclo = True
    elif tabs.active == 1:
        automatico = False
        voltageV1.value = cliente.valvulas['valvula1'].get_value()
        voltageV2.value = cliente.valvulas['valvula2'].get_value()


tabs.on_change('active', panelActive)
''' ******************** Curdoc ******************** '''

curdoc().add_root(tabs)
curdoc().title = 'Experiencia 1: Control de Procesos'
curdoc().add_periodic_callback(MainLoop, 150)
Beispiel #5
0
class EphemerisApp:

    to_seconds = dict(Day=86400, Hour=3600, Minute=60, Second=1)

    def __init__(self):

        # app variables
        self.active = True
        self.playAnimation = None
        self.start_epoch = None
        self.stop_epoch = None
        self.current_epoch = None

        # get initial configuration
        self.available_models = inspect.getmembers(StandardEphemerisModels,
                                                   inspect.isfunction)
        self.ephemeris_model = self.available_models[0][1]()
        self.spice_provider = SpiceProvider()
        self.spice_provider.SPICE_IDS = self.ephemeris_model.objects
        self.spice_provider.SPICE_NAMES = {
            v: k
            for k, v in self.ephemeris_model.objects.items()
        }

        # init data sources
        self.plot_source = self.spice_provider.state_source
        self.table_source = self.spice_provider.ephemeris_source
        self.cum_source = self.spice_provider.cum_source

        # gather options from ephemeris model and spice provider
        self.allowed_models = {
            model[1]().name: model[1]
            for model in self.available_models
        }
        allowed_objects = [
            self.spice_provider.fromId(name)
            for name in self.ephemeris_model.objects
        ]
        allowed_frames = self.ephemeris_model.FRAMES
        allowed_corrections = [name for name in SpiceProvider.CORRECTIONS]
        allowed_durations = [
            str(v) for v in self.ephemeris_model.DURATION_DAYS
        ]
        allowed_intervals = [name for name in SpiceProvider.INTERVALS]

        # set up widgets
        self.model = Select(title="Ephemeris Model",
                            options=list(self.allowed_models.keys()))

        self.center = Select(title="Center",
                             value=self.ephemeris_model.center,
                             options=allowed_objects)

        self.target = Select(title="Target",
                             value=self.ephemeris_model.target,
                             options=allowed_objects)

        self.frames = Select(title="Frame",
                             value=self.ephemeris_model.frame,
                             options=allowed_frames)

        self.planes = RadioButtonGroup(labels=['XY', 'YZ', 'XZ'], active=0)

        self.vector = Select(title='Vector Type',
                             value=self.ephemeris_model.vector_type,
                             options=allowed_corrections)

        self.epoch = DatePicker(title="Select Epoch",
                                value=datetime.strftime(
                                    self.ephemeris_model.epoch, "%Y-%m-%d"))

        self.offset = Slider(title="Days Since Epoch",
                             value=self.ephemeris_model.offset,
                             start=0,
                             end=self.ephemeris_model.duration,
                             step=1)

        self.duration = Select(title="Duration (Days)",
                               value=str(self.ephemeris_model.duration),
                               options=allowed_durations)

        self.interval = Select(title="Time Step",
                               value=str(self.ephemeris_model.step_size),
                               options=allowed_intervals)

        # create buttons
        self.play_button = Button(label="Play")
        self.exportRange = Div(text="Start and Stop Epoch: ")
        self.update_button = Button(label="Play")
        self.export_button = Button(label="Export")

        self.infoDiv = Div(
            text=
            "<hr>All ephemeris data shown on this website was obtained from publicly available "
            "SPICE files located at <a href='https://naif.jpl.nasa.gov/naif/data.html'>"
            "https://naif.jpl.nasa.gov/naif/data.html</a>, which is hosted by the  "
            "Navigation and Ancillary Information Facility (NAIF) at the NASA Jet Propulsion "
            "Laboratory. The exception is the SPICE kernel for the Parker Solar Probe, which is "
            "available at <a href='https://sppgway.jhuapl.edu/ancil_products'>"
            "https://sppgway.jhuapl.edu/ancil_products</a>, hosted by the Johns Hopkins University "
            "Applied Physics Laboratory. SpiceyPy is being used to process the SPICE files.",
            sizing_mode='stretch_width')

        # create plot tab objects
        self.plot = figure(match_aspect=True,
                           sizing_mode="stretch_both",
                           title="Astropynamics",
                           tools="hover, pan, reset, save",
                           tooltips=[("name", "@index")])

        self.plot.add_tools(BoxZoomTool(match_aspect=True))
        self.plot.circle('px',
                         'py',
                         size='radii',
                         source=self.plot_source,
                         line_width=3,
                         line_alpha=0.5,
                         name='XY')
        self.plot.circle('px',
                         'pz',
                         size='radii',
                         source=self.plot_source,
                         line_width=3,
                         line_alpha=0.5,
                         name='XZ').visible = False
        self.plot.circle('py',
                         'pz',
                         size='radii',
                         source=self.plot_source,
                         line_width=3,
                         line_alpha=0.5,
                         name='YZ').visible = False
        self.plot.line('px',
                       'py',
                       source=self.cum_source,
                       line_width=2,
                       line_alpha=0.5,
                       color='red',
                       name='XYOrbit')
        self.plot.line('px',
                       'pz',
                       source=self.cum_source,
                       line_width=2,
                       line_alpha=0.5,
                       color='red',
                       name='XZOrbit').visible = False
        self.plot.line('py',
                       'pz',
                       source=self.cum_source,
                       line_width=2,
                       line_alpha=0.5,
                       color='red',
                       name='YZOrbit').visible = False

        self.plotLayout = column(self.plot,
                                 self.offset,
                                 sizing_mode="stretch_width")
        self.plotTab = Panel(child=self.plotLayout, title="Display")

        # create data table tab objects
        fmt = NumberFormatter(format='0.000', text_align=TextAlign.right)
        columns = [
            TableColumn(field="index",
                        title="Epoch",
                        formatter=DateFormatter(format="%m/%d/%Y %H:%M:%S")),
            TableColumn(field="px", title="PX", formatter=fmt, width=10),
            TableColumn(field="py", title="PY", formatter=fmt),
            TableColumn(field="pz", title="PZ", formatter=fmt),
            TableColumn(field="vx", title="VX", formatter=fmt),
            TableColumn(field="vy", title="VY", formatter=fmt),
            TableColumn(field="vz", title="VZ", formatter=fmt)
        ]

        self.ephemerisTable = DataTable(source=self.table_source,
                                        columns=columns,
                                        sizing_mode="stretch_both")
        self.ephemerisLayout = column(self.exportRange,
                                      self.ephemerisTable,
                                      sizing_mode="stretch_width")
        self.dataTab = Panel(child=self.ephemerisLayout, title="Table")

        self.kernels = Div()
        self.kernelTab = Panel(child=self.kernels, title="Kernels")

        self.tabs = Tabs(tabs=[self.plotTab, self.dataTab, self.kernelTab])

        # init data
        self.model.value = "The Solar System"
        self.update_model(None, 0, self.model.value)
        self.update_epochs(None, 0, 0)
        self.update_states(None, 0, 0)

        self.model.on_change('value', self.update_model)
        self.frames.on_change('value', self.update_epochs)
        self.planes.on_change('active', self.update_plot_view)
        self.center.on_change('value', self.update_epochs)
        self.target.on_change('value', self.update_epochs)
        self.offset.on_change('value', self.update_offset)
        self.epoch.on_change('value', self.update_epochs)
        self.duration.on_change('value', self.update_epochs)
        self.interval.on_change('value', self.update_epochs)
        self.update_button.on_click(self.update_onclick)
        self.tabs.on_change('active', self.update_button_type)

        self.inputs = column(self.model, self.frames, self.planes, self.center,
                             self.target, self.epoch, self.duration,
                             self.interval, self.update_button)

    def get_layout(self):
        return column(row([self.inputs, self.tabs]),
                      self.infoDiv,
                      sizing_mode='stretch_width')

    def update_kenerls_tab(self):
        kernels = self.spice_provider.fetch_kernels()
        kernel_text = "<h3>Loaded Spice Kernels:</h3>\n"
        kernel_text += '<table>\n'
        for k in kernels:
            kernel_text += f"<tr><td><b>{k[1]}&emsp;&emsp;</b></td><td>{k[0].split('/')[-1]}</td></tr>\n"
        self.kernels.text = kernel_text + "</table>"

    def update_model(self, attr, old, new):

        # disable callbacks
        self.active = False

        # update model and load new kernel
        self.ephemeris_model = self.allowed_models[new]()
        self.spice_provider.set_meta_kernel(self.ephemeris_model.kernel)
        self.spice_provider.setSpiceIds(self.ephemeris_model.objects)

        self.update_kenerls_tab()

        # set widget values
        allowed_objects = [
            self.spice_provider.fromId(name)
            for name in self.ephemeris_model.objects
        ]
        allowed_frames = self.ephemeris_model.FRAMES
        allowed_durations = [
            str(v) for v in self.ephemeris_model.DURATION_DAYS
        ]
        self.target.options = allowed_objects
        self.center.options = allowed_objects
        self.frames.options = allowed_frames
        self.duration.options = allowed_durations

        self.target.value = self.ephemeris_model.target
        self.center.value = self.ephemeris_model.center
        self.frames.value = self.ephemeris_model.frame
        self.planes.active = self.ephemeris_model.plane
        self.epoch.value = datetime.strftime(self.ephemeris_model.epoch,
                                             "%Y-%m-%d")
        self.duration.value = str(self.ephemeris_model.duration)
        self.offset.value = self.ephemeris_model.offset
        self.offset.end = self.ephemeris_model.duration
        self.interval.value = self.ephemeris_model.step_size

        # reinstate callbacks
        self.active = True

        # update start and stop epochs and plot
        self.update_epochs(None, 0, 0)

    def update_epochs(self, attr, old, new):

        self.start_epoch = datetime.strptime(self.epoch.value, "%Y-%m-%d")
        self.stop_epoch = self.start_epoch + \
                          pd.Timedelta(seconds=(int(float(self.duration.value) * EphemerisApp.to_seconds['Day'])))

        self.offset.value = 0
        self.offset.end = int(
            float(self.duration.value) * EphemerisApp.to_seconds['Day'] /
            EphemerisApp.to_seconds[self.interval.value])
        self.offset.title = f"{self.interval.value}s Since Epoch"
        self.exportRange.text = f"Showing epoch range:\t<b>{self.start_epoch} to {self.stop_epoch}</b>"

        self.update_offset(None, 0, 0)

    def update_offset(self, attr, old, new):

        scale_factor = EphemerisApp.to_seconds[self.interval.value]
        self.current_epoch = self.start_epoch + pd.Timedelta(
            seconds=(self.offset.value * scale_factor))

        if self.playAnimation is None:
            SpiceProvider.reset_source(self.spice_provider.cum_source)

        self.update_states(None, 0, 0)

    def update_ephemeris(self, attr, old, new):

        self.update_epochs(attr, old, new)

        self.spice_provider.set_center(self.center.value)
        self.spice_provider.frame = self.frames.value
        self.spice_provider.correction = SpiceProvider.CORRECTIONS[
            self.vector.value]

        if self.active:
            self.spice_provider.fetch_ephemeris_states(self.target.value,
                                                       self.start_epoch,
                                                       self.stop_epoch,
                                                       self.interval.value)

    def update_states(self, attr, old, new):

        self.spice_provider.set_center(self.center.value)
        self.spice_provider.frame = self.frames.value
        self.spice_provider.correction = SpiceProvider.CORRECTIONS[
            self.vector.value]

        if self.active:
            self.spice_provider.fetch_target_states(
                self.ephemeris_model.objects, self.current_epoch,
                self.target.value)

    def update_plot_view(self, attr, old, new):

        self.plot.select_one({"name": self.planes.labels[old]}).visible = False
        self.plot.select_one({"name": self.planes.labels[new]}).visible = True

        self.plot.select_one({
            "name": self.planes.labels[old] + "Orbit"
        }).visible = False
        self.plot.select_one({
            "name": self.planes.labels[new] + "Orbit"
        }).visible = True

    def animate_update(self):

        self.offset.value = 0 if self.offset.value > self.offset.end else self.offset.value + 1
        if self.offset.value == 0:
            SpiceProvider.reset_source(self.spice_provider.cum_source)

    def animate(self, start=True):
        if self.update_button.label == 'Play' and start:
            self.update_button.label = 'Pause'
            self.playAnimation = curdoc().add_periodic_callback(
                self.animate_update, 50)
        elif self.playAnimation is not None:
            self.update_button.label = 'Play'
            curdoc().remove_periodic_callback(self.playAnimation)
            self.playAnimation = None

    def update_onclick(self):
        if self.tabs.active == 0:
            self.animate()
        elif self.tabs.active == 1:
            self.update_ephemeris(None, 0, 0)
        elif self.tabs.active == 2:
            self.update_kenerls_tab()

    def update_button_type(self, attr, old, new):
        self.animate(False)
        if self.tabs.active == 0:
            self.update_button.label = "Play"
        else:
            self.update_button.label = "Update"
            self.update_ephemeris(None, 0, 0)