def examples(): import glob #import unicorn.inspect import pysao os.chdir(os.getenv('THREEDHST') + '/3DHST_VariableBackgrounds/GS25') RGB_PATH = os.getenv('RELEASE') + 'v4.0/RGB/All/' ds9 = pysao.ds9() #### Objects with fits x = unicorn.inspect.ImageClassifier(glob.glob('ZFIT/PNG/*zfit.png'), FITS_PATH='2D/FITS/', logfile='inspect_zfit', RGB_PATH=RGB_PATH, ds9=ds9) #### Raw 2D files, including objects not fit x = unicorn.inspect.ImageClassifier(glob.glob('2D/PNG/*png'), FITS_PATH='2D/FITS/', logfile='inspect_raw2d', RGB_PATH=RGB_PATH, ds9=ds9)
def go_pointing(pointing='goodss-25', RELEASE='/Volumes/Voyager/TEST_SPECTRA_v4.1/GOODS-S/INTERLACE_v4.1/', RGB_PATH='/Volumes/Voyager/TEST_SPECTRA_v4.1/RGB_goodss/',show_ds9=True): """ Classify a 3D-HST pointing """ import glob #from unicorn import inspect field = '-'.join(pointing.split('-')[:-1]) ### Example paths for v4.0 and earlier releases #PNG_PATH = '%s/%s/%s-WFC3_v4.0_SPECTRA/%s/ZFIT/PNG/' %(RELEASE, field, field, pointing) #FITS_PATH = '%s/%s/%s-WFC3_v4.0_SPECTRA/%s/2D/FITS/' %(RELEASE, field, field, pointing) #PNG_PATH = '%s/%s/WFC3/%s/ZFIT/PNG/' %(RELEASE, field, pointing) #FITS_PATH = '%s/%s/WFC3/%s/2D/FITS/' %(RELEASE, field, pointing) PNG_PATH = FITS_PATH = RELEASE if show_ds9: import pysao ds9=pysao.ds9() x = ImageClassifier(images=glob.glob(PNG_PATH+pointing+'*new_zfit.png'), RGB_PATH=RGB_PATH, FITS_PATH=FITS_PATH, logfile='%s_inspect.info' %(pointing), ds9=ds9) else: x = ImageClassifier(images=glob.glob(PNG_PATH+pointing+'*new_zfit.png'), RGB_PATH=RGB_PATH, FITS_PATH=FITS_PATH, logfile='%s_inspect.info' %(pointing)) return x
def get_drizzled_cutouts(): ### Optinally display products to ds9 with, e.g., pysao.ds9 try: import pysao ds9 = pysao.ds9() ds9.set('scale limits -0.08 8') ds9.set('lock colorbar') ds9.set('frame lock wcs') ds9.set('tile') for f in range(6): ds9.frame(f+1) except: ds9 = None ### Full mosaic, also provides a reference WCS im_mosaic = pyfits.open('../../MACS1149/Catalog/MACS1149-F160W_drz_sci.fits') wcs_mosaic = stwcs.wcsutil.HSTWCS(im_mosaic, ext=0) ### Get cutout of NX pixels around the center position from the reference mosaic NX, pix_scale = 50, 0.065 wcs_mosaic.updatePscale(pix_scale) line_wavelengths = {'O2':3727, 'Ne3':3869, 'Hb':4861, 'O3':5007, 'Ha':6563., 'S2':6724} ### Object stats = {'id':404, 'z':1.40707, 'lines':{'G141':['O3','Ha','S2'], 'G102':['O2']}} stats = {'id':1422, 'z':2.27763, 'lines':{'G141':['O2','Hb','O3']}} stats = {'id':1917, 'z':1.89105, 'lines':{'G141':['Hb','O3'], 'G102':['O2']}} stats = {'id':2315, 'z':1.8936, 'lines':{'G141':['Hb','O3'], 'G102':['O2']}} stats = {'id':2389, 'z':1.8936, 'lines':{'G141':['Hb','O3'], 'G102':['O2']}} stats = {'id':3746, 'z':1.2477, 'lines':{'G141':['O3','Ha','S2'], 'G102':['O2','Hb','O3']}} import collections drizzled = collections.OrderedDict() for grism in stats['lines'].keys(): files=glob.glob('MACS1149-???-%s_%05d*2D.fits' %(grism, stats['id'])) for line in stats['lines'][grism]: lam = line_wavelengths[line]*(1+stats['z']) drizzled['%s_%s' %(grism, line)] = driz_from_twod(files, lam=lam, pixfrac=0.5, wcs_mosaic=wcs_mosaic, ds9=ds9) ### Show all keys = drizzled.keys() for i, key in enumerate(keys): print 'Frame %d: %s' %(i+1, key) ds9.frame(i+1) ds9.view(drizzled[key][1], header=drizzled[key][2])
def obj_lookup(dir, obj): import pysao cat = table.Table.read(dir + '/A2744_cat.dat', format = 'ascii')['id', 'X_IMAGE', 'Y_IMAGE'] obj = cat[cat['id'] == obj] X_IMAGE = str(np.rint(obj['X_IMAGE'][0])) Y_IMAGE = str(np.rint(obj['Y_IMAGE'][0])) #print obj ds9 = pysao.ds9() ds9.set('file 160.fits') ds9.set('regions file zheng2014.reg') ds9.set('scale log 99.5') ds9.set('scale limits -.1 10') ds9.set('cmap value 10.0889 0.358543') #ds9.xpa_help('pan') panstring = 'pan to ' + X_IMAGE + ' ' + Y_IMAGE + ' image' ds9.set(panstring) a = raw_input('Press ENTER to exit...') #print ds9.get('cmap value') ds9.set('exit')
def displayFit( self, **kwargs ): # get ready to show the IFU overlaid on the image provided by imageFile self.drawIFU( **kwargs ) self.drawStars( **kwargs ) # load region files with IFU and star coordinates ds9 = pysao.ds9() ds9.load_fits( kwargs[ 'imageFile' ] ) ds9.set( 'regions load ifu.reg' ) ds9.set( 'regions load stars.reg' ) # pan the ds9 frame to center on the IFU xPan = self.bestOffset[ 0 ] / 3600. + self.centerCoords[ 0 ] yPan = self.bestOffset[ 1 ] / 3600. + self.centerCoords[ 1 ] coords = ICRS( ra = xPan, dec = yPan, unit = ( u.degree, u.degree ) ) ds9.set( 'pan to %(x)s %(y)s wcs fk5' % { "x": coords.ra.to_string(), "y": coords.dec.to_string() } ) ds9.set( 'scale zscale' ) # set to zscale raw_input( "Press ENTER when finished" )
def go_pointing( pointing='goodss-25', RELEASE='/Volumes/Voyager/TEST_SPECTRA_v4.1/GOODS-S/INTERLACE_v4.1/', RGB_PATH='/Volumes/Voyager/TEST_SPECTRA_v4.1/RGB_goodss/', show_ds9=True): """ Classify a 3D-HST pointing """ import glob #from unicorn import inspect field = '-'.join(pointing.split('-')[:-1]) ### Example paths for v4.0 and earlier releases #PNG_PATH = '%s/%s/%s-WFC3_v4.0_SPECTRA/%s/ZFIT/PNG/' %(RELEASE, field, field, pointing) #FITS_PATH = '%s/%s/%s-WFC3_v4.0_SPECTRA/%s/2D/FITS/' %(RELEASE, field, field, pointing) #PNG_PATH = '%s/%s/WFC3/%s/ZFIT/PNG/' %(RELEASE, field, pointing) #FITS_PATH = '%s/%s/WFC3/%s/2D/FITS/' %(RELEASE, field, pointing) PNG_PATH = FITS_PATH = RELEASE if show_ds9: import pysao ds9 = pysao.ds9() x = ImageClassifier(images=glob.glob(PNG_PATH + pointing + '*new_zfit.png'), RGB_PATH=RGB_PATH, FITS_PATH=FITS_PATH, logfile='%s_inspect.info' % (pointing), ds9=ds9) else: x = ImageClassifier(images=glob.glob(PNG_PATH + pointing + '*new_zfit.png'), RGB_PATH=RGB_PATH, FITS_PATH=FITS_PATH, logfile='%s_inspect.info' % (pointing)) return x
import scipy.spatial import matplotlib.pyplot as plt import numpy as np class Picker(object): def __init__(self, xy): self.kdtree = scipy.spatial.KDTree(xy) def pick(self): pos = plt.ginput() return self.kdtree.query(pos[0]) import pysao ds9 = pysao.ds9() ds9.set("tile") ds9.set('mode crosshair') ds9.set("frame 1") ds9.set("file 2mass_J.fits") ds9.set("scale zscale") ds9.set("frame 2") ds9.set("file 2mass_H.fits") ds9.set("scale zscale") ds9.set('lock crosshair wcs') import atpy tbl = atpy.Table("2mass_table.xml") x = tbl["Jmag"]
def finding_chart(self, target, ds9, trange=[-6, 6] * u.hr, ticks=1 * u.hr, fov=1 * u.arcmin, frame=1, dss=True): """Plot a DS9 finding chart for a moving target. Parameters ---------- target : SolarSysObject The target to observe. ds9 : pysao.ds9 Plot to this DS9 instance. trange : Quantity, optional Plot the target's path over this time span, centered on the observer's date (`self.date`). ticks : Quantity, optional Plot tick marks using this interval. The first tick is a circle. fov : Quantity, optional Angular size of a box or rectangle to draw, indicating your instrument's FOV, or `None`. frame : int, optional DS9 frame number to display image. dss : bool, optional Set to `True` to retrieve a DSS image. """ import matplotlib.pyplot as plt import pysao from ..ephem import Earth, SolarSysObject assert isinstance(target, SolarSysObject), "target must be a SolarSysObject" trange = u.Quantity(trange, u.hr) ticks = u.Quantity(ticks, u.hr) ds9 = ds9 if ds9 is not None else pysao.ds9() # DSS g = Earth.observe(target, self.date, ltt=True) ds9.set('frame {}'.format(frame)) ds9.set('dsssao frame current') ds9.set('dsssao size 60 60') ds9.set('dsssao coord {} {}'.format( g['ra'].to_string(u.hr, sep=':'), g['dec'].to_string(u.deg, sep=':'))) ds9.set('dsssao close') ds9.set('cmap b') ds9.set('align') # FOV if fov is not None: if fov.size == 1: fov = [fov, fov] fov_deg = u.Quantity(fov, u.deg).value reg = 'fk5; box {} {} {} {} 0'.format( g['ra'].to_string(u.hr, sep=':'), g['dec'].to_string(u.deg, sep=':'), fov_deg[0], fov_deg[1]) ds9.set('regions', reg) # path dt = np.linspace(trange[0], trange[1], 31) g = Earth.observe(target, self.date + dt, ltt=True) for i in range(len(g) - 1): ds9.set('regions', 'fk5; line {} {} {} {}'.format( g[i]['ra'].to_string(u.hr, sep=':'), g[i]['dec'].to_string(u.deg, sep=':'), g[i+1]['ra'].to_string(u.hr, sep=':'), g[i+1]['dec'].to_string(u.deg, sep=':'))) # ticks dt1 = np.arange(0, trange[0].value, -ticks.value) if dt1[-1] != trange[0].value: dt1 = np.concatenate((dt1, [trange[0].value])) dt2 = np.arange(ticks.value, trange[1].value, ticks.value) if dt2[-1] != trange[0].value: dt2 = np.concatenate((dt2, [trange[1].value])) dt = np.concatenate((dt1[::-1], dt2)) * u.hr del dt1, dt2 g = Earth.observe(target, self.date + dt, ltt=True) for i in range(len(g)): s = 'fk5; point({},{}) # point=cross'.format( g[i]['ra'].to_string(u.hr, sep=':'), g[i]['dec'].to_string(u.deg, sep=':')) if i == 0: s = s.replace('cross', 'circle') ds9.set('regions', s) g = Earth.observe(target, self.date, ltt=True) ds9.set('regions', 'fk5; point({},{}) # point=x'.format( g['ra'].to_string(u.hr, sep=':'), g['dec'].to_string(u.deg, sep=':'))) return ds9
def ds9_mark(self, mask=None, sizekey='FLUX_RADIUS', ds9=None, doload=True, clearmarks=True, frame=None): """ Mark the sextracted outputs on ds9. Note that this requires `pysao` to be installed. Parameters ---------- mask : array or None A mask that will be applied to the x/y/size arrays to get the sample to mark or None to show everything sizekey : str or number The name of the column to use as the size of the circles or a number for them all to be the same. If key is missing, default=5. ds9 : None or pysao.ds9 instance if None, a new DS9 will be started, otherwise the instance to use doload : bool If True, loads the file. clearmarks : bool If True, clears the marks """ import pysao #try to get in existing ds9 if one wasn't given, otherwise make one if ds9 is None: ds9 = getattr(self, 'lastds9', None) if ds9 is not None: #check that it's still alive try: ds9.get('') # should just give all the XPA options except RuntimeError: # exernally killed self.lastds9 = ds9 = None if ds9 is None: if self.verbose: print("didn't find old ds9 - starting a new one") ds9 = self.lastds9 = pysao.ds9() currfn = ds9.get('iis filename').strip() if currfn != self.lastimgfn: if self.verbose: print("Current filename {0} does not match {1}. Reloading.".format(currfn, self.lastimgfn)) ds9.load_fits(self.lastimgfn) elif clearmarks: #delete existing marks ds9.set('regions delete all') tab = self.get_output() if isinstance(sizekey, basestring): try: sz = tab[sizekey] except KeyError: if self.verbose: print("didn't find key {0} defaulting to 5 px".format(sizekey)) sz = [5] * len(tab) else: sz = [sizekey] * len(tab) try: x = tab['X_IMAGE'] y = tab['Y_IMAGE'] except KeyError: try: x = tab['XWIN_IMAGE'] y = tab['YWIN_IMAGE'] except KeyError: raise KeyError('Could not find X_IMAGE/Y_IMAGE or XWIN_IMAGE/YWIN_IMAGE') if mask is not None: x = x[mask] y = y[mask] sz = np.array(sz)[mask] ds9.mark(x, y, sz) return ds9
def atd5(): """ Verify that mosaicAD gives the correct WCS information for the mosaiced data. Given a GMOS input file, the MosaicAD object method as_astrodata creates an output AstroData object. This object 'SCI' header have the CRPIX1 and CPRIX2 for the reference extension header. The value CRPIX1 should match the value explained in the Success Criteria section. The value CRPIX2 is unchanged. Resources: gmos_file='../data/gS20120420S0033.fits' gsaoi_file='../data/guS20120413S0048.fits' ds9 running """ import pywcs try: from stsci.numdisplay import display except ImportError: from numdisplay import display print '\n atd5 REQUIREMENT.......' print ('***** Given an AstroData object, the system shall update the header keywords ' ' CRPIX1 and CRPIX2 in the output mosaiced AD object to match the requested ' 'transformations') gmos_file='../data/gS20120420S0033.fits' gsaoi_file='../data/guS20120413S0048.fits' from astrodata import AstroData from gempy.adlibrary.mosaicAD import MosaicAD # This is the default Mosaic function from gempy.mosaic.gemMosaicFunction import gemini_mosaic_function ad = AstroData(gmos_file) # Creates a mosaicAD object using the input ad and the # default mosaic function name gemini_mosaic_function. # 'SCI' is the default extname. mo = MosaicAD(ad, gemini_mosaic_function) # outad = mo.as_astrodata() # NOTE: The ref_ext is the left most amplifier in # reference block. For GMOS the reference block # (2,1). E.G. for a 6-amp GMOS exposure the left # most exposure is 3. refblk = mo.geometry.ref_block col,row = refblk[0], refblk[1] amp_per_block = mo._amps_per_block ref_ext = col*amp_per_block+1 ocrpix1 = ad['SCI',ref_ext].header['CRPIX1'] xgap = mo.geometry.gap_dict['transform_gaps'][col,row][0] blksz_x,blksz_y = mo.geometry.blocksize # Success Criteria 1. # Get the x2 value from coords['amp_mosaic_coord'][refblk] xoff = mo.coords['amp_mosaic_coord'][max(0,col-1)][1] print ocrpix1 + xoff + xgap, 'should match: ' print outad['SCI',1].header['CRPIX1'] # Success Criteria 2. # For a GSAOI file, ad = AstroData(gsaoi_file) if ad.instrument() != 'GSAOI': print '******** file is not GSAOI ************' mo = MosaicAD(ad, gemini_mosaic_function) outad = mo.as_astrodata() outhdr = outad['SCI'].header inhdr = ad['SCI',2].header # The values should be the same. print 'Crpix1 values (in,out):',inhdr["CRPIX1"],outhdr['CRPIX1'] print 'Crpix2 values (in,out):',inhdr["CRPIX2"],outhdr['CRPIX2'] # Success Criteria 3. # For a GMOS file in extension #2 hdr = ad['SCI',2].header wcs = pywcs.WCS(hdr) import pysao # Bring up a ds9 display by instantiating the pysao object ds9 = pysao.ds9() # Display the image ds9.view(ad['SCI',2].data, frame=1) # display(ad['SCI',2].data,frame=1) print 'Click on any object:' X,Y,f,k = ds9.readcursor() # Get X,Y values from an object on the ds9 display # Get ra,dec ra,dec = wcs.wcs_pix2sky(X,Y,1) # Generate the mosaic_data for this ad using # as_astrodata method. # Display the mosaic mosaic_data for the 'SCI' extension mosaic_data = mo.mosaic_image_data() # Display the mosaic ds9.view(mosaic_data,frame=2) # display(ad['SCI',2].data,frame=1) print 'Click on the same object:' MX,MY,f,k = ds9.readcursor() #display(mosaic_data,frame=2) # Measure X,Y of the same object, named this MX,MY # Get the wcs from the mosaic header mhdr = outad['SCI'].header mwcs = pywcs.WCS(mhdr) mra,mdec = mwcs.wcs_pix2sky(MX,MY,1) print 'These RA,DEC should be pretty close:',(ra[0],mra[0]),(dec[0],mdec[0])
def atd3(): """ Verify that MosaicAD can merge associated binary tables Create a mosaic from the input AD object. It is up to the tester to see if there is one IMAGE extension name 'SCI' and one BINTABLE extension with the same number and values of EXTVER -these are associated. The as_astrodata method creates the mosaic. Please see the Procedure for the steps performed to verify the correctness of the merging. Resources: 1) gmos_file = '../data/N20120121S0175_ccMeasured.fits' 2) Uses pysao """ from astrodata import AstroData from gempy.adlibrary.mosaicAD import MosaicAD # This is the default Mosaic function from gempy.mosaic.gemMosaicFunction import gemini_mosaic_function print '\n atd3 REQUIREMENT.......' print ('***** Given an AstroData object with associated binary table, the system ' 'shall merge the tables') gmos_file = '../data/N20120121S0175_ccMeasured.fits' ad = AstroData(gmos_file) # 1) Make sure that we have an IMAGE and BINTABLE extension # with the same number and values of extver in one IMAGE and # BINTABLE extension. # 2) Creates a mosaicAD object using the input AD and the # default mosaic function named gemini_mosaic_function. # 3) The 'column_names' parameter in MosaicAD has as # default values the X_IMAGE, Y_IMAGE and X_WORLD, # Y_WORLD column names. The reference catalog have # RAJ2000 and DEJ2000. For more information please the # documentation about MosaicAD. mo = MosaicAD(ad, gemini_mosaic_function) # Now create the output AstroData object. outad = mo.as_astrodata() # Check that the output table has been merged correctly by # verifying that the duplicates rows are deleted and that the # new X,Y values for objects have been calculated correctly # based on the new WCS. # # Get input rows and remove duplicates. Output the content # of the resulting AD object which should show the # associated IMAGE and BINTABLE extensions. print outad.info() # Save to a filename from os import path nn = path.basename(ad.filename) outad.write(path.splitext(nn)[0]+'_AD.fits',clobber=True) # Verify that (X,Y) values in the merged tables correspond # the object positions. # The output catalog table name should be 'OBJCAT' and # pixel coordinates X_IMAGE and Y_IMAGE with corresponding # world coordinates Y_WORLD and Y_WORLD. tab = outad['OBJCAT'].data # Form a list of tuples (x_pixel,y_pixel) xy=[(x,y) for x,y in zip(tab.field('X_IMAGE'), tab.field('Y_IMAGE'))] # Now you can use any program to draw points and check for # location of the xy points on the objects. # Using DS9 PYSAO module # Assuming you have the module in your PYTHONPATH import pysao # Bring up a ds9 display by instantiating the pysao object ds9 = pysao.ds9() # Display the image ds9.view(outad['SCI'].data) # ***NOTE*** # Use file tab to display the 'SCI' extension of file # you save previously. Check for some of these pixel # coordinates with DS9. # Now draw the point tmp=[ds9.set_region('arrow point '+str(x)+' '+str(y)) for x,y in xy] # Verify for correctly removing duplicates when merging. # Use python sets() # Get the first all extensions from the input # AstroData object. Form a list of tuples (ra,dec) # from the reference tables in all extensions. # test for 'REFCAT' existance if ad['REFCAT'] == None: raise ValueError('"REFCAT" extension is not in the AstroData object') rd = [] for tab in ad['REFCAT']: rd += [(x,y) for x,y in zip(tab.data.field('RAJ2000'),\ tab.data.field('DEJ2000'))] # Turning rd list to a set will eliminate duplicates. print 'Number of unique elements from the list:',len(set(rd)) # Now from the outad object tab = outad['REFCAT'].data radec=[(x,y) for x,y in zip(tab.field('RAJ2000'), tab.field('DEJ2000'))] # The number of elements in the output table print 'The number of elements in the output table:',len(radec) jj = raw_input("Press Enter to exit the test")
def finding_chart(self, target, ds9, trange=[-6, 6] * u.hr, ticks=1 * u.hr, fov=1 * u.arcmin, frame=1, dss=True): """Plot a DS9 finding chart for a moving target. Parameters ---------- target : SolarSysObject The target to observe. ds9 : pysao.ds9 Plot to this DS9 instance. trange : Quantity, optional Plot the target's path over this time span, centered on the observer's date (`self.date`). ticks : Quantity, optional Plot tick marks using this interval. The first tick is a circle. fov : Quantity, optional Angular size of a box or rectangle to draw, indicating your instrument's FOV, or `None`. frame : int, optional DS9 frame number to display image. dss : bool, optional Set to `True` to retrieve a DSS image. """ import matplotlib.pyplot as plt import pysao from ..ephem import Earth, SolarSysObject assert isinstance(target, SolarSysObject), "target must be a SolarSysObject" trange = u.Quantity(trange, u.hr) ticks = u.Quantity(ticks, u.hr) ds9 = ds9 if ds9 is not None else pysao.ds9() # DSS g = Earth.observe(target, self.date, ltt=True) ds9.set('frame {}'.format(frame)) ds9.set('dsssao frame current') ds9.set('dsssao size 60 60') ds9.set('dsssao coord {} {}'.format(g['ra'].to_string(u.hr, sep=':'), g['dec'].to_string(u.deg, sep=':'))) ds9.set('dsssao close') ds9.set('cmap b') ds9.set('align') # FOV if fov is not None: if fov.size == 1: fov = [fov, fov] fov_deg = u.Quantity(fov, u.deg).value reg = 'fk5; box {} {} {} {} 0'.format( g['ra'].to_string(u.hr, sep=':'), g['dec'].to_string(u.deg, sep=':'), fov_deg[0], fov_deg[1]) ds9.set('regions', reg) # path dt = np.linspace(trange[0], trange[1], 31) g = Earth.observe(target, self.date + dt, ltt=True) for i in range(len(g) - 1): ds9.set( 'regions', 'fk5; line {} {} {} {}'.format( g[i]['ra'].to_string(u.hr, sep=':'), g[i]['dec'].to_string(u.deg, sep=':'), g[i + 1]['ra'].to_string(u.hr, sep=':'), g[i + 1]['dec'].to_string(u.deg, sep=':'))) # ticks dt1 = np.arange(0, trange[0].value, -ticks.value) if dt1[-1] != trange[0].value: dt1 = np.concatenate((dt1, [trange[0].value])) dt2 = np.arange(ticks.value, trange[1].value, ticks.value) if dt2[-1] != trange[0].value: dt2 = np.concatenate((dt2, [trange[1].value])) dt = np.concatenate((dt1[::-1], dt2)) * u.hr del dt1, dt2 g = Earth.observe(target, self.date + dt, ltt=True) for i in range(len(g)): s = 'fk5; point({},{}) # point=cross'.format( g[i]['ra'].to_string(u.hr, sep=':'), g[i]['dec'].to_string(u.deg, sep=':')) if i == 0: s = s.replace('cross', 'circle') ds9.set('regions', s) g = Earth.observe(target, self.date, ltt=True) ds9.set( 'regions', 'fk5; point({},{}) # point=x'.format( g['ra'].to_string(u.hr, sep=':'), g['dec'].to_string(u.deg, sep=':'))) return ds9
def __init__(self, images = ['UDS_54826.zfit.png', 'UDS_55031.zfit.png'], logfile='inspect_3dhst.info', RGB_PATH='./', RGB_EXTENSION='_vJH_6.png', FITS_PATH='./', load_log=True, ds9=None, rgb_lower=True): """ GUI tool for inspecting grism redshift fits x = unicorn.inspect.ImageClassifier(images=glob.glob('Specz/GOODS-S-25*zfit.png'), RGB_PATH=RGB_PATH, FITS_PATH='Specz/') """ if len(images) == 0: print 'No images specified' return False if not os.path.exists(images[0]): print 'First image not found (%s), is path correct?' %(images[0]) return False self.RGB_PATH = RGB_PATH self.FITS_PATH = FITS_PATH self.RGB_EXTENSION = RGB_EXTENSION self.rgb_lower=rgb_lower #### Check ds9 self.ds9 = ds9 if ds9 is True: try: import pysao self.ds9 = pysao.ds9() except: print 'Couldn\'t import pysao to run DS9' self.ds9 = None ##### Add .fits to filename and make backup if necessary self.logfile = logfile if not self.logfile.lower().endswith('.fits'): self.logfile += '.fits' if os.path.exists(self.logfile): bk = glob.glob(self.logfile+'.backup*') if len(bk) > 0: bkup_file = self.logfile + '.backup.%03d' %(len(bk)) else: bkup_file = self.logfile + '.backup' shutil.copy(self.logfile, bkup_file) print 'Made copy of %s -> %s' %(self.logfile, bkup_file) ####### Initialize parameters self.params = {} self.images = images self.marked_lines = None if os.path.exists(self.logfile) & load_log: self.read_fits() self.N = len(self.images) for key in ['line', 'extended', 'absorption', 'unamb', 'misid', 'contam', 'zp', 'tilt', 'investigate', 'star', 'seen', 'bad2d', 'deblend', 'sed']: if key not in self.params.keys(): self.params[key] = np.zeros(self.N, dtype=np.int) if self.marked_lines is None: self.marked_lines = np.zeros((self.N, 5)) if 'comment' not in self.params.keys(): self.params['comment'] = ['---' for i in range(self.N)] self.i = 0 ####### Initialize GUI master = tk.Toplevel() simple_twod = False if 'zfit.png' in self.images[0]: master.geometry('1050x630') elif '2D.png' in self.images[0]: master.geometry('850x750') simple_twod = True else: master.geometry('1050x630') self.master = master self.frame = tk.Frame(master) self.frame.pack() #### Image Panels imageFile = Image.open(self.images[0]) im = ImageTk.PhotoImage(imageFile) self.panel = tk.Label(self.frame , image=im, cursor='target') # imageFile2 = Image.open(self.images[0].replace('zfit','zfit.2D')).resize((500,202)) # im2 = ImageTk.PhotoImage(imageFile2) im2 = ImageTk.PhotoImage(self.get_twod_file(self.images[0])) self.panel2 = tk.Label(self.frame , image=im2) # self.panel2.configure(image = im2) # self.panel2.image = im2 #### RGB Panel im_rgb = ImageTk.PhotoImage(self.get_rgb_file(self.images[0])) self.panel_rgb = tk.Label(self.frame , image=im_rgb) #### Keypress binding self.master.bind("<Key>", self.keypress_event) #### Mouse binding - right click self.master.bind("<Button-2>", self.right_click_event) ### For logging slider movements #self.sliders = {} self.sliders = {} ###### ### Navigation buttons ### self.button_quit = tk.Button(self.frame, text = '(q)uit', command = self.finish) self.button_log = tk.Button(self.frame, text = 'Log to (F)ile', command = self.write_fits) self.button_prev = tk.Button(self.frame, text = '(p)rev', command = self.img_prev) self.button_next = tk.Button(self.frame, text = '(n)ext', command = self.img_next) self.buttons = {} #### Emission lne? self.sliders['line'] = mySlider(self, text='Emission (l)ine', param=self.params['line'], hotkey='l') #### Absorption self.sliders['absorption'] = mySlider(self, text='(a)bs./break', param=self.params['absorption'], hotkey='a') #### Extended line self.sliders['extended'] = mySlider(self, text='(e)xtended', param=self.params['extended'], hotkey='e') #### Unambiguous redshift self.buttons['unamb'] = myCheckbutton(self, text='(u)nambiguous', param=self.params['unamb'], hotkey='u') #### Flag contamination self.sliders['contam'] = mySlider(self, text='(b)ad contam', param=self.params['contam'], hotkey='b') #### Line misidentification self.buttons['misid'] = myCheckbutton(self, text='Line (m)isID', param=self.params['misid'], hotkey='m') #### Tilt? self.buttons['tilt'] = myCheckbutton(self, text='(t)ilt', param=self.params['tilt'], hotkey='t') #### Bad z_phot / z_spec or both self.buttons['zp'] = myCheckbutton(self, text='Bad (z)spec', param=self.params['zp'], hotkey='z') #### SED problems self.sliders['sed'] = mySlider(self, text='Bad SED (k)', param=self.params['sed'], hotkey='k', to=2) #### Flag for manual investigation self.sliders['investigate'] = mySlider(self, text='(i)nvestigate', param=self.params['investigate'], hotkey='i', to=4) ### Object seen already? self.buttons['seen'] = myCheckbutton(self, text='SEEN?', param=self.params['seen'], hotkey='xxx') #### Star? self.buttons['star'] = myCheckbutton(self, text='(s)tar', param=self.params['star'], hotkey='s') #### Spectrum problem self.buttons['bad2d'] = myCheckbutton(self, text='Bad 1D/2D (x)', param=self.params['bad2d'], hotkey='x') #### Deblend issue self.buttons['deblend'] = myCheckbutton(self, text='(d)eblend', param=self.params['deblend'], hotkey='d') ### Comment holder self.tvar = tk.StringVar() self.e_comment = tk.Label(self.frame, textvariable=self.tvar) self.e_comment.configure(relief=tk.RIDGE) self.tvar.set(self.params['comment'][0]) ##################### ##### Set up the grid for the GUI elements self.button_next.grid(row=1, column=4, columnspan=1) self.button_prev.grid(row=1, column=5, columnspan=1) self.button_log.grid(row=2, column=4, columnspan=1) self.button_quit.grid(row=2, column=5, columnspan=1) self.buttons['seen'].thebutton.grid(row=3, column=5) self.buttons['star'].thebutton.grid(row=3, column=4) self.sliders['line'].theslider.grid(row=4, column=0) self.sliders['absorption'].theslider.grid(row=5, column=0) self.sliders['extended'].theslider.grid(row=4, column=1) self.buttons['unamb'].thebutton.grid(row=5, column=1) self.sliders['contam'].theslider.grid(row=4, column=2) self.buttons['misid'].thebutton.grid(row=5, column=2) self.buttons['tilt'].thebutton.grid(row=4, column=3) self.buttons['zp'].thebutton.grid(row=5, column=3) self.sliders['sed'].theslider.grid(row=5, column=4) self.sliders['investigate'].theslider.grid(row=4, column=5) self.buttons['bad2d'].thebutton.grid(row=4, column=4) self.buttons['deblend'].thebutton.grid(row=5, column=5) self.e_comment.grid(row=6, column=0, columnspan=5) self.canvas = tk.Canvas(self.frame, background="white", height=5) self.line_tags = [] self.draw_lines() if simple_twod: #self.panel.place(x=0, y=0, relwidth=1, relheight=1) self.panel.grid(row=0, column=1, rowspan=4, columnspan=3) #self.canvas.grid(row=0, column=1, rowspan=1, columnspan=3) self.canvas.place(relx=0, rely=0, relwidth=1) else: self.panel.grid(row=0, column=0, columnspan=6) #self.canvas.grid(row=0, column=0, columnspan=6) self.canvas.place(relx=0, rely=0, relwidth=1) self.panel.grid() #self.canvas.grid(row=0, column=0, columnspan=6) self.panel2.grid(row=1, column=1, columnspan=3, rowspan=3) self.panel_rgb.grid(row=1, column=0, columnspan=1, rowspan=3) self.master.mainloop()
def ds9(*args, **kwargs): return pysao.ds9(path=os.path.expandvars('$DS9'))
def __init__(self, images=['UDS_54826.zfit.png', 'UDS_55031.zfit.png'], logfile='inspect_3dhst.info', RGB_PATH='./', RGB_EXTENSION='_vJH_6.png', FITS_PATH='./', load_log=True, ds9=None, rgb_lower=True): """ GUI tool for inspecting grism redshift fits x = unicorn.inspect.ImageClassifier(images=glob.glob('Specz/GOODS-S-25*zfit.png'), RGB_PATH=RGB_PATH, FITS_PATH='Specz/') """ if len(images) == 0: print 'No images specified' return False if not os.path.exists(images[0]): print 'First image not found (%s), is path correct?' % (images[0]) return False self.RGB_PATH = RGB_PATH self.FITS_PATH = FITS_PATH self.RGB_EXTENSION = RGB_EXTENSION self.rgb_lower = rgb_lower #### Check ds9 self.ds9 = ds9 if ds9 is True: try: import pysao self.ds9 = pysao.ds9() except: print 'Couldn\'t import pysao to run DS9' self.ds9 = None ##### Add .fits to filename and make backup if necessary self.logfile = logfile if not self.logfile.lower().endswith('.fits'): self.logfile += '.fits' if os.path.exists(self.logfile): bk = glob.glob(self.logfile + '.backup*') if len(bk) > 0: bkup_file = self.logfile + '.backup.%03d' % (len(bk)) else: bkup_file = self.logfile + '.backup' shutil.copy(self.logfile, bkup_file) print 'Made copy of %s -> %s' % (self.logfile, bkup_file) ####### Initialize parameters self.params = {} self.images = images self.marked_lines = None if os.path.exists(self.logfile) & load_log: self.read_fits() self.N = len(self.images) for key in [ 'line', 'extended', 'absorption', 'unamb', 'misid', 'contam', 'zp', 'tilt', 'investigate', 'star', 'seen', 'bad2d', 'deblend', 'sed' ]: if key not in self.params.keys(): self.params[key] = np.zeros(self.N, dtype=np.int) if self.marked_lines is None: self.marked_lines = np.zeros((self.N, 5)) if 'comment' not in self.params.keys(): self.params['comment'] = ['---' for i in range(self.N)] self.i = 0 ####### Initialize GUI master = tk.Toplevel() simple_twod = False if 'zfit.png' in self.images[0]: master.geometry('1050x630') elif '2D.png' in self.images[0]: master.geometry('850x750') simple_twod = True else: master.geometry('1050x630') self.master = master self.frame = tk.Frame(master) self.frame.pack() #### Image Panels imageFile = Image.open(self.images[0]) im = ImageTk.PhotoImage(imageFile) self.panel = tk.Label(self.frame, image=im, cursor='target') # imageFile2 = Image.open(self.images[0].replace('zfit','zfit.2D')).resize((500,202)) # im2 = ImageTk.PhotoImage(imageFile2) im2 = ImageTk.PhotoImage(self.get_twod_file(self.images[0])) self.panel2 = tk.Label(self.frame, image=im2) # self.panel2.configure(image = im2) # self.panel2.image = im2 #### RGB Panel im_rgb = ImageTk.PhotoImage(self.get_rgb_file(self.images[0])) self.panel_rgb = tk.Label(self.frame, image=im_rgb) #### Keypress binding self.master.bind("<Key>", self.keypress_event) #### Mouse binding - right click self.master.bind("<Button-2>", self.right_click_event) ### For logging slider movements #self.sliders = {} self.sliders = {} ###### ### Navigation buttons ### self.button_quit = tk.Button(self.frame, text='(q)uit', command=self.finish) self.button_log = tk.Button(self.frame, text='Log to (F)ile', command=self.write_fits) self.button_prev = tk.Button(self.frame, text='(p)rev', command=self.img_prev) self.button_next = tk.Button(self.frame, text='(n)ext', command=self.img_next) self.buttons = {} #### Emission lne? self.sliders['line'] = mySlider(self, text='Emission (l)ine', param=self.params['line'], hotkey='l') #### Absorption self.sliders['absorption'] = mySlider(self, text='(a)bs./break', param=self.params['absorption'], hotkey='a') #### Extended line self.sliders['extended'] = mySlider(self, text='(e)xtended', param=self.params['extended'], hotkey='e') #### Unambiguous redshift self.buttons['unamb'] = myCheckbutton(self, text='(u)nambiguous', param=self.params['unamb'], hotkey='u') #### Flag contamination self.sliders['contam'] = mySlider(self, text='(b)ad contam', param=self.params['contam'], hotkey='b') #### Line misidentification self.buttons['misid'] = myCheckbutton(self, text='Line (m)isID', param=self.params['misid'], hotkey='m') #### Tilt? self.buttons['tilt'] = myCheckbutton(self, text='(t)ilt', param=self.params['tilt'], hotkey='t') #### Bad z_phot / z_spec or both self.buttons['zp'] = myCheckbutton(self, text='Bad (z)spec', param=self.params['zp'], hotkey='z') #### SED problems self.sliders['sed'] = mySlider(self, text='Bad SED (k)', param=self.params['sed'], hotkey='k', to=2) #### Flag for manual investigation self.sliders['investigate'] = mySlider( self, text='(i)nvestigate', param=self.params['investigate'], hotkey='i', to=4) ### Object seen already? self.buttons['seen'] = myCheckbutton(self, text='SEEN?', param=self.params['seen'], hotkey='xxx') #### Star? self.buttons['star'] = myCheckbutton(self, text='(s)tar', param=self.params['star'], hotkey='s') #### Spectrum problem self.buttons['bad2d'] = myCheckbutton(self, text='Bad 1D/2D (x)', param=self.params['bad2d'], hotkey='x') #### Deblend issue self.buttons['deblend'] = myCheckbutton(self, text='(d)eblend', param=self.params['deblend'], hotkey='d') ### Comment holder self.tvar = tk.StringVar() self.e_comment = tk.Label(self.frame, textvariable=self.tvar) self.e_comment.configure(relief=tk.RIDGE) self.tvar.set(self.params['comment'][0]) ##################### ##### Set up the grid for the GUI elements self.button_next.grid(row=1, column=4, columnspan=1) self.button_prev.grid(row=1, column=5, columnspan=1) self.button_log.grid(row=2, column=4, columnspan=1) self.button_quit.grid(row=2, column=5, columnspan=1) self.buttons['seen'].thebutton.grid(row=3, column=5) self.buttons['star'].thebutton.grid(row=3, column=4) self.sliders['line'].theslider.grid(row=4, column=0) self.sliders['absorption'].theslider.grid(row=5, column=0) self.sliders['extended'].theslider.grid(row=4, column=1) self.buttons['unamb'].thebutton.grid(row=5, column=1) self.sliders['contam'].theslider.grid(row=4, column=2) self.buttons['misid'].thebutton.grid(row=5, column=2) self.buttons['tilt'].thebutton.grid(row=4, column=3) self.buttons['zp'].thebutton.grid(row=5, column=3) self.sliders['sed'].theslider.grid(row=5, column=4) self.sliders['investigate'].theslider.grid(row=4, column=5) self.buttons['bad2d'].thebutton.grid(row=4, column=4) self.buttons['deblend'].thebutton.grid(row=5, column=5) self.e_comment.grid(row=6, column=0, columnspan=5) self.canvas = tk.Canvas(self.frame, background="white", height=5) self.line_tags = [] self.draw_lines() if simple_twod: #self.panel.place(x=0, y=0, relwidth=1, relheight=1) self.panel.grid(row=0, column=1, rowspan=4, columnspan=3) #self.canvas.grid(row=0, column=1, rowspan=1, columnspan=3) self.canvas.place(relx=0, rely=0, relwidth=1) else: self.panel.grid(row=0, column=0, columnspan=6) #self.canvas.grid(row=0, column=0, columnspan=6) self.canvas.place(relx=0, rely=0, relwidth=1) self.panel.grid() #self.canvas.grid(row=0, column=0, columnspan=6) self.panel2.grid(row=1, column=1, columnspan=3, rowspan=3) self.panel_rgb.grid(row=1, column=0, columnspan=1, rowspan=3) self.master.mainloop()