Esempio n. 1
0
   def get_contour_lengths(self,bmap=None,pobj=None,show=True,test_function=None,\
                              func_vals_orig=None):

      import numpy as np
      ###########################################################################################
      class area_info:

         ########################################################################################
         def __init__(self,xy_bdy_coords,xy_conts,\
                        area,perimeter,lengths,\
                        spherical_geometry=False,\
                        ll_bdy_coords=None,ll_contours=None,\
                        func_vals=None,stream_func=None):
         
            import MIZchar as mizc
            # NB use "1*" to remove pointers to the arrays outside the function
            # - like copy, but works for lists also
            self.xy_bdy_coords   = 1*xy_bdy_coords # (x,y) coordinates of boundary (ie in projected space)
            self.xy_contours     = 1*xy_conts      # (x,y) coordinates of each contour
            self.lengths         = 1*lengths	   # lengths of each contour
            self.area	         = area		   # area of polygon
            self.perimeter       = perimeter	   # perimeter of polygon
            self.FDI             = mizc.frac_dim_index([self.area,self.perimeter])
            
            # lon-lat info if present
            self.spherical_geometry = spherical_geometry
            if spherical_geometry:
               if ll_contours is None:
                  raise ValueError('"ll_contours" not given')
               if ll_bdy_coords is None:
                  raise ValueError('"ll_bdy_coords" not given')
               self.lonlat_contours = 1*ll_contours   # (lon,lat) coordinates of each contour
               self.ll_bdy_coords   = 1*ll_bdy_coords # (lon,lat) coordinates of boundary

            if func_vals is not None:
               self.func_vals	 = 1*func_vals	   # value of function used by Laplace's equation
            if stream_func is not None:
               self.stream_func	 = 1*stream_func   # value of stream function produced by Laplace's equation

            # some summarising info about "lengths"
            lens                       = np.array(lengths)
            self.length_mean           = np.mean(lens)
            self.length_median         = np.median(lens)
            self.length_percentile05   = np.percentile(lens,5)
            self.length_percentile95   = np.percentile(lens,95)

            return
      ###########################################################################################

      if bmap is not None:
         # boundary/area information
         # - use routines for sphere
         import geometry_sphere as GS

         print('getting contour lengths on sphere...\n')

         x,y            = np.array(self.coords).transpose()
         lons,lats      = bmap(x,y,inverse=True)
         lst            = list(np.array([lons,lats]).transpose())
         ll_bdy_coords  = [(lo,la) for lo,la in lst]
         area           = GS.area_polygon_ellipsoid(lons,lats,radians=False)
         arclen         = GS.arc_length(lons,lats,radians=False,closed=True)
         perimeter      = arclen[-1]

         # get isolines of function (plot if pobj is not None)
         contours = self.get_isolines(pobj=pobj,show=show,test_function=test_function,\
                                       func_vals_orig=func_vals_orig)

         ll_conts = []
         lengths  = []

         for cont in contours:
            # list of coords (tuples)
            x,y         = np.array(cont).transpose()
            lons,lats	= bmap(x,y,inverse=True)
            arclen      = GS.arc_length(lons,lats,radians=False,closed=False)
            #
            lengths.append(arclen[-1])	#perimeter
            lst	  = list(np.array([lons,lats]).transpose())
            tups  = [(lo,la) for lo,la in lst]
            ll_conts.append(tups)

         # output object with all the info
         AI = area_info(self.coords,contours,\
                        area,perimeter,lengths,\
                        func_vals=self.func_vals,stream_func=self.stream_func_bdy,\
                        ll_bdy_coords=ll_bdy_coords,ll_contours=ll_conts,\
                        spherical_geometry=True)
      else:
         # boundary/area information
         # - just Euclidean routines
         import geometry_planar as GP

         print('getting contour lengths in the plane...\n')

         x,y         = np.array(self.coords).transpose()
         area        = self.shapely_polygon.area
         perimeter   = self.shapely_polygon.length

         # get isolines of function (plot if pobj is not None)
         contours = self.get_isolines(pobj=pobj,show=show,\
                                       test_function=test_function,\
                                       func_vals_orig=func_vals_orig)
         lengths  = []

         for cont in contours:
            # list of coords (tuples)
            P  = GP.curve_info(cont,closed=False)[0]	# perimeter
            lengths.append(P)

         # output object with all the info
         # area_info(xy_bdy_coords,xy_conts,\
         #			area,perimeter,lengths,\
         #			ll_bdy_coords=None,ll_conts=None,\
         #			func_vals=None,stream_func=None,):
         AI = area_info(self.coords,contours,\
                        area,perimeter,lengths,\
                        func_vals=self.func_vals,stream_func=self.stream_func_bdy,\
                        spherical_geometry=False)

      return AI
               height=100.e3,
               width=100.e3)
lons, lats = bmap(x0, y0, inverse=True)

####################################################################################
if 1:
    Psoln = Leqs.get_MIZ_widths(lons, lats)
    fun_sol = Psoln.potential
    stream = Psoln.stream
    AI = Psoln.area_info
else:
    import geometry_sphere as GS  # from py_funs
    import f_vals_smoother as smt

    R = 6378273.  # default is hyc2proj radius (m)
    AL = GS.arc_length(lons, lats, R=R, radians=False, closed=True)
    P = AL[-1]
    #
    latc = np.mean(lats)
    lonc = np.mean(lons)  # TODO 1st should make lon continuous around polygon
    # - to make sure lonc is inside polygon
    basemap = Basemap(lon_0=lonc,lat_0=latc,lat_ts=latc,\
                    projection='stere',rsphere=[R,R],\
                    width=P,height=P)
    # x,y         = basemap(lons,lats)
    x, y = bmap(lons, lats)
    xy_coords2 = np.array([x, y]).transpose()
    #
    PCA = smt.pca_mapper(xy_coords2)
    fvals2 = PCA.set_func_vals()
Esempio n. 3
0
def get_MIZ_widths(lons,lats,fvals=None,name=None,fig_outdir=None,basemap=None,xy_coords2=None):

   # Apparently the modules have to been called again 
   import time
   import sys,os
   import numpy as np 
   from matplotlib import pyplot as plt
   
   sys.path.append('../py_funs')
   import f_vals_smoother as smt	
   
   if xy_coords2 is None:

      ######################################################################################
      # make basemap if needed
      if basemap is None:
         from mpl_toolkits.basemap import Basemap
         import geometry_sphere as GS # from py_funs
         #
         R    = 6378273.# default is hyc2proj radius (m)
         AL   = GS.arc_length(lons,lats,R=R,radians=False,closed=True)
         P    = AL[-1]
         #
         latc = np.mean(lats)
         lonc = np.mean(lons)   # TODO 1st should make lon continuous around polygon
                                # - to make sure lonc is inside polygon
         basemap = Basemap(lon_0=lonc,lat_0=latc,lat_ts=latc,\
                              projection='stere',rsphere=[R,R],\
                              width=P,height=P)
         ###################################################################################

      x,y         = basemap(lons,lats)
      xy_coords2  = np.array([x,y]).transpose()
      ######################################################################################

   if fvals is not None:
      fvals2 = smt.smoother(fvals)
      CSopt  = 0
   else:
      import MIZchar as mizc
      # use principal components to set
      # the function values on the boundary
      PCA    = mizc.pca_mapper(xy_coords2)
      fvals2 = PCA.set_func_vals()
      CSopt  = 1

   #print(fvals2)
   #print(xy_coords2)
   t0 = time.clock()
   print('\n**********************************************************************')
   print('Calculating potential...\n')
   fun_sol  = dirichlet_fund_soln(xy_coords2,fvals2)#,bmap=basemap)
   t1       = time.clock()
   print('\nTime to get potential (s): '+str(t1-t0))
   print('**********************************************************************\n')

   print('\n**********************************************************************')
   print('Calculating stream function...\n')
   stream   = dirichlet_stream_func(potential=fun_sol)
   t2       = time.clock()
   print('\nTime to get stream function (s): '+str(t2-t1))
   print('**********************************************************************\n')

   ###########################################################################################
   #add a test function to eliminate contours that don't cross from "0" to "1":
   class contour_selection:

      def __init__(self,func_vals):
      	 self.func_vals = 1*func_vals
         return

      def selector_binary(self,i0,il):
   	 # assume func_vals are a binary function
   	 # keep contours that end on the opposite value
   	 # OR the "unknown" part (between 0,1)
   	 f0 = self.func_vals[i0]
   	 fl = self.func_vals[il]
   	 if f0==1.:
   	    keep  = (fl<1.)
   	 elif f0==0.:
   	    keep  = (fl>0.)
   	 else:
   	    #keep = False
   	    keep  = np.logical_or(fl==0.,fl==1.)
   	 return keep

      def selector_binary_v2(self,i0,il):
         # assume func_vals are a binary function
         # remove contours that end on the same value (or group of values)
         f0 = self.func_vals[i0]
         fl = self.func_vals[il]
         if f0==1.:
            keep  = (fl<1.)
         elif f0==0.:
            keep  = (fl>0.)
         else:
            keep  = ((fl==0.) or (fl==1.))
         return keep

      def selector_opp_sign(self,i0,il):
         # remove contours that end on values with opposite signs
            # - good for sinusoidal type functions
         f0     = self.func_vals[i0]
         fl     = self.func_vals[il]
         keep   = (f0*fl<0) # opposite signs
         return keep
   ###########################################################################################

   CS = contour_selection(fun_sol.func_vals)
   if CSopt==1:
      selector_function   = CS.selector_opp_sign
      fstr	          = '_vOpp'
   else:
      if 1:
         selector_function = CS.selector_binary
         fstr	           = '_v1'
      elif 0:
         selector_function = CS.selector_binary_v2
         fstr  	           = '_v2'
      else:
         selector_function = None
         fstr	           = ''
   
   if fig_outdir is None:
      # do not make a figure
      pobj = None
   else:
      # make a figure
      fig     = plt.figure()
      ax      = fig.add_subplot(111)
      pobj    = [fig,ax]
      outdir  = './outputs/aod/'+str(fig_outdir)
   
      if not os.path.exists(outdir):
         os.mkdir(outdir)
   
      outdir = outdir+'/'+str(name)+'_laplacian'
      if not os.path.exists(outdir):
         os.mkdir(outdir)
   
   print('\n**********************************************************************')
   print('Getting streamlines...\n')
   if 0:
      # euclidean space
      AI = stream.get_contour_lengths(pobj=pobj,show=False,\
         test_function=selector_function,\
         func_vals_orig=1*fun_sol.func_vals)
      if pobj is not None:
         figname  = outdir+'/test_Laplacian_planar'+fstr+'.png'
   else:
      # spherical stuff
      AI = stream.get_contour_lengths(pobj=pobj,bmap=basemap,show=False,\
                                       test_function=selector_function,\
                                       func_vals_orig=1*fun_sol.func_vals)
      if pobj is not None:
      	figname	= outdir+'/test_Laplacian_spherical'+fstr+'.png'
   	
   ttl	= 'Median length (km) '+str(np.round(10.*AI.length_median/1.e3)/10.)
   if pobj is not None:
      fig,ax  = pobj
      ax.title.set_text(ttl)
      ax.set_aspect('equal')

      if 0:
         # show for testing
         fig.show()
      else:
         # make figure
         #print('Saving plot to figure '+figname)
         fig.savefig(figname)
         fig.clf()
   
   t3 = time.clock()
   print('\nTime to get streamlines (mins): '+str((t3-t2)/60.))
   print(ttl)
   print('**********************************************************************\n')
   

   Psoln = MIZ_soln(AI,fun_sol,stream)
   # Psoln = [AI,fun_sol,stream]

   return Psoln