예제 #1
0
      def do_fill(pcoords,res=None,f=None):

         #############################################################
         if res is None: 
            print('Too few points - adding more')
         else:
            print('Checking boundary points are close enough together')

         xc,yc    = np.array(pcoords).transpose()
         xc2,yc2  = mizc.fill_poly(xc,yc,res=res)
         pc       = np.array([xc2,yc2]).transpose()   # arrays of arrays: coords = rows
         pc       = [tuple(xy) for xy in pc]          # list of tuples
         #############################################################

         #############################################################
         if f is not None:
            fv = []
            i0 = -1
            for i,cc in enumerate(pc):
               if cc in pcoords:
                  # NB this includes 1st and last points
                  i0 = i0+1
                  fv.append(f[i0])
               else:
                  x,y   = cc
                  x0,y0 = pcoords[i0]
                  x1,y1 = pcoords[i0+1]
                  wt    = np.sqrt(pow(x-x0,2)+pow(y-y0,2))/np.sqrt(pow(x1-x0,2)+pow(y1-y0,2))
                  #
                  f0 = f[i0]
                  f1 = f[i0+1]
                  fv.append(f0+wt*(f1-f0))
         #############################################################

         return pc,fv
예제 #2
0
         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
예제 #3
0
   def _get_singularities(self):
      import MIZchar as mizc
      import numpy as np

      print('Getting singularities...\n')

      bufres   = self.buffer_resolution
      eps      = self.resolution/2.
      poly     = self.shapely_polygon.buffer(eps,resolution=bufres)

      # make sure sing's are evenly spaced:
      xs,ys = np.array(poly.exterior.coords).transpose()
      xs,ys = mizc.fill_poly(xs,ys,1.5*eps)
      xys   = np.array([xs,ys]).transpose()
      #
      self.singularities            = [tuple(xyi) for xyi in xys]
      self.number_of_singularities  = len(xys)

      # put singularities (z_n) on the boundary of expanded polygon
      self.singularities   = list(poly.exterior.coords)

      if self.singularities[0]==self.singularities[-1]:
         self.singularities = self.singularities[:-1]

      self.number_of_singularities  = len(self.singularities)
      
      do_check = True
      while do_check:
         # check the number of singularities:
         do_check = self._check_singularities()
      # else:
      #    # accept automatically
      #    do_check = False
      #    print('Warning: not checking singularities')
      #    print('Number of boundary points : '+str(self.number_of_points))
      #    print('Number of singularities	: '+str(self.number_of_singularities)+'\n')
         
      return
예제 #4
0
# python $pydir/analyse_DAILY.py --infile=<<DAILY average .a file>> --outdir=<<path to output dir>> --plotting=<<True/False>>
import os, sys, matplotlib
matplotlib.use('Agg')
import mod_reading as mr
import MIZchar as mc
from getopt import getopt

if 0:
    # plot regions ie Greenland Sea, Labrador Sea,...
    mc.plot_regions_v2()

# ==========================================================================
# options
infile = None
outdir = '.'
plotting = False

opts, args = getopt(sys.argv[1:], "", ["infile=", "outdir=", "plotting="])
for opt, arg in opts:
    if opt == '--infile':
        infile = arg
    if opt == '--outdir':
        outdir = arg
    if opt == '--plotting':
        from distutils.util import strtobool
        plotting = strtobool(arg)
        # if arg not in ['True','False']:
        #    raise ValueError('Use --plotting=True or --plotting=False only')
        #    plotting = (arg=='True')

if infile is None:
예제 #5
0
    def regional_save(self,data,poly_list,area,perimeter,clonlat,basemap,region):

        # Prep the lists for polygon.txt
        head_poly_list = ('Polygon_number','Longitude','Latitude','Func_value')
    
        if data.shape == (1120,760):
            # REGION
            reg_repo = './outputs/MIZ/OSI/'+str(region)
            if not os.path.exists(reg_repo):
                os.mkdir(reg_repo)
        else:
            # REGION
            reg_repo = './outputs/MIZ/MDL/'+str(region)
            if not os.path.exists(reg_repo):
                os.mkdir(reg_repo)

        # POLYGONS
        polydir = reg_repo+'/polygons'
        if not os.path.exists(polydir):
            os.mkdir(polydir)

        filname = str(polydir)+'/'+str(dadate)+'.txt'
        with open(filname,'w+') as f:
            f.write(str(head_poly_list)+'\n')
            for n,en in enumerate(poly_list):
                for l,el in enumerate(en):
                    string = ' '.join(map(str,el))
                    for item in string:
                        f.write(item)
                    f.write('\n')
            f.close()

        # WIDTHS
        widthsdir = reg_repo+'/widths'
        if not os.path.exists(widthsdir):
            os.mkdir(widthsdir)

        reg_width_list = []
        reg_widths = widths.single_file(filname,basemap)
        for w,wd in enumerate(reg_widths):
            if wd is not None:
                reg_width_list.append(wd.int_widths)
        filname = str(widthsdir)+'/'+str(dadate)+'.txt'
        with open(filname,'w+') as f:
            for l,el in enumerate(reg_width_list):
                string = ' '.join(map(str,el))
                for item in string:
                    f.write(item)
                f.write('\n')
            f.close()

        # AVG WIDTH
        uglyway = open(filname,'r+')
        uglierway = uglyway.readlines()
        w_num = 0
        w_den = 0
        for el in uglierway:
            pw = np.array(map(float,el.split()))
            w_num += sum(pw)
            w_den += len(pw)
        avg_width = w_num/float(w_den)

        # MIZ LOCATION
        num_lon = 0
        num_lat = 0
        den = 0
        for n,en in enumerate(clonlat):
            num_lon += en[0]*area[n]
            num_lat += en[1]*area[n]
            den += area[n]
        mean_lon = num_lon/float(den)
        mean_lat = num_lat/float(den)

        # Regional Lists
        # NOTE list is [ice extent, ice area, miz extent, miz area]
        lst = []
    
        # Which mode?
        if np.nanmax(data) <= 1:
            lindata = np.reshape(data,data.size)
            for pt in lindata:
                if pt > .15 and pt < .80:
                    lst.append([1,1])
                elif pt >= .80:
                    lst.append([1,0])
        else:
            lindata = np.reshape(data,data.size)
            for pt in lindata:
                if pt > .1 and pt < 300:
                    lst.append([1,1])
                elif pt == 300:
                    lst.append([1,0])

        stats = map(sum,zip(*lst))
    
        filname = reg_repo+'/stats.txt'
        with open(filname,'a') as f:
            row1 = [dadate,stats[0],stats[1],avg_width,mean_lon,mean_lat]
            str1 = ' '.join(map(str,row1))
            f.write(str1+'\n')
            f.close()
        return()
예제 #6
0
def average_area_model(cdate, vertices, fcdir0, outdir='.'):
    # average MIZ area for a given date
    # use binary files since more likely to be there
    # returns None if nothing there

    fcdir = fcdir0 + '/' + cdate + '/'
    if not os.path.exists(fcdir):
        return
    lst = os.listdir(fcdir)
    if cdate in lst:
        # check if need to add another cdate
        fcdir += cdate + '/'

    lst = os.listdir(fcdir)
    if 'bin' in lst:
        bindir = fcdir + 'bin'
    else:
        bindir = fcdir + 'binaries'

    # make file_list object from binary files
    # - treat in same way as multi-record netcdf
    fli = mr.file_list(bindir, 'archv_wav', '.a')
    if fli.number_of_time_records == 0:
        return

    # loop over 6-h intervals:
    daily_areas = []
    for hr in range(0, 24, 6):
        dto = datetime.datetime(int(cdate[:4]), int(cdate[4:6]),
                                int(cdate[6:8]), hr)

        #print(dto)
        if dto in fli.datetimes:
            idx = fli.datetimes.index(dto)
            out = fli.MIZmap(no_width=True,
                             vertices=vertices,
                             time_index=idx,
                             outdir=outdir)
            # out   = fli.MIZmap(vertices=vertices,time_index=idx,outdir=outdir)
            # sys.exit()
            #
            tfil = out[out.keys()[0]]
            pil = mc.single_file(tfil)

            tot_area = 0
            for pio in pil.poly_info_objects:
                #pio.area		# approximate area (Euclidean after projection using NP as center)
                #pio.ll_coords #list of coords of boundaries
                lon, lat = np.array(pio.ll_coords).transpose()
                area = GS.area_polygon_ellipsoid(lon, lat)
                # print(area)
                tot_area += area

            print('\nTot area: ' + str(tot_area) + '\n')
            daily_areas.append(tot_area)

    if len(daily_areas) == 0:
        return
    else:
        # take daily average
        TotArea = np.mean(daily_areas)
        print('\nAvg tot area: ' + str(TotArea) + '\n')
        return TotArea
예제 #7
0
        print day

        # model area
        model_area = average_area_model(day.strftime("%Y%m%d"),
                                        vertices,
                                        FCdir,
                                        outdir=outdir_m)
        if model_area is None:
            print('skipping date ' + day.strftime("%Y%m%d") +
                  ' no model output')
            # sys.exit()
            continue

        # ========================================================================================================
        # chart area
        pil = mc.single_file(chartdir + '/' + day.strftime("%Y%m%d") +
                             '1200_Greenland_WA_MIZpolys.txt')
        #po=pil.plot_all(show=False,latlon=True)
        #plt.savefig('testfig.png')

        #po.fig.show()

        pil_reduced = pil.reduce_area(vertices)
        #- closing polygon
        #po0=pil_reduced.plot_all(show=False,latlon=True)
        #po0.fig.show()
        #po0=pil_reduced.plot_all(show=False,latlon=True,check_flags=True)

        lon, lat = np.array(vertices).transpose()
        print('rectangle area\t' + str(GS.area_polygon_ellipsoid(lon, lat)))

        chart_area = 0
예제 #8
0
import MIZchar as mc
import fns_plotting as FP

if 0:
    bmap = FP.start_HYCOM_map('gre')
else:
    lon0 = -10.
    lat0 = 77.
    lon1 = 2.
    lat1 = 83.
    bbox = [lon0, lat0, lon1, lat1]
    bmap = FP.start_map(bbox)

ddir = '/home/nersc/lucia/MIZvalid'
tfil = ddir + '/TP4archv_wav.2015_351_180000_dmax.txt'
tfo = mc.single_file(tfil)

METH = 5
Psolns = tfo.get_solutions(METH=METH)
Psolns.plot_solutions(bmap)
예제 #9
0
   def _check_singularities(self):
      # don't want too many singularities
      import numpy as np
      import geometry_planar	as GP
      
      N0 = self.number_of_points
      N1 = self.number_of_singularities
      
      # set limits for N1
      Nthresh  = 100
      frac     = 1.3
      # frac   = .2
      
      # if self.solve_exactly:
      #		# number of singularities and number of boundary points should be the same
      #		# - this doesn't work too well - need more sing's
      #		Ntarget	= N0
      if N0 <= Nthresh:
         # if N0<=Nthresh, try to get N1~N0
         Ntarget  = N0+30
      else:
         # try to get N1~frac*N0, if frac*N0<Nthresh
         Ntarget	= int(np.max([np.round(frac*N0),Nthresh]))
      
      print('\nChecking singularities...\n')
      print('Number of boundary points	     : '+str(N0))
      print('Number of singularities         : '+str(N1))
      print('Desired number of singularities : '+str(Ntarget))
      
      check_again = False
      # NB this applies to the case where N1==Ntarget
      # NB also if N1>=Ntarget, we can reduce N1 to Ntarget exactly in 1 go
      
      if N1>Ntarget:
      
         ##########################################################################
         # reduce the number of sing's by increasing spacing between points
         coords	= self.singularities
         perimeter,resolution,\
               spacings,tangent_dirn   = GP.curve_info(coords)
         #
         s_target    = N1/float(Ntarget)*resolution # increase mean spacing between points
         new_coords  = [coords[0]]
         #
         ss = 0
         s0 = 0
         s1 = s0+s_target
         for n,c0 in enumerate(coords[1:]):
            ss = ss+spacings[n]
            if ss>=s1:
               new_coords.append(c0)
               s0 = s1
               s1 = s0+s_target
         
         #######################################################################
         # update list of singularities:
         N2                            = len(new_coords)
         self.singularities            = new_coords
         self.number_of_singularities  = N2
         #######################################################################
         
         if N2>Ntarget:

            #######################################################################
            # delete a few points randomly from new_coords to get right number
            Ndel  = N2-Ntarget
            while Ndel>0:
               idel	= np.random.randint(N2)
               new_coords.remove(new_coords[idel])
               N2       = len(new_coords)
               Ndel     = N2-Ntarget
            
            # update list of singularities
            self.singularities            = new_coords
            self.number_of_singularities  = N2
            #######################################################################
         
         ##########################################################################
         elif N2<Ntarget:

            #######################################################################
            # get some more points from self.singularities
            # *this adds more at start preferentially
            # but shouldn't matter since it won't be too many
            Nadd	= Ntarget-N2
            iadd	= 0
            
            for coord in self.singularities:
               if coord in new_coords:
               	  # in there so now need to insert before next element of new_coords
               	  iadd	= iadd+1
               else:
               	  # adds coord before new_coords[iadd]
               	  new_coords  = list(new_coords)
               	  new_coords.insert(iadd,coord)
               	  N2    = len(new_coords)
               	  Nadd  = Ntarget-N2

               	  # new element so still need to increase point at which to place 
               	  iadd	= iadd+1

               if Nadd==0:
                  break

            # update list of singularities
            self.singularities            = new_coords
            self.number_of_singularities  = N2
            #######################################################################

         ##########################################################################
         print('New number of singularities		: '+str(Ntarget)+'\n')
         ##########################################################################

      elif N1<Ntarget:

         ##########################################################################
         # set up for another iteration
         if 0:
            # increase buffer_resolution
            # - not so good since this only adds more points round corners
            fac                     = int(np.ceil(1.2*Ntarget/float(N1)))
            self.buffer_resolution  = fac*self.buffer_resolution
         else:
            import MIZchar as mizc
            xs,ys = np.array(self.singularities).transpose()

            # double the number of sings
            # TODO this may not be the best way
            # - perhaps specify resolution
            xs,ys = mizc.fill_poly(xs,ys)
            xys   = np.array([xs,ys]).transpose()
            #
            self.singularities            = [tuple(xyi) for xyi in xys]
            self.number_of_singularities  = len(xys)
         ##########################################################################

         # need to call _get_singularities again,
         # to reset the singularities and check them
         check_again = True
         print('Trying again to get singularities (too few)...\n')
         ##########################################################################

      return check_again
예제 #10
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
예제 #11
0
    # day   = 28
    day0 = day
    day1 = day

    show = True
    # show  = False

for iday in range(day0, day1 + 1):
    cday = '%2.2d' % (iday)
    cdate = fmon + cday
    fname = indir + '/' + cdate + '_polys.txt'
    if os.path.exists(fname):
        print('\n' + 60 * '--' + '\nReading ' + fname + '\n')
        fig = plt.figure()
        ax1 = fig.add_subplot(1, 1, 1)
        Psolns   = mizc.single_file(fname,bmap,pobj=[fig,ax1],\
                                      cdate=cdate,METH=METH)

        ############################################################
        for pp in Psolns:
            pp.plot_representative_lines(bmap,
                                         ax=ax1,
                                         color='r',
                                         linewidth=1.5)
            Wav = pp.record['Width_mean'] / 1.e3  # mean width in km

            # add text with mean width
            xmin, xmax, ymin, ymax = pp.bbox(bmap)
            xav = (xmin + xmax) / 2.
            ax1.text(xmax,ymin,'%4.1f km' %(Wav),\
               color='r',fontsize=16,horizontalalignment='right',\
               verticalalignment='top')
    # create a binary corresponding to the level
    B = np.zeros(V.shape)
    good = np.logical_not(V.values.mask)
    data = V.values.data[good]
    Bgood = np.zeros(len(data))
    Bgood[data >= Vlev] = 1.
    B[good] = Bgood
    #print(len(Bgood[Bgood>.5]))
    #print(data)

    # find the contours
    vcont = sorted(msr.find_contours(B, .5), key=len)
    Vcont = []
    for cont in vcont:
        ij_in_rows = np.array(cont)
        x, y = MC.ij2xy(ij_in_rows, X, Y).transpose()
        if len(x) < 10:
            continue
        elif len(x) < 20:
            lon, lat = map(x, y, inverse=True)
        else:
            # reduce points according to STEP
            lon, lat = map(x[::STEP], y[::STEP], inverse=True)

        length = len(lon)
        Vcont.append({
            'lon': lon,
            'lat': lat,
            'contour_value': Vlev,
            'length': length
        })