Ejemplo n.º 1
0
def view():
    info = Label("Select a parcel to display.")

    temppath = config.get_value(['paths', 'temp'])
    datapath = config.get_value(['paths', 'data'])

    method = ToggleButtons(options=[('From local storage', 0),
                                    ('Remote to memory', 1)],
                           value=0,
                           description='',
                           disabled=True,
                           button_style='info',
                           tooltips=[
                               'View data that are stored on the local drive.',
                               'View data from memory.'
                           ])

    paths = RadioButtons(options=[
        (f"Temporary folder: '{temppath}'.", temppath),
        (f"Personal data folder: '{datapath}'.", datapath)
    ],
                         layout={'width': 'max-content'},
                         value=temppath)

    paths_box = Box([Label(value="Select folder:"), paths])

    tables_first = [
        f for f in os.listdir(paths.value)
        if os.path.isdir(os.path.join(paths.value, f))
    ]

    select_table = Dropdown(
        options=[f for f in tables_first if not f.startswith('.')],
        value=None,
        description='Select tabe:',
        disabled=False,
    )

    select_option = RadioButtons(options=[(f"Single parcel selection.", 1),
                                          (f"Multiple parcels selection.", 2)],
                                 disabled=True,
                                 layout={'width': 'max-content'})

    button_refresh = Button(layout=Layout(width='35px'), icon='fa-refresh')

    select_option_box = HBox([
        select_table, button_refresh,
        Label(value="Selection method:"), select_option
    ])

    selection_single = Dropdown(
        options=[],
        value=None,
        description='Select parcel:',
        disabled=False,
    )

    selection_multi = SelectMultiple(
        options=[],
        value=[],
        description='Select parcels:',
        disabled=False,
    )

    view_method = ToggleButtons(
        options=[],
        value=None,
        description='',
        disabled=False,
        button_style='info',
        tooltips=[],
    )

    rm_parcel = Button(value=False,
                       disabled=False,
                       button_style='danger',
                       tooltip='Delete parcel data.',
                       icon='trash',
                       layout=Layout(width='35px'))

    code_info = Label()
    single_box = HBox([selection_single, rm_parcel])
    select_box = Box([single_box])

    method_0 = VBox([info, paths_box, select_option_box, select_box])
    method_1 = VBox([])
    view_box = Output(layout=Layout(border='1px solid black'))
    method_out = Output()
    with method_out:
        display(method_0)

    def method_options(obj):
        with method_out:
            method_out.clear_output()
            if obj['new'] == 0:
                display(method_0)
            elif obj['new'] == 1:
                display(method_1)

    method.observe(method_options, 'value')

    @button_refresh.on_click
    def button_refresh_on_click(b):
        view_box.clear_output()
        tables_first = [
            f for f in os.listdir(paths.value)
            if os.path.isdir(os.path.join(paths.value, f))
        ]
        select_table.options = [
            f for f in tables_first if not f.startswith('.')
        ]
        if select_table.value is not None:
            parcels = f"{paths.value}{select_table.value}"
            parcels_list = [
                f for f in os.listdir(parcels) if not f.startswith('.')
            ]
            selection_single.options = parcels_list
            selection_multi.options = parcels_list
        else:
            selection_single.options = []
            selection_single.value = None
            selection_multi.options = []
            selection_multi.value = []

    @rm_parcel.on_click
    def rm_parcel_on_click(b):
        try:
            parcel_to_rm = f"{paths.value}{select_table.value}/{selection_single.value}"
            try:
                shutil.rmtree(f'{parcel_to_rm}')
            except Exception:
                pass
            try:
                os.remove(f'{parcel_to_rm}')
            except Exception:
                pass
#             print(f"The parce: '{selection_single.value}' is deleted.")
            parcels = f"{paths.value}{select_table.value}"
            parcels_list = [
                f for f in os.listdir(parcels) if not f.startswith('.')
            ]
            selection_single.options = parcels_list
            view_box.clear_output()
        except Exception:
            pass

    def on_select_option_change(change):
        if select_option.value == 1:
            select_box.children = [single_box]
        else:
            select_box.children = [selection_multi]

    select_option.observe(on_select_option_change, 'value')

    def on_datapath_change(change):
        tables = [
            f for f in os.listdir(paths.value)
            if os.path.isdir(os.path.join(paths.value, f))
        ]
        tables = [f for f in tables if not f.startswith('.')]
        select_table.options = tables

    paths.observe(on_datapath_change, 'value')

    def on_table_change(change):
        if select_table.value is not None:
            parcels = f"{paths.value}{select_table.value}"
            parcels_list = [
                f for f in os.listdir(parcels) if not f.startswith('.')
            ]
            selection_single.options = parcels_list
            selection_multi.options = parcels_list
        else:
            selection_single.options = []
            selection_single.value = None
            selection_multi.options = []
            selection_multi.value = []
            view_method.options = []

    select_table.observe(on_table_change, 'value')

    def on_selection_change(obj):
        code_info.value = "Select how to view the dataset."
        options_list = [('Get example code', 1)]
        if obj['new'] is not None:
            parceldata = f"{paths.value}{select_table.value}/{selection_single.value}"
            data_list = [
                f for f in os.listdir(parceldata) if not f.startswith('.')
            ]
            if any("time_series" in s for s in data_list):
                options_list.append(('Plot time series', 2))
            if any("chip_images" in s for s in data_list):
                options_list.append(('View images', 3))
            options_list.append(("Show on map", 4))
            if select_option.value == 2:
                options_list.append(('Comparison', 5))
            view_method.options = options_list
            view_method.value = None

    selection_single.observe(on_selection_change, 'value')
    selection_multi.observe(on_selection_change, 'value')

    def method_options(obj):
        view_box.clear_output()
        with view_box:
            if selection_single.value is None:
                with view_box:
                    print("Please select a parcel")

            elif select_option.value == 1:
                data_path = f'{paths.value}{select_table.value}/{selection_single.value}/'
                if obj['new'] == 1:
                    from src.ipycbm.ui_view import view_code
                    display(view_code.code(data_path))
                elif obj['new'] == 2:
                    from src.ipycbm.ui_view import view_time_series
                    display(view_time_series.time_series(data_path))
                elif obj['new'] == 3:
                    from src.ipycbm.ui_view import view_calendar
                    display(view_calendar.calendar(data_path))
                elif obj['new'] == 4:
                    from src.ipycbm.ui_view import view_map
                    display(view_map.widget_box(data_path))

            elif select_option.value == 2 and len(selection_multi.value) > 0:
                data_path = f'{paths.value}{select_table.value}/'
                data_paths = [
                    f'{data_path}{s}/' for s in selection_multi.value
                ]
                if obj['new'] == 1:
                    from src.ipycbm.ui_view import view_code
                    display(view_code.code(data_paths[0]))
                    pass
                elif obj['new'] == 2:
                    from src.ipycbm.ui_view import view_time_series
                    # display(view_time_series.time_series(data_list[0]))
                    pass
                elif obj['new'] == 3:
                    from src.ipycbm.ui_view import view_calendar
                    # display(view_chip_images.calendar(data_path))
                    pass
                elif obj['new'] == 4:
                    from src.ipycbm.ui_view import view_maps
                    display(view_maps.with_polygons(data_paths))

    selection_single.observe(method_options, 'value')
    selection_multi.observe(method_options, 'value')
    view_method.observe(method_options, 'value')

    notes_info = Label("Add a note for the parcel")
    notes_bt = Button(value=False,
                      description='Add note',
                      disabled=False,
                      button_style='info',
                      tooltip='Add a note.',
                      icon='sticky-note')
    notes_box = VBox([])

    @notes_bt.on_click
    def notes_bt_on_click(b):
        if notes_box.children == ():
            notes_box.children = [
                view_notes.notes(f"{paths.value}{select_table.value}/",
                                 select_table.value,
                                 selection_single.value.replace('parcel_', ''))
            ]
        else:
            notes_box.children = []

    wbox = VBox([
        method_out, code_info, view_method, view_box,
        HBox([notes_info, notes_bt]), notes_box
    ])

    return wbox
Ejemplo n.º 2
0
def foi():
    path_plug = "cbm/foi/foi_db_func/"
    path_data = f"{config.get_value(['paths', 'temp'])}foi/"

    progress = Output()

    def outlog(*text):
        with progress:
            print(*text)

    foi_info = HTML(
        value="""FOI procedures need direct access to the database. <br>
        In case there no image is provided, access to object storage will be needed to generate the base image from sentinel images.
        """,
        placeholder='FOI Information',
    )

    # Connect to database
    db_info = Label(f"1. Connect to database and object storage.")
    db_select = Dropdown(options=[db for db in config.get_value(['db'])],
                         description='Configure:',
                         disabled=True,
                         layout=Layout(width='140px'))
    db_config = Button(value=False,
                       disabled=False,
                       button_style='info',
                       tooltip='Configure db connection.',
                       icon='cogs',
                       layout=Layout(width='40px'))
    db_box = HBox([db_select, db_config])

    parcels_table = RadioButtons(
        options=[('Upload .shp', 0), ('From database', 1)],
        #    value='pineapple', # Defaults to 'pineapple'
        #    layout={'width': 'max-content'}, # If the items' names are long
        #         description='Pizza topping:',
        disabled=False)
    par_box = HBox([])

    def on_parcels_table(method):
        if method.new == 0:
            par_box.children = []
        elif method.new == 1:
            par_box.children = []

    parcels_table.observe(on_parcels_table, 'value')

    # Generate or upload image.
    img_info = Label(
        f"3. Upload or generate raster base image. (Only upload is currently available)"
    )
    img_option = ToggleButtons(
        options=['Upload', 'Generate'],
        value=None,
        disabled=True,
        button_style='info',  # 'success', 'info', 'warning', 'danger' or ''
        tooltips=['Upnload your base image', 'Get from object storage'])

    img_dist_folder = Text(value=f"{path_data}raster/",
                           placeholder='tmp/',
                           description='Folder:',
                           disabled=False)
    img_select = FileUpload(
        description='Select file:',
        icon='plus',
        accept='.tif, .tiff',
        multiple=True  # True to accept multiple files upload else False
    )
    img_clear = Button(value=False,
                       disabled=False,
                       button_style='info',
                       tooltip='Clear selections.',
                       icon='broom',
                       layout=Layout(width='40px'))
    img_upload = Button(value=False,
                        disabled=False,
                        button_style='info',
                        tooltip='Upload foi base image (.tif)',
                        icon='fa-upload',
                        layout=Layout(width='40px'))

    img_box = HBox(
        [HBox([img_dist_folder, img_select, img_clear, img_upload])])

    # YAML File upload
    yml_select = FileUpload(description='Select file:',
                            icon='plus',
                            accept='.yml, .yaml, .txt',
                            multiple=False)
    yml_clear = Button(value=False,
                       disabled=False,
                       button_style='info',
                       tooltip='Clear selection.',
                       icon='broom',
                       layout=Layout(width='40px'))
    yml_upload = Button(value=False,
                        disabled=False,
                        button_style='info',
                        tooltip='Upload yaml file.',
                        icon='fa-upload',
                        layout=Layout(width='40px'))
    yml_box = HBox([yml_select, yml_clear, yml_upload])

    # Prepare procedures
    pre_info = Label("4. Prepare FOI procedure.")
    pre_ins_func = Button(value=False,
                          disabled=False,
                          button_style='info',
                          tooltip='Insert functions to database.',
                          icon='fa-share-square',
                          layout=Layout(width='40px'))
    pre_ins_func_box = HBox(
        [Label("Add functions to database:"), pre_ins_func])
    vector_file = Dropdown(
        options=[s for s in glob.glob(f'{path_data}vector/*') if '.shp' in s],
        description='Vector file:',
        disabled=False,
    )
    raster_file = Dropdown(
        options=[s for s in glob.glob(f'{path_data}raster/*') if '.tif' in s],
        description='Raster file:',
        disabled=False,
    )

    yaml_file = Dropdown(
        options=[s for s in glob.glob(f'{path_data}/*') if '.yml' in s],
        description='yaml file:',
        disabled=False,
    )

    # heterogeneity_threshold
    pre_heto_chec = HTML("""
    Minimum and maximum thresholds for heterogeneity checks. In the example,
    any parcel with percentage of pixels for one class between 30 and 70 from
    the total, will be considered heterogenous.
    """)
    pre_min_het = IntText(value=30,
                          description='MIN:',
                          tooltip="Minimum threshold for heterogeneity checks",
                          disabled=False,
                          layout=Layout(width='150px'))
    pre_max_het = IntText(value=70,
                          description='MAX:',
                          tooltip="Maximum threshold for heterogeneity checks",
                          disabled=False,
                          layout=Layout(width='150px'))
    pre_heto_chec_box = HBox([pre_min_het, pre_max_het])
    pre_min_area = IntText(value=2000,
                           description='area:',
                           tooltip="Minimum area for clusters selection.",
                           disabled=False,
                           layout=Layout(width='200px'))

    refresh_selections = Button(layout=Layout(width='35px'), icon='fa-refresh')

    pre_box = VBox([
        pre_info, pre_ins_func_box,
        HBox([Label("Select the requared files:"), refresh_selections]),
        HTML("""a. Spatial data to be tested - parcels that will
            be checked for heterogeneity and cardinality."""),
        HBox([vector_file]),
        HTML("""b. Thematic raster - classification raster, or raster 
            from other source that will be used for testing heterogeneity and cardinality."""
             ),
        HBox([raster_file]),
        HTML(
            """c. YAML file that holds the classes form the thematic raster file - 
            can be also a simple list of values in the notebook 
            corespondence between pixel values and names for the classes"""),
        HBox([yaml_file, yml_box]), pre_heto_chec, pre_heto_chec_box,
        HBox([
            pre_min_area,
            HTML(
                "Minimum area for clusters selection - only clusters bigger from this threshold will be counted."
            )
        ])
    ])

    # Run procedures
    run_info = Label("5. Run FOI procedure.")
    run_proc = Button(
        description='Run FOI procedure',
        value=False,
        disabled=False,
        button_style='info',
        tooltip='Run',
        icon='play',
    )
    run_box = HBox([run_proc])

    def on_img_option_change(change):
        if img_option.value == 'Upload':
            img_box.children = [
                HBox([img_dist_folder, img_select, img_clear, img_upload])
            ]
        else:
            img_box.children = ()

    img_option.observe(on_img_option_change, 'value')

    @refresh_selections.on_click
    def refresh_selections_on_click(b):
        vector_file.options = [
            s for s in glob.glob(f'{path_data}vector/*') if '.shp' in s
        ]
        raster_file.options = [
            s for s in glob.glob(f'{path_data}raster/*') if '.tif' in s
        ]
        yaml_file.options = [
            s for s in glob.glob(f'{path_data}/*') if '.yml' in s
        ]

    @img_clear.on_click
    def img_clear_on_click(b):
        img_select.value.clear()
        img_select._counter = 0

    @img_upload.on_click
    def img_upload_on_click(b):
        progress.clear_output()
        os.makedirs(img_dist_folder.value, exist_ok=True)
        for key in img_select.value:
            content = img_select.value[key]['content']
            with open(f'{img_dist_folder.value}{key}', 'wb') as f:
                f.write(content)
        outlog("All files are uploaded.")

    @yml_clear.on_click
    def yml_clear_on_click(b):
        yml_select.value.clear()
        yml_select._counter = 0

    @yml_upload.on_click
    def yml_upload_on_click(b):
        progress.clear_output()
        yml_dist_folder = f'{path_data}'
        os.makedirs(yml_dist_folder, exist_ok=True)
        for key in yml_select.value:
            content = yml_select.value[key]['content']
            with open(f'{yml_dist_folder}{key}', 'wb') as f:
                f.write(content)
        outlog("The yaml file is uploaded.")

    db_conf_box = HBox([])

    @db_config.on_click
    def db_config_on_click(b):
        if db_conf_box.children == ():
            db_conf_box.children = [settings.direct_conn()]
        else:
            db_conf_box.children = ()

    @pre_ins_func.on_click
    def pre_ins_func_on_click(b):
        progress.clear_output()
        try:
            functions = glob.glob(f"{path_plug}*.func")
            db = config.get_value(['set', 'db_conn'])
            sche = config.get_value(['db', db, 'conn', 'sche'])
            user = config.get_value(['db', db, 'conn', 'user'])

            for f in functions:
                database.insert_function(
                    open(f).read().format(schema=sche, owner=user))
            finc_list = [
                f"ipycbm_{f.split('/')[-1].split('.')[0]}, " for f in functions
            ]
            outlog(
                f"The functions: {('').join(finc_list)}where added to the database"
            )
        except Exception as err:
            outlog("Could not add functions to dattabase.", err)

    @run_proc.on_click
    def run_proc_on_click(b):
        with progress:
            foi_proc.proc(vector_file.value, raster_file.value,
                          yaml_file.value, pre_min_het.value,
                          pre_max_het.value, pre_min_area.value)

    wbox = VBox([
        foi_info, db_info, db_box, db_conf_box,
        proc_func.upload_shp(path_data), img_info, img_option, img_box,
        pre_box, run_info, run_box, progress
    ])

    return wbox
Ejemplo n.º 3
0
def foi_v2():
    path_data = f"{config.get_value(['paths', 'temp'])}foi/"

    progress = Output()

    def outlog(*text):
        with progress:
            print(*text)

    imp_refresh = Button(layout=Layout(width='35px'), icon='fa-refresh')

    foi_info = HTML(
        value=
        """FOI procedures version 2 does not need direct access to the database.
        """,
        placeholder='FOI Information',
    )

    # Generate or upload image.
    img_info = Label(
        f"3. Upload or generate raster base image. (Only upload is currently available)"
    )
    img_option = ToggleButtons(
        options=['Upload', 'Generate'],
        value=None,
        disabled=True,
        button_style='info',  # 'success', 'info', 'warning', 'danger' or ''
        tooltips=['Upnload your base image', 'Get from object storage'])

    img_dist_folder = Text(value=f"{path_data}raster/",
                           placeholder='tmp/',
                           description='Folder:',
                           disabled=False)
    img_select = FileUpload(
        description='Select file:',
        icon='plus',
        accept='.tif, .tiff',
        multiple=True  # True to accept multiple files upload else False
    )
    img_clear = Button(value=False,
                       disabled=False,
                       button_style='info',
                       tooltip='Upload foi reference data (.shp)',
                       icon='broom',
                       layout=Layout(width='40px'))
    img_upload = Button(value=False,
                        disabled=False,
                        button_style='info',
                        tooltip='Upload foi base image (.tif)',
                        icon='fa-upload',
                        layout=Layout(width='40px'))

    img_box = HBox(
        [HBox([img_dist_folder, img_select, img_clear, img_upload])])

    # YAML File upload
    yml_select = FileUpload(description='Select file:',
                            icon='plus',
                            accept='.yml, .yaml, .txt',
                            multiple=False)
    yml_clear = Button(value=False,
                       disabled=False,
                       button_style='info',
                       tooltip='Clear selection.',
                       icon='broom',
                       layout=Layout(width='40px'))
    yml_upload = Button(value=False,
                        disabled=False,
                        button_style='info',
                        tooltip='Upload yaml file.',
                        icon='fa-upload',
                        layout=Layout(width='40px'))
    yml_box = HBox([yml_select, yml_clear, yml_upload])

    # Prepare procedures
    pre_info = Label("4. Prepare FOI procedure.")
    vector_file = Dropdown(
        options=[s for s in glob.glob(f'{path_data}vector/*') if '.shp' in s],
        description='Vector file:',
        disabled=False,
    )
    raster_file = Dropdown(
        options=[s for s in glob.glob(f'{path_data}raster/*') if '.tif' in s],
        description='Raster file:',
        disabled=False,
    )
    yaml_file = Dropdown(
        options=[s for s in glob.glob(f'{path_data}/*') if '.yml' in s],
        description='yaml file:',
        disabled=False,
    )

    # heterogeneity_threshold
    pre_heto_chec = HTML("""
    Minimum and maximum thresholds for heterogeneity checks. In the example,
    any parcel with percentage of pixels for one class between 30 and 70 from
    the total, will be considered heterogenous.
    """)
    pre_min_het = IntText(value=30,
                          description='MIN:',
                          tooltip="Minimum threshold for heterogeneity checks",
                          disabled=False,
                          layout=Layout(width='150px'))
    pre_max_het = IntText(value=70,
                          description='MAX:',
                          tooltip="Maximum threshold for heterogeneity checks",
                          disabled=False,
                          layout=Layout(width='150px'))
    pre_heto_chec_box = HBox([pre_min_het, pre_max_het])
    pre_min_cluster_size = IntText(
        value=20,
        description='pixels:',
        tooltip="Minimum area for clusters selection.",
        disabled=False,
        layout=Layout(width='200px'))
    pre_pixel_connectivity = IntText(
        value=8,
        description='connectivity type:',
        tooltip=
        "Type of pixel connectivity in analysis. Accepted values: 4 or 8.",
        disabled=False,
        layout=Layout(width='200px'))
    pre_negative_buffer = IntText(
        value=-10,
        description='negative buffer:',
        tooltip="Negative buffer to be applied on the FOI",
        disabled=False,
        layout=Layout(width='200px'))

    refresh_selections = Button(layout=Layout(width='35px'), icon='fa-refresh')
    pre_box = VBox([
        pre_info,
        Label("Select the requared files:"),
        HBox([
            vector_file,
            HTML(
                "Spatial data to be tested - parcels that will be checked for heterogeneity and cardinality."
            )
        ]),
        HBox([
            raster_file,
            HTML("""Thematic raster - classification raster, or raster 
            from other source that will be used for testing heterogeneity and cardinality."""
                 )
        ]),
        HTML(
            """YAML file that holds the classes form the thematic raster file - 
            can be also a simple list of values in the notebook 
            corespondence between pixel values and names for the classes"""),
        HBox([yaml_file, yml_box]), pre_heto_chec, pre_heto_chec_box,
        pre_pixel_connectivity, pre_negative_buffer,
        HBox([
            pre_min_cluster_size,
            HTML(
                "Minimum area for clusters selection - only clusters bigger from this threshold will be counted."
            )
        ])
    ])

    # Run procedures
    run_info = Label("5. Run FOI procedure.")
    run_proc = Button(
        description='Run FOI procedure version 2',
        value=False,
        disabled=False,
        button_style='info',
        tooltip='Run v2 FOI',
        icon='play',
    )
    run_box = HBox([run_proc])

    def on_img_option_change(change):
        if img_option.value == 'Upload':
            img_box.children = [
                HBox([img_dist_folder, img_select, img_clear, img_upload])
            ]
        else:
            img_box.children = ()

    img_option.observe(on_img_option_change, 'value')

    @refresh_selections.on_click
    def refresh_selections_on_click(b):
        vector_file.options = [
            s for s in glob.glob(f'{path_data}vector/*') if '.shp' in s
        ]
        raster_file.options = [
            s for s in glob.glob(f'{path_data}raster/*') if '.tif' in s
        ]
        yaml_file.options = [
            s for s in glob.glob(f'{path_data}/*') if '.yml' in s
        ]

    @img_clear.on_click
    def img_clear_on_click(b):
        img_select.value.clear()
        img_select._counter = 0

    @img_upload.on_click
    def img_upload_on_click(b):
        progress.clear_output()
        os.makedirs(img_dist_folder.value, exist_ok=True)
        for key in img_select.value:
            content = img_select.value[key]['content']
            with open(f'{img_dist_folder.value}{key}', 'wb') as f:
                f.write(content)
        outlog("All files are uploaded.")

    @yml_clear.on_click
    def yml_clear_on_click(b):
        yml_select.value.clear()
        yml_select._counter = 0

    @yml_upload.on_click
    def yml_upload_on_click(b):
        progress.clear_output()
        yml_dist_folder = f'{path_data}'
        os.makedirs(yml_dist_folder, exist_ok=True)
        for key in yml_select.value:
            content = yml_select.value[key]['content']
            with open(f'{yml_dist_folder}{key}', 'wb') as f:
                f.write(content)
        outlog("The yaml file is uploaded.")

    @run_proc.on_click
    def run_proc_on_click(b):
        with progress:
            foi_proc_v2.proc(vector_file.value, raster_file.value,
                             yaml_file.value, pre_negative_buffer.value,
                             pre_min_het.value, pre_max_het.value,
                             pre_pixel_connectivity.value,
                             pre_min_cluster_size.value)

    wbox_v2 = VBox([
        proc_func.upload_shp(path_data), img_info, img_option, img_box,
        pre_box, run_info, run_box, progress
    ])

    return wbox_v2
Ejemplo n.º 4
0
class Control(object):
    def __init__(self, m, label):
        self.m = m
        self.label = label
        self.width = 0.1
        self.elevation = 0
        self.coord = None
        self.io = None
        self.s = None
        self.p = None
        self.show_data = ''
        self.show_menu = False
        self.da_acc = xr.open_rasterio('../data/hydrosheds/acc.vrt')
        self.da_dem = xr.open_rasterio('../data/hydrosheds/dem.vrt')
        self.marker = None

    def show(self, **kwargs):
        if not self.show_menu:
            if kwargs.get('type') == 'mousemove':
                self.coord = kwargs.get('coordinates')
                if self.show_data == 'flow':
                    self.io, flow = overlay(self.label,
                                            self.coord,
                                            self.m,
                                            self.io,
                                            self.width,
                                            self.da_acc,
                                            func=np.sqrt,
                                            nan=0)
                    self.label.value = f'lat/lon = {self.coord}, flow = {flow}'
                elif self.show_data == 'elevation':
                    self.io, elevation = overlay(self.label,
                                                 self.coord,
                                                 self.m,
                                                 self.io,
                                                 self.width,
                                                 self.da_dem,
                                                 nan=-32768)
                    self.label.value = f'lat/lon = {self.coord}, elevation = {elevation}'
                else:
                    self.label.value = f'lat/lon = {self.coord}'
            elif 'width' in kwargs:
                self.width = kwargs.get('width')
                if self.coord and self.show_data == 'flow':
                    self.io, flow = overlay(self.label,
                                            self.coord,
                                            self.m,
                                            self.io,
                                            self.width,
                                            self.da_acc,
                                            func=np.sqrt,
                                            nan=0)
                elif self.coord and self.show_data == 'elevation':
                    self.io, elevation = overlay(self.label,
                                                 self.coord,
                                                 self.m,
                                                 self.io,
                                                 self.width,
                                                 self.da_dem,
                                                 nan=-32768)
            elif 'elevation' in kwargs:
                self.elevation = kwargs.get('elevation')
        if kwargs.get('type') == 'contextmenu':
            self.show_menu = True
            if self.show_data == 'flow':
                showHideFlow = 'Hide flow'
            else:
                showHideFlow = 'Show flow'
            if self.show_data == 'flow':
                self.s = ToggleButtons(options=[
                    'Hide flow', 'Delineate watershed', 'Set marker', 'Close'
                ],
                                       value=None)
            elif self.show_data == 'elevation':
                self.s = ToggleButtons(options=[
                    'Hide elevation', 'Delineate floodplain', 'Set marker',
                    'Close'
                ],
                                       value=None)
            else:
                self.s = ToggleButtons(options=[
                    'Show flow', 'Show elevation', 'Set marker', 'Close'
                ],
                                       value=None)
            self.s.observe(self.get_choice, names='value')
            self.p = Popup(location=self.coord,
                           child=self.s,
                           max_width=160,
                           close_button=False,
                           auto_close=True,
                           close_on_escape_key=False)
            #self.p = CustomPopup(location=self.coord, child=self.s, max_width=160, close_button=False, auto_close=True, close_on_escape_key=False)
            self.m.add_layer(self.p)

    def get_choice(self, x):
        self.show_menu = False
        self.s.close()
        self.m.remove_layer(self.p)
        self.p = None
        choice = x['new']
        if choice == 'Show flow':
            self.show_data = 'flow'
        elif choice == 'Show elevation':
            self.show_data = 'elevation'
        elif choice == 'Hide flow' or choice == 'Hide elevation':
            self.show_data = ''
            self.m.remove_layer(self.io)
            self.io = None
        elif choice == 'Delineate watershed':
            self.show_data = ''
            self.m.remove_layer(self.io)
            self.io = None
            self.label.value = 'Delineating watershed, please wait...'
            delineate(*self.coord)
            self.label.value = 'Watershed delineated'
            ds_mask = xr.open_zarr('tmp/ds_mask/0').compute()
            mask = ds_mask['mask'].values
            polygon = get_polygon(mask, ds_mask.lat.values[0] + 0.5 / 1200,
                                  ds_mask.lon.values[0] - 0.5 / 1200)
            self.m.add_layer(polygon)
            self.label.value = 'Watershed displayed'
        elif choice == 'Delineate floodplain':
            self.show_data = ''
            self.m.remove_layer(self.io)
            self.io = None
            self.label.value = 'Delineating floodplain, please wait...'
            da_mask = flood_delineate(*self.coord, self.elevation)
            self.label.value = 'Floodplain delineated'
            mask = da_mask.values
            polygon = get_polygon(mask, da_mask.lat.values[0] + 0.5 / 1200,
                                  da_mask.lon.values[0] - 0.5 / 1200)
            self.m.add_layer(polygon)
            self.label.value = 'Floodplain displayed'
        elif choice == 'Set marker':
            if self.marker is not None:
                self.m.remove_layer(self.marker)
            self.marker = Marker(location=self.coord)
            self.m.add_layer(self.marker)
        elif choice == 'Close':
            pass
Ejemplo n.º 5
0
from ipywidgets import ToggleButtons
from IPython.display import display, Markdown, HTML, clear_output


button = ToggleButtons(
    options=['Желаемое', 'Действительное'],
    button_style='danger',
    tooltips=["I'm waiting", "I'm waiting"],
    icons=['check'] * 2
)

OUT = 1

def eventhandler(b):
    if not OUT:
        clear_output(wait=True)
        display(button)
        display(HTML('<iframe width="720" height="480" src="https://www.youtube.com/embed/EOdA5X-K8H8" frameborder="1" allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'));
        globals()['OUT'] = 1
    else:
        clear_output(wait=True)
        display(button)
        display(Markdown('fail.md'))
        globals()['OUT'] = 0
    
    
button.observe(eventhandler)
display(button)
display(HTML('<iframe width="720" height="480" src="https://www.youtube.com/embed/EOdA5X-K8H8" frameborder="1" allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'));
Ejemplo n.º 6
0
                        width='100%')
main_box = Box(children=[box2], layout=main_box_layout)

# Eventos
def on_change(change):
    if change['type'] == 'change' and change['name'] == 'value':
        clear_output()
        display(box0)
        if change['new'] == opts[0]:
            gui.printBoardHex(b.getMatrix(), False, b.fromVirtual)
        elif change['new'] == opts[1]:
            gui.printBoardHex(b.getMatrix(), True, b.fromVirtual)
        elif change['new'] == opts[2]:
           gui.printBoardMatrix(b.getMatrix(), b.getLength())
        display(main_box)
buttons.observe(on_change)

def on_move2(btn):
    if b.checkWin(GameTokens.PLAYER2):
        player2TextError.value = 'Felicidades, ganaste!'
    elif b.checkWin(GameTokens.PLAYER1):
        player2TextError.value = 'Perdiste, intentalo nuevamente!'
    else:
        fromSlot = player2TextFrom.value.split(',')
        toSlot =  player2TextTo.value.split(',')
        (fromX, fromY) = (int(fromSlot[0]), int(fromSlot[1]))
        (toX, toY) = (int(toSlot[0]), int(toSlot[1]))
        res = b.moveToken(GameTokens.PLAYER2, fromX, fromY, toX, toY)
        if res == GameTokenMoves.VALID_MOVE:
            if not b.checkWin(GameTokens.PLAYER2):
                move1()
Ejemplo n.º 7
0
class SliceViewer(VBox):
    def __init__(self,
                 volume=None,
                 default_directory=os.getcwd(),
                 title='',
                 enhancement_steps=1000,
                 **kwargs):
        def on_chosen_path_change(old_path, new_path):
            self.dataset = FolderDataset(new_path)
            # TODO: If the path doesn't contain images, display a warning

        # A widget for changing the image folder
        self.pathchooser = PathChooser(
            chosen_path_desc='Image folder:',
            default_directory=default_directory,
            on_chosen_path_change=on_chosen_path_change,
        )
        self.pathchooser.layout.margin = '0 0 10px 0'

        # The number of increments of the min/max slider
        self.enhancement_steps = enhancement_steps

        self.scales = {
            'x': LinearScale(),
            'y': LinearScale(),
        }

        # The currently displayed image will be in bytes at `self.image_plot.image.value`
        self.image_plot = BQImage(
            image=IPyImage(),
            scales=self.scales,
        )

        self.figure = Figure(
            marks=[self.image_plot],
            padding_x=0,
            padding_y=0,
            animation_duration=1000,
            fig_margin={
                'top': 0,
                'right': 0,
                'bottom': 0,
                'left': 0,
            },
            layout=Layout(
                grid_area='figure',
                margin='0',
                width='320px',
                height='320px',
            ),
        )

        # Custom toolbar
        toolbar_width = '100%'
        toolbar_margin = '0px 0 2px 0'
        self.pan_zoom = PanZoom(scales={
            'x': [self.scales['x']],
            'y': [self.scales['y']],
        }, )

        self.save_button = Button(
            description='Save Image',
            tooltip='Save Image',
            icon='save',
            layout=Layout(
                width=toolbar_width,
                # flex='1 1 auto',
                margin=toolbar_margin,
            ),
        )
        self.save_button.on_click(self.save_current_image)

        self.hide_button = Button(
            description='Hide Image',
            tooltip='Hide Image',
            icon='eye-slash',
            layout=Layout(
                width=toolbar_width,
                # flex='1 1 auto',
                margin=toolbar_margin,
            ))
        self.hide_button.on_click(self.hide_current_image)

        self.pan_zoom_toggle_button = ToggleButton(
            description='Pan / Zoom',
            tooltip='Pan/Zoom',
            icon='arrows',
            layout=Layout(
                width=toolbar_width,
                # flex='1 1 auto',
                margin=toolbar_margin,
            ),
        )
        self.pan_zoom_toggle_button.observe(self.on_pan_zoom_toggle,
                                            names='value')

        self.reset_pan_zoom_button = Button(
            description='Undo Zoom',
            tooltip='Reset pan/zoom',
            icon='refresh',
            layout=Layout(
                width=toolbar_width,
                # flex='1 1 auto',
                margin=toolbar_margin,
            ),
        )
        self.reset_pan_zoom_button.on_click(self.reset_pan_zoom)

        self.reset_enhancements_button = Button(
            description='Un-Enhance',
            tooltip='Reset enhancements',
            icon='ban',
            layout=Layout(
                width=toolbar_width,
                # flex='1 1 auto',
                margin=toolbar_margin,
            ),
        )
        self.reset_enhancements_button.on_click(self.reset_enhancements)

        self.mini_map = IPyImage(layout=Layout(
            grid_area='mini-map',
            margin='0',
        ))
        self.mini_map.width = 180
        self.mini_map.height = 180
        # PERFORMANCE CONCERN
        # Ideally instead of four observations, this would observe 'scales' on `self.pan_zoom`
        # However, it doesn't fire updates
        # Ref: https://github.com/bloomberg/bqplot/issues/800
        self.image_plot.scales['x'].observe(self.on_pan_zoom_change('x_min'),
                                            names='min')
        self.image_plot.scales['x'].observe(self.on_pan_zoom_change('x_max'),
                                            names='max')
        self.image_plot.scales['y'].observe(self.on_pan_zoom_change('y_min'),
                                            names='min')
        self.image_plot.scales['y'].observe(self.on_pan_zoom_change('y_max'),
                                            names='max')

        self.plane_toggle = ToggleButtons(
            options=['yz', 'xz', 'xy'],
            description='',
            disabled=False,
            button_style='',
            tooltips=[
                'Step in x direction', 'Step in y direction',
                'Step in z direction'
            ],
            layout=Layout(
                width='200px',
                # flex='1 1 auto',
                margin='7px 0 auto auto',
            ),
        )
        self.plane_toggle.style.button_width = 'auto'
        self.plane_toggle.observe(self.on_plane_change, names='value')

        self.toolbar = VBox(
            children=[
                self.save_button,
                self.hide_button,
                self.pan_zoom_toggle_button,
                self.reset_pan_zoom_button,
                self.reset_enhancements_button,
            ],
            layout=Layout(
                grid_area='toolbar',
                margin='0',
            ),
        )

        # Image enhancements
        self.min_max_slider = FloatRangeSlider(
            value=[0, 255],
            min=0,
            max=255,
            step=255 / self.enhancement_steps,
            description='Min/Max:',
            orientation='horizontal',
            readout=True,
            readout_format='.1f',
            continuous_update=True,
            layout=Layout(
                grid_area='min-max-slider',
                margin='10px 0 10px -10px',
                width='100%',
            ),
        )
        self.min_max_slider.observe(self.on_min_max_change, names='value')

        self.index_slider = IntSlider(
            value=0,
            min=0,
            max=1,
            step=1,
            description='Index:',
            orientation='horizontal',
            readout=True,
            readout_format='d',
            continuous_update=True,
            layout=Layout(
                grid_area='index-slider',
                margin='8px -20px 10px -36px',
                width='100%',
            ),
        )
        self.index_slider.observe(self.on_image_index_change, names='value')

        # Animation
        self.play = Play(
            value=self.index_slider.value,
            min=self.index_slider.min,
            max=self.index_slider.max,
            step=self.index_slider.step,
        )
        jslink((self.play, 'value'), (self.index_slider, 'value'))
        # Keep 'max' in sync as well
        self.index_slider.observe(self.on_index_slider_max_change, names='max')

        self.bottom_bar = HBox(
            children=[
                self.play,
                self.index_slider,
                self.plane_toggle,
            ],
            layout=Layout(
                grid_area='bottom-bar',
                margin=f'10px -20px 0 0',
                # overflow='hidden',
            ))

        # Layout
        self.gridbox = GridBox(children=[
            self.figure,
            self.toolbar,
            self.mini_map,
            self.min_max_slider,
            self.bottom_bar,
        ], )
        # Initially hidden without data
        self.gridbox.layout.display = 'none'

        self._dataset = None
        if volume is not None:
            self.dataset = VolumeDataset(volume)
            # Hide pathchooser when using a volume
            self.pathchooser.layout.display = 'none'

        # Call VBox super class __init__
        super().__init__(
            children=[
                self.pathchooser,
                self.gridbox,
            ],
            layout=Layout(width='auto'),
            **kwargs,
        )

    @property
    def dataset(self):
        """
        Get the dataset that the SliceViewer is displaying.
        """
        return self._dataset

    @dataset.setter
    def dataset(self, dataset):
        """
        Set the dataset that the SliceViewer is displaying.
        """
        if dataset:
            # TODO: set initial pan_zoom_scales
            # image_as_array = dataset[0]
            # width, height = image_as_array.shape
            # self.get_initial_pan_zoom_scales()
            self.index_slider.max = len(dataset) - 1
            # self.play.max = self.index_slider.max
            # Could be simpler with 0 margins, but for now is written generically
            self.plane_toggle.disabled = not isinstance(dataset, VolumeDataset)
            self.gridbox.layout = Layout(
                width='auto',
                # height='500px',
                grid_gap='0px 10px',
                # grid_template_columns='auto auto auto',
                grid_template_columns=f'{self.figure_size[0]}px 180px',
                # grid_template_rows=f'134px {self.figure_size[1] - 110}px 52px 52px',
                grid_template_rows=f'140px 180px 36px 60px',
                grid_template_areas='''
                    "figure toolbar"
                    "figure mini-map"
                    "min-max-slider min-max-slider"
                    "bottom-bar bottom-bar"
                ''',
            )
            self.gridbox.layout.display = None
        else:
            self.gridbox.layout.display = 'none'
        self._dataset = dataset
        # Crucially, this also calls self.redraw
        self.reset_enhancements()

    @property
    def figure_size(self):
        """
        Get the figure layout width and height as integers.
        """
        width = int(self.figure.layout.width[:-2])
        height = int(self.figure.layout.height[:-2])
        return [width, height]

    @figure_size.setter
    def figure_size(self, size):
        """
        Set the figure layout width and height with the provided list.
        """
        width, height = size
        self.figure.layout.width = f'{width}px'
        self.figure.layout.height = f'{height}px'

    @property
    def current_image(self):
        """
        Get the current image from backing `self.dataset` according to `self.index_slider`.
        It should be a normalized numpy array.
        """
        return self.dataset[self.index_slider.value]

    @property
    def value_range(self):
        """
        Get the value ranges of the unormalized dataset.
        """
        low = getattr(self.dataset, 'min', 0)
        high = getattr(self.dataset, 'max', 255)
        return [low, high]

    @output.capture()
    def get_current_image_name(self):
        """
        Return the name of the current image selected according to `self.index_slider`.
        """
        if not self.dataset:
            return ''
        else:
            index = self.index_slider.value
            image_names = getattr(self.dataset, 'image_names', [])
            if image_names:
                return image_names[index]
            else:
                return f'sliceviewer-image-{index}.jpg'

    @output.capture()
    def get_current_scales(self):
        """
        Get the current image_plot scales in a plain dictionary.
        """
        scales = self.image_plot.scales
        plain_scales = {
            'x': [scales['x'].min, scales['x'].max],
            'y': [scales['y'].min, scales['y'].max],
        }
        # Coerce None to 0
        plain_scales['x'] = [x if x else 0 for x in plain_scales['x']]
        plain_scales['y'] = [y if y else 0 for y in plain_scales['y']]
        return plain_scales

    @output.capture()
    def redraw(self, image_as_array=None):
        """
        Redraw main image and mini-map. Defaults to enhanced current image.
        """
        # Main image
        if image_as_array is None:
            image_as_array = self.enhance_image(self.current_image)
        image = PIL_to_bytes(numpy_to_PIL(image_as_array))
        self.image_plot.image = IPyImage(value=image)
        # Mini-map
        self.redraw_mini_map(image_as_array=image_as_array)

    @output.capture()
    def redraw_mini_map(self, image_as_array=None, scales=None):
        """
        Redraw the mini-map. Defaults to enhanced current image.
        """
        if image_as_array is None:
            image_as_array = self.enhance_image(self.current_image)
        if scales is None:
            scales = self.get_current_scales()
        mini_map = self.draw_mini_map(image_as_array, scales)
        self.mini_map.value = PIL_to_bytes(numpy_to_PIL(mini_map))

    @output.capture()
    def on_image_index_change(self, change):
        """
        Load and display the new image.
        """
        enhanced = self.enhance_image(self.current_image)
        self.redraw(image_as_array=enhanced)

    @output.capture()
    def on_index_slider_max_change(self, change):
        """
        Sync play.max with index_slider.max and reset index slider.
        """
        self.play.max = change.new

    @output.capture()
    def get_initial_pan_zoom_scales(self):
        """
        Calculate the necessary pan_zoom scales to fill-in the main viewport
        when the input image is not square.
        """
        raise NotImplementedError

    @output.capture()
    def on_pan_zoom_toggle(self, change):
        """
        Update the `self.figure` interaction.
        """
        if change.new:
            self.figure.interaction = self.pan_zoom
        else:
            self.figure.interaction = None

    @output.capture()
    def reset_pan_zoom(self, button):
        """
        Reset figure/plot scales.
        """
        self.image_plot.scales['x'].min = None
        self.image_plot.scales['x'].max = None
        self.image_plot.scales['y'].min = None
        self.image_plot.scales['y'].max = None
        self.redraw_mini_map()

    @output.capture()
    def draw_mini_map(self, image_as_array, scales):
        """
        Draw a mini version of image_as_array with a rectangle indicating pan/zoom location.
        """
        # Commented code is preparation for non-square image
        # canvas_as_array = draw_checkerboard_canvas(
        #     height=int(self.mini_map.height),
        #     width=int(self.mini_map.width),
        # )
        # offsets, image_as_array = get_offsets_and_resize_for_canvas(
        #     image_as_array,
        #     canvas_as_array,
        # )
        shape = image_as_array.shape
        # Convert grayscale to RGB
        mini_map = to_rgb(image_as_array)
        # Draw a red square indicating the zoom location
        xs = [int(x * shape[1]) for x in scales['x']]
        ys = [int((1.0 - y) * shape[0]) for y in scales['y']]

        # Make sure values are in range
        def clamp(values, low, high):
            temp = [v if v > low else low for v in values]
            return [v if v < high else high for v in temp]

        # This will give a border width of 2 pixels
        xs.extend([x + 1 for x in xs])
        ys.extend([y - 1 for y in ys])
        xs = clamp(xs, 0, shape[1] - 2)
        ys = clamp(ys, 0, shape[0] - 2)
        for x in xs + [x + 1 for x in xs]:
            for y in range(ys[1], ys[0] + 1):
                # Color these locations full-on red
                mini_map[y][x][0] = 1.0
        for y in ys + [y + 1 for y in ys]:
            for x in range(xs[0], xs[1] + 1):
                # Color these locations full-on red
                mini_map[y][x][0] = 1.0
        return mini_map
        # Commented code is preparation for non-square image
        # canvas_as_array = to_rgb(canvas_as_array)
        # canvas_as_array[offsets[0]:, offsets[1]:] = mini_map
        # return canvas_as_array

    @output.capture()
    def on_pan_zoom_change(self, change_type):
        """
        Return a function that produces new scales when the user pans or zooms.

        :param change_type: One of ['x_min', 'x_max', 'y_min', 'y_max']
        """
        def handle_case(change):
            if change.new == None:
                return
            scales = self.get_current_scales()
            cases = {
                'x_min': {
                    'x': [change.new, scales['x'][1]],
                    'y': scales['y'],
                },
                'x_max': {
                    'x': [scales['x'][0], change.new],
                    'y': scales['y'],
                },
                'y_min': {
                    'x': scales['x'],
                    'y': [change.new, scales['y'][1]],
                },
                'y_max': {
                    'x': scales['x'],
                    'y': [scales['y'][0], change.new],
                },
            }
            new_scales = cases[change_type]
            self.redraw_mini_map(scales=new_scales)

        return handle_case

    @output.capture()
    def reset_enhancements(self, button=None):
        """
        Reset all of the image enhancement sliders.
        """
        [low, high] = self.value_range
        self.min_max_slider.min = low
        self.min_max_slider.max = high
        self.min_max_slider.value = [low, high]
        self.min_max_slider.step = (high - low) / self.enhancement_steps
        self.redraw()

    @output.capture()
    def save_current_image(self, button):
        """
        Save the current image with any processing applied.
        """
        directory = getattr(self.dataset, 'directory', os.getcwd())
        processed_directory = os.path.join(directory, 'ipysliceviewer')
        if not os.path.exists(processed_directory):
            os.makedirs(processed_directory)
        filepath = os.path.join(processed_directory,
                                self.get_current_image_name())
        with open(filepath, 'wb') as f:
            f.write(self.image_plot.image.value)

    @output.capture()
    def hide_current_image(self, button):
        """
        Hide the current image and remember this as a setting.
        This is like a soft form of deleting the image.
        """
        # Need more thought on how this should be remembered across restarts for the current dataset
        # Rough idea: text file or similar containing SliceViewer settings, just need to figure out
        # a good naming scheme for datasets - possibly can take name from Experimenter or SliceViewer's own text box
        raise NotImplementedError

    @output.capture()
    def enhance_image(self, image_as_array):
        """
        Apply enhancement sliders to image_as_array and return as a numpy array
        """
        # These values are not normalized even though the image above is
        # (this allows the user to work with the input range)
        new_min, new_max = self.min_max_slider.value
        # So, we'll convert them before using them to scale the normalized image
        [low, high] = self.value_range

        def rescale(x, low, high):
            return (x - low) / (high - low)

        new_min = rescale(new_min, low, high)
        new_max = rescale(new_max, low, high)
        processed_image = rescale(to_rgb(image_as_array), new_min, new_max)
        processed_image = np.clip(processed_image, 0, 1)
        return processed_image

    @output.capture()
    def on_min_max_change(self, change):
        """
        Handle changes to the min/max slider.
        """
        self.redraw()

    @output.capture()
    def on_plane_change(self, change):
        """
        Called when the slice plane is toggled.
        """
        if hasattr(self.dataset, 'plane'):
            self.dataset.plane = change.new
            old_max = self.index_slider.max
            new_max = len(self.dataset) - 1
            self.index_slider.max = new_max
            self.index_slider.value = min(self.index_slider.value, new_max)
            # Guarantee the image updates even if index does not change
            self.redraw()
Ejemplo n.º 8
0
def view():

    temppath = config.get_value(['paths', 'temp'])
    datapath = config.get_value(['paths', 'data'])

    paths = RadioButtons(options=[
        (f"Temporary folder: '{temppath}'.", temppath),
        (f"Personal data folder: '{datapath}'.", datapath)
    ],
                         layout={'width': 'max-content'},
                         value=temppath)

    paths_box = Box([Label(value="Select folder:"), paths])

    tables_first = [
        f for f in os.listdir(paths.value)
        if isdir(normpath(join(paths.value, f)))
    ]

    select_table = Dropdown(
        options=[f for f in tables_first if not f.startswith('.')],
        value=None,
        description='Select tabe:',
        disabled=False,
    )

    button_refresh = Button(layout=Layout(width='35px'), icon='fa-refresh')

    select_option_box = HBox([select_table, button_refresh])

    selection_single = Dropdown(
        options=[],
        value=None,
        description='Select parcel:',
        disabled=False,
    )

    view_source = ToggleButtons(
        options=[('From local folder', 0), ('Download new data', 1)],
        value=0,
        description='',
        disabled=False,
        button_style='success',
        tooltips=[],
    )

    view_method = ToggleButtons(
        options=[],
        value=None,
        description='',
        disabled=False,
        button_style='info',
        tooltips=[],
    )

    rm_parcel = Button(value=False,
                       disabled=False,
                       button_style='danger',
                       tooltip='Delete parcel data.',
                       icon='trash',
                       layout=Layout(width='35px'))
    source_box = VBox([])

    def on_source_change(obj):
        if view_source.value == 1:
            source_box.children = [get_panel.get()]
        else:
            source_box.children = []

    view_source.observe(on_source_change, 'value')

    code_info = Label()
    single_box = HBox([selection_single, rm_parcel])
    select_box = Box([single_box])

    selection = VBox([
        Label("Select a data source."), view_source, source_box, paths_box,
        Label("Select a parcel to display."), select_option_box, select_box
    ])

    view_box = Output(layout=Layout(border='1px solid black'))

    @button_refresh.on_click
    def button_refresh_on_click(b):
        view_box.clear_output()
        tables_first = [
            f for f in os.listdir(paths.value)
            if isdir(normpath(join(paths.value, f)))
        ]
        select_table.options = [
            f for f in tables_first if not f.startswith('.')
        ]
        if select_table.value is not None:
            parcels = normpath(join(paths.value, select_table.value))
            parcels_list = [
                f for f in os.listdir(parcels) if not f.startswith('.')
            ]
            selection_single.options = parcels_list
        else:
            selection_single.options = []
            selection_single.value = None

    @rm_parcel.on_click
    def rm_parcel_on_click(b):
        try:
            parcel_to_rm = normpath(
                join(paths.value, select_table.value, selection_single.value))
            try:
                shutil.rmtree(f'{parcel_to_rm}')
            except Exception:
                pass
            try:
                os.remove(f'{parcel_to_rm}')
            except Exception:
                pass
#             print(f"The parce: '{selection_single.value}' is deleted.")
            parcels = normpath(join(paths.value, select_table.value))
            parcels_list = [
                f for f in os.listdir(parcels) if not f.startswith('.')
            ]
            selection_single.options = parcels_list
            view_box.clear_output()
        except Exception:
            pass

    def on_datapath_change(change):
        tables = [
            f for f in os.listdir(paths.value)
            if isdir(normpath(join(paths.value, f)))
        ]
        tables = [f for f in tables if not f.startswith('.')]
        select_table.options = tables

    paths.observe(on_datapath_change, 'value')

    def on_table_change(change):
        if select_table.value is not None:
            parcels = normpath(join(paths.value, select_table.value))
            parcels_list = [
                f for f in os.listdir(parcels) if not f.startswith('.')
            ]
            selection_single.options = parcels_list
        else:
            selection_single.options = []
            selection_single.value = None
            view_method.options = []

    select_table.observe(on_table_change, 'value')

    def on_selection_change(obj):
        code_info.value = "Select how to view the dataset."
        options_list = [('Get example code', 1)]
        if obj['new'] is not None:
            parceldata = normpath(
                join(paths.value, select_table.value, selection_single.value))
            data_list = [
                f for f in os.listdir(parceldata) if not f.startswith('.')
            ]
            if any("time_series" in s for s in data_list):
                options_list.append(('Plot time series', 2))
            if any("chip_images" in s for s in data_list):
                options_list.append(('View images', 3))
            options_list.append(("Show on map", 4))
            view_method.options = options_list
            view_method.value = None

    selection_single.observe(on_selection_change, 'value')

    def method_options(obj):
        view_box.clear_output()
        data_path = normpath(
            join(paths.value, select_table.value, selection_single.value))
        with view_box:
            if obj['new'] == 1:
                display(view_code.code(data_path))
            elif obj['new'] == 2:
                display(
                    view_time_series.time_series_widget(
                        select_table.value, selection_single.value))
            elif obj['new'] == 3:
                display(view_grid.imgs_grid(data_path))
            elif obj['new'] == 4:
                display(view_map.widget_box(data_path))

    selection_single.observe(method_options, 'value')
    view_method.observe(method_options, 'value')

    notes_info = Label("Add a note for the parcel")
    notes_bt = Button(value=False,
                      description='Add note',
                      disabled=False,
                      button_style='info',
                      tooltip='Add a note.',
                      icon='sticky-note')
    notes_box = VBox([])

    @notes_bt.on_click
    def notes_bt_on_click(b):
        if notes_box.children == ():
            notes_box.children = [
                view_notes.notes(
                    normpath(join(paths.value, select_table.value)),
                    select_table.value, selection_single.value)
            ]
        else:
            notes_box.children = []

    wbox = VBox([
        selection, code_info, view_method, view_box,
        HBox([notes_info, notes_bt]), notes_box
    ])

    return wbox
Ejemplo n.º 9
0
def get():
    """Get the parcel's dataset for the given location or ids"""
    debug = False
    info = Label("1. Select the aoi to get parcel data.")

    values = config.read()
    ppoly_out = Output()
    progress = Output()

    def outlog(*text):
        with progress:
            print(*text)

    def outlog_poly(*text):
        with ppoly_out:
            print(*text)

    def aois_options():
        values = config.read()
        options = {}
        if values['set']['data_source'] == 'api':
            api_values = config.read('api_options.json')
            for aoi in api_values['aois']:
                options[(aoi.upper(), aoi)] = api_values['aois'][aoi]['years']
        elif values['set']['data_source'] == 'direct':
            values = config.read('api_options.json')
            for aoi in values['dataset']:
                options[(f"{aoi.upper()} ({aoi})", aoi)] = [aoi.split('_')[-1]]
        return options

    def aois_years():
        values = config.read()
        years = {}
        if values['set']['data_source'] == 'api':
            api_values = config.read('api_options.json')
            for aoi in api_values['aois']:
                years[aoi] = api_values['aois'][aoi]['years']
        elif values['set']['data_source'] == 'direct':
            values = config.read()
            for aoi in values['dataset']:
                years[aoi] = [aoi.split('_')[-1]]
        return years

    try:
        aois = Dropdown(
            options=tuple(aois_options()),
            value=values['set']['dataset'],
            description='AOI:',
        )
    except Exception:
        aois = Dropdown(
            options=tuple(aois_options()),
            description='AOI:',
        )

    def years_disabled():
        values = config.read()
        if values['set']['data_source'] == 'direct':
            return True
        else:
            return False

    year = Dropdown(
        options=next(iter(aois_options().values())),
        description='Year:',
        disabled=years_disabled(),
    )
    button_refresh = Button(layout=Layout(width='35px'), icon='fa-refresh')

    @button_refresh.on_click
    def button_refresh_on_click(b):
        values = config.read()
        if values['set']['data_source'] == 'api':
            from cbm.datas import api
            available_options = json.loads(api.get_options())
            try:
                api_options = normpath(
                    join(config.path_conf, 'api_options.json'))
                os.makedirs(dirname(api_options), exist_ok=True)
                with open(api_options, "w") as f:
                    json.dump(available_options, f, indent=4)
                outlog(f"File saved at: {api_options}")
            except Exception as err:
                outlog(f"Could not create the file 'api_options.json': {err}")

            outlog(f"The API options are updated.")
        aois.options = tuple(aois_options())
        year.options = aois_years()[aois.value]
        year.disabled = years_disabled()

    def table_options_change(change):
        api_values = config.read('api_options.json')
        id_examples = api_values['aois'][change.new]['id_examples']
        try:
            id_examples_label.value = ', '.join(str(x) for x in id_examples)
            year.options = aois_years()[change.new]
            year.disabled = years_disabled()
            pid.value = str(id_examples[0])
        except Exception:
            id_examples_label.value = ', '.join(str(x) for x in id_examples)
            aois.options = tuple(aois_options())
            year.options = aois_years()[aois.value]
            year.disabled = years_disabled()
            pid.value = str(id_examples[0])

    aois.observe(table_options_change, 'value')

    info_method = Label("2. Select a method to download parcel data.")

    method = ToggleButtons(
        options=[('Parcel ID', 2), ('Coordinates', 1), ('Map marker', 3),
                 ('Polygon', 4)],
        value=None,
        description='',
        disabled=False,
        button_style='info',
        tooltips=[
            'Enter lon lat', 'Enter parcel ID', 'Select a point on a map',
            'Get parcels id in a polygon'
        ],
    )

    plon = Text(value='5.664', placeholder='Add lon', description='Lon:')
    plat = Text(value='52.694', placeholder='Add lat', description='Lat:')
    wbox_lat_lot = VBox(children=[plat, plon])

    api_values = config.read('api_options.json')
    id_examples = api_values['aois'][aois.value]['id_examples']

    id_examples_label = Label(', '.join(str(x) for x in id_examples))
    info_pid = HBox(
        [Label("Multiple parcel ids can be added, e.g.: "), id_examples_label])

    pid = Textarea(
        value=str(id_examples[0]),
        placeholder='12345, 67890',
        description='Parcel(s) ID:',
    )

    wbox_pids = VBox(children=[info_pid, pid])

    bt_get_ids = Button(description="Find parcels",
                        disabled=False,
                        button_style='info',
                        tooltip='Find parcels within the polygon.',
                        icon='')

    get_ids_box = HBox(
        [bt_get_ids,
         Label("Find the parcels that are in the polygon.")])

    @bt_get_ids.on_click
    def bt_get_ids_on_click(b):
        with ppoly_out:
            try:
                # get_requests = data_source()
                ppoly_out.clear_output()
                polygon = get_maps.polygon_map.feature_collection['features'][
                    -1]['geometry']['coordinates'][0]
                polygon_str = '-'.join(
                    ['_'.join(map(str, c)) for c in polygon])
                outlog_poly(f"Geting parcel ids within the polygon...")
                polyids = parcel_info.by_polygon(aois.value, year.value,
                                                 polygon_str, ptype.value,
                                                 False, True)
                outlog_poly(
                    f"'{len(polyids['ogc_fid'])}' parcels where found:")
                outlog_poly(polyids['ogc_fid'])
                file = normpath(
                    join(config.get_value(['paths', 'temp']),
                         'pids_from_polygon.txt'))
                with open(file, "w") as text_file:
                    text_file.write('\n'.join(map(str, polyids['ogc_fid'])))
            except Exception as err:
                outlog("No parcel ids found:", err)

    method_out = Output(layout=Layout(border='1px solid black'))

    def method_options(obj):
        with method_out:
            method_out.clear_output()
            if obj['new'] == 1:
                display(wbox_lat_lot)
            elif obj['new'] == 2:
                display(wbox_pids)
            elif obj['new'] == 3:
                display(
                    get_maps.base_map(aois.value,
                                      config.get_value(['set',
                                                        'data_source'])))
            elif obj['new'] == 4:
                display(
                    VBox([
                        get_maps.polygon(
                            aois.value,
                            config.get_value(['set', 'data_source'])),
                        get_ids_box, ppoly_out
                    ]))

    method.observe(method_options, 'value')

    info_type = Label("3. Select datasets to download.")

    ptype = Text(value=None,
                 placeholder='(Optional) Parcel Type',
                 description='pType:',
                 disabled=False)

    table_options = HBox([aois, button_refresh, ptype, year])

    # ########### Time series options #########################################
    pts_bt = ToggleButton(
        value=False,
        description='Time series',
        button_style='success',  # success
        tooltip='Get parcel information',
        icon='toggle-off',
        layout=Layout(width='50%'))

    pts_bands = data_options.pts_bands()

    pts_tstype = SelectMultiple(
        options=[("Sentinel-2 Level 2A", 's2'),
                 ("S1 Backscattering Coefficients", 'bs'),
                 ("S1 6-day Coherence (20m)", 'c6')],
        value=['s2'],
        rows=3,
        description='TS type:',
        disabled=False,
    )

    pts_band = Dropdown(
        options=list(pts_bands['s2']),
        value='',
        description='Band:',
        disabled=False,
    )

    def pts_tstype_change(change):
        if len(pts_tstype.value) <= 1:
            pts_band.disabled = False
            try:
                pts_b = change.new[0]
                pts_band.options = pts_bands[pts_b]
            except Exception:
                pass
        else:
            pts_band.value = ''
            pts_band.disabled = True

    pts_tstype.observe(pts_tstype_change, 'value')

    pts_options = VBox(children=[pts_tstype, pts_band])

    # ########### Chip images options #########################################
    pci_bt = ToggleButton(value=False,
                          description='Chip images',
                          disabled=False,
                          button_style='success',
                          tooltip='Get parcel information',
                          icon='toggle-off',
                          layout=Layout(width='50%'))

    pci_start_date = DatePicker(
        value=datetime.date(2020, 6, 1),
        description='Start Date',
    )

    pci_end_date = DatePicker(
        value=datetime.date(2020, 6, 30),
        description='End Date',
    )

    pci_plevel = RadioButtons(
        options=['LEVEL2A', 'LEVEL1C'],
        value='LEVEL2A',
        description='Proces. level:',  # Processing level
        disabled=False,
        layout=Layout(width='50%'))

    pci_chipsize = IntSlider(value=640,
                             min=100,
                             max=5120,
                             step=10,
                             description='Chip size:',
                             disabled=False,
                             continuous_update=False,
                             orientation='horizontal',
                             readout=True,
                             readout_format='d')

    pci_bands = data_options.pci_bands()

    pci_satellite = RadioButtons(options=list(pci_bands),
                                 value='Sentinel 2',
                                 disabled=True,
                                 layout=Layout(width='100px'))

    pci_band = SelectMultiple(options=list(pci_bands['Sentinel 2']),
                              value=['B04'],
                              rows=11,
                              description='Band:',
                              disabled=False)

    sats_plevel = HBox([pci_satellite, pci_plevel])

    def on_sat_change(change):
        sat = change.new
        pci_band.options = pci_bands[sat]

    pci_satellite.observe(on_sat_change, 'value')

    pci_options = VBox(children=[
        pci_start_date, pci_end_date, sats_plevel, pci_chipsize, pci_band
    ])

    # ########### General options #############################################
    pts_wbox = VBox(children=[])
    pci_wbox = VBox(children=[])

    def pts_observe(button):
        if button['new']:
            pts_bt.icon = 'toggle-on'
            pts_wbox.children = [pts_options]
        else:
            pts_bt.icon = 'toggle-off'
            pts_wbox.children = []

    def pci_observe(button):
        if button['new']:
            pci_bt.icon = 'toggle-on'
            pci_wbox.children = [pci_options]
        else:
            pci_bt.icon = 'toggle-off'
            pci_wbox.children = []

    pts_bt.observe(pts_observe, names='value')
    pci_bt.observe(pci_observe, names='value')

    pts = VBox(children=[pts_bt, pts_wbox], layout=Layout(width='40%'))
    pci = VBox(children=[pci_bt, pci_wbox], layout=Layout(width='40%'))

    data_types = HBox(children=[pts, pci])

    info_get = Label("4. Download the selected data.")

    bt_get = Button(description='Download',
                    button_style='warning',
                    tooltip='Send the request',
                    icon='download')

    path_temp = config.get_value(['paths', 'temp'])
    path_data = config.get_value(['paths', 'data'])

    info_paths = HTML("".join([
        "<style>div.c {line-height: 1.1;}</style>",
        "<div class='c';>By default data will be stored in the temp folder ",
        f"({path_temp}), you will be asked to empty the temp folder each time ",
        "you start the notebook.<br>In your personal data folder ",
        f"({path_data}) you can permanently store the data.</div>"
    ]))

    paths = RadioButtons(options=[
        (f"Temporary folder: '{path_temp}'.", path_temp),
        (f"Personal data folder: '{path_data}'.", path_data)
    ],
                         layout={'width': 'max-content'},
                         value=path_temp)

    paths_box = Box([Label(value="Select folder:"), paths])

    def file_len(fname):
        with open(fname) as f:
            for i, l in enumerate(f):
                pass
        return i + 1

    def get_data(parcel):
        get_requests = data_source()
        pid = str(parcel['pid'][0])
        source = config.get_value(['set', 'data_source'])
        if source == 'api':
            datapath = normpath(join(paths.value, aois.value, year.value, pid))
        elif source == 'direct':
            dataset = config.get_value(['set', 'dataset'])
            datapath = normpath(join(paths.value, dataset, pid))
        file_pinf = normpath(join(datapath, 'info.json'))
        os.makedirs(dirname(file_pinf), exist_ok=True)
        with open(file_pinf, "w") as f:
            json.dump(parcel, f)
        outlog(f"File saved at: {file_pinf}")

        if pts_bt.value is True:
            outlog(f"Getting time series for parcel: '{pid}',",
                   f"({pts_tstype.value} {pts_band.value}).")
            for pts in pts_tstype.value:
                ts = time_series.by_pid(aois.value, year.value, pid, pts,
                                        ptype.value, pts_band.value)
                band = ''
                if pts_band.value != '':
                    band = f"_{pts_band.value}"
                file_ts = normpath(
                    join(datapath, f'time_series_{pts}{band}.csv'))
                if isinstance(ts, pd.DataFrame):
                    ts.to_csv(file_ts, index=True, header=True)
                elif isinstance(ts, dict):
                    os.makedirs(os.path.dirname(file_ts), exist_ok=True)
                    df = pd.DataFrame.from_dict(ts, orient='columns')
                    df.to_csv(file_ts, index=True, header=True)
            outlog("TS Files are saved.")
        if pci_bt.value is True:
            files_pci = normpath(join(datapath, 'chip_images'))
            outlog(f"Getting '{pci_band.value}' chip images for parcel: {pid}")
            with progress:
                get_requests.rcbl(parcel, pci_start_date.value,
                                  pci_end_date.value, pci_band.value,
                                  pci_chipsize.value, files_pci)
            filet = normpath(
                join(datapath, 'chip_images',
                     f'images_list.{pci_band.value[0]}.csv'))
            if file_len(filet) > 1:
                outlog(
                    f"Completed, all GeoTIFFs for bands '{pci_band.value}' are ",
                    f"downloaded in the folder: '{datapath}/chip_images'")
            else:
                outlog(
                    "No files where downloaded, please check your configurations"
                )

    def get_from_location(lon, lat):
        outlog(f"Finding parcel information for coordinates: {lon}, {lat}")
        parcel = parcel_info.by_location(aois.value, year.value, lon, lat,
                                         ptype.value, True, False, debug)
        pid = str(parcel['pid'][0])
        outlog(f"The parcel '{pid}' was found at this location.")
        try:
            get_data(parcel)
        except Exception as err:
            print(err)

    def get_from_id(pids):
        outlog(f"Getting parcels information for: '{pids}'")
        for pid in pids:
            try:
                parcel = parcel_info.by_pid(aois.value, year.value, pid,
                                            ptype.value, True, False, debug)
                get_data(parcel)
            except Exception as err:
                print(err)

    @bt_get.on_click
    def bt_get_on_click(b):
        progress.clear_output()
        if method.value == 1:
            try:
                with progress:
                    lon, lat = plon.value, plat.value
                    get_from_location(lon, lat)
            except Exception as err:
                outlog("Could not get parcel information for location",
                       f"'{lon}', '{lat}': {err}")

        elif method.value == 2:
            try:
                with progress:
                    pids = pid.value.replace(" ", "").split(",")
                    get_from_id(pids)
            except Exception as err:
                outlog(f"Could not get parcel information: {err}")

        elif method.value == 3:
            try:
                marker = get_maps.base_map.map_marker
                lon = str(round(marker.location[1], 2))
                lat = str(round(marker.location[0], 2))
                get_from_location(lon, lat)
            except Exception as err:
                outlog(f"Could not get parcel information: {err}")
        elif method.value == 4:
            try:
                plimit = int(values['set']['plimit'])
                file = normpath(
                    join(config.get_value(['paths', 'temp']),
                         'pids_from_polygon.txt'))
                with open(file, "r") as text_file:
                    pids = text_file.read().split('\n')
                outlog("Geting data form the parcels:")
                outlog(pids)
                if len(pids) <= plimit:
                    get_from_id(pids)
                else:
                    outlog(
                        "You exceeded the maximum amount of selected parcels ",
                        f"({plimit}) to get data. Please select smaller area.")
            except Exception as err:
                outlog("No pids file found.", err)
        else:
            outlog(f"Please select method to get parcel information.")

    return VBox([
        info, table_options, info_method, method, method_out, info_type,
        data_types, info_get, info_paths, paths_box, bt_get, progress
    ])
Ejemplo n.º 10
0
class Map_menu(object):
    def __init__(self, m, label, file_upload):
        self.m = m
        self.label = label
        self.file_upload = file_upload
        self.coord = None
        self.s = None
        self.p = None
        self.show_menu = False
        self.marker = None
        self.geojson = None
        self.marker_or_geojson = None
        self.current_io = None
        self.da = None

    def show(self, **kwargs):
        if not self.show_menu:
            if kwargs.get('type') == 'contextmenu':
                self.show_menu = True
                options = ['Show marker']
                if self.geojson is None:
                    options += ['Show GeoJSON']
                if self.marker_or_geojson is not None:
                    options += [f'Remove {self.marker_or_geojson}']
                options += ['Close']
                self.s = ToggleButtons(options=options, value=None)
                self.s.observe(self.get_choice, names='value')
                self.p = Popup(location=self.coord,
                               child=self.s,
                               max_width=160,
                               close_button=False,
                               auto_close=True,
                               close_on_escape_key=False)
                self.m.add_layer(self.p)
            elif kwargs.get('type') == 'mousemove':
                self.coord = kwargs.get('coordinates')
                lat, lon = self.coord
                if self.da is not None:
                    self.label.value = str(
                        self.da.sel(lat=lat, lon=lon, method='nearest').values)

    def get_choice(self, x):
        self.show_menu = False
        self.s.close()
        self.m.remove_layer(self.p)
        self.p = None
        choice = x['new']
        if choice == 'Show marker':
            self.show_marker()
        elif choice == 'Show GeoJSON':
            self.show_geojson()
        elif choice == 'Remove marker':
            self.remove_marker()
        elif choice == 'Remove GeoJSON':
            self.remove_geojson()
        elif choice == 'Close':
            pass

    def show_geojson(self, *args):
        data = json.loads(
            list(
                self.file_upload.value.values())[0]['content'].decode('ascii'))
        self.remove_marker()
        self.remove_geojson()
        self.geojson = GeoJSON(
            data=data,
            style={'color': 'green'})  #, 'opacity': 1})#, 'fillOpacity':0.1})
        self.m.add_layer(self.geojson)
        self.marker_or_geojson = 'GeoJSON'

    def show_marker(self):
        self.remove_marker()
        self.remove_geojson()
        self.marker = Marker(location=self.coord)
        self.m.add_layer(self.marker)
        self.marker_or_geojson = 'marker'

    def remove_marker(self):
        if self.marker is not None:
            self.m.remove_layer(self.marker)
            self.marker = None
        self.marker_or_geojson = None

    def remove_geojson(self):
        if self.geojson is not None:
            self.m.remove_layer(self.geojson)
            self.geojson = None
        self.marker_or_geojson = None
Ejemplo n.º 11
0
class Flow(object):
    def __init__(self, m, label):
        self.m = m
        self.label = label
        self.width = 0.1
        self.coord = None
        self.io = None
        self.s = None
        self.p = None
        self.show_flow = False
        self.show_menu = False
        self.da = xr.open_rasterio('../data/hydrosheds/acc.vrt')
        self.marker = None
    def show(self, **kwargs):
        if not self.show_menu:
            if kwargs.get('type') == 'mousemove':
                self.coord = kwargs.get('coordinates')
                if self.show_flow:
                    self.io, flow = show_acc(self.label, self.coord, self.m, self.io, self.width, self.da)
                    self.label.value = f'lat/lon = {self.coord}, flow = {flow}'
                else:
                    self.label.value = f'lat/lon = {self.coord}'
                    pass
            elif 'width' in kwargs:
                self.width = kwargs.get('width')
                if self.coord and self.show_flow:
                    self.io, flow = show_acc(self.label, self.coord, self.m, self.io, self.width, self.da)
        if kwargs.get('type') == 'contextmenu':
            self.show_menu = True
            if self.show_flow:
                showHideFlow = 'Hide flow'
            else:
                showHideFlow = 'Show flow'
            if showHideFlow == 'Hide flow':
                self.s = ToggleButtons(options=[showHideFlow, 'Delineate watershed', 'Set marker', 'Close'], value=None)
            else:
                self.s = ToggleButtons(options=[showHideFlow, 'Set marker', 'Close'], value=None)
            self.s.observe(self.get_choice, names='value')
            self.p = Popup(location=self.coord, child=self.s, max_width=160, close_button=False, auto_close=True, close_on_escape_key=False)
            self.m.add_layer(self.p)
    def get_choice(self, x):
        self.show_menu = False
        self.s.close()
        self.m.remove_layer(self.p)
        self.p = None
        choice = x['new']
        if choice == 'Show flow':
            self.show_flow = True
        elif choice == 'Hide flow':
            self.show_flow = False
            self.m.remove_layer(self.io)
            self.io = None
        elif choice == 'Delineate watershed':
            self.show_flow = False
            self.m.remove_layer(self.io)
            self.io = None
            self.label.value = 'Delineating watershed, please wait...'
            delineate(*self.coord)
            self.label.value = 'Watershed delineated'
            ds_mask = xr.open_zarr('tmp/ds_mask/0').compute()
            mask = ds_mask['mask'].values
            polygon = get_polygon(mask, ds_mask.lat.values[0]+0.5/1200, ds_mask.lon.values[0]-0.5/1200)
            self.m.add_layer(polygon)
            self.label.value = 'Watershed displayed'
        elif choice == 'Set marker':
            if self.marker is not None:
                self.m.remove_layer(self.marker)
            self.marker = Marker(location=self.coord)
            self.m.add_layer(self.marker)
        elif choice == 'Close':
            pass
Ejemplo n.º 12
0
def get():
    """Get the parcel's dataset for the given location or ids"""
    info = Label(
        "1. Select the region and the year to get parcel information.")

    values = config.read()
    # Set the max number of parcels that can be downloaded at once.
    plimit = int(values['set']['plimit'])

    def aois_options():
        values = config.read()
        options = {}
        if values['set']['data_source'] == '0':
            for desc in values['api']['options']['aois']:
                aoi = f"{values['api']['options']['aois'][desc]}"
                options[(desc, aoi)] = values['api']['options']['years'][aoi]
        elif values['set']['data_source'] == '1':
            for aoi in values['ds_conf']:
                desc = f"{values['ds_conf'][aoi]['desc']}"
                confgs = values['ds_conf'][aoi]['years']
                options[(f'{desc} ({aoi})', aoi)] = [y for y in confgs]
        return options

    def aois_years():
        values = config.read()
        years = {}
        if values['set']['data_source'] == '0':
            for desc in values['api']['options']['aois']:
                aoi = values['api']['options']['aois'][desc]
                years[aoi] = values['api']['options']['years'][aoi]
        elif values['set']['data_source'] == '1':
            for aoi in values['ds_conf']:
                desc = f"{values['ds_conf'][aoi]['desc']}"
                years[aoi] = [y for y in values['ds_conf'][aoi]['years']]
        return years

    try:
        aois = Dropdown(
            options=tuple(aois_options()),
            value=values['set']['ds_conf'],
            description='AOI:',
            disabled=False,
        )
    except:
        aois = Dropdown(
            options=tuple(aois_options()),
            description='AOI:',
            disabled=False,
        )

    year = Dropdown(
        options=next(iter(aois_options().values())),
        description='Year:',
        disabled=False,
    )
    button_refresh = Button(layout=Layout(width='35px'), icon='fa-refresh')

    @button_refresh.on_click
    def button_refresh_on_click(b):
        aois.options = tuple(aois_options())
        year.options = aois_years()[aois.value]

    def table_options_change(change):
        try:
            year.options = aois_years()[change.new]
        except:
            aois.options = tuple(aois_options())
            year.options = aois_years()[aois.value]

    aois.observe(table_options_change, 'value')

    info_method = Label("2. Select a method to get the data.")

    method = ToggleButtons(
        options=[('Parcel ID', 2), ('Coordinates', 1), ('Map marker', 3),
                 ('Polygon', 4)],
        value=None,
        description='',
        disabled=False,
        button_style='info',
        tooltips=[
            'Enter lat lon', 'Enter parcel ID', 'Select a point on a map',
            'Get parcels id in a polygon'
        ],
    )

    plon = Text(value='5.664',
                placeholder='Add lon',
                description='Lon:',
                disabled=False)

    plat = Text(value='52.694',
                placeholder='Add lat',
                description='Lat:',
                disabled=False)

    wbox_lat_lot = VBox(children=[plat, plon])

    info_pid = Label(
        "Multiple parcel id codes can be added (comma ',' separated, e.g.: 11111, 22222)."
    )

    pid = Textarea(value='34296',
                   placeholder='12345, 67890',
                   description='Parcel(s) ID:',
                   disabled=False)

    wbox_pids = VBox(children=[info_pid, pid])

    bt_get_ids = Button(description="Find parcels",
                        disabled=False,
                        button_style='info',
                        tooltip='Find parcels within the polygon.',
                        icon='')

    get_ids_box = HBox(
        [bt_get_ids,
         Label("Find the parcels that are in the polygon.")])

    ppoly_out = Output()

    progress = Output()

    def outlog(*text):
        with progress:
            print(*text)

    def outlog_poly(*text):
        with ppoly_out:
            print(*text)

    @bt_get_ids.on_click
    def bt_get_ids_on_click(b):
        with ppoly_out:
            try:
                get_requests = data_source()
                ppoly_out.clear_output()
                polygon = get_maps.polygon_map.feature_collection['features'][
                    -1]['geometry']['coordinates'][0]
                polygon_str = '-'.join(
                    ['_'.join(map(str, c)) for c in polygon])
                outlog_poly(f"Geting parcel ids within the polygon...")
                polyids = json.loads(
                    get_requests.ppoly(aois.value, year.value, polygon_str,
                                       False, True))
                outlog_poly(
                    f"'{len(polyids['ogc_fid'])}' parcels where found:")
                outlog_poly(polyids['ogc_fid'])
                file = config.get_value(['files', 'pids_poly'])
                with open(file, "w") as text_file:
                    text_file.write('\n'.join(map(str, polyids['ogc_fid'])))
            except Exception as err:
                outlog("No parcel ids found:", err)

    method_out = Output(layout=Layout(border='1px solid black'))

    def method_options(obj):
        with method_out:
            method_out.clear_output()
            if obj['new'] == 1:
                display(wbox_lat_lot)
            elif obj['new'] == 2:
                display(wbox_pids)
            elif obj['new'] == 3:
                display(
                    get_maps.base_map(
                        aois.value,
                        int(config.get_value(['set', 'data_source']))))
            elif obj['new'] == 4:
                display(
                    VBox([
                        get_maps.polygon(
                            aois.value,
                            int(config.get_value(['set', 'data_source']))),
                        get_ids_box, ppoly_out
                    ]))

    method.observe(method_options, 'value')

    info_type = Label("3. Select datasets to download.")

    table_options = HBox([aois, button_refresh, year])

    # ########### Time series options #########################################
    pts_bt = ToggleButton(
        value=False,
        description='Time series',
        disabled=False,
        button_style='success',  # success
        tooltip='Get parcel information',
        icon='toggle-off',
        layout=Layout(width='50%'))

    pts_bands = data_options.pts_bands()

    pts_tstype = SelectMultiple(
        options=data_options.pts_tstype(),
        value=['s2'],
        rows=3,
        description='TS type:',
        disabled=False,
    )

    pts_band = Dropdown(
        options=list(pts_bands['s2']),
        value='',
        description='Band:',
        disabled=False,
    )

    def pts_tstype_change(change):
        if len(pts_tstype.value) <= 1:
            pts_band.disabled = False
            try:
                pts_b = change.new[0]
                pts_band.options = pts_bands[pts_b]
            except:
                pass
        else:
            pts_band.value = ''
            pts_band.disabled = True

    pts_tstype.observe(pts_tstype_change, 'value')

    pts_options = VBox(children=[pts_tstype, pts_band])

    # ########### Chip images options #########################################
    pci_bt = ToggleButton(value=False,
                          description='Chip images',
                          disabled=False,
                          button_style='success',
                          tooltip='Get parcel information',
                          icon='toggle-off',
                          layout=Layout(width='50%'))

    pci_start_date = DatePicker(value=datetime.date(2019, 6, 1),
                                description='Start Date',
                                disabled=False)

    pci_end_date = DatePicker(value=datetime.date(2019, 6, 30),
                              description='End Date',
                              disabled=False)

    pci_plevel = RadioButtons(
        options=['LEVEL2A', 'LEVEL1C'],
        value='LEVEL2A',
        description='Proces. level:',  # Processing level
        disabled=False,
        layout=Layout(width='50%'))

    pci_chipsize = IntSlider(value=640,
                             min=100,
                             max=5120,
                             step=10,
                             description='Chip size:',
                             disabled=False,
                             continuous_update=False,
                             orientation='horizontal',
                             readout=True,
                             readout_format='d')

    pci_bands = data_options.pci_bands()

    pci_satellite = RadioButtons(options=list(pci_bands),
                                 value='Sentinel 2',
                                 disabled=True,
                                 layout=Layout(width='100px'))

    pci_band = SelectMultiple(options=list(pci_bands['Sentinel 2']),
                              value=['B04'],
                              rows=11,
                              description='Band:',
                              disabled=False)

    sats_plevel = HBox([pci_satellite, pci_plevel])

    def on_sat_change(change):
        sat = change.new
        pci_band.options = pci_bands[sat]

    pci_satellite.observe(on_sat_change, 'value')

    pci_options = VBox(children=[
        pci_start_date, pci_end_date, sats_plevel, pci_chipsize, pci_band
    ])

    # ########### General options #############################################
    pts_wbox = VBox(children=[])
    pci_wbox = VBox(children=[])

    def pts_observe(button):
        if button['new']:
            pts_bt.icon = 'toggle-on'
            pts_wbox.children = [pts_options]
        else:
            pts_bt.icon = 'toggle-off'
            pts_wbox.children = []

    def pci_observe(button):
        if button['new']:
            pci_bt.icon = 'toggle-on'
            pci_wbox.children = [pci_options]
        else:
            pci_bt.icon = 'toggle-off'
            pci_wbox.children = []

    pts_bt.observe(pts_observe, names='value')
    pci_bt.observe(pci_observe, names='value')

    pts = VBox(children=[pts_bt, pts_wbox], layout=Layout(width='40%'))
    pci = VBox(children=[pci_bt, pci_wbox], layout=Layout(width='40%'))

    data_types = HBox(children=[pts, pci])

    info_get = Label("4. Download the selected data.")

    bt_get = Button(description='Download',
                    disabled=False,
                    button_style='warning',
                    tooltip='Send the request',
                    icon='download')

    path_temp = config.get_value(['paths', 'temp'])
    path_data = config.get_value(['paths', 'data'])

    info_paths = HTML("".join([
        "<style>div.c {line-height: 1.1;}</style>",
        "<div class='c';>By default data will be stored in the temp folder ",
        f"({path_temp}), you will be asked to empty the temp folder each time ",
        "you start the notebook.<br>In your personal data folder ",
        f"({path_data}) you can permanently store the data.</div>"
    ]))

    paths = RadioButtons(options=[
        (f"Temporary folder: '{path_temp}'.", path_temp),
        (f"Personal data folder: '{path_data}'.", path_data)
    ],
                         layout={'width': 'max-content'},
                         value=path_temp)

    paths_box = Box([Label(value="Select folder:"), paths])

    def file_len(fname):
        with open(fname) as f:
            for i, l in enumerate(f):
                pass
        return i + 1

    def get_data(parcel):
        values = config.read()
        get_requests = data_source()
        pid = parcel['ogc_fid'][0]
        source = int(config.get_value(['set', 'data_source']))
        if source == 0:
            datapath = f'{paths.value}{aois.value}{year.value}/parcel_{pid}/'
        elif source == 1:
            ds_conf = config.get_value(['set', 'ds_conf'])
            datapath = f'{paths.value}{ds_conf}/parcel_{pid}/'
        file_pinf = f"{datapath}{pid}_information"

        outlog(data_handler.export(parcel, 10, file_pinf))

        if pts_bt.value is True:
            outlog(f"Getting time series for parcel: '{pid}',",
                   f"({pts_tstype.value} {pts_band.value}).")
            for pts in pts_tstype.value:
                ts = json.loads(
                    get_requests.pts(aois.value, year.value, pid, pts,
                                     pts_band.value))
                band = ''
                if pts_band.value != '':
                    band = f"_{pts_band.value}"
                file_ts = f"{datapath}{pid}_time_series_{pts}{band}"
                outlog(data_handler.export(ts, 11, file_ts))
        if pci_bt.value is True:
            files_pci = f"{datapath}{pid}_chip_images/"
            outlog(f"Getting '{pci_band.value}' chip images for parcel: {pid}")
            with progress:
                get_requests.rcbl(parcel, pci_start_date.value,
                                  pci_end_date.value, pci_band.value,
                                  pci_satellite.value, pci_chipsize.value,
                                  files_pci)
            filet = f'{datapath}/{pid}_chip_images/{pid}_images_list.{pci_band.value[0]}.csv'
            if file_len(filet) > 1:
                outlog(
                    f"Completed, all GeoTIFFs for bands '{pci_band.value}' are ",
                    f"downloaded in the folder: '{datapath}/{pid}_chip_images'"
                )
            else:
                outlog(
                    "No files where downloaded, please check your configurations"
                )

    def get_from_location(lon, lat):
        get_requests = data_source()
        outlog(f"Finding parcel information for coordinates: {lon}, {lat}")
        parcel = json.loads(
            get_requests.ploc(aois.value, year.value, lon, lat, True))
        pid = parcel['ogc_fid'][0]
        outlog(f"The parcel '{pid}' was found at this location.")
        try:
            get_data(parcel)
        except Exception as err:
            print(err)

    def get_from_id(pids):
        get_requests = data_source()
        outlog(f"Getting parcels information for: '{pids}'")
        for pid in pids:
            try:
                parcel = json.loads(
                    get_requests.pid(aois.value, year.value, pid, True))
                get_data(parcel)
            except Exception as err:
                print(err)

    @bt_get.on_click
    def bt_get_on_click(b):
        progress.clear_output()
        if method.value == 1:
            try:
                with progress:
                    get_requests = data_source()
                    lon, lat = plon.value, plat.value
                    get_from_location(lon, lat)
            except Exception as err:
                outlog(
                    f"Could not get parcel information for location '{lon}', '{lat}': {err}"
                )

        elif method.value == 2:
            try:
                with progress:
                    pids = pid.value.replace(" ", "").split(",")
                    get_from_id(pids)
            except Exception as err:
                outlog(f"Could not get parcel information: {err}")

        elif method.value == 3:
            try:
                marker = get_maps.base_map.map_marker
                lon = str(round(marker.location[1], 2))
                lat = str(round(marker.location[0], 2))
                get_from_location(lon, lat)
            except Exception as err:
                outlog(f"Could not get parcel information: {err}")
        elif method.value == 4:
            try:
                file = config.get_value(['files', 'pids_poly'])
                with open(file, "r") as text_file:
                    pids = text_file.read().split('\n')
                outlog("Geting data form the parcels:")
                outlog(pids)
                if len(pids) <= plimit:
                    get_from_id(pids)
                else:
                    outlog(
                        "You exceeded the maximum amount of selected parcels ",
                        f"({plimit}) to get data. Please select smaller area.")
            except Exception as err:
                outlog("No pids file found.", err)
        else:
            outlog(f"Please select method to get parcel information.")

    return VBox([
        info, table_options, info_method, method, method_out, info_type,
        data_types, info_get, info_paths, paths_box, bt_get, progress
    ])
Ejemplo n.º 13
0
def foi_tab_v1():
    path_foi = "foi/"
    path_foi_func = foi_v1.path_foi_func

    progress = Output()

    def outlog(*text):
        with progress:
            print(*text)

    foi_info = HTML(
        """FOI procedures version 1 (requires access to a database).
        """,
        placeholder='FOI Information')

    # Connect to database

    config_info = HTML(value="""1. Connect to database and object storage.<br>
        FOI procedures need direct access to the database. In case there no
        image is provided, access to object storage will be needed as well
        to generate the base image from sentinel images.
        """,
                       placeholder='FOI Information')
    config_conn = Button(value=False,
                         button_style='info',
                         tooltip='Configure db connection.',
                         icon='cogs',
                         layout=Layout(width='40px'))

    config_conn_box = HBox([])

    @config_conn.on_click
    def config_conn_on_click(b):
        if config_conn_box.children == ():
            config_conn_box.children = [settings_ds.direct_conn()]
        else:
            config_conn_box.children = ()

    config_box = VBox([config_info, config_conn, config_conn_box])

    # Spatial data to be tested
    spatial_info = HTML(
        """2. Select the spatial data to be tested - parcels that will be
        checked for heterogeneity and cardinality.<br>
        - Select a table from the database""")

    db_tables = Dropdown(options=[], description='db Tables:')
    refresh_db_tables = Button(value=False,
                               button_style='info',
                               tooltip='Get db tables.',
                               icon='refresh',
                               layout=Layout(width='40px'))

    @refresh_db_tables.on_click
    def refresh_db_tables_on_click(b):
        db_tables.options = db.tables(config.get_value(['set', 'db_conn']))

    db_tables_box = HBox([db_tables, refresh_db_tables])

    upload_shp = Button(description='Create new table',
                        value=False,
                        button_style='info',
                        tooltip='upload_shp.',
                        icon='up')

    upload_box = VBox([])

    @upload_shp.on_click
    def upload_shp_on_click(b):
        if upload_box.children == ():
            upload_box.children = [ext_func.upload_shp(path_foi, True)]
        else:
            upload_box.children = ()

    spatial_box = VBox([spatial_info, upload_shp, upload_box, db_tables_box])

    # Thematic raster.
    img_info = HTML(
        """3. Thematic raster - classification raster, or raster from other
        source that will be used for testing heterogeneity and cardinality.<br>
        - Upload or generate raster base image.
        (Only upload is currently available)""")
    img_option = ToggleButtons(
        options=['Upload', 'Generate'],
        value=None,
        disabled=True,
        button_style='info',  # 'success', 'info', 'warning', 'danger' or ''
        tooltips=['Upnload your base image', 'Get from object storage'])

    def on_img_option_change(change):
        if img_option.value == 'Upload':
            img_box.children = [HBox([img_info, img_option, img_file])]
        else:
            img_box.children = ()

    img_option.observe(on_img_option_change, 'value')

    img_file = cbm_widgets.get_files_dropdown(f'{path_foi}raster',
                                              '.tif, .tiff', 'Select Raster')
    img_box = VBox([img_info, img_option, img_file])

    # YAML File upload
    yml_info = HTML(
        """4. YAML file that holds the classes form the thematic raster.<br>
            - This can be also a simple list of values in the notebook
            corespondence between pixel values and names for the classes""")

    yml_file = cbm_widgets.get_files_dropdown(path_foi, '.yml, .yaml',
                                              'Select YML')
    yml_box = VBox([yml_info, yml_file])

    # Database functions
    dbf_info = HTML("""5. Create database functions.<br>
    - Import required database functions for FOI analysis to the database""")

    dbf_insert = Button(value=False,
                        button_style='info',
                        tooltip='Create functions.',
                        icon='fa-share-square')

    @dbf_insert.on_click
    def dbf_insert_on_click(b):
        outlog('path_foi_func :', path_foi_func)
        progress.clear_output()
        try:
            functions = glob.glob(f"{path_foi_func}*.func")
            db = config.get_value(['set', 'db_conn'])
            schema = config.get_value(['db', db, 'schema'])
            user = config.get_value(['db', db, 'user'])

            for f in functions:
                db.insert_function(
                    open(f).read().format(schema=schema, owner=user))
                outlog(f"The '{f}' Was imported to the database.")
            finc_list = [
                f"ipycbm_{f.split('/')[-1].split('.')[0]}, " for f in functions
            ]
            outlog(
                f"The functions: {('').join(finc_list)} where added to the database"
            )
        except Exception as err:
            outlog("Could not add functions to dattabase.", err)

    dbf_box = VBox([dbf_info, dbf_insert])

    # FOI Parameters
    param_info = HTML("""6. Set FOI v1 Parameters""")

    # heterogeneity_threshold
    param_heto_info = HTML("""
    Minimum and maximum thresholds for heterogeneity checks. In the example,
    any parcel with percentage of pixels for one class between 30 and 70 from
    the total, will be considered heterogenous.
    """)
    param_min_het = IntText(
        value=30,
        description='MIN:',
        tooltip="Minimum threshold for heterogeneity checks",
        layout=Layout(width='150px'))
    param_max_het = IntText(
        value=70,
        description='MAX:',
        tooltip="Maximum threshold for heterogeneity checks",
        layout=Layout(width='150px'))

    param_area_info = HTML("""Minimum area for clusters selection -
    only clusters bigger from this threshold will be counted.
    """)
    param_area = IntText(value=2000,
                         description='area:',
                         tooltip="Minimum area for clusters selection.",
                         layout=Layout(width='200px'))

    param_box = VBox([
        param_info, param_heto_info,
        HBox([param_min_het, param_max_het]), param_area_info, param_area
    ])

    # Run FOI analysis
    run_info = Label("7. Run the FOI analysis.")
    run_analysis = Button(
        description='Run FOI v1',
        value=False,
        button_style='info',
        tooltip='Run FOI analysis version 1',
        icon='play',
    )
    run_box = VBox([run_info, run_analysis])

    @run_analysis.on_click
    def run_analysis_on_click(b):
        with progress:
            foi_v1.main(db_tables.value,
                        f"{img_file.children[1].children[0].value}",
                        f"{yml_file.children[1].children[0].value}",
                        param_min_het.value, param_max_het.value,
                        param_area.value)

    wbox = VBox([
        foi_info, config_box, spatial_box, img_box, yml_box, dbf_box,
        param_box, run_box, progress
    ])

    return wbox
Ejemplo n.º 14
0
def foi_tab_v2():
    path_foi = "foi/"
    progress = Output()

    def outlog(*text):
        with progress:
            print(*text)

    foi_info = HTML(
        """FOI procedures version 2 (does not require access to a database).
        """,
        placeholder='FOI Information')

    # Vector file
    shp_info = HTML("""1. Spatial data to be tested -
        parcels that will be checked for heterogeneity and cardinality.""")
    shp_file = cbm_widgets.get_files_dropdown(f'{path_foi}vector', '',
                                              'Select .shp', True, True)
    shp_box = VBox([shp_info, shp_file])

    # Thematic raster.
    img_info = HTML(
        """2. Thematic raster - classification raster, or raster from other
        source that will be used for testing heterogeneity and cardinality.<br>
        - Upload or generate raster base image.
        (Only upload is currently available)""")
    img_option = ToggleButtons(
        options=['Upload', 'Generate'],
        value=None,
        disabled=True,
        button_style='',  # 'success', 'info', 'warning', 'danger' or ''
        tooltips=['Upnload your base image', 'Get from object storage'])

    def on_img_option_change(change):
        if img_option.value == 'Upload':
            img_box.children = [HBox([img_info, img_option, img_file])]
        else:
            img_box.children = ()

    img_option.observe(on_img_option_change, 'value')
    img_file = cbm_widgets.get_files_dropdown(f'{path_foi}raster',
                                              '.tif, .tiff', 'Select Raster')
    img_box = VBox([img_info, img_option, img_file])

    # YAML File upload
    yml_info = HTML(
        """3. YAML file that holds the classes form the thematic raster.<br>
            - This can be also a simple list of values in the notebook
            corespondence between pixel values and names for the classes""")
    yml_file = cbm_widgets.get_files_dropdown(path_foi, '.yml, .yaml',
                                              'Select YML')
    yml_box = VBox([yml_info, yml_file])

    # FOI Prerequisites
    pre_info = Label("4. Set FOI v2 Parameters.")

    # heterogeneity_threshold
    pre_heto_chec = HTML("""
    Minimum and maximum thresholds for heterogeneity checks. In the example,
    any parcel with percentage of pixels for one class between 30 and 70 from
    the total, will be considered heterogenous.
    """)
    pre_min_het = IntText(value=30,
                          description='MIN:',
                          tooltip="Minimum threshold for heterogeneity checks",
                          disabled=False,
                          layout=Layout(width='150px'))
    pre_max_het = IntText(value=70,
                          description='MAX:',
                          tooltip="Maximum threshold for heterogeneity checks",
                          disabled=False,
                          layout=Layout(width='150px'))
    pre_heto_chec_box = HBox([pre_min_het, pre_max_het])
    pre_min_cluster_size = IntText(
        value=20,
        description='pixels:',
        tooltip="Minimum area for clusters selection.",
        disabled=False,
        layout=Layout(width='200px'))
    pre_pixel_connectivity = IntText(
        value=8,
        description='connectivity type:',
        tooltip=
        "Type of pixel connectivity in analysis. Accepted values: 4 or 8.",
        disabled=False,
        layout=Layout(width='200px'))
    pre_negative_buffer = IntText(
        value=-10,
        description='negative buffer:',
        tooltip="Negative buffer to be applied on the FOI",
        disabled=False,
        layout=Layout(width='200px'))

    pre_box = VBox([
        pre_info, pre_heto_chec, pre_heto_chec_box, pre_pixel_connectivity,
        pre_negative_buffer,
        HBox([
            pre_min_cluster_size,
            HTML("""Minimum area for clusters selection - only clusters bigger
                    from this threshold will be counted.""")
        ])
    ])

    # Run FOI analysis
    run_info = Label("5. Run the FOI analysis.")
    run_analysis = Button(
        description='Run FOI v2',
        value=False,
        disabled=False,
        button_style='info',
        tooltip='Run FOI analysis version 2',
        icon='play',
    )
    run_box = HBox([run_analysis])

    @run_analysis.on_click
    def run_analysis_on_click(b):
        with progress:
            foi_v2.main(f"{shp_file.children[1].children[0].value}",
                        f"{img_file.children[1].children[0].value}",
                        f"{yml_file.children[1].children[0].value}",
                        pre_negative_buffer.value, pre_min_het.value,
                        pre_max_het.value, pre_pixel_connectivity.value,
                        pre_min_cluster_size.value)

    wbox_v2 = VBox([
        foi_info, shp_box, img_box, yml_box, pre_box, run_info, run_box,
        progress
    ])

    return wbox_v2