Ejemplo n.º 1
0
def fill_frc(fname, time, u, v):
    nc = netcdf.Pync(fname, 'w')

    tunits = netcdf.vatt(nc, 'wind_time', 'units')
    time = netcdf.date2num(time, tunits)
    tind = nc.dims['wind_time']

    nc.vars['wind_time'][tind] = time
    nc.vars['Uwind_ascat24'][tind, ...] = u
    nc.vars['Vwind_ascat24'][tind, ...] = v

    nc.close()
Ejemplo n.º 2
0
Archivo: ascat.py Proyecto: jcmt/okean
def fill_frc(fname,time,u,v):
  nc=netcdf.Pync(fname,'w')

  tunits=netcdf.vatt(nc,'wind_time','units')
  time=netcdf.date2num(time,tunits)
  tind=nc.dims['wind_time']

  nc.vars['wind_time'][tind]=time
  nc.vars['Uwind_ascat24'][tind,...]=u
  nc.vars['Vwind_ascat24'][tind,...]=v

  nc.close()
Ejemplo n.º 3
0
  def time_series(self,varname,x,y,times=None,depth=None,**opts):
    coords=opts.get('coords',self._default_coords('time_series')).split(',')

    if times is None: times=range(0,self.time.size)

    # depth or s_level: check if is float or if is negative!
    isDepth=False
    if not depth is None:
       if calc.isiterable(depth): depth=np.asarray(depth)
       if calc.isarray(depth):
         isDepth=np.any(depth<0) or depth.kind!='i' 
       else: isDepth=depth<0 or np.asarray(depth).dtype.kind!='i'

    out=vis.Data()
    out.label='time_series'
    if not depth is None and not isDepth:
      out.msg=self.check_slice(varname,t=np.max(times),k=depth) 
    else:
      out.msg=self.check_slice(varname,t=np.max(times)) 

    if out.msg: return out

    # find nearest point:
###    lon,lat,hr,mr=self.grid.vars(ruvp=self.var_at(varname))
    lon,lat,hr,mr=self.grid.vars(ruvp=self.vloc(varname))
    dist=(lon-x)**2+(lat-y)**2
    i,j=np.where(dist==dist.min())
    i,j=i[0],j[0]

    if not depth is None and not isDepth: arg={'s_SEARCH':depth}
    else: arg={}
    v=self.use(varname,xiSEARCH=j,etaSEARCH=i,SEARCHtime=times,**arg).T

    # calculate depths:
###    if self.hasz(varname):
    if 'z' in self.vaxes(varname):
      h=self.grid.h[i,j]
      zeta=self.use('zeta',xiSEARCH=j,etaSEARCH=i,SEARCHtime=times)
      h=h+0*zeta
####      z=rt.s_levels(h,zeta,self.s_params,rw=varname)
###      z=rt.s_levels(h,zeta,self.s_params,rw=self.var_at(varname)[1])
      z=rt.s_levels(h,zeta,self.s_params,rw=self.vloc(varname)[1])
      z=np.squeeze(z)

    # depth slice:
###    if isDepth and self.hasz(varname):
    if isDepth and 'z' in self.vaxes(varname):
      if v.ndim==2:
        # could use calc.griddata, but better use slicez cos data at
        # different times may be independent!
        if 0:
          from matplotlib.dates import date2num
          t=np.tile(date2num(self.time[times]),(v.shape[0],1))
          v=calc.griddata(t,z,v,t[0],depth+np.zeros(t[0].shape),
            extrap=opts.get('extrap',False),norm_xy=opts.get('norm_xy',False))
            # norm_xy True may be needed!
            # extrap also may be needed cos the 1st and last value may be masked!

        else:
          nt=len(times)
          land_mask=np.ones((nt,1),dtype=v.dtype) # needed for slicez... not used here!        

          v=rt.slicez(v[...,np.newaxis],land_mask,
               self.grid.h[i,j]*np.ones((nt,1),dtype=v.dtype), # bottom depth
               zeta[:,np.newaxis],self.s_params,depth,
               surface_masked=opts.get('surf_mask',True),
               spline=opts.get('spline',True))[...,0]

      else: # one time only
        v=np.interp(depth,z,v,left=np.nan,right=np.nan)
        v=np.ma.masked_where(np.isnan(v),v) 


    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='time series'
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass
     
    # coords
#########    if 't' in coords and self.hast(varname):
    if 't' in coords and 't' in self.vaxes(varname):
      if v.ndim==2:
        out.t=np.tile(self.time[times],(v.shape[0],1))
        from matplotlib.dates import date2num
        out.tnum=np.tile(date2num(self.time[times]),(v.shape[0],1))
      else: out.t=self.time[times]
      out.info['t']['name']='Time'
      out.info['tnum']=dict(name='Time',units=self.var_as['time']['units'])

###    if 'z' in coords and self.hasz(varname):
    if 'z' in coords and 'z' in self.vaxes(varname):
      if not depth is None:
        if not isDepth: out.z=z[depth,...]
        else: out.z=depth+0*v
      else: out.z=z
      out.info['z']=dict(name='Depth',units='m')

    if 'x' in coords:
      out.x=lon[i,j]
      if self.grid.spherical:
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
      else:
        out.x=x/1000.
        out.info['x']=dict(name='X-position',units='km')

    if 'y' in coords:
      out.y=lat[i,j]
      if self.grid.spherical:
        out.info['y']=dict(name='Latitude',units=r'$\^o$N')
      else:
        out.y=y/1000.
        out.info['y']=dict(name='Y-position',units='km')


    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 4
0
  def sliceiso(self,varname,iso,time,**opts):
    '''
    Depths where variable, increasing/dec with depth, has some value.

    Output is masked where surface is higher/lower than value or where all
    water column is lower/higher than value.
    '''


    coords=opts.get('coords',self._default_coords('sliceiso')).split(',')

    out=vis.Data()
    out.label='slice_iso'
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out

###    if not self.hasz(varname):
    if not 'z' in self.vaxes(varname):
      out.msg='a depth dependent variable is needed for sliceiso!'
      return out

    v=self.use(varname,SEARCHtime=time)
####    z=self.s_levels(time=time,ruvpw=self.var_at(varname))
###    z=self.s_levels(time=time,loc=self.var_at(varname))
    z=self.s_levels(time=time,loc=self.vloc(varname))
    v=rt.depthof(v,z,iso)

    out.v=v
    #out.info['v']['name']=varname
    out.info['v']['name']='depth'

    if isinstance(iso,np.ndarray) and iso.ndim==2: siso='2d'
    else: siso=str(iso)

    try:
      out.info['v']['slice']='%s (%s) iso=%s'%(varname,netcdf.vatt(self.nc,varname,'units'),siso)
    except:
      out.info['v']['slice']='%s iso=%s'%(varname,siso)
  
    out.info['v']['units']='metre'


    # coords:
    if any([i in coords for i in 'xy']):
###      x,y,h=self.grid.vars(ruvp=self.var_at(varname))[:3]
      x,y,h=self.grid.vars(ruvp=self.vloc(varname))[:3]

    if 'x' in coords:
       if self.grid.spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x/1000.
         out.info['x']=dict(name='Distance',units='km')

    if 'y' in coords:
       if self.grid.spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y/1000.
         out.info['y']=dict(name='Distance',units='km')

    if 'z' in coords:
      # makes no sense... v is the depth!
      coords.remove('z')

    if 't' in coords and 't' in self.vaxes(varname): out.t=self.time[time]

    if out.v.ndim==2:
      out.extra=[vis.Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.cmap']='k'
      out.extra[0].label='bathy'

    out.coordsReq=','.join(sorted(coords))

    # about projection:
    out.set_projection(self.grid.proj_info['basemap_opts'])

    return out
Ejemplo n.º 5
0
  def slicell(self,varname,X,Y,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicell')).split(',')

    data      = opts.get('data',False)
    extrap    = opts.get('extrap',False)
    maskLimit = opts.get('lmask',0.5) # points where interpolated mask are above
                                      # this value are considered as mask!
                                      # Most strict value is 0

    out=vis.Data()
    out.label='slicell'
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out#None,aux

    X=np.asarray(X)
    Y=np.asarray(Y)
    if X.ndim>1: X=np.squeeze(X)
    if Y.ndim>1: Y=np.squeeze(X)

###    x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0])
    x,y,h,m=self.grid.vars(ruvp=self.vloc(varname)[0])
    if True: # extrat only portion of data needed:
      i0,i1,j0,j1=calc.ij_limits(x, y, (X.min(),X.max()),(Y.min(),Y.max()), margin=1)
      xi='%d:%d'%(i0,i1)
      eta='%d:%d'%(j0,j1)

      if data is False: V=self.use(varname,SEARCHtime=time,xi_SEARCH=xi,eta_SEARCH=eta)
      else: v=data[...,j0:j1,i0:i1]

      x=x[j0:j1,i0:i1]
      y=y[j0:j1,i0:i1]
      h=h[j0:j1,i0:i1]
      m=m[j0:j1,i0:i1]

    else:
      if data is False: V=self.use(varname,SEARCHtime=time)
      else: v=data

    if V.ndim==3:
      v=calc.griddata(x,y,V,X,Y,extrap=extrap,mask2d=m==0, keepMaskVal=maskLimit)
    elif V.ndim==2:
      v=calc.griddata(x,y,np.ma.masked_where(m==0,V),X,Y,extrap=extrap, keepMaskVal=maskLimit)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='path npts=%d'%X.size
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'z' in coords and V.ndim==3:
      inds=dict(xi=(i0,i1),eta=(j0,j1))
#########      out.z=self.path_s_levels(time,X,Y,rw=varname[0],inds=inds)
###      out.z=self.path_s_levels(time,X,Y,rw=self.var_at(varname)[1],inds=inds)
###
#######      out.z,zw=self.path_s_levels(time,X,Y,rw=False,inds=inds)
#######      if self.vloc(varname)[1]=='w': out.z=zw
      out.z=self.path_s_levels(time,X,Y,rw=self.vloc(varname)[1],inds=inds)
      out.info['z']=dict(name='Depth',units='m')

    if 'd' in coords:
      d=calc.distance(X,Y)
      if d[-1]-d[0]>1e4:
        d=d/1000.
        dunits='km'
      else: dunits='m'

      if v.ndim==2: d=np.tile(d,(v.shape[0],1))
      out.d=d
      out.info['d']=dict(name='Distance',units=dunits)

    if 'x' in coords:
      if v.ndim==2: X=np.tile(X,(v.shape[0],1))
      out.x=X
      out.info['x']=dict(name='Longitude',units=r'$\^o$E')

    if 'y' in coords:
      if v.ndim==2: Y=np.tile(Y,(v.shape[0],1))
      out.y=Y
      out.info['y']=dict(name='Latitude',units=r'$\^o$N')

#######    if 't' in coords and self.hast(varname): out.t=self.time[time]
    if 't' in coords and 't' in self.vaxes(varname): out.t=self.time[time]

    if v.ndim==2: ################3 and not out.z is None: # zeta and bottom already calculated
      out.extra=[vis.Data()]
      if 'd' in coords: out.extra[0].x=out.d[0]
      if 'x' in coords: out.extra[0].y=out.x[0]
      if 'y' in coords: out.extra[0].x=out.y[0]
####      #h=-zw[0]
      h    = calc.griddata(x,y,h,X,Y,extrap=False)
      out.extra[0].v=-h # bottom
      out.extra[0].config['d1.plot']='fill_between'
      out.extra[0].config['d1.y0']=-h.max()-(h.max()-h.min())/20.
      out.extra[0].label='bottom'



    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 6
0
  def slicez(self,varname,ind,time=0,**opts):
    surf_mask=opts.get('surf_mask',True)
    spline=opts.get('spline',True)
    coords=opts.get('coords',self._default_coords('slicez')).split(',')

    out=vis.Data()
    out.label='slicez'
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out

    if not 'z' in self.vaxes(varname):
      return self.slicek(varname,ind,time,**opts)

    v=self.use(varname,SEARCHtime=time)
###    x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0])
    x,y,h,m=self.grid.vars(ruvp=self.vloc(varname)[0])
    zeta=self.use('zeta',SEARCHtime=time)
    zeta=rt.rho2uvp(zeta,varname)

    out.v=rt.slicez(v,m,h,zeta,self.s_params,ind,surf_mask,spline)

    out.info['v']['name']=varname
    if calc.isarray(ind):
      out.info['v']['slice']='z= array %.2f to %.2f'%(ind.min(),ind.max())
    else:
      out.info['v']['slice']='z=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'x' in coords:
       if self.grid.spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x/1000.
         out.info['x']=dict(name='Distance',units='km')

    if 'y' in coords:
       if self.grid.spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y/1000.
         out.info['y']=dict(name='Distance',units='km')

    if 'z' in coords:
      out.z=ind+np.zeros(out.v.shape)
      out.info['z']=dict(name='Depth',units='m')

    if 't' in coords and 't' in self.vaxes(varname): out.t=self.time[time]

    if out.v.ndim==2:
      out.extra=[vis.Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.cmap']='k'
      out.extra[0].label='bathy'


    out.coordsReq=','.join(sorted(coords))

    # about projection:
    out.set_projection(self.grid.proj_info['basemap_opts'])

    return out
Ejemplo n.º 7
0
  def slicek(self,varname,ind,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicek')).split(',')
    coords=['x','y','z','d']
    out=Data()
    out.msg=self.check_slice(varname,t=time,k=ind)
    if out.msg: out

    v=self.use(varname,SEARCHtime=time,s_SEARCH=ind)

    # add mask if not masked:
    if not np.ma.isMA(v): 
      m=self.grid.vars(ruvp=self.var_at(varname)[0])[-1]
      v=np.ma.masked_where(m==0,v)

    out.v=v
    out.info['v']['name']=varname
    if self.hasz(varname): out.info['v']['slice']='k=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'z' in coords and self.hasz(varname):
#####      out.z=self.s_levels(time,k=ind,ruvpw=self.var_at(varname))
      out.z=self.s_levels(time,k=ind,loc=self.var_at(varname))
      out.info['z']=dict(name='Depth',units='m')


    if any([i in coords for i in 'xy']):
      x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0])

    if 'x' in coords:
       if self.grid.is_spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x #/1000.
         out.info['x']=dict(name='Distance',units='m')
         
    if 'y' in coords:
       if self.grid.is_spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y#/1000.
         out.info['y']=dict(name='Distance',units='m')

    if 't' in coords and self.hast(varname): out.t=self.time[time]

    if v.ndim==2:
      out.extra=[Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.linecolors']='k'
      out.extra[0].alias='bathy'


    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 8
0
  def slicek(self,varname,ind,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicek')).split(',')

    out=Data()
    out.msg=self.check_slice(varname,t=time,k=ind)
    if out.msg: out

    v=self.use(varname,SEARCHtime=time,s_SEARCH=ind)

    # add mask if not masked:
    if not np.ma.isMA(v): 
      m=self.grid.vars(ruvp=self.var_at(varname))[-1]
      v=np.ma.masked_where(m==0,v)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='k=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'z' in coords and self.hasz(varname):
      out.z=self.s_levels(time,k=ind,ruvpw=self.var_at(varname))
      out.info['z']=dict(name='Depth',units='m')


    if any([i in coords for i in 'xy']):
      x,y,h,m=self.grid.vars(ruvp=self.var_at(varname))

    if 'x' in coords:
       if self.grid.is_spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x/1000.
         out.info['x']=dict(name='Distance',units='km')
         
    if 'y' in coords:
       if self.grid.is_spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y/1000.
         out.info['y']=dict(name='Distance',units='km')

    if 't' in coords: out.t=self.time[time]

    if v.ndim==2:
      out.extra=[Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.linecolors']='k'
      out.extra[0].alias='bathy'


    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 9
0
  def slicez(self,varname,ind,time=0,**opts):
    if not self.hasz(varname):
      return self.slicek(varname,ind,time,**opts)

    surf_nans=opts.get('surf_nans',True)
    spline=opts.get('spline',True)
    coords=opts.get('coords',self._default_coords('slicez')).split(',')

    out=Data()
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out##None,au

    v=self.use(varname,SEARCHtime=time)
    x,y,h,m=self.grid.vars(ruvp=self.var_at(varname))
    zeta=self.use('zeta',SEARCHtime=time)
    zeta=rt.rho2uvp(zeta,varname)

    v,mask=rt.slicez(v,m,h,zeta,self.s_params,ind,surf_nans,spline)
    v=np.ma.masked_where(mask,v)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='z=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'x' in coords:
       if self.grid.is_spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x/1000.
         out.info['x']=dict(name='Distance',units='km')

    if 'y' in coords:
       if self.grid.is_spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y/1000.
         out.info['y']=dict(name='Distance',units='km')

    if 'z' in coords:
      out.z=ind+np.zeros(v.shape)
      out.info['z']=dict(name='Depth',units='m')

    if 't' in coords: out.t=self.time[time]

    if v.ndim==2:
      out.extra=[Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.linecolors']='k'
      out.extra[0].alias='bathy'


    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 10
0
  def sliceiso(self,varname,iso,time,**opts):
    '''
    Depths where variable, increasing/dec with depth, has some value.

    Output is masked where surface is higher/lower than value or where all
    water column is lower/higher than value.
    '''


    coords=opts.get('coords',self._default_coords('sliceiso')).split(',')

    out=Data()
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out

    if not self.hasz(varname):
      out.msg='a depth dependent variable is needed for sliceiso!'
      return out

    v=self.use(varname,SEARCHtime=time)
    z=self.s_levels(time=time,ruvpw=self.var_at(varname))
    v=rt.depthof(v,z,iso)

    out.v=v
    out.info['v']['name']=varname

    if isinstance(iso,np.ndarray) and iso.ndim==2: siso='2d'
    else: siso=str(iso)

    out.info['v']['slice']='iso=%s'%siso
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass

    # coords:
    if any([i in coords for i in 'xy']):
      x,y,h=self.grid.vars(ruvp=self.var_at(varname))[:3]

    if 'x' in coords:
       if self.grid.is_spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x/1000.
         out.info['x']=dict(name='Distance',units='km')

    if 'y' in coords:
       if self.grid.is_spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y/1000.
         out.info['y']=dict(name='Distance',units='km')

    if 'z' in coords:
      # makes no sense... v is the depth!
      coords.remove('z')

    if 't' in coords: out.t=self.time[time]

    if v.ndim==2:
      out.extra=[Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.linecolors']='k'
      out.extra[0].alias='bathy'

    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 11
0
  def slicej(self,varname,ind,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicej')).split(',')

    out=Data()
    out.msg=self.check_slice(varname,t=time,j=ind)
    if out.msg: return out

    v=self.use(varname,SEARCHtime=time,eta_SEARCH=ind)

    # add mask if not masked:
    if not np.ma.isMA(v):
      m=self.grid.vars(ruvp=self.var_at(varname),j=ind)[-1]
      if v.ndim==2: m=np.tile(m,(v.shape[0],1))
      v=np.ma.masked_where(m==0,v)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='j=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.name,varname,'units')
    except: pass

    # coords:
    if 'z' in coords and v.ndim==2:
      out.z=self.s_levels(time=time,ruvpw=self.var_at(varname),j=ind)
      out.info['z']=dict(name='Depth',units='m')

    if any([i in coords for i in 'xyd']):
      x,y,h,m=self.grid.vars(ruvp=self.var_at(varname),j=ind)

    if 'd' in coords:
      d=calc.distance(x,y)
      if d[-1]-d[0]>1e4:
        d=d/1000.
        dunits='km'
      else: dunits='m'

      if v.ndim==2: d=np.tile(d,(v.shape[0],1))
      out.d=d
      out.info['d']=dict(name='Distance',units=dunits)

    if 'x' in coords:
      if v.ndim==2: x=np.tile(x,(v.shape[0],1))
      out.x=x
      out.info['x']=dict(name='Longitude',units=r'$\^o$E')

    if 'y' in coords:
      if v.ndim==2: y=np.tile(y,(v.shape[0],1))
      out.y=y
      out.info['y']=dict(name='Latitude',units=r'$\^o$N')

    if 't' in coords: out.t=self.time[time]

    if v.ndim==2:
      out.extra=[Data()]
      if 'd' in coords: out.extra[0].x=out.d[0]
      if 'x' in coords: out.extra[0].y=out.x[0]
      if 'y' in coords: out.extra[0].x=out.y[0]
      out.extra[0].v=-h
      out.extra[0].config['1d.plot']='fill_between'
      out.extra[0].config['1d.y0']=-h.max()-(h.max()-h.min())/20.
      out.extra[0].alias='bottom'

    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 12
0
  def time_series(self,varname,x,y,times=None,depth=None,**opts):
    coords=opts.get('coords',self._default_coords('time_series')).split(',')

    if times is None: times=range(0,self.time.size)

    # depth or s_level: check if is float or if is negative!
    isDepth=False
    if not depth is None:
       if calc.isiterable(depth): depth=np.asarray(depth)
       if calc.isarray(depth):
         isDepth=np.any(depth<0) or depth.kind!='i' 
       else: isDepth=depth<0 or np.asarray(depth).dtype.kind!='i'

    out=vis.Data()
    out.label='time_series'
    if not depth is None and not isDepth:
      out.msg=self.check_slice(varname,t=np.max(times),k=depth) 
    else:
      out.msg=self.check_slice(varname,t=np.max(times)) 

    if out.msg: return out

    # find nearest point:
###    lon,lat,hr,mr=self.grid.vars(ruvp=self.var_at(varname))
    lon,lat,hr,mr=self.grid.vars(ruvp=self.vloc(varname))
    dist=(lon-x)**2+(lat-y)**2
    i,j=np.where(dist==dist.min())
    i,j=i[0],j[0]

    if not depth is None and not isDepth: arg={'s_SEARCH':depth}
    else: arg={}
    v=self.use(varname,xiSEARCH=j,etaSEARCH=i,SEARCHtime=times,**arg).T

    # calculate depths:
###    if self.hasz(varname):
    if 'z' in self.vaxes(varname):
      h=self.grid.h[i,j]
      zeta=self.use('zeta',xiSEARCH=j,etaSEARCH=i,SEARCHtime=times)
      h=h+0*zeta
####      z=rt.s_levels(h,zeta,self.s_params,rw=varname)
###      z=rt.s_levels(h,zeta,self.s_params,rw=self.var_at(varname)[1])
      z=rt.s_levels(h,zeta,self.s_params,rw=self.vloc(varname)[1])
      z=np.squeeze(z)

    # depth slice:
###    if isDepth and self.hasz(varname):
    if isDepth and 'z' in self.vaxes(varname):
      if v.ndim==2:
        # could use calc.griddata, but better use slicez cos data at
        # different times may be independent!
        if 0:
          from matplotlib.dates import date2num
          t=np.tile(date2num(self.time[times]),(v.shape[0],1))
          v=calc.griddata(t,z,v,t[0],depth+np.zeros(t[0].shape),
            extrap=opts.get('extrap',False),norm_xy=opts.get('norm_xy',False))
            # norm_xy True may be needed!
            # extrap also may be needed cos the 1st and last value may be masked!

        else:
          nt=len(times)
          land_mask=np.ones((nt,1),dtype=v.dtype) # needed for slicez... not used here!        

          v=rt.slicez(v[...,np.newaxis],land_mask,
               self.grid.h[i,j]*np.ones((nt,1),dtype=v.dtype), # bottom depth
               zeta[:,np.newaxis],self.s_params,depth,
               surface_masked=opts.get('surf_mask',True),
               spline=opts.get('spline',True))[...,0]

      else: # one time only
        v=np.interp(depth,z,v,left=np.nan,right=np.nan)
        v=np.ma.masked_where(np.isnan(v),v) 


    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='time series'
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass
     
    # coords
#########    if 't' in coords and self.hast(varname):
    if 't' in coords and 't' in self.vaxes(varname):
      if v.ndim==2:
        out.t=np.tile(self.time[times],(v.shape[0],1))
        from matplotlib.dates import date2num
        out.tnum=np.tile(date2num(self.time[times]),(v.shape[0],1))
      else: out.t=self.time[times]
      out.info['t']['name']='Time'
      out.info['tnum']=dict(name='Time',units=self.var_as['time']['units'])

###    if 'z' in coords and self.hasz(varname):
    if 'z' in coords and 'z' in self.vaxes(varname):
      if not depth is None:
        if not isDepth: out.z=z[depth,...]
        else: out.z=depth+0*v
      else: out.z=z
      out.info['z']=dict(name='Depth',units='m')

    if 'x' in coords:
      out.x=lon[i,j]
      if self.grid.spherical:
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
      else:
        out.x=x/1000.
        out.info['x']=dict(name='X-position',units='km')

    if 'y' in coords:
      out.y=lat[i,j]
      if self.grid.spherical:
        out.info['y']=dict(name='Latitude',units=r'$\^o$N')
      else:
        out.y=y/1000.
        out.info['y']=dict(name='Y-position',units='km')


    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 13
0
  def slicell(self,varname,X,Y,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicell')).split(',')

    data      = opts.get('data',False)
    extrap    = opts.get('extrap',False)
    maskLimit = opts.get('lmask',0.5) # points where interpolated mask are above
                                      # this value are considered as mask!
                                      # Most strict value is 0

    out=vis.Data()
    out.label='slicell'
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out#None,aux

    X=np.asarray(X)
    Y=np.asarray(Y)
    if X.ndim>1: X=np.squeeze(X)
    if Y.ndim>1: Y=np.squeeze(X)

###    x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0])
    x,y,h,m=self.grid.vars(ruvp=self.vloc(varname)[0])
    if True: # extrat only portion of data needed:
      i0,i1,j0,j1=calc.ij_limits(x, y, (X.min(),X.max()),(Y.min(),Y.max()), margin=1)
      xi='%d:%d'%(i0,i1)
      eta='%d:%d'%(j0,j1)

      if data is False: V=self.use(varname,SEARCHtime=time,xi_SEARCH=xi,eta_SEARCH=eta)
      else: v=data[...,j0:j1,i0:i1]

      x=x[j0:j1,i0:i1]
      y=y[j0:j1,i0:i1]
      h=h[j0:j1,i0:i1]
      m=m[j0:j1,i0:i1]

    else:
      if data is False: V=self.use(varname,SEARCHtime=time)
      else: v=data

    if V.ndim==3:
      v=calc.griddata(x,y,V,X,Y,extrap=extrap,mask2d=m==0, keepMaskVal=maskLimit)
    elif V.ndim==2:
      v=calc.griddata(x,y,np.ma.masked_where(m==0,V),X,Y,extrap=extrap, keepMaskVal=maskLimit)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='path npts=%d'%X.size
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'z' in coords and V.ndim==3:
      inds=dict(xi=(i0,i1),eta=(j0,j1))
#########      out.z=self.path_s_levels(time,X,Y,rw=varname[0],inds=inds)
###      out.z=self.path_s_levels(time,X,Y,rw=self.var_at(varname)[1],inds=inds)
###
#######      out.z,zw=self.path_s_levels(time,X,Y,rw=False,inds=inds)
#######      if self.vloc(varname)[1]=='w': out.z=zw
      out.z=self.path_s_levels(time,X,Y,rw=self.vloc(varname)[1],inds=inds)
      out.info['z']=dict(name='Depth',units='m')

    if 'd' in coords:
      d=calc.distance(X,Y)
      if d[-1]-d[0]>1e4:
        d=d/1000.
        dunits='km'
      else: dunits='m'

      if v.ndim==2: d=np.tile(d,(v.shape[0],1))
      out.d=d
      out.info['d']=dict(name='Distance',units=dunits)

    if 'x' in coords:
      if v.ndim==2: X=np.tile(X,(v.shape[0],1))
      out.x=X
      out.info['x']=dict(name='Longitude',units=r'$\^o$E')

    if 'y' in coords:
      if v.ndim==2: Y=np.tile(Y,(v.shape[0],1))
      out.y=Y
      out.info['y']=dict(name='Latitude',units=r'$\^o$N')

#######    if 't' in coords and self.hast(varname): out.t=self.time[time]
    if 't' in coords and 't' in self.vaxes(varname): out.t=self.time[time]

    if v.ndim==2: ################3 and not out.z is None: # zeta and bottom already calculated
      out.extra=[vis.Data()]
      if 'd' in coords: out.extra[0].x=out.d[0]
      if 'x' in coords: out.extra[0].y=out.x[0]
      if 'y' in coords: out.extra[0].x=out.y[0]
####      #h=-zw[0]
      h    = calc.griddata(x,y,h,X,Y,extrap=False)
      out.extra[0].v=-h # bottom
      out.extra[0].config['d1.plot']='fill_between'
      out.extra[0].config['d1.y0']=-h.max()-(h.max()-h.min())/20.
      out.extra[0].label='bottom'



    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 14
0
  def slicez(self,varname,ind,time=0,**opts):
    surf_mask=opts.get('surf_mask',True)
    spline=opts.get('spline',True)
    coords=opts.get('coords',self._default_coords('slicez')).split(',')

    out=vis.Data()
    out.label='slicez'
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out

    if not 'z' in self.vaxes(varname):
      return self.slicek(varname,ind,time,**opts)

    v=self.use(varname,SEARCHtime=time)
###    x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0])
    x,y,h,m=self.grid.vars(ruvp=self.vloc(varname)[0])
    zeta=self.use('zeta',SEARCHtime=time)
    zeta=rt.rho2uvp(zeta,varname)

    out.v=rt.slicez(v,m,h,zeta,self.s_params,ind,surf_mask,spline)

    out.info['v']['name']=varname
    if calc.isarray(ind):
      out.info['v']['slice']='z= array %.2f to %.2f'%(ind.min(),ind.max())
    else:
      out.info['v']['slice']='z=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'x' in coords:
       if self.grid.spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x/1000.
         out.info['x']=dict(name='Distance',units='km')

    if 'y' in coords:
       if self.grid.spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y/1000.
         out.info['y']=dict(name='Distance',units='km')

    if 'z' in coords:
      out.z=ind+np.zeros(out.v.shape)
      out.info['z']=dict(name='Depth',units='m')

    if 't' in coords and 't' in self.vaxes(varname): out.t=self.time[time]

    if out.v.ndim==2:
      out.extra=[vis.Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.cmap']='k'
      out.extra[0].label='bathy'


    out.coordsReq=','.join(sorted(coords))

    # about projection:
    out.set_projection(self.grid.proj_info['basemap_opts'])

    return out
Ejemplo n.º 15
0
  def slicej(self,varname,ind,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicej')).split(',')

    out=vis.Data()
    out.label='slicej'
    out.msg=self.check_slice(varname,t=time,j=ind)
    if out.msg: return out

    v=self.use(varname,SEARCHtime=time,eta_SEARCH=ind)

    # add mask if not masked:
    if not np.ma.isMA(v):
###      m=self.grid.vars(ruvp=self.var_at(varname)[0],j=ind)[-1]
      m=self.grid.vars(ruvp=self.vloc(varname)[0],j=ind)[-1]
      if v.ndim==2: m=np.tile(m,(v.shape[0],1))
      v=np.ma.masked_where(m==0,v)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='j=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.name,varname,'units')
    except: pass

    # coords:
    if 'z' in coords and v.ndim==2:
######      out.z=self.s_levels(time=time,ruvpw=self.var_at(varname),j=ind)
###      out.z=self.s_levels(time=time,loc=self.var_at(varname),j=ind)
      out.z=self.s_levels(time=time,loc=self.vloc(varname),j=ind)
      out.info['z']=dict(name='Depth',units='m')

    if any([i in coords for i in 'xyd']):
###      x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0],j=ind)
      x,y,h,m=self.grid.vars(ruvp=self.vloc(varname)[0],j=ind)

    if 'd' in coords:
      d=calc.distance(x,y)
      if d[-1]-d[0]>1e4:
        d=d/1000.
        dunits='km'
      else: dunits='m'

      if v.ndim==2: d=np.tile(d,(v.shape[0],1))
      out.d=d
      out.info['d']=dict(name='Distance',units=dunits)

    if 'x' in coords:
      if v.ndim==2: x=np.tile(x,(v.shape[0],1))
      out.x=x
      out.info['x']=dict(name='Longitude',units=r'$\^o$E')

    if 'y' in coords:
      if v.ndim==2: y=np.tile(y,(v.shape[0],1))
      out.y=y
      out.info['y']=dict(name='Latitude',units=r'$\^o$N')

########    if 't' in coords and self.hast(varname): out.t=self.time[time]
    if 't' in coords and 't' in self.vaxes(varname): out.t=self.time[time]

    if v.ndim==2:
      out.extra=[vis.Data()]
      if 'd' in coords: out.extra[0].x=out.d[0]
      if 'x' in coords: out.extra[0].y=out.x[0]
      if 'y' in coords: out.extra[0].x=out.y[0]
      out.extra[0].v=-h
      out.extra[0].config['d1.plot']='fill_between'
      out.extra[0].config['d1.y0']=-h.max()-(h.max()-h.min())/20.
      out.extra[0].label='bottom'

    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 16
0
Archivo: roms.py Proyecto: bssrdf/okean
  def slicell(self,varname,X,Y,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicell')).split(',')

    data      = opts.get('data',False)
    extrap    = opts.get('extrap',False)
    maskLimit = opts.get('lmask',0.5) # points where interpolated mask are above
                                      # this value are considered as mask!
                                      # Most strict value is 0

    out=Data()
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out#None,aux

    X=np.asarray(X)
    Y=np.asarray(Y)
    if X.ndim>1: X=np.squeeze(X)
    if Y.ndim>1: Y=np.squeeze(X)

    x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0])
    if True: # extrat only portion of data needed:
      i0,i1,j0,j1=calc.ij_limits(x, y, (X.min(),X.max()),(Y.min(),Y.max()), margin=1)
      xi='%d:%d'%(i0,i1)
      eta='%d:%d'%(j0,j1)

      if data is False: V=self.use(varname,SEARCHtime=time,xi_SEARCH=xi,eta_SEARCH=eta)
      else: v=data[...,j0:j1,i0:i1]

      x=x[j0:j1,i0:i1]
      y=y[j0:j1,i0:i1]
      #h=h[j0:j1,i0:i1] # not used
      m=m[j0:j1,i0:i1]

    else:
      if data is False: V=self.use(varname,SEARCHtime=time)
      else: v=data

    if V.ndim==3:
      v=calc.griddata(x,y,V,X,Y,extrap=extrap,mask2d=m==0, keepMaskVal=maskLimit)
    elif V.ndim==2:
      v=calc.griddata(x,y,np.ma.masked_where(m==0,V),X,Y,extrap=extrap, keepMaskVal=maskLimit)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='path npts=%d'%X.size
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'z' in coords and V.ndim==3:
      inds=dict(xi=(i0,i1),eta=(j0,j1))
#########      out.z=self.path_s_levels(time,X,Y,rw=varname[0],inds=inds)
      out.z=self.path_s_levels(time,X,Y,rw=self.var_at(varname)[1],inds=inds)

    if 'd' in coords:
      d=calc.distance(X,Y)
      if v.ndim==2: d=np.tile(d,(v.shape[0],1))
      out.d=d

    if 'x' in coords:
      if v.ndim==2: X=np.tile(X,(v.shape[0],1))
      out.x=X

    if 'y' in coords:
      if v.ndim==2: Y=np.tile(Y,(v.shape[0],1))
      out.y=Y

    if 't' in coords and self.hast(varname): out.t=self.time[time]

    out.coordsReq=','.join(sorted(coords))
    return out
Ejemplo n.º 17
0
  def slicek(self,varname,ind,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicek')).split(',')

    out=vis.Data()
    out.label='slicek'
    out.msg=self.check_slice(varname,t=time,k=ind)
    if out.msg: return out

    v=self.use(varname,SEARCHtime=time,s_SEARCH=ind)

    # add mask if not masked:
    if not np.ma.isMA(v): 
###      m=self.grid.vars(ruvp=self.var_at(varname)[0])[-1]
      m=self.grid.vars(ruvp=self.vloc(varname)[0])[-1]
      v=np.ma.masked_where(m==0,v)

    out.v=v
    out.info['v']['name']=varname
#####    if self.hasz(varname): out.info['v']['slice']='k=%d'%ind
    if 'z' in self.vaxes(varname): out.info['v']['slice']='k=%d'%ind
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'z' in coords and 'z' in self.vaxes(varname):
      out.z=self.s_levels(time,k=ind,loc=self.vloc(varname))
      out.info['z']=dict(name='Depth',units='m')


    if any([i in coords for i in 'xy']):
      x,y,h,m=self.grid.vars(ruvp=self.vloc(varname)[0])

    if 'x' in coords:
       if self.grid.spherical:
         out.x=x
         out.info['x']=dict(name='Longitude',units=r'$\^o$E')
       else:
         out.x=x/1000.
         out.info['x']=dict(name='Distance',units='km')

    if 'y' in coords:
       if self.grid.spherical:
         out.y=y
         out.info['y']=dict(name='Latitude',units=r'$\^o$N')
       else:
         out.y=y/1000.
         out.info['y']=dict(name='Distance',units='km')

    if 't' in coords and 't' in self.vaxes(varname): out.t=self.time[time]

    if out.v.ndim==2: # always?
      out.extra=[vis.Data()]
      if 'x' in coords: out.extra[0].x=out.x
      if 'y' in coords: out.extra[0].y=out.y
      out.extra[0].v=h
      if h.max()>1000: cvals=200.,1000.
      elif h.max()>200: cvals=50.,100.,200.
      else: cvals=3
      out.extra[0].config['field.plot']='contour'
      out.extra[0].config['field.cvals']=cvals
      out.extra[0].config['field.cmap']='k'
      out.extra[0].label='bathy'


    out.coordsReq=','.join(sorted(coords))

    # about projection:
    out.set_projection(self.grid.proj_info['basemap_opts'])

    return out
Ejemplo n.º 18
0
  def slicell(self,varname,X,Y,time=0,**opts):
    coords=opts.get('coords',self._default_coords('slicell')).split(',')

    data      = opts.get('data',False)
    extrap    = opts.get('extrap',False)
    maskLimit = opts.get('lmask',0.5) # points where interpolated mask are above
                                      # this value are considered as mask!
                                      # Most strict value is 0

    out=Data()
    out.msg=self.check_slice(varname,t=time)
    if out.msg: return out#None,aux

    X=np.asarray(X)
    Y=np.asarray(Y)
    if X.ndim>1: X=np.squeeze(X)
    if Y.ndim>1: Y=np.squeeze(X)

    x,y,h,m=self.grid.vars(ruvp=self.var_at(varname)[0])
    if True: # extrat only portion of data needed:
      i0,i1,j0,j1=calc.ij_limits(x, y, (X.min(),X.max()),(Y.min(),Y.max()), margin=1)
      xi='%d:%d'%(i0,i1)
      eta='%d:%d'%(j0,j1)

      if data is False: V=self.use(varname,SEARCHtime=time,xi_SEARCH=xi,eta_SEARCH=eta)
      else: v=data[...,j0:j1,i0:i1]

      x=x[j0:j1,i0:i1]
      y=y[j0:j1,i0:i1]
      #h=h[j0:j1,i0:i1] # not used
      m=m[j0:j1,i0:i1]

    else:
      if data is False: V=self.use(varname,SEARCHtime=time)
      else: v=data

    if V.ndim==3:
      v=calc.griddata(x,y,V,X,Y,extrap=extrap,mask2d=m==0, keepMaskVal=maskLimit)
    elif V.ndim==2:
      v=calc.griddata(x,y,np.ma.masked_where(m==0,V),X,Y,extrap=extrap, keepMaskVal=maskLimit)

    out.v=v
    out.info['v']['name']=varname
    out.info['v']['slice']='path npts=%d'%X.size
    try: out.info['v']['units']=netcdf.vatt(self.nc,varname,'units')
    except: pass


    # coords:
    if 'z' in coords and V.ndim==3:
      inds=dict(xi=(i0,i1),eta=(j0,j1))
#########      out.z=self.path_s_levels(time,X,Y,rw=varname[0],inds=inds)
      out.z=self.path_s_levels(time,X,Y,rw=self.var_at(varname)[1],inds=inds)

    if 'd' in coords:
      d=calc.distance(X,Y)
      if v.ndim==2: d=np.tile(d,(v.shape[0],1))
      out.d=d

    if 'x' in coords:
      if v.ndim==2: X=np.tile(X,(v.shape[0],1))
      out.x=X

    if 'y' in coords:
      if v.ndim==2: Y=np.tile(Y,(v.shape[0],1))
      out.y=Y

    if 't' in coords and self.hast(varname): out.t=self.time[time]

    out.coordsReq=','.join(sorted(coords))
    return out