def find_peak(x, y, ref, sam, pro_max=1, pro_min=1, threshold=0.1, except_around=None): if except_around is not None and len(except_around) != 2: raise ValueError("Invalid except_around arg. Try [start, stop].") if except_around is not None: try: float(except_around[0]) float(except_around[1]) except ValueError: raise ValueError( "Invalid except_around arg. Only numeric values are allowed." ) x, y = _handle_input(x, y, ref, sam) max_indexes, _ = find_peaks(y, prominence=pro_max) y_rec = 1 / y min_indexes, _ = find_peaks(y_rec, prominence=pro_min) min_idx = [] max_idx = [] for idx in max_indexes: if _between(x[idx], except_around) or np.abs(y[idx]) > threshold: max_idx.append(idx) for idx in min_indexes: if _between(x[idx], except_around) or np.abs(y[idx]) > threshold: min_idx.append(idx) if len(x[max_idx]) != len(y[max_idx]) or len(x[min_idx]) != len(y[min_idx]): raise ValueError("Something went wrong, try to cut the edges of data.") return x[max_idx], y[max_idx], x[min_idx], y[min_idx]
def cwt(x, y, ref, sam, widths, floor_thres=0.1): x, y = _handle_input(x, y, ref, sam) idx = find_peaks_cwt(y, widths=widths) if _maybe_increase_before_cwt(y, tolerance=floor_thres): y += 2 y_rec = 1 / y idx2 = find_peaks_cwt(y_rec, widths=widths) return x[idx], y[idx] - 2, x[idx2], y[idx2] - 2
def convolution(x, y, ref, sam, win_len, standev=200): x, y = _handle_input(x, y, ref, sam) if win_len < 0 or win_len > len(x): raise ValueError("Window length must be 0 < window_length < len(x)") xint, yint = interpolate_data(x, y, [], []) window = gaussian(win_len, std=standev) smoothed = convolve(yint, window / window.sum(), mode="same") return xint, smoothed
def cut_data(x, y, ref, sam, start=None, stop=None): x, y = _handle_input(x, y, ref, sam) if start is None: start = np.min(x) if stop is None: stop = np.max(x) if start < stop: low_item, _ = find_nearest(x, start) high_item, _ = find_nearest(x, stop) mask = np.where((x >= low_item) & (x <= high_item)) return x[mask], y[mask] elif stop < start: raise ValueError("Start must not exceed stop value.") else: return np.array([]), np.array([])
def savgol(x, y, ref, sam, window=101, order=3): x, y = _handle_input(x, y, ref, sam) xint, yint = interpolate_data(x, y, [], []) if window > order: try: if window % 2 == 1: fil = savgol_filter(yint, window_length=window, polyorder=order) return xint, fil else: fil = savgol_filter(yint, window_length=window + 1, polyorder=order) return xint, fil except Exception as e: print(e) else: raise ValueError("Order must be lower than window length.")
def cff_method(x, y, ref, sam, ref_point=0, p0=None, maxtries=8000): """ Phase modulated cosine function fit method. Parameters ---------- x: array-like x-axis data y: array-like y-axis data ref, sam: array-like the reference and sample arm spectra evaluated at x p0: array-like the initial parameters for fitting Returns ------- dispersion: array-like [GD, GDD, TOD, FOD, QOD] bf: array-like best fitting curve """ if p0 is None: p0 = [1, 1, 1, 1, 1, 1, 1, 1, 1] x, y = _handle_input(x, y, ref, sam) try: orderhelper = np.max(np.flatnonzero(p0)) - 2 p0 = np.trim_zeros(p0, "b") _funct = _cosfit_config[orderhelper] popt, pcov = curve_fit(_funct, x - ref_point, y, p0, maxfev=maxtries) dispersion = np.zeros_like(popt)[:-3] for num in range(len(popt) - 3): dispersion[num] = popt[num + 3] * factorial(num + 1) return dispersion, _funct(x - ref_point, *popt) except RuntimeError: raise ValueError(f"""Max tries ({maxtries}) reached.. Parameters could not be estimated.""")
def test_input_handling5(self): with self.assertRaises(ValueError): _handle_input([], self.y, [], [])
def test_input_handling4(self): with self.assertRaises(ValueError): _handle_input(self.x, [], [], [])
def test_input_handling3(self): x, y = _handle_input(self.x, self.y, self.ref, []) np.testing.assert_array_equal(x, self.x) np.testing.assert_array_equal(y, self.y)
def min_max_method( x, y, ref, sam, ref_point, maxx=None, minx=None, SPP_callbacks=None, ): """ Build the phase from extremal positions and SPP_callbacks. """ x, y = _handle_input(x, y, ref, sam) if maxx is None: max_ind = argrelextrema(y, np.greater) maxx = x[max_ind] if minx is None: min_ind = argrelextrema(y, np.less) minx = x[min_ind] _, ref_index = find_nearest(x, ref_point) ref_point = x[ref_index] logger.info(f"refpoint set to {x[ref_index]} instead of {ref_point}.") # subtract the reference point from x axis at extremals max_freq = x[ref_index] - maxx min_freq = x[ref_index] - minx if SPP_callbacks is not None: if isinstance(SPP_callbacks, numbers.Number): SPP_callbacks -= ref_point elif isinstance(SPP_callbacks, (list, np.ndarray)): try: SPP_callbacks = np.asarray(SPP_callbacks) - ref_point except TypeError: pass else: raise TypeError("SPP_callbacks must be list-like, or number.") logger.info( f"SPP_callbacks are now {SPP_callbacks}, with ref_point {ref_point}." ) # find which extremal point is where (relative to reference_point) and order them # as they need to be multiplied together with the corresponding order `m` neg_freq = np.sort( np.append(max_freq[max_freq < 0], min_freq[min_freq < 0]))[::-1] pos_freq = np.sort( np.append(max_freq[max_freq >= 0], min_freq[min_freq >= 0])) pos_data_x, pos_data_y = _build_single_phase_data( -pos_freq, SPP_callbacks=SPP_callbacks) # if we fail, the whole negative half is empty try: if np.diff(pos_data_y)[-1] < 0: flip = True logger.info( "Positive side was flipped because the other side is decreasing." ) else: flip = False except IndexError: flip = False neq_data_x, neq_data_y = _build_single_phase_data( -neg_freq, SPP_callbacks=SPP_callbacks, flip=flip) x_s = np.insert(neq_data_x, np.searchsorted(neq_data_x, pos_data_x), pos_data_x) y_s = np.insert(neq_data_y, np.searchsorted(neq_data_x, pos_data_x), pos_data_y) return x_s + ref_point, -y_s + ref_point
def interpolate_data(x, y, ref, sam): x, y = _handle_input(x, y, ref, sam) xint = np.linspace(x[0], x[-1], len(x)) intp = interp1d(x, y, kind="linear") yint = intp(xint) return xint, yint