def ssobjangdiam(srcName, epoch, ephemdata="",unit=""): """ srcName: solar system object name (case insensitive) epoch: in string format (e.g. "2015/09/01:12:00:00") ephemdata: ephemeris data (default = "", look up the standard ~/alma/JPL_Horizons in the data repo unit: unit for the output ang. diam. """ defaultDataPath = os.getenv("CASAPATH").split()[0] + "/data/ephemerides/JPL-Horizons/" me = taskinit.metool() qa = taskinit.qatool() if ephemdata!="": datapath = ephemdata else: mjd = me.epoch("utc",epoch)['m0']['value'] datapath = findEphemTable(defaultDataPath, srcName, mjd) me.framecomet(datapath) me.doframe(me.epoch("utc", epoch)) me.doframe(me.observatory("ALMA")) angdiamrad= me.cometangdiam() if unit=="" or unit=="rad": angdiam = angdiamrad else: angdiam = qa.convert(qa.quantity(angdiamrad), unit) return angdiam
def qufromgain(caltable, badspw=[], paoffset=0.0): mytb = taskinit.tbtool() myme = taskinit.metool() mytb.open(caltable + '/ANTENNA') pos = mytb.getcol('POSITION') meanpos = pl.mean(pos, 1) frame = mytb.getcolkeyword('POSITION', 'MEASINFO')['Ref'] units = mytb.getcolkeyword('POSITION', 'QuantumUnits') mpos = myme.position(frame, str(meanpos[0]) + units[0], str(meanpos[1]) + units[1], str(meanpos[2]) + units[2]) myme.doframe(mpos) # _geodetic_ latitude latr = myme.measure(mpos, 'WGS84')['m1']['value'] print 'Latitude = ', latr * 180 / pi mytb.open(caltable + '/FIELD') nfld = mytb.nrows() dirs = mytb.getcol('DELAY_DIR')[:, 0, :] mytb.close() print 'Found as many as ' + str(nfld) + ' fields.' mytb.open(caltable + '/SPECTRAL_WINDOW') nspw = mytb.nrows() bandnames = [x.split('#')[0].split('_')[-1] for x in mytb.getcol('NAME')] mytb.close() print 'Found as many as ' + str(nspw) + ' spws.' R = pl.zeros((nspw, nfld)) Q = pl.zeros((nspw, nfld)) U = pl.zeros((nspw, nfld)) mask = pl.ones((nspw, nfld), dtype=bool) if (len(badspw) > 0): mask[badspw, :] = False QU = {} mytb.open(caltable) for ifld in range(nfld): for ispw in range(nspw): st = mytb.query('FIELD_ID==' + str(ifld) + ' && SPECTRAL_WINDOW_ID==' + str(ispw)) nrows = st.nrows() if nrows > 0: rah = dirs[0, ifld] * 12.0 / pi decr = dirs[1, ifld] times = st.getcol('TIME') gains = st.getcol('CPARAM') ants = st.getcol('ANTENNA1') nants = ants.max() + 1 # times time0 = 86400.0 * floor(times[0] / 86400.0) rtimes = times - time0 # amplitude ratio amps = pl.absolute(gains) amps[amps == 0.0] = 1.0 ratio = amps[0, 0, :] / amps[1, 0, :] ratio.resize(nrows / nants, nants) # parang parang = pl.zeros(len(times)) for itim in range(len(times)): tm = myme.epoch('UTC', str(times[itim]) + 's') last = myme.measure(tm, 'LAST')['m0']['value'] last -= floor(last) # days last *= 24.0 # hours ha = last - rah # hours har = ha * 2.0 * pi / 24.0 parang[itim] = atan2((cos(latr) * sin(har)), (sin(latr) * cos(decr) - cos(latr) * sin(decr) * cos(har))) parang.resize(nrows / nants, nants) parang += bandpa(bandnames[ispw]) # feed pos ang offset parang += (paoffset * pi / 180.) # manual feed pa offset parangd = parang * (180.0 / pi) A = pl.ones((nrows / nants, 3)) A[:, 1] = pl.cos(2 * parang[:, 0]) A[:, 2] = pl.sin(2 * parang[:, 0]) fit = pl.lstsq(A, pl.square(ratio)) ants0 = range(nants) rsum = pl.sum(ratio[:, ants0], 1) rsum /= len(ants0) fit = pl.lstsq(A, pl.square(rsum)) R[ispw, ifld] = fit[0][0] Q[ispw, ifld] = fit[0][1] / R[ispw, ifld] / 2.0 U[ispw, ifld] = fit[0][2] / R[ispw, ifld] / 2.0 P = sqrt(Q[ispw, ifld]**2 + U[ispw, ifld]**2) X = 0.5 * atan2(U[ispw, ifld], Q[ispw, ifld]) * 180 / pi print 'Fld=', ifld, 'Spw=', ispw, '(B=' + str( bandnames[ispw]) + ', PA offset=' + str( bandpa(bandnames[ispw]) * 180. / pi) + 'deg)', 'Gx/Gy=', R[ispw, ifld], 'Q=', Q[ ispw, ifld], 'U=', U[ispw, ifld], 'P=', P, 'X=', X else: mask[ispw, ifld] = False st.close() if sum(mask[:, ifld]) > 0: print 'For field id = ', ifld, ' there are ', sum( mask[:, ifld]), 'good spws.' Qm = pl.mean(Q[mask[:, ifld], ifld]) Um = pl.mean(U[mask[:, ifld], ifld]) QU[ifld] = (Qm, Um) Qe = pl.std(Q[mask[:, ifld], ifld]) Ue = pl.std(U[mask[:, ifld], ifld]) Pm = sqrt(Qm**2 + Um**2) Xm = 0.5 * atan2(Um, Qm) * 180 / pi print 'Spw mean: Fld=', ifld, 'Q=', Qm, 'U=', Um, '(rms=', Qe, Ue, ')', 'P=', Pm, 'X=', Xm mytb.close() return QU
def qufromgain(caltable,badspw=[],paoffset=0.0): mytb=taskinit.tbtool() myme=taskinit.metool() mytb.open(caltable+'/ANTENNA') pos=mytb.getcol('POSITION') meanpos=pl.mean(pos,1) frame=mytb.getcolkeyword('POSITION','MEASINFO')['Ref'] units=mytb.getcolkeyword('POSITION','QuantumUnits') mpos=myme.position(frame, str(meanpos[0])+units[0], str(meanpos[1])+units[1], str(meanpos[2])+units[2]) myme.doframe(mpos) # _geodetic_ latitude latr=myme.measure(mpos,'WGS84')['m1']['value'] print 'Latitude = ',latr*180/pi mytb.open(caltable+'/FIELD') nfld=mytb.nrows() dirs=mytb.getcol('DELAY_DIR')[:,0,:] mytb.close() print 'Found as many as '+str(nfld)+' fields.' mytb.open(caltable+'/SPECTRAL_WINDOW') nspw=mytb.nrows() bandnames=[x.split('#')[0].split('_')[-1] for x in mytb.getcol('NAME')] mytb.close() print 'Found as many as '+str(nspw)+' spws.' R=pl.zeros((nspw,nfld)) Q=pl.zeros((nspw,nfld)) U=pl.zeros((nspw,nfld)) mask=pl.ones((nspw,nfld),dtype=bool) if (len(badspw)>0): mask[badspw,:]=False QU={} mytb.open(caltable) for ifld in range(nfld): for ispw in range(nspw): st=mytb.query('FIELD_ID=='+str(ifld)+' && SPECTRAL_WINDOW_ID=='+str(ispw)) nrows=st.nrows() if nrows > 0: rah=dirs[0,ifld]*12.0/pi decr=dirs[1,ifld] times=st.getcol('TIME') gains=st.getcol('CPARAM') ants=st.getcol('ANTENNA1') nants=ants.max()+1 # times time0=86400.0*floor(times[0]/86400.0) rtimes=times-time0 # amplitude ratio amps=pl.absolute(gains) amps[amps==0.0]=1.0 ratio=amps[0,0,:]/amps[1,0,:] ratio.resize(nrows/nants,nants) # parang parang=pl.zeros(len(times)) for itim in range(len(times)): tm=myme.epoch('UTC',str(times[itim])+'s') last=myme.measure(tm,'LAST')['m0']['value'] last-=floor(last) # days last*=24.0 # hours ha=last-rah # hours har=ha*2.0*pi/24.0 parang[itim]=atan2( (cos(latr)*sin(har)), (sin(latr)*cos(decr)-cos(latr)*sin(decr)*cos(har)) ) parang.resize(nrows/nants,nants) parang+=bandpa(bandnames[ispw]) # feed pos ang offset parang+=(paoffset*pi/180.) # manual feed pa offset parangd=parang*(180.0/pi) A=pl.ones((nrows/nants,3)) A[:,1]=pl.cos(2*parang[:,0]) A[:,2]=pl.sin(2*parang[:,0]) fit=pl.lstsq(A,pl.square(ratio)) ants0=range(nants) rsum=pl.sum(ratio[:,ants0],1) rsum/=len(ants0) fit=pl.lstsq(A,pl.square(rsum)) R[ispw,ifld]=fit[0][0] Q[ispw,ifld]=fit[0][1]/R[ispw,ifld]/2.0 U[ispw,ifld]=fit[0][2]/R[ispw,ifld]/2.0 P=sqrt(Q[ispw,ifld]**2+U[ispw,ifld]**2) X=0.5*atan2(U[ispw,ifld],Q[ispw,ifld])*180/pi print 'Fld=',ifld,'Spw=',ispw,'(B='+str(bandnames[ispw])+', PA offset='+str(bandpa(bandnames[ispw])*180./pi)+'deg)','Gx/Gy=',R[ispw,ifld],'Q=',Q[ispw,ifld],'U=',U[ispw,ifld],'P=',P,'X=',X else: mask[ispw,ifld]=False st.close() if sum(mask[:,ifld])>0: print 'For field id = ',ifld,' there are ',sum(mask[:,ifld]),'good spws.' Qm=pl.mean(Q[mask[:,ifld],ifld]) Um=pl.mean(U[mask[:,ifld],ifld]) QU[ifld]=(Qm,Um) Qe=pl.std(Q[mask[:,ifld],ifld]) Ue=pl.std(U[mask[:,ifld],ifld]) Pm=sqrt(Qm**2+Um**2) Xm=0.5*atan2(Um,Qm)*180/pi print 'Spw mean: Fld=', ifld,'Q=',Qm,'U=',Um,'(rms=',Qe,Ue,')','P=',Pm,'X=',Xm mytb.close() return QU
def predictcomp(objname=None, standard=None, epoch=None, minfreq=None, maxfreq=None, nfreqs=None, prefix=None, antennalist=None, showplot=None, savefig=None, symb=None, include0amp=None, include0bl=None, blunit=None, bl0flux=None): """ Writes a component list named clist to disk and returns a dict of {'clist': clist, 'objname': objname, 'angdiam': angular diameter in radians (if used in clist), 'standard': standard, 'epoch': epoch, 'freqs': pl.array of frequencies, in GHz, 'uvrange': pl.array of baseline lengths, in m, 'amps': pl.array of predicted visibility amplitudes, in Jy, 'savedfig': False or, if made, the filename of a plot.} or False on error. objname: An object supported by standard. standard: A standard for calculating flux densities, as in setjy. Default: 'Butler-JPL-Horizons 2010' epoch: The epoch to use for the calculations. Irrelevant for extrasolar standards. minfreq: The minimum frequency to use. Example: '342.0GHz' maxfreq: The maximum frequency to use. Default: minfreq Example: '346.0GHz' Example: '', anything <= 0, or None: use minfreq. nfreqs: The number of frequencies to use. Default: 1 if minfreq == maxfreq, 2 otherwise. prefix: The component list will be saved to prefix + '<objname>_spw0_<minfreq><epoch>.cl' Default: '' antennalist: An array configuration file as used by simdata. If given, a plot of S vs. |u| will be made. Default: '' (None, just make clist.) showplot: Whether or not to show the plot on screen. Subparameter of antennalist. Default: Necessarily False if antennalist is not specified. True otherwise. savefig: Filename for saving a plot of S vs. |u|. Subparameter of antennalist. Default: False (necessarily if antennalist is not specified) Examples: True (save to prefix + '.png') 'myplot.png' (save to myplot.png) symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: '.' include0amp: Force the lower limit of the amplitude axis to 0. Default: False include0bl: Force the lower limit of the baseline length axis to 0. blunit: Unit of the baseline length bl0flux: show zero baseline flux """ retval = False try: casalog.origin('predictcomp') # some parameter minimally required if objname == '': raise Exception, "Error, objname is undefined" if minfreq == '': raise Exception, "Error, minfreq is undefined" minfreqq = qa.quantity(minfreq) minfreqHz = qa.convert(minfreqq, 'Hz')['value'] try: maxfreqq = qa.quantity(maxfreq) except Exception, instance: maxfreqq = minfreqq frequnit = maxfreqq['unit'] maxfreqHz = qa.convert(maxfreqq, 'Hz')['value'] if maxfreqHz <= 0.0: maxfreqq = minfreqq maxfreqHz = minfreqHz if minfreqHz != maxfreqHz: if nfreqs < 2: nfreqs = 2 else: nfreqs = 1 freqs = pl.linspace(minfreqHz, maxfreqHz, nfreqs) myme = metool() mepoch = myme.epoch('UTC', epoch) #if not prefix: ## meanfreq = {'value': 0.5 * (minfreqHz + maxfreqHz), ## 'unit': frequnit} ## prefix = "%s%s_%.7g" % (objname, epoch.replace('/', '-'), ## minfreqq['value']) ## if minfreqHz != maxfreqHz: ## prefix += "to" + maxfreq ## else: ## prefix += minfreqq['unit'] ## prefix += "_" # prefix = '' # if not prefix: if not os.access("./", os.W_OK): casalog.post( "No write access in the current directory, trying to write cl to /tmp...", "WARN") prefix = "/tmp/" if not os.access(prefix, os.W_OK): casalog.post("No write access to /tmp to write cl file", "SEVERE") return False else: prefixdir = os.path.dirname(prefix) if prefixdir == '/' and len(prefix) > 1: prefix = prefix + '/' prefixdir = os.path.dirname(prefix) if not os.path.exists(prefixdir): prefixdirs = prefixdir.split('/') if prefixdirs[0] == "" and len(prefixdirs) > 1: rootdir = "/" + prefixdirs[1] else: rootdir = "./" if os.access(rootdir, os.W_OK): if prefixdir != '': os.makedirs(prefixdir) else: casalog.post( "No write access to " + rootdir + " to write cl file", "SEVERE") return False # Get clist myim = imtool() if hasattr(myim, 'predictcomp'): casalog.post('local im instance created', 'DEBUG1') else: casalog.post('Error creating a local im instance.', 'SEVERE') return False #print "FREQS=",freqs # output CL file name is fixed : prefix+"spw0_"+minfreq+mepoch.cl minfreqGHz = qa.convert(qa.quantity(minfreq), 'GHz')['value'] decimalfreq = minfreqGHz - int(minfreqGHz) decimalepoch = mepoch['m0']['value'] - int(mepoch['m0']['value']) if decimalfreq == 0.0: minfreqGHzStr = str(int(minfreqGHz)) + 'GHz' else: minfreqGHzStr = str(minfreqGHz) + 'GHz' if decimalepoch == 0.0: epochStr = str(int(mepoch['m0']['value'])) + 'd' else: epochStr = str(mepoch['m0']['value']) + 'd' outfilename = "spw0_" + objname + "_" + minfreqGHzStr + epochStr + '.cl' outfilename = prefix + outfilename if (os.path.exists(outfilename) and os.path.isdir(outfilename)): shutil.rmtree(outfilename) casalog.post("Removing the existing componentlist, " + outfilename) if standard == 'Butler-JPL-Horizons 2012': clist = predictSolarObjectCompList(objname, mepoch, freqs.tolist(), prefix) else: clist = myim.predictcomp(objname, standard, mepoch, freqs.tolist(), prefix) #print "created componentlist =",clist if os.path.isdir(clist): # The spw0 is useless here, but it is added by FluxStandard for the sake of setjy. casalog.post('The component list was saved to ' + clist) retval = { 'clist': clist, 'objname': objname, 'standard': standard, 'epoch': mepoch, 'freqs (GHz)': 1.0e-9 * freqs, 'antennalist': antennalist } mycl = cltool() mycl.open(clist) comp = mycl.getcomponent(0) zeroblf = comp['flux']['value'] if standard == 'Butler-JPL-Horizons 2012': f0 = comp['spectrum']['frequency']['m0']['value'] else: f0 = retval['freqs (GHz)'][0] casalog.post("Zero baseline flux %s @ %sGHz " % (zeroblf, f0), 'INFO') mycl.close(False) # False prevents the stupid warning. for k in ('shape', 'spectrum'): retval[k] = comp[k] if antennalist: retval['spectrum']['bl0flux'] = {} retval['spectrum']['bl0flux']['value'] = zeroblf[0] retval['spectrum']['bl0flux']['unit'] = 'Jy' retval['savedfig'] = savefig if not bl0flux: zeroblf = [0.0] retval.update( plotcomp(retval, showplot, wantdict=True, symb=symb, include0amp=include0amp, include0bl=include0bl, blunit=blunit, bl0flux=zeroblf[0])) else: retval['savedfig'] = None else: casalog.post("There was an error in making the component list.", 'SEVERE')
def plotcomp(compdict, showplot=True, wantdict=False, symb=',', include0amp=False, include0bl=False, blunit='', bl0flux=0.0): """ Given a dict including {'clist': component list, 'objname': objname, 'epoch': epoch, 'shape': component shape dict, including direction. 'freqs (GHz)': pl.array of frequencies, 'antennalist': An array configuration file as used by simdata, 'savedfig': False or, if specified, the filename to save the plot to, 'standard': setjy fluxstandard type}, and symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: ',': The smallest points I could find, make a plot of visibility amplitude vs. baseline length for clist at epoch. If antennalist is not found as is, it will look for antennalist in os.getenv('CASAPATH').split(' ')[0] + '/data/alma/simmos/'. showplot: Whether or not to show the plot on screen. If wantdict is True, it returns a dictionary with the amplitudes and baselines on success. Otherwise, it returns True or False as its estimated success value. include0amp: Force the lower limit of the amplitude axis to 0. include0bl: Force the lower limit of the baseline length axis to 0. blunit: unit of the baseline length (='' used the unit in the data or klambda) bl0flux: Zero baseline flux """ def failval(): """ Returns an appropriate failure value. Note that mydict.update(plotcomp(wantdict=True, ...)) would give a confusing error message if plotcomp returned False. """ retval = False if wantdict: retval = {} return retval retval = failval() # Default try: clist = compdict['clist'] objname = compdict['objname'] epoch = compdict['epoch'] epstr = mepoch_to_str(epoch) antennalist = compdict['antennalist'] # Read the configuration info. if not antennalist: print "compdict['antennalist'] must be set!" print "Try something in", os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" return failval() # Try repodir if raw antennalist doesn't work. if not os.path.exists(antennalist): repodir = os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" antennalist = repodir + antennalist su = simutil("") stnx, stny, stnz, diam, padnames, telescopename, obsmeas = su.readantenna(antennalist) #print "telescopename:", telescopename # Check that the source is up. myme = metool() posobs = myme.observatory(telescopename) #print "posobs:", posobs myme.doframe(epoch) myme.doframe(posobs) azel = myme.measure(compdict['shape']['direction'], 'azel') azeldegs = tuple([qa.convert(azel[m], 'deg')['value'] for m in ('m0', 'm1')]) casalog.post("(az, el): (%.2f, %.2f) degrees" % azeldegs) # riseset blabs to the logger, so introduce it now. casalog.post('Rise and set times of ' + objname + " from " + telescopename + ':') approx = '' if 'JPL' in compdict.get('standard', 'JPL'): # The object is in the Solar System or not known to be extragalactic. approx = "APPROXIMATE. The times do not account for the apparent motion of "\ + objname + "." casalog.post(" (" + approx + ")") riset = myme.riseset(compdict['shape']['direction']) msg = '' if riset['rise'] == 'above': msg = objname + " is circumpolar" elif riset['rise'] == 'below': msg = objname + ' is not visible from ' + telescopename if msg: if approx: msg += ' around ' + mepoch_to_str(epoch) casalog.post(msg) else: for t in riset: riset[t]['str'] = mepoch_to_str(riset[t]['utc']) casalog.post(objname + " rises at %s and sets at %s." % (riset['rise']['str'], riset['set']['str'])) tmeridian=(riset['rise']['utc']['m0']['value']+riset['set']['utc']['m0']['value'])/2. casalog.post(objname + ': meridian passage at ' + qa.time(str(tmeridian)+'d')[0]) if approx: riset['NOTE'] = approx if not azel['m1']['value'] > 0.0: casalog.post(objname + " is not visible from " + telescopename + " at " + epstr, 'SEVERE') if wantdict: return riset else: return False # Start a temp MS. workingdir = os.path.abspath(os.path.dirname(clist.rstrip('/'))) tempms = tempfile.mkdtemp(prefix=objname, dir=workingdir) mysm = smtool() mysm.open(tempms) su.setcfg(mysm, telescopename, stnx, stny, stnz, diam, padnames, posobs) #print "cfg set" # Only 1 polarization is wanted for now. stokes, feeds = su.polsettings(telescopename, 'RR') casalog.post("stokes, feeds: %s, %s" % (stokes, feeds)) fband = su.bandname(compdict['freqs (GHz)'][0]) chaninc = 1.0 nchan = len(compdict['freqs (GHz)']) if nchan > 1: chaninc = (compdict['freqs (GHz)'][-1] - compdict['freqs (GHz)'][0]) / (nchan - 1) mysm.setspwindow(spwname=fband, freq=str(compdict['freqs (GHz)'][0]) + 'GHz', deltafreq=str(chaninc) + 'GHz', freqresolution='1Hz', nchannels=nchan, refcode="LSRK", stokes=stokes) mysm.setfeed(mode=feeds, pol=['']) mysm.setlimits(shadowlimit=0.01, elevationlimit='10deg') mysm.setauto(0.0) mysm.setfield(sourcename=objname, sourcedirection=compdict['shape']['direction'], calcode="OBJ", distance='0m') mysm.settimes(integrationtime="1s", usehourangle=False, referencetime=epoch) # this only creates blank uv entries mysm.observe(sourcename=objname, spwname=fband, starttime="-0.5s", stoptime="0.5s", project=objname) mysm.setdata(fieldid=[0]) mysm.setvp() casalog.post("done setting up simulation parameters") mysm.predict(complist=clist) # do actual calculation of visibilities: mysm.close() casalog.post("Simulation finished.") mytb = tbtool() mytb.open(tempms) data = mytb.getcol('DATA')[0] # Again, only 1 polarization for now. data = abs(data) baselines = mytb.getcol('UVW')[:2,:] # Drop w. datablunit = mytb.getcolkeywords('UVW')['QuantumUnits'] mytb.close() #print "Got the data and baselines" shutil.rmtree(tempms) if datablunit[1] != datablunit[0]: casalog.post('The baseline units are mismatched!: %s' % datablunit, 'SEVERE') return failval() datablunit = datablunit[0] # uv dist unit in klambda or m if datablunit == 'm' and blunit=='klambda': kl = qa.constants('C')['value']/(compdict['freqs (GHz)'][0]*1e6) blunit = 'k$\lambda$' else: blunit = datablunit kl = 1.0 pl.ioff() #baselines = pl.hypot(baselines[0]/kl, baselines[1]/kl) baselines = pl.hypot(baselines[0], baselines[1]) #if not showplot: # casalog.post('Sorry, not showing the plot is not yet implemented', # 'WARN') if showplot: pl.ion() pl.clf() pl.ioff() nfreqs = len(compdict['freqs (GHz)']) for freqnum in xrange(nfreqs): freq = compdict['freqs (GHz)'][freqnum] casalog.post("Plotting " + str(freq) + " GHz.") pl.plot(baselines/kl, data[freqnum], symb, label="%.3g GHz" % freq) #pl.plot(baselines, data[freqnum], symb, label="%.3g GHz" % freq) pl.xlabel("Baseline length (" + blunit + ")") pl.ylabel("Visibility amplitude (Jy)") if include0amp: pl.ylim(ymin=0.0) if include0bl: pl.xlim(xmin=0.0) pl.suptitle(objname + " (predicted by %s)" % compdict['standard'], fontsize=14) #pl.suptitle(objname + " (predicted)", fontsize=14) # Unlike compdict['antennalist'], antennalist might have had repodir # prefixed to it. pl.title('at ' + epstr + ' for ' + os.path.basename(compdict['antennalist']), fontsize=10) titletxt='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs # for comparison of old and new models - omit azeldegs as all in az~0 if bl0flux > 0.0: if len(compdict['freqs (GHz)']) == 1: titletxt+='\n bl0 flux:%.3f Jy' % bl0flux else: titletxt+='\n bl0 flux:%.3f Jy @ %s GHz' % (bl0flux, compdict['freqs (GHz)'][0]) pl.legend(loc='best', title=titletxt) #pl.legend(loc='best', title='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs) y_formatter=matplotlib.ticker.ScalarFormatter(useOffset=False) pl.axes().yaxis.set_major_formatter(y_formatter) if showplot: pl.ion() pl.draw() if compdict.get('savedfig'): pl.savefig(compdict.get('savedfig')) casalog.post("Saved plot to " + str(compdict.get('savedfig'))) if wantdict: retval = {'amps': data, 'antennalist': antennalist, # Absolute path, now. 'azel': azel, 'baselines': baselines, 'blunit': blunit, 'riseset': riset, 'savedfig': compdict.get('savedfig')} else: retval = True except Exception, instance: casalog.post(str(instance), 'SEVERE') if os.path.isdir(tempms): shutil.rmtree(tempms)
def plotcomp(compdict, showplot=True, wantdict=False, symb=',', include0amp=False, include0bl=False, blunit='', bl0flux=0.0): """ Given a dict including {'clist': component list, 'objname': objname, 'epoch': epoch, 'shape': component shape dict, including direction. 'freqs (GHz)': pl.array of frequencies, 'antennalist': An array configuration file as used by simdata, 'savedfig': False or, if specified, the filename to save the plot to, 'standard': setjy fluxstandard type}, and symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: ',': The smallest points I could find, make a plot of visibility amplitude vs. baseline length for clist at epoch. If antennalist is not found as is, it will look for antennalist in os.getenv('CASAPATH').split(' ')[0] + '/data/alma/simmos/'. showplot: Whether or not to show the plot on screen. If wantdict is True, it returns a dictionary with the amplitudes and baselines on success. Otherwise, it returns True or False as its estimated success value. include0amp: Force the lower limit of the amplitude axis to 0. include0bl: Force the lower limit of the baseline length axis to 0. blunit: unit of the baseline length (='' used the unit in the data or klambda) bl0flux: Zero baseline flux """ def failval(): """ Returns an appropriate failure value. Note that mydict.update(plotcomp(wantdict=True, ...)) would give a confusing error message if plotcomp returned False. """ retval = False if wantdict: retval = {} return retval retval = failval() # Default try: clist = compdict['clist'] objname = compdict['objname'] epoch = compdict['epoch'] epstr = mepoch_to_str(epoch) antennalist = compdict['antennalist'] # Read the configuration info. if not antennalist: print "compdict['antennalist'] must be set!" print "Try something in", os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" return failval() # Try repodir if raw antennalist doesn't work. if not os.path.exists(antennalist): repodir = os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" antennalist = repodir + antennalist su = simutil("") stnx, stny, stnz, diam, padnames, nant, telescopename = su.readantenna(antennalist) #print "telescopename:", telescopename # Check that the source is up. myme = metool() posobs = myme.observatory(telescopename) #print "posobs:", posobs myme.doframe(epoch) myme.doframe(posobs) azel = myme.measure(compdict['shape']['direction'], 'azel') azeldegs = tuple([qa.convert(azel[m], 'deg')['value'] for m in ('m0', 'm1')]) casalog.post("(az, el): (%.2f, %.2f) degrees" % azeldegs) # riseset blabs to the logger, so introduce it now. casalog.post('Rise and set times of ' + objname + " from " + telescopename + ':') approx = '' if 'JPL' in compdict.get('standard', 'JPL'): # The object is in the Solar System or not known to be extragalactic. approx = "APPROXIMATE. The times do not account for the apparent motion of "\ + objname + "." casalog.post(" (" + approx + ")") riset = myme.riseset(compdict['shape']['direction']) msg = '' if riset['rise'] == 'above': msg = objname + " is circumpolar" elif riset['rise'] == 'below': msg = objname + ' is not visible from ' + telescopename if msg: if approx: msg += ' around ' + mepoch_to_str(epoch) casalog.post(msg) else: for t in riset: riset[t]['str'] = mepoch_to_str(riset[t]['utc']) casalog.post(objname + " rises at %s and sets at %s." % (riset['rise']['str'], riset['set']['str'])) tmeridian=(riset['rise']['utc']['m0']['value']+riset['set']['utc']['m0']['value'])/2. casalog.post(objname + ': meridian passage at ' + qa.time(str(tmeridian)+'d')[0]) if approx: riset['NOTE'] = approx if not azel['m1']['value'] > 0.0: casalog.post(objname + " is not visible from " + telescopename + " at " + epstr, 'SEVERE') if wantdict: return riset else: return False # Start a temp MS. workingdir = os.path.abspath(os.path.dirname(clist.rstrip('/'))) tempms = tempfile.mkdtemp(prefix=objname, dir=workingdir) mysm = smtool() mysm.open(tempms) su.setcfg(mysm, telescopename, stnx, stny, stnz, diam, padnames, posobs) #print "cfg set" # Only 1 polarization is wanted for now. stokes, feeds = su.polsettings(telescopename, 'RR') casalog.post("stokes, feeds: %s, %s" % (stokes, feeds)) fband = su.bandname(compdict['freqs (GHz)'][0]) chaninc = 1.0 nchan = len(compdict['freqs (GHz)']) if nchan > 1: chaninc = (compdict['freqs (GHz)'][-1] - compdict['freqs (GHz)'][0]) / (nchan - 1) mysm.setspwindow(spwname=fband, freq=str(compdict['freqs (GHz)'][0]) + 'GHz', deltafreq=str(chaninc) + 'GHz', freqresolution='1Hz', nchannels=nchan, refcode="LSRK", stokes=stokes) mysm.setfeed(mode=feeds, pol=['']) mysm.setlimits(shadowlimit=0.01, elevationlimit='10deg') mysm.setauto(0.0) mysm.setfield(sourcename=objname, sourcedirection=compdict['shape']['direction'], calcode="OBJ", distance='0m') mysm.settimes(integrationtime="1s", usehourangle=False, referencetime=epoch) # this only creates blank uv entries mysm.observe(sourcename=objname, spwname=fband, starttime="-0.5s", stoptime="0.5s", project=objname) mysm.setdata(fieldid=[0]) mysm.setvp() casalog.post("done setting up simulation parameters") mysm.predict(complist=clist) # do actual calculation of visibilities: mysm.close() casalog.post("Simulation finished.") mytb = tbtool() mytb.open(tempms) data = mytb.getcol('DATA')[0] # Again, only 1 polarization for now. data = abs(data) baselines = mytb.getcol('UVW')[:2,:] # Drop w. datablunit = mytb.getcolkeywords('UVW')['QuantumUnits'] mytb.close() #print "Got the data and baselines" shutil.rmtree(tempms) if datablunit[1] != datablunit[0]: casalog.post('The baseline units are mismatched!: %s' % datablunit, 'SEVERE') return failval() datablunit = datablunit[0] # uv dist unit in klambda or m if datablunit == 'm' and blunit=='klambda': kl = qa.constants('C')['value']/(compdict['freqs (GHz)'][0]*1e6) blunit = 'k$\lambda$' else: blunit = datablunit kl = 1.0 pl.ioff() #baselines = pl.hypot(baselines[0]/kl, baselines[1]/kl) baselines = pl.hypot(baselines[0], baselines[1]) #if not showplot: # casalog.post('Sorry, not showing the plot is not yet implemented', # 'WARN') if showplot: pl.ion() pl.clf() pl.ioff() nfreqs = len(compdict['freqs (GHz)']) for freqnum in xrange(nfreqs): freq = compdict['freqs (GHz)'][freqnum] casalog.post("Plotting " + str(freq) + " GHz.") pl.plot(baselines/kl, data[freqnum], symb, label="%.3g GHz" % freq) #pl.plot(baselines, data[freqnum], symb, label="%.3g GHz" % freq) pl.xlabel("Baseline length (" + blunit + ")") pl.ylabel("Visibility amplitude (Jy)") if include0amp: pl.ylim(ymin=0.0) if include0bl: pl.xlim(xmin=0.0) pl.suptitle(objname + " (predicted by %s)" % compdict['standard'], fontsize=14) #pl.suptitle(objname + " (predicted)", fontsize=14) # Unlike compdict['antennalist'], antennalist might have had repodir # prefixed to it. pl.title('at ' + epstr + ' for ' + os.path.basename(compdict['antennalist']), fontsize=10) titletxt='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs # for comparison of old and new models - omit azeldegs as all in az~0 if bl0flux > 0.0: if len(compdict['freqs (GHz)']) == 1: titletxt+='\n bl0 flux:%.3f Jy' % bl0flux else: titletxt+='\n bl0 flux:%.3f Jy @ %s GHz' % (bl0flux, compdict['freqs (GHz)'][0]) pl.legend(loc='best', title=titletxt) #pl.legend(loc='best', title='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs) y_formatter=matplotlib.ticker.ScalarFormatter(useOffset=False) pl.axes().yaxis.set_major_formatter(y_formatter) if showplot: pl.ion() pl.draw() if compdict.get('savedfig'): pl.savefig(compdict.get('savedfig')) casalog.post("Saved plot to " + str(compdict.get('savedfig'))) if wantdict: retval = {'amps': data, 'antennalist': antennalist, # Absolute path, now. 'azel': azel, 'baselines': baselines, 'blunit': blunit, 'riseset': riset, 'savedfig': compdict.get('savedfig')} else: retval = True except Exception, instance: casalog.post(str(instance), 'SEVERE') if os.path.isdir(tempms): shutil.rmtree(tempms)
def predictcomp(objname=None, standard=None, epoch=None, minfreq=None, maxfreq=None, nfreqs=None, prefix=None, antennalist=None, showplot=None, savefig=None, symb=None, include0amp=None, include0bl=None, blunit=None, bl0flux=None): """ Writes a component list named clist to disk and returns a dict of {'clist': clist, 'objname': objname, 'angdiam': angular diameter in radians (if used in clist), 'standard': standard, 'epoch': epoch, 'freqs': pl.array of frequencies, in GHz, 'uvrange': pl.array of baseline lengths, in m, 'amps': pl.array of predicted visibility amplitudes, in Jy, 'savedfig': False or, if made, the filename of a plot.} or False on error. objname: An object supported by standard. standard: A standard for calculating flux densities, as in setjy. Default: 'Butler-JPL-Horizons 2010' epoch: The epoch to use for the calculations. Irrelevant for extrasolar standards. minfreq: The minimum frequency to use. Example: '342.0GHz' maxfreq: The maximum frequency to use. Default: minfreq Example: '346.0GHz' Example: '', anything <= 0, or None: use minfreq. nfreqs: The number of frequencies to use. Default: 1 if minfreq == maxfreq, 2 otherwise. prefix: The component list will be saved to prefix + 'spw0_<objname>_<minfreq><epoch>.cl' Default: '' antennalist: An array configuration file as used by simdata. If given, a plot of S vs. |u| will be made. Default: '' (None, just make clist.) showplot: Whether or not to show the plot on screen. Subparameter of antennalist. Default: Necessarily False if antennalist is not specified. True otherwise. savefig: Filename for saving a plot of S vs. |u|. Subparameter of antennalist. Default: False (necessarily if antennalist is not specified) Examples: True (save to prefix + '.png') 'myplot.png' (save to myplot.png) symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: '.' include0amp: Force the lower limit of the amplitude axis to 0. Default: False include0bl: Force the lower limit of the baseline length axis to 0. blunit: Unit of the baseline length bl0flux: show zero baseline flux """ retval = False try: casalog.origin('predictcomp') # some parameter minimally required if objname=='': raise Exception, "Error, objname is undefined" if minfreq=='': raise Exception, "Error, minfreq is undefined" minfreqq = qa.quantity(minfreq) minfreqHz = qa.convert(minfreqq, 'Hz')['value'] try: maxfreqq = qa.quantity(maxfreq) except Exception, instance: maxfreqq = minfreqq frequnit = maxfreqq['unit'] maxfreqHz = qa.convert(maxfreqq, 'Hz')['value'] if maxfreqHz <= 0.0: maxfreqq = minfreqq maxfreqHz = minfreqHz if minfreqHz != maxfreqHz: if nfreqs < 2: nfreqs = 2 else: nfreqs = 1 freqs = pl.linspace(minfreqHz, maxfreqHz, nfreqs) myme = metool() mepoch = myme.epoch('UTC', epoch) #if not prefix: ## meanfreq = {'value': 0.5 * (minfreqHz + maxfreqHz), ## 'unit': frequnit} ## prefix = "%s%s_%.7g" % (objname, epoch.replace('/', '-'), ## minfreqq['value']) ## if minfreqHz != maxfreqHz: ## prefix += "to" + maxfreq ## else: ## prefix += minfreqq['unit'] ## prefix += "_" # prefix = '' # if not prefix: if not os.access("./",os.W_OK): casalog.post("No write access in the current directory, trying to write cl to /tmp...","WARN") prefix="/tmp/" if not os.access(prefix, os.W_OK): casalog.post("No write access to /tmp to write cl file", "SEVERE") return False else: prefixdir=os.path.dirname(prefix) if not os.path.exists(prefixdir): prefixdirs = prefixdir.split('/') if prefixdirs[0]=="": rootdir = "/" + prefixdirs[1] else: rootdir = "./" if os.access(rootdir,os.W_OK): os.makedirs(prefixdir) else: casalog.post("No write access to "+rootdir+" to write cl file", "SEVERE") return False # Get clist myim = imtool() if hasattr(myim, 'predictcomp'): casalog.post('local im instance created', 'DEBUG1') else: casalog.post('Error creating a local im instance.', 'SEVERE') return False #print "FREQS=",freqs if standard=='Butler-JPL-Horizons 2012': clist = predictSolarObjectCompList(objname, mepoch, freqs.tolist(), prefix) else: clist = myim.predictcomp(objname, standard, mepoch, freqs.tolist(), prefix) #print "created componentlist =",clist if os.path.isdir(clist): # The spw0 is useless here, but it is added by FluxStandard for the sake of setjy. casalog.post('The component list was saved to ' + clist) retval = {'clist': clist, 'objname': objname, 'standard': standard, 'epoch': mepoch, 'freqs (GHz)': 1.0e-9 * freqs, 'antennalist': antennalist} mycl = cltool() mycl.open(clist) comp = mycl.getcomponent(0) zeroblf=comp['flux']['value'] if standard=='Butler-JPL-Horizons 2012': f0=comp['spectrum']['frequency']['m0']['value'] else: f0=retval['freqs (GHz)'][0] casalog.post("Zero baseline flux %s @ %sGHz " % (zeroblf, f0),'INFO') mycl.close(False) # False prevents the stupid warning. for k in ('shape', 'spectrum'): retval[k] = comp[k] if antennalist: retval['spectrum']['bl0flux']={} retval['spectrum']['bl0flux']['value']=zeroblf[0] retval['spectrum']['bl0flux']['unit']='Jy' retval['savedfig'] = savefig if not bl0flux: zeroblf=[0.0] retval.update(plotcomp(retval, showplot, wantdict=True, symb=symb, include0amp=include0amp, include0bl=include0bl, blunit=blunit, bl0flux=zeroblf[0])) else: retval['savedfig'] = None else: casalog.post("There was an error in making the component list.", 'SEVERE')
def qufromgain(caltable,badspw=[],badant=[],fieldids=[],paoffset=None): mytb=taskinit.tbtool() myme=taskinit.metool() pos=myme.observatory('atca') myme.doframe(pos) # _geodetic_ latitude latr=myme.measure(pos,'WGS84')['m1']['value'] #print 'latitude: ',latr*180/pi mytb.open(caltable+'/FIELD') nfld=mytb.nrows() dirs=mytb.getcol('DELAY_DIR')[:,0,:] mytb.close() print 'Found '+str(nfld)+' fields.' mytb.open(caltable+'/SPECTRAL_WINDOW') freq=mytb.getcol('REF_FREQUENCY') nspw=mytb.nrows() mytb.close() print 'Found '+str(nspw)+' spws.' #sort out pa offset to apply paoff=pl.zeros(nspw) if paoffset==None: # use defaults for ATCA # (should get these from Feed subtable, but cal table doesn't have one) for ispw in range(nspw): if freq[ispw]<30e9 or freq[ispw]>50e9: paoff[ispw]=45. else: paoff[ispw]=135. else: paoff=paoffset R=pl.zeros((nspw,nfld)) Q=pl.zeros((nspw,nfld)) U=pl.zeros((nspw,nfld)) mask=pl.ones((nspw,nfld),dtype=bool) if (len(badspw)>0): mask[badspw,:]=False if (len(fieldids)==0): fieldids=range(nfld) QU={} mytb.open(caltable) for ifld in fieldids: for ispw in range(nspw): if not mask[ispw,ifld]: continue st=mytb.query('FIELD_ID=='+str(ifld)+' && SPECTRAL_WINDOW_ID=='+str(ispw)) nrows=st.nrows() if nrows > 0: rah=dirs[0,ifld]*12.0/pi decr=dirs[1,ifld] times=st.getcol('TIME') gains=st.getcol('CPARAM') ants=st.getcol('ANTENNA1') ntimes=len(pl.unique(times)) nants=ants.max()+1 #print nrows, ntimes, nants # times time0=86400.0*floor(times[0]/86400.0) rtimes=times-time0 # amplitude ratio amps=pl.absolute(gains) amps[amps==0.0]=1.0 ratio=amps[0,0,:]/amps[1,0,:] # parang parang=pl.zeros(len(times)) for itim in range(len(times)): tm=myme.epoch('UTC',str(times[itim])+'s') last=myme.measure(tm,'LAST')['m0']['value'] last-=floor(last) # days last*=24.0 # hours ha=last-rah # hours har=ha*2.0*pi/24.0 parang[itim]=atan2( (cos(latr)*sin(har)), (sin(latr)*cos(decr)-cos(latr)*sin(decr)*cos(har)) ) ratio.resize(nrows/nants,nants) parang.resize(nrows/nants,nants) parang+=paoff[ispw]*pi/180. parangd=parang*(180.0/pi) A=pl.ones((nrows/nants,3)) A[:,1]=pl.cos(2*parang[:,0]) A[:,2]=pl.sin(2*parang[:,0]) fit=pl.lstsq(A,pl.square(ratio)) amask=pl.ones(nants,dtype=bool) if len(badant)>0: amask[badant]=False rsum=pl.sum(ratio[:,amask],1) rsum/=pl.sum(amask) fit=pl.lstsq(A,pl.square(rsum)) R[ispw,ifld]=fit[0][0] Q[ispw,ifld]=fit[0][1]/R[ispw,ifld]/2.0 U[ispw,ifld]=fit[0][2]/R[ispw,ifld]/2.0 P=sqrt(Q[ispw,ifld]**2+U[ispw,ifld]**2) X=0.5*atan2(U[ispw,ifld],Q[ispw,ifld])*180/pi print 'Fld=%i, Spw=%i, PA Offset=%5.1f, Gx/Gy=%5.3f, Q=%5.3f, U=%5.3f, P=%5.3f, X=%5.1f' % (ifld,ispw,paoff[ispw],R[ispw,ifld],Q[ispw,ifld],U[ispw,ifld],P,X) else: mask[ispw,ifld]=False st.close() if (sum(mask[:,ifld]))>0: print 'For field id = ',ifld,' there are ',sum(mask[:,ifld]),'good spws.' Qm=pl.mean(Q[mask[:,ifld],ifld]) Um=pl.mean(U[mask[:,ifld],ifld]) QU[ifld]=(Qm,Um) Qe=pl.std(Q[mask[:,ifld],ifld]) Ue=pl.std(U[mask[:,ifld],ifld]) Pm=sqrt(Qm**2+Um**2) Xm=0.5*atan2(Um,Qm)*180/pi print 'Spw mean: Fld=%i Fractional: Q=%5.3f, U=%5.3f, (rms= %5.3f,%5.3f), P=%5.3f, X=%5.1f' % (ifld,Qm,Um,Qe,Ue,Pm,Xm) mytb.close() return QU