def update(self): scores = self.pred_scores[self.vis_image_index] im = self.dataset[self.vis_image_index][0] # fastai Image object _, sort_order = self._list_sort(scores, reverse=True) pred_labels_str = "" for i in sort_order: pred_labels_str += f"{self.labels[i]} ({scores[i]:3.2f})\n" self.w_pred_labels.value = str(pred_labels_str) self.w_image_header.value = f"Image index: {self.vis_image_index}" self.w_img.value = im._repr_png_() # Fix the width of the image widget and adjust the height self.w_img.layout.height = ( f"{int(self.IM_WIDTH * (im.size[1]/im.size[0]))}px") self.w_gt_label.value = str( self.labels[self.dataset[self.vis_image_index][1]]) self.w_filename.value = str( self.dataset.items[self.vis_image_index].name) self.w_path.value = str( self.dataset.items[self.vis_image_index].parent) bqpyplot.clear() bqpyplot.bar( self.labels, scores, align="center", alpha=1.0, color=np.abs(scores), scales={"color": bqplot.ColorScale(scheme="Blues", min=0)}, )
def update_ui(self): pred_label = self.pred_labels[self.vis_image_index] img_obj = self.dataset.images[self.vis_image_index] scores = self.pred_scores[self.vis_image_index] self.w_image_header.value = "Image index: {}".format( self.vis_image_index) self.w_img.value = wImread(img_obj, self.context) self.w_gt_label.value = self.dataset.get_labels_for_image( img_obj)[0].name self.w_pred_label.value = str(pred_label) self.w_pred_score.value = str( self.pred_scores[self.vis_image_index, self.label_to_id[pred_label]]) self.w_index.value = str(self.vis_image_index) self.w_filename.value = img_obj.name self.w_path.value = img_obj.storage_path bqPyplot.clear() bqPyplot.bar( self.labels, scores, align='center', alpha=1.0, color=np.abs(scores), scales={'color': bqplot.ColorScale(scheme='Blues', min=0)})
def updateUI(self): predLabel = self.predLabels[self.visImageIndex] imgObj = self.dataset.images[self.visImageIndex] scores = self.predScores[self.visImageIndex] self.wImageHeader.value = "Image index: {}".format(self.visImageIndex) self.wImg.value = wImread(imgObj, self.imgOrigDir) self.wGtLabel.value = imgObj.label self.wPredLabel.value = str(self.lutId2Label[predLabel]) self.wPredScore.value = str(self.predScores[self.visImageIndex, predLabel]) self.wIndex.value = str(self.visImageIndex) self.wFilename.value = imgObj.filename bqPyplot.clear() bqPyplot.bar( self.labels, scores, align='center', alpha=1.0, color=np.abs(scores), scales={'color': bqplot.ColorScale(scheme='Blues', min=0)})
def vue_do_aper_phot(self, *args, **kwargs): if self._selected_data is None or self._selected_subset is None: self.result_available = False self.results = [] self.plot_available = False self.radial_plot = '' self.hub.broadcast(SnackbarMessage( "No data for aperture photometry", color='error', sender=self)) return data = self._selected_data reg = self._selected_subset try: comp = data.get_component(data.main_components[0]) try: bg = float(self.background_value) except ValueError: # Clearer error message raise ValueError('Missing or invalid background value') comp_no_bg = comp.data - bg # TODO: Use photutils when it supports astropy regions. if not isinstance(reg, RectanglePixelRegion): aper_mask = reg.to_mask(mode='exact') else: # TODO: https://github.com/astropy/regions/issues/404 (moot if we use photutils?) aper_mask = reg.to_mask(mode='subpixels', subpixels=32) npix = np.sum(aper_mask) * u.pix img = aper_mask.get_values(comp_no_bg, mask=None) aper_mask_stat = reg.to_mask(mode='center') comp_no_bg_cutout = aper_mask_stat.cutout(comp_no_bg) img_stat = aper_mask_stat.get_values(comp_no_bg, mask=None) include_pixarea_fac = False include_counts_fac = False include_flux_scale = False if comp.units: img_unit = u.Unit(comp.units) img = img * img_unit img_stat = img_stat * img_unit bg = bg * img_unit comp_no_bg_cutout = comp_no_bg_cutout * img_unit if u.sr in img_unit.bases: # TODO: Better way to detect surface brightness unit? try: pixarea = float(self.pixel_area) except ValueError: # Clearer error message raise ValueError('Missing or invalid pixel area') if not np.allclose(pixarea, 0): include_pixarea_fac = True if img_unit != u.count: try: ctfac = float(self.counts_factor) except ValueError: # Clearer error message raise ValueError('Missing or invalid counts conversion factor') if not np.allclose(ctfac, 0): include_counts_fac = True try: flux_scale = float(self.flux_scaling) except ValueError: # Clearer error message raise ValueError('Missing or invalid flux scaling') if not np.allclose(flux_scale, 0): include_flux_scale = True rawsum = np.nansum(img) d = {'id': 1, 'xcenter': reg.center.x * u.pix, 'ycenter': reg.center.y * u.pix} if data.coords is not None: d['sky_center'] = data.coords.pixel_to_world(reg.center.x, reg.center.y) else: d['sky_center'] = None d.update({'background': bg, 'npix': npix}) if include_pixarea_fac: pixarea = pixarea * (u.arcsec * u.arcsec / u.pix) pixarea_fac = npix * pixarea.to(u.sr / u.pix) d.update({'aperture_sum': rawsum * pixarea_fac, 'pixarea_tot': pixarea_fac}) else: d.update({'aperture_sum': rawsum, 'pixarea_tot': None}) if include_counts_fac: ctfac = ctfac * (rawsum.unit / u.count) sum_ct = rawsum / ctfac d.update({'aperture_sum_counts': sum_ct, 'aperture_sum_counts_err': np.sqrt(sum_ct.value) * sum_ct.unit, 'counts_fac': ctfac}) else: d.update({'aperture_sum_counts': None, 'aperture_sum_counts_err': None, 'counts_fac': None}) if include_flux_scale: flux_scale = flux_scale * rawsum.unit d.update({'aperture_sum_mag': -2.5 * np.log10(rawsum / flux_scale) * u.mag, 'flux_scaling': flux_scale}) else: d.update({'aperture_sum_mag': None, 'flux_scaling': None}) # Extra stats beyond photutils. d.update({'mean': np.nanmean(img_stat), 'stddev': np.nanstd(img_stat), 'median': np.nanmedian(img_stat), 'min': np.nanmin(img_stat), 'max': np.nanmax(img_stat), 'data_label': data.label, 'subset_label': reg.meta.get('label', ''), 'timestamp': Time(datetime.utcnow())}) # Attach to app for Python extraction. if (not hasattr(self.app, '_aper_phot_results') or not isinstance(self.app._aper_phot_results, QTable)): self.app._aper_phot_results = _qtable_from_dict(d) else: try: d['id'] = self.app._aper_phot_results['id'].max() + 1 self.app._aper_phot_results.add_row(d.values()) except Exception: # Discard incompatible QTable d['id'] = 1 self.app._aper_phot_results = _qtable_from_dict(d) # Radial profile reg_bb = reg.bounding_box reg_ogrid = np.ogrid[reg_bb.iymin:reg_bb.iymax, reg_bb.ixmin:reg_bb.ixmax] radial_dx = reg_ogrid[1] - reg.center.x radial_dy = reg_ogrid[0] - reg.center.y radial_r = np.hypot(radial_dx, radial_dy).ravel() # pix radial_img = comp_no_bg_cutout.ravel() if comp.units: y_data = radial_img.value y_label = radial_img.unit.to_string() else: y_data = radial_img y_label = 'Value' bqplt.clear() # NOTE: default margin in bqplot is 60 in all directions fig = bqplt.figure(1, title='Radial profile from Subset center', fig_margin={'top': 60, 'bottom': 60, 'left': 40, 'right': 10}, title_style={'font-size': '12px'}) # TODO: Jenn wants title at bottom. # noqa bqplt.plot(radial_r, y_data, 'go', figure=fig, default_size=1) bqplt.xlabel(label='pix', mark=fig.marks[-1], figure=fig) bqplt.ylabel(label=y_label, mark=fig.marks[-1], figure=fig) except Exception as e: # pragma: no cover self.result_available = False self.results = [] self.plot_available = False self.radial_plot = '' self.hub.broadcast(SnackbarMessage( f"Aperture photometry failed: {repr(e)}", color='error', sender=self)) else: # Parse results for GUI. tmp = [] for key, x in d.items(): if key in ('id', 'data_label', 'subset_label', 'background', 'pixarea_tot', 'counts_fac', 'aperture_sum_counts_err', 'flux_scaling', 'timestamp'): continue if (isinstance(x, (int, float, u.Quantity)) and key not in ('xcenter', 'ycenter', 'sky_center', 'npix', 'aperture_sum_counts')): x = f'{x:.4e}' tmp.append({'function': key, 'result': x}) elif key == 'sky_center' and x is not None: tmp.append({'function': 'RA center', 'result': f'{x.ra.deg:.4f} deg'}) tmp.append({'function': 'Dec center', 'result': f'{x.dec.deg:.4f} deg'}) elif key in ('xcenter', 'ycenter', 'npix'): x = f'{x:.1f}' tmp.append({'function': key, 'result': x}) elif key == 'aperture_sum_counts' and x is not None: x = f'{x:.4e} ({d["aperture_sum_counts_err"]:.4e})' tmp.append({'function': key, 'result': x}) elif not isinstance(x, str): x = str(x) tmp.append({'function': key, 'result': x}) self.results = tmp self.result_available = True self.radial_plot = fig self.bqplot_figs_resize = [fig] self.plot_available = True
def submit_clicked(b): with output_widget: output_widget.clear_output() print('Computing...') Map.default_style = {'cursor': 'wait'} try: admin1_id = admin1_widget.value admin2_id = admin2_widget.value band1 = first_band.value band2 = second_band.value selected_year = year_widget.value threshold = nd_threshold.value bands = band_combo.value.split('/') apply_fmask = fmask_widget.value palette = nd_color.value use_aoi = aoi_widget.value download = download_widget.value if use_aoi: if Map.user_roi is not None: roi = Map.user_roi layer_name = 'User drawn AOI' geom = roi else: output_widget.clear_output() print('No user AOI could be found.') return else: statefp = ee.Feature(states.filter(ee.Filter.eq('NAME', admin1_id)).first()).get('STATEFP') roi = fc.filter(ee.Filter.And(ee.Filter.eq('NAME', admin2_id), ee.Filter.eq('STATEFP', statefp))) layer_name = admin1_id + '-' + admin2_id geom = roi.geometry() Map.layers = Map.layers[:4] Map.addLayer(ee.Image().paint(geom, 0, 2), {'palette': 'red'}, layer_name) images = geemap.landsat_timeseries(roi=roi, start_year=1984, end_year=2020, start_date='01-01', end_date='12-31', apply_fmask=apply_fmask) nd_images = images.map(lambda img: img.normalizedDifference([band1, band2])) result_images = nd_images.map(lambda img: img.gt(threshold)) selected_image = ee.Image(images.toList(images.size()).get(selected_year - 1984)) selected_result_image = ee.Image(result_images.toList(result_images.size()).get(selected_year - 1984)).selfMask() vis_params = { 'bands': bands, 'min': 0, 'max': 3000 } Map.addLayer(selected_image, vis_params, 'Landsat ' + str(selected_year)) Map.addLayer(selected_result_image, {'palette': palette}, 'Result ' + str(selected_year)) def cal_area(img): pixel_area = img.multiply(ee.Image.pixelArea()).divide(1e4) img_area = pixel_area.reduceRegion(**{ 'geometry': geom, 'reducer': ee.Reducer.sum(), 'scale': 1000, 'maxPixels': 1e12, 'bestEffort': True }) return img.set({'area': img_area}) areas = result_images.map(cal_area) stats = areas.aggregate_array('area').getInfo() x = list(range(1984, 2021)) y = [item.get('nd') for item in stats] fig = plt.figure(1) fig.layout.height = '270px' plt.clear() plt.plot(x, y) plt.title('Temporal trend (1984-2020)') plt.xlabel('Year') plt.ylabel('Area (ha)') output_widget.clear_output() plt.show() if download: out_dir = os.path.join(os.path.expanduser('~'), 'Downloads') out_name = 'chart_' + geemap.random_string() + '.csv' out_csv = os.path.join(out_dir, out_name) if not os.path.exists(out_dir): os.makedirs(out_dir) with open(out_csv, 'w') as f: f.write('year, area (ha)\n') for index, item in enumerate(x): line = '{},{:.2f}\n'.format(item, y[index]) f.write(line) link = geemap.create_download_link( out_csv, title="Click here to download the chart data: ") display(link) except Exception as e: print(e) print('An error occurred during computation.') Map.default_style = {'cursor': 'default'}
def plot(self, x, y, plot_type=None, overlay=False, position='bottomright', min_width=None, max_width=None, min_height=None, max_height=None, **kwargs): """Creates a plot based on x-array and y-array data. Args: x (numpy.ndarray or list): The x-coordinates of the plotted line. y (numpy.ndarray or list): The y-coordinates of the plotted line. plot_type (str, optional): The plot type can be one of "None", "bar", "scatter" or "hist". Defaults to None. overlay (bool, optional): Whether to overlay plotted lines on the figure. Defaults to False. position (str, optional): Position of the control, can be ‘bottomleft’, ‘bottomright’, ‘topleft’, or ‘topright’. Defaults to 'bottomright'. min_width (int, optional): Min width of the widget (in pixels), if None it will respect the content size. Defaults to None. max_width (int, optional): Max width of the widget (in pixels), if None it will respect the content size. Defaults to None. min_height (int, optional): Min height of the widget (in pixels), if None it will respect the content size. Defaults to None. max_height (int, optional): Max height of the widget (in pixels), if None it will respect the content size. Defaults to None. """ if self.plot_widget is not None: plot_widget = self.plot_widget else: plot_widget = widgets.Output(layout={'border': '1px solid black'}) plot_control = WidgetControl(widget=plot_widget, position=position, min_width=min_width, max_width=max_width, min_height=min_height, max_height=max_height) self.plot_widget = plot_widget self.plot_control = plot_control self.add_control(plot_control) if max_width is None: max_width = 500 if max_height is None: max_height = 300 if (plot_type is None) and ('markers' not in kwargs.keys()): kwargs['markers'] = 'circle' with plot_widget: try: fig = plt.figure(1, **kwargs) if max_width is not None: fig.layout.width = str(max_width) + 'px' if max_height is not None: fig.layout.height = str(max_height) + 'px' plot_widget.clear_output(wait=True) if not overlay: plt.clear() if plot_type is None: if 'marker' not in kwargs.keys(): kwargs['marker'] = 'circle' plt.plot(x, y, **kwargs) elif plot_type == 'bar': plt.bar(x, y, **kwargs) elif plot_type == 'scatter': plt.scatter(x, y, **kwargs) elif plot_type == 'hist': plt.hist(y, **kwargs) plt.show() except Exception as e: print(e) print("Failed to create plot.")