def test_interpolation_ensemble(self): data_dict, x, y, z = self.get_synthetic_data_dict() x = x[0:15] y = y[0:15] z = z[0:15] data_dict['var2d'] = np.ones(data_dict['var2d'].shape) data_dict['var3d'] = np.ones(data_dict['var3d'].shape) data_dict['var2de'] = [data_dict['var2d']*1, data_dict['var2d']*2, data_dict['var2d']*3] data_dict['var3de'] = [data_dict['var3d']*31, data_dict['var3d']*32, data_dict['var3d']*33] b = ReaderBlock(data_dict) interp = b.interpolate(x, y, z)[0] # 1 is profiles v2 = interp['var2d'] v2e = interp['var2de'] v3 = interp['var3d'] v3e = interp['var3de'] self.assertEqual(v2[0], 1) self.assertEqual(v2e[0], 1) self.assertEqual(v2e[1], 2) self.assertEqual(v2e[3], 1) self.assertEqual(v3[0], 1) self.assertEqual(v3e[0], 31) self.assertEqual(v3e[1], 32) self.assertAlmostEqual(v3e[3], 31)
def test_interpolation_3dArrays(self): """Test interpolation.""" reader = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') # 100000 points within 50x50 pixels over sea (corner of domain) num_points = 1000 np.random.seed(0) # To get the same random numbers each time x = np.random.uniform(reader.xmin, reader.xmin+800*50, num_points) y = np.random.uniform(reader.ymax-800*50, reader.ymax, num_points) z = np.random.uniform(-200, 0, num_points) variables = ['x_sea_water_velocity', 'y_sea_water_velocity', 'sea_water_temperature'] # Read a block of data covering the points data = reader.get_variables(variables, time=reader.start_time, x=x, y=y, z=z, block=True) b = ReaderBlock(data, interpolation_horizontal='nearest') env, prof = b.interpolate(x, y, z, variables, profiles=['sea_water_temperature'], profiles_depth=[-30, 0]) self.assertAlmostEqual(env['x_sea_water_velocity'][100], 0.075019, 3) self.assertAlmostEqual(prof['sea_water_temperature'][0,11], 7.549999, 3) self.assertAlmostEqual(prof['sea_water_temperature'][-1,11], 8.389999, 3) self.assertEqual(prof['z'][-1], b.z[-1])
def test_interpolation_missing(self): """Test interpolation.""" reader = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') num_points = 50 np.random.seed(0) # To get the same random numbers each time lons = np.random.uniform(10, 11, num_points) lats = np.random.uniform(66, 67.0, num_points) z = np.random.uniform(-200, 0, num_points) x, y = reader.lonlat2xy(lons, lats) variables = ['x_sea_water_velocity', 'y_sea_water_velocity', 'sea_water_temperature'] # Read a block of data covering the points data = reader.get_variables(variables, time=reader.start_time, x=x, y=y, z=z, block=True) # Introduce missing values data['x_sea_water_velocity'] = np.ma.masked_where( data['x_sea_water_velocity']>.08, data['x_sea_water_velocity']) b = ReaderBlock(data, interpolation_horizontal='linearND') env, prof = b.interpolate(x, y, z, variables, profiles=['x_sea_water_velocity'], profiles_depth=[-30, 0]) self.assertAlmostEqual(env['x_sea_water_velocity'][10], 0.074, 2) self.assertAlmostEqual(prof['x_sea_water_velocity'][5,48], -0.090, 2)
def test_interpolation_missing(self): """Test interpolation.""" reader = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') num_points = 50 np.random.seed(0) # To get the same random numbers each time lons = np.random.uniform(10, 11, num_points) lats = np.random.uniform(66, 67.0, num_points) z = np.random.uniform(-200, 0, num_points) x, y = reader.lonlat2xy(lons, lats) variables = ['x_sea_water_velocity', 'y_sea_water_velocity', 'sea_water_temperature'] # Read a block of data covering the points data = reader.get_variables(variables, time=reader.start_time, x=x, y=y, z=z, block=True) # Introduce missing values data['x_sea_water_velocity'].mask[[data['x_sea_water_velocity']>.08]] = True b = ReaderBlock(data, interpolation_horizontal='linearND') env, prof = b.interpolate(x, y, z, variables, profiles=['x_sea_water_velocity'], profiles_depth=[-30, 0]) self.assertAlmostEqual(env['x_sea_water_velocity'][10], 0.056, 2) self.assertAlmostEqual(prof['x_sea_water_velocity'][5,48], -0.090, 2)
def test_repeated(self): """Check that block can be used for interpolation to several sets of positions""" reader = reader_netCDF_CF_generic.Reader(o.test_data_folder() + '14Jan2016_NorKyst_z_3d/NorKyst-800m_ZDEPTHS_his_00_3Dsubset.nc') # 100 points within 50x50 pixels over sea (corner of domain) num_points = 100 np.random.seed(0) # To get the same random numbers each time x = np.random.uniform(reader.xmin, reader.xmin+800*50, num_points) y = np.random.uniform(reader.ymax-800*50, reader.ymax, num_points) z = np.random.uniform(-200, 0, num_points) variables = ['x_sea_water_velocity', 'y_sea_water_velocity', 'sea_water_temperature'] # Read a block of data covering the points data = reader.get_variables(variables, time=reader.start_time, x=x, y=y, z=z, block=True) b = ReaderBlock(data, interpolation_horizontal='nearest') env, prof = b.interpolate(x, y, z, 'sea_water_temperature') x2 = x[20:30] y2 = y[20:30] z2 = z[20:30] env2, prof2 = b.interpolate(x2, y2, z2, 'sea_water_temperature') env3, prof3 = b.interpolate(x, y, z, 'sea_water_temperature') self.assertEqual(env['sea_water_temperature'][0], env3['sea_water_temperature'][0]) self.assertEqual(env['sea_water_temperature'][20], env2['sea_water_temperature'][0])
def test_zNone(self): d = {} d['x'] = np.arange(5) d['y'] = np.arange(7) d['z'] = 0 d['time'] = None d['var'] = np.random.rand(5, 6) rb = ReaderBlock(d) z = None i, p = rb.interpolate(np.array([1, 2]), np.array([2, 3]), z, 'var') self.assertTrue(i['var'][0] > 0)
def test_zNone(self): d = {} d['x'] = np.arange(5) d['y'] = np.arange(7) d['z'] = 0 d['time'] = None d['var'] = np.random.rand(5,6) rb = ReaderBlock(d) z = None i,p = rb.interpolate(np.array([1, 2]), np.array([2, 3]), z, 'var') self.assertTrue(i['var'][0] > 0)
def test_interpolation_horizontal(self): data_dict, x, y, z = self.get_synthetic_data_dict() # Make block from dictionary, and apply tests b = ReaderBlock(data_dict) self.assertEqual(b.data_dict['var2d'].shape, (len(b.y), len(b.x))) self.assertEqual(b.data_dict['var3d'].shape, (len(b.z), len(b.y), len(b.x))) # Make some element positions interpolator2d = b.Interpolator2DClass(b.x, b.y, x, y) values = interpolator2d(data_dict['var2d']) # Checking output is as expected self.assertEqual(values[10], 1.6487979858538129) self.assertEqual(sum(values.mask), 15)
def test_covers_positions(self): data_dict, x, y, z = self.get_synthetic_data_dict() # Make block from dictionary, and apply tests b = ReaderBlock(data_dict) xn = np.linspace(-70, 470, 100) yn = np.linspace(10, 340, 100) self.assertTrue(b.covers_positions(xn, yn)) xn = np.linspace(500, 600, 100) yn = np.linspace(400, 500, 100) self.assertFalse(b.covers_positions(xn, yn)) xn = np.linspace(400, 500, 100) yn = np.linspace(0, 30, 100) self.assertFalse(b.covers_positions(xn, yn))
def test_linearNDFast(self): """Test interpolation.""" reader = reader_ROMS_native.Reader( o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc' ) reader.buffer = 3 num_points = 50 np.random.seed(0) # To get the same random numbers each time lons = np.random.uniform(14, 15, num_points) lats = np.random.uniform(68, 68.4, num_points) z = np.random.uniform(-20, 0, num_points) x, y = reader.lonlat2xy(lons, lats) #z=None variables = ['x_sea_water_velocity'] # Read a block of data covering the points data = reader.get_variables(variables, time=reader.start_time, x=x, y=y, z=z, block=True) b = ReaderBlock(data.copy(), interpolation_horizontal='linearNDFast') x2 = np.random.uniform(x.min(), x.max(), num_points) y2 = np.random.uniform(y.min(), y.max(), num_points) z2 = np.random.uniform(-20, 0, num_points) self.assertTrue(b.covers_positions(x, y, z)) self.assertTrue(b.covers_positions(x2, y2, z2)) # Check that there are holes in the arrays of the ReaderBlock self.assertEqual( np.sum(~np.isfinite(b.data_dict['x_sea_water_velocity'])), 1001) # Check that LinearNDFast interpolation gives a real value env, prof = b.interpolate(x2, y2, z2, variables, profiles=variables, profiles_depth=[-30, 0]) self.assertEqual(np.sum(~np.isfinite(env['x_sea_water_velocity'])), 0) # Check that the arrays of the ReaderBlock have been filled in self.assertEqual( np.sum(~np.isfinite(b.data_dict['x_sea_water_velocity'])), 0) # Check that nearest interpolation contains some NaN values b2 = ReaderBlock(data.copy(), interpolation_horizontal='nearest') env, prof = b2.interpolate(x2, y2, z2, variables, profiles=variables, profiles_depth=[-30, 0]) self.assertEqual(np.sum(~np.isfinite(env['x_sea_water_velocity'])), 31)
def test_linearNDFast(self): """Test interpolation.""" reader = reader_ROMS_native.Reader(o.test_data_folder() + '2Feb2016_Nordic_sigma_3d/Nordic-4km_SLEVELS_avg_00_subset2Feb2016.nc') reader.buffer=3 num_points = 50 np.random.seed(0) # To get the same random numbers each time lons = np.random.uniform(14, 15, num_points) lats = np.random.uniform(68, 68.4, num_points) z = np.random.uniform(-20, 0, num_points) x, y = reader.lonlat2xy(lons, lats) #z=None variables = ['x_sea_water_velocity'] # Read a block of data covering the points data = reader.get_variables(variables, time=reader.start_time, x=x, y=y, z=z, block=True) b = ReaderBlock(data.copy(), interpolation_horizontal='linearNDFast') x2 = np.random.uniform(x.min(), x.max(), num_points) y2 = np.random.uniform(y.min(), y.max(), num_points) z2 = np.random.uniform(-20, 0, num_points) self.assertTrue(b.covers_positions(x, y, z)) self.assertTrue(b.covers_positions(x2, y2, z2)) # Check that there are holes in the arrays of the ReaderBlock self.assertEqual( np.sum(~np.isfinite(b.data_dict['x_sea_water_velocity'])), 1001) # Check that LinearNDFast interpolation gives a real value env, prof = b.interpolate(x2, y2, z2, variables, profiles=variables, profiles_depth=[-30, 0]) self.assertEqual( np.sum(~np.isfinite(env['x_sea_water_velocity'])), 0) # Check that the arrays of the ReaderBlock have been filled in self.assertEqual( np.sum(~np.isfinite(b.data_dict['x_sea_water_velocity'])), 0) # Check that nearest interpolation contains some NaN values b2 = ReaderBlock(data.copy(), interpolation_horizontal='nearest') env, prof = b2.interpolate(x2, y2, z2, variables, profiles=variables, profiles_depth=[-30, 0]) self.assertEqual( np.sum(~np.isfinite(env['x_sea_water_velocity'])), 31)
def test_flipped(self): x = np.arange(10).astype(np.float32) y = np.arange(20).astype(np.float32) X, Y = np.meshgrid(x, y) d = X * 5 b = ReaderBlock({'x': x, 'y': y, 'v': d, 'time': datetime.now()}) b_flipped = ReaderBlock({ 'x': np.flip(x), 'y': y, 'v': np.flip(d, axis=1), 'time': datetime.now() }) x0 = np.array([0, 7, 7.3, 7.41, 9]) # Some random points y0 = np.array([5, 5, 8, 8.2, 5]) bi = b.Interpolator2DClass(b.x, b.y, x0, y0) bi_flipped = b_flipped.Interpolator2DClass(b_flipped.x, b_flipped.y, x0, y0) np.testing.assert_array_almost_equal(bi(d), bi_flipped(np.flip(d, axis=1))) np.testing.assert_array_almost_equal(bi(d), 5 * x0)
def get_variables_interpolated(self, variables, profiles=None, profiles_depth=None, time=None, lon=None, lat=None, z=None, block=False, rotate_to_proj=None): self.timer_start('total') self.timer_start('preparing') # Raise error if time not not within coverage of reader if not self.covers_time(time): raise ValueError('%s is outside time coverage (%s - %s) of %s' % (time, self.start_time, self.end_time, self.name)) # Check which particles are covered (indep of time) ind_covered = self.covers_positions(lon, lat, z) if len(ind_covered) == 0: raise ValueError(('All %s particles (%.2f-%.2fE, %.2f-%.2fN) ' + 'are outside domain of %s (%s)') % (len(lon), lon.min(), lon.max(), lat.min(), lat.max(), self.name, self.coverage_string())) # Find reader time_before/time_after time_nearest, time_before, time_after, i1, i2, i3 = \ self.nearest_time(time) logging.debug('Reader time:\n\t\t%s (before)\n\t\t%s (after)' % (time_before, time_after)) if time == time_before: time_after = None reader_x, reader_y = self.lonlat2xy(lon[ind_covered], lat[ind_covered]) z = z.copy()[ind_covered] # Send values and not reference # to avoid modifications if block is False or self.return_block is False: # Analytical reader, continous in space and time self.timer_end('preparing') env_before = self._get_variables(variables, profiles, profiles_depth, time, #time_before, reader_x, reader_y, z, block=block) logging.debug('Fetched env-before') self.timer_start('preparing') else: # Swap before- and after-blocks if matching times if str(variables) in self.var_block_before: block_before_time = self.var_block_before[ str(variables)].time if str(variables) in self.var_block_after: block_after_time = self.var_block_after[ str(variables)].time if block_before_time != time_before: if block_after_time == time_before: self.var_block_before[str(variables)] = \ self.var_block_after[str(variables)] if block_after_time != time_after: if block_before_time == time_before: self.var_block_after[str(variables)] = \ self.var_block_before[str(variables)] # Fetch data, if no buffer is available if (not str(variables) in self.var_block_before) or \ (self.var_block_before[str(variables)].time != time_before): self.timer_end('preparing') reader_data_dict = \ self._get_variables(variables, profiles, profiles_depth, time_before, reader_x, reader_y, z, block=block) self.timer_start('preparing') self.var_block_before[str(variables)] = \ ReaderBlock(reader_data_dict, interpolation_horizontal=self.interpolation) try: len_z = len(self.var_block_before[str(variables)].z) except: len_z = 1 logging.debug(('Fetched env-block (size %ix%ix%i) ' + 'for time before (%s)') % (len(self.var_block_before[str(variables)].x), len(self.var_block_before[str(variables)].y), len_z, time_before)) if not str(variables) in self.var_block_after or \ self.var_block_after[str(variables)].time != time_after: if time_after is None: self.var_block_after[str(variables)] = \ self.var_block_before[str(variables)] else: self.timer_end('preparing') reader_data_dict = \ self._get_variables(variables, profiles, profiles_depth, time_after, reader_x, reader_y, z, block=block) self.timer_start('preparing') self.var_block_after[str(variables)] = \ ReaderBlock( reader_data_dict, interpolation_horizontal=self.interpolation) try: len_z = len(self.var_block_after[str(variables)].z) except: len_z = 1 logging.debug(('Fetched env-block (size %ix%ix%i) ' + 'for time after (%s)') % (len(self.var_block_after[ str(variables)].x), len(self.var_block_after[ str(variables)].y), len_z, time_after)) if self.var_block_before[str(variables)].covers_positions( reader_x, reader_y) is False or \ self.var_block_after[str(variables)].covers_positions( reader_x, reader_y) is False: logging.warning('Data block from %s not large enough to ' 'cover element positions within timestep. ' 'Buffer size (%s) must be increased.' % (self.name, str(self.buffer))) self.timer_end('preparing') ############################################################ # Interpolate before/after blocks onto particles in space ############################################################ self.timer_start('interpolation') logging.debug('Interpolating before (%s) in space (%s)' % (self.var_block_before[str(variables)].time, self.interpolation)) env_before, env_profiles_before = self.var_block_before[ str(variables)].interpolate( reader_x, reader_y, z, variables, profiles, profiles_depth) if (time_after is not None) and (time_before != time): logging.debug('Interpolating after (%s) in space (%s)' % (self.var_block_after[str(variables)].time, self.interpolation)) env_after, env_profiles_after = self.var_block_after[ str(variables)].interpolate( reader_x, reader_y, z, variables, profiles, profiles_depth) self.timer_end('interpolation') ####################### # Time interpolation ####################### self.timer_start('interpolation_time') env_profiles = None if (time_after is not None) and (time_before != time): weight_after = ((time - time_before).total_seconds() / (time_after - time_before).total_seconds()) logging.debug(('Interpolating before (%s, weight %.2f) and' '\n\t\t after (%s, weight %.2f) in time') % (self.var_block_before[str(variables)].time, 1 - weight_after, self.var_block_after[str(variables)].time, weight_after)) env = {} for var in variables: # Weighting together, and masking invalid entries env[var] = np.ma.masked_invalid((env_before[var] * (1 - weight_after) + env_after[var] * weight_after)) if var in standard_names.keys(): invalid = np.where((env[var] < standard_names[var]['valid_min']) | (env[var] > standard_names[var]['valid_max']))[0] if len(invalid) > 0: logging.warning('Invalid values found for ' + var) logging.warning(env[var][invalid]) logging.warning('(allowed range: [%s, %s])' % (standard_names[var]['valid_min'], standard_names[var]['valid_max'])) logging.warning('Replacing with NaN') env[var][invalid] = np.nan # Interpolating vertical profiles in time if profiles is not None: env_profiles = {} logging.info('Interpolating profiles in time') # Truncating layers not present both before and after numlayers = np.minimum(len(env_profiles_before['z']), len(env_profiles_after['z'])) env_profiles['z'] = env_profiles_before['z'][0:numlayers+1] for var in env_profiles_before.keys(): if var == 'z': continue env_profiles[var] = ( env_profiles_before[var][0:numlayers, :] * (1 - weight_after) + env_profiles_after[var][0:numlayers, :]*weight_after) else: env_profiles = None else: logging.debug('No time interpolation needed - right on time.') env = env_before if profiles is not None: if 'env_profiles_before' in locals(): env_profiles = env_profiles_before else: # Copying data from environment to vertical profiles env_profiles = {'z': profiles_depth} for var in profiles: env_profiles[var] = np.ma.array([env[var], env[var]]) self.timer_end('interpolation_time') #################### # Rotate vectors #################### if rotate_to_proj is not None: if self.simulation_SRS is True: logging.debug('Reader SRS is the same as calculation SRS - ' 'rotation of vectors is not needed.') else: vector_pairs = [] for var in variables: for vector_pair in vector_pairs_xy: if var in vector_pair: counterpart = list(set(vector_pair) - set([var]))[0] if counterpart in variables: vector_pairs.append(vector_pair) else: sys.exit('Missing component of vector pair:' + counterpart) # Extract unique vector pairs vector_pairs = [list(x) for x in set(tuple(x) for x in vector_pairs)] if len(vector_pairs) > 0: self.timer_start('rotating vectors') for vector_pair in vector_pairs: env[vector_pair[0]], env[vector_pair[1]] = \ self.rotate_vectors(reader_x, reader_y, env[vector_pair[0]], env[vector_pair[1]], self.proj, rotate_to_proj) if profiles is not None and vector_pair[0] in profiles: sys.exit('Rotating profiles of vectors ' 'is not yet implemented') self.timer_end('rotating vectors') # Masking non-covered pixels self.timer_start('masking') if len(ind_covered) != len(lon): logging.debug('Masking %i elements outside coverage' % (len(lon)-len(ind_covered))) for var in variables: tmp = np.nan*np.ones(lon.shape) tmp[ind_covered] = env[var].copy() env[var] = np.ma.masked_invalid(tmp) # Filling also fin missing columns # for env_profiles outside coverage if env_profiles is not None and var in env_profiles.keys(): tmp = np.nan*np.ones((env_profiles[var].shape[0], len(lon))) tmp[:, ind_covered] = env_profiles[var].copy() env_profiles[var] = np.ma.masked_invalid(tmp) self.timer_end('masking') self.timer_end('total') return env, env_profiles
'sea_floor_depth_below_sea_level', 'sea_water_salinity', 'x_sea_water_velocity', 'sea_water_temperature', 'sea_ice_thickness' ] reader_arctic.buffer = 1000 # read all reader_arctic.verticalbuffer = 1000 # read all start_time = datetime.now() for t in reader_arctic.times: v = reader_arctic.get_variables(variables, time=t, x=x, y=y, z=z) time_spent = datetime.now() - start_time print('%6.2f seconds on this machine' % time_spent.total_seconds()) print('--------------------------------------------------------') print('Test 3: Interpolating 3D arrays onto particle positions') print(' 2.5 seconds on reference machine.') start_time = datetime.now() b = ReaderBlock(v, interpolation_horizontal='linearND') num_points = 10000 x = np.random.uniform(reader_arctic.xmin, reader_arctic.xmax, num_points) y = np.random.uniform(reader_arctic.ymin, reader_arctic.ymax, num_points) z = np.random.uniform(-200, 0, num_points) env, prof = b.interpolate(x, y, z, variables, profiles=['sea_water_temperature'], profiles_depth=[-30, 0]) time_spent = datetime.now() - start_time print('%6.1f seconds on this machine' % time_spent.total_seconds()) print('--------------------------------------------------------') print('Test 4: Vertical mixing with 50 elements and 7200 cycles (CPU-heavy)')
z = np.array([-20, -10]) variables = ['sea_surface_elevation', 'sea_ice_area_fraction', 'barotropic_sea_water_x_velocity', 'y_sea_water_velocity', 'sea_floor_depth_below_sea_level', 'sea_water_salinity', 'x_sea_water_velocity', 'barotropic_sea_water_y_velocity', 'sea_water_temperature', 'sea_ice_thickness'] reader_arctic.buffer=1000 # read all reader_arctic.verticalbuffer=1000 # read all start_time = datetime.now() for t in reader_arctic.times: v = reader_arctic.get_variables(variables, time=t, x=x, y=y, z=z, block=True) time_spent = datetime.now() - start_time print '%6.2f seconds on this machine' % time_spent.total_seconds() print '--------------------------------------------------------' print 'Test 3: Interpolating 3D arrays onto particle positions' print ' 2.5 seconds on reference machine.' start_time = datetime.now() b = ReaderBlock(v, interpolation_horizontal='linearND') num_points = 10000 x = np.random.uniform(reader_arctic.xmin, reader_arctic.xmax, num_points) y = np.random.uniform(reader_arctic.ymin, reader_arctic.ymax, num_points) z = np.random.uniform(-200, 0, num_points) env, prof = b.interpolate(x, y, z, variables, profiles=['sea_water_temperature'], profiles_depth=[-30, 0]) time_spent = datetime.now() - start_time print '%6.1f seconds on this machine' % time_spent.total_seconds() print '--------------------------------------------------------' print 'Test 4: Vertical mixing with 50 elements and 7200 cycles (CPU-heavy)' print ' 10.0 seconds on reference machine.' reader_arctic.buffer=10