def add_location_markers(self,axis, grid_idx): for name, val in self.markersLocations.iteritems(): ''' find indices of coordinates ''' lat_idx=cm.find_index_recursively(array=self.lats,value=val['lat'],decimals=2) lon_idx=cm.find_index_recursively(array=self.lons,value=val['lon'],decimals=2) ''' add marker ''' axis.plot(self.lons[lon_idx],self.lats[lat_idx],val['type'], color=val['color'], markersize=5) if grid_idx == 0: ''' add label ''' axis.text(self.lons[lon_idx],self.lats[lat_idx],name, color=val['color'], horizontalalignment='center', verticalalignment='bottom', weight='bold')
def get_topo(**kwargs): lats=kwargs['lats'] lons=kwargs['lons'] dem_file=tempfile.gettempdir()+'/terrain_resampled.tmp' dtm,_,_=get_data(dem_file) data=dtm['array'] yg=dtm['yg'] xg=dtm['xg'] idx_lat=[] idx_lon=[] for lat,lon in zip(lats,lons): idx_lat.append(cm.find_index_recursively(array=yg,value=lat,decimals=4)) idx_lon.append(cm.find_index_recursively(array=xg,value=lon,decimals=4)) """ filter out repeated indexes """ indexes_filtered=[] first=True for val in zip(idx_lon,idx_lat): if first: val_foo=val indexes_filtered.append(val) first=False elif val!=val_foo: indexes_filtered.append(val) val_foo=val """ save topo points """ altitude=[] for x,y in zip(idx_lon,idx_lat): altitude.append(data[y,x]) return altitude
def cross_section(self,**kwargs): field_array=kwargs['field'] ''' calculate wind components''' u_array=self.u_array v_array=self.v_array ''' along cross section assuming self.azimuth within [0, 90] ''' wind_dir_section = self.azimuth -180. wx = u_array*np.sin(wind_dir_section*np.pi/180.) wy = v_array*np.cos(wind_dir_section*np.pi/180.) wind_array = -(wx+wy) ''' perpendicular to cross section ''' orthogonal_dir_section =wind_dir_section + 90. qx = u_array*np.sin(orthogonal_dir_section*np.pi/180.) qy = v_array*np.cos(orthogonal_dir_section*np.pi/180.) orth_array = (qx+qy) self.slice_type='cross_section' self.set_panel(option=self.slice_type,wind=False) figsize=self.figure_size['vertical'] ''' get indices of starting and ending coordinates ''' latix_0=cm.find_index_recursively(array=self.lats,value=self.slice[0][0],decimals=2) lonix_0=cm.find_index_recursively(array=self.lons,value=self.slice[0][1],decimals=2) latix_1=cm.find_index_recursively(array=self.lats,value=self.slice[1][0],decimals=2) lonix_1=cm.find_index_recursively(array=self.lons,value=self.slice[1][1],decimals=2) ''' create grid for the entire domain ''' xx = np.arange(0,self.axesval['x'].size) yy = np.arange(0,self.axesval['y'].size) zz = np.arange(0,self.axesval['z'].size) xm,ym,zm = np.meshgrid(xx,yy,zz) ''' convert grid and plotting field to vector columns''' xd=np.reshape(xm,[1,xm.size]).tolist() yd=np.reshape(ym,[1,ym.size]).tolist() zd=np.reshape(zm,[1,zm.size]).tolist() xd=xd[0] yd=yd[0] zd=zd[0] ''' specify grid for interpolated cross section ''' hres = 100 vres = 44 xi = np.linspace(lonix_0, lonix_1, hres) yi = np.linspace(latix_0, latix_1, hres) zi = np.linspace(0, 43, vres) zi=np.array([zi,]*hres) ki=np.ma.empty([vres,hres]) wi=np.ma.empty([vres,hres]) qi=np.ma.empty([vres,hres]) # fillv = field_array.fill_value ''' convert to standard numpy array (not masked) and replace fill values for nans ''' kd=np.ma.filled(field_array, fill_value=np.nan) wd=np.ma.filled(wind_array, fill_value=np.nan) qd=np.ma.filled(orth_array, fill_value=np.nan) ''' convert to 1 column array ''' kd=np.reshape(kd,[kd.size,1]) wd=np.reshape(wd,[wd.size,1]) qd=np.reshape(qd,[qd.size,1]) ''' create kdTree with entire domain''' coords=zip(xd,yd,zd) tree = cKDTree(coords) ''' interpolate using kdTree (nearest neighbor) and averaging the neighborhood ''' neigh = 8 for k in range(vres): coords = zip(yi, xi, zi[:,k]) dist, idx = tree.query( coords, k=neigh, eps=0, p=1, distance_upper_bound=10) kd_mean = np.nanmean(kd[idx],axis=1) wd_mean = np.nanmean(wd[idx],axis=1) qd_mean = np.nanmean(qd[idx],axis=1) ki[k,:]=kd_mean.T wi[k,:]=wd_mean.T qi[k,:]=qd_mean.T component = [wi, qi] comptitle = ['Along-section wind speed [m s-1] (contours)\n', 'Cross-section wind speed [m s-1] (contours)\n'] for n in range(2): """make plot with wind speed along cross section """ with sns.axes_style("white"): fig,ax = plt.subplots(figsize=(8,11*0.5)) ''' add field as image ''' zsynth = self.axesval['z'] gate_hgt=0.25 #[km] extent = [0, self.distance, zsynth[0]-gate_hgt/2., zsynth[-1]+gate_hgt/2.] # im, cmap, norm = self.add_field(ax,array=ki,field=self.var, extent=extent) im, cmap, norm = self.add_field2(ax,array=ki,field=self.var, extent=extent) ''' add terrain profiel ''' prof = Terrain.get_altitude_profile(self) prof = np.asarray(prof) self.add_terrain_profile(ax, prof ,None) self.terrain.array['profile']=prof ''' add contour of wind section ''' X,Y = np.meshgrid(np.linspace(0, self.distance, hres), zsynth) sigma=0.5 section = gaussian_filter(component[n], sigma,mode='nearest') cs = ax.contour(X,Y,section,colors='k', linewidths=1.5, levels=range(-4,26,2)) # cs = ax.contour(X,Y,component[n],colors='k',linewidths=0.5, levels=range(-4,26,2)) ax.clabel(cs, fontsize=12, fmt='%1.0f',) ax.set_yticks(zsynth[1::2]) ytlabels = ["{:3.1f}".format(z) for z in zsynth[1::2]] ax.set_yticklabels(ytlabels) ax.set_ylim(0. , 7.5) ax.set_xlim(0. , self.distance) legname = os.path.basename(self.file) ta=ax.transAxes ax.text(0.05,0.9, legname[:3].upper() + " " + legname[3:5], transform = ta,weight='bold') y,x = zip(*self.slice) stlat='{:3.2f}'.format(y[0]) stlon='{:3.2f}'.format(x[0]) ax.text(0.05,0.85, 'start: ('+stlat+','+stlon+')', transform = ta) enlat='{:3.2f}'.format(y[-1]) enlon='{:3.2f}'.format(x[-1]) ax.text(0.05,0.8, 'end: ('+enlat+','+enlon+')', transform = ta) staz='{:3.1f}'.format(self.azimuth) ax.text(0.05, 0.75, 'az: '+staz, transform=ta) ax.set_xlabel('Distance along cross section [km]') ax.set_ylabel('Altitude [km]') if self.verticalGridMajorOn: ax.grid(True, which = 'major',linewidth=1) if self.verticalGridMinorOn: ax.grid(True, which = 'minor',alpha=0.5) ax.minorticks_on() ''' add color bar ''' fig.colorbar(im,cmap=cmap, norm=norm) ''' add title ''' titext='Dual-Doppler Synthesis: '+ self.get_var_title(self.var)+' (color coded)\n' titext=titext+comptitle[n] line_start='Start time: '+self.synth_start.strftime('%Y-%m-%d %H:%M')+' UTC\n' line_end='End time: '+self.synth_end.strftime('%Y-%m-%d %H:%M')+' UTC' fig.suptitle(titext+line_start+line_end) plt.subplots_adjust(top=0.85,right=1.0) plt.draw() return ki,component
def compare_with_synth(self,**kwargs): """ Method description ---------------------------- Comparison between the synthesis field and flight level data is achieved by: 1) Find all the indexes of the synth grid where the flight trajectory intersects 2) Filter out repeated indexes of the trajectory (LINE) 3) Save geographic coordinates of the LINE 4) In the synth grid, search the 9 nearest neighbors along each point of LINE 5) Fill missing synth values by averaging the neighbors 6) In the flight data, search 15 values nearest to each point of LINE 7) Average each set of 15 values of the flight array """ synth=kwargs['array'] synth_lons=kwargs['x'] synth_lats=kwargs['y'] synth_z=kwargs['z'] zlevel=kwargs['level'] flightmet = kwargs['met'] # flight level meteo field used for comparison noplot = kwargs['noplot'] idx = np.where(synth_z==zlevel) data = np.squeeze(synth[:,:,idx]) flgt_lats,flgt_lons=zip(*self.flightPath) flight_altitude=self.met['palt'] if flightmet in ['u','v']: wspd=self.met['wspd'] wdir=self.met['wdir'] u = -wspd*np.sin(wdir*np.pi/180.) v = -wspd*np.cos(wdir*np.pi/180.) if flightmet == 'u': flight_wspd = u else: flight_wspd = v else: flight_wspd=self.met[flightmet] flgt_lats = np.asarray(cm.around(flgt_lats,4)) flgt_lons = np.asarray(cm.around(flgt_lons,4)) synth_lats = np.asarray(cm.around(synth_lats,4)) synth_lons = np.asarray(cm.around(synth_lons,4)) idx_lat=[] idx_lon=[] for lat,lon in zip(flgt_lats,flgt_lons): idx_lat.append(cm.find_index_recursively(array=synth_lats,value=lat,decimals=4)) idx_lon.append(cm.find_index_recursively(array=synth_lons,value=lon,decimals=4)) """ filter out repeated indexes """ indexes_filtered=[] first=True for val in zip(idx_lon,idx_lat): if first: val_foo=val indexes_filtered.append(val) first=False elif val!=val_foo: indexes_filtered.append(val) val_foo=val """ save geographic coordinates of the line """ line_lat=[] line_lon=[] for lon,lat in indexes_filtered: line_lon.append(synth_lons[lon]) line_lat.append(synth_lats[lat]) linesynth=zip(line_lon,line_lat) """ search nearest neighbors """ synth_coord=list(product(synth_lons,synth_lats)) tree = cKDTree(synth_coord) neigh = 9 dist, idx = tree.query(linesynth, k=neigh, eps=0, p=2, distance_upper_bound=0.1) """ convert to one-column array """ grid_shape=data.shape data = data.reshape(grid_shape[0]*grid_shape[1],1) """ gets the center point """ idx_split=zip(*idx) idx0 = list(idx_split[0]) """ extract center point value """ data_extract=data[idx0] """ average neighbors """ data_extract2=[] for i in idx: data_extract2.append(np.nanmean(data[i])) """ save center points of line """ line_center=[] line_neighbors=[] for i in idx: value=np.unravel_index(i[0], grid_shape) line_center.append(value) for j in i[1:]: value=np.unravel_index(j, grid_shape) line_neighbors.append(value) """ convert back to 2D array """ data=data.reshape(121,131) """ swap coordinates to (lon,lat)""" flight_coord = [(t[1], t[0]) for t in self.flightPath] tree = cKDTree(flight_coord) neigh = 15 dist, idx = tree.query(linesynth, k=neigh, eps=0, p=2, distance_upper_bound=0.1) """ average flight data """ flgt_mean=[] flgt_altitude=[] for i in idx: flgt_mean.append(np.nanmean(flight_wspd[i])) flgt_altitude.append(np.nanmean(flight_altitude[i])) """ make plots """ jet = plt.get_cmap('jet') cNorm = colors.Normalize(vmin=np.amin(data), vmax=np.amax(data)) scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) synth_alt=str(int(zlevel[0]*1000)) flgt_alt=str(int(np.average(flgt_altitude))) if flightmet == 'wspd': windtype = 'Horizontal' elif flightmet == 'u': windtype = 'U-component' elif flightmet == 'v': windtype = 'V-component' elif flightmet == 'wvert': windtype = 'Vertical' antext1='Synthesis alt: '+synth_alt+' m MSL' antext2='Flight level alt: '+flgt_alt+' m MSL' title1=windtype +' wind speed\n'+self.name title2='Flight level and P3 synthesis comparison - '+windtype+' wind speed\n'+self.name if noplot is True: pass else: ''' grid ''' plt.figure(figsize=(8,7)) im=plt.imshow(data.T, interpolation='none',origin='lower',cmap='jet') for p,val in zip(line_center,data_extract2): colorVal=scalarMap.to_rgba(val) plt.plot(p[0],p[1],color=colorVal,marker='s',markersize=6,linestyle='none') plt.xlabel('X') plt.ylabel('Y') plt.colorbar(im) plt.annotate(antext1, xy=(0.1, 0.95), xycoords="axes fraction",fontsize=14) plt.suptitle(title1) plt.grid(which='major') plt.draw() ''' timeseries ''' fig, ax1 = plt.subplots(figsize=(8,7)) ln1=ax1.plot(data_extract,'bo',label='raw synthesis wind') ln2=ax1.plot(data_extract2,'rs',label='synthesis wind interpolated') ln3=ax1.plot(flgt_mean,'g',label='flight wind') ax1.set_ylabel('wind speed [m/s]') ax1.set_xlabel('Points along line') ax2=ax1.twinx() vmin=min(flgt_altitude)-50 vmax=max(flgt_altitude)+50 ln4=ax2.plot(flgt_altitude,'black',label='flight altitude') ax2.set_ylim([vmin,vmax]) ax2.set_ylabel('Meters MSL') lns=ln1+ln2+ln3+ln4 labs=[l.get_label() for l in lns] ax2.legend(lns,labs,numpoints=1,loc=4,prop={'size':10}) ax2.annotate(antext1, xy=(0.5, 0.9), xycoords="axes fraction",fontsize=14) plt.grid(which='major') plt.suptitle(title2) plt.draw() ''' scatter ''' # with sns.axes_style("darkgrid"): fig,ax=plt.subplots(figsize=(8,7)) # fig,ax=plt.subplots() x=np.asarray(flgt_mean) y=np.asarray(data_extract2) ax.scatter(x,y) #---------- # 1:1 line #========== maxx=np.nanmax(x) minx=np.nanmin(x) maxy=np.nanmax(y) miny=np.nanmin(y) mmax=np.max([maxx,maxy]) mmin=np.min([minx,miny]) x1to1=np.linspace(-30,30,3) y1to1=x1to1 ax.plot(x1to1, y1to1, color='k', linestyle='-', linewidth=2) #------------- # regression #============= xs = x[~np.isnan(y)] ys = y[~np.isnan(y)] model=sm.OLS(ys,xs) result=model.fit() c=0 m=result.params[0] xr=np.linspace(-30,30,3) yr=c+m*xr ax.plot(xr, yr, color='r', linestyle=':', linewidth=2) #-------------- r2=np.round(result.rsquared,decimals=2) m=np.round(m,decimals=2) antext3="R-sqr: "+str(r2) antext4="Y = "+str(m)+" * X" textstr = antext2+'\n'+antext1+'\n'+antext3+'\n'+antext4 ax.text(0.5, 0.05, textstr, transform=ax.transAxes, fontsize=14, verticalalignment='bottom') ax.set_aspect(1) ax.set_xlim([mmin*0.95, mmax*1.05]) ax.set_ylim([mmin*0.95, mmax*1.05]) plt.suptitle(title2) plt.xlabel('Flight wind speed [m s-1]') plt.ylabel('Synthesis wind speed [m s-1]') plt.grid(which='major') return flgt_mean, data_extract2