if star['name'] not in obsinfo: print 'No phase range and exposure time specified for', star['name'] exit(1) # Loop through the targets in RA order keys = peinfo.keys() keys.sort() for key in keys: star = peinfo[key] obs = obsinfo[star['name']] # Interpret dates start_year, start_month, start_day = obs['start'].split('-') end_year, end_month, end_day = obs['end'].split('-') mjd_start = sla.cldj(int(start_year), int(start_month), int(start_day)) mjd_end = sla.cldj(int(end_year), int(end_month), int(end_day)) if mjd_end <= mjd_start: print 'ERROR: end date should be after start date' exit(1) # middle used to estimate systematic uncert mjd_mid = (mjd_start + mjd_end) / 2. # Compute light travel time stuff at start, middle and end of date interval tt,tdb,btdb_start,hutc_start,htdb,vhel,vbar = \ sla.utc2tdb(mjd_start,longit,latit,height,star['ra'],star['dec']) tt,tdb,btdb_mid,hutc_mid,htdb,vhel,vbar = \ sla.utc2tdb(mjd_mid,longit,latit,height,star['ra'],star['dec'])
else: print 'No target prefixes loaded.' # Compute maximum length of the names if len(prefixes): mpre = max([len(n) for n in prefixes.values()]) + 1 else: mpre = 0 left = max([len(n) for n in peinfo.keys()]) + mpre # Compute maximum length of the names # Rather primitive times to define sun down and up; won't work # properly in far north or south or around the dateline mjd_day1 = sla.cldj(year, month, day) - longit/360. + 0.5 mjd_night = mjd_day1 + 0.5 mjd_day2 = mjd_day1 + 1.0 sunset = sla.sun_at_elev(longit, latit, height, mjd_day1, mjd_night, -0.25) sunrise = sla.sun_at_elev(longit, latit, height, mjd_night, mjd_day2, -0.25) twiset = sla.sun_at_elev(longit, latit, height, mjd_day1, mjd_night, args.twilight) twirise = sla.sun_at_elev(longit, latit, height, mjd_night, mjd_day2, args.twilight) # really stop at these points rset = sla.sun_at_elev(longit, latit, height, mjd_day1, mjd_night, -10.) rrise = sla.sun_at_elev(longit, latit, height, mjd_night, mjd_day2, -10.)
def make_eso_chart(fname, cname, target, info, pid, pi, pos, field, scale, stype='sec', source=None, angle=None, mark=True, s1=0.04, s2=0.1, plo=50.0, phi=99.8, sloc=-0.43, pwidth=6, fsize=12, aspect=0.6, pm=None, obsdate=None, lhead=0.02): """Make a chart suitable for VLT. Arguments:: fname : (string) fits file from DSS, e.g. 'PG1018-047.fits' cname : (string) chart name (e.g. "name.pdf". The type of file is deduced from the suffix. Either .pdf or .jpg are recognised) target : (string) target name, e.g. 'PG1018-047' info : (string or list of strings) extra information, e.g. 'Slit angle: parallactic'. A list of strings will be printed line by line pid : (string) programme ID, e.g. '088.D-0041(A)' pi : (string) PI name, e.g. 'Marsh' pos : (string) position, e.g. '10 21 10.6 -04 56 19.6' (assumed 2000) field : (float) field width to display, arcmin, e.g. 1.0 scale : (float) size of scale to indicate in arcsec, e.g. 30 stype : (string) 'sec' or 'min' to indicate how to mark the scale source : (string) source of fits file, e.g. 'DSS blue'. Ignore for automatic version. angle : (float) indicator / slit angle to display, degrees. None to ignore. mark : (bool) True to indicate object s1 : (float) fraction of field for start of slit and object markers (displaced from object) s2 : (float) fraction of field for end of slit and object markers (displaced from object) plo : (float) Low image display level, percentile phi : (float) High image display level, percentile sloc : (float) vertical location of scale bar in terms of 'field' pwidth : (float) (approx) plot width in inches fsize : (int) fontsize, pt aspect : (float) aspect (vertical/horizontal) [should be < 1] pm : (tuple) proper motion in RA, and dec, arcsec/year in both coords. This is used to correct the predicted position of the target in the image by finding the date on which the image was taken. obsdate : (string) if you set pm, then if you also set date, an arrow arrow will be drawn from target to its expected position at obsdate and the chart will be centred on the head of the arrow. obsdate should be in YYYY-MM-DD format. lhead : (float) length of arrow head as fraction of field. If this turns out to be longer than the entire arrow, no arrow is drawn. Returns (ilo,ihi) display levels used """ # ra, dec in degrees ra,dec,sys = subs.str2radec(pos) ra *= 15 # Read data hdulist = fits.open(fname) data = hdulist[0].data head = hdulist[0].header hdulist.close() arrow = False if pm: # try to correct position to supplied date or # date of chart if 'DATE-OBS' in head: dobs = head['DATE-OBS'] year = int(dobs[:4]) month = int(dobs[5:7]) day = int(dobs[8:10]) deltat = (sla.cldj(year,month,day) - sla.cldj(2000,1,1))/365.25 dra = pm[0]*deltat/np.cos(np.radians(dec))/3600. ddec = pm[1]*deltat/3600. ra += dra dec += ddec if obsdate: yearp,monthp,dayp = obsdate.split('-') deltat = (sla.cldj(int(yearp),int(monthp),int(dayp)) - \ sla.cldj(year,month,day))/365.25 dra = pm[0]*deltat/np.cos(np.radians(dec))/3600. ddec = pm[1]*deltat/3600. ra += dra dec += ddec arrow = True else: print 'WARNING: Could not find DATE-OBS in header' # Read WCS info wcs = astWCS.WCS(fname) dx = 60.*wcs.getXPixelSizeDeg() dy = 60.*wcs.getYPixelSizeDeg() rot = wcs.getRotationDeg() if rot > 180.: rot -= 360. if not wcs.coordsAreInImage(ra,dec): print 'WARNING: coordinates not inside image' # pixel position corresponding to desired ra and dec x,y = wcs.wcs2pix(ra, dec) if arrow: if not wcs.coordsAreInImage(ra-dra,dec-ddec): print 'WARNING: End of proper motion arrow is not inside image' xa,ya = wcs.wcs2pix(ra-dra, dec-ddec) ny, nx = data.shape # plot limits limits = (dx*(-0.5-x),dx*(nx-0.5-x),dy*(-0.5-y),dy*(ny-0.5-y)) if source is None: if 'SURVEY' in head: source = head['SURVEY'] if source == 'POSSII-F': source = 'POSS-II red' elif source == 'POSSII-J': source = 'POSS-II blue' elif source == 'POSSII-N': source = 'POSS-II ir' elif source == 'POSSI-E': source = 'POSS-I red' elif source == 'POSSI-O': source = 'POSS-I blue' elif source == 'SERC-I': source = 'SERC ir' elif source == 'SERC-J': source = 'SERC blue' elif source == 'AAO-SES': source = 'AAO red' elif source == 'AAO-GR': source = 'AAO red' else: source = 'UNKNOWN' # Start plotting fig = plt.figure(figsize=(pwidth,pwidth)) axes = fig.add_subplot(111,aspect='equal') mpl.rc('font', size=fsize) # Derive the plot range ilo = stats.scoreatpercentile(data.flat, plo) ihi = stats.scoreatpercentile(data.flat, phi) # Plot plt.imshow(data, vmin=ilo, vmax=ihi, cmap=cm.binary, extent=limits, interpolation='nearest', origin='lower') axes.autoscale(False) # draw slit angle if angle is not None: ca = m.cos(m.radians(angle+rot)) sa = m.sin(m.radians(angle+rot)) t1 = s1*field t2 = s2*field plt.plot([-sa*t1,-sa*t2],[+ca*t1,+ca*t2],BLUE,lw=3) plt.plot([+sa*t1,+sa*t2],[-ca*t1,-ca*t2],BLUE,lw=3) # Mark object if mark: t1 = s1*field t2 = s2*field plt.plot([t1,t2],[0,0],RED,lw=3) plt.plot([0,0],[t1,t2],RED,lw=3) # draw arrow if arrow: # Slightly complicated because matplotlib # arrow stupidly starts drawing the head of the # arrow at the end point so we need to shrink the # arrow. If it becomes negative, don't draw at all, # just issue a warning delx, dely = dx*(x-xa), dy*(y-ya) length = m.sqrt(delx**2+dely**2) hl = field*lhead lnew = length-hl if lnew > 0: shrink = lnew/length plt.arrow(-delx, -dely, shrink*delx, shrink*dely, head_width=0.5*hl, head_length=hl) else: print 'WARNING: arrow head too long; arrow not drawn' # Draw scale bar if stype == 'sec' or stype == 'min': if stype == 'sec': plt.text(0, (sloc-0.05)*field, str(scale) + ' arcsec', horizontalalignment='center',color=RED) elif stype == 'min': plt.text(0, (sloc-0.05)*field, str(scale/60) + ' arcmin', horizontalalignment='center',color=RED) scale /= 60. plt.plot([-0.5*scale,+0.5*scale],[sloc*field,sloc*field],RED,lw=3) plt.plot([+0.5*scale,+0.5*scale],[(sloc+0.02)*field,(sloc-0.02)*field], RED,lw=3) plt.plot([-0.5*scale,-0.5*scale],[(sloc+0.02)*field,(sloc-0.02)*field], RED,lw=3) # North-East indicator. ev, nv = East / North vectors xc, yc = 0.4*field, -0.4*field rot = m.radians(rot) rmat = np.matrix(((m.cos(rot),-m.sin(rot)),(m.sin(rot),m.cos(rot)))) nv = np.array((0.,0.2*field)) nv = nv.reshape((2,1)) nv = rmat*nv nv = np.array(nv).flatten() ev = np.array((-0.2*field,0.)) ev = ev.reshape((2,1)) ev = rmat*ev ev = np.array(ev).flatten() plt.plot([xc,xc+nv[0]],[yc,yc+nv[1]],RED,lw=3) plt.text(xc+1.1*nv[0], yc+1.1*nv[1], 'N', horizontalalignment='center', color=RED) plt.plot([xc,xc+ev[0]],[yc,yc+ev[1]],RED,lw=3) plt.text(xc+1.15*ev[0], yc+1.1*ev[1], 'E', verticalalignment='center', color=RED) # finally the textual info with a helper function def ptext(x, y, field, tstr): """ Converts relative (0-1) x,y limits into data coords and plots a string. """ xd = -field/2.+field*x yd = -field/2.+field*y plt.text(xd, yd, tstr, horizontalalignment='left',color=BLUE) xoff = 0.02 dely = 0.035 yoff = 0.96 if pid != '': ptext(xoff, yoff, field, pid) yoff -= dely if pi != '': ptext(xoff, yoff, field, 'PI: ' + pi) yoff -= 1.5*dely if target != '': ptext(xoff, yoff, field, 'Target: ' + target) yoff -= 1.5*dely rah,ram,ras,decd,decm,decs = pos.split() ptext(xoff, yoff, field, 'RA (2000) : ' + rah + ' ' + ram + ' ' + ras) yoff -= dely ptext(xoff, yoff, field, 'Dec (2000): ' + decd + ' ' + decm + ' ' + decs) yoff -= 1.5*dely ptext(xoff, yoff, field, "Field: " + str(field) + "' x " + str(field) + "'") if 'DATE-OBS' in head: yoff -= dely ptext(xoff, yoff, field, 'Date: ' + head['DATE-OBS'][:10]) if source != '': yoff -= dely ptext(xoff, yoff, field, 'Survey: ' + source) yoff -= 2.*dely if info is not None: if isinstance(info, list): for line in info: ptext(xoff, yoff, field, line) yoff -= dely else: ptext(xoff, yoff, field, info) plt.xlim(-field/2.,field/2.) plt.ylim(-field/2.,field/2.) plt.savefig(cname,bbox_inches='tight') return (ilo,ihi)
elif abs(eq - 2000) > 0.001: ra = -1. dec = -100. print 'ERROR: unrecognised equinox ' + str(eq) + ' file = ' + mfile + ' nspec = ' + str(nspec) nnopos += 1 nbadeq += 1 else: ra = -1. dec = -100. nnopos += 1 # Time if 'RJD' in mspec: mjd = mspec['RJD'] -2400000.5 elif 'Day' in mspec and 'Month' in mspec and 'Year' in mspec and 'UTC' in mspec: mjd = sla.cldj(mspec['Year'],mspec['Month'],mspec['Day']) + mspec['UTC']/24. ntcalc += 1 else: mjd = 0. nnojd += 1 # Dwell if 'Dwell' in mspec: dwell = mspec['Dwell'] else: dwell = -1. nnoexp += 1 # Record number if 'Record' in mspec: nrec = mspec['Record']
else: (ra,dec,system) = subs.str2radec(target) dist = options.dist wave = options.wave import trm.sla as sla dre = re.compile('(\d\d\d\d)-(\d\d)-(\d\d)$') m = re.match(dre, options.start) if m: year = int(m.group(1)) month = int(m.group(2)) day = int(m.group(3)) start_mjd = sla.cldj(year, month, day) else: print 'Could not understand the start date:',options.start exit(1) m = re.match(dre, options.end) if m: year = int(m.group(1)) month = int(m.group(2)) day = int(m.group(3)) end_mjd = sla.cldj(year, month, day) else: print 'Could not understand the end date:',options.end exit(1) if start_mjd >= end_mjd: