def eidw(self, power=2.0, anisotropy=5.0, smoothie=0, plane='sn', plot=False): """ Performs Elliptical Inverse Distance Weighting (EIDW) interpolation to the instance's data Kwargs: power <float> : power parameter, should be above 2.0 anisotropy <float> : anisotropy parameter: if >1.0, it brings points closer in the longitudinal (s) direction, if <1.0 it brings points closer in the transverse (n) direction smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented plot <boolean> : decides to plot or not the resulting EIDW values """ gc.enable() print "Calculating: Elliptical Inverse Distance Weighting [EIDW]" #check if power < 2.0: print "Warning: Power parameter too small; set to 2.0." power = 2.0 eidw = deepcopy(self.z) #avoid overwrite #calculate EIDW (radius='None' executes global EIDW) if plane == 'sn': eidw[self.nodata] = self.eidw_interpol(self.s[self.isdata], self.n[self.isdata], eidw[self.isdata], self.s[self.nodata], self.n[self.nodata], power, anisotropy, 'None') elif plane == 'xy': x = self.x.flatten() y = self.y.flatten() eidw[self.nodata] = self.eidw_interpol( x[self.isdata], y[self.isdata], eidw[self.isdata], x[self.nodata], y[self.nodata], power, anisotropy, 'None') else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return #grid (matrix) notation eidw = common.to_grid(eidw, self.rows, self.cols) #add pre-defined banks eidw = self.__add_banks(eidw) #smoothen for i in range(self.rows): eidw[i, :] = common.smooth(eidw[i, :], smoothie) print "Finished [EIDW]." self.z_interpol = eidw del eidw #plot if plot: self.plot(fignum='EIDW-GLOBAL')
def error_map(self, x, y, clim, plotname): import matplotlib.pyplot as plt err = self.GT.flatten() - self.P.flatten() levels = np.linspace(clim[0], clim[1], 11) n, m = self.GT.shape plt.figure("Error Map - " + str(plotname)) err = common.to_grid(err, n, m) Gx = common.to_grid(x, n, m) Gy = common.to_grid(y, n, m) #If more than half the points are unknown, the dataset to plot logically must be a testing dataset if np.sum(np.isnan(err)) > err.shape[0] * err.shape[1] / 2.0: print "-> Assuming plot of Testing Dataset." cs = plt.scatter(Gx, Gy, s=10, c=err, cmap=plt.cm.bwr, vmin=clim[0], vmax=clim[1], edgecolors='none') else: cs = plt.contourf(Gx, Gy, err, levels, cmap=plt.cm.bwr, extend='both') cs.cmap.set_over('deeppink') cs.cmap.set_under('k') cs.set_clim(np.floor(levels[0]), np.ceil(levels[-1])) cbar = plt.colorbar(cs) cbar.set_label('Bed Level Difference (m)', labelpad=15, weight='bold', size='14') plt.axis('equal') plt.ion() plt.show()
def rbf(self, method='linear', anisotropy=5.0, smoothie=0, plane='sn', plot=False): """ Performs Radial Basis Interpolation using the defined method (linear or thin plate spline) Kwargs: method <str> : choice of RBF interpolation ['linear' or 'tps'] anisotropy <float> : anisotropy parameter: if >1.0, it brings points closer in the longitudinal (s) direction, if <1.0 it brings points closer in the transverse (n) direction smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented plot <boolean> : decides to plot or not the resulting RBF values """ gc.enable() print "Calculating: Radial Basis Function (RBF) with {0} method".format( method) rbf = deepcopy(self.z) #avoid overwrite #choice of plane and rbf interpolation if plane == 'sn': rbf[self.nodata] = self.rbf_solver( self.s[self.isdata], self.n[self.isdata], rbf[self.isdata], self.s[self.nodata], self.n[self.nodata], anisotropy, method) elif plane == 'xy': x = self.x.flatten() y = self.y.flatten() rbf[self.nodata] = self.rbf_solver(x[self.isdata], y[self.isdata], rbf[self.isdata], x[self.nodata], y[self.nodata], anisotropy, method) else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return rbf = common.to_grid(rbf, self.rows, self.cols) #griddify #add pre-defined banks rbf = self.__add_banks(rbf) #smoothen for i in range(self.rows): rbf[i, :] = common.smooth(rbf[i, :], smoothie) print "Finished [RBF]." self.z_interpol = rbf del rbf #plot if plot: self.plot(fignum='RADIAL-BASIS[{0}]'.format(method.upper()))
def idw(self, power=2.0, smoothie=0, plane='sn', plot=False): """ Performs Inverse Distance Weighting (IDW) interpolation to the instance's data Kwargs: power <float> : power parameter, should be above 2.0 smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented plot <boolean> : decides to plot or not the resulting IDW values """ gc.enable() print "Calculating: Inverse Distance Weighting" #check if power < 2.0: print "Warning: Power parameter too small; set to 2.0." power = 2.0 idw = deepcopy(self.z) #avoid overwrite #calculate IDW (when anisotropy ratio is 1, we have IDW; radius='None' executes global IDW) if plane == 'sn': idw[self.nodata] = self.eidw_interpol( self.s[self.isdata], self.n[self.isdata], idw[self.isdata], self.s[self.nodata], self.n[self.nodata], power, 1.0, 'None') elif plane == 'xy': x = self.x.flatten() y = self.y.flatten() idw[self.nodata] = self.eidw_interpol( x[self.isdata], y[self.isdata], idw[self.isdata], x[self.nodata], y[self.nodata], power, 1.0, 'None') else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return #grid (matrix) notation idw = common.to_grid(idw, self.rows, self.cols) #add pre-defined banks idw = self.__add_banks(idw) #smoothen for i in range(self.rows): idw[i, :] = common.smooth(idw[i, :], smoothie) print "Finished [IDW]." self.z_interpol = idw del idw #plot if plot: self.plot(fignum='IDW-GLOBAL')
def gridify_samples(self, branch): """ Use to set the sample data on the grid, if it is known that the samples respond to the specified grid. """ if self.samples: try: data = zip(*self.samples)[2] #retrive only z values b = str(branch) s = self.gr.grid[b]['x'].shape self.griddeddata[b] = common.to_grid(data, s[0], s[1]) print "Success: Sample data set to grid notation (matrix).\n" except: print "ERROR: Could not transform samples onto gridded data." else: print "No data samples loaded."
def cubic(self, smoothie=0, plane='sn', fill_nans=True, plot=False): """ Performs Cubic interpolation to the instance's data (piecewise cubic, continuously differentiable and approximately curvature-minimizing polynomial surface). WARNING: High memory usage, usually in \'xy\' plane Kwargs: smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented fill_nans <str> : decides to fill NaN values in a linear manner or keep NaN values plot <boolean> : decides to plot or not the resulting CUBIC values """ gc.enable() print "Calculating: Cubic Interpolation" cubic = deepcopy(self.z) #avoid overwrite #choice of plane if plane == 'sn': pnts = np.array(zip(self.s, self.n)) elif plane == 'xy': pnts = np.array(zip(self.x.flatten(), self.y.flatten())) else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return #cubic interpolation cubic[self.nodata] = griddata(pnts[self.isdata], cubic[self.isdata], pnts[self.nodata], method='cubic', fill_value=np.nan) cubic = common.to_grid(cubic, self.rows, self.cols) #griddify if fill_nans: cubic = self.__fill_nans(cubic) #linear fill of nan values #add pre-defined banks cubic = self.__add_banks(cubic) #smoothen for i in range(self.rows): cubic[i, :] = common.smooth(cubic[i, :], smoothie) print "Finished [CUBIC]." self.z_interpol = cubic del cubic #plot if plot: self.plot(fignum='CUBIC')
def linear(self, smoothie=0, plane='sn', fill_nans=True, plot=False): """ Performs Linear Barycentric interpolation to the instance's data Kwargs: smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented fill_nans <str> : decides to fill NaN values in a linear manner or keep NaN values plot <boolean> : decides to plot or not the resulting LINEAR values """ gc.enable() print "Calculating: Linear Barycentric Interpolation" linear = deepcopy(self.z) #avoid overwrite #choice of plane if plane == 'sn': pnts = np.array(zip(self.s, self.n)) elif plane == 'xy': pnts = np.array(zip(self.x.flatten(), self.y.flatten())) else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return #linear interpolation linear[self.nodata] = griddata(pnts[self.isdata], linear[self.isdata], pnts[self.nodata], method='linear', fill_value=np.nan) linear = common.to_grid(linear, self.rows, self.cols) #griddify if fill_nans: linear = self.__fill_nans(linear) #linear fill of nan values #add pre-defined banks linear = self.__add_banks(linear) #smoothen for i in range(self.rows): linear[i, :] = common.smooth(linear[i, :], smoothie) print "Finished [LINEAR]." self.z_interpol = linear del linear #plot if plot: self.plot(fignum='LINEAR-BARYCENTRIC')
def near(self, smoothie=0, plane='sn', plot=False): """ Fills values of unsampled data points with the values of the closest sampled data point of the instance's data. Kwargs: smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented plot <boolean> : decides to plot or not the result NEAREST values """ gc.enable() print "Calculating: Nearest-Neighbour \"Interpolation\"" near = deepcopy(self.z) #avoid overwrite #choice of plane if plane == 'sn': pnts = np.array(zip(self.s, self.n)) elif plane == 'xy': pnts = np.array(zip(self.x.flatten(), self.y.flatten())) else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return #find nearest values near[self.nodata] = griddata(pnts[self.isdata], near[self.isdata], pnts[self.nodata], method='nearest') near = common.to_grid(near, self.rows, self.cols) #griddify #add pre-defined banks near = self.__add_banks(near) #smoothen for i in range(self.rows): near[i, :] = common.smooth(near[i, :], smoothie) print "Finished [NEAR]." self.z_interpol = near del near #plot if plot: self.plot(fignum='NEAREST')
def fuse(self, ftype='free-form', dthres=0.0, anisotropy=1.0, smoothie=0): gc.enable() print "Calculating: Fusion method (" + ftype + ")" if ftype not in ['free-form', 'cross-sections']: print "Warning: Please specify testing dataset type as: \'free-form\' for trackline or free-form data, or \'cross-sections\' for cross-sectional data." print "Assuming free-form data." ftype = 'free-form' s, n = self.s.flatten(), self.n.flatten() isdata = self.isdata.flatten() nodata = self.nodata.flatten() #if samples in free-form (ie tracklines) if ftype == 'free-form': #check dthres = abs(float(dthres)) #distance matrix: s0, n0 = s[isdata], n[isdata] #sampled s1, n1 = s[nodata], n[nodata] #unsampled dm = common.distance_matrix(s0, n0, s1, n1, anisotropy) #matrix #if no threshold is defined, calculate the furthest possible point # = this is where bathymetry has the most impact dmins = dm.min(axis=0) if dthres <= 0: dthres = dmins.max() print "Threshold Distance:", dthres #weights w_bth = dmins / dthres #weights for model dataset w_bth[w_bth > 1.0] = 1.0 #adjust to range of [0,1] w_int = 1.0 - w_bth #weights for interpolation dataset del dm, dmins, s0, n0, s1, n1 #clear #if samples in cross-sections else: #find cross-sections and the points where there is data (clustering of data): cs_where = [] for j in range(self.cols): if np.nansum(self.isdata[:, j]) != 0: cs_where.append(j) print "Cross-section at: ", j #Find minimum distances from 2 different cross-sections ratios = np.ones((self.rows * self.cols, 2)) * np.inf for j in cs_where: dist_from_cs = common.distance_matrix( self.s[:, j][self.isdata[:, j]], self.n[:, j][self.isdata[:, j]], s, n, anisotropy) cs_mindist = np.min(dist_from_cs, axis=0) change = cs_mindist < ratios[:, 1] ratios[:, 1][change] = cs_mindist[change] ratios = np.sort(ratios, axis=1) #holds min distances from 2 cs del dist_from_cs #weights w_int = [] w_bth = [] for i in range(len(ratios)): #real distances d1 = ratios[i, 0] #distance from one cs d2 = ratios[i, 1] #distance from another cs if d1 == 0.0: d1 = 1e-20 #avoid division by 0 if d2 == 0.0: d2 = 1e-20 #avoid division by 0 hd = (d1 + d2) / 2.0 #half-distance if d1 < hd: d2 -= hd r1 = 1. / (1. + (d2 / d1)**2) else: d1 -= hd r1 = 1. / (1. + (d1 / d2)**2) if r1 > 1.0: r1 = 1.0 r2 = 1.0 - r1 w_bth.append(r1) w_int.append(r2) w_int = np.array(w_int)[nodata] w_bth = np.array(w_bth)[nodata] #In both cases, fused dataset is the sum of the weighted datasets I = self.inter.flatten() M = self.model.flatten() fusion = self.z.flatten() #initialize, so to keep measured data values fusion[nodata] = I[nodata] * w_int + M[nodata] * w_bth fusion = common.to_grid(fusion, self.rows, self.cols) #grid (matrix) notation del w_bth, w_int #clear #smoothen the longitudinals, if required if smoothie > 0: for i in range(self.rows): fusion[i, :] = common.smooth(fusion[i, :], smoothie) if smoothie > int(fusion.shape[0] / 4): smoothie = int(fusion.shape[0] / 4) for i in range(self.cols): fusion[:, i] = common.smooth(fusion[:, i], smoothie) print "Finished [FUSION]." self.fused = fusion del fusion
def plot(self, fignum, clim='auto', classes=100, system='xy', hold=False): #append nan values Gz = deepcopy(self.z_interpol) Gz[Gz == -999.0] = np.nan if system == 'xy': Gx = self.x Gy = self.y elif system == 'sn': Gx = common.to_grid(self.s, self.rows, self.cols) Gy = common.to_grid(self.n, self.rows, self.cols) elif system == 'mn': Gx, Gy = np.meshgrid(self.cols, self.rows) else: print "Wrong coordinate system chosen. Please specify input system as \'xy\', \'sn\' or \'mn\'." #plt.close(fignum) plt.figure(fignum) #plt.clf() # set colorlimits minn = np.nanmin(Gz) maxx = np.nanmax(Gz) if clim == 'auto': mean = np.mean(np.ma.masked_array(Gz, np.isnan(Gz))) classes = int(classes) if classes % 2 == 1: classes += 1 dl = np.linspace(minn, mean, classes / 2) dr = np.linspace(mean, maxx, classes / 2) d = 10.0 flag = True c = 0 while flag: levels = np.round(np.append(dl, dr[1:]) / d) * d if c % 2 == 0: d = d / 2.0 else: d = d - 4 * d / 5.0 c += 1 flag = len(levels) != len(set(levels)) elif clim == 'minmax': levels = np.linspace(minn, maxx, classes) else: levels = np.linspace(clim[0], clim[1], classes) #If more than half the points are unknown, the dataset to plot logically must be a testing dataset if np.sum(np.isnan(Gz)) > Gz.shape[0] * Gz.shape[1] / 2.0: print "-> Assuming plot of Testing Dataset." cs = plt.scatter(Gx, Gy, s=10, c=Gz, cmap=plt.cm.jet, vmin=clim[0], vmax=clim[1], edgecolors='none') else: cs = plt.contourf(Gx, Gy, Gz, levels, cmap=plt.cm.jet, extend="both") cs.cmap.set_under('k') cs.set_clim(np.floor(levels[0]), np.ceil(levels[-1])) cbar = plt.colorbar(cs) cbar.set_label('Bed Level (m)', labelpad=15, weight='bold', size='14') plt.axis('equal') plt.hold(hold) #used when the data needs to be "on top" of other data plt.ion() plt.show()
def natneigh(self, anisotropy=1.0, smoothie=0, plane='sn', plot=False): """ Performs Natural Neighbor (NN) interpolation with defined anisotropy to the instance's data. The algorithm assumes a brute-force way of calculating the Voronoi cells every time an unsampled point's value is computed. Kwargs: anisotropy <float> : anisotropy parameter: if >1.0, it brings points closer in the longitudinal (s) direction, if <1.0 it brings points closer in the transverse (n) direction smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented plot <boolean> : decides to plot or not the resulting NN values """ from scipy.spatial import voronoi_plot_2d import matplotlib.pyplot as plt gc.enable() print "Calculating: Natural Neighbour [NN]" nn = deepcopy(self.z) #avoid overwrite #choose plane if plane == 'sn': x = self.s * 1. / anisotropy #already flattened y = self.n #already flattened elif plane == 'xy': x = self.x.flatten() * 1. / anisotropy y = self.y.flatten() else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return #DEFINE BOUNDARY FOR INTERPOLATION #griddify points to choose boundary easier: Gx = common.to_grid(x, self.rows, self.cols) Gy = common.to_grid(y, self.rows, self.cols) bx = np.hstack((Gx[0, :], Gx[1:-1, -1], Gx[-1, :][::-1], Gx[1:-1, 0][::-1])) by = np.hstack((Gy[0, :], Gy[1:-1, -1], Gy[-1, :][::-1], Gy[1:-1, 0][::-1])) #define boundary: boundary = np.array(zip(bx, by)) #VORONOI OF SAMPLED DATA POINTS: vorpoints = np.array(zip(x[self.isdata], y[self.isdata])) #shift points around central point of the dataset (for precision purposes) center = vorpoints.mean(axis=0) vorpoints -= center #construct Voronoi diagram from (centered) sampled data points vor = Voronoi(vorpoints) vor.close() """ #TODO: delete: voronoi_plot_2d(vor) plt.ion() plt.axis('equal') plt.show() """ #calculate areas of sampled dataset Voronoi cells original_areas, vor = self.__find_areas(vor, boundary - center) """ #TODO: delete: # colorize for region in vor.regions[1:]: polygon = vor.vertices[region] plt.fill(*zip(*polygon), alpha=0.4) plt.plot(vorpoints[:,0], vorpoints[:,1], 'ko') plt.xlim(vor.min_bound[0] - 0.1, vor.max_bound[0] + 0.1) plt.ylim(vor.min_bound[1] - 0.1, vor.max_bound[1] + 0.1) plt.axis('equal') plt.ion() plt.show() """ #ITERATE THROUGH UNSAMPLED DATA POINTS: # ~ For each unsampled point, construct the new Voronoi diagram consisting of the # ~ sampled data and the current unsampled point. Then calculate the new areas and # ~ find the normalized weights based on how much of each area is "stolen away" from # ~ each sampled dataset Voronoi cell (https://en.wikipedia.org/wiki/Natural_neighbor). # ~ The areas are always bounded by the river polygon (based on the grid defined). unknown = [] for i in range(len(x[self.nodata])): if i % 1000 == 0: print i, "out of ", len(x[self.nodata]) #add new point shifted around central point varys = np.vstack((vorpoints, [ x[self.nodata][i] - center[0], y[self.nodata][i] - center[1] ])) #calculate new Voronoi pntvor = Voronoi(varys) pntvor.close() #calculate areas new_areas, pntvor = self.__find_areas(pntvor, boundary - center) new_areas = new_areas[:-1] #exclude new point's area w = new_areas / original_areas w[w > 1.0] = 1.0 #make sure that no area is larger than initial areas areaweight = 1.0 - w normalize = np.nansum(areaweight) if normalize == 0.0: #to avoid division by 0 normalize = 1e-12 areaweight /= normalize unknown.append(np.nansum(areaweight * self.z[self.isdata])) nn[self.nodata] = np.array(unknown) #grid (matrix) notation nn = common.to_grid(nn, self.rows, self.cols) #add pre-defined banks nn = self.__add_banks(nn) #smoothen for i in range(self.rows): nn[i, :] = common.smooth(nn[i, :], smoothie) print "Finished [NN]." self.z_interpol = nn del nn #plot if plot: self.plot(fignum='NN')
def uk(self, sill, vmodel='spherical', anisotropy=1.0, smoothie=0, plane='sn', plot=False): """ Performs Universal Kriging (UK) interpolation with defined anisotropy to the instance's data using the specified model for its semivariogram. The sill for the semivariogram needs to be defined. The range used is equal to the sill times the anisotropy defined. Args: sill <float> : Sill value for semivariogram in UK Kwargs: vmodel <str> : Semivariogram model (default: 'spherical') anisotropy <float> : anisotropy parameter: if >1.0, it brings points closer in the longitudinal (s) direction, if <1.0 it brings points closer in the transverse (n) direction smoothie <int> : smoothing degree (Gaussian window) plane <str> : chooses plane for interpolation; 'xy' for Cartesian, 'sn' for flow-oriented plot <boolean> : decides to plot or not the resulting UK values """ gc.enable() print "Calculating: Universal Kriging [UK]" uk = deepcopy(self.z) #avoid overwrite #calculate UK with anisotropy defined if plane == 'sn': UK = UniversalKriging( self.s[self.isdata], self.n[self.isdata], uk[self.isdata], anisotropy_scaling=anisotropy, anisotropy_angle=0.0, nlags=self.cols, variogram_model=vmodel, variogram_parameters=[sill, sill * anisotropy, 0.0], drift_terms=['functional'], functional_drift=[self.uk_funct], verbose=True, enable_plotting=True) uk[self.nodata], sigmas = UK.execute('points', self.s[self.nodata], self.n[self.nodata]) elif plane == 'xy': x = self.x.flatten() y = self.y.flatten() UK = UniversalKriging( x[self.isdata], y[self.isdata], uk[self.isdata], anisotropy_scaling=anisotropy, anisotropy_angle=0.0, nlags=self.cols, variogram_model=vmodel, variogram_parameters=[sill, sill * anisotropy, 0.0], drift_terms=['regional_linear'], functional_drift=[self.uk_funct], verbose=False, enable_plotting=False) uk[self.nodata], sigmas = UK.execute('points', x[self.nodata], y[self.nodata]) else: print "Error: Plane for interpolation not correctly specified. No interpolation performed." return #grid (matrix) notation uk = common.to_grid(uk, self.rows, self.cols) #add pre-defined banks uk = self.__add_banks(uk) #smoothen for i in range(self.rows): uk[i, :] = common.smooth(uk[i, :], smoothie) print "Finished [UK]." self.z_interpol = uk del uk #plot if plot: self.plot(fignum='UK')
def hw_slope(self, widths, lengths, plotname=False): import matplotlib.pyplot as plt #take half-width: k = int(self.GT.shape[0] / 4.0) CDhw = self.P[k:-k, :] #computed dataset half-width GThw = self.GT[k:-k, :] #ground-truth dataset half-width numlines = CDhw.shape[0] #TODO: find a better way to fill this #filling of ground-truth half-widths // by nearest grid neighbour z = GThw.flatten() m = range(CDhw.shape[1]) * CDhw.shape[0] n = sorted(m) gpnts = np.vstack((m, n)).T znear = griddata(gpnts[~np.isnan(z)], z[~np.isnan(z)], gpnts[np.isnan(z)], method='nearest') z[np.isnan(z)] = znear GThw = common.to_grid(z, CDhw.shape[0], CDhw.shape[1]) #real half-width w = (float(numlines - 1) / (self.P.shape[0] - 1)) * np.array(widths) slopeDiff = [] a = [] gt_a = [] testNHWS = [] gtNHWS = [] for j in range(CDhw.shape[1]): #for each cross-section excl = ~np.isnan(GThw[:, j]) * ~np.isnan( CDhw[:, j]) #mutual exclusion cs_x = np.linspace(0.0, 1.0, numlines) * w[j] #test cs_y = CDhw[:, j] testslope = np.polyfit(cs_x[excl], cs_y[excl], 1) #f(x) = ax+b #ground-truth cs_y = GThw[:, j] gtslope = np.polyfit(cs_x[excl], cs_y[excl], 1) #f(x) = ax+b if np.isnan(gtslope[0]): #print gtslope #print cs_x[excl],cs_y[excl] print "CHECK" #slope difference a.append(testslope[0]) gt_a.append(gtslope[0]) slopeDiff.append(abs(a[-1] - gt_a[-1])) #Normalized Half-Width Slope H = testslope[0] * cs_x[numlines / 2] + testslope[1] Hgt = gtslope[0] * cs_x[numlines / 2] + gtslope[1] testNHWS.append(testslope[0] * 1. / H) gtNHWS.append(gtslope[0] * 1. / Hgt) #//end for-loop #slope's mae (not necessary): print "SLOPE metrics:" slopeDiff = np.array(slopeDiff) sub = np.sum(np.isnan(slopeDiff)) Csum = np.nansum(slopeDiff) Dim = len(slopeDiff) - sub slope_mae = Csum / Dim print "mae:", slope_mae slopeDiff = np.array(slopeDiff)**2 sub = np.sum(np.isnan(slopeDiff)) Csum = np.nansum(slopeDiff) Dim = len(slopeDiff) - sub slope_rmse = np.sqrt(Csum / Dim) print "rmse:", slope_rmse nsd = np.sum( np.abs(np.array(gtNHWS) - np.array(testNHWS))) / len(gtNHWS) print "nsdiff:", nsd #PLOTS: if plotname: #alpha "normalized" plt.close(plotname + ' NHWS') plt.figure(plotname + ' NHWS') plt.xlabel('River span (m)', weight='bold', size='14') plt.ylabel('Normalized Half-Width Slope (1/m)', weight='bold', size='14') plt.hold(True) plt.plot(lengths, testNHWS, 'r.-') plt.plot(lengths, gtNHWS, 'b.-') plt.hold(False) #return calculations; in order of output: #[slope of dataset to be tested, slope of ground-truth data, MAE of slope for dataset to be tested, # RMSE of slope for dataset to be tested, absolute slope difference] return [testNHWS, gtNHWS, slope_mae, slope_rmse, nsd]