def __init__(self, lon=2, lat=66, proj4='+proj=stere +lat_0=90 +lon_0=70 +lat_ts=60 ' + '+units=m +a=6.371e+06 +e=0 +no_defs'): self.fileName = 'ArtificialOceanEddy' self.name = 'ArtificialOceanEddy' self.proj4 = proj4 self.proj = pyproj.Proj(proj4) # Calculate x,y of center of eddy from given lon and lat x0, y0 = self.proj(lon, lat) width = 600000 # 600 km box self.pixelsize = 10000 # Artificial 10 km pixel size self.delta_x = self.pixelsize self.delta_y = self.pixelsize self.x0 = x0 self.y0 = y0 self.xmin = x0 - width self.xmax = x0 + width self.ymin = y0 - width self.ymax = y0 + width self.start_time = None self.end_time = None self.time_step = None self.variables = ['x_sea_water_velocity', 'y_sea_water_velocity'] # Run constructor of parent Reader class super(Reader, self).__init__()
def __init__(self, initial_time=datetime(2000, 1, 1, 0, 0), epsilon=0.1, omega=0.628, A=0.25, proj4='+proj=stere +lat_0=0 +lon_0=0 +lat_ts=0 ' + '+units=m +a=6.371e+06 +e=0 +no_defs'): self.fileName = 'double_gyre' self.name = 'double_gyre' self.proj4 = proj4 self.proj = pyproj.Proj(proj4) self.return_block = False self.xmin = 0. self.xmax = 2. self.ymin = 0. self.ymax = 1. self.A = A self.epsilon = epsilon self.omega = omega self.initial_time = initial_time self.start_time = None self.end_time = None self.time_step = None self.variables = ['x_sea_water_velocity', 'y_sea_water_velocity'] # Run constructor of parent Reader class super(Reader, self).__init__()
def update_surface_oilfilm_thickness(self): '''The mass of oil is summed within a grid of 20x20 cells covering the oil at a given time. Each oil particle within each cell is given a film thickness as the amount of oil divided by the cell area. ''' from scipy.stats import binned_statistic_2d surface = np.where(self.elements.z == 0)[0] if len(surface) == 0: print('No oil at surface, no film thickness to update') return print('Updating oil film thickness for %s of %s elements at surface' % (len(surface), self.num_elements_active())) meanlon = self.elements.lon[surface].mean() meanlat = self.elements.lat[surface].mean() # Using stereographic coordinates to get regular X and Y psproj = pyproj.Proj('+proj=stere +lat_0=%s +lat_ts=%s +lon_0=%s' % (meanlat, meanlat, meanlon)) X, Y = psproj(self.elements.lon[surface], self.elements.lat[surface]) mass_bin, x_edge, y_edge, binnumber = binned_statistic_2d( X, Y, self.elements.mass_oil[surface], expand_binnumbers=True, statistic='sum', bins=100) bin_area = (x_edge[1] - x_edge[0]) * (y_edge[1] - y_edge[0]) oil_density = 1000 # ok approximation here film_thickness = (mass_bin / oil_density) / bin_area # Postulating min and max film thickness max_thickness = 0.01 # 1 cm min_thickness = 1e-9 # 1 nanometer if film_thickness.max() > max_thickness: print('Warning: decreasing thickness to %sm for %s of %s bins' % (max_thickness, np.sum(film_thickness > max_thickness), film_thickness.size)) film_thickness[film_thickness > max_thickness] = max_thickness num_too_thin = np.sum((film_thickness < min_thickness) & (film_thickness > 0)) if num_too_thin > 0: print('Warning: increasing thickness to %sm for %s of %s bins' % (min_thickness, num_too_thin, film_thickness.size)) film_thickness[film_thickness < min_thickness] = min_thickness # https://github.com/scipy/scipy/issues/7010 binnumber = binnumber - 1 bx = binnumber[0, :] by = binnumber[1, :] # Update thickness self.elements.oil_film_thickness[ surface] = self.elements.oil_film_thickness[surface] * np.nan self.elements.oil_film_thickness[surface] = \ film_thickness[bx, by]
def seed_from_gml(self, gmlfile, num_elements=1000, *args, **kwargs): """Read oil slick contours from GML file, and seed particles within.""" # Specific imports import datetime from matplotlib.path import Path from xml.etree import ElementTree from matplotlib.patches import Polygon from mpl_toolkits.basemap import pyproj namespaces = { 'od': 'http://cweb.ksat.no/cweb/schema/geoweb/oil', 'gml': 'http://www.opengis.net/gml' } slicks = [] with open(gmlfile, 'rt') as e: tree = ElementTree.parse(e) pos1 = 'od:oilDetectionMember/od:oilDetection/od:oilSpill/gml:Polygon' pos2 = 'gml:exterior/gml:LinearRing/gml:posList' # This retrieves some other types of patches, found in some files only # Should be combines with the above, to get all patches #pos1 = 'od:oilDetectionMember/od:oilDetection/od:oilSpill/ # gml:Surface/gml:polygonPatches' #pos2 = 'gml:PolygonPatch/gml:exterior/gml:LinearRing/gml:posList' # Find detection time time_pos = 'od:oilDetectionMember/od:oilDetection/od:detectionTime' oil_time = datetime.datetime.strptime( tree.find(time_pos, namespaces).text, '%Y-%m-%dT%H:%M:%S.%fZ') for patch in tree.findall(pos1, namespaces): pos = patch.find(pos2, namespaces).text c = np.array(pos.split()).astype(np.float) lon = c[0::2] lat = c[1::2] slicks.append(Polygon(list(zip(lon, lat)))) # Find boundary and area of all patches lons = np.array([]) lats = lons.copy() for slick in slicks: ext = slick.get_extents() lons = np.append(lons, [ext.xmin, ext.xmax]) lats = np.append(lats, [ext.ymin, ext.ymax]) # Make a stereographic projection centred on the polygon lonmin = lons.min() lonmax = lons.max() latmin = lats.min() latmax = lats.max() # Place n points within the polygons proj = pyproj.Proj( '+proj=aea +lat_1=%f +lat_2=%f +lat_0=%f +lon_0=%f' % (latmin, latmax, (latmin + latmax) / 2, (lonmin + lonmax) / 2)) slickarea = np.array([]) for slick in slicks: lonlat = slick.get_xy() lon = lonlat[:, 0] lat = lonlat[:, 1] x, y = proj(lon, lat) area_of_polygon = 0.0 for i in range(-1, len(x) - 1): area_of_polygon += x[i] * (y[i + 1] - y[i - 1]) area_of_polygon = abs(area_of_polygon) / 2.0 slickarea = np.append(slickarea, area_of_polygon) # in m2 # Make points deltax = np.sqrt(np.sum(slickarea) / num_elements) lonpoints = np.array([]) latpoints = np.array([]) for i, slick in enumerate(slicks): lonlat = slick.get_xy() lon = lonlat[:, 0] lat = lonlat[:, 1] x, y = proj(lon, lat) xvec = np.arange(x.min(), x.max(), deltax) yvec = np.arange(y.min(), y.max(), deltax) x, y = np.meshgrid(xvec, yvec) lon, lat = proj(x, y, inverse=True) lon = lon.ravel() lat = lat.ravel() points = np.c_[lon, lat] ind = Path(slick.xy).contains_points(points) lonpoints = np.append(lonpoints, lon[ind]) latpoints = np.append(latpoints, lat[ind]) # Finally seed at found positions kwargs['lon'] = lonpoints kwargs['lat'] = latpoints self.seed_elements(time=oil_time, **kwargs)