casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
task_plotweather.py
Go to the documentation of this file.
00001 ###############################################
00002 ## To plot stuff in weather tables, saved to MSname+.plotWX.png
00003 ## and estimate zenith opacity per spw, returned as a list named myTau
00004 ##
00005 ##
00006 ## J. Marvil 2.6.12
00007 ## revised 4.27.12 to add support for missing/empty weather table
00008 ## revised 11.05.12 to address CASA 4.0 changes
00009 ###############################################
00010 
00011 
00012 import casac
00013 from taskinit import *
00014 import pylab as pl
00015 from math import pi,floor
00016 import os.path as osp
00017 
00018 
00019 ###############
00020 ## hides the extreme Y-axis ticks, helps stack plots close together without labels overlaping
00021 def jm_clip_Yticks():
00022     xa=pl.gca()
00023     nlabels=0
00024     for label in xa.yaxis.get_ticklabels(): 
00025         nlabels+=1
00026     thislabel=0
00027     if nlabels>3:
00028         for label in xa.yaxis.get_ticklabels(): 
00029             if thislabel==0: label.set_alpha(0)            
00030             if thislabel==nlabels-1: label.set_alpha(0)
00031             thislabel+=1
00032 
00033 ##############
00034 ##  sets the position of the y-axis label to the right side of the plot, can also move up/down
00035 def jm_set_Ylabel_pos(pos=(0.5,0.5)):
00036     ax=pl.gca();
00037     ax.yaxis.set_label_position('right')
00038     ax.yaxis.label.set_rotation(270)
00039     ax.yaxis.label.set_position(pos)
00040 
00041 
00042 ###############
00043 ## fixed y-ticks, from myMin to myMax
00044 def jm_set_Ylim_ticks(myMin=-1,myMax=1):
00045     myYlocs=pl.linspace(round(myMin,1),round(myMax,1),5)
00046     myLocator = pl.FixedLocator(myYlocs)
00047     ax=pl.gca()
00048     ax.yaxis.set_major_locator( myLocator )
00049     pl.ylim(myMin,myMax)
00050     jm_clip_Yticks()
00051 
00052 ###############
00053 ## variable y-ticks, but not more than 1+ this argument
00054 def jm_set_Yvar_ticks(myScale=4):
00055     xa=pl.gca()
00056     xa.yaxis.set_major_locator(pl.MaxNLocator(myScale))
00057     jm_clip_Yticks()
00058 
00059 ###############
00060 ## calculates K-band zenith opacity from temperature and dewpoint
00061 def Tau_K_Calc(D,T,day, weights=(.5,.5)): 
00062     P = pl.exp(1.81+(17.27*D)/(D+237.3)) # water vapor partial pressure 
00063     h = 324.7*P/(T+273.15) # PWV in mm 
00064     tau_w = 3.8 + 0.23*h + 0.065*h**2 # tau from weather, in %, at 22GHz
00065     if day > 199: day = day - 365. 
00066     m = day + 165. # modified day of the year 
00067     tau_d = 22.1 - 0.178*m + 0.00044*m**2 # tau from seaonal model, in % 
00068     tau_k = weights[0]*tau_w + weights[1]*tau_d # the average, with equal weights (as in the AIPS default) 
00069     return tau_k, h
00070 
00071 ################
00072 ## calculates elevation of the sun
00073 def jm_sunEL(mytime):
00074     me.doframe(me.observatory('VLA'))
00075     me.doframe(me.epoch('utc',mytime))
00076     mysun=me.measure(me.direction('SUN'),'AZELGEO')
00077     return mysun['m1']['value']
00078 
00079 ################
00080 ## gets and plots data from the weather table of the given MS
00081 def plotweather(vis='', seasonal_weight=0.5, doPlot=True, plotName = ''):
00082     myMS=vis
00083     if plotName == '': plotName = myMS+'.plotweather.png'
00084 
00085     # check for weather table
00086 
00087     if osp.isdir(myMS+'/WEATHER'):
00088     
00089         try:
00090             tb.open(myMS+'/WEATHER')
00091             firstTime = tb.getcol('TIME')[0]
00092             tb.close()
00093             WEATHER_table_exists = True
00094 
00095         except:
00096             print 'could not open weather table, using seasonal model only and turning off plots'
00097             WEATHER_table_exists = False
00098             doPlot=False
00099             seasonal_weight = 1.0
00100     else:
00101         print 'could not find a weather table, using seasonal model only and turning off plots'
00102         WEATHER_table_exists = False
00103         doPlot=False
00104         seasonal_weight = 1.0
00105 
00106 
00107 
00108     ##retrieve center frequency for each sub-band
00109     tb.open(myMS+'/SPECTRAL_WINDOW')
00110     spwFreqs=tb.getcol('REF_FREQUENCY') * 1e-9   
00111     tb.close()
00112 
00113     ##retrieve stuff from weather table, if exists
00114     
00115     if WEATHER_table_exists:
00116         tb.open(myMS+'/WEATHER')
00117         mytime=tb.getcol('TIME')
00118         mytemp=tb.getcol('TEMPERATURE') - 273.15
00119         mydew=tb.getcol('DEW_POINT') - 273.15
00120         mywinds=tb.getcol('WIND_SPEED')
00121         mywindd=tb.getcol('WIND_DIRECTION')*(180.0/pi)
00122         mypres=tb.getcol('PRESSURE')
00123         myhum=tb.getcol('REL_HUMIDITY')
00124         tb.close()
00125 
00126     else:
00127         ms.open(myMS)
00128         mytime_range = ms.range(["time"])
00129         mytime = [mytime_range['time'][0]]
00130 
00131 
00132     ##calculate the elevation of the sun
00133     sunEL=[]
00134     for time in mytime:
00135         t1= qa.quantity(time,'s')
00136         myday=qa.convert(t1,'d')
00137         sunEL1=jm_sunEL(myday)        
00138         sunEL.append(sunEL1)
00139 
00140     ##convert time to a string of date/time
00141     myTimestr = []
00142     myTimestr2=[]
00143     for time in mytime:
00144         q1=qa.quantity(time,'s')
00145         time1=qa.time(q1,form='ymd')[0]
00146         time2=qa.time(q1,form='local')[0]
00147         myTimestr.append(time1)
00148         myTimestr2.append(time2)
00149  
00150     ##convert time to a decimal
00151     numtime=pl.datestr2num(myTimestr)    
00152 
00153     ##### calculate opacity as in EVLA memo 143
00154     thisday= 30*(float(myTimestr[0][5:7])-1)+float(myTimestr[0][8:10]) 
00155     thisday=thisday + 5 * (thisday / 365.)
00156 
00157 
00158     if WEATHER_table_exists:
00159         # get 22 GHz zenith opacity and pwv estimate from weatherstation (myPWV)
00160         myTauZ, myPWV1 = Tau_K_Calc(mydew,mytemp,thisday)
00161         myTauZ1, myPWV = Tau_K_Calc(mydew,mytemp,thisday, weights=(0,1.0))
00162         myTauZ2, myPWV = Tau_K_Calc(mydew,mytemp,thisday, weights=(1.0,0))
00163 
00164         # estimate pwv from seasonal model zenith opacity    
00165         myPWV2 = -1.71 + 1.3647*myTauZ1
00166         myPWV = (1-seasonal_weight)*myPWV1 + seasonal_weight*myPWV2
00167  
00168     else:
00169         day = thisday*1.0
00170         if day > 199: day = day - 365. 
00171         m = day + 165. # modified day of the year 
00172         myTauZ = 22.1 - 0.178*m + 0.00044*m**2 # tau from seaonal model, in % 
00173         myPWV = -1.71 + 1.3647*myTauZ
00174         myPWV1, myPWV2 = myPWV, myPWV
00175         myTauZ1, myTauZ2 = myTauZ, myTauZ
00176  
00177     tmp = qa.quantity(270.0,'K')
00178     pre = qa.quantity(790.0,'mbar')
00179     alt = qa.quantity(2125,'m')
00180     h0 = qa.quantity(2.0,'km')
00181     wvl = qa.quantity(-5.6, 'K/km')
00182     mxA = qa.quantity(48,'km')
00183     dpr = qa.quantity(10.0,'mbar')
00184     dpm = 1.2
00185     att = 1
00186     nb = 1
00187 
00188     fC=qa.quantity(25.0,'GHz')
00189     fW=qa.quantity(50.,'GHz')
00190     fR=qa.quantity(0.25,'GHz')
00191 
00192     at=casac.atmosphere()
00193     hum=20.0
00194 
00195     myatm=at.initAtmProfile(alt,tmp,pre,mxA,hum,wvl,dpr,dpm,h0,att)
00196 
00197     at.initSpectralWindow(nb,fC,fW,fR)
00198     sg=at.getSpectralWindow()
00199     mysg = sg['value']
00200 
00201     nstep = 20
00202     pwv = []  
00203     opac = pl.zeros((len(mysg),nstep))
00204     
00205     for i in range(nstep):
00206         hum = 20.0*(i+1)
00207         myatm = at.initAtmProfile(alt,tmp,pre,mxA,hum,wvl,dpr,dpm,h0,att)
00208         w=at.getGroundWH2O()
00209         pwv.append(w['value'][0])
00210         at.initSpectralWindow(nb,fC,fW,fR)
00211         at.setUserWH2O(w)
00212         sg=at.getSpectralWindow()
00213         mysg = sg['value']
00214         sdry=at.getDryOpacitySpec()
00215         swet=at.getWetOpacitySpec()
00216         sd=sdry[1]
00217         sw=swet[1]['value']
00218         stot = pl.array(sd)+pl.array(sw)
00219         opac[:,i]=stot
00220 
00221     pwv_coef=pl.zeros((len(mysg),2))
00222     for i in range(len(mysg)):
00223         myfit=pl.polyfit(pwv,opac[i,:],1)
00224         pwv_coef[i,:]=myfit
00225     
00226     freqs=pl.array(mysg)/1e9
00227     coef0=pwv_coef[:,1]/1e-3
00228     coef1=pwv_coef[:,0]/1e-3
00229 
00230 
00231     #interpolate between nearest table entries for each spw center frequency
00232     meanTau=[]
00233 
00234     for i in range(len(spwFreqs)):
00235         mysearch=(pl.array(freqs)-spwFreqs[i])**2
00236         hits=pl.find(mysearch == min(mysearch))
00237         if len(hits) > 1: hits=hits[0]
00238         tau_interp = (pl.array(coef0[hits-2:hits+2])+pl.array(coef1[hits-2:hits+2])*pl.mean(myPWV)) * 1e-1  #percent
00239         tau_F = pl.interp(spwFreqs[i],freqs[hits-2:hits+2],tau_interp)
00240         meanTau.append(pl.mean(tau_F*.01))  #nepers
00241 
00242 
00243     tau_allF = (pl.array(coef0) + pl.array(coef1)*pl.mean(myPWV)) * 1e-1  #percent
00244     tau_allF1 = (pl.array(coef0) + pl.array(coef1)*pl.mean(myPWV1)) *1e-1  
00245     tau_allF2 = (pl.array(coef0) + pl.array(coef1)*pl.mean(myPWV2)) *1e-1  
00246 
00247     casalog.post('SPW : Frequency (GHz) : Zenith opacity (nepers)')
00248     for i in range(len(meanTau)):
00249         myStr = str(i).rjust(3) + '  :  ' 
00250         myStr2 = '%.3f'%(spwFreqs[i])
00251         myStr += myStr2.rjust(7) + '  :  ' +str(round(meanTau[i], 3))
00252         casalog.post(myStr)
00253 
00254 
00255 
00256     ##make the plots
00257 
00258     if doPlot==False:
00259         return meanTau
00260 
00261     pl.ioff()
00262     myColor2='#A6A6A6'
00263     myColorW='#92B5F2'
00264     myColor1='#4D4DFF'  
00265     myOrangeColor='#FF6600'
00266     myYellowColor='#FFCC00'
00267     myWeirdColor='#006666'
00268     myLightBrown='#996633'
00269     myDarkGreay='#333333'
00270 
00271     thisfig=pl.figure(1)
00272     thisfig.clf()
00273     thisfig.set_size_inches(8.5,10)
00274 
00275     Xrange=numtime[-1]-numtime[0]
00276     Yrange=max(mywinds)-min(mywinds)
00277     Xtextoffset=-Xrange*.01
00278     Ytextoffset=-Yrange*.08
00279     Xplotpad=Xrange*.03
00280     Yplotpad=Yrange*.03
00281 
00282     sp1=thisfig.add_axes([.13,.8,.8,.15])
00283     pl.ylabel('solar el')
00284     nsuns=30
00285     myj=pl.array(pl.linspace(0,len(sunEL)-1,nsuns),dtype='int')
00286     for i in myj:
00287         if sunEL[i]<0: pl.plot([numtime[i],numtime[i]],[(180/pi)*sunEL[i],(180/pi)*sunEL[i]],'kH')
00288         else: pl.plot([numtime[i],numtime[i]],[(180/pi)*sunEL[i],(180/pi)*sunEL[i]],'H',color=myYellowColor)
00289     pl.plot([numtime[0],numtime[-1]],[0,0],'-',color='brown')
00290     xa=pl.gca(); xa.set_xticklabels('')
00291     jm_set_Ylim_ticks(myMin=-90,myMax=90)
00292     jm_set_Ylabel_pos(pos=(0,.5))
00293     pl.title('Weather Summary for '+myMS)
00294     pl.xlim(numtime[0]-Xplotpad,numtime[-1]+Xplotpad)
00295     xa.set_xticks(pl.linspace(min(numtime),max(numtime),3))
00296 
00297     sp2=thisfig.add_axes([.13,.65,.8,.15])
00298     pl.ylabel('wind (m/s)')
00299     nwind=60
00300     myj=pl.array(pl.linspace(0,len(mywinds)-1,nwind),dtype='int')
00301     for i in myj:
00302         pl.text(numtime[i]+Xtextoffset,Ytextoffset+mywinds[i],'-->',rotation=mywindd[i], alpha=1,color='purple',fontsize=12) 
00303 
00304     pl.plot(numtime, .3+mywinds,'.', color='black', ms=2, alpha=0)
00305     jm_set_Ylabel_pos(pos=(0,.5))
00306     jm_set_Yvar_ticks(5)
00307     xa=pl.gca(); xa.set_xticklabels('')
00308     pl.xlim(numtime[0]-Xplotpad,numtime[-1]+Xplotpad)
00309     pl.ylim(min(mywinds)-Yplotpad,max(mywinds)+Yplotpad)
00310     xa.set_xticks(pl.linspace(min(numtime),max(numtime),3))
00311 
00312     sp4=thisfig.add_axes([.13,.5,.8,.15])
00313     pl.plot(numtime, mytemp,'-', color=myOrangeColor,lw=2)      
00314     pl.plot(numtime, mydew,'-', color=myWeirdColor,lw=2)      
00315     pl.ylabel('temp,dew')
00316     jm_set_Ylabel_pos(pos=(0, .5))
00317     xa=pl.gca(); xa.set_xticklabels('')
00318     jm_set_Yvar_ticks(5)
00319     pl.xlim(numtime[0]-Xplotpad,numtime[-1]+Xplotpad)
00320     xa.set_xticks(pl.linspace(min(numtime),max(numtime),3))
00321 
00322     sp7=thisfig.add_axes([.13,.35,.8,.15])
00323     pl.ylabel('PWV (mm)')
00324     pl.plot(numtime, myPWV2, color=myColor2, lw=2, label='seasonal model')
00325     pl.plot(numtime, myPWV1, color=myColor1, lw=2, label='weather station')
00326     pl.plot(numtime, myPWV, color=myColorW,lw=2, label='weighted')
00327 
00328     thismin=min([min(myPWV),min(myPWV1),min(myPWV2)])
00329     thismax=max([max(myPWV),max(myPWV1),max(myPWV2)])
00330     pl.ylim(.8*thismin,1.2*thismax)
00331     jm_set_Ylabel_pos(pos=(0,.5))
00332     jm_set_Yvar_ticks(5)
00333     xa=pl.gca(); xa.set_xticklabels('')
00334     pl.xlim(numtime[0]-Xplotpad,numtime[-1]+Xplotpad)
00335 
00336     middletimei=int(floor(len(myTimestr)/2.))
00337     middletimes=str(myTimestr[middletimei])[11:]
00338     endtimes=myTimestr[-1][11:]                
00339     ax=pl.gca()
00340     axt=ax.get_xticks()
00341     ax.set_xticks(pl.linspace(min(numtime),max(numtime),3))
00342     ax.set_xticklabels([myTimestr[0],middletimes,endtimes ])
00343 
00344     sp8=thisfig.add_axes([.13,.1,.8,.2])
00345     pl.plot(freqs,.01*tau_allF2,'-', color=myColor2, lw=2, label='seasonal model')
00346     pl.plot(freqs,.01*tau_allF1,'-', color=myColor1, lw=2, label='weather station')
00347     pl.plot(freqs,.01*tau_allF,'-', color=myColorW, lw=2,label='weighted')
00348 
00349   
00350     sp8.legend(loc=2, borderaxespad=0)
00351     pl.ylabel('Tau_Z (nepers)')
00352     pl.xlabel('Frequency (GHz)')
00353     pl.ylim(0,.25)
00354     jm_set_Yvar_ticks(6)
00355     jm_set_Ylabel_pos(pos=(0,.5))
00356     pl.savefig( plotName, dpi=150)
00357     pl.close()
00358 
00359     casalog.post('wrote weather figure: '+plotName)
00360     return meanTau
00361 
00362