def geom_polar_grid(rmin, rmax, nr, phimin, phimax, nphi, d): r = np.linspace(rmin, rmax, nr) #km: create nr grid points on radial direction """answer la: yes""" phi = np.linspace(phimin, phimax, nphi) * np.pi / 180 #km: create nphi grid points on azimuth direction """answer la: yes""" r_g, phi_g = np.meshgrid(r, phi) #km: construct the polar grid and save cordinates in r_g and phi_g """answer la: yes""" r_t, phi_t = wr.translationpolargrid((r_g, np.pi - phi_g), d / 2) #translate the polar grid """answer la: yes""" return (r_g, phi_g, r_t, phi_t)
def early_weights_kernel(r, phi, dir_mean, tri, d, center, n=21, m=51): gamma = (2 * np.pi - dir_mean) r_unique = np.unique(r) phi_unique = np.unique(phi) delta_r = np.min(np.diff(r_unique)) delta_phi = np.min(np.diff(phi_unique)) r_refine = np.linspace(r_unique.min() - delta_r / 2, r_unique.max() + delta_r / 2, len(r_unique) * (n - 1) + 1) phi_refine = np.linspace(phi_unique.min() - delta_phi / 2, phi_unique.max() + delta_phi / 2, len(phi_unique) * (m - 1) + 1) r_t_refine, phi_t_refine = np.meshgrid(r_refine, phi_refine) #LOS angles s_ref = np.sin(phi_t_refine - gamma) c_ref = np.cos(phi_t_refine - gamma) r_t_refine, phi_t_refine = wr.translationpolargrid( (r_t_refine, phi_t_refine), d) x_t_refine, y_t_refine = r_t_refine * np.cos( phi_t_refine), r_t_refine * np.sin(phi_t_refine) # Rotation and translation x_trans = -(center) * np.sin(gamma) y_trans = (center) * (1 - np.cos(gamma)) S11 = np.cos(gamma) S12 = np.sin(gamma) T1 = np.array([[1, 0, x_trans], [0, 1, y_trans], [0, 0, 1]]) R = np.array([[S11, S12, 0], [-S12, S11, 0], [0, 0, 1]]) Xx = np.array(np.c_[x_t_refine.flatten(), y_t_refine.flatten(), np.ones(len(y_t_refine.flatten()))]).T Xx = np.dot(T1, np.dot(R, Xx)) uv = Xx[:2, :].T vtx, wts = interp_weights2(uv, tri, d=2) h = 2 * (np.r_[np.repeat(r_unique, (n - 1)), r_unique[-1]] - r_refine) / delta_r w = .75 * (1 - h**2) w = np.reshape(np.repeat(w, phi_t_refine.shape[0]), (phi_t_refine.T).shape).T norm = np.sum(w[0, :(n - 1)]) w = w / norm shapes = np.array([phi_t_refine.shape[0], phi_t_refine.shape[1], n, m]) return (vtx, wts, w, c_ref, s_ref, shapes)
def early_weights_pulsed(r, phi, dl, dir_mean , tri, d, center, n=21, m=51): gamma = (2*np.pi-dir_mean) r_unique = np.unique(r) phi_unique = np.unique(phi) delta_r = np.min(np.diff(r_unique)) delta_phi = np.min(np.diff(phi_unique)) r_refine = np.linspace(r_unique.min()-delta_r/2,r_unique.max()+ delta_r/2,len(r_unique)*(n-1)+1) phi_refine = np.linspace(phi_unique.min()-delta_phi/2, phi_unique.max()+ delta_phi/2, len(phi_unique)*(m-1)+1) r_t_refine, phi_t_refine = np.meshgrid(r_refine,phi_refine) #LOS angles s_ref = np.sin(phi_t_refine-gamma) c_ref = np.cos(phi_t_refine-gamma) r_t_refine, phi_t_refine = wr.translationpolargrid((r_t_refine, phi_t_refine),d) x_t_refine, y_t_refine = r_t_refine*np.cos(phi_t_refine), r_t_refine*np.sin(phi_t_refine) # Rotation and translation x_trans = -(center)*np.sin(gamma) y_trans = (center)*(1-np.cos(gamma)) S11 = np.cos(gamma) S12 = np.sin(gamma) T1 = np.array([[1,0,x_trans], [0,1, y_trans], [0, 0, 1]]) R = np.array([[S11,S12,0], [-S12,S11, 0], [0, 0, 1]]) Xx = np.array(np.c_[x_t_refine.flatten(), y_t_refine.flatten(), np.ones(len(y_t_refine.flatten()))]).T Xx = np.dot(T1,np.dot(R,Xx)) uv = Xx[:2,:].T vtx, wts = interp_weights2(uv, tri, d = 2) aux_1 = np.reshape(np.repeat(r_unique,len(r_refine),axis = 0),(len(r_unique),len(r_refine))) aux_2 = np.reshape(np.repeat(r_refine,len(r_unique)),(len(r_refine),len(r_unique))).T r_F = aux_1-aux_2 rp = dl/(2*np.sqrt(np.log(2))) erf = sp.special.erf((r_F+.5*delta_r)/rp)-sp.special.erf((r_F-.5*delta_r)/rp) w = (1/2/delta_r)*erf shapes = np.array([phi_t_refine.shape[0], phi_t_refine.shape[1], n, m]) return (vtx, wts, w, c_ref, s_ref, shapes)
def geom_polar_grid(rmin,rmax,nr,phimin,phimax,nphi,d): r = np.linspace(rmin,rmax,nr) phi = np.linspace(phimin,phimax,nphi)*np.pi/180 r_g, phi_g = np.meshgrid(r,phi) r_t,phi_t = wr.translationpolargrid((r_g, np.pi-phi_g),d/2) return (r_g, phi_g, r_t, phi_t)
def early_weights_pulsed(r, phi, dl, dir_mean, tri, d, center, beam_orig, scanner_id, L_x, L_y, n=21, m=51): gamma = (2 * np.pi - dir_mean) #km5: why this rotation ? r_unique = np.unique( r) #km5:remove the repeating radial coorddinates (local cs) phi_unique = np.unique( phi) #km5:remove the repeating azimuthal coorddinates (local cs) delta_r = np.min(np.diff(r_unique)) #km5:find radial spacing delta_phi = np.min(np.diff(phi_unique)) #km5:find azimuthal spacing r_refine = np.linspace( r_unique.min() - delta_r / 2, r_unique.max() + delta_r / 2, len(r_unique) * (n - 1) + 1) #km5:create refine discretization in the radial direction phi_refine = np.linspace( phi_unique.min() - delta_phi / 2, phi_unique.max() + delta_phi / 2, len(phi_unique) * (m - 1) + 1) #km5:create refine discretization in the azimuthal direction r_t_refine, phi_t_refine = np.meshgrid( r_refine, phi_refine) #km5: generte the refine mesh #LOS angles s_ref = np.sin(phi_t_refine - gamma) #km5: what does (phi_t_refine-gamma) represent ? c_ref = np.cos(phi_t_refine - gamma) r_t_refine, phi_t_refine = wr.translationpolargrid( (r_t_refine, phi_t_refine), d) #km5: tranlation to the global polar cs x_t_refine, y_t_refine = r_t_refine * np.cos( phi_t_refine), r_t_refine * np.sin( phi_t_refine) #km5:from polar to cartesian """ !!!!!!!!!!!! try plugging in beam2() from here""" beam_orig[0] = -d[0] ### # Rotation and translation #km change: x_trans = -(center) * np.sin( gamma) #km5: find the translated center of the scanners y_trans = (center) * (1 - np.cos(gamma)) S11 = np.cos(gamma) S12 = np.sin(gamma) T1 = np.array([[1, 0, x_trans], [0, 1, y_trans], [0, 0, 1]]) R = np.array([[S11, S12, 0], [-S12, S11, 0], [0, 0, 1]]) Xx = np.array(np.c_[x_t_refine.flatten(), y_t_refine.flatten(), np.ones(len(y_t_refine.flatten()))]).T #uv=Xx[:2,:].T Xx = np.dot(T1, np.dot(R, Xx)) uv_t = Xx[:2, :].T #################################################################### r_refine_unique = np.unique(r_refine) phi_refine_unique = np.unique(phi_refine) delta_r_refine = np.min( np.diff(r_refine_unique)) #km6:find radial spacing of the coarse mesh delta_phi_refine = np.abs(np.min(np.diff( phi_refine_unique))) #km5:find azimuthal spacing of the coarse mesh r_max = np.max(r_refine) r_min = np.min(r_refine) x_min = np.min(x_t_refine) x_max = np.max(x_t_refine) y_min = np.min(y_t_refine) y_max = np.max(y_t_refine) d_r = delta_r_refine d_phi = math.degrees(delta_phi_refine) u_mean = 15 time_step = float(45 / len(phi_refine_unique)) if scanner_id == 0: rotation = 1 angle_stop = np.degrees(np.max(phi_refine)) angle_start = np.degrees(np.min(phi_refine)) else: rotation = 1 angle_start = np.degrees(np.min(phi_refine)) angle_stop = np.degrees(np.max(phi_refine)) """comment la8: What is the difference if scan_id is 0 or not?""" print("elements", (r_max - r_min) / d_r * (float(np.max(phi_refine)) - float(np.min(phi_refine)) / d_phi)) uv = beam(x_min, x_max, y_min, y_max, u_mean, beam_orig, float(angle_start), float(angle_stop), abs(d_r), abs(d_phi), time_step, abs(r_max), abs(r_min), rotation) vu = 1 """ !!!!!!!!!!!! to here, to get uv""" vtx, wts = interp_weights2(uv, tri, d=2) aux_1 = np.reshape(np.repeat(r_unique, len(r_refine), axis=0), (len(r_unique), len(r_refine))) aux_2 = np.reshape(np.repeat(r_refine, len(r_unique)), (len(r_refine), len(r_unique))).T r_F = aux_1 - aux_2 rp = dl / (2 * np.sqrt(np.log(2))) erf = sp.special.erf((r_F + .5 * delta_r) / rp) - sp.special.erf( (r_F - .5 * delta_r) / rp) w = (1 / 2 / delta_r) * erf shapes = np.array([phi_t_refine.shape[0], phi_t_refine.shape[1], n, m]) return ( vtx, wts, w, c_ref, s_ref, shapes, uv_t, vu, uv ) #km5: returns the vertices the weights the beam weightfunction w a cosine and a sine (which I cant understand what do they represent) and info for the scanner shape (polar coordinates number of beams etc)
def early_weights_pulsed2(r, phi, tri, dl, dir_mean, d, center, rot_speed, u_mean, n=21, m=51, tri_calc=False): dir_mean = wrap_angle(dir_mean) gamma = -wrap_angle(np.pi - dir_mean) #gamma = -(np.pi-dir_mean)#(2*np.pi-dir_mean) r_unique = r[0, :] phi_unique = phi[:, 0] delta_r = np.diff(r_unique)[0] delta_phi = np.diff(phi_unique)[0] r_refine = np.linspace(r_unique[0] - delta_r / 2, r_unique[-1] + delta_r / 2, len(r_unique) * (n - 1) + 1) phi_refine = np.linspace(phi_unique[0] - delta_phi / 2, phi_unique[-1] + delta_phi / 2, len(phi_unique) * (m - 1) + 1) r_t_refine, phi_t_refine = np.meshgrid(r_refine, phi_refine) #LOS angles s_ref = np.sin(phi_t_refine - gamma) #(np.pi-dir_mean))#+np.pi/2-dir_mean) c_ref = np.cos(phi_t_refine - gamma) #(np.pi-dir_mean))#+np.pi/2-dir_mean) r_t_refine, phi_t_refine = wr.translationpolargrid( (r_t_refine, phi_t_refine), d) x_t_refine, y_t_refine = r_t_refine * np.cos( phi_t_refine), r_t_refine * np.sin(phi_t_refine) ############################################################################# print('Rotation') """ Rotation and translation: we then rotate according to wind direction. To do this we first translate to the position where the midpoint between the two lidars should be (see Figure_rot1,2 in the repo), and then rotate to wind direction, in local coordinates. The wind rose and cartesian have a different orientations that is why I put the 2*pi below) """ y_trans = (center) * np.sin(gamma) x_trans = (center) * (1 - np.cos(gamma)) S11 = np.cos(gamma) S12 = np.sin(gamma) T1 = np.array([[1, 0, x_trans], [0, 1, y_trans], [0, 0, 1]]) R = np.array([[S11, S12, 0], [-S12, S11, 0], [0, 0, 1]]) uv = np.array(np.c_[x_t_refine.flatten(), y_t_refine.flatten(), np.ones(len(y_t_refine.flatten()))]).T uv = np.dot(T1, np.dot(R, uv))[:2, :].T # y_trans = -(center)*np.sin(gamma) # x_trans = -(center)*(1-np.cos(gamma)) # T1 = np.array([[1,0,x_trans], [0,1, y_trans], [0, 0, 1]]) # uvo = np.dot(T1,(np.c_[uv,np.ones(uv.shape[0])]).T)[:2,:].T # ro = np.sqrt(uvo[:,1]**2+uvo[:,0]**2) # phio = np.arctan2(uvo[:,1],uvo[:,0]) # _,phio = wr.translationpolargrid((ro,phio),d) # s_ref = np.reshape(np.sin(phio),x_t_refine.shape) # c_ref = np.reshape(np.cos(phio),x_t_refine.shape) """ Once the scan are translated and rotated, we apply the final displacement due to wind field advection, we calculate the displacements per beam separatdly """ print('Advection') # Here I suppose that the mesh is equally spaced in phi, and it changes in axis 1, # you can make it more general # phimin = phi_refine[0] # phimax = phi_refine[-1] n_p = len(phi_refine) n_r = len(r_refine) dphi = np.abs(np.diff(phi_refine)[0]) # np.abs(phimin-phimax)/(n_p-1) t_step = dphi / rot_speed t_total = t_step * (n_p - 1) #np.abs(phimin-phimax)/rot_speed #Below it is t_total+t_step to include the last point t_array = np.arange(0, t_total + t_step, t_step) """ The displacements array is the same for both scans with the same shape as x_0_t, x_1_t, y_0_t and y_1_t so I repeat the column of displacements per beam nr0 times, or the number of range gates along each beam """ print('disp') disp_x = np.array([ list(u_mean * t_array), ] * n_r).transpose() """ No displacement in y, since the global coordinates are the streamwise and lateral components""" disp_y = np.zeros(disp_x.shape) #Just to check that everything is ok """ Finally, the scans translated, rotated and advected to estimate the domain size """ print(uv.shape, disp_x.flatten().shape) uv = uv - np.c_[disp_x.flatten(), disp_y.flatten()] if tri_calc: vtx, wts = interp_weights2(uv, tri, d=2) else: vtx, wts = [], [] aux_1 = np.reshape(np.repeat(r_unique, len(r_refine), axis=0), (len(r_unique), len(r_refine))) aux_2 = np.reshape(np.repeat(r_refine, len(r_unique)), (len(r_refine), len(r_unique))).T print('weights in each beam') r_F = aux_1 - aux_2 rp = dl / (2 * np.sqrt(np.log(2))) erf = sp.special.erf((r_F + .5 * delta_r) / rp) - sp.special.erf( (r_F - .5 * delta_r) / rp) w = (1 / 2 / delta_r) * erf shapes = np.array([phi_t_refine.shape[0], phi_t_refine.shape[1], n, m]) return (vtx, wts, w, c_ref, s_ref, shapes, uv, r_t_refine, phi_t_refine ) #(w, c_ref, s_ref, shapes,uv)#
(r_0, phi_0), (r_1, phi_1), -d) switch = 1 print(t_scan[0]) uo, vo, grdu, so, r_i_0, phi_i_0, r_i_1, phi_i_1, mask = wr.direct_wf_rec( df0.astype(np.float32), df1.astype(np.float32), tri, d, N_grid=chunk) r_i = np.sqrt(grdu[0]**2 + grdu[1]**2) phi_i = np.arctan2(grdu[1], grdu[0]) ind = tri.get_trifinder()(grdu[0].flatten(), grdu[1].flatten()) != -1 r_i_0, phi_i_0 = wr.translationpolargrid((r_i, phi_i), -d / 2) phi_i_0 = np.pi * 0.5 - phi_i_0 phi_i_0 = np.where(phi_i_0 < 0, 2 * np.pi + phi_i_0, phi_i_0) r_i_1, phi_i_1 = wr.translationpolargrid((r_i, phi_i), d / 2) phi_i_1 = np.pi * 0.5 - phi_i_1 phi_i_1 = np.where(phi_i_1 < 0, 2 * np.pi + phi_i_1, phi_i_1) plt.figure() plt.contourf(grdu[0], grdu[1], phi_i_0 * 180 / np.pi, 10, cmap='jet') plt.colorbar() plt.figure() plt.contourf(grdu[0], grdu[1], phi_i_1 * 180 / np.pi, 10, cmap='jet') plt.colorbar() # Angle of lidars fig0, ax0 = plt.subplots(figsize=(8, 8))
os.chdir(file_in_path) # In[Lidar local coordinates] r_s = np.linspace(150, 7000, 198) r_v = np.linspace(150, 7000, 198) phi_s = np.linspace(256, 344, 45) * np.pi / 180 phi_v = np.linspace(196, 284, 45) * np.pi / 180 r_s_g, phi_s_g = np.meshgrid(r_s, phi_s) r_v_g, phi_v_g = np.meshgrid(r_v, phi_v) siro = np.array([6322832.3, 0]) vara = np.array([6327082.4, 0]) d = vara - siro r_s_t, phi_s_t = wr.translationpolargrid((r_s_g, np.pi - phi_s_g), -d / 2) r_v_t, phi_v_t = wr.translationpolargrid((r_v_g, np.pi - phi_v_g), d / 2) x_max = np.max(np.r_[(r_s_t * np.cos(phi_s_t)).flatten(), (r_v_t * np.cos(phi_v_t)).flatten()]) x_min = np.min(np.r_[(r_s_t * np.cos(phi_s_t)).flatten(), (r_v_t * np.cos(phi_v_t)).flatten()]) y_max = np.max(np.r_[(r_s_t * np.sin(phi_s_t)).flatten(), (r_v_t * np.sin(phi_v_t)).flatten()]) y_min = np.min(np.r_[(r_s_t * np.sin(phi_s_t)).flatten(), (r_v_t * np.sin(phi_v_t)).flatten()]) L_x = x_max - x_min L_y = y_max - y_min
R = 7000 Dtheta = 2*np.pi/180 k = lambda k1,k2: np.sqrt(k1**2+k2**2) azim0 = ((90-np.arange(256,346,2)) % 360)*np.pi/180 azim1 = ((90-np.arange(196,286,2)) % 360)*np.pi/180 r = np.arange(105,7035,35) r0, azim0 = np.meshgrid(r,azim0) r1, azim1 = np.meshgrid(r,azim1) loc0 = np.array([0,6322832.3])#-d loc1 = np.array([0,6327082.4])# d d = loc1-loc0 r_prime0, azim_prime0 = wr.translationpolargrid((r0,azim0),d/2) r_prime1, azim_prime1 = wr.translationpolargrid((r1,azim1),-d/2) x0,y0 = r_prime0*np.cos(azim_prime0), r_prime0*np.sin(azim_prime0) x1,y1 = r_prime1*np.cos(azim_prime1), r_prime1*np.sin(azim_prime1) r_hat0 = np.array([x0/r_prime0,y0/r_prime0]) r_hat1 = np.array([x1/r_prime1,y1/r_prime1]) x = np.linspace(np.min(np.r_[x0.flatten(),x1.flatten()]),np.max(np.r_[x0.flatten(),x1.flatten()]),100) y = np.linspace(np.min(np.r_[y0.flatten(),y1.flatten()]),np.max(np.r_[y0.flatten(),y1.flatten()]),100) x, y = np.meshgrid(x,y) rhat0 = np.zeros((x.flatten().shape[0],2))*np.nan rhat1 = np.zeros((x.flatten().shape[0],2))*np.nan
#km4: Return the size of the in general rectangular (but now square) domain. A structured cartesian grid with N_x x N_y points. The coordinates of the grid points x y. #km4: Another structured uniform grid for the same domain but with different spacing and the distance of the two scanners d. """answer la4: yes. grid_new is used as the recangular grid for wind field reconstruction from the values of V_LOS of each scan interpolated to this grid, if you see below (line 153), from grid_new phi_tri_1_s is calculated as de local (local to each Windscanner) azimuth angle used for reconstruction""" #km5:commented this line _,tri_i,_, _, _, _, _, _ = wr.grid_over2((r_1_g, np.pi-phi_1_g),(r_0_g, np.pi-phi_0_g),-d) """answer la5: ok""" #km4: returns the trianguulation of the intersection set centers between the 2 scanners in cartesian coordinates #km4: If I am not wrong, this procedure is also done in the sy.geom_syn_field function """answer la4: yes, indeed it is not used afterwards, (you can erase this line I think)""" # Triangulation and weights for each scan dl = 75 # From Cartesian coord. to polar in global grid r_tri_s = np.sqrt(grid_new[0]**2 + grid_new[1]**2) phi_tri_s = np.arctan2(grid_new[1],grid_new[0]) r_tri_1_s, phi_tri_1_s = wr.translationpolargrid((r_tri_s, phi_tri_s),-d/2) r_tri_0_s, phi_tri_0_s = wr.translationpolargrid((r_tri_s, phi_tri_s),d/2) """answer la4: So this wis just step to recover the original azimuth angle for each scan (local coordinates for each scan) this time in the corresponding points of the reconstructed wind field in cartesian coordinates, to be used in wind field reconstruction""" # Mann-model parameters ae = [0.025, 0.05, 0.075] #km5: create a variety of cases with a bunch of mann parameters """answer la5: yes""" L = [62,62.5,125,250,500,750,1000] G = [0,1,2,2.5,3.5] seed = np.arange(1,10) ae,L,G,seed = np.meshgrid(ae,L,G,-seed) sym = [] no_sym = []
def early_weights_pulsed(r, phi, dl, dir_mean, tri, d, center, n=21, m=51): gamma = (2 * np.pi - dir_mean) #km5: why this rotation ? r_unique = np.unique( r) #km5:remove the repeating radial coorddinates (local cs) phi_unique = np.unique( phi) #km5:remove the repeating azimuthal coorddinates (local cs) delta_r = np.min(np.diff(r_unique)) #km5:find radial spacing delta_phi = np.min(np.diff(phi_unique)) #km5:find azimuthal spacing r_refine = np.linspace( r_unique.min() - delta_r / 2, r_unique.max() + delta_r / 2, len(r_unique) * (n - 1) + 1) #km5:create refine discretization in the radial direction phi_refine = np.linspace( phi_unique.min() - delta_phi / 2, phi_unique.max() + delta_phi / 2, len(phi_unique) * (m - 1) + 1) #km5:create refine discretization in the azimuthal direction r_t_refine, phi_t_refine = np.meshgrid( r_refine, phi_refine) #km5: generte the refine mesh #LOS angles s_ref = np.sin(phi_t_refine - gamma) #km5: what does (phi_t_refine-gamma) represent ? c_ref = np.cos(phi_t_refine - gamma) r_t_refine, phi_t_refine = wr.translationpolargrid( (r_t_refine, phi_t_refine), d) #km5: tranlation to the global polar cs x_t_refine, y_t_refine = r_t_refine * np.cos( phi_t_refine), r_t_refine * np.sin( phi_t_refine) #km5:from polar to cartesian ### # Rotation and translation x_trans = -(center) * np.sin( gamma) #km5: find the translated center of the scanners y_trans = (center) * (1 - np.cos(gamma)) S11 = np.cos(gamma) S12 = np.sin(gamma) T1 = np.array([[1, 0, x_trans], [0, 1, y_trans], [0, 0, 1]]) R = np.array([[S11, S12, 0], [-S12, S11, 0], [0, 0, 1]]) Xx = np.array(np.c_[x_t_refine.flatten(), y_t_refine.flatten(), np.ones(len(y_t_refine.flatten()))]).T Xx = np.dot(T1, np.dot(R, Xx)) uv = Xx[:2, :].T vtx, wts = interp_weights2(uv, tri, d=2) aux_1 = np.reshape(np.repeat(r_unique, len(r_refine), axis=0), (len(r_unique), len(r_refine))) aux_2 = np.reshape(np.repeat(r_refine, len(r_unique)), (len(r_refine), len(r_unique))).T r_F = aux_1 - aux_2 rp = dl / (2 * np.sqrt(np.log(2))) erf = sp.special.erf((r_F + .5 * delta_r) / rp) - sp.special.erf( (r_F - .5 * delta_r) / rp) w = (1 / 2 / delta_r) * erf shapes = np.array([phi_t_refine.shape[0], phi_t_refine.shape[1], n, m]) return ( vtx, wts, w, c_ref, s_ref, shapes ) #km5: returns the vertices the weights the beam weightfunction w a cosine and a sine (which I cant understand what do they represent) and info for the scanner shape (polar coordinates number of beams etc)