def keppca(infile, maskfile, outfile, components, plotpca, nreps, clobber, verbose, logfile, status, cmdLine=False): try: import mdp except: msg = 'ERROR -- KEPPCA: this task has an external python dependency to MDP, a Modular toolkit for Data Processing (http://mdp-toolkit.sourceforge.net). In order to take advantage of this PCA task, the user must first install MDP with their current python distribution. Note carefully that you may have more than python installation on your machine, and ensure that MDP is installed with the same version of python that the PyKE tools employ. Installation instructions for MDP can be found at the URL provided above.' status = kepmsg.err(None, msg, True) # startup parameters status = 0 labelsize = 32 ticksize = 18 xsize = 16 ysize = 10 lcolor = '#0000ff' lwidth = 1.0 fcolor = '#ffff00' falpha = 0.2 seterr(all="ignore") # log the call if status == 0: hashline = '----------------------------------------------------------------------------' kepmsg.log(logfile, hashline, verbose) call = 'KEPPCA -- ' call += 'infile=' + infile + ' ' call += 'maskfile=' + maskfile + ' ' call += 'outfile=' + outfile + ' ' call += 'components=' + components + ' ' ppca = 'n' if (plotpca): ppca = 'y' call += 'plotpca=' + ppca + ' ' call += 'nmaps=' + str(nreps) + ' ' overwrite = 'n' if (clobber): overwrite = 'y' call += 'clobber=' + overwrite + ' ' chatter = 'n' if (verbose): chatter = 'y' call += 'verbose=' + chatter + ' ' call += 'logfile=' + logfile kepmsg.log(logfile, call + '\n', verbose) # start time if status == 0: kepmsg.clock('KEPPCA started at', logfile, verbose) # test log file if status == 0: logfile = kepmsg.test(logfile) # clobber output file if status == 0: if clobber: status = kepio.clobber(outfile, logfile, verbose) if kepio.fileexists(outfile): message = 'ERROR -- KEPPCA: ' + outfile + ' exists. Use clobber=yes' status = kepmsg.err(logfile, message, verbose) # Set output file names - text file with data and plot if status == 0: dataout = copy(outfile) repname = re.sub('.fits', '.png', outfile) # open input file if status == 0: instr = pyfits.open(infile, mode='readonly', memmap=True) tstart, tstop, bjdref, cadence, status = kepio.timekeys( instr, infile, logfile, verbose, status) # open TPF FITS file if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \ kepio.readTPF(infile,'TIME',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \ kepio.readTPF(infile,'TIMECORR',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \ kepio.readTPF(infile,'CADENCENO',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \ kepio.readTPF(infile,'FLUX',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \ kepio.readTPF(infile,'FLUX_ERR',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, flux_bkg, status = \ kepio.readTPF(infile,'FLUX_BKG',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, flux_bkg_err, status = \ kepio.readTPF(infile,'FLUX_BKG_ERR',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, qual, status = \ kepio.readTPF(infile,'QUALITY',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, pcorr1, status = \ kepio.readTPF(infile,'POS_CORR1',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, pcorr2, status = \ kepio.readTPF(infile,'POS_CORR2',logfile,verbose) # Save original data dimensions, in case of using maskfile if status == 0: xdimorig = xdim ydimorig = ydim # read mask definition file if it has been supplied if status == 0 and 'aper' not in maskfile.lower( ) and maskfile.lower() != 'all': maskx = array([], 'int') masky = array([], 'int') lines, status = kepio.openascii(maskfile, 'r', logfile, verbose) for line in lines: line = line.strip().split('|') if len(line) == 6: y0 = int(line[3]) x0 = int(line[4]) line = line[5].split(';') for items in line: try: masky = numpy.append(masky, y0 + int(items.split(',')[0])) maskx = numpy.append(maskx, x0 + int(items.split(',')[1])) except: continue status = kepio.closeascii(lines, logfile, verbose) if len(maskx) == 0 or len(masky) == 0: message = 'ERROR -- KEPPCA: ' + maskfile + ' contains no pixels.' status = kepmsg.err(logfile, message, verbose) xdim = max(maskx) - min(maskx) + 1 # Find largest x dimension of mask ydim = max(masky) - min(masky) + 1 # Find largest y dimension of mask # pad mask to ensure it is rectangular workx = array([], 'int') worky = array([], 'int') for ip in arange(min(maskx), max(maskx) + 1): for jp in arange(min(masky), max(masky) + 1): workx = append(workx, ip) worky = append(worky, jp) maskx = workx masky = worky # define new subimage bitmap... if status == 0 and maskfile.lower() != 'all': aperx = numpy.array([], 'int') apery = numpy.array([], 'int') aperb = maskx - x0 + xdimorig * ( masky - y0 ) # aperb is an array that contains the pixel numbers in the mask npix = len(aperb) # ...or use all pixels if status == 0 and maskfile.lower() == 'all': npix = xdimorig * ydimorig aperb = array([], 'int') aperb = numpy.r_[0:npix] # legal mask defined? if status == 0: if len(aperb) == 0: message = 'ERROR -- KEPPCA: no legal pixels within the subimage are defined.' status = kepmsg.err(logfile, message, verbose) # Identify principal components desired if status == 0: pcaout = [] txt = components.strip().split(',') for work1 in txt: try: pcaout.append(int(work1.strip())) except: work2 = work1.strip().split('-') try: for work3 in range(int(work2[0]), int(work2[1]) + 1): pcaout.append(work3) except: message = 'ERROR -- KEPPCA: cannot understand principal component list requested' status = kepmsg.err(logfile, message, verbose) if status == 0: pcaout = set(sort(pcaout)) pcarem = array( list(pcaout)) - 1 # The list of pca component numbers to be removed # Initialize arrays and variables, and apply pixel mask to the data if status == 0: ntim = 0 time = numpy.array([], dtype='float64') timecorr = numpy.array([], dtype='float32') cadenceno = numpy.array([], dtype='int') pixseries = numpy.array([], dtype='float32') errseries = numpy.array([], dtype='float32') bkgseries = numpy.array([], dtype='float32') berseries = numpy.array([], dtype='float32') quality = numpy.array([], dtype='float32') pos_corr1 = numpy.array([], dtype='float32') pos_corr2 = numpy.array([], dtype='float32') nrows = numpy.size(fluxpixels, 0) # Apply the pixel mask so we are left with only the desired pixels if status == 0: pixseriesb = fluxpixels[:, aperb] errseriesb = errpixels[:, aperb] bkgseriesb = flux_bkg[:, aperb] berseriesb = flux_bkg_err[:, aperb] # Read in the data to various arrays if status == 0: for i in range(nrows): if qual[i] < 10000 and \ numpy.isfinite(barytime[i]) and \ numpy.isfinite(fluxpixels[i,int(ydim*xdim/2+0.5)]) and \ numpy.isfinite(fluxpixels[i,1+int(ydim*xdim/2+0.5)]): ntim += 1 time = numpy.append(time, barytime[i]) timecorr = numpy.append(timecorr, tcorr[i]) cadenceno = numpy.append(cadenceno, cadno[i]) pixseries = numpy.append(pixseries, pixseriesb[i]) errseries = numpy.append(errseries, errseriesb[i]) bkgseries = numpy.append(bkgseries, bkgseriesb[i]) berseries = numpy.append(berseries, berseriesb[i]) quality = numpy.append(quality, qual[i]) pos_corr1 = numpy.append(pos_corr1, pcorr1[i]) pos_corr2 = numpy.append(pos_corr2, pcorr2[i]) pixseries = numpy.reshape(pixseries, (ntim, npix)) errseries = numpy.reshape(errseries, (ntim, npix)) bkgseries = numpy.reshape(bkgseries, (ntim, npix)) berseries = numpy.reshape(berseries, (ntim, npix)) tmp = numpy.median(pixseries, axis=1) for i in range(len(tmp)): pixseries[i] = pixseries[i] - tmp[i] # Figure out which pixels are undefined/nan and remove them. Keep track for adding back in later if status == 0: nanpixels = numpy.array([], dtype='int') i = 0 while (i < npix): if numpy.isnan(pixseries[0, i]): nanpixels = numpy.append(nanpixels, i) npix = npix - 1 i = i + 1 pixseries = numpy.delete(pixseries, nanpixels, 1) errseries = numpy.delete(errseries, nanpixels, 1) pixseries[numpy.isnan(pixseries)] = random.gauss(100, 10) errseries[numpy.isnan(errseries)] = 10 # Compute statistical weights, means, standard deviations if status == 0: weightseries = (pixseries / errseries)**2 pixMean = numpy.average(pixseries, axis=0, weights=weightseries) pixStd = numpy.std(pixseries, axis=0) # Normalize the input by subtracting the mean and divising by the standard deviation. # This makes it a correlation-based PCA, which is what we want. if status == 0: pixseriesnorm = (pixseries - pixMean) / pixStd # Number of principal components to compute. Setting it equal to the number of pixels if status == 0: nvecin = npix # Run PCA using the MDP Whitening PCA, which produces normalized PCA components (zero mean and unit variance) if status == 0: pcan = mdp.nodes.WhiteningNode(svd=True) pcar = pcan.execute(pixseriesnorm) eigvec = pcan.get_recmatrix() model = pcar # Re-insert nan columns as zeros if status == 0: for i in range(0, len(nanpixels)): nanpixels[i] = nanpixels[i] - i eigvec = numpy.insert(eigvec, nanpixels, 0, 1) pixMean = numpy.insert(pixMean, nanpixels, 0, 0) # Make output eigenvectors (correlation images) into xpix by ypix images if status == 0: eigvec = eigvec.reshape(nvecin, ydim, xdim) # Calculate sum of all pixels to display as raw lightcurve and other quantities if status == 0: pixseriessum = sum(pixseries, axis=1) nrem = len(pcarem) # Number of components to remove nplot = npix # Number of pcas to plot - currently set to plot all components, but could set # nplot = nrem to just plot as many components as is being removed # Subtract components by fitting them to the summed light curve if status == 0: x0 = numpy.tile(-1.0, 1) for k in range(0, nrem): def f(x): fluxcor = pixseriessum for k in range(0, len(x)): fluxcor = fluxcor - x[k] * model[:, pcarem[k]] return mad(fluxcor) if k == 0: x0 = array([-1.0]) else: x0 = numpy.append(x0, 1.0) myfit = scipy.optimize.fmin(f, x0, maxiter=50000, maxfun=50000, disp=False) x0 = myfit # Now that coefficients for all components have been found, subtract them to produce a calibrated time-series, # and then divide by the robust mean to produce a normalized time series as well if status == 0: c = myfit fluxcor = pixseriessum for k in range(0, nrem): fluxcor = fluxcor - c[k] * model[:, pcarem[k]] normfluxcor = fluxcor / mean(reject_outliers(fluxcor, 2)) # input file data if status == 0: cards0 = instr[0].header.cards cards1 = instr[1].header.cards cards2 = instr[2].header.cards table = instr[1].data[:] maskmap = copy(instr[2].data) # subimage physical WCS data if status == 0: crpix1p = cards2['CRPIX1P'].value crpix2p = cards2['CRPIX2P'].value crval1p = cards2['CRVAL1P'].value crval2p = cards2['CRVAL2P'].value cdelt1p = cards2['CDELT1P'].value cdelt2p = cards2['CDELT2P'].value # dummy columns for output file if status == 0: sap_flux_err = numpy.empty(len(time)) sap_flux_err[:] = numpy.nan sap_bkg = numpy.empty(len(time)) sap_bkg[:] = numpy.nan sap_bkg_err = numpy.empty(len(time)) sap_bkg_err[:] = numpy.nan pdc_flux = numpy.empty(len(time)) pdc_flux[:] = numpy.nan pdc_flux_err = numpy.empty(len(time)) pdc_flux_err[:] = numpy.nan psf_centr1 = numpy.empty(len(time)) psf_centr1[:] = numpy.nan psf_centr1_err = numpy.empty(len(time)) psf_centr1_err[:] = numpy.nan psf_centr2 = numpy.empty(len(time)) psf_centr2[:] = numpy.nan psf_centr2_err = numpy.empty(len(time)) psf_centr2_err[:] = numpy.nan mom_centr1 = numpy.empty(len(time)) mom_centr1[:] = numpy.nan mom_centr1_err = numpy.empty(len(time)) mom_centr1_err[:] = numpy.nan mom_centr2 = numpy.empty(len(time)) mom_centr2[:] = numpy.nan mom_centr2_err = numpy.empty(len(time)) mom_centr2_err[:] = numpy.nan # mask bitmap if status == 0 and 'aper' not in maskfile.lower( ) and maskfile.lower() != 'all': for i in range(maskmap.shape[0]): for j in range(maskmap.shape[1]): aperx = append(aperx, crval1p + (j + 1 - crpix1p) * cdelt1p) apery = append(apery, crval2p + (i + 1 - crpix2p) * cdelt2p) if maskmap[i, j] == 0: pass else: maskmap[i, j] = 1 for k in range(len(maskx)): if aperx[-1] == maskx[k] and apery[-1] == masky[k]: maskmap[i, j] = 3 # construct output primary extension if status == 0: hdu0 = pyfits.PrimaryHDU() for i in range(len(cards0)): if cards0[i].keyword not in list(hdu0.header.keys()): hdu0.header[cards0[i].keyword] = (cards0[i].value, cards0[i].comment) else: hdu0.header.cards[ cards0[i].keyword].comment = cards0[i].comment status = kepkey.history(call, hdu0, outfile, logfile, verbose) outstr = HDUList(hdu0) # construct output light curve extension if status == 0: col1 = Column(name='TIME', format='D', unit='BJD - 2454833', array=time) col2 = Column(name='TIMECORR', format='E', unit='d', array=timecorr) col3 = Column(name='CADENCENO', format='J', array=cadenceno) col4 = Column(name='SAP_FLUX', format='E', unit='e-/s', array=pixseriessum) col5 = Column(name='SAP_FLUX_ERR', format='E', unit='e-/s', array=sap_flux_err) col6 = Column(name='SAP_BKG', format='E', unit='e-/s', array=sap_bkg) col7 = Column(name='SAP_BKG_ERR', format='E', unit='e-/s', array=sap_bkg_err) col8 = Column(name='PDCSAP_FLUX', format='E', unit='e-/s', array=pdc_flux) col9 = Column(name='PDCSAP_FLUX_ERR', format='E', unit='e-/s', array=pdc_flux_err) col10 = Column(name='SAP_QUALITY', format='J', array=quality) col11 = Column(name='PSF_CENTR1', format='E', unit='pixel', array=psf_centr1) col12 = Column(name='PSF_CENTR1_ERR', format='E', unit='pixel', array=psf_centr1_err) col13 = Column(name='PSF_CENTR2', format='E', unit='pixel', array=psf_centr2) col14 = Column(name='PSF_CENTR2_ERR', format='E', unit='pixel', array=psf_centr2_err) col15 = Column(name='MOM_CENTR1', format='E', unit='pixel', array=mom_centr1) col16 = Column(name='MOM_CENTR1_ERR', format='E', unit='pixel', array=mom_centr1_err) col17 = Column(name='MOM_CENTR2', format='E', unit='pixel', array=mom_centr2) col18 = Column(name='MOM_CENTR2_ERR', format='E', unit='pixel', array=mom_centr2_err) col19 = Column(name='POS_CORR1', format='E', unit='pixel', array=pos_corr1) col20 = Column(name='POS_CORR2', format='E', unit='pixel', array=pos_corr2) col21 = Column(name='PCA_FLUX', format='E', unit='e-/s', array=fluxcor) col22 = Column(name='PCA_FLUX_NRM', format='E', array=normfluxcor) cols = ColDefs([col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11, \ col12,col13,col14,col15,col16,col17,col18,col19,col20,col21,col22]) hdu1 = new_table(cols) hdu1.header['TTYPE1'] = ('TIME', 'column title: data time stamps') hdu1.header['TFORM1'] = ('D', 'data type: float64') hdu1.header['TUNIT1'] = ('BJD - 2454833', 'column units: barycenter corrected JD') hdu1.header['TDISP1'] = ('D12.7', 'column display format') hdu1.header['TTYPE2'] = ( 'TIMECORR', 'column title: barycentric-timeslice correction') hdu1.header['TFORM2'] = ('E', 'data type: float32') hdu1.header['TUNIT2'] = ('d', 'column units: days') hdu1.header['TTYPE3'] = ('CADENCENO', 'column title: unique cadence number') hdu1.header['TFORM3'] = ('J', 'column format: signed integer32') hdu1.header['TTYPE4'] = ('SAP_FLUX', 'column title: aperture photometry flux') hdu1.header['TFORM4'] = ('E', 'column format: float32') hdu1.header['TUNIT4'] = ('e-/s', 'column units: electrons per second') hdu1.header['TTYPE5'] = ('SAP_FLUX_ERR', 'column title: aperture phot. flux error') hdu1.header['TFORM5'] = ('E', 'column format: float32') hdu1.header['TUNIT5'] = ( 'e-/s', 'column units: electrons per second (1-sigma)') hdu1.header['TTYPE6'] = ( 'SAP_BKG', 'column title: aperture phot. background flux') hdu1.header['TFORM6'] = ('E', 'column format: float32') hdu1.header['TUNIT6'] = ('e-/s', 'column units: electrons per second') hdu1.header['TTYPE7'] = ( 'SAP_BKG_ERR', 'column title: ap. phot. background flux error') hdu1.header['TFORM7'] = ('E', 'column format: float32') hdu1.header['TUNIT7'] = ( 'e-/s', 'column units: electrons per second (1-sigma)') hdu1.header['TTYPE8'] = ('PDCSAP_FLUX', 'column title: PDC photometry flux') hdu1.header['TFORM8'] = ('E', 'column format: float32') hdu1.header['TUNIT8'] = ('e-/s', 'column units: electrons per second') hdu1.header['TTYPE9'] = ('PDCSAP_FLUX_ERR', 'column title: PDC flux error') hdu1.header['TFORM9'] = ('E', 'column format: float32') hdu1.header['TUNIT9'] = ( 'e-/s', 'column units: electrons per second (1-sigma)') hdu1.header['TTYPE10'] = ( 'SAP_QUALITY', 'column title: aperture photometry quality flag') hdu1.header['TFORM10'] = ('J', 'column format: signed integer32') hdu1.header['TTYPE11'] = ('PSF_CENTR1', 'column title: PSF fitted column centroid') hdu1.header['TFORM11'] = ('E', 'column format: float32') hdu1.header['TUNIT11'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE12'] = ('PSF_CENTR1_ERR', 'column title: PSF fitted column error') hdu1.header['TFORM12'] = ('E', 'column format: float32') hdu1.header['TUNIT12'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE13'] = ('PSF_CENTR2', 'column title: PSF fitted row centroid') hdu1.header['TFORM13'] = ('E', 'column format: float32') hdu1.header['TUNIT13'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE14'] = ('PSF_CENTR2_ERR', 'column title: PSF fitted row error') hdu1.header['TFORM14'] = ('E', 'column format: float32') hdu1.header['TUNIT14'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE15'] = ( 'MOM_CENTR1', 'column title: moment-derived column centroid') hdu1.header['TFORM15'] = ('E', 'column format: float32') hdu1.header['TUNIT15'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE16'] = ('MOM_CENTR1_ERR', 'column title: moment-derived column error') hdu1.header['TFORM16'] = ('E', 'column format: float32') hdu1.header['TUNIT16'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE17'] = ('MOM_CENTR2', 'column title: moment-derived row centroid') hdu1.header['TFORM17'] = ('E', 'column format: float32') hdu1.header['TUNIT17'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE18'] = ('MOM_CENTR2_ERR', 'column title: moment-derived row error') hdu1.header['TFORM18'] = ('E', 'column format: float32') hdu1.header['TUNIT18'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE19'] = ( 'POS_CORR1', 'column title: col correction for vel. abbern') hdu1.header['TFORM19'] = ('E', 'column format: float32') hdu1.header['TUNIT19'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE20'] = ( 'POS_CORR2', 'column title: row correction for vel. abbern') hdu1.header['TFORM20'] = ('E', 'column format: float32') hdu1.header['TUNIT20'] = ('pixel', 'column units: pixel') hdu1.header['TTYPE21'] = ('PCA_FLUX', 'column title: PCA-corrected flux') hdu1.header['TFORM21'] = ('E', 'column format: float32') hdu1.header['TUNIT21'] = ('pixel', 'column units: e-/s') hdu1.header['TTYPE22'] = ( 'PCA_FLUX_NRM', 'column title: normalized PCA-corrected flux') hdu1.header['TFORM22'] = ('E', 'column format: float32') hdu1.header['EXTNAME'] = ('LIGHTCURVE', 'name of extension') for i in range(len(cards1)): if (cards1[i].keyword not in list(hdu1.header.keys()) and cards1[i].keyword[:4] not in [ 'TTYP', 'TFOR', 'TUNI', 'TDIS', 'TDIM', 'WCAX', '1CTY', '2CTY', '1CRP', '2CRP', '1CRV', '2CRV', '1CUN', '2CUN', '1CDE', '2CDE', '1CTY', '2CTY', '1CDL', '2CDL', '11PC', '12PC', '21PC', '22PC' ]): hdu1.header[cards1[i].keyword] = (cards1[i].value, cards1[i].comment) outstr.append(hdu1) # construct output mask bitmap extension if status == 0: hdu2 = ImageHDU(maskmap) for i in range(len(cards2)): if cards2[i].keyword not in list(hdu2.header.keys()): hdu2.header[cards2[i].keyword] = (cards2[i].value, cards2[i].comment) else: hdu2.header.cards[ cards2[i].keyword].comment = cards2[i].comment outstr.append(hdu2) # construct principal component table if status == 0: cols = [ Column(name='TIME', format='E', unit='BJD - 2454833', array=time) ] for i in range(len(pcar[0, :])): colname = 'PC' + str(i + 1) col = Column(name=colname, format='E', array=pcar[:, i]) cols.append(col) hdu3 = new_table(ColDefs(cols)) hdu3.header['EXTNAME'] = ('PRINCIPAL_COMPONENTS', 'name of extension') hdu3.header['TTYPE1'] = ('TIME', 'column title: data time stamps') hdu3.header['TFORM1'] = ('D', 'data type: float64') hdu3.header['TUNIT1'] = ('BJD - 2454833', 'column units: barycenter corrected JD') hdu3.header['TDISP1'] = ('D12.7', 'column display format') for i in range(len(pcar[0, :])): hdu3.header['TTYPE' + str(i + 2)] = \ ('PC' + str(i + 1), 'column title: principal component number' + str(i + 1)) hdu3.header['TFORM' + str(i + 2)] = ('E', 'column format: float32') outstr.append(hdu3) # write output file if status == 0: outstr.writeto(outfile) # close input structure if status == 0: status = kepio.closefits(instr, logfile, verbose) # Create PCA report if status == 0 and plotpca: npp = 7 # Number of plots per page l = 1 repcnt = 1 for k in range(nreps): # First plot of every pagewith flux image, flux and calibrated time series status = kepplot.define(16, 12, logfile, verbose) if (k % (npp - 1) == 0): pylab.figure(figsize=[10, 16]) subplot2grid((npp, 6), (0, 0), colspan=2) # imshow(log10(pixMean.reshape(xdim,ydim).T-min(pixMean)+1),interpolation="nearest",cmap='RdYlBu') imshow(log10( flipud(pixMean.reshape(ydim, xdim)) - min(pixMean) + 1), interpolation="nearest", cmap='RdYlBu') xticks([]) yticks([]) ax1 = subplot2grid((npp, 6), (0, 2), colspan=4) px = copy(time) + bjdref py = copy(pixseriessum) px, xlab, status = kepplot.cleanx(px, logfile, verbose) py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) kepplot.RangeOfPlot(px, py, 0.01, False) kepplot.plot1d(px, py, cadence, lcolor, lwidth, fcolor, falpha, True) py = copy(fluxcor) py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) plot(px, py, marker='.', color='r', linestyle='', markersize=1.0) kepplot.labels('', re.sub('\)', '', re.sub('Flux \(', '', ylab)), 'k', 18) grid() setp(ax1.get_xticklabels(), visible=False) # plot principal components subplot2grid((npp, 6), (l, 0), colspan=2) imshow(eigvec[k], interpolation="nearest", cmap='RdYlBu') xlim(-0.5, xdim - 0.5) ylim(-0.5, ydim - 0.5) xticks([]) yticks([]) # The last plot on the page that should have the xlabel if (k % (npp - 1) == npp - 2 or k == nvecin - 1): subplot2grid((npp, 6), (l, 2), colspan=4) py = copy(model[:, k]) kepplot.RangeOfPlot(px, py, 0.01, False) kepplot.plot1d(px, py, cadence, 'r', lwidth, 'g', falpha, True) kepplot.labels(xlab, 'PC ' + str(k + 1), 'k', 18) pylab.grid() pylab.tight_layout() l = 1 pylab.savefig(re.sub('.png', '_%d.png' % repcnt, repname)) if not cmdLine: kepplot.render(cmdLine) repcnt += 1 # The other plots on the page that should have no xlabel else: ax2 = subplot2grid((npp, 6), (l, 2), colspan=4) py = copy(model[:, k]) kepplot.RangeOfPlot(px, py, 0.01, False) kepplot.plot1d(px, py, cadence, 'r', lwidth, 'g', falpha, True) kepplot.labels('', 'PC ' + str(k + 1), 'k', 18) grid() setp(ax2.get_xticklabels(), visible=False) pylab.tight_layout() l = l + 1 pylab.savefig(re.sub('.png', '_%d.png' % repcnt, repname)) if not cmdLine: kepplot.render(cmdLine) # plot style and size if status == 0 and plotpca: status = kepplot.define(labelsize, ticksize, logfile, verbose) pylab.figure(figsize=[xsize, ysize]) pylab.clf() # plot aperture photometry and PCA corrected data if status == 0 and plotpca: ax = kepplot.location([0.06, 0.54, 0.93, 0.43]) px = copy(time) + bjdref py = copy(pixseriessum) px, xlab, status = kepplot.cleanx(px, logfile, verbose) py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) kepplot.RangeOfPlot(px, py, 0.01, False) kepplot.plot1d(px, py, cadence, lcolor, lwidth, fcolor, falpha, True) py = copy(fluxcor) py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) kepplot.plot1d(px, py, cadence, 'r', 2, fcolor, 0.0, True) pylab.setp(pylab.gca(), xticklabels=[]) kepplot.labels('', ylab, 'k', 24) pylab.grid() # plot aperture photometry and PCA corrected data if status == 0 and plotpca: ax = kepplot.location([0.06, 0.09, 0.93, 0.43]) yr = array([], 'float32') npc = min([6, nrem]) for i in range(npc - 1, -1, -1): py = pcar[:, i] * c[i] py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) cl = float(i) / (float(npc)) kepplot.plot1d(px, py, cadence, [1.0 - cl, 0.0, cl], 2, fcolor, 0.0, True) yr = append(yr, py) y1 = max(yr) y2 = -min(yr) kepplot.RangeOfPlot(px, array([-y1, y1, -y2, y2]), 0.01, False) kepplot.labels(xlab, 'Principal Components', 'k', 24) pylab.grid() # save plot to file if status == 0 and plotpca: pylab.savefig(repname) # render plot if status == 0 and plotpca: kepplot.render(cmdLine) # stop time if status == 0: kepmsg.clock('KEPPCA ended at', logfile, verbose) return
def keppca(infile,maskfile,outfile,components,plotpca,nreps,clobber,verbose,logfile,status,cmdLine=False): try: import mdp except: msg = 'ERROR -- KEPPCA: this task has an external python dependency to MDP, a Modular toolkit for Data Processing (http://mdp-toolkit.sourceforge.net). In order to take advantage of this PCA task, the user must first install MDP with their current python distribution. Note carefully that you may have more than python installation on your machine, and ensure that MDP is installed with the same version of python that the PyKE tools employ. Installation instructions for MDP can be found at the URL provided above.' status = kepmsg.err(None,msg,True) # startup parameters status = 0 labelsize = 32 ticksize = 18 xsize = 16 ysize = 10 lcolor = '#0000ff' lwidth = 1.0 fcolor = '#ffff00' falpha = 0.2 seterr(all="ignore") # log the call if status == 0: hashline = '----------------------------------------------------------------------------' kepmsg.log(logfile,hashline,verbose) call = 'KEPPCA -- ' call += 'infile='+infile+' ' call += 'maskfile='+maskfile+' ' call += 'outfile='+outfile+' ' call += 'components='+components+' ' ppca = 'n' if (plotpca): ppca = 'y' call += 'plotpca='+ppca+ ' ' call += 'nmaps='+str(nreps)+' ' overwrite = 'n' if (clobber): overwrite = 'y' call += 'clobber='+overwrite+ ' ' chatter = 'n' if (verbose): chatter = 'y' call += 'verbose='+chatter+' ' call += 'logfile='+logfile kepmsg.log(logfile,call+'\n',verbose) # start time if status == 0: kepmsg.clock('KEPPCA started at',logfile,verbose) # test log file if status == 0: logfile = kepmsg.test(logfile) # clobber output file if status == 0: if clobber: status = kepio.clobber(outfile,logfile,verbose) if kepio.fileexists(outfile): message = 'ERROR -- KEPPCA: ' + outfile + ' exists. Use clobber=yes' status = kepmsg.err(logfile,message,verbose) # Set output file names - text file with data and plot if status == 0: dataout = copy(outfile) repname = re.sub('.fits','.png',outfile) # open input file if status == 0: instr = pyfits.open(infile,mode='readonly',memmap=True) tstart, tstop, bjdref, cadence, status = kepio.timekeys(instr,infile,logfile,verbose,status) # open TPF FITS file if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, barytime, status = \ kepio.readTPF(infile,'TIME',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, tcorr, status = \ kepio.readTPF(infile,'TIMECORR',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, cadno, status = \ kepio.readTPF(infile,'CADENCENO',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, fluxpixels, status = \ kepio.readTPF(infile,'FLUX',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, errpixels, status = \ kepio.readTPF(infile,'FLUX_ERR',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, flux_bkg, status = \ kepio.readTPF(infile,'FLUX_BKG',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, flux_bkg_err, status = \ kepio.readTPF(infile,'FLUX_BKG_ERR',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, qual, status = \ kepio.readTPF(infile,'QUALITY',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, pcorr1, status = \ kepio.readTPF(infile,'POS_CORR1',logfile,verbose) if status == 0: kepid, channel, skygroup, module, output, quarter, season, \ ra, dec, column, row, kepmag, xdim, ydim, pcorr2, status = \ kepio.readTPF(infile,'POS_CORR2',logfile,verbose) # Save original data dimensions, in case of using maskfile if status == 0: xdimorig = xdim ydimorig = ydim # read mask definition file if it has been supplied if status == 0 and 'aper' not in maskfile.lower() and maskfile.lower() != 'all': maskx = array([],'int') masky = array([],'int') lines, status = kepio.openascii(maskfile,'r',logfile,verbose) for line in lines: line = line.strip().split('|') if len(line) == 6: y0 = int(line[3]) x0 = int(line[4]) line = line[5].split(';') for items in line: try: masky = numpy.append(masky,y0 + int(items.split(',')[0])) maskx = numpy.append(maskx,x0 + int(items.split(',')[1])) except: continue status = kepio.closeascii(lines,logfile,verbose) if len(maskx) == 0 or len(masky) == 0: message = 'ERROR -- KEPPCA: ' + maskfile + ' contains no pixels.' status = kepmsg.err(logfile,message,verbose) xdim = max(maskx) - min(maskx) + 1 # Find largest x dimension of mask ydim = max(masky) - min(masky) + 1 # Find largest y dimension of mask # pad mask to ensure it is rectangular workx = array([],'int') worky = array([],'int') for ip in arange(min(maskx),max(maskx) + 1): for jp in arange(min(masky),max(masky) + 1): workx = append(workx,ip) worky = append(worky,jp) maskx = workx masky = worky # define new subimage bitmap... if status == 0 and maskfile.lower() != 'all': aperx = numpy.array([],'int') apery = numpy.array([],'int') aperb = maskx - x0 + xdimorig * (masky - y0) # aperb is an array that contains the pixel numbers in the mask npix = len(aperb) # ...or use all pixels if status == 0 and maskfile.lower() == 'all': npix = xdimorig*ydimorig aperb = array([],'int') aperb = numpy.r_[0:npix] # legal mask defined? if status == 0: if len(aperb) == 0: message = 'ERROR -- KEPPCA: no legal pixels within the subimage are defined.' status = kepmsg.err(logfile,message,verbose) # Identify principal components desired if status == 0: pcaout = [] txt = components.strip().split(',') for work1 in txt: try: pcaout.append(int(work1.strip())) except: work2 = work1.strip().split('-') try: for work3 in range(int(work2[0]),int(work2[1]) + 1): pcaout.append(work3) except: message = 'ERROR -- KEPPCA: cannot understand principal component list requested' status = kepmsg.err(logfile,message,verbose) if status == 0: pcaout = set(sort(pcaout)) pcarem = array(list(pcaout))-1 # The list of pca component numbers to be removed # Initialize arrays and variables, and apply pixel mask to the data if status == 0: ntim = 0 time = numpy.array([],dtype='float64') timecorr = numpy.array([],dtype='float32') cadenceno = numpy.array([],dtype='int') pixseries = numpy.array([],dtype='float32') errseries = numpy.array([],dtype='float32') bkgseries = numpy.array([],dtype='float32') berseries = numpy.array([],dtype='float32') quality = numpy.array([],dtype='float32') pos_corr1 = numpy.array([],dtype='float32') pos_corr2 = numpy.array([],dtype='float32') nrows = numpy.size(fluxpixels,0) # Apply the pixel mask so we are left with only the desired pixels if status == 0: pixseriesb = fluxpixels[:,aperb] errseriesb = errpixels[:,aperb] bkgseriesb = flux_bkg[:,aperb] berseriesb = flux_bkg_err[:,aperb] # Read in the data to various arrays if status == 0: for i in range(nrows): if qual[i] < 10000 and \ numpy.isfinite(barytime[i]) and \ numpy.isfinite(fluxpixels[i,int(ydim*xdim/2+0.5)]) and \ numpy.isfinite(fluxpixels[i,1+int(ydim*xdim/2+0.5)]): ntim += 1 time = numpy.append(time,barytime[i]) timecorr = numpy.append(timecorr,tcorr[i]) cadenceno = numpy.append(cadenceno,cadno[i]) pixseries = numpy.append(pixseries,pixseriesb[i]) errseries = numpy.append(errseries,errseriesb[i]) bkgseries = numpy.append(bkgseries,bkgseriesb[i]) berseries = numpy.append(berseries,berseriesb[i]) quality = numpy.append(quality,qual[i]) pos_corr1 = numpy.append(pos_corr1,pcorr1[i]) pos_corr2 = numpy.append(pos_corr2,pcorr2[i]) pixseries = numpy.reshape(pixseries,(ntim,npix)) errseries = numpy.reshape(errseries,(ntim,npix)) bkgseries = numpy.reshape(bkgseries,(ntim,npix)) berseries = numpy.reshape(berseries,(ntim,npix)) tmp = numpy.median(pixseries,axis=1) for i in range(len(tmp)): pixseries[i] = pixseries[i] - tmp[i] # Figure out which pixels are undefined/nan and remove them. Keep track for adding back in later if status == 0: nanpixels = numpy.array([],dtype='int') i = 0 while (i < npix): if numpy.isnan(pixseries[0,i]): nanpixels = numpy.append(nanpixels,i) npix = npix - 1 i = i + 1 pixseries = numpy.delete(pixseries,nanpixels,1) errseries = numpy.delete(errseries,nanpixels,1) pixseries[numpy.isnan(pixseries)] = random.gauss(100,10) errseries[numpy.isnan(errseries)] = 10 # Compute statistical weights, means, standard deviations if status == 0: weightseries = (pixseries/errseries)**2 pixMean = numpy.average(pixseries,axis=0,weights=weightseries) pixStd = numpy.std(pixseries,axis=0) # Normalize the input by subtracting the mean and divising by the standard deviation. # This makes it a correlation-based PCA, which is what we want. if status == 0: pixseriesnorm = (pixseries - pixMean)/pixStd # Number of principal components to compute. Setting it equal to the number of pixels if status == 0: nvecin = npix # Run PCA using the MDP Whitening PCA, which produces normalized PCA components (zero mean and unit variance) if status == 0: pcan = mdp.nodes.WhiteningNode(svd=True) pcar = pcan.execute(pixseriesnorm) eigvec = pcan.get_recmatrix() model = pcar # Re-insert nan columns as zeros if status == 0: for i in range(0,len(nanpixels)): nanpixels[i] = nanpixels[i]-i eigvec = numpy.insert(eigvec,nanpixels,0,1) pixMean = numpy.insert(pixMean,nanpixels,0,0) # Make output eigenvectors (correlation images) into xpix by ypix images if status == 0: eigvec = eigvec.reshape(nvecin,ydim,xdim) # Calculate sum of all pixels to display as raw lightcurve and other quantities if status == 0: pixseriessum = sum(pixseries,axis=1) nrem=len(pcarem) # Number of components to remove nplot = npix # Number of pcas to plot - currently set to plot all components, but could set # nplot = nrem to just plot as many components as is being removed # Subtract components by fitting them to the summed light curve if status == 0: x0 = numpy.tile(-1.0,1) for k in range(0,nrem): def f(x): fluxcor = pixseriessum for k in range(0,len(x)): fluxcor = fluxcor - x[k]*model[:,pcarem[k]] return mad(fluxcor) if k==0: x0 = array([-1.0]) else: x0 = numpy.append(x0,1.0) myfit = scipy.optimize.fmin(f,x0,maxiter=50000,maxfun=50000,disp=False) x0 = myfit # Now that coefficients for all components have been found, subtract them to produce a calibrated time-series, # and then divide by the robust mean to produce a normalized time series as well if status == 0: c = myfit fluxcor = pixseriessum for k in range(0,nrem): fluxcor = fluxcor - c[k]*model[:,pcarem[k]] normfluxcor = fluxcor/mean(reject_outliers(fluxcor,2)) # input file data if status == 0: cards0 = instr[0].header.cards cards1 = instr[1].header.cards cards2 = instr[2].header.cards table = instr[1].data[:] maskmap = copy(instr[2].data) # subimage physical WCS data if status == 0: crpix1p = cards2['CRPIX1P'].value crpix2p = cards2['CRPIX2P'].value crval1p = cards2['CRVAL1P'].value crval2p = cards2['CRVAL2P'].value cdelt1p = cards2['CDELT1P'].value cdelt2p = cards2['CDELT2P'].value # dummy columns for output file if status == 0: sap_flux_err = numpy.empty(len(time)); sap_flux_err[:] = numpy.nan sap_bkg = numpy.empty(len(time)); sap_bkg[:] = numpy.nan sap_bkg_err = numpy.empty(len(time)); sap_bkg_err[:] = numpy.nan pdc_flux = numpy.empty(len(time)); pdc_flux[:] = numpy.nan pdc_flux_err = numpy.empty(len(time)); pdc_flux_err[:] = numpy.nan psf_centr1 = numpy.empty(len(time)); psf_centr1[:] = numpy.nan psf_centr1_err = numpy.empty(len(time)); psf_centr1_err[:] = numpy.nan psf_centr2 = numpy.empty(len(time)); psf_centr2[:] = numpy.nan psf_centr2_err = numpy.empty(len(time)); psf_centr2_err[:] = numpy.nan mom_centr1 = numpy.empty(len(time)); mom_centr1[:] = numpy.nan mom_centr1_err = numpy.empty(len(time)); mom_centr1_err[:] = numpy.nan mom_centr2 = numpy.empty(len(time)); mom_centr2[:] = numpy.nan mom_centr2_err = numpy.empty(len(time)); mom_centr2_err[:] = numpy.nan # mask bitmap if status == 0 and 'aper' not in maskfile.lower() and maskfile.lower() != 'all': for i in range(maskmap.shape[0]): for j in range(maskmap.shape[1]): aperx = append(aperx,crval1p + (j + 1 - crpix1p) * cdelt1p) apery = append(apery,crval2p + (i + 1 - crpix2p) * cdelt2p) if maskmap[i,j] == 0: pass else: maskmap[i,j] = 1 for k in range(len(maskx)): if aperx[-1] == maskx[k] and apery[-1] == masky[k]: maskmap[i,j] = 3 # construct output primary extension if status == 0: hdu0 = pyfits.PrimaryHDU() for i in range(len(cards0)): if cards0[i].keyword not in hdu0.header.keys(): hdu0.header[cards0[i].keyword] = (cards0[i].value, cards0[i].comment) else: hdu0.header.cards[cards0[i].keyword].comment = cards0[i].comment status = kepkey.history(call,hdu0,outfile,logfile,verbose) outstr = HDUList(hdu0) # construct output light curve extension if status == 0: col1 = Column(name='TIME',format='D',unit='BJD - 2454833',array=time) col2 = Column(name='TIMECORR',format='E',unit='d',array=timecorr) col3 = Column(name='CADENCENO',format='J',array=cadenceno) col4 = Column(name='SAP_FLUX',format='E',unit='e-/s',array=pixseriessum) col5 = Column(name='SAP_FLUX_ERR',format='E',unit='e-/s',array=sap_flux_err) col6 = Column(name='SAP_BKG',format='E',unit='e-/s',array=sap_bkg) col7 = Column(name='SAP_BKG_ERR',format='E',unit='e-/s',array=sap_bkg_err) col8 = Column(name='PDCSAP_FLUX',format='E',unit='e-/s',array=pdc_flux) col9 = Column(name='PDCSAP_FLUX_ERR',format='E',unit='e-/s',array=pdc_flux_err) col10 = Column(name='SAP_QUALITY',format='J',array=quality) col11 = Column(name='PSF_CENTR1',format='E',unit='pixel',array=psf_centr1) col12 = Column(name='PSF_CENTR1_ERR',format='E',unit='pixel',array=psf_centr1_err) col13 = Column(name='PSF_CENTR2',format='E',unit='pixel',array=psf_centr2) col14 = Column(name='PSF_CENTR2_ERR',format='E',unit='pixel',array=psf_centr2_err) col15 = Column(name='MOM_CENTR1',format='E',unit='pixel',array=mom_centr1) col16 = Column(name='MOM_CENTR1_ERR',format='E',unit='pixel',array=mom_centr1_err) col17 = Column(name='MOM_CENTR2',format='E',unit='pixel',array=mom_centr2) col18 = Column(name='MOM_CENTR2_ERR',format='E',unit='pixel',array=mom_centr2_err) col19 = Column(name='POS_CORR1',format='E',unit='pixel',array=pos_corr1) col20 = Column(name='POS_CORR2',format='E',unit='pixel',array=pos_corr2) col21 = Column(name='PCA_FLUX',format='E',unit='e-/s',array=fluxcor) col22 = Column(name='PCA_FLUX_NRM',format='E',array=normfluxcor) cols = ColDefs([col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11, \ col12,col13,col14,col15,col16,col17,col18,col19,col20,col21,col22]) hdu1 = new_table(cols) hdu1.header['TTYPE1'] = ('TIME','column title: data time stamps') hdu1.header['TFORM1'] = ('D','data type: float64') hdu1.header['TUNIT1'] = ('BJD - 2454833','column units: barycenter corrected JD') hdu1.header['TDISP1'] = ('D12.7','column display format') hdu1.header['TTYPE2'] = ('TIMECORR','column title: barycentric-timeslice correction') hdu1.header['TFORM2'] = ('E','data type: float32') hdu1.header['TUNIT2'] = ('d','column units: days') hdu1.header['TTYPE3'] = ('CADENCENO','column title: unique cadence number') hdu1.header['TFORM3'] = ('J','column format: signed integer32') hdu1.header['TTYPE4'] = ('SAP_FLUX','column title: aperture photometry flux') hdu1.header['TFORM4'] = ('E','column format: float32') hdu1.header['TUNIT4'] = ('e-/s','column units: electrons per second') hdu1.header['TTYPE5'] = ('SAP_FLUX_ERR','column title: aperture phot. flux error') hdu1.header['TFORM5'] = ('E','column format: float32') hdu1.header['TUNIT5'] = ('e-/s','column units: electrons per second (1-sigma)') hdu1.header['TTYPE6'] = ('SAP_BKG','column title: aperture phot. background flux') hdu1.header['TFORM6'] = ('E','column format: float32') hdu1.header['TUNIT6'] = ('e-/s','column units: electrons per second') hdu1.header['TTYPE7'] = ('SAP_BKG_ERR','column title: ap. phot. background flux error') hdu1.header['TFORM7'] = ('E','column format: float32') hdu1.header['TUNIT7'] = ('e-/s','column units: electrons per second (1-sigma)') hdu1.header['TTYPE8'] = ('PDCSAP_FLUX','column title: PDC photometry flux') hdu1.header['TFORM8'] = ('E','column format: float32') hdu1.header['TUNIT8'] = ('e-/s','column units: electrons per second') hdu1.header['TTYPE9'] = ('PDCSAP_FLUX_ERR','column title: PDC flux error') hdu1.header['TFORM9'] = ('E','column format: float32') hdu1.header['TUNIT9'] = ('e-/s','column units: electrons per second (1-sigma)') hdu1.header['TTYPE10'] = ('SAP_QUALITY','column title: aperture photometry quality flag') hdu1.header['TFORM10'] = ('J','column format: signed integer32') hdu1.header['TTYPE11'] = ('PSF_CENTR1','column title: PSF fitted column centroid') hdu1.header['TFORM11'] = ('E','column format: float32') hdu1.header['TUNIT11'] = ('pixel','column units: pixel') hdu1.header['TTYPE12'] = ('PSF_CENTR1_ERR','column title: PSF fitted column error') hdu1.header['TFORM12'] = ('E','column format: float32') hdu1.header['TUNIT12'] = ('pixel','column units: pixel') hdu1.header['TTYPE13'] = ('PSF_CENTR2','column title: PSF fitted row centroid') hdu1.header['TFORM13'] = ('E','column format: float32') hdu1.header['TUNIT13'] = ('pixel','column units: pixel') hdu1.header['TTYPE14'] = ('PSF_CENTR2_ERR','column title: PSF fitted row error') hdu1.header['TFORM14'] = ('E','column format: float32') hdu1.header['TUNIT14'] = ('pixel','column units: pixel') hdu1.header['TTYPE15'] = ('MOM_CENTR1','column title: moment-derived column centroid') hdu1.header['TFORM15'] = ('E','column format: float32') hdu1.header['TUNIT15'] = ('pixel','column units: pixel') hdu1.header['TTYPE16'] = ('MOM_CENTR1_ERR','column title: moment-derived column error') hdu1.header['TFORM16'] = ('E','column format: float32') hdu1.header['TUNIT16'] = ('pixel','column units: pixel') hdu1.header['TTYPE17'] = ('MOM_CENTR2','column title: moment-derived row centroid') hdu1.header['TFORM17'] = ('E','column format: float32') hdu1.header['TUNIT17'] = ('pixel','column units: pixel') hdu1.header['TTYPE18'] = ('MOM_CENTR2_ERR','column title: moment-derived row error') hdu1.header['TFORM18'] = ('E','column format: float32') hdu1.header['TUNIT18'] = ('pixel','column units: pixel') hdu1.header['TTYPE19'] = ('POS_CORR1','column title: col correction for vel. abbern') hdu1.header['TFORM19'] = ('E','column format: float32') hdu1.header['TUNIT19'] = ('pixel','column units: pixel') hdu1.header['TTYPE20'] = ('POS_CORR2','column title: row correction for vel. abbern') hdu1.header['TFORM20'] = ('E','column format: float32') hdu1.header['TUNIT20'] = ('pixel','column units: pixel') hdu1.header['TTYPE21'] = ('PCA_FLUX','column title: PCA-corrected flux') hdu1.header['TFORM21'] = ('E','column format: float32') hdu1.header['TUNIT21'] = ('pixel','column units: e-/s') hdu1.header['TTYPE22'] = ('PCA_FLUX_NRM','column title: normalized PCA-corrected flux') hdu1.header['TFORM22'] = ('E','column format: float32') hdu1.header['EXTNAME'] = ('LIGHTCURVE','name of extension') for i in range(len(cards1)): if (cards1[i].keyword not in hdu1.header.keys() and cards1[i].keyword[:4] not in ['TTYP','TFOR','TUNI','TDIS','TDIM','WCAX','1CTY', '2CTY','1CRP','2CRP','1CRV','2CRV','1CUN','2CUN', '1CDE','2CDE','1CTY','2CTY','1CDL','2CDL','11PC', '12PC','21PC','22PC']): hdu1.header[cards1[i].keyword] = (cards1[i].value, cards1[i].comment) outstr.append(hdu1) # construct output mask bitmap extension if status == 0: hdu2 = ImageHDU(maskmap) for i in range(len(cards2)): if cards2[i].keyword not in hdu2.header.keys(): hdu2.header[cards2[i].keyword] = (cards2[i].value, cards2[i].comment) else: hdu2.header.cards[cards2[i].keyword].comment = cards2[i].comment outstr.append(hdu2) # construct principal component table if status == 0: cols = [Column(name='TIME',format='E',unit='BJD - 2454833',array=time)] for i in range(len(pcar[0,:])): colname = 'PC' + str(i + 1) col = Column(name=colname,format='E',array=pcar[:,i]) cols.append(col) hdu3 = new_table(ColDefs(cols)) hdu3.header['EXTNAME'] = ('PRINCIPAL_COMPONENTS','name of extension') hdu3.header['TTYPE1'] = ('TIME','column title: data time stamps') hdu3.header['TFORM1'] = ('D','data type: float64') hdu3.header['TUNIT1'] = ('BJD - 2454833','column units: barycenter corrected JD') hdu3.header['TDISP1'] = ('D12.7','column display format') for i in range(len(pcar[0,:])): hdu3.header['TTYPE' + str(i + 2)] = \ ('PC' + str(i + 1), 'column title: principal component number' + str(i + 1)) hdu3.header['TFORM' + str(i + 2)] = ('E','column format: float32') outstr.append(hdu3) # write output file if status == 0: outstr.writeto(outfile) # close input structure if status == 0: status = kepio.closefits(instr,logfile,verbose) # Create PCA report if status == 0 and plotpca: npp = 7 # Number of plots per page l = 1 repcnt = 1 for k in range(nreps): # First plot of every pagewith flux image, flux and calibrated time series status = kepplot.define(16,12,logfile,verbose) if (k % (npp - 1) == 0): pylab.figure(figsize=[10,16]) subplot2grid((npp,6),(0,0), colspan=2) # imshow(log10(pixMean.reshape(xdim,ydim).T-min(pixMean)+1),interpolation="nearest",cmap='RdYlBu') imshow(log10(flipud(pixMean.reshape(ydim,xdim))-min(pixMean)+1),interpolation="nearest",cmap='RdYlBu') xticks([]) yticks([]) ax1 = subplot2grid((npp,6),(0,2), colspan=4) px = copy(time) + bjdref py = copy(pixseriessum) px, xlab, status = kepplot.cleanx(px,logfile,verbose) py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) kepplot.RangeOfPlot(px,py,0.01,False) kepplot.plot1d(px,py,cadence,lcolor,lwidth,fcolor,falpha,True) py = copy(fluxcor) py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) plot(px,py,marker='.',color='r',linestyle='',markersize=1.0) kepplot.labels('',re.sub('\)','',re.sub('Flux \(','',ylab)),'k',18) grid() setp(ax1.get_xticklabels(), visible=False) # plot principal components subplot2grid((npp,6),(l,0), colspan=2) imshow(eigvec[k],interpolation="nearest",cmap='RdYlBu') xlim(-0.5,xdim-0.5) ylim(-0.5,ydim-0.5) xticks([]) yticks([]) # The last plot on the page that should have the xlabel if ( k% (npp - 1) == npp - 2 or k == nvecin - 1): subplot2grid((npp,6),(l,2), colspan=4) py = copy(model[:,k]) kepplot.RangeOfPlot(px,py,0.01,False) kepplot.plot1d(px,py,cadence,'r',lwidth,'g',falpha,True) kepplot.labels(xlab,'PC ' + str(k+1),'k',18) pylab.grid() pylab.tight_layout() l = 1 pylab.savefig(re.sub('.png','_%d.png' % repcnt,repname)) if not cmdLine: kepplot.render(cmdLine) repcnt += 1 # The other plots on the page that should have no xlabel else: ax2 = subplot2grid((npp,6),(l,2), colspan=4) py = copy(model[:,k]) kepplot.RangeOfPlot(px,py,0.01,False) kepplot.plot1d(px,py,cadence,'r',lwidth,'g',falpha,True) kepplot.labels('','PC ' + str(k+1),'k',18) grid() setp(ax2.get_xticklabels(), visible=False) pylab.tight_layout() l=l+1 pylab.savefig(re.sub('.png','_%d.png' % repcnt,repname)) if not cmdLine: kepplot.render(cmdLine) # plot style and size if status == 0 and plotpca: status = kepplot.define(labelsize,ticksize,logfile,verbose) pylab.figure(figsize=[xsize,ysize]) pylab.clf() # plot aperture photometry and PCA corrected data if status == 0 and plotpca: ax = kepplot.location([0.06,0.54,0.93,0.43]) px = copy(time) + bjdref py = copy(pixseriessum) px, xlab, status = kepplot.cleanx(px,logfile,verbose) py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) kepplot.RangeOfPlot(px,py,0.01,False) kepplot.plot1d(px,py,cadence,lcolor,lwidth,fcolor,falpha,True) py = copy(fluxcor) py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) kepplot.plot1d(px,py,cadence,'r',2,fcolor,0.0,True) pylab.setp(pylab.gca(),xticklabels=[]) kepplot.labels('',ylab,'k',24) pylab.grid() # plot aperture photometry and PCA corrected data if status == 0 and plotpca: ax = kepplot.location([0.06,0.09,0.93,0.43]) yr = array([],'float32') npc = min([6,nrem]) for i in range(npc-1,-1,-1): py = pcar[:,i] * c[i] py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) cl = float(i) / (float(npc)) kepplot.plot1d(px,py,cadence,[1.0-cl,0.0,cl],2,fcolor,0.0,True) yr = append(yr,py) y1 = max(yr) y2 = -min(yr) kepplot.RangeOfPlot(px,array([-y1,y1,-y2,y2]),0.01,False) kepplot.labels(xlab,'Principal Components','k',24) pylab.grid() # save plot to file if status == 0 and plotpca: pylab.savefig(repname) # render plot if status == 0 and plotpca: kepplot.render(cmdLine) # stop time if status == 0: kepmsg.clock('KEPPCA ended at',logfile,verbose) return
def kepsff(infile,outfile,datacol,cenmethod,stepsize,npoly_cxcy,sigma_cxcy,npoly_ardx, npoly_dsdt,sigma_dsdt,npoly_arfl,sigma_arfl,plotres,clobber,verbose,logfile, status,cmdLine=False): # startup parameters status = 0 labelsize = 16 ticksize = 14 xsize = 20 ysize = 8 lcolor = '#0000ff' lwidth = 1.0 fcolor = '#ffff00' falpha = 0.2 seterr(all="ignore") # log the call hashline = '----------------------------------------------------------------------------' kepmsg.log(logfile,hashline,verbose) call = 'KEPSFF -- ' call += 'infile='+infile+' ' call += 'outfile='+outfile+' ' call += 'datacol='+datacol+' ' call += 'cenmethod='+cenmethod+' ' call += 'stepsize='+str(stepsize)+' ' call += 'npoly_cxcy='+str(npoly_cxcy)+' ' call += 'sigma_cxcy='+str(sigma_cxcy)+' ' call += 'npoly_ardx='+str(npoly_ardx)+' ' call += 'npoly_dsdt='+str(npoly_dsdt)+' ' call += 'sigma_dsdt='+str(sigma_dsdt)+' ' call += 'npoly_arfl='+str(npoly_arfl)+' ' call += 'sigma_arfl='+str(sigma_arfl)+' ' savep = 'n' if (plotres): savep = 'y' call += 'plotres='+savep+ ' ' overwrite = 'n' if (clobber): overwrite = 'y' call += 'clobber='+overwrite+ ' ' chatter = 'n' if (verbose): chatter = 'y' call += 'verbose='+chatter+' ' call += 'logfile='+logfile kepmsg.log(logfile,call+'\n',verbose) # start time kepmsg.clock('KEPSFF started at',logfile,verbose) # test log file logfile = kepmsg.test(logfile) # clobber output file if clobber: status = kepio.clobber(outfile,logfile,verbose) if kepio.fileexists(outfile): message = 'ERROR -- KEPSFF: ' + outfile + ' exists. Use clobber=yes' status = kepmsg.err(logfile,message,verbose) # open input file if status == 0: instr, status = kepio.openfits(infile,'readonly',logfile,verbose) if status == 0: tstart, tstop, bjdref, cadence, status = kepio.timekeys(instr,infile,logfile,verbose,status) if status == 0: try: work = instr[0].header['FILEVER'] cadenom = 1.0 except: cadenom = cadence # fudge non-compliant FITS keywords with no values if status == 0: instr = kepkey.emptykeys(instr,file,logfile,verbose) # read table structure if status == 0: table, status = kepio.readfitstab(infile,instr[1],logfile,verbose) # determine sequence of windows in time if status == 0: frametim = instr[1].header['FRAMETIM'] num_frm = instr[1].header['NUM_FRM'] exptime = frametim * num_frm / 86400 tstart = table.field('TIME')[0] tstop = table.field('TIME')[-1] winedge = arange(tstart,tstop,stepsize) if tstop > winedge[-1] + stepsize / 2: winedge = append(winedge,tstop) else: winedge[-1] = tstop winedge = (winedge - tstart) / exptime winedge = winedge.astype(int) if len(table.field('TIME')) > winedge[-1] + 1: winedge = append(winedge,len(table.field('TIME'))) elif len(table.field('TIME')) < winedge[-1]: winedge[-1] = len(table.field('TIME')) # step through the time windows if status == 0: for iw in range(1,len(winedge)): t1 = winedge[iw-1] t2 = winedge[iw] # filter input data table work1 = numpy.array([table.field('TIME')[t1:t2], table.field('CADENCENO')[t1:t2], table.field(datacol)[t1:t2], table.field('MOM_CENTR1')[t1:t2], table.field('MOM_CENTR2')[t1:t2], table.field('PSF_CENTR1')[t1:t2], table.field('PSF_CENTR2')[t1:t2], table.field('SAP_QUALITY')[t1:t2]],'float64') work1 = numpy.rot90(work1,3) work2 = work1[~numpy.isnan(work1).any(1)] work2 = work2[(work2[:,0] == 0.0) | (work2[:,0] > 1e5)] # assign table columns intime = work2[:,7] + bjdref cadenceno = work2[:,6].astype(int) indata = work2[:,5] mom_centr1 = work2[:,4] mom_centr2 = work2[:,3] psf_centr1 = work2[:,2] psf_centr2 = work2[:,1] sap_quality = work2[:,0] if cenmethod == 'moments': centr1 = copy(mom_centr1) centr2 = copy(mom_centr2) else: centr1 = copy(psf_centr1) centr2 = copy(psf_centr2) # fit centroid data with low-order polynomial cfit = zeros((len(centr2))) csig = zeros((len(centr2))) functype = 'poly' + str(npoly_cxcy) pinit = array([nanmean(centr2)]) if npoly_cxcy > 0: for j in range(npoly_cxcy): pinit = append(pinit,0.0) try: coeffs, errors, covar, iiter, sigma, chi2, dof, fit, plotx, ploty, status = \ kepfit.lsqclip(functype,pinit,centr1,centr2,None,sigma_cxcy,sigma_cxcy,10,logfile,verbose) for j in range(len(coeffs)): cfit += coeffs[j] * numpy.power(centr1,j) csig[:] = sigma except: message = 'ERROR -- KEPSFF: could not fit centroid data with polynomial. There are no data points within the range of input rows %d - %d. Either increase the stepsize (with an appreciation of the effects on light curve quality this will have!), or better yet - cut the timeseries up to remove large gaps in the input light curve using kepclip.' % (t1,t2) status = kepmsg.err(logfile,message,verbose) # sys.exit('') os._exit(1) # reject outliers time_good = array([],'float64') centr1_good = array([],'float32') centr2_good = array([],'float32') flux_good = array([],'float32') cad_good = array([],'int') for i in range(len(cfit)): if abs(centr2[i] - cfit[i]) < sigma_cxcy * csig[i]: time_good = append(time_good,intime[i]) centr1_good = append(centr1_good,centr1[i]) centr2_good = append(centr2_good,centr2[i]) flux_good = append(flux_good,indata[i]) cad_good = append(cad_good,cadenceno[i]) # covariance matrix for centroid time series centr = concatenate([[centr1_good] - mean(centr1_good), [centr2_good] - mean(centr2_good)]) covar = cov(centr) # eigenvector eigenvalues of covariance matrix [eval, evec] = numpy.linalg.eigh(covar) ex = arange(-10.0,10.0,0.1) epar = evec[1,1] / evec[0,1] * ex enor = evec[1,0] / evec[0,0] * ex ex = ex + mean(centr1) epar = epar + mean(centr2_good) enor = enor + mean(centr2_good) # rotate centroid data centr_rot = dot(evec.T,centr) # fit polynomial to rotated centroids rfit = zeros((len(centr2))) rsig = zeros((len(centr2))) functype = 'poly' + str(npoly_ardx) pinit = array([nanmean(centr_rot[0,:])]) pinit = array([1.0]) if npoly_ardx > 0: for j in range(npoly_ardx): pinit = append(pinit,0.0) try: coeffs, errors, covar, iiter, sigma, chi2, dof, fit, plotx, ploty, status = \ kepfit.lsqclip(functype,pinit,centr_rot[1,:],centr_rot[0,:],None,100.0,100.0,1, logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile,message,verbose) rx = linspace(nanmin(centr_rot[1,:]),nanmax(centr_rot[1,:]),100) ry = zeros((len(rx))) for i in range(len(coeffs)): ry = ry + coeffs[i] * numpy.power(rx,i) # calculate arclength of centroids s = zeros((len(rx))) for i in range(1,len(s)): work3 = ((ry[i] - ry[i-1]) / (rx[i] - rx[i-1]))**2 s[i] = s[i-1] + math.sqrt(1.0 + work3) * (rx[i] - rx[i-1]) # fit arclength as a function of strongest eigenvector sfit = zeros((len(centr2))) ssig = zeros((len(centr2))) functype = 'poly' + str(npoly_ardx) pinit = array([nanmean(s)]) if npoly_ardx > 0: for j in range(npoly_ardx): pinit = append(pinit,0.0) try: acoeffs, errors, covar, iiter, sigma, chi2, dof, fit, plotx, ploty, status = \ kepfit.lsqclip(functype,pinit,rx,s,None,100.0,100.0,100,logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile,message,verbose) # correlate arclength with detrended flux t = copy(time_good) c = copy(cad_good) y = copy(flux_good) z = centr_rot[1,:] x = zeros((len(z))) for i in range(len(acoeffs)): x = x + acoeffs[i] * numpy.power(z,i) # calculate time derivative of arclength s dx = zeros((len(x))) for i in range(1,len(x)): dx[i] = (x[i] - x[i-1]) / (t[i] - t[i-1]) dx[0] = dx[1] # fit polynomial to derivative and flag outliers (thruster firings) dfit = zeros((len(dx))) dsig = zeros((len(dx))) functype = 'poly' + str(npoly_dsdt) pinit = array([nanmean(dx)]) if npoly_dsdt > 0: for j in range(npoly_dsdt): pinit = append(pinit,0.0) try: dcoeffs, errors, covar, iiter, dsigma, chi2, dof, fit, dumx, dumy, status = \ kepfit.lsqclip(functype,pinit,t,dx,None,3.0,3.0,10,logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile,message,verbose) for i in range(len(dcoeffs)): dfit = dfit + dcoeffs[i] * numpy.power(t,i) centr1_pnt = array([],'float32') centr2_pnt = array([],'float32') time_pnt = array([],'float64') flux_pnt = array([],'float32') dx_pnt = array([],'float32') s_pnt = array([],'float32') time_thr = array([],'float64') flux_thr = array([],'float32') dx_thr = array([],'float32') thr_cadence = [] for i in range(len(t)): if dx[i] < dfit[i] + sigma_dsdt * dsigma and dx[i] > dfit[i] - sigma_dsdt * dsigma: time_pnt = append(time_pnt,time_good[i]) flux_pnt = append(flux_pnt,flux_good[i]) dx_pnt = append(dx_pnt,dx[i]) s_pnt = append(s_pnt,x[i]) centr1_pnt = append(centr1_pnt,centr1_good[i]) centr2_pnt = append(centr2_pnt,centr2_good[i]) else: time_thr = append(time_thr,time_good[i]) flux_thr = append(flux_thr,flux_good[i]) dx_thr = append(dx_thr,dx[i]) thr_cadence.append(cad_good[i]) # fit arclength-flux correlation cfit = zeros((len(time_pnt))) csig = zeros((len(time_pnt))) functype = 'poly' + str(npoly_arfl) pinit = array([nanmean(flux_pnt)]) if npoly_arfl > 0: for j in range(npoly_arfl): pinit = append(pinit,0.0) try: ccoeffs, errors, covar, iiter, sigma, chi2, dof, fit, plx, ply, status = \ kepfit.lsqclip(functype,pinit,s_pnt,flux_pnt,None,sigma_arfl,sigma_arfl,100,logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile,message,verbose) # correction factors for unfiltered data centr = concatenate([[centr1] - mean(centr1_good), [centr2] - mean(centr2_good)]) centr_rot = dot(evec.T,centr) yy = copy(indata) zz = centr_rot[1,:] xx = zeros((len(zz))) cfac = zeros((len(zz))) for i in range(len(acoeffs)): xx = xx + acoeffs[i] * numpy.power(zz,i) for i in range(len(ccoeffs)): cfac = cfac + ccoeffs[i] * numpy.power(xx,i) # apply correction to flux time-series out_detsap = indata / cfac # split time-series data for plotting tim_gd = array([],'float32') flx_gd = array([],'float32') tim_bd = array([],'float32') flx_bd = array([],'float32') for i in range(len(indata)): if intime[i] in time_pnt: tim_gd = append(tim_gd,intime[i]) flx_gd = append(flx_gd,out_detsap[i]) else: tim_bd = append(tim_bd,intime[i]) flx_bd = append(flx_bd,out_detsap[i]) # plot style and size status = kepplot.define(labelsize,ticksize,logfile,verbose) pylab.figure(figsize=[xsize,ysize]) pylab.clf() # plot x-centroid vs y-centroid ax = kepplot.location([0.04,0.57,0.16,0.41]) # plot location px = copy(centr1) # clean-up x-axis units py = copy(centr2) # clean-up y-axis units pxmin = px.min() pxmax = px.max() pymin = py.min() pymax = py.max() pxr = pxmax - pxmin pyr = pymax - pymin pad = 0.05 if pxr > pyr: dely = (pxr - pyr) / 2 xlim(pxmin - pxr * pad, pxmax + pxr * pad) ylim(pymin - dely - pyr * pad, pymax + dely + pyr * pad) else: delx = (pyr - pxr) / 2 ylim(pymin - pyr * pad, pymax + pyr * pad) xlim(pxmin - delx - pxr * pad, pxmax + delx + pxr * pad) pylab.plot(px,py,color='#980000',markersize=5,marker='D',ls='') # plot data pylab.plot(centr1_good,centr2_good,color='#009900',markersize=5,marker='D',ls='') # plot data pylab.plot(ex,epar,color='k',ls='-') pylab.plot(ex,enor,color='k',ls='-') for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) kepplot.labels('CCD Column','CCD Row','k',16) # labels pylab.grid() # grid lines # plot arclength fits vs drift along strongest eigenvector ax = kepplot.location([0.24,0.57,0.16,0.41]) # plot location px = rx - rx[0] py = s - rx - (s[0] - rx[0]) # clean-up y-axis units py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) # clean-up x-axis units kepplot.RangeOfPlot(px,py,0.05,False) # data limits pylab.plot(px,py,color='#009900',markersize=5,marker='D',ls='') px = plotx - rx[0] # clean-up x-axis units py = ploty-plotx - (s[0] - rx[0]) # clean-up y-axis units py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) # clean-up x-axis units pylab.plot(px,py,color='r',ls='-',lw=3) for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) ylab = re.sub(' e\S+',' pixels)',ylab) ylab = re.sub(' s\S+','',ylab) ylab = re.sub('Flux','s $-$ x\'',ylab) kepplot.labels('Linear Drift [x\'] (pixels)',ylab,'k',16) # labels pylab.grid() # grid lines # plot time derivative of arclength s ax = kepplot.location([0.04,0.08,0.16,0.41]) # plot location px = copy(time_pnt) py = copy(dx_pnt) px, xlab, status = kepplot.cleanx(px,logfile,verbose) # clean-up x-axis units kepplot.RangeOfPlot(px,dx,0.05,False) # data limits pylab.plot(px,py,color='#009900',markersize=5,marker='D',ls='') try: px = copy(time_thr) py = copy(dx_thr) px, xlab, status = kepplot.cleanx(px,logfile,verbose) # clean-up x-axis units pylab.plot(px,py,color='#980000',markersize=5,marker='D',ls='') except: pass px = copy(t) py = copy(dfit) px, xlab, status = kepplot.cleanx(px,logfile,verbose) # clean-up x-axis units pylab.plot(px,py,color='r',ls='-',lw=3) py = copy(dfit+sigma_dsdt*dsigma) pylab.plot(px,py,color='r',ls='--',lw=3) py = copy(dfit-sigma_dsdt*dsigma) pylab.plot(px,py,color='r',ls='--',lw=3) for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) kepplot.labels(xlab,'ds/dt (pixels day$^{-1}$)','k',16) # labels pylab.grid() # grid lines # plot relation of arclength vs detrended flux ax = kepplot.location([0.24,0.08,0.16,0.41]) # plot location px = copy(s_pnt) py = copy(flux_pnt) py, ylab, status = kepplot.cleany(py,1.0,logfile,verbose) # clean-up x-axis units kepplot.RangeOfPlot(px,py,0.05,False) # data limits pylab.plot(px,py,color='#009900',markersize=5,marker='D',ls='') pylab.plot(plx,ply,color='r',ls='-',lw=3) for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) kepplot.labels('Arclength [s] (pixels)',ylab,'k',16) # labels pylab.grid() # grid lines # plot aperture photometry kepplot.location([0.44,0.53,0.55,0.45]) # plot location px, xlab, status = kepplot.cleanx(intime,logfile,verbose) # clean-up x-axis units py, ylab, status = kepplot.cleany(indata,1.0,logfile,verbose) # clean-up x-axis units kepplot.RangeOfPlot(px,py,0.01,True) # data limits kepplot.plot1d(px,py,cadence,lcolor,lwidth,fcolor,falpha,True) # plot data kepplot.labels(' ',ylab,'k',16) # labels pylab.setp(pylab.gca(),xticklabels=[]) # remove x- or y-tick labels kepplot.labels(xlab,re.sub('Flux','Aperture Flux',ylab),'k',16) # labels pylab.grid() # grid lines # Plot corrected photometry kepplot.location([0.44,0.08,0.55,0.45]) # plot location kepplot.RangeOfPlot(px,py,0.01,True) # data limits px, xlab, status = kepplot.cleanx(tim_gd,logfile,verbose) # clean-up x-axis units py, ylab, status = kepplot.cleany(flx_gd,1.0,logfile,verbose) # clean-up x-axis units kepplot.plot1d(px,py,cadence,lcolor,lwidth,fcolor,falpha,True) # plot data try: px, xlab, status = kepplot.cleanx(tim_bd,logfile,verbose) # clean-up x-axis units py = copy(flx_bd) pylab.plot(px,py,color='#980000',markersize=5,marker='D',ls='') except: pass kepplot.labels(xlab,re.sub('Flux','Corrected Flux',ylab),'k',16) # labels pylab.grid() # grid lines # render plot if plotres: kepplot.render(cmdLine) # save plot to file if plotres: pylab.savefig(re.sub('.fits','_%d.png' % (iw + 1),outfile)) # correct fluxes within the output file intime = work1[:,7] + bjdref cadenceno = work1[:,6].astype(int) indata = work1[:,5] mom_centr1 = work1[:,4] mom_centr2 = work1[:,3] psf_centr1 = work1[:,2] psf_centr2 = work1[:,1] centr1 = copy(mom_centr1) centr2 = copy(mom_centr2) centr = concatenate([[centr1] - mean(centr1_good), [centr2] - mean(centr2_good)]) centr_rot = dot(evec.T,centr) yy = copy(indata) zz = centr_rot[1,:] xx = zeros((len(zz))) cfac = zeros((len(zz))) for i in range(len(acoeffs)): xx = xx + acoeffs[i] * numpy.power(zz,i) for i in range(len(ccoeffs)): cfac = cfac + ccoeffs[i] * numpy.power(xx,i) out_detsap = yy / cfac instr[1].data.field('SAP_FLUX')[t1:t2] /= cfac instr[1].data.field('PDCSAP_FLUX')[t1:t2] /= cfac try: instr[1].data.field('DETSAP_FLUX')[t1:t2] /= cfac except: pass # add quality flag to output file for thruster firings for i in range(len(intime)): if cadenceno[i] in thr_cadence: instr[1].data.field('SAP_QUALITY')[t1+i] += 131072 # write output file if status == 0: instr.writeto(outfile) # close input file if status == 0: status = kepio.closefits(instr,logfile,verbose) # end time if (status == 0): message = 'KEPSFF completed at' else: message = '\nKEPSFF aborted at' kepmsg.clock(message,logfile,verbose)
def kepsff(infile, outfile, datacol, cenmethod, stepsize, npoly_cxcy, sigma_cxcy, npoly_ardx, npoly_dsdt, sigma_dsdt, npoly_arfl, sigma_arfl, plotres, clobber, verbose, logfile, status, cmdLine=False): # startup parameters status = 0 labelsize = 16 ticksize = 14 xsize = 20 ysize = 8 lcolor = '#0000ff' lwidth = 1.0 fcolor = '#ffff00' falpha = 0.2 seterr(all="ignore") # log the call hashline = '----------------------------------------------------------------------------' kepmsg.log(logfile, hashline, verbose) call = 'KEPSFF -- ' call += 'infile=' + infile + ' ' call += 'outfile=' + outfile + ' ' call += 'datacol=' + datacol + ' ' call += 'cenmethod=' + cenmethod + ' ' call += 'stepsize=' + str(stepsize) + ' ' call += 'npoly_cxcy=' + str(npoly_cxcy) + ' ' call += 'sigma_cxcy=' + str(sigma_cxcy) + ' ' call += 'npoly_ardx=' + str(npoly_ardx) + ' ' call += 'npoly_dsdt=' + str(npoly_dsdt) + ' ' call += 'sigma_dsdt=' + str(sigma_dsdt) + ' ' call += 'npoly_arfl=' + str(npoly_arfl) + ' ' call += 'sigma_arfl=' + str(sigma_arfl) + ' ' savep = 'n' if (plotres): savep = 'y' call += 'plotres=' + savep + ' ' overwrite = 'n' if (clobber): overwrite = 'y' call += 'clobber=' + overwrite + ' ' chatter = 'n' if (verbose): chatter = 'y' call += 'verbose=' + chatter + ' ' call += 'logfile=' + logfile kepmsg.log(logfile, call + '\n', verbose) # start time kepmsg.clock('KEPSFF started at', logfile, verbose) # test log file logfile = kepmsg.test(logfile) # clobber output file if clobber: status = kepio.clobber(outfile, logfile, verbose) if kepio.fileexists(outfile): message = 'ERROR -- KEPSFF: ' + outfile + ' exists. Use clobber=yes' status = kepmsg.err(logfile, message, verbose) # open input file if status == 0: instr, status = kepio.openfits(infile, 'readonly', logfile, verbose) if status == 0: tstart, tstop, bjdref, cadence, status = kepio.timekeys( instr, infile, logfile, verbose, status) if status == 0: try: work = instr[0].header['FILEVER'] cadenom = 1.0 except: cadenom = cadence # fudge non-compliant FITS keywords with no values if status == 0: instr = kepkey.emptykeys(instr, file, logfile, verbose) # read table structure if status == 0: table, status = kepio.readfitstab(infile, instr[1], logfile, verbose) # determine sequence of windows in time if status == 0: frametim = instr[1].header['FRAMETIM'] num_frm = instr[1].header['NUM_FRM'] exptime = frametim * num_frm / 86400 tstart = table.field('TIME')[0] tstop = table.field('TIME')[-1] winedge = arange(tstart, tstop, stepsize) if tstop > winedge[-1] + stepsize / 2: winedge = append(winedge, tstop) else: winedge[-1] = tstop winedge = (winedge - tstart) / exptime winedge = winedge.astype(int) if len(table.field('TIME')) > winedge[-1] + 1: winedge = append(winedge, len(table.field('TIME'))) elif len(table.field('TIME')) < winedge[-1]: winedge[-1] = len(table.field('TIME')) # step through the time windows if status == 0: for iw in range(1, len(winedge)): t1 = winedge[iw - 1] t2 = winedge[iw] # filter input data table work1 = numpy.array([ table.field('TIME')[t1:t2], table.field('CADENCENO')[t1:t2], table.field(datacol)[t1:t2], table.field('MOM_CENTR1')[t1:t2], table.field('MOM_CENTR2')[t1:t2], table.field('PSF_CENTR1')[t1:t2], table.field('PSF_CENTR2')[t1:t2], table.field('SAP_QUALITY')[t1:t2] ], 'float64') work1 = numpy.rot90(work1, 3) work2 = work1[~numpy.isnan(work1).any(1)] work2 = work2[(work2[:, 0] == 0.0) | (work2[:, 0] > 1e5)] # assign table columns intime = work2[:, 7] + bjdref cadenceno = work2[:, 6].astype(int) indata = work2[:, 5] mom_centr1 = work2[:, 4] mom_centr2 = work2[:, 3] psf_centr1 = work2[:, 2] psf_centr2 = work2[:, 1] sap_quality = work2[:, 0] if cenmethod == 'moments': centr1 = copy(mom_centr1) centr2 = copy(mom_centr2) else: centr1 = copy(psf_centr1) centr2 = copy(psf_centr2) # fit centroid data with low-order polynomial cfit = zeros((len(centr2))) csig = zeros((len(centr2))) functype = 'poly' + str(npoly_cxcy) pinit = array([nanmean(centr2)]) if npoly_cxcy > 0: for j in range(npoly_cxcy): pinit = append(pinit, 0.0) try: coeffs, errors, covar, iiter, sigma, chi2, dof, fit, plotx, ploty, status = \ kepfit.lsqclip(functype,pinit,centr1,centr2,None,sigma_cxcy,sigma_cxcy,10,logfile,verbose) for j in range(len(coeffs)): cfit += coeffs[j] * numpy.power(centr1, j) csig[:] = sigma except: message = 'ERROR -- KEPSFF: could not fit centroid data with polynomial. There are no data points within the range of input rows %d - %d. Either increase the stepsize (with an appreciation of the effects on light curve quality this will have!), or better yet - cut the timeseries up to remove large gaps in the input light curve using kepclip.' % ( t1, t2) status = kepmsg.err(logfile, message, verbose) # sys.exit('') os._exit(1) # reject outliers time_good = array([], 'float64') centr1_good = array([], 'float32') centr2_good = array([], 'float32') flux_good = array([], 'float32') cad_good = array([], 'int') for i in range(len(cfit)): if abs(centr2[i] - cfit[i]) < sigma_cxcy * csig[i]: time_good = append(time_good, intime[i]) centr1_good = append(centr1_good, centr1[i]) centr2_good = append(centr2_good, centr2[i]) flux_good = append(flux_good, indata[i]) cad_good = append(cad_good, cadenceno[i]) # covariance matrix for centroid time series centr = concatenate([[centr1_good] - mean(centr1_good), [centr2_good] - mean(centr2_good)]) covar = cov(centr) # eigenvector eigenvalues of covariance matrix [eval, evec] = numpy.linalg.eigh(covar) ex = arange(-10.0, 10.0, 0.1) epar = evec[1, 1] / evec[0, 1] * ex enor = evec[1, 0] / evec[0, 0] * ex ex = ex + mean(centr1) epar = epar + mean(centr2_good) enor = enor + mean(centr2_good) # rotate centroid data centr_rot = dot(evec.T, centr) # fit polynomial to rotated centroids rfit = zeros((len(centr2))) rsig = zeros((len(centr2))) functype = 'poly' + str(npoly_ardx) pinit = array([nanmean(centr_rot[0, :])]) pinit = array([1.0]) if npoly_ardx > 0: for j in range(npoly_ardx): pinit = append(pinit, 0.0) try: coeffs, errors, covar, iiter, sigma, chi2, dof, fit, plotx, ploty, status = \ kepfit.lsqclip(functype,pinit,centr_rot[1,:],centr_rot[0,:],None,100.0,100.0,1, logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile, message, verbose) rx = linspace(nanmin(centr_rot[1, :]), nanmax(centr_rot[1, :]), 100) ry = zeros((len(rx))) for i in range(len(coeffs)): ry = ry + coeffs[i] * numpy.power(rx, i) # calculate arclength of centroids s = zeros((len(rx))) for i in range(1, len(s)): work3 = ((ry[i] - ry[i - 1]) / (rx[i] - rx[i - 1]))**2 s[i] = s[i - 1] + math.sqrt(1.0 + work3) * (rx[i] - rx[i - 1]) # fit arclength as a function of strongest eigenvector sfit = zeros((len(centr2))) ssig = zeros((len(centr2))) functype = 'poly' + str(npoly_ardx) pinit = array([nanmean(s)]) if npoly_ardx > 0: for j in range(npoly_ardx): pinit = append(pinit, 0.0) try: acoeffs, errors, covar, iiter, sigma, chi2, dof, fit, plotx, ploty, status = \ kepfit.lsqclip(functype,pinit,rx,s,None,100.0,100.0,100,logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile, message, verbose) # correlate arclength with detrended flux t = copy(time_good) c = copy(cad_good) y = copy(flux_good) z = centr_rot[1, :] x = zeros((len(z))) for i in range(len(acoeffs)): x = x + acoeffs[i] * numpy.power(z, i) # calculate time derivative of arclength s dx = zeros((len(x))) for i in range(1, len(x)): dx[i] = (x[i] - x[i - 1]) / (t[i] - t[i - 1]) dx[0] = dx[1] # fit polynomial to derivative and flag outliers (thruster firings) dfit = zeros((len(dx))) dsig = zeros((len(dx))) functype = 'poly' + str(npoly_dsdt) pinit = array([nanmean(dx)]) if npoly_dsdt > 0: for j in range(npoly_dsdt): pinit = append(pinit, 0.0) try: dcoeffs, errors, covar, iiter, dsigma, chi2, dof, fit, dumx, dumy, status = \ kepfit.lsqclip(functype,pinit,t,dx,None,3.0,3.0,10,logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile, message, verbose) for i in range(len(dcoeffs)): dfit = dfit + dcoeffs[i] * numpy.power(t, i) centr1_pnt = array([], 'float32') centr2_pnt = array([], 'float32') time_pnt = array([], 'float64') flux_pnt = array([], 'float32') dx_pnt = array([], 'float32') s_pnt = array([], 'float32') time_thr = array([], 'float64') flux_thr = array([], 'float32') dx_thr = array([], 'float32') thr_cadence = [] for i in range(len(t)): if dx[i] < dfit[i] + sigma_dsdt * dsigma and dx[ i] > dfit[i] - sigma_dsdt * dsigma: time_pnt = append(time_pnt, time_good[i]) flux_pnt = append(flux_pnt, flux_good[i]) dx_pnt = append(dx_pnt, dx[i]) s_pnt = append(s_pnt, x[i]) centr1_pnt = append(centr1_pnt, centr1_good[i]) centr2_pnt = append(centr2_pnt, centr2_good[i]) else: time_thr = append(time_thr, time_good[i]) flux_thr = append(flux_thr, flux_good[i]) dx_thr = append(dx_thr, dx[i]) thr_cadence.append(cad_good[i]) # fit arclength-flux correlation cfit = zeros((len(time_pnt))) csig = zeros((len(time_pnt))) functype = 'poly' + str(npoly_arfl) pinit = array([nanmean(flux_pnt)]) if npoly_arfl > 0: for j in range(npoly_arfl): pinit = append(pinit, 0.0) try: ccoeffs, errors, covar, iiter, sigma, chi2, dof, fit, plx, ply, status = \ kepfit.lsqclip(functype,pinit,s_pnt,flux_pnt,None,sigma_arfl,sigma_arfl,100,logfile,verbose) except: message = 'ERROR -- KEPSFF: could not fit rotated centroid data with polynomial' status = kepmsg.err(logfile, message, verbose) # correction factors for unfiltered data centr = concatenate([[centr1] - mean(centr1_good), [centr2] - mean(centr2_good)]) centr_rot = dot(evec.T, centr) yy = copy(indata) zz = centr_rot[1, :] xx = zeros((len(zz))) cfac = zeros((len(zz))) for i in range(len(acoeffs)): xx = xx + acoeffs[i] * numpy.power(zz, i) for i in range(len(ccoeffs)): cfac = cfac + ccoeffs[i] * numpy.power(xx, i) # apply correction to flux time-series out_detsap = indata / cfac # split time-series data for plotting tim_gd = array([], 'float32') flx_gd = array([], 'float32') tim_bd = array([], 'float32') flx_bd = array([], 'float32') for i in range(len(indata)): if intime[i] in time_pnt: tim_gd = append(tim_gd, intime[i]) flx_gd = append(flx_gd, out_detsap[i]) else: tim_bd = append(tim_bd, intime[i]) flx_bd = append(flx_bd, out_detsap[i]) # plot style and size status = kepplot.define(labelsize, ticksize, logfile, verbose) pylab.figure(figsize=[xsize, ysize]) pylab.clf() # plot x-centroid vs y-centroid ax = kepplot.location([0.04, 0.57, 0.16, 0.41]) # plot location px = copy(centr1) # clean-up x-axis units py = copy(centr2) # clean-up y-axis units pxmin = px.min() pxmax = px.max() pymin = py.min() pymax = py.max() pxr = pxmax - pxmin pyr = pymax - pymin pad = 0.05 if pxr > pyr: dely = (pxr - pyr) / 2 xlim(pxmin - pxr * pad, pxmax + pxr * pad) ylim(pymin - dely - pyr * pad, pymax + dely + pyr * pad) else: delx = (pyr - pxr) / 2 ylim(pymin - pyr * pad, pymax + pyr * pad) xlim(pxmin - delx - pxr * pad, pxmax + delx + pxr * pad) pylab.plot(px, py, color='#980000', markersize=5, marker='D', ls='') # plot data pylab.plot(centr1_good, centr2_good, color='#009900', markersize=5, marker='D', ls='') # plot data pylab.plot(ex, epar, color='k', ls='-') pylab.plot(ex, enor, color='k', ls='-') for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) kepplot.labels('CCD Column', 'CCD Row', 'k', 16) # labels pylab.grid() # grid lines # plot arclength fits vs drift along strongest eigenvector ax = kepplot.location([0.24, 0.57, 0.16, 0.41]) # plot location px = rx - rx[0] py = s - rx - (s[0] - rx[0]) # clean-up y-axis units py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) # clean-up x-axis units kepplot.RangeOfPlot(px, py, 0.05, False) # data limits pylab.plot(px, py, color='#009900', markersize=5, marker='D', ls='') px = plotx - rx[0] # clean-up x-axis units py = ploty - plotx - (s[0] - rx[0]) # clean-up y-axis units py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) # clean-up x-axis units pylab.plot(px, py, color='r', ls='-', lw=3) for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) ylab = re.sub(' e\S+', ' pixels)', ylab) ylab = re.sub(' s\S+', '', ylab) ylab = re.sub('Flux', 's $-$ x\'', ylab) kepplot.labels('Linear Drift [x\'] (pixels)', ylab, 'k', 16) # labels pylab.grid() # grid lines # plot time derivative of arclength s ax = kepplot.location([0.04, 0.08, 0.16, 0.41]) # plot location px = copy(time_pnt) py = copy(dx_pnt) px, xlab, status = kepplot.cleanx(px, logfile, verbose) # clean-up x-axis units kepplot.RangeOfPlot(px, dx, 0.05, False) # data limits pylab.plot(px, py, color='#009900', markersize=5, marker='D', ls='') try: px = copy(time_thr) py = copy(dx_thr) px, xlab, status = kepplot.cleanx( px, logfile, verbose) # clean-up x-axis units pylab.plot(px, py, color='#980000', markersize=5, marker='D', ls='') except: pass px = copy(t) py = copy(dfit) px, xlab, status = kepplot.cleanx(px, logfile, verbose) # clean-up x-axis units pylab.plot(px, py, color='r', ls='-', lw=3) py = copy(dfit + sigma_dsdt * dsigma) pylab.plot(px, py, color='r', ls='--', lw=3) py = copy(dfit - sigma_dsdt * dsigma) pylab.plot(px, py, color='r', ls='--', lw=3) for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) kepplot.labels(xlab, 'ds/dt (pixels day$^{-1}$)', 'k', 16) # labels pylab.grid() # grid lines # plot relation of arclength vs detrended flux ax = kepplot.location([0.24, 0.08, 0.16, 0.41]) # plot location px = copy(s_pnt) py = copy(flux_pnt) py, ylab, status = kepplot.cleany(py, 1.0, logfile, verbose) # clean-up x-axis units kepplot.RangeOfPlot(px, py, 0.05, False) # data limits pylab.plot(px, py, color='#009900', markersize=5, marker='D', ls='') pylab.plot(plx, ply, color='r', ls='-', lw=3) for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize(14) for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize(14) kepplot.labels('Arclength [s] (pixels)', ylab, 'k', 16) # labels pylab.grid() # grid lines # plot aperture photometry kepplot.location([0.44, 0.53, 0.55, 0.45]) # plot location px, xlab, status = kepplot.cleanx(intime, logfile, verbose) # clean-up x-axis units py, ylab, status = kepplot.cleany(indata, 1.0, logfile, verbose) # clean-up x-axis units kepplot.RangeOfPlot(px, py, 0.01, True) # data limits kepplot.plot1d(px, py, cadence, lcolor, lwidth, fcolor, falpha, True) # plot data kepplot.labels(' ', ylab, 'k', 16) # labels pylab.setp(pylab.gca(), xticklabels=[]) # remove x- or y-tick labels kepplot.labels(xlab, re.sub('Flux', 'Aperture Flux', ylab), 'k', 16) # labels pylab.grid() # grid lines # Plot corrected photometry kepplot.location([0.44, 0.08, 0.55, 0.45]) # plot location kepplot.RangeOfPlot(px, py, 0.01, True) # data limits px, xlab, status = kepplot.cleanx(tim_gd, logfile, verbose) # clean-up x-axis units py, ylab, status = kepplot.cleany(flx_gd, 1.0, logfile, verbose) # clean-up x-axis units kepplot.plot1d(px, py, cadence, lcolor, lwidth, fcolor, falpha, True) # plot data try: px, xlab, status = kepplot.cleanx( tim_bd, logfile, verbose) # clean-up x-axis units py = copy(flx_bd) pylab.plot(px, py, color='#980000', markersize=5, marker='D', ls='') except: pass kepplot.labels(xlab, re.sub('Flux', 'Corrected Flux', ylab), 'k', 16) # labels pylab.grid() # grid lines # render plot if plotres: kepplot.render(cmdLine) # save plot to file if plotres: pylab.savefig(re.sub('.fits', '_%d.png' % (iw + 1), outfile)) # correct fluxes within the output file intime = work1[:, 7] + bjdref cadenceno = work1[:, 6].astype(int) indata = work1[:, 5] mom_centr1 = work1[:, 4] mom_centr2 = work1[:, 3] psf_centr1 = work1[:, 2] psf_centr2 = work1[:, 1] centr1 = copy(mom_centr1) centr2 = copy(mom_centr2) centr = concatenate([[centr1] - mean(centr1_good), [centr2] - mean(centr2_good)]) centr_rot = dot(evec.T, centr) yy = copy(indata) zz = centr_rot[1, :] xx = zeros((len(zz))) cfac = zeros((len(zz))) for i in range(len(acoeffs)): xx = xx + acoeffs[i] * numpy.power(zz, i) for i in range(len(ccoeffs)): cfac = cfac + ccoeffs[i] * numpy.power(xx, i) out_detsap = yy / cfac instr[1].data.field('SAP_FLUX')[t1:t2] /= cfac instr[1].data.field('PDCSAP_FLUX')[t1:t2] /= cfac try: instr[1].data.field('DETSAP_FLUX')[t1:t2] /= cfac except: pass # add quality flag to output file for thruster firings for i in range(len(intime)): if cadenceno[i] in thr_cadence: instr[1].data.field('SAP_QUALITY')[t1 + i] += 131072 # write output file if status == 0: instr.writeto(outfile) # close input file if status == 0: status = kepio.closefits(instr, logfile, verbose) # end time if (status == 0): message = 'KEPSFF completed at' else: message = '\nKEPSFF aborted at' kepmsg.clock(message, logfile, verbose)