def measure_flexure_y(fine, HDUlist, profwidth=5, plot=False, outname=None): dat = HDUlist[0].data exptime = HDUlist[0].header["EXPTIME"] profs = [] xx = np.arange(profwidth * 2) for ix in np.arange(500, 1200, 10): f = fine[ix] profile = np.zeros(profwidth * 2) # bad fit if not f.ok: continue # noisy fit if f.lamnrms > 1: continue # short spectrum if f.xrange[1] - f.xrange[0] < 200: continue yfun = np.poly1d(f.poly) for xpos in np.arange(f.xrange[0], f.xrange[1]): try: ypos = int(np.round(yfun(xpos))) except: continue try: profile += dat[ypos - profwidth : ypos + profwidth, xpos] except: continue profs.append(profile - np.min(profile)) if plot: pl.figure(1) ffun = FF.mpfit_residuals(FF.gaussian4) parinfo = [{"value": 1}, {"value": profwidth}, {"value": 2}, {"value": 0}, {"value": 0}] profposys = [] for prof in profs: if plot: pl.step(xx, prof) parinfo[0]["value"] = np.max(prof) fit = FF.mpfit_do(ffun, xx, prof, parinfo) if plot: pl.plot(xx, FF.gaussian4(fit.params, xx)) profposys.append(fit.params[1] - profwidth - 1) if plot: pl.show() profposys = np.array(profposys) mn = np.mean(profposys) sd = np.std(profposys) ok = np.abs(profposys - mn) / sd < 3 required_shift = np.mean(profposys[ok]) print "dY = %3.2f pixel shift" % required_shift return required_shift
def measure_flexure_y(fine, HDUlist, profwidth=5, plot=False, outname=None): dat = HDUlist[0].data exptime = HDUlist[0].header['EXPTIME'] profs = [] xx = np.arange(profwidth*2) for ix in np.arange(500, 1200, 10): f = fine[ix] profile = np.zeros(profwidth*2) if not f.ok: continue if f.lamrms > 1: continue if f.xrange[1] - f.xrange[0] < 200: continue yfun = np.poly1d(f.poly) for xpos in np.arange(f.xrange[0], f.xrange[1]): try: ypos = int(np.round(yfun(xpos))) except: continue try: profile += dat[ypos-profwidth:ypos+profwidth, xpos] except: continue profs.append(profile - np.min(profile)) if plot: pl.figure(1) ffun = FF.mpfit_residuals(FF.gaussian4) parinfo= [{'value': 1}, {'value': profwidth}, {'value': 2}, {'value': 0}, {'value': 0}] profposys = [] for prof in profs: if plot: pl.step(xx, prof) parinfo[0]['value'] = np.max(prof) fit = FF.mpfit_do(ffun, xx, prof, parinfo) if plot: pl.plot(xx, FF.gaussian4(fit.params, xx)) profposys.append(fit.params[1] - profwidth-1) if plot: pl.show() profposys = np.array(profposys) mn = np.mean(profposys) sd = np.std(profposys) ok = np.abs(profposys - mn)/sd < 3 required_shift = np.mean(profposys[ok]) print "dY = %3.2f pixel shift" % required_shift return required_shift
def measure_flexure_y(cube, hdulist, profwidth=5, plot=False): # get image to measure dat = hdulist[0].data # store profiles profs = [] # x values of profiles xx = np.arange(profwidth*2) # get a sample (70) of spaxels for ix in np.arange(500, 1200, 10): # get specific spaxel f = cube[ix] # set up profile vector for this spaxel profile = np.zeros(profwidth*2) # weed out baddies # bad fit if not f.ok: continue # noisy fit if f.lamnrms > 1: continue # short spectrum if f.xrange[1] - f.xrange[0] < 200: continue # get trace of spaxel on image in y yfun = np.poly1d(f.poly) # loop over x positions of this spaxel for xpos in np.arange(f.xrange[0], f.xrange[1]): # get the y position at the given xpos try: ypos = int(np.round(yfun(xpos))) except: continue # sum profile over all xpos try: profile += dat[ypos-profwidth:ypos+profwidth, xpos] except: continue # append profile after subtracting minimum profs.append(profile - np.min(profile)) if plot: pl.figure(1) # set up Gaussian fit to profiles ffun = NFit.mpfit_residuals(NFit.gaussian4) # initial guess parinfo = [{'value': 1}, {'value': profwidth}, {'value': 2}, {'value': 0}, {'value': 0}] # y positions of profiles profposys = [] profwidys = [] for prof in profs: # plot input profile if plot: pl.plot(xx, prof, 'ro') # update initial guess parinfo[0]['value'] = np.max(prof) # fit Gaussian fit = NFit.mpfit_do(ffun, xx, prof, parinfo) # overplot fit if plot: pl.plot(xx, NFit.gaussian4(fit.params, xx)) # x offset between nominal trace position (profwidth-1) and # Gaussian fit position (fit.params[1]) profposys.append(fit.params[1] - profwidth-1) profwidys.append(fit.params[2]) profposys = np.array(profposys) profwidys = np.array(profwidys) # get statistics mn = np.mean(profposys) sd = np.std(profposys) # clean 3 sigma outliers ok = np.abs(profposys - mn)/sd < 3 # final shift required_shift = np.mean(profposys[ok]) # now do width mn = np.mean(profwidys) sd = np.std(profwidys) # clean 3 sigma outliers ok = np.abs(profwidys - mn)/sd < 3 average_width = np.mean(profwidys[ok]) * 2.354 print "yFWHM = %5.2f pixels" % average_width print "dY = %3.2f pixel shift" % required_shift if plot: px = (profwidth+1) + required_shift pl.plot([px, px], [0, np.max(profs)], '--') pl.show() return required_shift, average_width
def measure_flexure_x(cube, hdulist, drow=0., skylines=(557.0, 589.0), lamstart=1000.0, lamratio=239./240., lamlen=250, extract_width=3, skywidth=9, outfile='dX', plot=False): """Measures flexure in X direction, returns pixel offset Args: cube (extraction array): List of Extraction object, the fine loc + wave solution for each spectrum hdulist (pyfits obj): Pyfits object for the spectrum to measure drow (float): offset in rows for flexure (y-axis) skylines (float, float): The night skylines to centroid on in nm - See Wavelength.fiducial spectrum for following: lamstart (float): Wavelength to start the grid on, default 1000 nm lamratio (float): Resolution of sed machine lamlen (int): Length of spectrum extract_width(int): Number of pixels to extract spectrum around skywidth(float): Fit gaussian to the ROI of skyline+-skywidth in nm. outfile (string): output pdf plot showing fits to skyline(s) plot (bool): set to True to show plot, else plot to pdf file Returns: Offset number of pixels in X direction. """ # read in image dat = hdulist[0].data # select 70 representative spaxels spec_ixs = np.arange(500, 1200, 10) # fiducial wavelength grid lamgrid = Wavelength.fiducial_spectrum(lamstart=lamstart, lamratio=lamratio, len=lamlen) # initialize grid of spaxel spectra specgrid = np.zeros((len(lamgrid), len(spec_ixs))) # loop over selected spaxels for i, ix in enumerate(spec_ixs): # get spaxel f = cube[ix] # skip baddies # bad fit if not f.ok: continue # noisy fit if f.lamnrms > 1: continue # short spectrum if f.xrange[1] - f.xrange[0] < 200: continue # set up spectral vector for this spaxel spec = np.zeros(f.xrange[1] - f.xrange[0]) yfun = np.poly1d(f.poly) # loop over x positions in spaxel for jx, xpos in enumerate(np.arange(f.xrange[0], f.xrange[1])): # get y position on image ypos = yfun(xpos) # extract spectrum from image try: spec[jx] = np.sum(dat[ypos-extract_width:ypos+extract_width, xpos]) except: continue # get wavelengths of spaxel try: ll = f.get_lambda_nm() except: continue # resample spectrum on fiducial wavelength grid specfun = interp1d(ll, spec, bounds_error=False) # insert into grid of spaxel spectra specgrid[:, i] = specfun(lamgrid) # create a median spectrum from spaxel grid # taking a median minimizes impact of objects in sample skyspec = np.median(specgrid, axis=1) # plot resulting sky spectrum pl.step(lamgrid, skyspec, where='mid') pl.xlabel("Wavelength [nm]") pl.ylabel("Spec Irr [ph/10 m/nm]") legend = ["Sky"] # accumulate average offsets from known sky lines sumoff = 0. sumscale = 0. minsig = 10000. # loop over input sky lines for skyline in skylines: # extract a wavelength window around sky line roi = (lamgrid > skyline-skywidth) & (lamgrid < skyline+skywidth) # prepare for Gaussian fit ffun = NFit.mpfit_residuals(NFit.gaussian4) # initial setup of fit parinfo = [ {'value': np.max(skyspec[roi]), 'limited': [1, 0], 'limits': [0, 0]}, {'value': skyline}, {'value': 3}, {'value': np.min(skyspec[roi]), 'limited': [1, 0], 'limits': [0, 0]}] # do the fit fit = NFit.mpfit_do(ffun, lamgrid[roi], skyspec[roi], parinfo) # did the fit succeed? if fit.status == 1 and fit.params[2] > 0.: off = fit.params[1] - skyline sumoff += off * fit.params[0] sumscale += fit.params[0] if fit.params[2] < minsig: minsig = fit.params[2] pl.plot(lamgrid[roi], NFit.gaussian4(fit.params, lamgrid[roi])) dxnm = fit.params[1] - skyline legend.append("%.1f, %.2f" % (skyline, off)) else: dxnm = 0. print("line = %6.1f (%6.1f), FWHM = %.2f nm, status = %d, dX = %3.2f nm shift" % (skyline, fit.params[0], fit.params[2]*2.354, fit.status, dxnm)) if sumscale > 0.: dxnm = sumoff / sumscale else: print "Warning: no good skylines to fit! Setting X offset to 0.0 nm" dxnm = 0. minsig = 0. print "dX = %3.2f nm shift" % dxnm pl.title("dX = %3.2f nm shift, dY = %3.2f px shift" % (dxnm, drow)) pl.legend(legend) if plot: pl.show() else: pl.savefig(outfile + ".pdf") # return offset and best FWHM return dxnm, minsig*2.354
def measure_flexure_y(cube, hdulist, profwidth=5, plot=False): # get image to measure dat = hdulist[0].data # store profiles profs = [] # x values of profiles xx = np.arange(profwidth*2) # get a sample (70) of spaxels for ix in np.arange(500, 1200, 10): # get specific spaxel f = cube[ix] # set up profile vector for this spaxel profile = np.zeros(profwidth*2) # weed out baddies # bad fit if not f.ok: continue # noisy fit if f.lamnrms > 1: continue # short spectrum if f.xrange[1] - f.xrange[0] < 200: continue # get trace of spaxel on image in y yfun = np.poly1d(f.poly) # loop over x positions of this spaxel for xpos in np.arange(f.xrange[0], f.xrange[1]): # get the y position at the given xpos try: ypos = int(np.round(yfun(xpos))) except: continue # sum profile over all xpos try: profile += dat[ypos-profwidth:ypos+profwidth, xpos] except: continue # append profile after subtracting minimum profs.append(profile - np.min(profile)) if plot: pl.figure(1) # set up Gaussian fit to profiles ffun = NFit.mpfit_residuals(NFit.gaussian4) # initial guess parinfo = [{'value': 1}, {'value': profwidth}, {'value': 2}, {'value': 0}, {'value': 0}] # y positions of profiles profposys = [] profwidys = [] for prof in profs: # plot input profile if plot: pl.plot(xx, prof, 'ro') # update initial guess parinfo[0]['value'] = np.max(prof) # fit Gaussian fit = NFit.mpfit_do(ffun, xx, prof, parinfo) # overplot fit if plot: pl.plot(xx, NFit.gaussian4(fit.params, xx)) # x offset between nominal trace position (profwidth-1) and # Gaussian fit position (fit.params[1]) profposys.append(fit.params[1] - profwidth-1) profwidys.append(fit.params[2]) profposys = np.array(profposys) profwidys = np.array(profwidys) # get statistics mn = np.mean(profposys) sd = np.std(profposys) # clean 3 sigma outliers ok = np.abs(profposys - mn)/sd < 3 # final shift required_shift = np.mean(profposys[ok]) # now do width mn = np.mean(profwidys) sd = np.std(profwidys) # clean 3 sigma outliers ok = np.abs(profwidys - mn)/sd < 3 average_width = np.mean(profwidys[ok]) * 2.354 print("yFWHM = %5.2f pixels" % float(average_width)) print("dY = %3.2f pixel shift" % required_shift) if plot: px = (profwidth+1) + required_shift pl.plot([px, px], [0, np.max(profs)], '--') pl.show() return required_shift, average_width
def measure_flexure_x(cube, hdulist, drow=0., skylines=(557.0, 589.0), extract_width=3, skywidth=9, outfile='dX', plot=False): """Measures flexure in X direction, returns pixel offset Args: cube (extraction array): List of Extraction object, the fine loc + wave solution for each spectrum hdulist (astropy.io.fits obj): Pyfits object for the spectrum to measure drow (float): offset in rows for flexure (y-axis) skylines (float, float): The night skylines to centroid on in nm extract_width(int): Number of pixels to extract spectrum around skywidth(float): Fit gaussian to the ROI of skyline+-skywidth in nm. outfile (string): output pdf plot showing fits to skyline(s) plot (bool): set to True to show plot, else plot to pdf file Returns: Offset number of pixels in X direction. """ # read in image dat = hdulist[0].data # select 70 representative spaxels spec_ixs = np.arange(500, 1200, 10) # fiducial wavelength grid lamgrid = None # loop over selected spaxels for i, ix in enumerate(spec_ixs): # get spaxel f = cube[ix] # skip baddies # bad fit if not f.ok: continue # noisy fit if f.lamnrms > 1: continue # short spectrum if f.xrange[1] - f.xrange[0] < 200: continue # set up spectral vector for this spaxel spec = np.zeros(f.xrange[1] - f.xrange[0]) yfun = np.poly1d(f.poly) # loop over x positions in spaxel for jx, xpos in enumerate(np.arange(f.xrange[0], f.xrange[1])): # get y position on image ypos = int(yfun(xpos)) # extract spectrum from image try: spec[jx] = np.sum(dat[ypos-extract_width:ypos+extract_width, xpos]) except: print("Warning: no sum for sky spectrum %d at %d" % (jx, xpos)) continue # get wavelengths of spaxel try: ll = f.get_lambda_nm() except: continue if lamgrid is None: lamgrid = ll # initialize grid of spaxel spectra specgrid = np.zeros((len(lamgrid), len(spec_ixs))) # resample spectrum on fiducial wavelength grid specfun = interp1d(ll, spec, bounds_error=False) # insert into grid of spaxel spectra specgrid[:, i] = specfun(lamgrid) # create a median spectrum from spaxel grid # taking a median minimizes impact of objects in sample skyspec = np.nanmedian(specgrid, axis=1) # plot resulting sky spectrum pl.step(lamgrid, skyspec, where='mid') pl.xlabel("Wavelength [nm]") pl.ylabel("Spec Irr [ph/10 m/nm]") legend = ["Sky"] # accumulate average offsets from known sky lines sumoff = 0. sumscale = 0. minsig = 10000. # loop over input sky lines for skyline in skylines: # extract a wavelength window around sky line roi = (lamgrid > skyline-skywidth) & (lamgrid < skyline+skywidth) # prepare for Gaussian fit ffun = NFit.mpfit_residuals(NFit.gaussian4) # initial setup of fit parinfo = [ {'value': np.max(skyspec[roi]), 'limited': [1, 0], 'limits': [0, 0]}, {'value': skyline}, {'value': 3}, {'value': np.min(skyspec[roi]), 'limited': [1, 0], 'limits': [0, 0]}] # do the fit fit = NFit.mpfit_do(ffun, lamgrid[roi], skyspec[roi], parinfo) # did the fit succeed? if fit.status == 1 and 0. < fit.params[2] < 12.: off = fit.params[1] - skyline sumoff += off * fit.params[0] sumscale += fit.params[0] if fit.params[2] < minsig: minsig = fit.params[2] pl.plot(lamgrid[roi], NFit.gaussian4(fit.params, lamgrid[roi])) dxnm = fit.params[1] - skyline legend.append("%.1f, %.2f" % (skyline, off)) print("line = %6.1f (%6.1f), FWHM = %.2f nm, status = %d," " dX = %3.2f nm shift" % (skyline, fit.params[0], fit.params[2]*2.354, fit.status, dxnm)) if sumscale > 0.: dxnm = sumoff / sumscale else: print("Warning: no good skylines to fit! Setting X offset to 0.0 nm") dxnm = 0. minsig = 0. print("dX = %3.2f nm shift" % dxnm) pl.title("dX = %3.2f nm shift, dY = %3.2f px shift" % (dxnm, drow)) pl.legend(legend) ax = pl.gca() ax.annotate('DRP: ' + drp_ver, xy=(0.0, 0.01), xytext=(0, 0), xycoords=('axes fraction', 'figure fraction'), textcoords='offset points', size=6, ha='center', va='bottom') if plot: pl.show() else: pl.savefig(outfile + ".pdf") # return offset and best FWHM return dxnm, minsig*2.354
def measure_flexure_x( fine, HDUlist, plot=True, dY=0, skyline=589.0, lamstart=1000.0, lamratio=239.0 / 240.0, lamlen=250, extract_width=3, skywidth=9, outfile="dX", ): """Measures flexure in X direction, returns pixel offset Args: fine: List of Extraction object, the fine loc + wave solution for each spectrum HDUlist: Pyfits object for the spectrum to measure plot: Plot + save results to a file dY: the measured pixel flexure in Y direction to account for skyline(float): The night skyline to centroid on in nm skywidth(float): Fit gaussian to the ROI of (skyline-skywidth to skyline+skywidth) in nm. extract_width(int): Number of pixels to extract spectrum around - See Wavelength.fiducial spectrum for following: lamstart: Wavelength to start the grid on, default 1000 nm lamratio: Resolution of sed machine lamlen: Length of spectrum Returns: Offset number of pixels in X direction. """ dat = HDUlist[0].data exptime = HDUlist[0].header["EXPTIME"] spec_ixs = np.arange(500, 1200, 10) lamgrid = Wavelength.fiducial_spectrum(lamstart=lamstart, lamratio=lamratio, len=lamlen) specgrid = np.zeros((len(lamgrid), len(spec_ixs))) for i, ix in enumerate(spec_ixs): f = fine[ix] # bad fit if not f.ok: continue # noisy fit if f.lamnrms > 1: continue # short spectrum if f.xrange[1] - f.xrange[0] < 200: continue spec = np.zeros(f.xrange[1] - f.xrange[0]) yfun = np.poly1d(f.poly) for jx, xpos in enumerate(np.arange(f.xrange[0], f.xrange[1])): ypos = yfun(xpos) try: spec[jx] = np.sum(dat[ypos - extract_width : ypos + extract_width, xpos]) except: continue try: ll = f.get_lambda_nm() except: continue specfun = interp1d(ll, spec, bounds_error=False) specgrid[:, i] = specfun(lamgrid) skyspec = np.median(specgrid, axis=1) pl.step(lamgrid, skyspec, where="mid") roi = (lamgrid > skyline - skywidth) & (lamgrid < skyline + skywidth) ffun = FF.mpfit_residuals(FF.gaussian4) parinfo = [ {"value": np.max(skyspec[roi]), "limited": [1, 0], "limits": [0, 0]}, {"value": skyline}, {"value": 3}, {"value": np.min(skyspec[roi]), "limited": [1, 0], "limits": [0, 0]}, ] fit = FF.mpfit_do(ffun, lamgrid[roi], skyspec[roi], parinfo) pl.plot(lamgrid, FF.gaussian4(fit.params, lamgrid)) pl.savefig(outfile + ".pdf") dXnm = fit.params[1] - skyline print "dX = %3.2f nm shift" % dXnm return dXnm
def measure_flexure_x(fine, HDUlist, plot=True, dY=0, skyline=589.0, lamstart=1000.0, lamratio=239./240., lamlen=250, extract_width=3, skywidth=9, outfile='dX'): '''Measures flexure in X direction, returns pixel offset Args: fine: List of Extraction object, the fine loc + wave solution for each spectrum HDUlist: Pyfits object for the spectrum to measure plot: Plot + save results to a file dY: the measured pixel flexure in Y direction to account for skyline(float): The night skyline to centroid on in nm skywidth(float): Fit gaussian to the ROI of (skyline-skywidth to skyline+skywidth) in nm. extract_width(int): Number of pixels to extract spectrum around - See Wavelength.fiducial spectrum for following: lamstart: Wavelength to start the grid on, default 1000 nm lamratio: Resolution of sed machine lamlen: Length of spectrum Returns: Offset number of pixels in X direction. ''' dat = HDUlist[0].data exptime = HDUlist[0].header['EXPTIME'] spec_ixs = np.arange(500, 1200, 10) lamgrid = Wavelength.fiducial_spectrum(lamstart=lamstart, lamratio=lamratio, len=lamlen) specgrid = np.zeros((len(lamgrid), len(spec_ixs))) for i,ix in enumerate(spec_ixs): f = fine[ix] if not f.ok: continue if f.lamrms > 1: continue if f.xrange[1] - f.xrange[0] < 200: continue spec = np.zeros(f.xrange[1] - f.xrange[0]) yfun = np.poly1d(f.poly) for jx,xpos in enumerate(np.arange(f.xrange[0], f.xrange[1])): ypos = yfun(xpos) try:spec[jx] = np.sum(dat[ypos-extract_width:ypos+extract_width, xpos]) except: continue try:ll = f.get_lambda_nm() except: continue specfun = interp1d(ll, spec, bounds_error=False) specgrid[:,i] = specfun(lamgrid) skyspec = np.median(specgrid, axis=1) pl.step(lamgrid, skyspec, where='mid') roi = (lamgrid>skyline-skywidth) & (lamgrid<skyline+skywidth) ffun = FF.mpfit_residuals(FF.gaussian4) parinfo= [ {'value': np.max(skyspec[roi]), 'limited': [1,0], 'limits': [0, 0]}, {'value': skyline}, {'value': 3}, {'value': np.min(skyspec[roi]), 'limited': [1,0], 'limits': [0,0]}] fit = FF.mpfit_do(ffun, lamgrid[roi], skyspec[roi], parinfo) pl.plot(lamgrid, FF.gaussian4(fit.params, lamgrid)) pl.savefig(outfile + ".pdf") dXnm = fit.params[1] - skyline print "dX = %3.2f nm shift" % dXnm return dXnm
def measure_flexure_x(cube, hdulist, drow=0., skylines=(557.0, 589.0), lamstart=1000.0, lamratio=239. / 240., lamlen=250, extract_width=3, skywidth=9, outfile='dX'): """Measures flexure in X direction, returns pixel offset Args: cube (extraction array): List of Extraction object, the fine loc + wave solution for each spectrum hdulist (pyfits obj): Pyfits object for the spectrum to measure drow (float): offset in rows for flexure (y-axis) skylines (float, float): The night skylines to centroid on in nm skywidth(float): Fit gaussian to the ROI of (skyline-skywidth to skyline+skywidth) in nm. extract_width(int): Number of pixels to extract spectrum around - See Wavelength.fiducial spectrum for following: lamstart (float): Wavelength to start the grid on, default 1000 nm lamratio (float): Resolution of sed machine lamlen (int): Length of spectrum outfile (string): output pdf plot showing fits to skyline(s) Returns: Offset number of pixels in X direction. """ dat = hdulist[0].data spec_ixs = np.arange(500, 1200, 10) lamgrid = Wavelength.fiducial_spectrum(lamstart=lamstart, lamratio=lamratio, len=lamlen) specgrid = np.zeros((len(lamgrid), len(spec_ixs))) for i, ix in enumerate(spec_ixs): f = cube[ix] # bad fit if not f.ok: continue # noisy fit if f.lamnrms > 1: continue # short spectrum if f.xrange[1] - f.xrange[0] < 200: continue spec = np.zeros(f.xrange[1] - f.xrange[0]) yfun = np.poly1d(f.poly) for jx, xpos in enumerate(np.arange(f.xrange[0], f.xrange[1])): ypos = yfun(xpos) try: spec[jx] = np.sum(dat[ypos - extract_width:ypos + extract_width, xpos]) except: continue try: ll = f.get_lambda_nm() except: continue specfun = interp1d(ll, spec, bounds_error=False) specgrid[:, i] = specfun(lamgrid) skyspec = np.median(specgrid, axis=1) pl.step(lamgrid, skyspec, where='mid') pl.xlabel("Wavelength [nm]") pl.ylabel("Spec Irr [ph/10 m/nm]") sumoff = 0. sumscale = 0. legend = ["Sky"] for skyline in skylines: roi = (lamgrid > skyline - skywidth) & (lamgrid < skyline + skywidth) ffun = NFit.mpfit_residuals(NFit.gaussian4) parinfo = [{ 'value': np.max(skyspec[roi]), 'limited': [1, 0], 'limits': [0, 0] }, { 'value': skyline }, { 'value': 3 }, { 'value': np.min(skyspec[roi]), 'limited': [1, 0], 'limits': [0, 0] }] fit = NFit.mpfit_do(ffun, lamgrid[roi], skyspec[roi], parinfo) if fit.status == 1: off = fit.params[1] - skyline sumoff += off * fit.params[0] sumscale += fit.params[0] pl.plot(lamgrid[roi], NFit.gaussian4(fit.params, lamgrid[roi])) dxnm = fit.params[1] - skyline legend.append("%.1f, %.2f" % (skyline, off)) else: dxnm = 0. print("line = %6.1f (%6.1f), status = %d, dX = %3.2f nm shift" % (skyline, fit.params[0], fit.status, dxnm)) if sumscale > 0.: dxnm = sumoff / sumscale else: print "Warning: no good skylines to fit! Setting X offset to 0.0 nm" dxnm = 0. print "dX = %3.2f nm shift" % dxnm pl.title("dX = %3.2f nm shift, dY = %3.2f px shift" % (dxnm, drow)) pl.legend(legend) pl.savefig(outfile + ".pdf") return dxnm