def normalised_image(arr_in: np.array): ''' Scale the contents of an array to values between 0 and 1. ''' if arr_in.max() == arr_in.min(): return np.ones_like(arr_in) * max(0, min(1, arr_in.max())) return (arr_in - arr_in.min()) / (arr_in.max() - arr_in.min())
def print_one_set_statistics(x_train: np.array, y_train: np.array) -> None: """ """ Total_data_num = len(x_train) print("\n________Table : Data portions info_________") t = Texttable() t.add_rows([ ['Data Portion', 'Number', 'Percent'], ['Total', Total_data_num, "{:.0%}".format(1)], ]) print(t.draw()) print("//////////////////////////////////////////////////\n") print( "_______________________Table : Data shape info________________________" ) t = Texttable() t.add_rows([['Name', 'Shape', 'Min', 'Max', 'Type'], [ 'x train', x_train.shape, x_train.min(), x_train.max(), type(x_train) ], [ 'y train', y_train.shape, y_train.min(), y_train.max(), type(y_train) ]]) print(t.draw()) print("//////////////////////////////////////////////////\n")
def pixmapToImage(self, pixmap: np.array, mode="RGB"): if pixmap.max() > 255: pixmap *= 255.0 / pixmap.max() pixmap = np.array(pixmap, np.uint8) img = Image.fromarray(pixmap, mode) return img
def scale_array(array: np.array) -> np.array: """ Scales a numpy array from 0 to 1. Works in 3D Return np.array """ assert array.max() - array.min() > 0 return ((array - array.min()) / (array.max() - array.min())).astype( np.float32)
def character_for_2by2_pixels(square: np.array, color_mode: bool = False) -> str: """ Convert 2x2 matrix (non-negative integers) to unicode character representation for plotting. """ assert square.shape == (2, 2) assert square.min() >= 0 # Postprocess to remove everything that is not max color max_color = square.max() if max_color <= 1: binary_square = np.clip(square, a_min=0, a_max=1) else: binary_square = np.clip(square, a_min=max_color - 1, a_max=max_color) - (max_color - 1) # binary_square = np.clip(square, a_min=0, a_max=1) integer_encoding = np.multiply(binary_square, BINARY_ENCODING_MATRIX).sum() char = UNICODE_SQUARES[integer_encoding] if char == "" or not color_mode: return char color_code = list(COLOR_CODES.values())[(square.max() - 1) % len(COLOR_CODES)] return f"{color_code}{char}{COLOR_RESET_CODE}"
def update_parameters(self, epsilons: np.array, r_plus: np.array, r_minus: np.array): """ This method update internal mu and sigma according to evaluation results of perturbated parameters mus, sigmas, baseline, maximum_reward are updated. epsilons: parameter_number x sample_number r_plus: sample_number r_minus: sample_number """ self.__mu += self.mu_delta(epsilons, r_plus, r_minus) self.__mu = np.minimum( self.__mu, self.__parameter_bound["upper"]) # prevent too large self.__mu = np.maximum( self.__mu, self.__parameter_bound["lower"]) # prevent too small self.__sigma += self.sigma_delta(epsilons, r_plus, r_minus) self.__sigma = np.minimum( self.__sigma, self.__sigma_upper_bound) # prevent too large sigma assert np.all(self.__sigma > 0), "got negative sigma\n{}".format( self.__sigma) print("updated sigma", self.__sigma) self.__maximum_reward = max(self.__maximum_reward, r_plus.max(), r_minus.max()) b = self.__baseline.add_new_value( (r_plus.mean() + r_minus.mean()) / 2.)
def plot(model, X_test: np.array, y_test: np.array, grid_step=0.02): cmap_light = ListedColormap(["#FFAAAA", "#AAFFAA"]) cmap_bold = ListedColormap(["#FF0000", "#00FF00"]) # calculate min, max and limits x_min, x_max = X_test.min() - 1, X_test.max() + 1 y_min, y_max = y_test.min() - 1, y_test.max() + 1 xx, yy = np.meshgrid( np.arange(x_min, x_max, grid_step), np.arange(y_min, y_max, grid_step) ) # predict class using data and kNN classifier Z = model.predict(np.c_[xx.ravel(), yy.ravel()]) # Put the result into a color plot Z = Z.reshape(xx.shape) plt.figure() plt.pcolormesh(xx, yy, Z, cmap=cmap_light) plt.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cmap_bold) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt.title("Classification") plt.show()
def linear_reg(xi: np.array, y: list): slope, intercept, r_value, p_value, std_err = stats.linregress(xi, y) line = slope * xi + intercept mape = mean_absolute_percentage_error(y, line) line_x = np.arange(xi.min(), xi.max(), (xi.max() - xi.min()) / 30) if len(xi) > 2 else [] line_y = calculate_line(line_x, slope, intercept) if line_x != [] else [] return line_x, line_y, r_value, mape
def histogram_equalize(array: np.array, num_bins=1000): array = array + np.abs(array.min()) h = np.histogram(array, bins=num_bins, range=(0, array.max())) c = 255 * np.cumsum(h[0]) / np.sum(h[0]) new_img = np.zeros(array.shape) max_val = array.max() for index,value in np.ndenumerate(array): new_img[index] = c[int((num_bins-1) * value / max_val)] return np.floor(new_img)
def plot_confusion_matrix( cm: np.array, classes: np.array, normalize: bool = False, title: Text = "Confusion matrix", cmap=None, zmin: int = 1, out: Optional[Text] = None, ) -> None: # pragma: no cover """Print and plot the confusion matrix for the intent classification. Normalization can be applied by setting `normalize=True`.""" import matplotlib.pyplot as plt from matplotlib.colors import LogNorm zmax = cm.max() plt.clf() if not cmap: cmap = plt.cm.Blues plt.imshow( cm, interpolation="nearest", cmap=cmap, aspect="auto", norm=LogNorm(vmin=zmin, vmax=zmax), ) plt.title(title) plt.colorbar() tick_marks = np.arange(len(classes)) plt.xticks(tick_marks, classes, rotation=90) plt.yticks(tick_marks, classes) if normalize: cm = cm.astype("float") / cm.sum(axis=1)[:, np.newaxis] logger.info("Normalized confusion matrix: \n{}".format(cm)) else: logger.info("Confusion matrix, without normalization: \n{}".format(cm)) thresh = cm.max() / 2.0 for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): plt.text( j, i, cm[i, j], horizontalalignment="center", color="white" if cm[i, j] > thresh else "black", ) plt.ylabel("True label") plt.xlabel("Predicted label") # save confusion matrix to file before showing it if out: fig = plt.gcf() fig.set_size_inches(20, 20) fig.savefig(out, bbox_inches="tight")
def save_chebyshev(self, q: np.array, p: np.array): """ Pre-calculate the Chebyshev polynomials at specified grid points :param p: :param q: :return: None """ # if p and q were supplied before, do not re-calculate if self._p is not p or self._q is not q: # consistency checks assert len(p.shape) == 2 and (p.shape[0] == 1 or p.shape[1] == 1), "Array p must be flat" assert p.min() >= -1. and p.max( ) <= 1., "Range of p must be [-1, 1]" assert len(q.shape) == 2 and (q.shape[0] == 1 or q.shape[1] == 1), "Array q must be flat" assert q.min() >= -1. and q.max( ) <= 1., "Range of q must be [-1, 1]" self._p = p self._q = q self.chebyshev_t_p = get_chebyshev_list(p, np.ones_like(p), p, self.n_basis_vect) self.chebyshev_u_p = get_chebyshev_list(p, np.ones_like(p), 2. * p, self.n_basis_vect) self.chebyshev_t_q = get_chebyshev_list(q, np.ones_like(q), q, self.n_basis_vect) self.chebyshev_u_q = get_chebyshev_list(q, np.ones_like(q), 2. * q, self.n_basis_vect) ############################################################################################################ # # Allocate arrays # ############################################################################################################ self.upsilon1 = np.zeros((p.size, q.size), dtype=np.complex) self.upsilon2 = self.upsilon1.copy() self.diff_p_upsilon1 = self.upsilon1.copy() self.diff_q_upsilon1 = self.upsilon1.copy() self.diff_p_upsilon2 = self.upsilon2.copy() self.diff_q_upsilon2 = self.upsilon2.copy() self.D11 = self.upsilon1.copy() self.D12 = self.D11.copy() self.D22 = self.D11.copy() self.classical_rho = np.zeros_like(self.D11, dtype=np.float)
def normalize_data( data_opm_reference: np.array, data_ensembles_flownet: List[np.array] ) -> Tuple[np.array, List[np.array]]: """ This function normalizes data from a 2D numpy array containing data from the reference simulation and multiple ensembles of FlowNet simulations, using the MinMaxScaler from sklearn.preprocessing module Args: data_opm_reference: is the 2D numpy array containing data from reference simulation replicated into as many columns as the size of ensemble of FlowNet realizations data_ensembles_flownet: is a list of 2D numpy arrays containing data from ensembles of FlowNet simulations; each list entry correspond to the ensemble of a given iteration of ES-MDA Returns: norm_data_opm_reference: is a normalized 2D numpy array for the reference simulation data norm_data_ensembles_flownet: a list of normalized 2D numpy arrays for the ensembles of FlowNet simulations """ for k, data_ens in enumerate(data_ensembles_flownet): if k == 0: tmp = data_ens else: tmp = np.append(tmp, data_ens, axis=1) matrix_data = np.append(data_opm_reference, tmp, axis=1) if np.isclose(data_opm_reference.max(), data_opm_reference.min()): if np.isclose(data_opm_reference.max(), 0.0): scale = np.tile(1.0, matrix_data.shape[0]) else: scale = 1 / (np.tile(data_opm_reference.max(), matrix_data.shape[0])) else: scale = 1 / (np.tile(data_opm_reference.max(), matrix_data.shape[0]) - np.tile(data_opm_reference.min(), matrix_data.shape[0])) norm_matrix_data = (matrix_data * scale[:, None] - (np.tile( data_opm_reference.min(), matrix_data.shape[0]) * scale)[:, None]) n_data = int(norm_matrix_data.shape[1] / (len(data_ensembles_flownet) + 1)) norm_data_opm_reference = norm_matrix_data[:, :n_data] norm_data_ensembles_flownet = [] for k in range(len(data_ensembles_flownet)): norm_data_ensembles_flownet.append( norm_matrix_data[:, (k + 1) * n_data:(k + 2) * n_data]) return norm_data_opm_reference, norm_data_ensembles_flownet
def cluster_accuracy(predicted: np.array, target: np.array): assert predicted.size == target.size, ''.join( 'Different size between predicted\ and target, {} and {}').format(predicted.size, target.size) D = max(predicted.max(), target.max()) + 1 w = np.zeros((D, D), dtype=np.int64) for i in range(predicted.size): w[predicted[i], target[i]] += 1 ind_1, ind_2 = linear_sum_assignment(w.max() - w) return sum([w[i, j] for i, j in zip(ind_1, ind_2)]) * 1.0 / predicted.size, w
def calculate_for_continuous(data_train: np.array, data_valid: np.array) -> Real: kde_desc_train = stats.gaussian_kde(data_train) kde_desc_valid = stats.gaussian_kde(data_valid) interval = np.linspace( start=min(data_train.min(), data_valid.min()), stop=max(data_train.max(), data_valid.max()), num=1000, ) return stats.entropy( kde_desc_train.evaluate(interval) + 1e-10, kde_desc_valid.evaluate(interval) + 1e-10, )
def fill_by_surr(img: np.array, surr_rate: float=0.02) -> np.array: """Filter. Points by surrounded points. """ w_arr = np.zeros(img.shape) w, h = w_arr.shape m_limit = img.max() l_limit = m_limit * 0.4 h_limit = m_limit * 0.8 dx = int(np.round(w * surr_rate)) dy = int(np.round(h * surr_rate)) for i in range(w): for j in range(h): for x in range(i - dx, i + dx): if x < 0 or x >= w: continue for y in range(j - dy, j + dy): if y < 0 or y >= h: continue if img[x, y] > h_limit: w_arr[i, j] += 2 elif img[x, y] > l_limit: w_arr[i, j] += 1 return w_arr / w_arr.max()
def log_histogram(self, tag: str, data: np.array, step: int, num_bars: int = 30): """ Adds a histogram to log. Parameters ---------- tag: str data: np.array Array of any shape. step: int num_bars: int The number of bars if the resulting histogram. """ data = data.ravel() min_ = data.min() max_ = data.max() sum_ = data.sum() sum_sq = data.dot(data) if min_ == max_: num = 1 bucket_limit = [min_] bucket = [len(data)] else: bucket, bucket_limit = np.histogram(data, num_bars) num = len(bucket_limit) bucket_limit = bucket_limit[1:] hist = HistogramProto(min=min_, max=max_, sum=sum_, sum_squares=sum_sq, num=num, bucket_limit=bucket_limit, bucket=bucket) self._write_event(tag, step, histo=hist)
def _warn_available_data(test_dates: Union[float, np.array], dates_with_data: np.array) -> None: """Warn if given dates don't falls within a range dates with measurements Args: test_dates: Dates to check for available data dates_with_data: Dates with data available """ test_dates = np.atleast_1d(test_dates) # In case passed a float if not len(dates_with_data): err_msg = 'No PWV data for primary receiver available on local machine.' raise RuntimeError(err_msg) # Check date falls within the range of available PWV data min_known_date = dates_with_data.min(), if (test_dates < min_known_date).any(): min_date = datetime.utcfromtimestamp(min_known_date) raise ValueError( f'No PWV data found for dates before {min_date} on local machine') max_known_date = dates_with_data.max() if (test_dates > max_known_date).any(): max_date = datetime.utcfromtimestamp(max_known_date) raise ValueError( f'No PWV data found for dates after {max_date} on local machine')
def min_max(a: np.array) -> np.array: """ get the mean of this window len(v) and compare it to current price """ # x = ((s - s.min()) / (s.max() - s.min())).iat[-1] # return x * 2 - 1 return (a - a.min()) / (a.max() - a.min())
def normalize(arr: np.array, lower: float = 0.0, upper: float = 1.0) -> tuple: """ Normalize the input data in a range given by [lower, upper] :code:`arrNorm, t = normalize(arr, lower, upper)` Args: arr (np.array): the input data array lower (float): the minimum value of the new range upper (float): the maximum value of the new range Returns: (tuple): tuple containing: arrNorm (np.array) : the normalized data t (np.array) : the corresponding linear transformation s.t. :code:`arrNorm = t[0] * arr + t[1]` """ arr = arr.copy() if lower > upper: lower, upper = upper, lower alpha = (upper - lower) / (arr.max() - arr.min()) t = np.array([alpha, lower - arr.min() * alpha], dtype='float') arr = t[0] * arr + t[1] return arr, t
def find_content_rect(img: np.array, intensity: float=0.6) -> np.array: """Search submatrix with content. """ w, h = img.shape mid = img.max() * intensity x1 = y1 = x2 = y2 = 0 for i in range(w): if img[i, :h].max() > mid: x1 = i break for i in range(h): if img[:w, i].max() > mid: y1 = i break for i in range(w): j = w - i - 1 if img[j, :h].max() > mid: x2 = j break for i in range(h): j = h - i - 1 if img[:w, j].max() > mid: y2 = j break return img[x1: x2, y1: y2]
def print_ts_model_stats( actuals: np.array, predicted: np.array, number_as_percentage: float = 100) -> Tuple[float, float, float]: """ This program prints and returns MAE, RMSE, MAPE. If you like the MAE and RMSE as a percentage of something, just give that number in the input as "number_as_percentage" and it will return the MAE and RMSE as a ratio of that number. Returns MAE, MAE_as_percentage, and RMSE_as_percentage """ #print(len(actuals)) #print(len(predicted)) plt.figure(figsize=(15, 8)) dfplot = pd.DataFrame([predicted, actuals]).T dfplot.columns = ['Forecast', 'Actual'] plt.plot(dfplot) plt.legend(['Forecast', 'Actual']) mae = mean_absolute_error(actuals, predicted) mae_asp = (mean_absolute_error(actuals, predicted) / number_as_percentage) * 100 rmse_asp = (np.sqrt(mean_squared_error(actuals, predicted)) / number_as_percentage) * 100 print('MAE (%% AUM) = %0.2f%%' % mae_asp) print('RMSE (%% AUM) = %0.2f%%' % rmse_asp) print('MAE (as %% Actual) = %0.2f%%' % (mae / abs(actuals).mean() * 100)) _ = print_mape(actuals, predicted) rmse = print_rmse(actuals, predicted) mape = print_mape(actuals, predicted) print("MAPE = %0.0f%%" % (mape)) # Normalized RMSE print('RMSE = {:,.Of}'.format(rmse)) print('Normalized RMSE (MinMax) = %0.0f%%' % (100 * rmse / abs(actuals.max() - actuals.min()))) print('Normalized RMSE = %0.0f%%' % (100 * rmse / actuals.std())) return mae, mae_asp, rmse_asp
def calculate_confusion_matrix_from_arrays_fast(ground_truth: np.array, prediction: np.array, num_classes: int) -> np.array: """Calculate confusion matrix for a given set of classes. if GT value is outside of the [0, num_classes) it is excluded. 10x faster than scikit learn implementation. Implemented by Anton Nesterenko. Args: ground_truth: prediction: num_classes: Returns: """ if not prediction.max() < num_classes: raise ValueError( f"Max predicted class number must be equal {num_classes - 1}") r = np.zeros(num_classes**2) valid_idx = np.where(ground_truth < num_classes)[0] idx, vals = np.unique(prediction[valid_idx] + ground_truth[valid_idx] * num_classes, return_counts=True) r[idx] = vals return r.reshape(num_classes, num_classes).astype(np.uint64)
def print_ts_model_stats(actuals: np.array, predicted: np.array) -> Tuple[float, float, float]: """ This program prints and returns MAE, RMSE, MAPE. If you like the MAE and RMSE as a percentage of something, just give that number in the input as "number_as_percentage" and it will return the MAE and RMSE as a ratio of that number. Returns MAE, MAE_as_percentage, and RMSE_as_percentage """ number_as_percentage = actuals.std() plt.figure(figsize=(15, 8)) dfplot = pd.DataFrame([actuals, predicted]).T dfplot.columns = ['Actual', 'Forecast'] plt.plot(dfplot) plt.legend(['actual', 'forecast']) plt.title( 'Random Forest: Actual vs Forecast in expanding (training) Window Cross Validation', fontsize=20) print('\n-------------------------------------------') print('Model Cross Validation Results:') print('-------------------------------------------') mae = mean_absolute_error(actuals, predicted) mae_asp = (mean_absolute_error(actuals, predicted) / number_as_percentage) * 100 print(' MAE (as %% Std Dev of Actuals) = %0.2f%%' % mae_asp) rmse = print_rmse(actuals, predicted) mape = print_mape(actuals, predicted) print(" MAPE (Mean Absolute Percent Error) = %0.0f%%" % (mape)) # Normalized RMSE print('RMSE = {:,.Of}'.format(rmse)) print(' Normalized RMSE (MinMax) = %0.0f%%' % (100 * rmse / abs(actuals.max() - actuals.min()))) rmse_asp = (np.sqrt(mean_squared_error(actuals, predicted)) / number_as_percentage) * 100 print(' Normalized RMSE (as Std Dev of Actuals)= %0.0f%%' % rmse_asp) return rmse, rmse_asp
def get_card(img: Image, coords: np.array) -> Image: img_arr = np.array(img) # shift center = coords.sum(axis=0) / 4 shift_x = img_arr.shape[0] / 2 - center[0] shift_y = img_arr.shape[1] / 2 - center[1] img_arr = shift_image(img_arr, shift_x, shift_y) coords = shift_coords(coords, shift_x, shift_y) # rotate p1 = coords[0] p2 = coords[1] delta_x = p2[0] - p1[0] delta_y = p2[1] - p1[1] theta_radians = math.atan2(-delta_y, delta_x) angle = -theta_radians / math.pi * 180 img_arr = rotate_image(img_arr, angle) coords = rotate_coords(coords, theta_radians, img_arr.shape, radians=True) # crop a = coords.min(axis=0).astype(int) b = coords.max(axis=0).astype(int) box = (a.item(0), a.item(1), b.item(0), b.item(1)) return Image.fromarray(img_arr).crop(box)
def fit_fcs_in_xy_bin (xybin : Tuple[int, int], selection_map : Dict[int, List[DataFrame]], event_map : DataFrame, n_time_bins : int, time_diffs : np.array, nbins_z : int, nbins_e : int, range_z : Tuple[float, float], range_e : Tuple[float, float], energy : str = 'S2e', z : str = 'Z', fit : FitType = FitType.profile, n_min : int = 100)->FitParTS: """Returns fits in the bin specified by xybin""" i = xybin[0] j = xybin[1] nevt = event_map[i][j] tlast = time_diffs.max() tfrst = time_diffs.min() ts, masks = get_time_series_df(n_time_bins, (tfrst, tlast), selection_map[i][j]) logging.debug(f' ****fit_fcs_in_xy_bin: bins ={i,j}') if nevt > n_min: logging.debug(f' events in fit ={nevt}, time series = {ts}') return time_fcs_df(ts, masks, selection_map[i][j], nbins_z, nbins_e, range_z, range_e, energy, z, fit) else: warnings.warn(f'Cannot fit: events in bin[{i}][{j}] ={event_map[i][j]} < {n_min}', UserWarning) dum = np.zeros(len(ts), dtype=float) dum.fill(np.nan) return FitParTS(ts, dum, dum, dum, dum, dum)
def convert_arr2qpixmap(data: np.array, resol: [float, float], size: int) -> QtGui.QPixmap: """ convert 2D numpy array to PySide2's QPixmap object Args: data : 2d array resol : resolution for each axis size : size of longest axis Returns: QPixmap object aspect_ratio ( width / height ) """ fov_size = (np.asarray(data.shape) * np.asarray(resol)).tolist() size = float(size) aspect_ratio = float(np.divide(*fov_size)) rescaled_data = data / data.max() * 255 rescaled_data = rescaled_data.astype('uint8') imgobj = Image.fromarray(rescaled_data.T) qimgobj = ImageQt.ImageQt(imgobj) qpixmap = QtGui.QPixmap(qimgobj) if aspect_ratio > 1: # height is longer width = size / aspect_ratio height = size else: # equal or width is longer width = size height = size * aspect_ratio qpixmap = qpixmap.scaled(QtCore.QSize(width, height), aspectMode=QtCore.Qt.KeepAspectRatio) return qpixmap
def get_adjacency_matrix(segments: np.array): # slic returns labels from 0 to n n = segments.max() + 1 r = np.zeros((n, n)) x, y = segments.shape # horizontally iterate over pixels for i in range(x): for j in range(0, y - 1): seg1 = segments[i][j] seg2 = segments[i][j + 1] if seg1 != seg2: r[seg1][seg2] = r[seg1][seg2] + 1 r[seg2][seg1] = r[seg2][seg1] + 1 # vertically iterate over pixels for j in range(y): for i in range(0, x - 1): seg1 = segments[i][j] seg2 = segments[i + 1][j] if seg1 != seg2: r[seg1][seg2] = r[seg1][seg2] + 1 r[seg2][seg1] = r[seg2][seg1] + 1 min_pixel_count_for_neigbor = 5 return r > min_pixel_count_for_neigbor
def train(self, x: np.array, y: np.array): self.train_x = x self.train_y = y self.n_classes = len(set(self.train_y)) self.mins = x.min(axis=0) self.maxes = x.max(axis=0)
def interpolate_file_karin(swh_in: np.array, x_ac_in: np.array, height_sdt: np.array, cross_track: np.array, swh: np.array) -> np.ndarray: warning = False size_swh = np.shape(swh_in) if len(size_swh) == 1: swh_in = swh_in.reshape((1, size_swh[0])) size_swh = np.shape(swh_in) hsdt = np.zeros(size_swh) for j in range(size_swh[1]): xacj = x_ac_in[j] indice_ac = np.argmin(np.abs(cross_track - xacj)) for i in range(size_swh[0]): threshold = swh_in[i, j] indices = np.argmin(np.abs(swh - threshold)) if swh[indices] > threshold: indices -= 1 if swh.max() <= threshold: hsdt[i, j] = height_sdt[-1, indice_ac] warning = True else: rswh = threshold - swh[indices] hsdt[i, j] = height_sdt[indices, indice_ac] * ( 1 - rswh) + rswh * height_sdt[indices + 1, indice_ac] if warning is True: warnings.warn( f'swh={threshold} is greater than the maximum value, ' f'therefore swh is set to the file maximum ' 'value', RuntimeWarning) return hsdt
def _find_nearest_slice_index(list_of_values: np.array, val1, val2=False): try: assert list_of_values.ndim == 1 except AssertionError as e: raise e min_val = list_of_values.min() max_val = list_of_values.max() if not max_val >= val1 >= min_val: raise ValueError( f'specified coordinate value ({val1}) is outside the min/max range: [{min_val}, {max_val}]' ) index1 = (np.abs(list_of_values - val1)).argmin() if val2 is False: return index1 if not max_val >= val2 >= min_val: raise ValueError( f'specified coordinate value ({val2}) is outside the min/max range: [{min_val}, {max_val}]' ) index2 = (np.abs(list_of_values - val2)).argmin() if index1 == index2: return index1 elif index1 < index2: # we'll put this check in there just in case they got the coordinates wrong return slice(index1, index2) else: return slice(index2, index1)