def __rectify_spectral(order): """ """ for frame in order.frames: order.objImg[frame] = image_lib.rectify_spectral(order.objImg[frame], order.spectralTrace) order.ffObjImg[frame] = image_lib.rectify_spectral( order.ffObjImg[frame], order.spectralTrace) return
def reduce_order(order, flat_order): # flatten obj but keep original for noise calc order.flattenedObjImg = np.array(order.objCutout / flat_order.normFlatImg) if np.amin(order.flattenedObjImg) < 0: order.flattenedObjImg -= np.amin(order.flattenedObjImg) order.flattened = True order.objImg = np.array(order.objCutout) # should probably use objImg instead of objCutout to begin with logger.info('order has been flat fielded') # rectify flat, normalized flat, obj and flattened obj in spatial dimension order.objImg = image_lib.rectify_spatial(order.objImg, flat_order.smoothedSpatialTrace) order.flattenedObjImg = image_lib.rectify_spatial( order.flattenedObjImg, flat_order.smoothedSpatialTrace) # trim rectified order order.objImg = order.objImg[flat_order.botTrim:flat_order.topTrim, :] order.flattenedObjImg = order.flattenedObjImg[flat_order.botTrim:flat_order.topTrim, :] order.srNormFlatImg = flat_order.rectFlatImg order.srFlatObjImg = order.flattenedObjImg order.spatialRectified = True # find spatial profile and peak find_spatial_profile_and_peak(order) # characterize spatial profile by fitting to Gaussian characterize_spatial_profile(order) # find and smooth spectral trace try: order.spectralTrace = nirspec_lib.smooth_spectral_trace( nirspec_lib.find_spectral_trace( order.flattenedObjImg), order.flattenedObjImg.shape[0]) except Exception as e: logger.warning('not rectifying order {} in spectral dimension'.format(order.orderNum)) else: flat_order.rectFlatImg = image_lib.rectify_spectral(flat_order.rectFlatImg, order.spectralTrace) order.objImg = image_lib.rectify_spectral(order.objImg, order.spectralTrace) order.objImgFlattened = image_lib.rectify_spectral(order.flattenedObjImg, order.spectralTrace) order.spectralRectified = True # compute noise image order.noiseImg = nirspec_lib.calc_noise_img( order.objImg, flat_order.rectFlatImg, order.integrationTime) # extract spectra extract_spectra(order, flat_order) # calculate SNR bg = 0.0 if order.topBgMean is not None: bg += order.topBgMean if order.botBgMean is not None: bg += order.botBgMean if order.topBgMean is not None and order.botBgMean is not None: bg /= 2 order.snr = np.absolute(np.mean(order.flattenedObjImg[order.peakLocation:order.peakLocation + 1, :]) / bg) logger.info('signal-to-noise ratio = {:.1f}'.format(order.snr)) # find and identify sky lines line_pairs = None # line_pairs are (column number, accepted wavelength try: oh_wavelengths, oh_intensities = wavelength_utils.get_oh_lines() except IOError as e: logger.critical('cannot read OH line file: ' + str(e)) raise try: # synthesize sky spectrum and store in order object order.synthesizedSkySpec = wavelength_utils.synthesize_sky( oh_wavelengths, oh_intensities, order.gratingEqWaveScale) # identify lines and return list of (column number, accepted wavelength) tuples line_pairs = wavelength_utils.line_id(order, oh_wavelengths, oh_intensities) except (IOError, ValueError) as e: logger.warning('sky line matching failed: ' + str(e)) if line_pairs is not None: logger.info(str(len(line_pairs)) + ' matched sky lines found in order') # add line pairs to Order object as Line objects for line_pair in line_pairs: col, waveAccepted = line_pair peak = order.skySpec[col] cent = image_lib.centroid(order.skySpec, 1024, 5, col) line = Line.Line(order.frame, order.orderNum, waveAccepted, col, cent, peak) order.lines.append(line) if len(order.lines) >= 3: # do local wavelength fit measured = [] accepted = [] for line in order.lines: measured.append(order.gratingEqWaveScale[line.col]) accepted.append(line.waveAccepted) (order.orderCalSlope, order.orderCalIncpt, order.orderCalCorrCoeff, p, e) = \ scipy.stats.linregress(np.array(measured), np.array(accepted)) order.orderCalNLines = len(order.lines) logger.info('per order wavelength fit: n = {}, a = {:.6f}, b = {:.6f}, r = {:.6f}'.format( len(order.lines), order.orderCalIncpt, order.orderCalSlope, order.orderCalCorrCoeff)) for line in order.lines: line.orderWaveFit = order.orderCalIncpt + \ (order.orderCalSlope * order.gratingEqWaveScale[line.col]) line.orderFitRes = abs(line.orderWaveFit - line.waveAccepted) line.orderFitSlope = (order.orderCalSlope * (order.gratingEqWaveScale[1023] - order.gratingEqWaveScale[0]))/1024.0 else: logger.warning('no matched sky lines in order ' + str(order.orderNum)) order.orderCal = False return
def reduce_order(order): # normalize flat order.normalizedFlatImg, order.flatMean = image_lib.normalize( order.flatCutout, order.onOrderMask, order.offOrderMask) order.flatNormalized = True logger.info('flat normalized, flat mean = ' + str(round(order.flatMean, 1))) # flatten obj but keep original for noise calc order.flattenedObjImg = np.array(order.objCutout / order.normalizedFlatImg) if np.amin(order.flattenedObjImg) < 0: order.flattenedObjImg -= np.amin(order.flattenedObjImg) order.flattened = True order.objImg = np.array(order.objCutout) # should probably use objImg instead of objCutout to begin with order.flatImg = np.array(order.flatCutout) logger.info('order has been flat fielded') # smooth spatial trace # this should probably be done where the trace is first found order.smoothedTrace, order.traceMask = nirspec_lib.smooth_spatial_trace(order.avgTrace) logger.info('spatial trace smoothed, ' + str(order.objImg.shape[1] - np.count_nonzero(order.traceMask)) + ' points ignored') # rectify flat, normalized flat, obj and flattened obj in spatial dimension order.flatImg = image_lib.rectify_spatial(order.flatImg, order.smoothedTrace) order.normalizedFlatImg = image_lib.rectify_spatial(order.normalizedFlatImg, order.smoothedTrace) order.objImg = image_lib.rectify_spatial(order.objImg, order.smoothedTrace) order.flattenedObjImg = image_lib.rectify_spatial(order.flattenedObjImg, order.smoothedTrace) if order.lowestPoint > order.padding: top = order.highestPoint - order.lowestPoint + order.padding - 3 else: top = order.highestPoint - 3 h = np.amin(order.topTrace - order.botTrace) bot = top - h + 3 bot = max(0, bot) top = min(top, 1023) order.flatImg = order.flatImg[bot:top, :] order.normalizedFlatImg = order.normalizedFlatImg[bot:top, :] order.objImg = order.objImg[bot:top, :] order.flattenedObjImg = order.flattenedObjImg[bot:top, :] order.srNormFlatImg = order.normalizedFlatImg order.srFlatObjImg = order.flattenedObjImg order.spatialRectified = True # find spatial profile and peak order.spatialProfile = order.flattenedObjImg.mean(axis=1) # import pylab as pl # # pl.figure() # pl.cla() # pl.imshow(order.flattenedObjImg) # pl.show() # # pl.figure(str(order.orderNum)) # pl.cla() # pl.plot(order.spatialProfile) # pl.show() order.peakLocation = np.argmax(order.spatialProfile[5:-5]) + 5 logger.info('spatial profile peak intensity row {:d}'.format(order.peakLocation)) p0 = order.peakLocation - (config.params['obj_window'] / 2) p1 = order.peakLocation + (config.params['obj_window'] / 2) order.centroid = (scipy.ndimage.measurements.center_of_mass( order.spatialProfile[p0:p1]))[0] + p0 logger.info('spatial profile peak centroid row {:.1f}'.format(float(order.centroid))) # characterize spatial profile by fitting to Gaussian try: for w in range(10, 30, 10): logger.debug('gaussian window width = {}'.format(2 * w)) x0 = max(0, order.peakLocation - w) x1 = min(len(order.spatialProfile) - 1, order.peakLocation + w) x = range(x1 - x0) order.gaussianParams, pcov = scipy.optimize.curve_fit( image_lib.gaussian, x, order.spatialProfile[x0:x1] - np.amin(order.spatialProfile[x0:x1])) order.gaussianParams[1] += x0 if order.gaussianParams[2] > 1.0: break except Exception as e: logger.warning('cannot fit spatial profile to Gaussian') order.gaussianParams = None else: logger.info('spatial peak width = {:.1f} pixels'.format(abs(order.gaussianParams[2]))) # find and smooth spectral trace try: order.spectral_trace = nirspec_lib.smooth_spectral_trace( nirspec_lib.find_spectral_trace( order.flattenedObjImg, order.padding), order.flattenedObjImg.shape[0]) except Exception as e: logger.warning('not rectifying order in spectral dimension') else: # rectify flat, normalized flat, obj and flattened obj in spectral dimension order.flatImg = image_lib.rectify_spectral(order.flatImg, order.spectral_trace) order.normalizedFlatImg = image_lib.rectify_spectral(order.normalizedFlatImg, order.spectral_trace) order.objImg = image_lib.rectify_spectral(order.objImg, order.spectral_trace) order.objImgFlattened = image_lib.rectify_spectral(order.flattenedObjImg, order.spectral_trace) order.spectralRectified = True # compute noise image order.noiseImg = nirspec_lib.calc_noise_img( order.objImg, order.normalizedFlatImg, order.integrationTime) # extract spectra order.objWindow, order.topSkyWindow, order.botSkyWindow = \ image_lib.get_extraction_ranges(order.objImg.shape[0], order.peakLocation, config.params['obj_window'], config.params['sky_window'], config.params['sky_separation']) logger.info('extraction window width = {}'.format(str(len(order.objWindow)))) logger.info('top background window width = {}'.format(str(len(order.topSkyWindow)))) if len(order.topSkyWindow) > 0: logger.info('top background window separation = {}'.format( str(order.topSkyWindow[0] - order.objWindow[-1]))) logger.info('bottom background window width = {}'.format(str(len(order.botSkyWindow)))) if len(order.botSkyWindow) > 0: logger.info('bottom background window separation = {}'.format( str(order.objWindow[0] - order.botSkyWindow[-1]))) order.objSpec, order.flatSpec, order.skySpec, order.noiseSpec, order.topBgMean, \ order.botBgMean = image_lib.extract_spectra( order.flattenedObjImg, order.normalizedFlatImg, order.noiseImg, order.objWindow, order.topSkyWindow, order.botSkyWindow) # calculate SNR bg = 0.0 if order.topBgMean is not None: bg += order.topBgMean if order.botBgMean is not None: bg += order.botBgMean if order.topBgMean is not None and order.botBgMean is not None: bg /= 2 order.snr = np.absolute(np.mean(order.flattenedObjImg[order.peakLocation:order.peakLocation + 1, :]) / bg) logger.info('signal-to-noise ratio = {:.1f}'.format(order.snr)) # find and identify sky lines line_pairs = None # line_pairs are (column number, accepted wavelength try: oh_wavelengths, oh_intensities = wavelength_utils.get_oh_lines(config.params['oh_filename']) except IOError as e: logger.critical('cannot read OH line file: ' + str(e)) raise try: # synthesize sky spectrum and store in order object order.synthesizedSkySpec = wavelength_utils.synthesize_sky( oh_wavelengths, oh_intensities, order.wavelengthScaleCalc) # identify lines and return list of (column number, accepted wavelength) tuples line_pairs = wavelength_utils.line_id(order, oh_wavelengths, oh_intensities) except (IOError, ValueError) as e: logger.warning('sky line matching failed: ' + str(e)) if line_pairs is not None: logger.info(str(len(line_pairs)) + ' matched sky lines found in order') # add line pairs to Order object as Line objects for line_pair in line_pairs: line = Line.Line() line.col, line.acceptedWavelength = line_pair line.peak = order.skySpec[line.col] # find centroid of peak w = 5 p0 = max(0, line.col - (w / 2)) p1 = min(1023, line.col + (w / 2)) + 1 line.centroid = p0 + scipy.ndimage.center_of_mass(order.skySpec[p0:p1])[0] if abs(line.centroid - line.col) > 1: logger.warning('sky line centroid error, col = {}, centroid = {:.3f}'.format( line.col, line.centroid)) line.centroid = line.col order.lines.append(line) if len(order.lines) >= 3: # do local wavelength fit measured = [] accepted = [] for line in order.lines: measured.append(order.wavelengthScaleCalc[line.col]) accepted.append(line.acceptedWavelength) (order.perOrderSlope, order.perOrderIntercept, order.perOrderCorrCoeff, p, e) = \ scipy.stats.linregress(np.array(measured), np.array(accepted)) logger.info('per order wavelength fit: n = {}, a = {:.6f}, b = {:.6f}, r = {:.6f}'.format( len(order.lines), order.perOrderIntercept, order.perOrderSlope, order.perOrderCorrCoeff)) for line in order.lines: line.localFitWavelength = order.perOrderIntercept + \ (order.perOrderSlope * order.wavelengthScaleCalc[line.col]) line.localFitResidual = abs(line.localFitWavelength - line.acceptedWavelength) line.localFitSlope = (order.perOrderSlope * (order.wavelengthScaleCalc[1023] - order.wavelengthScaleCalc[0]))/1024.0 else: logger.warning('no matched sky lines in order ' + str(order.orderNum)) return
def reduce_order(order): # flatten object images for this order __flatten(order) # rectify obj and flattened obj in spatial dimension __rectify_spatial(order) # trim rectified order __trim(order) # save rectified images before spectral rectify for diagnostics order.srNormFlatImg = order.flatOrder.rectFlatImg for frame in order.frames: order.srFfObjImg[frame] = order.ffObjImg[frame] # find spatial profile and peak __find_spatial_profile_and_peak(order) # characterize spatial profile by fitting to Gaussian __characterize_spatial_profile(order) # Find and smooth spectral trace, always use frame A try: order.spectralTrace = nirspec_lib.smooth_spectral_trace( nirspec_lib.find_spectral_trace(order.ffObjImg['A']), order.ffObjImg['A'].shape[0]) except Exception as e: logger.warning('not rectifying order {} in spectral dimension'.format( order.flatOrder.orderNum)) else: order.flatOrder.rectFlatImg = image_lib.rectify_spectral( order.flatOrder.rectFlatImg, order.spectralTrace) __rectify_spectral(order) order.spectralRectified = True # compute noise image order.noiseImg = nirspec_lib.calc_noise_img(order.objImg['A'], order.flatOrder.rectFlatImg, order.integrationTime) # extract spectra __extract_spectra(order) # calculate approximate SNR __calc_approximate_snr(order) # find and identify sky lines line_pairs = None # line_pairs are (column number, accepted wavelength) try: oh_wavelengths, oh_intensities = wavelength_utils.get_oh_lines() except IOError as e: logger.critical('cannot read OH line file: ' + str(e)) raise try: # synthesize sky spectrum and store in order object order.synthesizedSkySpec = wavelength_utils.synthesize_sky( oh_wavelengths, oh_intensities, order.flatOrder.gratingEqWaveScale) # identify lines and return list of (column number, accepted # wavelength) tuples line_pairs = wavelength_utils.line_id(order, oh_wavelengths, oh_intensities) except (IOError, ValueError) as e: logger.warning('sky line matching failed: ' + str(e)) if line_pairs is not None: logger.info(str(len(line_pairs)) + ' matched sky lines found in order') # add line pairs to Order object as Line objects for line_pair in line_pairs: col, waveAccepted = line_pair peak = order.skySpec['A'][col] cent = image_lib.centroid(order.skySpec['A'], 1024, 5, col) line = Line.Line(order.baseNames['A'], order.flatOrder.orderNum, waveAccepted, col, cent, peak) order.lines.append(line) if len(order.lines) >= 3: # do local wavelength fit measured = [] accepted = [] for line in order.lines: measured.append(order.flatOrder.gratingEqWaveScale[line.col]) accepted.append(line.waveAccepted) (order.orderCalSlope, order.orderCalIncpt, order.orderCalCorrCoeff, p, e) = \ scipy.stats.linregress(np.array(measured), np.array(accepted)) order.orderCalNLines = len(order.lines) logger.info( 'per order wavelength fit: n = {}, a = {:.6f}, b = {:.6f}, r = {:.6f}' .format(len(order.lines), order.orderCalIncpt, order.orderCalSlope, order.orderCalCorrCoeff)) for line in order.lines: line.orderWaveFit = order.orderCalIncpt + \ (order.orderCalSlope * order.flatOrder.gratingEqWaveScale[line.col]) line.orderFitRes = abs(line.orderWaveFit - line.waveAccepted) line.orderFitSlope = ( order.orderCalSlope * (order.flatOrder.gratingEqWaveScale[1023] - order.flatOrder.gratingEqWaveScale[0])) / 1024.0 else: logger.warning('no matched sky lines in order ' + str(order.flatOrder.orderNum)) order.orderCal = False return
def __rectify_spectral(order, eta=None, arc=None): """ """ for frame in order.frames: #print('FRAME', frame) if frame == 'AB': continue if config.params['onoff'] == True and frame == 'B': order.objImg[frame], peak1 = image_lib.rectify_spectral( order.objImg[frame], order.spectralTrace['A'], returnpeak=True) order.ffObjImg[frame], peak2 = image_lib.rectify_spectral( order.ffObjImg[frame], order.spectralTrace['A'], returnpeak=True) else: order.objImg[frame], peak1 = image_lib.rectify_spectral( order.objImg[frame], order.spectralTrace[frame], returnpeak=True) order.ffObjImg[frame], peak2 = image_lib.rectify_spectral( order.ffObjImg[frame], order.spectralTrace[frame], returnpeak=True) if frame == 'A': order.flatOrder.rectFlatImg, peak0 = image_lib.rectify_spectral( order.flatOrder.rectFlatImg, order.spectralTrace[frame], returnpeak=True) if eta is not None: if frame == 'B': if config.params['onoff'] == True: order.etaImgB = order.etaImg order.ffEtaImgB = iorder.ffEtaImg else: order.etaImgB = image_lib.rectify_spectral( order.etaImgB, order.spectralTrace[frame], peak1) order.ffEtaImgB = image_lib.rectify_spectral( order.ffEtaImgB, order.spectralTrace[frame], peak2) else: order.etaImg = image_lib.rectify_spectral( order.etaImg, order.spectralTrace[frame], peak1) order.ffEtaImg = image_lib.rectify_spectral( order.ffEtaImg, order.spectralTrace[frame], peak2) if arc is not None: if frame == 'B': if config.params['onoff'] == True: order.arcImgB = order.arcImg order.ffArcImgB = iorder.ffArcImg else: order.arcImgB = image_lib.rectify_spectral( order.arcImgB, order.spectralTrace[frame], peak1) order.ffArcImgB = image_lib.rectify_spectral( order.ffArcImgB, order.spectralTrace[frame], peak2) else: order.arcImg = image_lib.rectify_spectral( order.arcImg, order.spectralTrace[frame], peak1) order.ffArcImg = image_lib.rectify_spectral( order.ffArcImg, order.spectralTrace[frame], peak2) return