def kde_minmode(data,x,max_num_mode,min_mode_pdf): kde=gaussian_kde(data) f=kde.factor f_list=np.linspace(f,(data.max()-data.min()),100) s=UnivariateSpline(x,kde(x),s=0) s1=UnivariateSpline(x,s(x,1),s=0) s2=UnivariateSpline(x,s1(x,1),s=0) extrema=s1.roots() maxima=extrema[np.where((s2(extrema)<0)*(s(extrema)>=min_mode_pdf))] if len(maxima)>max_num_mode: for q in range(1,len(f_list)): f=f_list[q] kde2=gaussian_kde(data,bw_method=f) s=UnivariateSpline(x,kde2(x),s=0) s1=UnivariateSpline(x,s(x,1),s=0) s2=UnivariateSpline(x,s1(x,1),s=0) extrema=s1.roots() maxima=extrema[np.where((s2(extrema)<0)*(s(extrema)>=min_mode_pdf))] if len(maxima)<=max_num_mode: ## print 'modes: ',maxima break kde=gaussian_kde(data,bw_method=f) ## else: ## print maxima return kde,maxima
def get_fwhm(flux): #We assume max is on 0. If not, source is probably contaminated flux = flux - flux.min() spline = UnivariateSpline(np.arange(rmax), flux - flux[0] / 2., s=0) if spline.roots().shape != (1, ): return np.nan return spline.roots()[0]
def grad_dist(curdata,ax): #gaussian kernel density estimation x=np.linspace(0,90,91) kde=gaussian_kde(curdata) line,=ax.plot(x,kde(x), '-', label=hl[j][0:-2]+"0") curcolor=plt.getp(line,'color') ## #plotting histogram ## ax.hist(curdata,bins=int(max(curdata))+1, ## normed=True, histtype='step', ## color=curcolor, linewidth=0.5) #defining splines for kd function and corresponding 1st and seconde derivatives x=np.linspace(0,90,901) s=UnivariateSpline(x,kde(x),s=0,k=3) s1=UnivariateSpline(x,s(x,1),s=0,k=3) s2=UnivariateSpline(x,s1(x,1),s=0,k=3) #identifying local maxima (where s1=0, s2<0, and s>0.005) maxima=s1.roots()[np.where(s2(s1.roots())<0)[0]] maxima=maxima[np.where(s(maxima)>0.005)[0]] #s_max=maxima[-1] s_max=maxima[np.argmax(s(maxima))] ax.plot(s_max, s(s_max),'o', color=curcolor) #identifying steepest segment after maxima (where x>=maxima, s1<0) x2=x[np.where(x>=s_max)[0]] slope=s1(x2) s1_min=x2[np.argmin(slope)] ax.plot(s1_min,s(s1_min),'o', color=curcolor) print round(s_max,1),round(s1_min,1) return round(s_max,1),round(s1_min,1)
def fwhm(x, y, bg=[0, 100, 150, 240]): """ Evaluates the full width half maximum of y in units of x. Parameters ---------- x : numpy.array y : numpy.array bg : list Background sampling limits Returns ------- fwhm : number Full width half maximum """ # xnew = copy(x) # ynew = copy(y) # xc = x[(x>bg[0])&(x<bg[1]) | (x>bg[2])&(x<bg[3])] # yc = y[(x>bg[0])&(x<bg[1]) | (x>bg[2])&(x<bg[3])] # bgfit = polyfit(xc,yc,1) # ynew = ynew-polyval(bgfit,xnew) xnew, ynew = rmbg(x, y, bg) f = UnivariateSpline(xnew, ynew / max(ynew) - 0.5, s=0) fwhm = f.roots()[1] - f.roots()[0] return fwhm
def beam_enter_exit(powers, duration, dt=296, min_z_power=0.3): """Calculates when the source enters and exits the beam Parameters ---------- powers : `list`, (ntimes, nfreqs) Powers for the duration every dt and freq. duration : `int` Duration of the observation according to the metadata in seconds. dt : `int`, optional The time interval of how often powers are calculated. Default: 296. min_z_power : `float`, optional Zenith normalised power cut off. |br| Default: 0.3. Returns ------- dect_beg_norm, dect_end_norm : `float` Fraction of the observation when the source enters and exits the beam respectively. """ from scipy.interpolate import UnivariateSpline time_steps = np.array(range(0, duration, dt), dtype=float) # For each time step record the min power so even if the source is in # one freq channel it's recorded powers_freq_min = [] for p in powers: powers_freq_min.append(float(min(p) - min_z_power)) if min(powers_freq_min) > 0.: enter_beam = 0. exit_beam = 1. else: powers_freq_min = np.array(powers_freq_min) logger.debug("time_steps: {}".format(time_steps)) logger.debug("powers: {}".format(powers_freq_min)) try: spline = UnivariateSpline(time_steps, powers_freq_min, s=0.) except: return None, None if len(spline.roots()) == 2: enter_beam, exit_beam = spline.roots() enter_beam /= duration exit_beam /= duration elif len(spline.roots()) == 1: if powers_freq_min[0] > powers_freq_min[-1]: #power declines so starts in beam then exits enter_beam = 0. exit_beam = spline.roots()[0] / duration else: enter_beam = spline.roots()[0] / duration exit_beam = 1. else: enter_beam = 0. exit_beam = 1. return enter_beam, exit_beam
def _computeLag(self, data): """ Given the output of conditional average compute the time lag corresponding to the maximum correlation of each of the structure with respect to the first. In order increase resolution we make a gaussian fit of the cross-correlation function in analogy to what done for TCV using the lmfit class and determine the center of the gaussian Parameters ---------- data xarray DataArray containing the saved Conditional Average structure Returns ------- Dictionary with keys indicating the names of the signals for which cross-correlation are saved and reporting correlation and error """ lag = np.arange(data.shape[1], dtype='float') - data.shape[1]/2. lag *= self.dt outDictionary = {} _Name = [n for n in data.sig.values if n != self.refSignal] for n in _Name: a = data.sel(sig=n).values b = data.sel(sig=self.refSignal).values xcor = np.correlate(a, b, mode='same') xcor /= np.sqrt(np.dot(a, a) * np.dot(b, b)) # the gaussian fit is not approriate for AUG # since the cross-correlation function is strongly asymmetric # we used for fit a Skewed Gaussian Distribution # This is used to estimate the error mod = SkewedGaussianModel() pars = mod.guess(xcor, x=lag) pars['sigma'].set(value=1e-5, vary=True) pars['gamma'].set(value=stats.skew(xcor),vary=True) out = mod.fit(xcor, pars, x=lag) # for a better estimate of the lag we use the computation of the # roots of the hilbert transform of the cross-correlation # function h = hilbert(xcor) S = UnivariateSpline(lag, np.imag(h), s=0) tau = S.roots()[np.argmin(np.abs(S.roots()))] outDictionary[n + '-' + self.refSignal] = {'tau': tau, 'err': out.params['center'].stderr, 'maxlag':lag[np.argmax(xcor)]} return outDictionary
def get_FWHM(resolution,bins): x_range = numpy.linspace(min(resolution),max(resolution),bins) y_values,bin_edges = numpy.histogram(resolution,bins=bins) spline = UnivariateSpline(x_range,y_values - max(y_values)/2.) r = spline.roots() if len(r) != 2: print("Root are weird") print(r) r1 = 0 r2 = 0 else: r1, r2 = spline.roots() return r1, r2
def fit(self, x, y, levels=[0.5, 0.75, 0.25], quiet=False): from scipy.interpolate import UnivariateSpline maxy = np.max(y) miny = np.min(y) self.fitRoots = [] for divide in levels: spline = UnivariateSpline(x, y - (maxy - miny) * divide - miny, s=0) roots = spline.roots() # find the roots if len(roots) != 2: print("ERROR: must be 2 roots on every level.") print("Redefine levels and run again") return r1, r2 = roots self.fitRoots.append(roots) #--------- print("SECTION MEAN : ", np.mean(self.fitRoots)) #PLOT: if not quiet: fig = plt.figure() for divide, (r1, r2) in zip(levels, self.fitRoots): plt.plot([r1, r2], [(maxy - miny) * divide + miny, (maxy - miny) * divide + miny], 'k-') plt.plot([(r1 + r2) / 2, (r1 + r2) / 2], [(maxy - miny) * divide + miny - maxy / 20, (maxy - miny) * divide + miny + maxy / 20], 'k-') plt.plot(x, y, 'k-') return np.round(np.mean(self.fitRoots), 1)
def fwhm_datarun(datarun, known_energy, yrange=[0, -1], xrange=[0, -1], rebin=1, fwhm_smooth=2, **kwargs): """ Given a 2d-array of [energies(eV),lineout], calculate fwhm of peak in the lineout. """ lineout = np.sum(datarun.get_array()[yrange[0]:yrange[1], xrange[0]:xrange[1]], axis=1) / datarun.photon_value if rebin != 1: #rebin using oliver's rebin_spectrum function lineout = _rebin_spectrum(np.array(range(len(lineout))), lineout, rebin)[1] lineout_energyscale = add_energy_scale(lineout, known_energy, rebinparam=rebin, **kwargs) x, y = lineout_energyscale y = gfilt(y, fwhm_smooth) spline = UnivariateSpline(x, y - np.max(y) / 2, s=0) r1, r2 = spline.roots() return format(r2 - r1, '.3f')
def get_fwhm(self): """uses a 3rd degree smoothing spline to model the peak. All half max is subtracted from all the rfu data. """ maxrfu = max(self.rnrfu) halfmax = maxrfu / 2 # create a spline of x and blue-np.max(blue)/2 # print(len(self.rntime), len(self.rnrfu), len(np.subtract(self.rnrfu, halfmax))) spline = UnivariateSpline(np.asarray(self.rntime), np.subtract(self.rnrfu, halfmax), s=0) # find the roots roots = spline.roots() # if we don't have our peaks separated all the way and cant reach half max if len(roots) < 2: r2 = self.rntime[-1] r1 = self.rntime[0] else: r2 = roots[-1] r1 = roots[0] # print(r2, r1, "were r's", self.rntime[self.rnrfu.index(maxrfu)]) if r2 < self.rntime[self.rnrfu.index(maxrfu)]: r2 = self.rntime[-1] if r1 > self.rntime[self.rnrfu.index(maxrfu)]: r1 = self.rntime[0] fwhm = np.abs(r2 - r1) # print(fwhm, " is the FWHM") self.spline = spline return fwhm
def map_metric(block_level, data: MetricTuple, metric: str, ion: str) -> Tuple[Optional[float], Optional[float]]: """Compute the block_level required to present the same percentage change as in Smith and Zakon 2000. :param block_level: Sequence of block levels :param data: Listed MetricTuple :param metric: Name of the metric to map :param ion: Name of the ion (Na/K) :return: Effective block level and metric value """ data = np.array(data.__getattribute__(metric), dtype=float) # extract metric from named tuple block_level = block_level[::-1] data = data[::-1] # fitting requires increasing 'x' # clip out crash invalid = np.where(np.isnan(data))[0][0] data_trim = data[:invalid] trimed_block = block_level[:invalid] percent_change = (data_trim - data_trim[0]) / abs(data_trim[0]) # root finding y_to_find = CHANGE_DATA[ion][metric] freduced = UnivariateSpline(trimed_block, percent_change - y_to_find, s=0) effective_block = freduced.roots() if effective_block: f = UnivariateSpline(trimed_block, data_trim, s=0) return effective_block, f(effective_block) return np.nan, np.nan
def get_t_for_vols(self, vols, t_max=1000): """ Find the temperatures corresponding to a specific volume. The search is performed interpolating the V(T) dependence with a spline and finding the roots with of V(t) - v. It may return more than one temperature for a volume in case of non monotonic behavior. Args: vols: list of volumes t_max: maximum temperature considered for the fit Returns: A list of lists of temperatures. For each volume more than one temperature can be identified. """ if not isinstance(vols, (list, tuple, np.ndarray)): vols = [vols] f = self.fit_energies(0, t_max, t_max+1) temps = [] for v in vols: spline = UnivariateSpline(f.temp, f.min_vol - v, s=0) temps.append(spline.roots()) return temps
def FWHM(self, bins, vals): spline = UnivariateSpline(bins[:-1] + np.diff(bins) / 2., vals - np.max(vals) / 2., s=0) roots = spline.roots() # find the roots r1, r2 = roots[0], roots[-1] return np.abs(r1 - r2)
def acf(self): """ Compute the autocorrelation function according to http://stackoverflow.com/q/14297012/190597 http://en.wikipedia.org/wiki/Autocorrelation#Estimation Parameters ---------- None Results ------- Autocorrelation function Attributes ---------- Define the autocorrelation time as attribute to the class (self.act) computed as the time where the correlation is 1/e the maximum value """ n = self.nsamp variance = self.variance xx = self.sig - self.mean r = np.correlate(xx, xx, mode='full')[-n:] result = r / (variance * (np.arange(n, 0, -1))) # define the lag lag = np.arange(result.size, dtype='float') * self.dt # interpolate S = UnivariateSpline(lag, result - 1. / np.exp(1), s=0) self.act = S.roots()[0] return result
def get_t_for_vols(self, vols, t_max=1000): """ Find the temperatures corresponding to a specific volume. The search is performed interpolating the V(T) dependence with a spline and finding the roots with of V(t) - v. It may return more than one temperature for a volume in case of non monotonic behavior. Args: vols: list of volumes t_max: maximum temperature considered for the fit Returns: A list of lists of temperatures. For each volume more than one temperature can be identified. """ if not isinstance(vols, (list, tuple, np.ndarray)): vols = [vols] f = self.fit_energies(0, t_max, t_max + 1) temps = [] for v in vols: spline = UnivariateSpline(f.temp, f.min_vol - v, s=0) temps.append(spline.roots()) return temps
def imageSlice(image, xc, yc, width): ylen, xlen = image.shape xstart = max(0, xc - width / 2) xend = min(xlen, xc + width / 2) # I cannot get array slicing to work for the life of me slice = [] for i in range(int(xstart), int(xend)): slice.append(image[yc, i]) # https://stackoverflow.com/questions/10582795/finding-the-full-width-half-maximum-of-a-peak/10583774#10583774 shiftedSlice = [] halfMax = max(slice) / 2 baseline = numpy.mean(image) for y in slice: shiftedSlice.append(y - halfMax - baseline) x = numpy.linspace(0, width, width) spline = UnivariateSpline(x, shiftedSlice, s=0) r1, r2 = spline.roots() #r1 = 0 #r2 = 0 return (slice, r2 - r1)
def halbwertsbreite(x, y): spline = UnivariateSpline(x, y-np.max(y)/2, s=0) r1, r2 = spline.roots() # find the roots lambda1 = 2*d*np.sin(np.deg2rad(r1)) lambda2 = 2*d*np.sin(np.deg2rad(r2)) E1 = h*c/lambda1 E2 = h*c/lambda2 DE = E1 - E2 print ('Halbwertswinkel: {0:.5e} deg, {1:.5e} deg'.format(r1, r2)) print ('Halbwertsbreite: {0:.5e}'.format(np.abs(r1-r2))) print (u'Energieaufloesung: {0:.5e} eV'.format(DE)) xnew = np.linspace(min(x), max(x)) ynew = spline(xnew) plt.plot(x, y, 'rx', label='Messdaten') plt.plot(xnew, ynew+np.max(y)/2,'b-', label='Interpolation') plt.axvline(r1) plt.axvline(r2) plt.grid() plt.legend() plt.xlabel("doppelter Kristallwinkel in Grad") plt.ylabel(u"Zählrate")
def peak_fwhm(peak, gram): """ Returns the full width half max of the peak. Calculates FWHM using a 3rd degree spline of the peak and determining the width at exactly 1/2 of the max signal. :param peak: Peak to analzye :return: full width half max :rtype : float """ peak_rfu, peak_time = get_peak_portions(peak, gram) maxrfu = max(peak_rfu) halfmax = maxrfu / 2 # create a spline of x and blue-np.max(blue)/2 spline = UnivariateSpline(np.asarray(peak_time), np.subtract(peak_rfu, halfmax), s=0) # find the roots roots = spline.roots() # if we don't have our peaks separated all the way and cant reach half max if len(roots) < 2: r2 = peak_time[-1] r1 = peak_time[0] else: r2 = roots[-1] r1 = roots[0] if r2 < peak_time[peak_rfu.index(maxrfu)]: r2 = peak_time[-1] if r1 > peak_time[peak_rfu.index(maxrfu)]: r1 = peak_time[0] fwhm = np.abs(r2 - r1) return fwhm
def fwhm(x, y, k=10, ret_roots=False): """ Determine full-with-half-maximum of a peaked set of points, x and y. Assumes that there is only one peak present in the dataset. The function uses a spline interpolation with smoothing parameter k ('s' in scipy.interpolate.UnivariateSpline). """ class MultiplePeaks(Exception): pass class NoPeaksFound(Exception): pass half_max = np.max(y) / 2.0 s = UnivariateSpline(x, y - half_max, s=k) roots = s.roots() if len(roots) > 2: # Multiple peaks. Use the two that straddle the maximum value maxvel = x[np.argmax(y)] left_idx = np.argmin(maxvel - roots) right_idx = np.argmin(roots - maxvel) roots = np.array((roots[left_idx], roots[right_idx])) elif len(roots) < 2: raise NoPeaksFound("No proper peaks were found in the data set; likely " "the dataset is flat (e.g. all zeros).") if ret_roots: return roots[0], roots[1] return abs(roots[1] - roots[0])
def calc_fwhm(x, y, return_roots=False): """ Calculates the FWHM for a given dataset, by finding the roots of splines. INPUTS: x - x input array y - y input array OUTPUT: FWHM The Full Width Half Max of the data OPTIONAL: return_roots - Boolean. If true, return the roots. EXAMPLE: """ spline = UnivariateSpline(x, y - np.max(y) / 2.0, s=0) roots = spline.roots() fwhm = roots[1] - roots[0] if return_roots == True: return fwhm, roots else: return fwhm
def halbwertsbreite(x, y): spline = UnivariateSpline(x, y - np.max(y) / 2, s=0) r1, r2 = spline.roots() # find the roots lambda1 = 2 * d * np.sin(np.deg2rad(r1)) lambda2 = 2 * d * np.sin(np.deg2rad(r2)) E1 = h * c / lambda1 E2 = h * c / lambda2 DE = E1 - E2 print 'Halbwertswinkel: {0:.5e} deg, {1:.5e} deg'.format(r1, r2) print 'Halbwertsbreite: {0:.5e}'.format(np.abs(r1 - r2)) print u'Energieaufloesung: {0:.5e} eV'.format(DE) xnew = np.linspace(min(x), max(x)) ynew = spline(xnew) plt.plot(x, y, "x") plt.plot(xnew, ynew + np.max(y) / 2, label='Interpolation') plt.axvline(r1) plt.axvline(r2) plt.grid() plt.legend() plt.xlabel("Kristallwinkel in Grad") plt.ylabel(u"Zählrate")
def calc_fwzm(x, y, z=20, return_roots=False): """ Calculates the Full with at the Z-th maximum for a given dataset, by finding the roots of splines. INPUTS: x - x input array y - y input array OUTPUT: FWZM The Full Width Half Max of the data OPTIONAL: return_roots - Boolean. If true, return the roots. EXAMPLE: """ try: spline = UnivariateSpline(x, y - np.max(y) / z, s=0) roots = spline.roots() fwzm = roots[1] - roots[0] if return_roots == True: return fwzm, roots else: return fwzm except Exception as e: print("Error with finding roots! Returning 0") if return_roots == True: return 0., 0 else: return 0.
def curveFitting(diff, title): plt.figure() y, bins, patches = plt.hist(diff, bins=200, range=(-100, 100)) x = bins[:-1] + 0.5 mean = np.mean(diff) sigma = np.std(diff) print("------------") print(title) print(mean) print(sigma) popt, pcov = curve_fit(gaussian, x, y, p0=[1, mean, sigma]) y_gauss = gaussian(x, *popt) spline = UnivariateSpline(x, y_gauss - np.max(y_gauss) / 2, s=0) r1, r2 = spline.roots() # find the roots print(r1) print(r2) print("FWHM: " + str(abs(r2 - r1))) plt.figure() plt.plot(x, y, 'b+:', label='data') plt.plot(x, gaussian(x, *popt), 'ro:', label='fit') plt.legend() plt.title(title)
def spline_plotting(x, y, nrmse): if not nrmse: spline = UnivariateSpline(x, y - np.max(y) / 2, s=0) r1, r2 = spline.roots() # find the roots else: spline = UnivariateSpline(x, y - np.max(abs(y)) / 2, s=0) r1, r2 = spline.roots() # find the roots FWHM = abs(r1 - r2) print("r1=%f and r2=%f" % (r1, r2)) print("FWHM", FWHM) plot(x, y) plot(r1, 0, marker='o') plot(r2, 0, marker='o') axvspan(r1, r2, facecolor='g', alpha=0.5) show() return FWHM
def bandwidth(wl, phi, **kwargs): """ Function to calculate the bandwidth of a given phasematching spectrum fitting it with savgol_filter and then approximating it with a UnivariateSpline. .. warning:: This function has not been tested thoroughly. :param wl: Wavelengths :type wl: Array :param phi: Phasematching intensity :type phi: Array :return: FWHM bandwidth of the phasematching intensity Additional parameters :param window_size: Savgol_filter window_size parameter :type window_size: int :param polynomial_order: Savgol_filter polynomial_order parameter :type polynomial_order: int """ window_size = kwargs.get("window_size", 71) polynomial_order = kwargs.get("polynomial_order", 9) smoothed = savgol_filter(phi, window_size, polynomial_order) spline = UnivariateSpline(wl * 1e9, np.abs(smoothed) ** 2 - np.max(np.abs(smoothed) ** 2) / 2, s=0) r1, r2 = spline.roots() bw = r2 - r1 return bw
def curie_inflection(self, min_temp: float, max_temp: float)\ -> Tuple[float, UnivariateSpline]: """Estimate Curie temperature by inflection point. Estimate Curie point by determining the inflection point of the curve segment starting at the Hopkinson peak. The curve segment must be specified. :param min_temp: start of curve segment :param max_temp: end of curve segment :return: (temp, spline) where temp is the estimated Curie temperature; spline is the scipy.interpolate.UnivariateSpline used to fit the data and determine the inflection point """ # Fit a cubic spline to the data. Using the whole dataset gives # a better approximation at the endpoints of the selected range. spline = UnivariateSpline(self.data[0][0], self.data[0][1], s=.1) # Get the data points which lie within the selected range. temps, _ = MeasurementCycle.chop_data(self.data[0], min_temp, max_temp) # Evaluate the second derivative of the spline at each selected # temperature step. derivs = [spline.derivatives(t)[2] for t in temps] # Fit a new spline to the derivatives in order to calculate the # inflection point. spline2 = UnivariateSpline(temps, derivs, s=3) # The root of the 2nd-derivative spline gives the inflection point. return spline2.roots()[0], spline
def fwhm(arr1d): """ Given an array containing a peak, return its FWHM based on a spline interpolation. """ x = np.arange(len(arr1d)) spline = UnivariateSpline(x, arr1d - np.max(arr1d) / 2, s=0) r1, r2 = spline.roots() return r2 - r1
def beam_enter_exit(powers, duration, dt=296, min_power=0.3): """ Calculates when the source enters and exits the beam beam_enter_exit(min_power, powers, imax, dt): powers: list of powers fo the duration every dt and freq powers[times][freqs] dt: the time interval of how often powers are calculated duration: duration of the observation according to the metadata in seconds min_power: zenith normalised power cut off """ from scipy.interpolate import UnivariateSpline time_steps = np.array(range(0, duration, dt), dtype=float) #For each time step record the min power so even if the source is in #one freq channel it's recorded powers_freq_min = [] for p in powers: powers_freq_min.append(float(min(p) - min_power)) if min(powers_freq_min) > 0.: enter = 0. exit = 1. else: powers_freq_min = np.array(powers_freq_min) logger.debug("time_steps: {}".format(time_steps)) logger.debug("powers: {}".format(powers_freq_min)) try: spline = UnivariateSpline(time_steps, powers_freq_min, s=0.) except: return None, None if len(spline.roots()) == 2: enter, exit = spline.roots() enter /= duration exit /= duration elif len(spline.roots()) == 1: if powers_freq_min[0] > powers_freq_min[-1]: #power declines so starts in beem then exits enter = 0. exit = spline.roots()[0] / duration else: enter = spline.roots()[0] / duration exit = 1. else: enter = 0. exit = 1. return enter, exit
def fwhm_ev(arr2d, fwhm_smooth=2): """ Given a 2d-array of [energies(eV),lineout], calculate fwhm of peak in the lineout. """ x, y = arr2d y = gfilt(y, fwhm_smooth) spline = UnivariateSpline(x, y - np.max(y) / 2, s=0) r1, r2 = spline.roots() return format(r2 - r1, '.3f')
def FWHM_scipy(X, Y): """Computing FWHM (Full width at half maximum)""" try: from scipy.interpolate import UnivariateSpline spline = UnivariateSpline(X, Y, s=0) r1, r2 = spline.roots() # find the roots return r2 - r1 # return the difference (full width) except ImportError: return FWHM(X, Y)
def get_depth(array): x = np.linspace(0,1,array.shape[0]) z = array #data points spl = UnivariateSpline(x,z) spl.set_smoothing_factor(10) z_spl = spl(x) z_smooth = UnivariateSpline(x, z_spl) z_smooth.set_smoothing_factor(1e5) #getting the first order derivative dz = np.gradient(z_spl) dz_spl = UnivariateSpline(x, dz) dz_spl.set_smoothing_factor(1e-3) #getting the second order derivative h = 0.0001 d2z = (dz[1:]-dz[:-1])/h d2z_spl = UnivariateSpline(x[1:], d2z) d2z_spl.set_smoothing_factor(1e-3) #getting the difference between the aaverage line and the "real" profile delta_z = z_spl - z_smooth(x) delta_z_spl = UnivariateSpline(x, delta_z) delta_z_spl.set_smoothing_factor(1e-3) #first derivative of the difference of the two lines dz = np.gradient(delta_z) dz_spl = UnivariateSpline(x, dz) dz_spl.set_smoothing_factor(1e-3) roots = dz_spl.roots() #roots of the difference mins = [i for _,i in sorted(zip(delta_z_spl(roots),roots))][:2] #roots = dz_spl.roots() eps_down=5 #lower bound for second dderivative n=len(mins) #print("Second derivative value at its roots",d2z_spl(roots)) grooves=[] for i in range(n): if d2z_spl(mins[i]) > eps_down and (z_smooth(mins[i]) -spl(mins[i])) >= 1: grooves.append(mins[i]) #or roots, I dont know grooves=np.array(grooves) #print("All roots",roots) dz_mins = delta_z_spl(grooves) if dz_mins.size ==0: return np.nan return -1*np.average(dz_mins)
def guessMeanFwhmAmplitude(self, xdata, ydata): peaky = np.amax(ydata) index = np.where(ydata == peaky)[0][0] peakx = xdata[index] halfpeaky = peaky / 2. f = UnivariateSpline(xdata, ydata - peaky / 2., k=3) w1, w2 = f.roots() fwhm = w2 - w1 return peakx, fwhm, peaky
def graph(filename, name): # load the data df = pd.read_csv(filename, header=None, skiprows=[0]) df = df.to_numpy() X = df[:, 0] Y = df[:, 1:] # plot the raw data fig, ax = plt.subplots(figsize=(12, 8)) for col in range(Y.shape[1]): # columns to skip if col + 1 in [6, 7, 8]: continue print(f"Plotting column {col+1}...", end='\r') ax.plot(X, Y[:, col], label=f"Plot {col+1}") # produce a guess for your parameters # NOTE manual guesses are better! # curve_fit will then fine tune the values mean = 1.2484e10 std = 1.5e5 # Gaussian best fit Y_hat = np.mean(Y, axis=1) # NOTE check out the documentation for curve_fit, its helpful opt, _ = curve_fit(gaussian, X, Y_hat, p0=[1, mean, std]) print("\nOptimal parameters:", opt) # plot the best fit ax.plot(X, gaussian(X, *opt), label=f"Best Fit", linestyle='--') # FWHM S = Y.sum(axis=1) spline = UnivariateSpline(X, S - np.max(S) / 2, s=0) r = spline.roots() # find the roots r1, r2 = r[0], r[-1] print(f"Lower: {r1}\nUpper: {r2}") plt.axvline(x=r1, color='g', linestyle="--", alpha=0.5) plt.axvline(x=r2, color='g', linestyle="--", alpha=0.5) # graph labelling plt.legend() plt.xlabel("Frequency (Hz)") plt.ylabel("Amplitude") plt.savefig(f"{name}.png") print("Done!")
def fwhm_scipy(x, y): #MR27092016 """Computing FWHM (Full width at half maximum)""" try: from scipy.interpolate import UnivariateSpline spline = UnivariateSpline(x, y, s=0) r1, r2 = spline.roots() # find the roots return r2 - r1 # return the difference (full width) except ImportError: return fwhm(x, y)
def fwhm(data, ypos=0.5): spatial = data.sum(1) spatial = spatial-np.min(spatial) spatial_range = range(0, len(spatial)) spline = UnivariateSpline(spatial_range, (spatial -np.max(spatial)*ypos), s=0.1, k=3) roots = spline.roots() if len(roots) < 2: return np.inf, (-np.inf, +np.inf) return roots[-1]-roots[0], roots
def fwhm(x, y): try: if x[0] > x[-1]: x, y = x[::-1], y[::-1] spline = UnivariateSpline(x, y - y.max() * 0.5, s=0) roots = spline.roots() return max(roots) - min(roots) except ValueError: return
def _computeDeltaT(self, x, y, e): """ Computation of FWHM of the Ion saturation current Conditionally averaged sampled signal. It actually provide the computation directly as the FWHM Parameters ---------- x: time basis y: results of the CAS for ion saturation current e: error Returns ------- delta : the FWHM err : the Error on the FWHM """ _dummy = (y - y.min()) spline = UnivariateSpline(x, _dummy - _dummy.max()/2., s=0) if spline.roots().size > 2: a = np.sort(spline.roots()) r1 = a[a < 0][-1] r2 = a[a > 0][0] else: r1, r2 = spline.roots() delta = (r2 - r1) # now compute an estimate of the error _dummy = (y + e) - (y + e).min() spline = UnivariateSpline(x, _dummy - _dummy.max()/2., s=0) if spline.roots().size > 2: a = np.sort(spline.roots()) r1 = a[a < 0][-1] r2 = a[a > 0][0] else: r1, r2 = spline.roots() deltaUp = (r2 - r1) _dummy = (y - e) - (y - e).min() spline = UnivariateSpline(x, _dummy - _dummy.max()/2., s=0) if spline.roots().size > 2: a = np.sort(spline.roots()) r1 = a[a < 0][-1] r2 = a[a > 0][0] else: r1, r2 = spline.roots() deltaDown = (r2 - r1) err = np.asarray([np.abs(delta), np.abs(deltaUp), np.abs(deltaDown)]).std() return delta, err
def MTF50(self, MTFx, MTFy): ''' return object resolution as [line pairs/mm] where MTF=50% see http://www.imatest.com/docs/sharpness/ ''' if self.mtf_x is None: self.MTF() f = UnivariateSpline(self.mtf_x, self.mtf_y - 0.5) return f.roots()[0]
def find_critical_temperature(df, offset): curve = [] temps = np.round(df.temperature,2).unique() for temp in temps: curve.append([temp,df.loc[np.round(df.temperature,2) == temp].TTc.mean()]) curve = np.array(curve) curve = curve[curve[:,0].argsort()] f = UnivariateSpline(curve[:,0],curve[:,1]-offset) root = f.roots() return root[0]
def MTF50(self, MTFx,MTFy): ''' return object resolution as [line pairs/mm] where MTF=50% see http://www.imatest.com/docs/sharpness/ ''' if self.mtf_x is None: self.MTF() f = UnivariateSpline(self.mtf_x, self.mtf_y-0.5) return f.roots()[0]
def correlation(x, y): """ Compute the cross correlation function, return the lag x-values, the normalized correlation and the correlation time defined as where it assumes 1/e values of the maximum Args: x: first array y: second array. Can be the same and then computes the auto-correlation time Returns: tuple with lag, correlation and correlation time """ lag = np.arange(x.size, dtype="float") - x.size / 2.0 c = np.correlate(x, y, mode="same") c /= np.sqrt(np.dot(x, x) * np.dot(y, y)) S = UnivariateSpline(lag, c - 1 / np.exp(1), s=0) tac = S.roots()[S.roots() > 0][0] return lag, c, tac
def interpolate_to_find_crossover(frequencies,spl): from scipy.interpolate import UnivariateSpline s = UnivariateSpline(frequencies,spl,s=0) root = [] for r in s.roots(): if r>=1000 and r<=5000: root.append(r) if len(root)==1: return root[0] else: return 0
def calculate_fwhm(stimuli): """ Returns a tuple with positions on the x axis Assumes that stimuli exists in self.smooth_responses """ top = peaks[stimuli][1] low = float(self.smoothed_responses[stimuli](0)) half_max = (top - low)/2 y = self.mean_responses[stimuli] spline = UnivariateSpline(self.x_axis, y - half_max - low, s=factor) roots = spline.roots() if np.any(roots): for i in range(1, len(roots)): if roots[i] > peaks[stimuli][0]: break roots = (roots[i - 1], roots[i]) return roots
def integral(x, y, I, k=10): """ Integrate y = f(x) for x = 0 to a such that the integral = I I can be an array """ I = np.atleast_1d(I) f = UnivariateSpline(x, y, s=k) # Integrate as a function of x F = f.antiderivative() Y = F(x) a = [] for intval in I: F2 = UnivariateSpline(x, Y/Y[-1] - intval, s=0) a.append(F2.roots()) return np.hstack(a)
def get_profile_func_ab(self, profile_x, profile_y): from scipy.interpolate import UnivariateSpline profile_ = UnivariateSpline(profile_x, profile_y, k=3, s=0, bbox=[0, 1]) roots = list(profile_.roots()) #assert(len(roots) == 1) integ_list = [] from itertools import izip, cycle for ss, int_r1, int_r2 in izip(cycle([1, -1]), [0] + roots, roots + [1]): #print ss, int_r1, int_r2 integ_list.append(profile_.integral(int_r1, int_r2)) integ = np.abs(np.sum(integ_list)) def profile(o, x, slitpos): return profile_(slitpos) / integ return profile
def interpolate( file ): openFile = open(file, "r") read_it = openFile.read() x = [] y = [] for line in read_it.splitlines(): text = line.split() x.append( float(text[0]) ) #Add all x's to an array y.append( float(text[1]) ) #Add all y's to an array x = np.array(x) y = np.array(y) f = UnivariateSpline(x,y,k=3) #Interpolate the points roots = f.roots() #Find the roots print roots openFile.close();
def long_jump(V0,p,x=0,dt=0.1,f=stdout): """calculate parabolic trajectory w/drag via iteration using a fixed step size Rk4 method""" Dc=-0.000225*p x=[x] y=[0] v=[(V0*cos(pi/8),V0*sin(pi/8))] dvx=lambda x:Dc*x**2 dvy=lambda y:Dc*y**2-9.81 i=0 while y[i]>-0.1: v.append((Rk4(dvx,v[i][0],dt),Rk4(dvy,v[i][1],dt))) x.append(x[i]+dt/2*(v[i][0]+v[i+1][0])) y.append(y[i]+dt/2*(v[i][1]+v[i+1][1])) i+=1 #position step is simplified but it should be accurate enough, if not the rk4 version is outlined in that function fxn=UnivariateSpline(x,y) dist=fxn.roots() print("The distance jumped was {:6g} m".format(dist[len(dist)-1]),file=f) #elif V0==0: # v_i=-v[len(v)-1][1]/sin(pi/2) # v_init=(v_i*cos(pi/8),v_i*sin(pi/8)) # print("The inital velocity was {} m/s or \nThe vector {}".format(v_i,v_init),file=f) return
plt.plot(x, y, 'rx', label='Messdaten') plt.plot(xnew, ynew+np.max(y)/2,'b-', label='Interpolation') plt.axvline(r1) plt.axvline(r2) plt.grid() plt.legend() plt.xlabel("doppelter Kristallwinkel in Grad") plt.ylabel(u"Zählrate") ############################################################### spline = UnivariateSpline(theta[84:90], Z[84:90]-np.max(Z[84:90])/2, s=0) r1, r2 = spline.roots() # find the roots lambda1 = 2*d*np.sin(np.deg2rad(r1)) lambda2 = 2*d*np.sin(np.deg2rad(r2)) E1 = h*c/lambda1 E2 = h*c/lambda2 DE = E1 - E2 print ('Halbwertswinkel: {0:.5e} deg, {1:.5e} deg'.format(r1, r2)) print ('Halbwertsbreite: {0:.5e}'.format(np.abs(r1-r2))) print (u'Energieaufloesung: {0:.5e} eV'.format(DE)) xnew = np.linspace(min(theta[84:90]), max(theta[84:90])) ynew = spline(xnew) plt.plot(theta[84:90], Z[84:90], 'rx', label='Messdaten') plt.plot(xnew, ynew+np.max(Z[84:90])/2,'b-', label='Interpolation')
def estimate(self, observedLC): """! Estimate intrinsicFlux, period, eccentricity, omega, tau, & a2sini """ ## intrinsicFluxEst maxPeriodFactor = 10.0 model = LombScargleFast().fit(observedLC.t, observedLC.y, observedLC.yerr) periods, power = model.periodogram_auto(nyquist_factor = observedLC.numCadences) model.optimizer.period_range = (2.0*np.mean(observedLC.t[1:] - observedLC.t[:-1]), maxPeriodFactor*observedLC.T) periodEst = model.best_period numIntrinsicFlux = 100 lowestFlux = np.min(observedLC.y[np.where(observedLC.mask == 1.0)]) highestFlux = np.max(observedLC.y[np.where(observedLC.mask == 1.0)]) intrinsicFlux = np.linspace(np.min(observedLC.y[np.where(observedLC.mask == 1.0)]), np.max(observedLC.y[np.where(observedLC.mask == 1.0)]), num = numIntrinsicFlux) intrinsicFluxList = list() totalIntegralList = list() for f in xrange(1, numIntrinsicFlux - 1): beamedLC = observedLC.copy() beamedLC.x = np.require(np.zeros(beamedLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) for i in xrange(beamedLC.numCadences): beamedLC.y[i] = observedLC.y[i]/intrinsicFlux[f] beamedLC.yerr[i] = observedLC.yerr[i]/intrinsicFlux[f] dopplerLC = beamedLC.copy() dopplerLC.x = np.require(np.zeros(dopplerLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) for i in xrange(observedLC.numCadences): dopplerLC.y[i] = math.pow(beamedLC.y[i], 1.0/3.44) dopplerLC.yerr[i] = (1.0/3.44)*math.fabs(dopplerLC.y[i]*(beamedLC.yerr[i]/beamedLC.y[i])) dzdtLC = dopplerLC.copy() dzdtLC.x = np.require(np.zeros(dopplerLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) for i in xrange(observedLC.numCadences): dzdtLC.y[i] = 1.0 - (1.0/dopplerLC.y[i]) dzdtLC.yerr[i] = math.fabs((-1.0*dopplerLC.yerr[i])/math.pow(dopplerLC.y[i], 2.0)) foldedLC = dzdtLC.fold(periodEst) foldedLC.x = np.require(np.zeros(foldedLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) integralSpline = UnivariateSpline(foldedLC.t[np.where(foldedLC.mask == 1.0)], foldedLC.y[np.where(foldedLC.mask == 1.0)], 1.0/foldedLC.yerr[np.where(foldedLC.mask == 1.0)], k = 3, s = None, check_finite = True) totalIntegral = math.fabs(integralSpline.integral(foldedLC.t[0], foldedLC.t[-1])) intrinsicFluxList.append(intrinsicFlux[f]) totalIntegralList.append(totalIntegral) intrinsicFluxEst = intrinsicFluxList[np.where(np.array(totalIntegralList) == np.min(np.array(totalIntegralList)))[0][0]] ## periodEst for i in xrange(beamedLC.numCadences): beamedLC.y[i] = observedLC.y[i]/intrinsicFluxEst beamedLC.yerr[i] = observedLC.yerr[i]/intrinsicFluxEst dopplerLC.y[i] = math.pow(beamedLC.y[i], 1.0/3.44) dopplerLC.yerr[i] = (1.0/3.44)*math.fabs(dopplerLC.y[i]*(beamedLC.yerr[i]/beamedLC.y[i])) dzdtLC.y[i] = 1.0 - (1.0/dopplerLC.y[i]) dzdtLC.yerr[i] = math.fabs((-1.0*dopplerLC.yerr[i])/math.pow(dopplerLC.y[i], 2.0)) model = LombScargleFast().fit(dzdtLC.t, dzdtLC.y, dzdtLC.yerr) periods, power = model.periodogram_auto(nyquist_factor = dzdtLC.numCadences) model.optimizer.period_range = (2.0*np.mean(dzdtLC.t[1:] - dzdtLC.t[:-1]), maxPeriodFactor*dzdtLC.T) periodEst = model.best_period ## eccentricityEst & omega2Est # First find a full period going from rising to falling. risingSpline = UnivariateSpline(dzdtLC.t[np.where(dzdtLC.mask == 1.0)], dzdtLC.y[np.where(dzdtLC.mask == 1.0)], 1.0/dzdtLC.yerr[np.where(dzdtLC.mask == 1.0)], k = 3, s = None, check_finite = True) risingSplineRoots = risingSpline.roots() firstRoot = risingSplineRoots[0] if risingSpline.derivatives(risingSplineRoots[0])[1] > 0.0: tRising = risingSplineRoots[0] else: tRising = risingSplineRoots[1] # Now fold the LC starting at tRising and going for a full period. foldedLC = dzdtLC.fold(periodEst, tStart = tRising) foldedLC.x = np.require(np.zeros(foldedLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) # Fit the folded LC with a spline to figure out alpha and beta fitLC = foldedLC.copy() foldedSpline = UnivariateSpline(foldedLC.t[np.where(foldedLC.mask == 1.0)], foldedLC.y[np.where(foldedLC.mask == 1.0)], 1.0/foldedLC.yerr[np.where(foldedLC.mask == 1.0)], k = 3, s = 2*foldedLC.numCadences, check_finite = True) for i in xrange(fitLC.numCadences): fitLC.x[i] = foldedSpline(fitLC.t[i]) # Now get the roots and find the falling root tZeros = foldedSpline.roots() if tZeros.shape[0] == 1: # We have found just tFalling tFalling = tZeros[0] tRising = fitLC.t[0] startIndex = 0 tFull = fitLC.t[-1] stopIndex = fitLC.numCadences elif tZeros.shape[0] == 2: # We have found tFalling and one of tRising or tFull if foldedSpline.derivatives(tZeros[0])[1] < 0.0: tFalling = tZeros[0] tFull = tZeros[1] stopIndex = np.where(fitLC.t < tFull)[0][-1] tRising = fitLC.t[0] startIndex = 0 elif foldedSpline.derivatives(tZeros[0])[1] > 0.0: if foldedSpline.derivatives(tZeros[1])[1] < 0.0: tRising = tZeros[0] startIndex = np.where(fitLC.t > tRising)[0][0] tFalling = tZeros[1] tFull = fitLC.t[-1] stopIndex = fitLC.numCadences else: raise RuntimeError('Could not determine alpha & omega correctly because the first root is rising but the second root is not falling!') elif tZeros.shape[0] == 3: tRising = tZeros[0] startIndex = np.where(fitLC.t > tRising)[0][0] tFalling = tZeros[1] tFull = tZeros[2] stopIndex = np.where(fitLC.t < tFull)[0][-1] else: raise RuntimeError('Could not determine alpha & omega correctly because tZeros has %d roots!'%(tZeros.shape[0])) # One full period now goes from tRising to periodEst. The maxima occurs between tRising and tFalling while the minima occurs between tFalling and tRising + periodEst # Find the minima and maxima alpha = math.fabs(fitLC.x[np.where(np.max(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]]) beta = math.fabs(fitLC.x[np.where(np.min(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]]) peakLoc = fitLC.t[np.where(np.max(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]] troughLoc = fitLC.t[np.where(np.min(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]] KEst = 0.5*(alpha + beta) delta2 = (math.fabs(foldedSpline.integral(tRising, peakLoc)) + math.fabs(foldedSpline.integral(troughLoc, tFull)))/2.0 delta1 = (math.fabs(foldedSpline.integral(peakLoc, tFalling)) + math.fabs(foldedSpline.integral(tFalling, troughLoc)))/2.0 eCosOmega2 = (alpha - beta)/(alpha + beta) eSinOmega2 = ((2.0*math.sqrt(alpha*beta))/(alpha + beta))*((delta2 - delta1)/(delta2 + delta1)) eccentricityEst = math.sqrt(math.pow(eCosOmega2, 2.0) + math.pow(eSinOmega2, 2.0)) tanOmega2 = math.fabs(eSinOmega2/eCosOmega2) if (eCosOmega2/math.fabs(eCosOmega2) == 1.0) and (eSinOmega2/math.fabs(eSinOmega2) == 1.0): omega2Est = math.atan(tanOmega2)*(180.0/math.pi) if (eCosOmega2/math.fabs(eCosOmega2) == -1.0) and (eSinOmega2/math.fabs(eSinOmega2) == 1.0): omega2Est = 180.0 - math.atan(tanOmega2)*(180.0/math.pi) if (eCosOmega2/math.fabs(eCosOmega2) == -1.0) and (eSinOmega2/math.fabs(eSinOmega2) == -1.0): omega2Est = 180.0 + math.atan(tanOmega2)*(180.0/math.pi) if (eCosOmega2/math.fabs(eCosOmega2) == 1.0) and (eSinOmega2/math.fabs(eSinOmega2) == -1.0): omega2Est = 360.0 - math.atan(tanOmega2)*(180.0/math.pi) omega1Est = omega2Est - 180.0 ## tauEst zDot = KEst*(1.0 + eccentricityEst)*(eCosOmega2/eccentricityEst) zDotLC = dzdtLC.copy() for i in xrange(zDotLC.numCadences): zDotLC.y[i] = zDotLC.y[i] - zDot zDotSpline = UnivariateSpline(zDotLC.t[np.where(zDotLC.mask == 1.0)], zDotLC.y[np.where(zDotLC.mask == 1.0)], 1.0/zDotLC.yerr[np.where(zDotLC.mask == 1.0)], k = 3, s = 2*zDotLC.numCadences, check_finite = True) for i in xrange(zDotLC.numCadences): zDotLC.x[i] = zDotSpline(zDotLC.t[i]) zDotZeros = zDotSpline.roots() zDotFoldedLC = dzdtLC.fold(periodEst) zDotFoldedSpline = UnivariateSpline(zDotFoldedLC.t[np.where(zDotFoldedLC.mask == 1.0)], zDotFoldedLC.y[np.where(zDotFoldedLC.mask == 1.0)], 1.0/zDotFoldedLC.yerr[np.where(zDotFoldedLC.mask == 1.0)], k = 3, s = 2*zDotFoldedLC.numCadences, check_finite = True) for i in xrange(zDotFoldedLC.numCadences): zDotFoldedLC.x[i] = zDotFoldedSpline(zDotFoldedLC.t[i]) tC = zDotFoldedLC.t[np.where(np.max(zDotFoldedLC.x) == zDotFoldedLC.x)[0][0]] nuC = (360.0 - omega2Est)%360.0 tE = zDotFoldedLC.t[np.where(np.min(zDotFoldedLC.x) == zDotFoldedLC.x)[0][0]] nuE = (180.0 - omega2Est)%360.0 if math.fabs(360.0 - nuC) < math.fabs(360 - nuE): tauEst = zDotZeros[np.where(zDotZeros > tC)[0][0]] else: tauEst = zDotZeros[np.where(zDotZeros > tE)[0][0]] ## a2sinInclinationEst a2sinInclinationEst = ((KEst*periodEst*self.Day*self.c*math.sqrt(1.0 - math.pow(eccentricityEst, 2.0)))/self.twoPi)/self.Parsec return intrinsicFluxEst, periodEst, eccentricityEst, omega1Est, tauEst, a2sinInclinationEst
def writeFilterBoundaries(threshold=0.6, toplot=True, survey='sdss'): """ PURPOSE: write file filterboundary.txt to record filter boundary defined by threshold*100% of maximum throughput PARAMETERS: threshold=0.6: (float) toplot=True: (bool) survey='sdss': (string) one of the following: sdss, hsc, ukirt Return --------- None Output ---------- filterboundary.txt """ # fileout print("[filtertools] running writeFilterBoundaries()") localpath = getlocalpath() if np.log10(threshold) > -1: fileout = localpath+survey+'/'+get_fn_FilterBoundaries(threshold) else: fileout = localpath+survey+'/'+get_fn_FilterBoundaries(threshold) bands = surveybands[survey] tabout = at.Table([[], [], [], ], names=('band', 'w1', 'w2'), dtype=('S1', 'i4', 'i4')) for band in bands: # readin filter function spec, ws = getFilterResponseFunc(band=band, survey=survey) x = ws y = spec/max(spec) - threshold spl = UnivariateSpline(x, y, s=0) roots = spl.roots() # solve for root f = interp1d(ws, spec/max(spec), kind='linear', bounds_error=False, fill_value=0.) tosolve = lambda x: f(x)-threshold x1 = fsolve(tosolve, x0=roots[0]) x2 = fsolve(tosolve, x0=roots[-1]) tabout.add_row([band, x1, x2]) if toplot: plt.clf() fig = plt.figure() ax = fig.add_subplot(111) ax.plot(ws, spec/max(spec), color='black') ax.axhline(threshold) ax.axvline(x1) ax.axvline(x2) ax.set_xlim(min(ws) ,max(ws)) # raw_input("Enter...") fig.savefig(band+'_'+'%.1f'%threshold+'.pdf') tabout.write(fileout, format='ascii.fixed_width', delimiter='')
def get_peaks(v, winsize, delta): winlen = int(winsize) maxindex = len(v) - 1 peakvalues, valleyvalues = peakdetect(np.array(v), delta = delta, lookahead = winlen / 4.0) peakindexes = [value[0] for value in peakvalues] valleyindexes = np.array([value[0] for value in valleyvalues]) peaks = [] for i, peakindex in enumerate(peakindexes): # prepare data for peak fitting leftboundary = _peak_boundary(i, peakindexes, valleyindexes, "left", v) rightboundary = _peak_boundary(i, peakindexes, valleyindexes, "right", v) halfheight = v[peakindex] / 2.0 peakdata = v[leftboundary:rightboundary] peakmax = np.max(peakdata) peakmean = np.mean(peakdata) # UnivariateSpline(k = 3), peakdata must have 4 site if len(peakdata) < 4: peaks += [[peakindex, leftboundary, rightboundary, peakmax, peakmean, "PEAK"]] continue peakdata = [x - halfheight for x in peakdata] indexes = range(leftboundary, rightboundary) ## find FWHM spline = UnivariateSpline(indexes, peakdata, s = 0) root = spline.roots() rootcount = len(root) if(rootcount == 0): r1 = (leftboundary + peakindex) / 2.0 r2 = (peakindex + rightboundary) / 2.0 elif(rootcount == 1): r = root[0] if( r < peakindex): r1 = r r2 = (peakindex + rightboundary) / 2.0 else: r1 = (leftboundary + peakindex) / 2.0 r2 = r else: distanceleft = [peakindex - r for r in root if r < peakindex] distanceright = [r - peakindex for r in root if r > peakindex] if(len(distanceleft) == 0): r1 = (leftboundary + peakindex) / 2.0 else: r1 = peakindex - min(distanceleft) if(len(distanceright) == 0): r2 = (peakindex + rightboundary) / 2.0 else: r2 = peakindex + min(distanceright) rangestart = int(r1) if r1 > 0 else 0 rangeend = int(r2) if r2 < maxindex else maxindex peakmax = v[peakindex] peakmean = np.mean(v[rangestart:(rangeend + 1)]) peaks += [[peakindex, rangestart, rangeend, peakmax, peakmean, "PEAK"]] return peaks
def process(self, recipe, band, obsids, frametypes): igr_path = self.igr_path igr_storage = self.igr_storage if recipe == "A0V_AB": DO_STD = True #FIX_TELLURIC=False elif recipe == "STELLAR_AB": DO_STD = False #FIX_TELLURIC=True elif recipe == "EXTENDED_AB": DO_STD = False #FIX_TELLURIC=True elif recipe == "EXTENDED_ONOFF": DO_STD = False #FIX_TELLURIC=True if 1: obj_filenames = igr_path.get_filenames(band, obsids) master_obsid = obsids[0] tgt_basename = os.path.splitext(os.path.basename(obj_filenames[0]))[0] db = {} basenames = {} db_types = ["flat_off", "flat_on", "thar", "sky"] for db_type in db_types: db_name = igr_path.get_section_filename_base("PRIMARY_CALIB_PATH", "%s.db" % db_type, ) db[db_type] = ProductDB(db_name) # db on output path db_types = ["a0v"] for db_type in db_types: db_name = igr_path.get_section_filename_base("OUTDATA_PATH", "%s.db" % db_type, ) db[db_type] = ProductDB(db_name) # to get basenames db_types = ["flat_off", "flat_on", "thar", "sky"] # if FIX_TELLURIC: # db_types.append("a0v") for db_type in db_types: basenames[db_type] = db[db_type].query(band, master_obsid) if 1: # make aperture from libs.storage_descriptions import SKY_WVLSOL_JSON_DESC sky_basename = db["sky"].query(band, master_obsid) wvlsol_products = igr_storage.load([SKY_WVLSOL_JSON_DESC], sky_basename)[SKY_WVLSOL_JSON_DESC] orders_w_solutions = wvlsol_products["orders"] wvl_solutions = map(np.array, wvlsol_products["wvl_sol"]) from libs.storage_descriptions import ONED_SPEC_JSON_DESC raw_spec_products = igr_storage.load([ONED_SPEC_JSON_DESC], sky_basename) from recipe_wvlsol_sky import load_aperture2 ap = load_aperture2(igr_storage, band, master_obsid, db["flat_on"], raw_spec_products[ONED_SPEC_JSON_DESC]["orders"], orders_w_solutions) # This should be saved somewhere and loaded, instead of making it every time. order_map = ap.make_order_map() slitpos_map = ap.make_slitpos_map() order_map2 = ap.make_order_map(mask_top_bottom=True) if 1: from libs.storage_descriptions import (HOTPIX_MASK_DESC, DEADPIX_MASK_DESC, ORDER_FLAT_IM_DESC, ORDER_FLAT_JSON_DESC, FLAT_MASK_DESC) hotpix_mask = igr_storage.load([HOTPIX_MASK_DESC], basenames["flat_off"])[HOTPIX_MASK_DESC] deadpix_mask = igr_storage.load([DEADPIX_MASK_DESC], basenames["flat_on"])[DEADPIX_MASK_DESC] pix_mask = hotpix_mask.data | deadpix_mask.data # aperture_solution_products = PipelineProducts.load(aperture_solutions_name) orderflat_ = igr_storage.load([ORDER_FLAT_IM_DESC], basenames["flat_on"])[ORDER_FLAT_IM_DESC] orderflat = orderflat_.data orderflat[pix_mask] = np.nan orderflat_json = igr_storage.load([ORDER_FLAT_JSON_DESC], basenames["flat_on"])[ORDER_FLAT_JSON_DESC] order_flat_meanspec = np.array(orderflat_json["mean_order_specs"]) # flat_normed = igr_storage.load([FLAT_NORMED_DESC], # basenames["flat_on"])[FLAT_NORMED_DESC] flat_mask = igr_storage.load([FLAT_MASK_DESC], basenames["flat_on"])[FLAT_MASK_DESC] bias_mask = flat_mask.data & (order_map2 > 0) SLITOFFSET_FITS_DESC = ("PRIMARY_CALIB_PATH", "SKY_", ".slitoffset_map.fits") prod_ = igr_storage.load([SLITOFFSET_FITS_DESC], basenames["sky"])[SLITOFFSET_FITS_DESC] #fn = sky_path.get_secondary_path("slitoffset_map.fits") slitoffset_map = prod_.data if 1: abba_names = obj_filenames def filter_abba_names(abba_names, frametypes, frametype): return [an for an, ft in zip(abba_names, frametypes) if ft == frametype] a_name_list = filter_abba_names(abba_names, frametypes, "A") b_name_list = filter_abba_names(abba_names, frametypes, "B") if recipe in ["A0V_AB", "STELLAR_AB"]: IF_POINT_SOURCE = True elif recipe in ["EXTENDED_AB", "EXTENDED_ONOFF"]: IF_POINT_SOURCE = False else: print "Unknown recipe : %s" % recipe if 1: #ab_names = ab_names_list[0] # master_hdu = pyfits.open(a_name_list[0])[0] a_list = [pyfits.open(name)[0].data \ for name in a_name_list] b_list = [pyfits.open(name)[0].data \ for name in b_name_list] # we may need to detrip # first define extract profile (gaussian). # dx = 100 if IF_POINT_SOURCE: # if point source # for point sources, variance estimation becomes wrong # if lenth of two is different, assert len(a_list) == len(b_list) # a_b != 1 for the cases when len(a) != len(b) a_b = float(len(a_list)) / len(b_list) a_data = np.sum(a_list, axis=0) b_data = np.sum(b_list, axis=0) data_minus = a_data - a_b*b_data #data_minus0 = data_minus from libs.destriper import destriper if 1: data_minus = destriper.get_destriped(data_minus, ~np.isfinite(data_minus), pattern=64) data_minus_flattened = data_minus / orderflat data_minus_flattened[~flat_mask.data] = np.nan #data_minus_flattened[order_flat_meanspec<0.1*order_flat_meanspec.max()] = np.nan # for variance, we need a square of a_b data_plus = (a_data + (a_b**2)*b_data) import scipy.ndimage as ni bias_mask2 = ni.binary_dilation(bias_mask) from libs import instrument_parameters gain = instrument_parameters.gain[band] # random noise variance0 = data_minus variance_ = variance0.copy() variance_[bias_mask2] = np.nan variance_[pix_mask] = np.nan mm = np.ma.array(variance0, mask=~np.isfinite(variance0)) ss = np.ma.median(mm, axis=0) variance_ = variance_ - ss # iterate over fixed number of times. # need to be improved. for i in range(5): st = np.nanstd(variance_, axis=0) variance_[np.abs(variance_) > 3*st] = np.nan #st = np.nanstd(variance_, axis=0) variance = destriper.get_destriped(variance0, ~np.isfinite(variance_), pattern=64) variance_ = variance.copy() variance_[bias_mask2] = np.nan variance_[pix_mask] = np.nan st = np.nanstd(variance_) st = np.nanstd(variance_[np.abs(variance_) < 3*st]) variance_[np.abs(variance_-ss) > 3*st] = np.nan x_std = ni.median_filter(np.nanstd(variance_, axis=0), 11) variance_map0 = np.zeros_like(variance) + x_std**2 variance_map = variance_map0 + np.abs(data_plus)/gain # add poison noise in ADU # we ignore effect of flattening # now estimate lsf # estimate lsf ordermap_bpixed = order_map.copy() ordermap_bpixed[pix_mask] = 0 ordermap_bpixed[~np.isfinite(orderflat)] = 0 # if IF_POINT_SOURCE: # if point source x1, x2 = 800, 1200 bins, lsf_list = ap.extract_lsf(ordermap_bpixed, slitpos_map, data_minus_flattened, x1, x2, bins=None) hh0 = np.sum(lsf_list, axis=0) peak1, peak2 = max(hh0), -min(hh0) lsf_x = 0.5*(bins[1:]+bins[:-1]) lsf_y = hh0/(peak1+peak2) from scipy.interpolate import UnivariateSpline lsf_ = UnivariateSpline(lsf_x, lsf_y, k=3, s=0, bbox=[0, 1]) roots = list(lsf_.roots()) #assert(len(roots) == 1) integ_list = [] from itertools import izip, cycle for ss, int_r1, int_r2 in izip(cycle([1, -1]), [0] + roots, roots + [1]): #print ss, int_r1, int_r2 integ_list.append(lsf_.integral(int_r1, int_r2)) integ = np.abs(np.sum(integ_list)) def lsf(o, x, slitpos): return lsf_(slitpos) / integ # make weight map profile_map = ap.make_profile_map(order_map, slitpos_map, lsf) # extract spec s_list, v_list = ap.extract_stellar(ordermap_bpixed, profile_map, variance_map, data_minus_flattened, slitoffset_map=slitoffset_map) # make synth_spec : profile * spectra synth_map = ap.make_synth_map(order_map, slitpos_map, profile_map, s_list, slitoffset_map=slitoffset_map) sig_map = (data_minus_flattened - synth_map)**2/variance_map ## mark sig_map > 100 as cosmicay. The threshold need to be fixed. # reextract with new variance map and CR is rejected variance_map_r = variance_map0 + np.abs(synth_map)/gain variance_map2 = np.max([variance_map, variance_map_r], axis=0) variance_map2[np.abs(sig_map) > 100] = np.nan # extract spec s_list, v_list = ap.extract_stellar(ordermap_bpixed, profile_map, variance_map2, data_minus_flattened, slitoffset_map=slitoffset_map) else: # if extended source from scipy.interpolate import UnivariateSpline if recipe in ["EXTENDED_AB", "EXTENDED_ABBA"]: delta = 0.01 lsf_ = UnivariateSpline([0, 0.5-delta, 0.5+delta, 1], [1., 1., -1., -1.], k=1, s=0, bbox=[0, 1]) else: lsf_ = UnivariateSpline([0, 1], [1., 1.], k=1, s=0, bbox=[0, 1]) def lsf(o, x, slitpos): return lsf_(slitpos) profile_map = ap.make_profile_map(order_map, slitpos_map, lsf) # we need to update the variance map by rejecting # cosmicray sources, but it is not clear how we do this # for extended source. variance_map2 = variance_map s_list, v_list = ap.extract_stellar(ordermap_bpixed, profile_map, variance_map2, data_minus_flattened, slitoffset_map=slitoffset_map ) if 1: # calculate S/N per resolution sn_list = [] for wvl, s, v in zip(wvl_solutions, s_list, v_list): dw = np.gradient(wvl) pixel_per_res_element = (wvl/40000.)/dw #print pixel_per_res_element[1024] # len(pixel_per_res_element) = 2047. But we ignore it. sn = (s/v**.5)*(pixel_per_res_element**.5) sn_list.append(sn) if 1: # save the product from libs.storage_descriptions import (COMBINED_IMAGE_DESC, VARIANCE_MAP_DESC) from libs.products import PipelineImage r = PipelineProducts("1d specs") r.add(COMBINED_IMAGE_DESC, PipelineImage([], data_minus_flattened)) r.add(VARIANCE_MAP_DESC, PipelineImage([], variance_map2)) # r.add(VARIANCE_MAP_DESC, PipelineImage([], # variance_map.data)) igr_storage.store(r, mastername=obj_filenames[0], masterhdu=None) if 1: # save spectra, variance, sn from libs.storage_descriptions import SKY_WVLSOL_FITS_DESC fn = igr_storage.get_path(SKY_WVLSOL_FITS_DESC, basenames["sky"]) # fn = sky_path.get_secondary_path("wvlsol_v1.fits") f = pyfits.open(fn) d = np.array(s_list) f[0].data = d.astype("f32") from libs.storage_descriptions import (SPEC_FITS_DESC, VARIANCE_FITS_DESC, SN_FITS_DESC) fout = igr_storage.get_path(SPEC_FITS_DESC, tgt_basename) f.writeto(fout, clobber=True) d = np.array(v_list) f[0].data = d.astype("f32") fout = igr_storage.get_path(VARIANCE_FITS_DESC, tgt_basename) f.writeto(fout, clobber=True) d = np.array(sn_list) f[0].data = d.astype("f32") fout = igr_storage.get_path(SN_FITS_DESC, tgt_basename) f.writeto(fout, clobber=True) if 1: # from libs.storage_descriptions import ORDER_FLAT_JSON_DESC prod = igr_storage.load([ORDER_FLAT_JSON_DESC], basenames["flat_on"])[ORDER_FLAT_JSON_DESC] new_orders = prod["orders"] # fitted_response = orderflat_products["fitted_responses"] i1i2_list = prod["i1i2_list"] order_indices = [] for o in ap.orders: o_new_ind = np.searchsorted(new_orders, o) order_indices.append(o_new_ind) if DO_STD: # a quick and dirty flattening for A0V stars from libs.master_calib import get_master_calib_abspath fn = get_master_calib_abspath("A0V/vegallpr25.50000resam5") d = np.genfromtxt(fn) wvl_a0v, flux_a0v, cont_a0v = (d[:,i] for i in [0, 1, 2]) wvl_a0v = wvl_a0v/1000. wvl_limits = [] for wvl_ in wvl_solutions: wvl_limits.extend([wvl_[0], wvl_[-1]]) dwvl = abs(wvl_[0] - wvl_[-1])*0.1 # padding mask_wvl1 = min(wvl_limits) - dwvl mask_wvl2 = max(wvl_limits) + dwvl #print mask_wvl1, mask_wvl2 # if band == "H": # mask_wvl1, mask_wvl2 = 1.450, 1.850 # else: # mask_wvl1, mask_wvl2 = 1.850, 2.550 mask_igr = (mask_wvl1 < wvl_a0v) & (wvl_a0v < mask_wvl2) fn = get_master_calib_abspath("telluric/LBL_A15_s0_w050_R0060000_T.fits") telluric = pyfits.open(fn)[1].data telluric_lam = telluric["lam"] tel_mask_igr = (mask_wvl1 < telluric_lam) & (telluric_lam < mask_wvl2) #plot(telluric_lam[tel_mask_H], telluric["trans"][tel_mask_H]) from scipy.interpolate import interp1d, UnivariateSpline # spl = UnivariateSpline(telluric_lam[tel_mask_igr], # telluric["trans"][tel_mask_igr], # k=1,s=0) spl = interp1d(telluric_lam[tel_mask_igr], telluric["trans"][tel_mask_igr], bounds_error=False ) trans = spl(wvl_a0v[mask_igr]) # ax1.plot(wvl_a0v[mask_igr], flux[mask_igr]/cont[mask_igr]*trans, # color="0.5", zorder=0.5) trans_m = ni.maximum_filter(trans, 128) trans_mg = ni.gaussian_filter(trans_m, 32) zzz0 = (flux_a0v/cont_a0v)[mask_igr] zzz = zzz0*trans mmm = trans/trans_mg > 0.95 zzz[~mmm] = np.nan wvl_zzz = wvl_a0v[mask_igr] #ax2.plot(, zzz) # #ax2 = subplot(212) # if DO_STD: # telluric_cor = [] a0v_flattened = [] for o_index, wvl, s in zip(order_indices, wvl_solutions, s_list): i1, i2 = i1i2_list[o_index] #sl = slice(i1, i2) wvl1, wvl2 = wvl[i1], wvl[i2] #wvl1, wvl2 = wvl[0], wvl[-1] z_m = (wvl1 < wvl_zzz) & (wvl_zzz < wvl2) wvl1, wvl2 = min(wvl), max(wvl) z_m2 = (wvl1 < wvl_zzz) & (wvl_zzz < wvl2) #z_m = z_m2 ss = interp1d(wvl, s) s_interped = ss(wvl_zzz[z_m]) xxx, yyy = wvl_zzz[z_m], s_interped/zzz[z_m] from astropy.modeling import models, fitting p_init = models.Chebyshev1D(domain=[xxx[0], xxx[-1]], degree=6) fit_p = fitting.LinearLSQFitter() x_m = np.isfinite(yyy) p = fit_p(p_init, xxx[x_m], yyy[x_m]) #ax2.plot(xxx, yyy) #ax2.plot(xxx, p(xxx)) res_ = p(wvl) z_interp = interp1d(wvl_zzz[z_m], zzz0[z_m], bounds_error=False) A0V = z_interp(wvl) #res_[res_<0.3*res_.max()] = np.nan s_f = (s/res_)/A0V s_f[:i1] = np.nan s_f[i2:] = np.nan a0v_flattened.append(s_f) d = np.array(a0v_flattened) #d[~np.isfinite(d)] = 0. f[0].data = d.astype("f32") from libs.storage_descriptions import SPEC_FITS_FLATTENED_DESC fout = igr_storage.get_path(SPEC_FITS_FLATTENED_DESC, tgt_basename) f.writeto(fout, clobber=True) db["a0v"].update(band, tgt_basename)
def estimate(self, observedLC): """! Estimate intrinsicFlux, period, eccentricity, omega, tau, & a2sini """ # fluxEst if observedLC.numCadences > 50: model = gatspy.periodic.LombScargleFast(optimizer_kwds={"quiet": True}).fit(observedLC.t, observedLC.y, observedLC.yerr) else: model = gatspy.periodic.LombScargle(optimizer_kwds={"quiet": True}).fit(observedLC.t, observedLC.y, observedLC.yerr) periods, power = model.periodogram_auto(nyquist_factor=observedLC.numCadences) model.optimizer.period_range = ( 2.0*np.mean(observedLC.t[1:] - observedLC.t[:-1]), observedLC.T) periodEst = model.best_period numIntrinsicFlux = 100 lowestFlux = np.min(observedLC.y[np.where(observedLC.mask == 1.0)]) highestFlux = np.max(observedLC.y[np.where(observedLC.mask == 1.0)]) intrinsicFlux = np.linspace(np.min(observedLC.y[np.where(observedLC.mask == 1.0)]), np.max( observedLC.y[np.where(observedLC.mask == 1.0)]), num=numIntrinsicFlux) intrinsicFluxList = list() totalIntegralList = list() for f in xrange(1, numIntrinsicFlux - 1): beamedLC = observedLC.copy() beamedLC.x = np.require(np.zeros(beamedLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) for i in xrange(beamedLC.numCadences): beamedLC.y[i] = observedLC.y[i]/intrinsicFlux[f] beamedLC.yerr[i] = observedLC.yerr[i]/intrinsicFlux[f] dopplerLC = beamedLC.copy() dopplerLC.x = np.require(np.zeros(dopplerLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) for i in xrange(observedLC.numCadences): dopplerLC.y[i] = math.pow(beamedLC.y[i], 1.0/3.44) dopplerLC.yerr[i] = (1.0/3.44)*math.fabs(dopplerLC.y[i]*(beamedLC.yerr[i]/beamedLC.y[i])) dzdtLC = dopplerLC.copy() dzdtLC.x = np.require(np.zeros(dopplerLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) for i in xrange(observedLC.numCadences): dzdtLC.y[i] = 1.0 - (1.0/dopplerLC.y[i]) dzdtLC.yerr[i] = math.fabs((-1.0*dopplerLC.yerr[i])/math.pow(dopplerLC.y[i], 2.0)) foldedLC = dzdtLC.fold(periodEst) foldedLC.x = np.require(np.zeros(foldedLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) integralSpline = UnivariateSpline( foldedLC.t[np.where(foldedLC.mask == 1.0)], foldedLC.y[np.where(foldedLC.mask == 1.0)], 1.0/foldedLC.yerr[np.where(foldedLC.mask == 1.0)], k=3, s=None, check_finite=True) totalIntegral = math.fabs(integralSpline.integral(foldedLC.t[0], foldedLC.t[-1])) intrinsicFluxList.append(intrinsicFlux[f]) totalIntegralList.append(totalIntegral) fluxEst = intrinsicFluxList[ np.where(np.array(totalIntegralList) == np.min(np.array(totalIntegralList)))[0][0]] # periodEst for i in xrange(beamedLC.numCadences): beamedLC.y[i] = observedLC.y[i]/fluxEst beamedLC.yerr[i] = observedLC.yerr[i]/fluxEst dopplerLC.y[i] = math.pow(beamedLC.y[i], 1.0/3.44) dopplerLC.yerr[i] = (1.0/3.44)*math.fabs(dopplerLC.y[i]*(beamedLC.yerr[i]/beamedLC.y[i])) dzdtLC.y[i] = 1.0 - (1.0/dopplerLC.y[i]) dzdtLC.yerr[i] = math.fabs((-1.0*dopplerLC.yerr[i])/math.pow(dopplerLC.y[i], 2.0)) if observedLC.numCadences > 50: model = gatspy.periodic.LombScargleFast(optimizer_kwds={"quiet": True}).fit(dzdtLC.t, dzdtLC.y, dzdtLC.yerr) else: model = gatspy.periodic.LombScargle(optimizer_kwds={"quiet": True}).fit(dzdtLC.t, dzdtLC.y, dzdtLC.yerr) periods, power = model.periodogram_auto(nyquist_factor=dzdtLC.numCadences) model.optimizer.period_range = (2.0*np.mean(dzdtLC.t[1:] - dzdtLC.t[:-1]), dzdtLC.T) periodEst = model.best_period # eccentricityEst & omega2Est # First find a full period going from rising to falling. risingSpline = UnivariateSpline( dzdtLC.t[np.where(dzdtLC.mask == 1.0)], dzdtLC.y[np.where(dzdtLC.mask == 1.0)], 1.0/dzdtLC.yerr[np.where(dzdtLC.mask == 1.0)], k=3, s=None, check_finite=True) risingSplineRoots = risingSpline.roots() firstRoot = risingSplineRoots[0] if risingSpline.derivatives(risingSplineRoots[0])[1] > 0.0: tRising = risingSplineRoots[0] else: tRising = risingSplineRoots[1] # Now fold the LC starting at tRising and going for a full period. foldedLC = dzdtLC.fold(periodEst, tStart=tRising) foldedLC.x = np.require(np.zeros(foldedLC.numCadences), requirements=['F', 'A', 'W', 'O', 'E']) # Fit the folded LC with a spline to figure out alpha and beta fitLC = foldedLC.copy() foldedSpline = UnivariateSpline( foldedLC.t[np.where(foldedLC.mask == 1.0)], foldedLC.y[np.where(foldedLC.mask == 1.0)], 1.0/foldedLC.yerr[np.where(foldedLC.mask == 1.0)], k=3, s=2*foldedLC.numCadences, check_finite=True) for i in xrange(fitLC.numCadences): fitLC.x[i] = foldedSpline(fitLC.t[i]) # Now get the roots and find the falling root tZeros = foldedSpline.roots() # Find tRising, tFalling, tFull, startIndex, & stopIndex via DBSCAN ####################### # Find the number of clusters '''dbsObj = DBSCAN(eps = periodEst/10.0, min_samples = 1) db = dbsObj.fit(tZeros.reshape(-1,1)) core_samples_mask = np.zeros_like(db.labels_, dtype=bool) core_samples_mask[db.core_sample_indices_] = True labels = db.labels_ unique_labels = set(labels) n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)''' # Find tRising, tFalling, tFull, startIndex, & stopIndex if tZeros.shape[0] == 1: # We have found just tFalling tFalling = tZeros[0] tRising = fitLC.t[0] startIndex = 0 tFull = fitLC.t[-1] stopIndex = fitLC.numCadences elif tZeros.shape[0] == 2: # We have found tFalling and one of tRising or tFull if foldedSpline.derivatives(tZeros[0])[1] < 0.0: tFalling = tZeros[0] tFull = tZeros[1] stopIndex = np.where(fitLC.t < tFull)[0][-1] tRising = fitLC.t[0] startIndex = 0 elif foldedSpline.derivatives(tZeros[0])[1] > 0.0: if foldedSpline.derivatives(tZeros[1])[1] < 0.0: tRising = tZeros[0] startIndex = np.where(fitLC.t > tRising)[0][0] tFalling = tZeros[1] tFull = fitLC.t[-1] stopIndex = fitLC.numCadences else: raise RuntimeError( 'Could not determine alpha & omega correctly because the first root is rising but \ the second root is not falling!') elif tZeros.shape[0] == 3: tRising = tZeros[0] startIndex = np.where(fitLC.t > tRising)[0][0] tFalling = tZeros[1] tFull = tZeros[2] stopIndex = np.where(fitLC.t < tFull)[0][-1] else: # More than 3 roots!!! Use K-Means to cluster the roots assuming we have 3 groups root_groups = KMeans(n_clusters=3).fit_predict(tZeros.reshape(-1, 1)) RisingGroupNumber = root_groups[0] FullGroupNumber = root_groups[-1] RisingSet = set(root_groups[np.where(root_groups != RisingGroupNumber)[0]]) FullSet = set(root_groups[np.where(root_groups != FullGroupNumber)[0]]) FallingSet = RisingSet.intersection(FullSet) FallingGroupNumber = FallingSet.pop() numRisingRoots = np.where(root_groups == RisingGroupNumber)[0].shape[0] numFallingRoots = np.where(root_groups == FallingGroupNumber)[0].shape[0] numFullRoots = np.where(root_groups == FullGroupNumber)[0].shape[0] if numRisingRoots == 1: tRising = tZeros[np.where(root_groups == RisingGroupNumber)[0]][0] else: RisingRootCands = tZeros[np.where(root_groups == RisingGroupNumber)[0]] for i in xrange(RisingRootCands.shape[0]): if foldedSpline.derivatives(RisingRootCands[i])[1] > 0.0: tRising = RisingRootCands[i] break if numFallingRoots == 1: tFalling = tZeros[np.where(root_groups == FallingGroupNumber)[0]][0] else: FallingRootCands = tZeros[np.where(root_groups == FallingGroupNumber)[0]] for i in xrange(FallingRootCands.shape[0]): if foldedSpline.derivatives(FallingRootCands[i])[1] < 0.0: tFalling = FallingRootCands[i] break if numFullRoots == 1: tFull = tZeros[np.where(root_groups == FullGroupNumber)[0]][0] else: FullRootCands = tZeros[np.where(root_groups == FullGroupNumber)[0]] for i in xrange(FullRootCands.shape[0]): if foldedSpline.derivatives(FullRootCands[i])[1] > 0.0: tFull = FullRootCands[i] break startIndex = np.where(fitLC.t > tRising)[0][0] stopIndex = np.where(fitLC.t < tFull)[0][-1] # # One full period now goes from tRising to periodEst. The maxima occurs between tRising and tFalling # while the minima occurs between tFalling and tRising + periodEst. Find the minima and maxima alpha = math.fabs(fitLC.x[np.where(np.max(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]]) beta = math.fabs(fitLC.x[np.where(np.min(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]]) peakLoc = fitLC.t[np.where(np.max(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]] troughLoc = fitLC.t[np.where(np.min(fitLC.x[startIndex:stopIndex]) == fitLC.x)[0][0]] KEst = 0.5*(alpha + beta) delta2 = (math.fabs(foldedSpline.integral(tRising, peakLoc)) + math.fabs( foldedSpline.integral(troughLoc, tFull)))/2.0 delta1 = (math.fabs(foldedSpline.integral(peakLoc, tFalling)) + math.fabs( foldedSpline.integral(tFalling, troughLoc)))/2.0 eCosOmega2 = (alpha - beta)/(alpha + beta) eSinOmega2 = ((2.0*math.sqrt(alpha*beta))/(alpha + beta))*((delta2 - delta1)/(delta2 + delta1)) eccentricityEst = math.sqrt(math.pow(eCosOmega2, 2.0) + math.pow(eSinOmega2, 2.0)) tanOmega2 = math.fabs(eSinOmega2/eCosOmega2) if (eCosOmega2/math.fabs(eCosOmega2) == 1.0) and (eSinOmega2/math.fabs(eSinOmega2) == 1.0): omega2Est = math.atan(tanOmega2)*(180.0/math.pi) if (eCosOmega2/math.fabs(eCosOmega2) == -1.0) and (eSinOmega2/math.fabs(eSinOmega2) == 1.0): omega2Est = 180.0 - math.atan(tanOmega2)*(180.0/math.pi) if (eCosOmega2/math.fabs(eCosOmega2) == -1.0) and (eSinOmega2/math.fabs(eSinOmega2) == -1.0): omega2Est = 180.0 + math.atan(tanOmega2)*(180.0/math.pi) if (eCosOmega2/math.fabs(eCosOmega2) == 1.0) and (eSinOmega2/math.fabs(eSinOmega2) == -1.0): omega2Est = 360.0 - math.atan(tanOmega2)*(180.0/math.pi) if omega2Est >= 180.0: omega1Est = omega2Est - 180.0 if omega2Est < 180.0: omega1Est = omega2Est + 180.0 # tauEst zDot = KEst*(1.0 + eccentricityEst)*(eCosOmega2/eccentricityEst) zDotLC = dzdtLC.copy() for i in xrange(zDotLC.numCadences): zDotLC.y[i] = zDotLC.y[i] - zDot zDotSpline = UnivariateSpline( zDotLC.t[np.where(zDotLC.mask == 1.0)], zDotLC.y[np.where(zDotLC.mask == 1.0)], 1.0/zDotLC.yerr[np.where(zDotLC.mask == 1.0)], k=3, s=2*zDotLC.numCadences, check_finite=True) for i in xrange(zDotLC.numCadences): zDotLC.x[i] = zDotSpline(zDotLC.t[i]) zDotZeros = zDotSpline.roots() zDotFoldedLC = dzdtLC.fold(periodEst) zDotFoldedSpline = UnivariateSpline( zDotFoldedLC.t[np.where(zDotFoldedLC.mask == 1.0)], zDotFoldedLC.y[np.where(zDotFoldedLC.mask == 1.0)], 1.0/zDotFoldedLC.yerr[np.where(zDotFoldedLC.mask == 1.0)], k=3, s=2*zDotFoldedLC.numCadences, check_finite=True) for i in xrange(zDotFoldedLC.numCadences): zDotFoldedLC.x[i] = zDotFoldedSpline(zDotFoldedLC.t[i]) tC = zDotFoldedLC.t[np.where(np.max(zDotFoldedLC.x) == zDotFoldedLC.x)[0][0]] nuC = (360.0 - omega2Est)%360.0 tE = zDotFoldedLC.t[np.where(np.min(zDotFoldedLC.x) == zDotFoldedLC.x)[0][0]] nuE = (180.0 - omega2Est)%360.0 if math.fabs(360.0 - nuC) < math.fabs(360 - nuE): tauEst = zDotZeros[np.where(zDotZeros > tC)[0][0]] else: tauEst = zDotZeros[np.where(zDotZeros > tE)[0][0]] tauEst = tauEst%periodEst # a2sinInclinationEst a2sinInclinationEst = ((KEst*periodEst*self.Day*self.c*math.sqrt(1.0 - math.pow( eccentricityEst, 2.0)))/self.twoPi)/self.Parsec return fluxEst, periodEst, eccentricityEst, omega1Est, tauEst, a2sinInclinationEst
def find_FWHM(bins, hist): maximum = hist[np.argmax(hist)] peak = bins[np.argmax(hist)] spline = UnivariateSpline(bins[:-1], hist-maximum/2 , s=0) return peak, spline.roots()
def FWHM(self, bins, vals): spline = UnivariateSpline(bins[:-1]+np.diff(bins)/2., vals-np.max(vals)/2., s=0) roots = spline.roots() # find the roots r1, r2 = roots[0], roots[-1] return np.abs(r1-r2)
def find_spline_maxima(xi,yi,min_normpeak=0.05,min_area_k=0.05): #============================================================================== # description # extracts peaks from the gaussian_kse function, # such that peaks have a minimum normalized peak height and a minimum bound area # # inputs # xi,yi points corresponding to the gaussian_kde function of the data # min_normpeak minimum normalized peak of the gaussian_kde function # min_area_k proportional constant multiplied to the maximum bound area to compute the minimum bound area # # output # peaks[x,y] the peak locations [x] and heights [y] of the gaussian_kde function #============================================================================== #setting gaussian_kde points as spline s0=UnivariateSpline(xi,yi,s=0) try: #first derivative (for gettinge extrema) dy=s0(xi,1) s1=UnivariateSpline(xi,dy,s=0) #second derivative (for getting inflection points) dy2=s1(xi,1) s2=UnivariateSpline(xi,dy2,s=0) #solving for extrema, maxima, and inflection points extrema=s1.roots() maxima=np.sort(extrema[(s2(extrema)<0)]) inflection=np.sort(s2.roots()) try: #setting up dataframe for definite integrals with inflection points as bounds df_integ=pd.DataFrame() df_integ['lb']=inflection[:-1] df_integ['ub']=inflection[1:] #assigning maxima to specific ranges df_integ['maxloc']=np.nan for i in range(len(df_integ)): try: len((maxima>df_integ['lb'][i])*(maxima<df_integ['ub'][i]))>0 df_integ['maxloc'][i]=maxima[(maxima>df_integ['lb'][i])*(maxima<df_integ['ub'][i])] except: continue #filtering maxima based on peak height and area df_integ.dropna(inplace=True) df_integ['maxpeak']=s0(df_integ['maxloc']) df_integ=df_integ[df_integ['maxpeak']>0.001] df_integ['normpeak']=s0(df_integ['maxpeak'])/s0(df_integ['maxpeak'].values.max()) df_integ['area']=df_integ.apply(lambda x: s0.integral(x[0],x[1]), axis = 1) df_integ=df_integ[(df_integ['area']>min_area_k*df_integ['area'].values.max())*(df_integ['normpeak']>min_normpeak)] return df_integ['maxloc'],df_integ['maxpeak']#,inflection[df_integ.index],s0(inflection[df_integ.index]) except: #filtering maxima based on peak height only maxima=extrema[(s2(extrema)<0)*(s0(extrema)/s0(extrema).max()>min_normpeak)] return maxima,s0(maxima)#,inflection,s0(inflection) except: #unimodal kde return xi[np.argmax(yi)],yi.max()#,None,None
x=[] for i in range(1024): x.append(i) row=int(y[j]) x1=dat[row] x2=dat[row+1] x3=dat[row-1] vec=[] for i in range(1024): vec.append(x1+x2+x3) nvec=np.median(vec,axis=0) spline = UnivariateSpline(x, nvec-np.max(nvec)/2, s=0) if len(spline.roots()) == 2: r1, r2 = spline.roots() fwhm=r2-r1 elif len(spline.roots()) == 4: r1, r2, r3, r4 = spline.roots() fwhm=r3-r2 mfwhm.append(fwhm) for j in range(len(p)): mat=mfwhm val=mat[j] mat[j]=0 for h in range(len(mat)): mat[h]=abs(mat[h]-val)