def interp_bry(obctype,ncglo,tndx_glo,ncbry,tndx_bry,\
               h_bry,theta_s,theta_b,hc,N,vtransform,\
	       Nzgoodmin,depth,angle_bry,\
               LonT_bry,LatT_bry,iminT_bry,imaxT_bry,jminT_bry,jmaxT_bry,elemT_bry,coefT_bry,\
               LonU_bry,LatU_bry,iminU_bry,imaxU_bry,jminU_bry,jmaxU_bry,elemU_bry,coefU_bry,\
	       LonV_bry,LatV_bry,iminV_bry,imaxV_bry,jminV_bry,jmaxV_bry,elemV_bry,coefV_bry):


#
#
################################################################
# function interp_bry(obctype,ncglo,tndx_glo,ncbry,tndx_bry,\
#              h_bry,theta_s,theta_b,hc,N,vtransform,\
#	       Nzgoodmin,depth,angle_bry,\
#              LonT_bry,LatT_bry,iminT_bry,imaxT_bry,jminT_bry,jmaxT_bry,elemT_bry,coefT_bry,\
#              LonU_bry,LatU_bry,iminU_bry,imaxU_bry,jminU_bry,jmaxU_bry,elemU_bry,coefU_bry,\
#	       LonV_bry,LatV_bry,iminV_bry,imaxV_bry,jminV_bry,jmaxV_bry,elemV_bry,coefV_bry)
#
#
#   Interpolates all the variable for one boundary
#
#   Input:
#
#              obctype,ncglo,tndx_glo,ncbry,tndx_bry,
#              h_bry,theta_s,theta_b,hc,N,vtransform,
#	       Nzgoodmin,depth,angle_bry,
#              LonT_bry,LatT_bry,iminT_bry,imaxT_bry,jminT_bry,jmaxT_bry,elemT_bry,coefT_bry,
#              LonU_bry,LatU_bry,iminU_bry,imaxU_bry,jminU_bry,jmaxU_bry,elemU_bry,coefU_bry,
#	       LonV_bry,LatV_bry,iminV_bry,imaxV_bry,jminV_bry,jmaxV_bry,elemV_bry,coefV_bry
#
#   Output:
#
#   ncbry    Netcdf file structure
#
################################################################
#
#

  
#
#
# 1: SSH 
#
#

    print('Interpolate SSH...')
  
    (zeta_bry,NzGood) = glor.interp_tracers(ncglo,'ssh',tndx_glo,-1,\
                                        iminT_bry,imaxT_bry,jminT_bry,jmaxT_bry,\
				        LonT_bry,LatT_bry,coefT_bry,elemT_bry)

      

#
# Get CROCO sigma coordinate at rho and w points (using zeta)
#

    z_rho=vgrd.zlevs(h_bry,zeta_bry,theta_s,theta_b,hc,N,'r',vtransform)

    z_w=vgrd.zlevs(h_bry,zeta_bry,theta_s,theta_b,hc,N,'w',vtransform)

#
#
# 2: Temperature
#
#

    print('Interpolate Temperature...')

    temp_bry=glor.interp3d(ncglo,'temp',tndx_glo,Nzgoodmin,depth,z_rho,\
                             iminT_bry,imaxT_bry,jminT_bry,jmaxT_bry,\
			     LonT_bry,LatT_bry,coefT_bry,elemT_bry)

#
#
# 3: Salinity 
#
#

    print('Interpolate Salinity...')

    salt_bry=glor.interp3d(ncglo,'salt',tndx_glo,Nzgoodmin,depth,z_rho,\
                             iminT_bry,imaxT_bry,jminT_bry,jmaxT_bry,\
			     LonT_bry,LatT_bry,coefT_bry,elemT_bry)

#
#
# 4: U and V 
#
# (interpolate on z levels at rho points - rotate to align with the grid - 
#  put to u and v points - vertical interpolation to sigma grid)
#
#

    cosa=np.cos(angle_bry)
    sina=np.sin(angle_bry)

    [u_bry,v_bry]=glor.interp3d_uv(ncglo,tndx_glo,Nzgoodmin,depth,z_rho,cosa,sina,\
                    iminU_bry,imaxU_bry,jminU_bry,jmaxU_bry,\
		    LonU_bry,LatU_bry,coefU_bry,elemU_bry,\
                    iminV_bry,imaxV_bry,jminV_bry,jmaxV_bry,\
		    LonV_bry,LatV_bry,coefV_bry,elemV_bry)


#
#
# 5: UBAR and VBAR 
#
# Here it could be nice to get the barotropic transport from GLORYS, to put it on CROCO grid,
# and to correct u and v accordingly...
# But let's start simple and just integrate u and v on CROCO grid.
#
#

    (ubar_bry,h0)=vgrd.vintegr(u_bry,rho2u_3d(z_w),rho2u_3d(z_rho),np.nan,np.nan)/rho2u_2d(h_bry)
    (vbar_bry,h0)=vgrd.vintegr(v_bry,rho2v_3d(z_w),rho2v_3d(z_rho),np.nan,np.nan)/rho2v_2d(h_bry)


    if obctype=='s':

      ncbry['zeta_south'][tndx_bry,:]=zeta_bry[0,:]
      ncbry['temp_south'][tndx_bry,:,:]=temp_bry[:,0,:]
      ncbry['salt_south'][tndx_bry,:,:]=salt_bry[:,0,:]
      ncbry['u_south'][tndx_bry,:,:]=u_bry[:,0,:]
      ncbry['v_south'][tndx_bry,:,:]=v_bry[:,0,:]
      ncbry['ubar_south'][tndx_bry,:]=ubar_bry[0,:]
      ncbry['vbar_south'][tndx_bry,:]=vbar_bry[0,:]
      
    elif obctype=='n':

      ncbry['zeta_north'][tndx_bry,:]=zeta_bry[-1,:]
      ncbry['temp_north'][tndx_bry,:,:]=temp_bry[:,-1,:]
      ncbry['salt_north'][tndx_bry,:,:]=salt_bry[:,-1,:]
      ncbry['u_north'][tndx_bry,:,:]=u_bry[:,-1,:]
      ncbry['v_north'][tndx_bry,:,:]=v_bry[:,-1,:]
      ncbry['ubar_north'][tndx_bry,:]=ubar_bry[-1,:]
      ncbry['vbar_north'][tndx_bry,:]=vbar_bry[-1,:]

    elif obctype=='e':

      ncbry['zeta_east'][tndx_bry,:]=zeta_bry[:,0]
      ncbry['temp_east'][tndx_bry,:,:]=temp_bry[:,:,0]
      ncbry['salt_east'][tndx_bry,:,:]=salt_bry[:,:,0]
      ncbry['u_east'][tndx_bry,:,:]=u_bry[:,:,0]
      ncbry['v_east'][tndx_bry,:,:]=v_bry[:,:,0]
      ncbry['ubar_east'][tndx_bry,:]=ubar_bry[:,0]
      ncbry['vbar_east'][tndx_bry,:]=vbar_bry[:,0]


    elif obctype=='w':

      ncbry['zeta_west'][tndx_bry,:]=zeta_bry[:,-1]
      ncbry['temp_west'][tndx_bry,:,:]=temp_bry[:,:,-1]
      ncbry['salt_west'][tndx_bry,:,:]=salt_bry[:,:,-1]
      ncbry['u_west'][tndx_bry,:,:]=u_bry[:,:,-1]
      ncbry['v_west'][tndx_bry,:,:]=v_bry[:,:,-1]
      ncbry['ubar_west'][tndx_bry,:]=ubar_bry[:,-1]
      ncbry['vbar_west'][tndx_bry,:]=vbar_bry[:,-1]

    return(ncbry)
    #
    #

    print('Interpolate SSH...')

    (zeta, NzGood) = glor.interp_tracers(ncglo, 'ssh', tndx_glo, -1, iminT,
                                         imaxT, jminT, jmaxT, LonT, LatT,
                                         coefT, elemT)

    ncini['zeta'][tndx_ini, :, :] = zeta

    #
    # Get CROCO sigma coordinate at rho and w points (using zeta)
    #

    z_rho = vgrd.zlevs(h, zeta, theta_s, theta_b, hc, N, 'r', vtransform)

    z_w = vgrd.zlevs(h, zeta, theta_s, theta_b, hc, N, 'w', vtransform)

    #
    #
    # 2: Temperature
    #
    #

    print('Interpolate Temperature...')

    temp = glor.interp3d(ncglo, 'temp', tndx_glo, Nzgoodmin, depth, z_rho,
                         iminT, imaxT, jminT, jmaxT, LonT, LatT, coefT, elemT)

    ncini['temp'][tndx_ini, :, :, :] = temp
#
# Calculate rho at z=0
#
a = -P0 * (1 - np.exp(-H)) / (g * (H - 1 + np.exp(-H)))
rho1 = rho0 + a * np.exp(-(np.power(X, 2) + np.power(Y, 2)) / radius**2)

#
# Surface elevation
#
zeta = (P1 - Pa) / (g * rho1)

#
# Vertical grid
#
zw = zlevs(h0, zeta, theta_s, theta_b, hc, N, 'w', vtransform)
zr = zlevs(h0, zeta, theta_s, theta_b, hc, N, 'r', vtransform)

#
# Density
#
#
M, L = np.shape(X)
xr = np.reshape(X, (1, M, L))
xr = np.tile(xr, (N, 1, 1))
M, L = np.shape(Y)
yr = np.reshape(Y, (1, M, L))
yr = np.tile(yr, (N, 1, 1))

#
rho = rho0 * (1 - N2 * zr / g)
def get_NS_section(Lat_min,Lat_max,Lon_sec,fname,vname,tndx):

#
#  Extract a  merdional vertical slice from a ROMS netcdf file 
#  (with a regular rectangular grid)
#
# 
# On Input:
# 
#    Lat_min     Minimum latitude of section
#    Lat_max     Maximum latitude of section
#    Lon_sec     Longitude of section
#    fname       ROMS/CROCO netcdf name
#    vname       ROMS/CROCO variable name
#
#
# On Output: LAT,Z,VAR
#
#    LAT         Latitudes of the section (2D matrix)
#    Z           Slice Z-positions (2D matrix)
#    VAR         Slice variable (2D matrix)
#
#
### FUNCTION GET_NS_SECTION ###################################################
#
#

# 
# Open netcdf file
# 

  nc=netcdf(fname,mode='r')

#
# Read in the file
#

  lon = np.array(nc.variables['lon_rho'][0,:])
  lat = np.array(nc.variables['lat_rho'][:,0])

  print( 'Lon min: ', lon.min(),' Lon max: ', lon.max())
  print( 'Lat min: ', lat.min(),' Lat max: ', lat.max())

  dlon=np.abs(lon-Lon_sec)
  dlat1=np.abs(lat-Lat_min)
  dlat2=np.abs(lat-Lat_max)

  i=np.int(np.array(np.where(dlon==np.min(dlon))))
  jmin=np.int(np.array(np.where(dlat1==np.min(dlat1))))
  jmax=np.int(np.array(np.where(dlat2==np.min(dlat2))))

  lat = lat[jmin:jmax]
  rmask=np.array(nc.variables['mask_rho'][jmin:jmax,i])
  h=np.array(nc.variables['h'][jmin:jmax,i])
  zeta=np.array(nc.variables['zeta'][tndx,jmin:jmax,i])
  print(vname)
  VAR=np.array(nc.variables[vname][tndx,:,jmin:jmax,i])

  theta_s=nc.theta_s
  theta_b=nc.theta_b
  hc=nc.hc
  vtransform=nc.variables['Vtransform'][:]
  sc_r=nc.variables['sc_r'][:]
  N=np.size(sc_r)

  nc.close()

  LAT=np.matlib.repmat(lat,N,1)
  MASK=np.matlib.repmat(rmask,N,1)
  VAR[np.where(MASK==0)]=np.nan
  Z=vgrd.zlevs(h,zeta,theta_s,theta_b,hc,N,'r',vtransform)

  return LAT,Z,VAR
def get_UV_section(lonsec,latsec,u,v,lon,lat,rmask,h,zeta,theta_s,theta_b,hc,N,vtransform):

#
#  Extract a vertical slice of cross-section and along section velocities
#  in any direction (or along a curve) from a ROMS netcdf file.
#
# 
# On Input:
# 
#    lonsec      Longitudes of the points of the section. 
#    latsec      Latitudes of the points of the section.
#    u           CROCO eastward velocities at rho point
#    v           CROCO northward velocities at rho point
#    lon         Longitudes at rho points
#    lat         Latitudes at rho points
#    rmask
#    h
#    zeta
#    theta_s
#    theta_b
#    hc
#    N
#    vtransform
#
#
# On Output: LON,LAT,X,Z,Un,Ut
#
#    LON         Longitudes of the section (2D matrix).
#    LAT         Latitudes of the section (2D matrix).
#    X           Slice X-distances (km) from the first point (2D matrix).
#    Z           Slice Z-positions (2D matrix). 
#    Un          Slice cross-section velocities (2D matrix). 
#    Ut          Slice along-section velocities (2D matrix). 
#
#

  Npts=np.size(lonsec)
    
  dlon=np.gradient(lonsec)
  dlat=np.gradient(latsec)
  Rearth=6367442.76
  deg2rad=np.pi/180
  dx=Rearth*deg2rad*dlon*np.cos(deg2rad*latsec)
  dy=Rearth*deg2rad*dlat
    
  dl=np.sqrt(dx*dx +dy*dy)
  
  tx=dx/dl
  ty=dy/dl
  nx=-ty
  ny=tx

#
# Get a first subgrid limited by the size of the section (extended by twice the resolution dl)
#


  (dlony,dlonx)=np.gradient(lon)
  (dlaty,dlatx)=np.gradient(lat)
  dl=2*np.max((np.max(np.abs(dlonx)),np.max(np.abs(dlony)),np.max(np.abs(dlatx)),np.max(np.abs(dlaty))))
  minlon=np.min(lonsec)-dl
  minlat=np.min(latsec)-dl
  maxlon=np.max(lonsec)+dl
  maxlat=np.max(latsec)+dl

  sub=( (lon>minlon) & (lon<maxlon) & (lat>minlat) & (lat<maxlat) )
  (jndx,indx)=np.where(sub)
  imin=np.min(indx)
  imax=np.max(indx)
  jmin=np.min(jndx)
  jmax=np.max(jndx)


  lon=lon[jmin:jmax,imin:imax]
  lat=lat[jmin:jmax,imin:imax]
  zeta=zeta[jmin:jmax,imin:imax]
  h=h[jmin:jmax,imin:imax]
  rmask=rmask[jmin:jmax,imin:imax]
  u=u[:,jmin:jmax,imin:imax]
  v=v[:,jmin:jmax,imin:imax]

  masksec=np.nan+0*lonsec
  zetasec=np.nan+0*lonsec
  HSEC=np.nan+0*lonsec
  Un=np.nan+np.zeros((N,Npts))
  Ut=np.nan+np.zeros((N,Npts))

#
# Do an interpolation for each point of the section
#

  for i in np.arange(0,Npts):

#
# Get a subgrid around each point
#

    sub=( (lon>lonsec[i]-dl) & (lon<lonsec[i]+dl) & \
          (lat>latsec[i]-dl) & (lat<latsec[i]+dl) )
    (jndx,indx)=np.where(sub)
    imin=np.min(indx)
    imax=np.max(indx)
    jmin=np.min(jndx)
    jmax=np.max(jndx)

    londata=lon[jmin:jmax,imin:imax].ravel()
    latdata=lat[jmin:jmax,imin:imax].ravel()
    maskdata=rmask[jmin:jmax,imin:imax].ravel()
    zetadata=zeta[jmin:jmax,imin:imax].ravel()
    hdata=h[jmin:jmax,imin:imax].ravel()

#
# Get the mask as nearest point
#

    masksec[i]=griddata((londata,latdata),maskdata, (lonsec[i], latsec[i]), method='nearest')

#
# If there is enough data, do the interpolation
#
 
    isgood=np.where(np.isfinite(zetadata))

    if np.size(isgood)>4:
      zetasec[i]=griddata((londata[isgood],latdata[isgood]),zetadata[isgood], (lonsec[i], latsec[i]), method='cubic')
      HSEC[i]=griddata((londata[isgood],latdata[isgood]),hdata[isgood], (lonsec[i], latsec[i]), method='cubic')
  
      for k in np.arange(0,N):
        vdata=u[k,jmin:jmax,imin:imax].ravel()
        U=griddata((londata[isgood],latdata[isgood]),vdata[isgood], (lonsec[i], latsec[i]), method='cubic')
        vdata=v[k,jmin:jmax,imin:imax].ravel()
        V=griddata((londata[isgood],latdata[isgood]),vdata[isgood], (lonsec[i], latsec[i]), method='cubic')
        Un[k,i]=U*nx[i]+V*ny[i]
        Ut[k,i]=U*tx[i]+V*ty[i]

#
# Get the vertical positions
#
 
  zetasec[np.where(np.isnan(zetasec))]=0.
  HSEC[np.where(np.isnan(HSEC))]=hc
  Z=vgrd.zlevs(HSEC,zetasec,theta_s,theta_b,hc,N,'r',vtransform)

#
# Get the horizontal positions
#
  dx=0.*lonsec
  for i in np.arange(1,Npts):
    dx[i]=1e-3*tpx.spheric_dist(latsec[i-1],latsec[i],lonsec[i-1],lonsec[i])

  dist=np.cumsum(dx)
  X=np.matlib.repmat(dist,N,1)
  LON=np.matlib.repmat(lonsec,N,1)
  LAT=np.matlib.repmat(latsec,N,1)

  return LON,LAT,X,Z,Un,Ut
def get_section(lonsec,latsec,var,lon,lat,rmask,h,zeta,theta_s,theta_b,hc,N,vtransform):

#
#  Extract a vertical slice in any direction (or along a curve)
#  from a ROMS netcdf file.
#
# 
# On Input:
# 
#    lonsec      Longitudes of the points of the section. 
#    latsec      Latitudes of the points of the section.
#    var         CROCO 3D variable at rho point
#    lon         Longitudes at rho points
#    lat         Latitudes at rho points
#    rmask
#    h
#    zeta
#    theta_s
#    theta_b
#    hc
#    N
#    vtransform
#
#
# On Output:LON,LAT,X,Z,VAR
#
#    LON         Longitudes of the section (2D matrix).
#    LAT         Latitudes of the section (2D matrix).
#    X           Slice X-distances (km) from the first point (2D matrix).
#    Z           Slice Z-positions (matrix). 
#    VAR         Slice of the variable (matrix).
#
#

  Npts=np.size(lonsec)

#
# Get a first subgrid limited by the size of the section (extended by twice the resolution dl)
#


  (dlony,dlonx)=np.gradient(lon)
  (dlaty,dlatx)=np.gradient(lat)
  dl=2*np.max((np.max(np.abs(dlonx)),np.max(np.abs(dlony)),np.max(np.abs(dlatx)),np.max(np.abs(dlaty))))


  print(dl)
  
  minlon=np.min(lonsec)-dl
  minlat=np.min(latsec)-dl
  maxlon=np.max(lonsec)+dl
  maxlat=np.max(latsec)+dl

  sub=( (lon>minlon) & (lon<maxlon) & (lat>minlat) & (lat<maxlat) )
  (jndx,indx)=np.where(sub)
  imin=np.min(indx)
  imax=np.max(indx)
  jmin=np.min(jndx)
  jmax=np.max(jndx)


  lon=lon[jmin:jmax,imin:imax]
  lat=lat[jmin:jmax,imin:imax]
  zeta=zeta[jmin:jmax,imin:imax]
  h=h[jmin:jmax,imin:imax]
  rmask=rmask[jmin:jmax,imin:imax]
  var=var[:,jmin:jmax,imin:imax]

  masksec=np.nan+0*lonsec
  zetasec=np.nan+0*lonsec
  HSEC=np.nan+0*lonsec
  VAR=np.nan+np.zeros((N,Npts))

#
# Do an interpolation for each point of the section
#

  for i in np.arange(0,Npts):

#
# Get a subgrid around each point
#

    sub=( (lon>lonsec[i]-dl) & (lon<lonsec[i]+dl) & \
          (lat>latsec[i]-dl) & (lat<latsec[i]+dl) )
    (jndx,indx)=np.where(sub)
    imin=np.min(indx)
    imax=np.max(indx)
    jmin=np.min(jndx)
    jmax=np.max(jndx)

    londata=lon[jmin:jmax,imin:imax].ravel()
    latdata=lat[jmin:jmax,imin:imax].ravel()
    maskdata=rmask[jmin:jmax,imin:imax].ravel()
    zetadata=zeta[jmin:jmax,imin:imax].ravel()
    hdata=h[jmin:jmax,imin:imax].ravel()

#
# Get the mask as nearest point
#

    masksec[i]=griddata((londata,latdata),maskdata, (lonsec[i], latsec[i]), method='nearest')

#
# If there is enough data, do the interpolation
#
 
    isgood=np.where(np.isfinite(zetadata))

    if np.size(isgood)>4:
      zetasec[i]=griddata((londata[isgood],latdata[isgood]),zetadata[isgood], (lonsec[i], latsec[i]), method='cubic')
      HSEC[i]=griddata((londata[isgood],latdata[isgood]),hdata[isgood], (lonsec[i], latsec[i]), method='cubic')
  
      for k in np.arange(0,N):
        vdata=var[k,jmin:jmax,imin:imax].ravel()
        VAR[k,i]=griddata((londata[isgood],latdata[isgood]),vdata[isgood], (lonsec[i], latsec[i]), method='cubic')

#
# Get the vertical positions
#
 
  zetasec[np.where(np.isnan(zetasec))]=0.
  HSEC[np.where(np.isnan(HSEC))]=hc
  Z=vgrd.zlevs(HSEC,zetasec,theta_s,theta_b,hc,N,'r',vtransform)

#
# Get the horizontal positions
#
 

# Get the horizontal positions
#
  dx=0.*lonsec
  for i in np.arange(1,Npts):
    dx[i]=1e-3*tpx.spheric_dist(latsec[i-1],latsec[i],lonsec[i-1],lonsec[i])

  dist=np.cumsum(dx)
  X=np.matlib.repmat(dist,N,1)
  LON=np.matlib.repmat(lonsec,N,1)
  LAT=np.matlib.repmat(latsec,N,1)

  return LON,LAT,X,Z,VAR