def test_fit(self): # Test the method Class1.method1 # See http://docs.python.org/library/unittest.html#test-cases for further # information #print "run gaussian fit" #print gaussian fit, popt, perr = nonLinFit(gaussian, self.x_data, self.y_data, p_guess=self.p_guess, verbose=False) diff = max(fit) - (self.p[1]+self.p[0]) self.assertTrue(abs(diff) < 0.0001) for i in range(len(self.p)): self.assertAlmostEqual(self.p[i],popt[i]) #print "run gauss + polynomial fit" fitPoly, poptPoly, perr = nonLinFit(gaussPlusPoly, self.x_data, self.y_data_poly, p_guess=self.p_poly_guess, verbose=False) for i in range(len(self.p)): self.assertAlmostEqual(self.p_poly[i],poptPoly[i]) coeff = self.fitter.fit() self.assertTrue(coeff[0] == 1.) error = self.fitter.calcLinFitError(self.x_data) self.assertTrue(numpy.mean(error) == 0.) line = self.fitter.straightLine(self.x_data) self.assertTrue(numpy.all(line - self.x_data) == 0.) del coeff del error del fitPoly del popt del poptPoly del fit del line
def get_psf_fit(data, minX=0, leftY=0, verbose=False, makeplot=False): """ fits a pinhole (point source) continuum spectrum by a Gaussian for each row (x axis). :Parameters: data: MiriMeasuredModel (or similar 2-D DataModel) The 2-D data product from which spectra will be extracted. :Returns: * x values per row * fit function (vs x) per row * all Gaussian fit parameters per row * all errors of Gaussian fit parameters per row """ # Make sure the given data is a 2-D JWST data product. if isinstance(data, MiriMeasuredModel): if np.ndim(data.data) != 2: strg = "lrs_extract_spec - 2 dimensional data expected " strg += "(%d given)." % np.ndim(data.data) raise TypeError(strg) else: raise TypeError("lrs_extract_spec - " + \ "Given data product is not a MiriMeasuredModel") if np.ndim(data.err) != 2: raise TypeError("lrs_extract_spec - " + \ "Given data product does not contain any data!") sig = data.data sigErr = data.err all_x = [] all_p = [] all_fit = [] all_perr = [] for i in range(sig.shape[0]): si = sig[i, :] simax = np.max(si) stdevSi = np.std(si) if simax <= 0 or stdevSi == 0: if verbose: print("signal is below or equal zero in row ", i) continue if simax / stdevSi < 1. or simax < np.mean(sigErr): if verbose: print("signal too low in row ", i) continue maxind = np.where(si == simax)[0][0] p_guess = (0, simax, maxind, 2) try: fit, p, perr = nonLinFit(gaussian, np.arange(sig.shape[1]), si, y_sigma=sigErr[i, :], p_guess=p_guess, plotting=makeplot, verbose=verbose) p[2] = p[2] + leftY all_p.append(p) all_fit.append(fit) all_perr.append(perr) all_x.append(i + minX) except: print("fit ", i, " did not work") return all_x, all_fit, all_p, all_perr
def lrs_extract_spec_with_fit(data, minX=0, leftY=0, verbose=False, makeplot=False): """ Extracts spectra from the data by summing along the spatial-x axis considering NaNs. The row extension to sum over is determined by a Gaussian fit +- 3*FWHM :Parameters: data: MiriMeasuredModel (or similar 2-D DataModel) The 2-D data product from which spectra will be extracted. :Returns: Spectrum1d: dataproduct with * spec: 1d array The extracted spectrum * err: 1d array The propagated error :Raises: TypeError if wrong input type """ # Make sure the given data is a 2-D JWST data product. if isinstance(data, MiriMeasuredModel): if np.ndim(data.data) != 2: strg = "lrs_extract_spec - 2 dimensional data expected " strg += "(%d given)." % np.ndim(data.data) raise TypeError(strg) else: raise TypeError("lrs_extract_spec - " + \ "Given data product is not a MiriMeasuredModel") if np.ndim(data.err) != 2: raise TypeError("lrs_extract_spec - " + \ "Given data product does not contain any data!") sig = data.data sigErr = data.err col = [] xpixel = [] fwhm = [] for i in range(sig.shape[0]): si = sig[i, :] simax = np.max(si) stdevSi = np.std(si) if simax <= 0 or stdevSi == 0: continue if simax < 0.03 and simax / stdevSi < 1.: continue maxind = np.where(si == simax)[0][0] p_guess = (0, simax, maxind, 2) try: fit, p, perr = nonLinFit(gaussian, np.arange(sig.shape[1]), si, y_sigma=sigErr[i, :], p_guess=p_guess, plotting=False, verbose=verbose) col.append(p[2] + leftY) xpixel.append(i + minX) fwhm.append(p[3]) except: print("fit ", i, " did not work") col = np.asarray(col) xpixel = np.asarray(xpixel) fwhm = np.asarray(fwhm) if makeplot: mplt.plot_xy(xpixel, col, title="fit result position of peak") stdevCol = np.std(col) meanCol = np.mean(col) if verbose: print("mean column ", meanCol) print("stddev column ", stdevCol) colInd = np.where( np.logical_and(col < meanCol + _sigma_clip * stdevCol, col > meanCol - _sigma_clip * stdevCol))[0] newXpixel = xpixel[colInd] newCol = col[colInd] newFwhm = fwhm[colInd] coeff = np.polyfit(newXpixel, newCol, 1) line = coeff[0] * newXpixel + coeff[1] fwhmCoeff = np.polyfit(newXpixel, newFwhm, 1) lineFwhm = fwhmCoeff[0] * newXpixel + fwhmCoeff[1] if verbose: print("no of useful pixels ", len(newXpixel)) if makeplot: fig = pyplot.figure(facecolor="0.98") fit = fig.add_subplot(211) fit.plot(newXpixel, newCol, 'ro', np.sort(newXpixel), line) fit.set_title("fitted determined columns") fw = fig.add_subplot(212) fw.plot(newXpixel, lineFwhm) fw.set_title("FWHM") pyplot.show() #extract the spectra along col +- 3 * FHWM spec = np.ndarray(sig.shape[0]) err = np.ndarray(sig.shape[0]) for i in range(sig.shape[0]): column = coeff[0] * (i + minX) + coeff[1] - leftY fw = fwhmCoeff[0] * (i + minX) + fwhmCoeff[1] si = sig[i, int(column - 3. * fw):int(column + 3. * fw)] er = sigErr[i, int(column - 3. * fw):int(column + 3. * fw)] spec[i] = np.nansum(si) err[i] = np.sqrt(np.nansum(np.square(er))) if np.ndim(data.dq) > 1: dq = data.dq # Crunch the DQ array into 1-D by taking the maximum # qual = np.max(dq, 1) qual = dq.max(0) data.dq = qual else: qual = None data.data = spec data.err = err #spectrum = Spectrum1D(spec, error = err, quality = qual ) return data, newXpixel, line