def plot_predicted_probabilities(predictions, groundtruth, n_classes, uncertainty): """ plot predictions with ground truth arguments --------- predictions: numpy nd.array probability maps of classes of patches shape = (n_patches, patch_size_padded, patch_size_padded, n_classes) groundtruth: numpy nd.array one-hot lables of patches shape = (n_patches, patch_size_padded, patch_size_padded, n_classes) nclasses: int number of prediction classes uncertainty: float between 0 and 1 if uncertainty is higher than this number, class 'unsure' is assigned output ------ figure with predictionsmaps plotted in first n rows and ground truth in last row. The columns represent differnet patches. """ #colors_extra = ['linen', 'lightgreen', 'limegreen', 'darkgreen', 'yellow', 'black'] colors_extra = np.array([(194/256,230/256,153/256),(120/256,198/256,121/256), (49/256,163/256,84/256),(0/256,76/256,38/256),(229/256,224/256,204/256),(0,0,0)]) cmap_extra = ListedColormap(colors_extra) n_patches = len(predictions) rows = 7 # prepare fig, ax = plt.subplots(rows,n_patches) for i in range(n_patches): im = predictions[i] gt = groundtruth[i] # prepare prediction plot plt_im = np.zeros_like(im, dtype=np.uint8) plt_im = np.argmax(im, axis=2) plt_im[np.max(im, axis=2)<(1-uncertainty)] = 5 # plot probability maps for j in range(n_classes): ax[j,i].imshow(im[:,:,j], vmin=0, vmax=1) # prepare gt plot plt_gt = np.zeros_like(gt, dtype=np.uint8) plt_gt = np.argmax(gt, axis=2) # plot prediction im = ax[5,i].imshow(plt_im, cmap=cmap_extra, vmin=0, vmax=5) # plot gt grtr = ax[6,i].imshow(plt_gt, cmap=cmap, vmin=0, vmax=4) ep.draw_legend(im,titles=["tara0", "tara20", "tara50", "forest","non-cultivable","not sure"],classes=[0, 1, 2, 3,4,5])
def NDVI(bands, year): """Normalized Difference Vegetation Index (NDVI)""" #ndvi = es.normalized_diff(band4, band3) # (band4-band3)/(band4+band3) ndvi = es.normalized_diff(bands[3], bands[2]) # (band4-band3)/(band4+band3) titles = ['Normalized Difference Vegetation Index (NDVI) Year: %s' %year] # Turn off bytescale scaling due to float values for NDVI ep.plot_bands(ndvi, cmap="RdYlGn", cols=1, title=titles, vmin=-1, vmax=1) # Create classes and apply to NDVI results ndvi_class_bins = [-np.inf, 0, 0.25, 0.5, 0.75, np.inf] ndvi_landsat_class = np.digitize(ndvi, ndvi_class_bins) # Define color map and class names ndvi_colors = ListedColormap(['gray', 'y', 'yellowgreen', 'g', 'darkgreen']) ndvi_names = ['0.00 No Vegetation','0.25 Bare Area','0.50 Low Vegetation','0.75 Moderate Vegetation','1.00 High Vegetation'] # Get list of classes classes = np.unique(ndvi_landsat_class).tolist() fig, ax = plt.subplots(figsize=(8, 8)) im = ax.imshow(ndvi_landsat_class, cmap=ndvi_colors) ep.draw_legend(im_ax=im, classes=classes, titles=ndvi_names) ax.set_title('Normalized Difference Vegetation Index (NDVI) Classes. \nYear: %s' %yr,fontsize=14) ax.set_axis_off(); plt.tight_layout() plt.show()
def test_non_ax_obj(): """Draw_legend fun should raise AttributeError if provided with a non mpl axis object""" with pytest.raises( AttributeError, match="The legend function requires a matplotlib axis object", ): ep.draw_legend(im_ax=list())
def plot_predicted_patches(predictions, groundtruth, patch=None): """ plot predicted patches with ground truth arguments --------- predictions: numpy nd.array probability maps of classes of patches shape = (n_patches, patch_size_padded, patch_size_padded, n_classes) groundtruth: numpy nd.array one-hot lables of patches shape = (n_patches, patch_size_padded, patch_size_padded, n_classes) patch: numpy.ndarray image of patch shape = (n_patches, patch_size_padded, patch_size_padded, n_classes) output ------ figure with n predictions plotted in first row and ground truth in second row. if patch is specified the third row contains RGB image """ n_patches = len(predictions) cols = 2 if np.any(patch != None): cols = 3 # prepare fig, ax = plt.subplots(n_patches,cols, figsize=(15,15)) for i in range(n_patches): im = predictions[i] gt = groundtruth[i] # prepare prediction plot plt_im = np.zeros_like(im, dtype=np.uint8) plt_im = np.argmax(im, axis=2) # prepare gt plot plt_gt = np.zeros_like(gt, dtype=np.uint8) plt_gt = np.argmax(gt, axis=2) # plot training image ax[i,0].imshow(plt_im, cmap=cmap, vmin=0, vmax=4) # plot gt grtr = ax[i,1].imshow(plt_gt, cmap=cmap, vmin=0, vmax=4) # plot RGB if np.any(patch != None): plt_im = patch[i][:, :, [0,1,2]].astype(np.float64) ax[i,2].imshow(plt_im) ep.draw_legend(grtr,titles=["tara0", "tara20", "tara50", "woods","no coltivable"],classes=[0, 1, 2, 3,4])
def test_listedcmap_ncol_equals_nclasses(vals_missing_plot_list_cmap): """If a 5 color listed cmap is provided and 6 classes are specified, return value error""" n_classes = 5 im_ax, arr = vals_missing_plot_list_cmap with pytest.raises( ValueError, match="There are more classes than colors in your cmap"): ep.draw_legend(im_ax, classes=np.arange(0, n_classes + 1)) plt.close()
def test_subplots(binned_array): """Test to ensure that a plot with subplots still has a legend.""" bins, arr_class = binned_array f, (ax1, ax2) = plt.subplots(2, 1) im_ax = ax1.imshow(arr_class) ep.draw_legend(im_ax) im_ax2 = ax2.imshow(arr_class) ep.draw_legend(im_ax2) plt.close(f)
def plot_random_patches(patches_path, n_patches, classes, class_names): """ plot random patches with ground truth arguments --------- patches_path: string path to folder containing the patches n_patches: int number of random patches to plot classes: list list of predicted classes class_names: list output ------ figure with n_patches plotted in first row and ground truth in second row. """ images_path = patches_path + 'images/' labels_path = patches_path + 'labels/' rows = 2 cols = n_patches # get path images list im_list = list_files(images_path, '.npy') gt_list = list_files(labels_path, '.npy') # prepare index = np.array([0,1,2]) fig, ax = plt.subplots(rows,cols) for i in range(n_patches): idx=np.random.randint(len(im_list)) im = np.load(images_path + im_list[idx]) gt = np.load(labels_path + gt_list[idx]) # prepare RGB plot plt_im = im[:, :, index].astype(np.float64) # prepare gt plot plt_gt = np.zeros_like(gt, dtype=np.uint8) plt_gt = np.argmax(gt, axis=2) # plot training image image = ax[0,i].imshow(plt_im) # plot gt grtr = ax[1,i].imshow(plt_gt, cmap=cmap, vmin=0, vmax=4) #colors not right ep.draw_legend(grtr,titles=class_names,classes=classes)
def plot_categorical_w_window(self, output_file, labels, cmap, xy, width, height, box=True): """Creates a figure of a categorical raster with a zoomed window :param output_file: path, file path of the figure :param labels: list of strings, labels (i.e., titles)for the categories :param cmap: string, colormap to plot the raster :param xy: tuple (x,y), origin of the zoomed window, the upper left corner :param width: integer, width (number of cells) of the zoomed window :param height: integer, height (number of cells) of the zoomed window :returns: saves the figure of the raster """ raster_np = read_raster(self.path) print('Classes identified in the raster: ', np.unique(raster_np)) # cmap = matplotlib.colors.ListedColormap(list_colors) fig, ax = plt.subplots(1, 2) ax[0].imshow(raster_np, cmap=cmap) rectangle = patches.Rectangle(xy, width, height, fill=False) ax[0].add_patch(rectangle) plt.setp(ax, xticks=[], yticks=[]) # Plot Patch box_np = raster_np[xy[1]: xy[1] + height, xy[0]: xy[0] + width] im = ax[1].imshow(box_np, cmap=cmap) cbar = ep.draw_legend(im, titles=labels) # cbar.ax[].tick_params(labelsize=20) if not box: ax.axis('off') fig.savefig(output_file, dpi=700, bbox_inches='tight')
def test_listed_cmap(arr_plot_list_cmap): """Test that the the legend generates properly when provided with a ListedColormap""" im_ax, arr = arr_plot_list_cmap leg = ep.draw_legend(im_ax) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == len(np.unique(arr)) plt.close()
def test_num_titles_classes(binned_array_3bins): """Test to ensure the the number of "handles" or classes provided for each legend items matches the number of classes being used to build the legend. This case should return a ValueError if these items are different""" bins, im_arr_bin = binned_array_3bins im_arr_bin[im_arr_bin == 2] = 3 fig, ax = plt.subplots(figsize=(5, 5)) im_ax = ax.imshow(im_arr_bin, cmap="Blues") with pytest.raises(ValueError): ep.draw_legend(im_ax=im_ax, classes=[1, 2], titles=["small", "medium", "large"]) with pytest.raises(ValueError): ep.draw_legend(im_ax=im_ax, classes=[1, 2, 3], titles=["small", "large"])
def plot_patches(patch, gt, n_patches): """ plot patches with ground truth arguments --------- patch: numpy.ndarray image of patch shape = (n_patches, patch_size_padded, patch_size_padded, n_classes) gt: numpy.ndarray one-hot lables of patches shape = (n_patches, patch_size_padded, patch_size_padded, n_classes) n_patches: int number of random patches to plot output ------ figure with n_patches plotted in first row and ground truth in second row. """ rows = 2 cols = n_patches # prepare index = np.array([0,1,2]) fig, ax = plt.subplots(rows,cols) for i in range(n_patches): # prepare RGB plot plt_im = patch[i][:, :, index].astype(np.float64) # prepare gt plot plt_gt = np.zeros_like(gt[i], dtype=np.uint8) plt_gt = np.argmax(gt[i], axis=2) # plot training image image = ax[0,i].imshow(plt_im) # plot gt grtr = ax[1,i].imshow(plt_gt, cmap=cmap, vmin=0, vmax=4) ep.draw_legend(grtr,titles=["tara0", "tara20", "tara50", "forest","non-cultivable"],classes=[0, 1, 2, 3,4])
def test_noncont_listed_cmap(vals_missing_plot_list_cmap): """An arr with 3 vals (missing the 1, and 5) which requires normalization produces creates a legend with 3 handles.""" im_ax, arr = vals_missing_plot_list_cmap leg = ep.draw_legend(im_ax) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == len(np.unique(arr)) plt.close()
def test_classes_provided_as_array(arr_plot_list_cmap): """Test that draw_legend works when classes are provided as an arr (not a list).""" im_ax, arr = arr_plot_list_cmap n_classes = 5 leg = ep.draw_legend(im_ax, classes=np.arange(n_classes)) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == n_classes plt.close()
def test_neg_vals(): """Test that the legend plots when positive and negative values are provided""" arr = np.array([[-1, 0, 1], [1, 0, -1]]) f, ax = plt.subplots() im_ax = ax.imshow(arr) leg_neg = ep.draw_legend(im_ax) legend_cols = [i.get_facecolor() for i in leg_neg.get_patches()] assert len(legend_cols) == len(np.unique(arr)) plt.close(f)
def test_neg_vals(binned_array): """Test that the things plot when positive and negative vales are provided""" bins, arr_class = binned_array f, ax = plt.subplots() im_ax = ax.imshow(arr_class) leg_neg = ep.draw_legend(im_ax) legend_cols = [i.get_facecolor() for i in leg_neg.get_patches()] assert len(legend_cols) == len(bins) - 1 plt.close(f)
def plot_categorical_raster(self, output_file, labels, cmap, box=True): """Creates a figure of a categorical raster :param output_file: path, file path of the figure :param labels: list of strings, labels (i.e., titles)for the categories :param cmap: string, colormap to plot the raster :param box: boolean, if False it sets off the frame of the picture :returns: saves the figure of the raster """ raster_np = read_raster(self.path) print('Classes identified in the raster: ', np.unique(raster_np)) # cmap = matplotlib.colors.ListedColormap(list_colors) fig, ax = plt.subplots() im = ax.imshow(raster_np, cmap=cmap) ep.draw_legend(im, titles=labels) ax.set_axis_off() # plt.show() if not box: ax.axis('off') fig.savefig(output_file, dpi=200, bbox_inches='tight')
def test_num_titles_classes(arr_plot_blues): """Test that the number of classes equals the number of legend titles""" im_ax, _ = arr_plot_blues with pytest.raises( ValueError, match="The number of classes should equal the number of titles", ): ep.draw_legend(im_ax=im_ax, classes=[1, 2], titles=["small", "medium", "large"]) with pytest.raises( ValueError, match="The number of classes should equal the number of titles", ): ep.draw_legend(im_ax=im_ax, classes=[1, 2, 3], titles=["small", "large"]) plt.close()
def test_cont_cmap_3_classes(vals_missing_plot_cont_cmap): """Test legend for a listed cmap where the user wants all classes to be drawn in the legend. IE the classified image has classes 2,3,4 and the user wants classes 1-5 to appear """ im_ax, arr = vals_missing_plot_cont_cmap class_list = list(range(5)) leg = ep.draw_legend(im_ax, classes=class_list) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == len(class_list) plt.close()
def test_stock_legend_titles(arr_plot_blues): """Test that the correct number of default titles plot""" im_ax, im_arr_bin = arr_plot_blues # Default legend title values def_titles = ["Category {}".format(i) for i in np.unique(im_arr_bin)] the_legend = ep.draw_legend(im_ax=im_ax) # Legend handle titles should equal unique values in ax array assert len(the_legend.get_texts()) == len(np.unique( im_ax.get_array().data)) assert def_titles == [text.get_text() for text in the_legend.get_texts()] plt.close()
def test_colors(arr_plot_blues): """Test that the correct colors appear in the patches of the legend""" im_ax, _ = arr_plot_blues the_legend = ep.draw_legend(im_ax=im_ax) legend_cols = [i.get_facecolor() for i in the_legend.get_patches()] # Get the array and cmap from axis object cmap_name = im_ax.axes.get_images()[0].get_cmap().name unique_vals = np.unique(im_ax.get_array().data) image_colors = ep.make_col_list(unique_vals, cmap=cmap_name) assert image_colors == legend_cols plt.close()
def test_custom_legend_titles(arr_plot_blues): """Test that the correct number of custom legend titles plot""" im_ax, _ = arr_plot_blues custom_titles = ["one", "two", "three"] the_legend = ep.draw_legend(im_ax=im_ax, titles=custom_titles) assert len(the_legend.get_texts()) == len(np.unique( im_ax.get_array().data)) assert custom_titles == [ text.get_text() for text in the_legend.get_texts() ] plt.close()
def test_custom_legend_titles(binned_array_3bins): """Test that the correct number of and text for custom legend titles plot when titles parameter = None""" bins, im_arr_bin = binned_array_3bins f, ax = plt.subplots() imp2 = ax.imshow(im_arr_bin, cmap="Blues") custom_titles = ["one", "two", "three"] the_legend = ep.draw_legend(im_ax=imp2, titles=custom_titles) assert len(the_legend.get_texts()) == len(np.unique(imp2.get_array().data)) assert custom_titles == [ text.get_text() for text in the_legend.get_texts() ] plt.close(f)
def test_noncont_listed_cmap_3_classes(binned_array, listed_cmap): """Test legend for a non continuous listed cmap where the user wants all classes to be drawn in the legend. IE the classified image has classes 2,3,4 and the user wants classes 1-5 to appear """ cmap, norm = listed_cmap bins, arr_class = binned_array f, ax = plt.subplots(figsize=(5, 5)) im = ax.imshow(arr_class, cmap=cmap, norm=norm) leg = ep.draw_legend(im, classes=[1, 2, 3, 4, 5]) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == len([1, 2, 3, 4, 5]) plt.close(f)
def test_listed_cmap(binned_array): """Test that the the legend generates properly when provided with a Listed colormap""" bins, arr_class = binned_array # TODO make the list of colors a fixture for reuse cmap_list = ListedColormap( ["white", "tan", "purple", "springgreen", "darkgreen"]) f, ax = plt.subplots() im_plt = ax.imshow(arr_class, cmap=cmap_list) leg = ep.draw_legend(im_plt) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == len(bins) - 1 plt.close(f)
def test_masked_vals(): """Test to ensure that a masked array plots properly""" im_arr = np.random.uniform(-2, 1, (15, 15)) bins = [-0.8, -0.2, 0.2, 0.8, np.Inf] im_arr_bin = np.digitize(im_arr, bins) arr_bin_ma = np.ma.masked_equal(im_arr_bin, 0) unmasked_vals = [ val for val in np.unique(arr_bin_ma) if val is not np.ma.core.masked ] f, ax = plt.subplots() im_ax = ax.imshow(arr_bin_ma) leg = ep.draw_legend(im_ax) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == len(unmasked_vals) plt.close(f)
def test_colors(binned_array_3bins): """Test that the correct colors appear in the patches of the legend""" bins, im_arr_bin = binned_array_3bins f, ax = plt.subplots() im = ax.imshow(im_arr_bin, cmap="Blues") the_legend = ep.draw_legend(im_ax=im) # NOTE: Do I know for sure things are rendering in the right order? legend_cols = [i.get_facecolor() for i in the_legend.get_patches()] # Get the array and cmap from axis object cmap_name = im.axes.get_images()[0].get_cmap().name unique_vals = np.unique(im.get_array().data) image_colors = ep.make_col_list(unique_vals, cmap=cmap_name) assert image_colors == legend_cols
def test_stock_legend_titles(binned_array_3bins): """Test that the correct number of generic titles plot when titles parameter = None""" bins, im_arr_bin = binned_array_3bins f, ax = plt.subplots() imp2 = ax.imshow(im_arr_bin, cmap="Blues") # Default legend title values should be def_titles = ["Category {}".format(i) for i in np.unique(im_arr_bin)] the_legend = ep.draw_legend(im_ax=imp2) # Legend handle titles should equal unique values in ax array assert len(the_legend.get_texts()) == len(np.unique(imp2.get_array().data)) assert def_titles == [text.get_text() for text in the_legend.get_texts()] plt.close(f)
def test_noncont_listed_cmap(binned_array, listed_cmap): """Test that an arr with 3 classes (missing the 1, and 5) which would need to be normalized, only creates a legend with x handles by default""" cmap, norm = listed_cmap bins, arr_class = binned_array arr_class[arr_class == 1] = 2 arr_class[arr_class == 5] = 4 f, ax = plt.subplots(figsize=(5, 5)) im = ax.imshow(arr_class, cmap=cmap, norm=norm) leg = ep.draw_legend(im) legend_cols = [i.get_facecolor() for i in leg.get_patches()] assert len(legend_cols) == len(np.unique(arr_class)) plt.close(f)
nbr_cmap = ListedColormap(nbr_colors) # Define class names ndvi_cat_names = [ "No Vegetation", "Bare Area", "Low Vegetation", "Moderate Vegetation", "High Vegetation", ] # Get list of classes classes = np.unique(ndvi_landsat_class) classes = classes.tolist() # The mask returns a value of none in the classes. remove that classes = classes[0:5] # Plot your data fig, ax = plt.subplots(figsize=(12, 12)) im = ax.imshow(ndvi_landsat_class, cmap=nbr_cmap) ep.draw_legend(im_ax=im, classes=classes, titles=ndvi_cat_names) ax.set_title( "Landsat 8 - Normalized Difference Vegetation Index (NDVI) Classes", fontsize=14, ) ax.set_axis_off() # Auto adjust subplot to fit figure size plt.tight_layout()
# Create a colormap with 11 colors cmap = plt.cm.get_cmap('tab20b', 11) # Get a list of unique values in the qa layer vals = np.unique(landsat_qa).tolist() bins = [0] + vals # Normalize the colormap bounds = [((a + b) / 2) for a, b in zip(bins[:-1], bins[1::1])] + \ [(bins[-1] - bins[-2]) + bins[-1]] norm = colors.BoundaryNorm(bounds, cmap.N) # Plot the data fig, ax = plt.subplots(figsize=(12, 8)) im = ax.imshow(landsat_qa, cmap=cmap, norm=norm) ep.draw_legend(im, classes=vals, cmap=cmap, titles=vals) ax.set_title("Landsat Collection Quality Assessment Layer") ax.set_axis_off() plt.show() # - # In the image above, you can see the cloud and the shadow that is obstructing our landsat image. # Unfortunately for you, this cloud covers a part of your analysis area in the Cold Springs # Fire location. There are a few ways to handle this issue. We will look at one: # simply masking out or removing the cloud for your analysis, first. # # To remove all pixels that are cloud and cloud shadow covered we need to first # determine what each value in our qa raster represents. The table below is from the USGS landsat website. # It describes what all of the values in the pixel_qa layer represent. #