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
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
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
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
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>'));
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()
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()
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
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 ])
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
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
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 ])
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
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