Esempio n. 1
0
  def extract(self,varname,method='fast',nfast=1,quiet=1):
    if not self.roms.hast(varname):
      method,nfast='fast',1

    tag=self.horiz_var_type(varname)
    if tag in self.uinds.keys():
      inds0=self.inds0[tag]
      uinds=self.uinds[tag]
    else:
      inds0,uinds=self.locate(varname,quiet)

    J,I,T = uinds.T
    J0,I0,T0 = inds0.T

    if not self.roms.hast(varname): no_time=True
    else: no_time=False


    if method=='fast': # faster but will download more data than needed!
      II=range(I.min(),I.max()+1)
      JJ=range(J.min(),J.max()+1)
      TT=range(T[T>=0].min(),T.max()+1)


      if not calc.isiterable(nfast) and nfast==1:
        if not quiet: print('loading %s : ijt= %d %d %d'%(varname,len(II),len(JJ),len(TT)))
        v=netcdf.use(self.nc,varname,xiSEARCH=II,etaSEARCH=JJ,ocean_time=TT)
      else:
        v=False
        if not calc.isiterable(nfast):
          nfast=min(nfast,len(TT)-1)
          tmp=range(TT[0],TT[-1]+2,(TT[-1]-TT[0])/nfast)
          if tmp[-1]<TT[-1]+1: tmp+=[TT[-1]+1]
        else: tmp=nfast

        for k in range(len(tmp)-1):
          tt=range(tmp[k],tmp[k+1])
          if not quiet: print('loading %s : ijt= %d %d %d (t %d to %d)'%(varname,len(II),len(JJ),len(tt), tt[0],tt[-1]))
          vtmp=netcdf.use(self.nc,varname,xiSEARCH=II,etaSEARCH=JJ,ocean_time=tt)
          if not v is False:
            if vtmp.ndim<v.ndim: vtmp=vtmp[np.newaxis,:] # if len of last tt is 1 !
            v=np.vstack((v,vtmp))
          else: v=vtmp

      
      if v.ndim>3:
        V=np.ma.zeros((I.size,v.shape[1]),'f')
      else:
        V=np.ma.zeros(I.size,'f')

      for i in range(I.size):
        xi   = I[i]-I.min()
        eta  = J[i]-J.min()
        if T[i]>=0: tind = T[i]-T[T>=0].min()
        else: tind=T[i] # negative means data ouside model time

        if v.ndim==4:
          V[i]=v[tind,:,eta,xi]
        elif v.ndim==3:
          V[i]=v[tind,eta,xi]
        elif v.ndim==2:
          V[i]=v[eta,xi]

    else:
      V=False
      for i in range(len(I)):
        if T[i]<0: continue
        if not quiet: print('loading %s  (%d of %d): ijt= %d %d %d'%(varname,i,len(I),I[i],J[i],T[i]))
        v=netcdf.use(self.nc,varname,xiSEARCH=I[i],etaSEARCH=J[i],ocean_time=T[i])
        if V is False:
          if v.ndim>1: shape=(len(I),)+v.shape
          else: shape=len(I)
          V=np.ma.zeros(shape,'f')

        V[i]=v

    lon,lat=self.model_lon_lat(varname)
    U=np.array(())
    for i in range(len(self.t)):
      xi   = I0[i]
      eta  = J0[i]
      tind = T0[i]
      if tind<0: continue # data outside model time

      # rotate cell before interp:
      xp=np.asarray([lon[eta,xi],lon[eta,xi+1],lon[eta+1,xi+1],lon[eta+1,xi],self.x[i]])
      yp=np.asarray([lat[eta,xi],lat[eta,xi+1],lat[eta+1,xi+1],lat[eta+1,xi],self.y[i]])
      xp,yp=calc.rot2d(xp,yp,self.roms.grid.angle[eta,xi])
      x=xp[:-1].min(),xp[-1],xp[:-1].max()
      y=yp[:-1].min(),yp[-1],yp[:-1].max()

      A = x[1]-x[0]
      a = x[2]-x[1]
      B = y[1]-y[0]
      b = y[2]-y[1]

      tcond=(T==tind)#|(tind<0)
      tcond1=(T==tind+1)#|(tind+1<0)
      j0=np.where((I==xi)&(J==eta)&tcond)[0][0]
      j1=np.where((I==xi+1)&(J==eta)&tcond)[0][0]
      j2=np.where((I==xi+1)&(J==eta+1)&tcond)[0][0]
      j3=np.where((I==xi)&(J==eta+1)&tcond)[0][0]
      u0=(V[j0]*a*b+V[j1]*A*b+V[j2]*A*B+V[j3]*a*B)/(a*b+A*b+A*B+a*B)
      
      if not no_time:
        dt0=self.t[i]-self.roms.time[tind]
        dt1=self.roms.time[tind+1]-self.t[i]
        dt0=dt0.days*86400+dt0.seconds
        dt1=dt1.days*86400+dt1.seconds

        k0=np.where((I==xi)&(J==eta)&tcond1)[0][0]
        k1=np.where((I==xi+1)&(J==eta)&tcond1)[0][0]
        k2=np.where((I==xi+1)&(J==eta+1)&tcond1)[0][0]
        k3=np.where((I==xi)&(J==eta+1)&tcond1)[0][0]

        u1=(V[k0]*a*b+V[k1]*A*b+V[k2]*A*B+V[k3]*a*B)/(a*b+A*b+A*B+a*B)
        u=(u0*dt1+u1*dt0)/(dt1+dt0)
      else:
        u=u0

      if not U.size:
        U=np.ma.zeros((len(self.t),u.size),'f')
        U=np.ma.masked_where(U==0,U)

      U[i]=u

    U=np.squeeze(U)
    return U
Esempio n. 2
0
  def _slice(self,slc,varname,ind,it0,**opts):
##    border=opts.get('border',1)

    if slc=='ll': x,y=ind

    o=[]
    It,twarn=self.tinds(it0)
    for c,i in enumerate(self):
      meth=getattr(i,'slice'+slc)
      if slc=='uv':  o+=[meth(ind,It[c],**opts)]
      elif slc=='ll':o+=[meth(varname,x,y,It[c],**opts)]
      else:          o+=[meth(varname,ind,It[c],**opts)]
      #if msg[c]:
      #  if o[-1].msg: o[-1].msg+='\n'
      #  o[-1].msg+=msg[c]


    # add filled border for next domain:
    if slc in ['i','j','k','z','iso']:#,'uv']:
      for i in range(len(self)-1):
        xb,yb=self[i+1].grid.border()
        o[i].extra+=[vis.Data(xb,yb)]
        o[i].extra[-1].label='border grid %d'%(i+1)
        #if i>0:
        o[i].extra[-1].config['d1.plot']='fill'
        o[i].extra[-1].config['d1_fill.options']['lw']=0
        o[i].extra[-1].config['d1_fill.options']['facecolor']='w'
        #o[i].extra[-1].config['plot.zorder']=1
        #else:
        #  o[i].extra[-1].config['d1.plot']='plot'
    elif slc=='uv': # for uv, better to mask arrows inside child domains
      if not hasattr(self.grid,'ingrd'): self.grid._set_ingrid('p')
      from functools import reduce
      for c,i in enumerate(o):
        if not i.v is None:
          if len(self.grid[c].ingrd_p):
            mask=reduce(lambda i,j: i&j,self.grid[c].ingrd_p)
            mask=mask&(~i.v.mask)
            i.nmask=mask # nested domains mask
            i.v.mask=i.v.mask|i.nmask
          else: i.nmask=None



    # vfield settings:
    if not o[0].v is None:
      vfield=o[0].get_param('vfield')
      if not vfield['options']['scale']:
        vfield['options']={'units':'width','scale':10}

      # use same vfield settings for all slices:
      for i in o:
        for k in vfield: i.config['vfield.'+k]=vfield[k]

      # no key for slices[1:]:
      for i in o[1:]:
        i.config['vfield.key_XYU']=0,0,0


    # field settings:
    if not o[0].v is None:
      field=o[0].get_param('field')

      if field['clim'] is False:
        if np.iscomplexobj(o[0].v):
          field['clim']=np.abs(o[0].v).min(),np.abs(o[0].v).max()
        else:
          field['clim']=o[0].v.min(),o[0].v.max()

        if field['clim'][0]==field['clim'][1]:
          field['clim']=field['clim'][0]-1,field['clim'][0]+1

      if field['cvals'] is False:
        tk=ticks.loose_label_n(field['clim'][0],field['clim'][1],7)
        field['cvals']=tk

      # use same field settings for all slices:
      for i in o:
        for k in field: i.config['field.'+k]=field[k]


    # also same settings for extras like bathy contours:
    Lab=['bathy']
    for lab in Lab:
      for e in o[0].extra:
        if e.label==lab and not e.v is None:
          field=e.get_param('field')
          if field['clim'] is False: field['clim']=e.v.min(),e.v.max()
          if field['cvals'] is False or  not calc.isiterable(field['cvals']):
            # the isiterable here is because it can be an integer (nof fixed set)
            tk=ticks.loose_label_n(field['clim'][0],field['clim'][1],3)
            field['cvals']=tk

      for i in o:
        for e in i.extra:
          if e.label==lab:
            for k in field: e.config['field.'+k]=field[k]

    # add border for all domains:
#    xb,yb=self.grid.border()
#    o[0].extra+=[vis.Data(x=xb,v=yb)]
    borders=[]
    for i in self:
      xb,yb=i.grid.border()
      c=vis.Data(x=xb,v=yb)
      c.set_param(d1_line__options=dict(lw=0.5,color='k',ls='-'))
      borders+=[c]

    o[-1].extra+=borders

    # set zorder:
    c=1
    for i in o:
      c+=0.1
      i.config['plot.zorder']=c
      for j in i.extra:
        c+=0.1
        j.config['plot.zorder']=c

    # place some stuff above continents:
    z=o[0].config['proj.continents']['zorder']
    z+=0.1
    # vfield:
    if slc=='uv':
      for i in o: i.config['plot.zorder']=z

    # place borders above continents:
    for b in borders: b.config['plot.zorder']=z


    return vis.MData(o,warnings=twarn)
Esempio n. 3
0
  def _slice(self,slc,varname,ind,it0,**opts):
##    border=opts.get('border',1)

    if slc=='ll': x,y=ind

    o=[]
    It,twarn=self.tinds(it0)
    for c,i in enumerate(self):
      meth=getattr(i,'slice'+slc)
      if slc=='uv':  o+=[meth(ind,It[c],**opts)]
      elif slc=='ll':o+=[meth(varname,x,y,It[c],**opts)]
      else:          o+=[meth(varname,ind,It[c],**opts)]
      #if msg[c]:
      #  if o[-1].msg: o[-1].msg+='\n'
      #  o[-1].msg+=msg[c]


    # add filled border for next domain:
    if slc in ['i','j','k','z','iso']:#,'uv']:
      for i in range(len(self)-1):
        xb,yb=self[i+1].grid.border()
        o[i].extra+=[vis.Data(xb,yb)]
        o[i].extra[-1].label='border grid %d'%(i+1)
        #if i>0:
        o[i].extra[-1].config['d1.plot']='fill'
        o[i].extra[-1].config['d1_fill.options']['lw']=0
        o[i].extra[-1].config['d1_fill.options']['facecolor']='w'
        #o[i].extra[-1].config['plot.zorder']=1
        #else:
        #  o[i].extra[-1].config['d1.plot']='plot'
    elif slc=='uv': # for uv, better to mask arrows inside child domains
      if not hasattr(self.grid,'ingrd'): self.grid._set_ingrid('p')
      from functools import reduce
      for c,i in enumerate(o):
        if not i.v is None:
          if len(self.grid[c].ingrd_p):
            mask=reduce(lambda i,j: i&j,self.grid[c].ingrd_p)
            mask=mask&(~i.v.mask)
            i.nmask=mask # nested domains mask
            i.v.mask=i.v.mask|i.nmask
          else: i.nmask=None



    # vfield settings:
    if not o[0].v is None:
      vfield=o[0].get_param('vfield')
      if not vfield['options']['scale']:
        vfield['options']={'units':'width','scale':10}

      # use same vfield settings for all slices:
      for i in o:
        for k in vfield: i.config['vfield.'+k]=vfield[k]

      # no key for slices[1:]:
      for i in o[1:]:
        i.config['vfield.key_XYU']=0,0,0


    # field settings:
    if not o[0].v is None:
      field=o[0].get_param('field')

      if field['clim'] is False:
        if np.iscomplexobj(o[0].v):
          field['clim']=np.abs(o[0].v).min(),np.abs(o[0].v).max()
        else:
          field['clim']=o[0].v.min(),o[0].v.max()

        if field['clim'][0]==field['clim'][1]:
          field['clim']=field['clim'][0]-1,field['clim'][0]+1

      if field['cvals'] is False:
        tk=ticks.loose_label_n(field['clim'][0],field['clim'][1],7)
        field['cvals']=tk

      # use same field settings for all slices:
      for i in o:
        for k in field: i.config['field.'+k]=field[k]


    # also same settings for extras like bathy contours:
    Lab=['bathy']
    for lab in Lab:
      for e in o[0].extra:
        if e.label==lab and not e.v is None:
          field=e.get_param('field')
          if field['clim'] is False: field['clim']=e.v.min(),e.v.max()
          if field['cvals'] is False or  not calc.isiterable(field['cvals']):
            # the isiterable here is because it can be an integer (nof fixed set)
            tk=ticks.loose_label_n(field['clim'][0],field['clim'][1],3)
            field['cvals']=tk

      for i in o:
        for e in i.extra:
          if e.label==lab:
            for k in field: e.config['field.'+k]=field[k]

    # add border for all domains:
#    xb,yb=self.grid.border()
#    o[0].extra+=[vis.Data(x=xb,v=yb)]
    borders=[]
    for i in self:
      xb,yb=i.grid.border()
      c=vis.Data(x=xb,v=yb)
      c.set_param(d1_line__options=dict(lw=0.5,color='k',ls='-'))
      borders+=[c]

    o[-1].extra+=borders

    # set zorder:
    c=1
    for i in o:
      c+=0.1
      i.config['plot.zorder']=c
      for j in i.extra:
        c+=0.1
        j.config['plot.zorder']=c

    # place some stuff above continents:
    z=o[0].config['proj.continents']['zorder']
    z+=0.1
    # vfield:
    if slc=='uv':
      for i in o: i.config['plot.zorder']=z

    # place borders above continents:
    for b in borders: b.config['plot.zorder']=z


    return vis.MData(o,warnings=twarn)
Esempio n. 4
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
Esempio n. 5
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