def test_save_load(self): for fs_loader in self.filesystem_loaders: with fs_loader() as temp_fs: self.eopatch.save('/', filesystem=temp_fs) eopatch2 = EOPatch.load('/', filesystem=temp_fs) self.assertEqual(self.eopatch, eopatch2) eopatch2.save('/', filesystem=temp_fs, overwrite_permission=1) eopatch2 = EOPatch.load('/', filesystem=temp_fs) self.assertEqual(self.eopatch, eopatch2) eopatch2.save('/', filesystem=temp_fs, overwrite_permission=1) eopatch2 = EOPatch.load('/', filesystem=temp_fs, lazy_loading=False) self.assertEqual(self.eopatch, eopatch2) features = { FeatureType.DATA_TIMELESS: {'mask'}, FeatureType.TIMESTAMP:... } eopatch2.save('/', filesystem=temp_fs, features=features, compress_level=3, overwrite_permission=1) eopatch2 = EOPatch.load('/', filesystem=temp_fs, lazy_loading=True) self.assertEqual(self.eopatch, eopatch2) eopatch3 = EOPatch.load('/', filesystem=temp_fs, lazy_loading=True, features=features) self.assertNotEqual(self.eopatch, eopatch3)
def setUpClass(cls): cls.patch = EOPatch.load(cls.TEST_PATCH_FILENAME) cls._prepare_patch(cls.patch) HaralickTask((FeatureType.DATA, 'ndvi', 'haralick_contrast'), texture_feature='contrast', distance=1, angle=0, levels=255, window_size=3, stride=1).execute(cls.patch) HaralickTask( (FeatureType.DATA, 'ndvi', 'haralick_sum_of_square_variance'), texture_feature='sum_of_square_variance', distance=1, angle=np.pi / 2, levels=8, window_size=5, stride=1).execute(cls.patch) HaralickTask((FeatureType.DATA, 'ndvi', 'haralick_sum_entropy'), texture_feature='sum_entropy', distance=1, angle=-np.pi / 2, levels=8, window_size=7, stride=1).execute(cls.patch) cls.initial_patch = EOPatch.load(cls.TEST_PATCH_FILENAME) cls._prepare_patch(cls.initial_patch)
def test_object_sampling_task(small_image, seed, amount): t, h, w, d = 10, *small_image.shape, 5 eop = EOPatch() eop.data["bands"] = np.arange(t * h * w * d).reshape(t, h, w, d) eop.mask_timeless["raster"] = small_image.reshape(small_image.shape + (1,)) task = BlockSamplingTask( [(FeatureType.DATA, "bands", "SAMPLED_DATA"), (FeatureType.MASK_TIMELESS, "raster", "SAMPLED_LABELS")], amount=amount, mask_of_samples=(FeatureType.MASK_TIMELESS, "sampling_mask"), ) task.execute(eop, seed=seed) expected_amount = amount if isinstance(amount, int) else round(np.prod(small_image.shape) * amount) # assert features, labels and sampled rows and cols are added to eopatch assert "SAMPLED_LABELS" in eop.mask_timeless, "Labels not added to eopatch" assert "SAMPLED_DATA" in eop.data, "Features not added to eopatch" assert "sampling_mask" in eop.mask_timeless, "Mask of sampling not generated" # check validity of sampling assert eop.data["SAMPLED_DATA"].shape == (t, expected_amount, 1, d), "Incorrect features size" assert eop.mask_timeless["SAMPLED_LABELS"].shape == (expected_amount, 1, 1), "Incorrect number of samples" assert eop.mask_timeless["sampling_mask"].shape == (h, w, 1), "Sampling mask of incorrect size" sampled_uniques, sampled_counts = np.unique(eop.data["SAMPLED_DATA"], return_counts=True) masked = eop.mask_timeless["sampling_mask"].squeeze(axis=2) == 1 masked_uniques, masked_counts = np.unique(eop.data["bands"][:, masked, :], return_counts=True) assert_array_equal(sampled_uniques, masked_uniques, err_msg="Sampling mask not correctly describing sampled points") assert_array_equal(sampled_counts, masked_counts, err_msg="Sampling mask not correctly describing sampled points")
def test_workflow_copying_eopatches(): feature1 = FeatureType.DATA, "data1" feature2 = FeatureType.DATA, "data2" create_node = EONode(CreateEOPatchTask()) init_node = EONode( InitializeFeatureTask([feature1, feature2], shape=(2, 4, 4, 3), init_value=1), inputs=[create_node], ) remove_node1 = EONode(RemoveFeatureTask([feature1]), inputs=[init_node]) remove_node2 = EONode(RemoveFeatureTask([feature2]), inputs=[init_node]) output_node1 = EONode(OutputTask(name="out1"), inputs=[remove_node1]) output_node2 = EONode(OutputTask(name="out2"), inputs=[remove_node2]) workflow = EOWorkflow([ create_node, init_node, remove_node1, remove_node2, output_node1, output_node2 ]) results = workflow.execute() eop1 = results.outputs["out1"] eop2 = results.outputs["out2"] assert eop1 == EOPatch( data={"data2": np.ones((2, 4, 4, 3), dtype=np.uint8)}) assert eop2 == EOPatch( data={"data1": np.ones((2, 4, 4, 3), dtype=np.uint8)})
def test_nonexistent_location(self): path = './folder/subfolder/new-eopatch/' empty_eop = EOPatch() for fs_loader in self.filesystem_loaders: with fs_loader() as temp_fs: with self.assertRaises(ResourceNotFound): EOPatch.load(path, filesystem=temp_fs) empty_eop.save(path, filesystem=temp_fs) with TempFS() as temp_fs: full_path = os.path.join(temp_fs.root_path, path) with self.assertRaises(CreateFailed): EOPatch.load(full_path) load_task = LoadTask(full_path) with self.assertRaises(CreateFailed): load_task.execute() empty_eop.save(full_path) self.assertTrue(os.path.exists(full_path)) with TempFS() as temp_fs: full_path = os.path.join(temp_fs.root_path, path) save_task = SaveTask(full_path) save_task.execute(empty_eop) self.assertTrue(os.path.exists(full_path))
def test_copy_lazy_loaded_patch(test_eopatch_path, features): original_eopatch = EOPatch.load(test_eopatch_path, lazy_loading=True) copied_eopatch = original_eopatch.copy(features=features) value1 = original_eopatch.mask.__getitem__("CLM", load=False) assert isinstance(value1, FeatureIO) value2 = copied_eopatch.mask.__getitem__("CLM", load=False) assert isinstance(value2, FeatureIO) assert value1 is value2 mask1 = original_eopatch.mask["CLM"] assert copied_eopatch.mask.__getitem__("CLM", load=False).loaded_value is not None mask2 = copied_eopatch.mask["CLM"] assert isinstance(mask1, np.ndarray) assert mask1 is mask2 original_eopatch = EOPatch.load(test_eopatch_path, lazy_loading=True) copied_eopatch = original_eopatch.copy(features=features, deep=True) value1 = original_eopatch.mask.__getitem__("CLM", load=False) assert isinstance(value1, FeatureIO) value2 = copied_eopatch.mask.__getitem__("CLM", load=False) assert isinstance(value2, FeatureIO) assert value1 is not value2 mask1 = original_eopatch.mask["CLM"] assert copied_eopatch.mask.__getitem__("CLM", load=False).loaded_value is None mask2 = copied_eopatch.mask["CLM"] assert np.array_equal(mask1, mask2) and mask1 is not mask2
def test_vector_feature_types(): eop = EOPatch() invalid_entries = [{}, [], 0, None] for feature_type in FeatureTypeSet.VECTOR_TYPES: for entry in invalid_entries: with pytest.raises(ValueError): # Invalid entry for feature_type should raise an error eop[feature_type]["TEST"] = entry crs_test = CRS.WGS84.pyproj_crs() geo_test = GeoSeries([BBox((1, 2, 3, 4), crs=CRS.WGS84).geometry], crs=crs_test) eop.vector_timeless["TEST"] = geo_test assert isinstance( eop.vector_timeless["TEST"], GeoDataFrame), "GeoSeries should be parsed into GeoDataFrame" assert hasattr(eop.vector_timeless["TEST"], "geometry"), "Feature should have geometry attribute" assert eop.vector_timeless[ "TEST"].crs == crs_test, "GeoDataFrame should still contain the crs" with pytest.raises(ValueError): # Should fail because there is no TIMESTAMP column eop.vector["TEST"] = geo_test
def test_repr(test_eopatch_path): test_eopatch = EOPatch.load(test_eopatch_path) repr_str = repr(test_eopatch) assert repr_str.startswith("EOPatch(") and repr_str.endswith(")") assert len(repr_str) > 100 assert repr(EOPatch()) == "EOPatch()"
def test_point_sampling_task(self): # test PointSamplingTask t, h, w, d = 10, 100, 100, 5 eop = EOPatch() eop.data['bands'] = np.arange(t * h * w * d).reshape(t, h, w, d) eop.mask_timeless['raster'] = self.raster.reshape(self.raster_size + (1, )) task = PointSamplingTask(n_samples=self.n_samples, ref_mask_feature='raster', ref_labels=[0, 1], sample_features=[(FeatureType.DATA, 'bands', 'SAMPLED_DATA'), (FeatureType.MASK_TIMELESS, 'raster', 'SAMPLED_LABELS') ], even_sampling=True) task.execute(eop) # assert features, labels and sampled rows and cols are added to eopatch self.assertIn('SAMPLED_LABELS', eop.mask_timeless, msg="labels not added to eopatch") self.assertIn('SAMPLED_DATA', eop.data, msg="features not added to eopatch") # check validity of sampling self.assertTupleEqual(eop.data['SAMPLED_DATA'].shape, (t, self.n_samples, 1, d), msg="incorrect features size") self.assertTupleEqual(eop.mask_timeless['SAMPLED_LABELS'].shape, (self.n_samples, 1, 1), msg="incorrect number of samples")
def test_train_split_per_value(): """Test if class ids get assigned to the same subclasses in multiple eopatches""" shape = (1000, 1000, 3) input1 = np.random.randint(10, size=shape, dtype=int) input2 = np.random.randint(10, size=shape, dtype=int) patch1 = EOPatch() patch1[INPUT_FEATURE] = input1 patch2 = EOPatch() patch2[INPUT_FEATURE] = input2 bins = [0.2, 0.6] split_task = TrainTestSplitTask(INPUT_FEATURE, OUTPUT_FEATURE, bins, split_type="per_value") # seeds should get ignored when splitting 'per_value' patch1 = split_task(patch1, seed=1) patch2 = split_task(patch2, seed=1) otuput1 = patch1[OUTPUT_FEATURE] otuput2 = patch2[OUTPUT_FEATURE] unique = set(np.unique(input1)) | set(np.unique(input2)) for uniq in unique: folds1 = otuput1[input1 == uniq] folds2 = otuput2[input2 == uniq] assert_array_equal(np.unique(folds1), np.unique(folds2))
def test_temporal_indices(self): """ Test case for computation of argmax/argmin of NDVI and another band Cases with and without data masking are tested """ # EOPatch eopatch = EOPatch() t, h, w, c = 5, 3, 3, 2 # NDVI ndvi_shape = (t, h, w, 1) # VAlid data mask valid_data = np.ones(ndvi_shape, np.bool) valid_data[0] = 0 valid_data[-1] = 0 # Fill in eopatch eopatch.add_feature(FeatureType.DATA, 'NDVI', np.arange(np.prod(ndvi_shape)).reshape(ndvi_shape)) eopatch.add_feature(FeatureType.MASK, 'IS_DATA', np.ones(ndvi_shape, dtype=np.int16)) eopatch.add_feature(FeatureType.MASK, 'VALID_DATA', valid_data) # Task add_ndvi = AddMaxMinTemporalIndicesTask(mask_data=False) # Run task new_eopatch = add_ndvi(eopatch) # Asserts self.assertTrue( np.array_equal(new_eopatch.data_timeless['ARGMIN_NDVI'], np.zeros((h, w, 1)))) self.assertTrue( np.array_equal(new_eopatch.data_timeless['ARGMAX_NDVI'], (t - 1) * np.ones((h, w, 1)))) del add_ndvi, new_eopatch # Repeat with valid dat amask add_ndvi = AddMaxMinTemporalIndicesTask(mask_data=True) new_eopatch = add_ndvi(eopatch) # Asserts self.assertTrue( np.array_equal(new_eopatch.data_timeless['ARGMIN_NDVI'], np.ones((h, w, 1)))) self.assertTrue( np.array_equal(new_eopatch.data_timeless['ARGMAX_NDVI'], (t - 2) * np.ones((h, w, 1)))) del add_ndvi, new_eopatch, valid_data # BANDS bands_shape = (t, h, w, c) eopatch.add_feature( FeatureType.DATA, 'BANDS', np.arange(np.prod(bands_shape)).reshape(bands_shape)) add_bands = AddMaxMinTemporalIndicesTask(data_feature='BANDS', data_index=1, amax_data_feature='ARGMAX_B1', amin_data_feature='ARGMIN_B1', mask_data=False) new_eopatch = add_bands(eopatch) self.assertTrue( np.array_equal(new_eopatch.data_timeless['ARGMIN_B1'], np.zeros((h, w, 1)))) self.assertTrue( np.array_equal(new_eopatch.data_timeless['ARGMAX_B1'], (t - 1) * np.ones((h, w, 1))))
def test_nonexistent_location(fs_loader): path = "./folder/subfolder/new-eopatch/" empty_eop = EOPatch() with fs_loader() as temp_fs: with pytest.raises(ResourceNotFound): EOPatch.load(path, filesystem=temp_fs) empty_eop.save(path, filesystem=temp_fs) with TempFS() as temp_fs: full_path = os.path.join(temp_fs.root_path, path) with pytest.raises(CreateFailed): EOPatch.load(full_path) load_task = LoadTask(full_path) with pytest.raises(CreateFailed): load_task.execute() empty_eop.save(full_path) assert os.path.exists(full_path) with TempFS() as temp_fs: full_path = os.path.join(temp_fs.root_path, path) save_task = SaveTask(full_path) save_task.execute(empty_eop) assert os.path.exists(full_path)
def test_save_load(eopatch, fs_loader): with fs_loader() as temp_fs: eopatch.save("/", filesystem=temp_fs) eopatch2 = EOPatch.load("/", filesystem=temp_fs) assert eopatch == eopatch2 eopatch2.save("/", filesystem=temp_fs, overwrite_permission=1) eopatch2 = EOPatch.load("/", filesystem=temp_fs) assert eopatch == eopatch2 eopatch2.save("/", filesystem=temp_fs, overwrite_permission=1) eopatch2 = EOPatch.load("/", filesystem=temp_fs, lazy_loading=False) assert eopatch == eopatch2 features = { FeatureType.DATA_TIMELESS: ["mask"], FeatureType.TIMESTAMP:... } eopatch2.save("/", filesystem=temp_fs, features=features, compress_level=3, overwrite_permission=1) eopatch2 = EOPatch.load("/", filesystem=temp_fs, lazy_loading=True) assert eopatch == eopatch2 eopatch3 = EOPatch.load("/", filesystem=temp_fs, lazy_loading=True, features=features) assert eopatch != eopatch3
def test_vector_feature_types(self): eop = EOPatch() invalid_entries = [{}, [], 0, None] for feature_type in FeatureTypeSet.VECTOR_TYPES: for entry in invalid_entries: with self.assertRaises( ValueError, msg='Invalid entry {} for {} should raise an error'. format(entry, feature_type)): eop[feature_type]['TEST'] = entry crs_test = {'init': 'epsg:4326'} geo_test = GeoSeries( [BBox((1, 2, 3, 4), crs=CRS.WGS84).get_geometry()], crs=crs_test) eop.vector_timeless['TEST'] = geo_test self.assertTrue(isinstance(eop.vector_timeless['TEST'], GeoDataFrame), 'GeoSeries should be parsed into GeoDataFrame') self.assertTrue(hasattr(eop.vector_timeless['TEST'], 'geometry'), 'Feature should have geometry attribute') self.assertEqual(eop.vector_timeless['TEST'].crs, crs_test, 'GeoDataFrame should still contain the crs') with self.assertRaises( ValueError, msg='Should fail because there is no TIMESTAMP column'): eop.vector['TEST'] = geo_test
def test_add_feature(self): bands = np.arange(2*3*3*2).reshape(2, 3, 3, 2) eop = EOPatch() eop.data['bands'] = bands self.assertTrue(np.array_equal(eop.data['bands'], bands), msg="Data numpy array not stored")
def test_save_load(self): with tempfile.TemporaryDirectory() as tmp_dir_name: self.eopatch.save(tmp_dir_name) eopatch2 = EOPatch.load(tmp_dir_name, mmap=False) self.assertEqual(self.eopatch, eopatch2) eopatch2.save(tmp_dir_name, file_format='pkl', overwrite_permission=1) eopatch2 = EOPatch.load(tmp_dir_name) self.assertEqual(self.eopatch, eopatch2) eopatch2.save(tmp_dir_name, file_format='npy', overwrite_permission=1) eopatch2 = EOPatch.load(tmp_dir_name, lazy_loading=False, mmap=False) self.assertEqual(self.eopatch, eopatch2) eopatch2.save(tmp_dir_name, file_format=FileFormat.NPY, features={ FeatureType.DATA_TIMELESS: {'mask'}, FeatureType.TIMESTAMP:... }, compress_level=3, overwrite_permission=1) eopatch2 = EOPatch.load(tmp_dir_name, lazy_loading=True, mmap=False) self.assertEqual(self.eopatch, eopatch2)
def execute(self, eopatch): """ Execute method that processes EOPatch and returns EOPatch """ # pylint: disable=too-many-locals feature_type, feature_name, new_feature_name = next(self.feature(eopatch)) # Make a copy not to change original numpy array feature_data = eopatch[feature_type][feature_name].copy() time_num, height, width, band_num = feature_data.shape if time_num <= 1: raise ValueError('Feature {} has time dimension of size {}, required at least size ' '2'.format((feature_type, feature_name), time_num)) # Apply a mask on data if self.mask_feature is not None: for mask_type, mask_name in self.mask_feature(eopatch): negated_mask = ~eopatch[mask_type][mask_name].astype(np.bool) feature_data = self._mask_feature_data(feature_data, negated_mask, mask_type) # Flatten array feature_data = np.reshape(feature_data, (time_num, height * width * band_num)) # If resampling create new EOPatch new_eopatch = EOPatch() if self.resample_range else eopatch # Resample times times = eopatch.time_series(scale_time=self.scale_time) new_eopatch.timestamp = self.get_resampled_timestamp(eopatch.timestamp) total_diff = int((new_eopatch.timestamp[0].date() - eopatch.timestamp[0].date()).total_seconds()) resampled_times = new_eopatch.time_series(scale_time=self.scale_time) + total_diff // self.scale_time # Add BBox to eopatch if it was created anew if new_eopatch.bbox is None: new_eopatch.bbox = eopatch.bbox # Replace duplicate acquisitions which have same values on the chosen time scale with their average feature_data, times = self._get_unique_times(feature_data, times) # Interpolate feature_data = self.interpolate_data(feature_data, times, resampled_times) # Normalize if self.result_interval: min_val, max_val = self.result_interval valid_mask = ~np.isnan(feature_data) feature_data[valid_mask] = np.maximum(np.minimum(feature_data[valid_mask], max_val), min_val) # Replace unknown value if not np.isnan(self.unknown_value): feature_data[np.isnan(feature_data)] = self.unknown_value # Reshape back new_eopatch[feature_type][new_feature_name] = np.reshape(feature_data, (feature_data.shape[0], height, width, band_num)) # append features from old patch new_eopatch = self._copy_old_features(new_eopatch, eopatch, self.copy_features) return new_eopatch
def test_add_feature(): bands = np.arange(2 * 3 * 3 * 2).reshape(2, 3, 3, 2) eop = EOPatch() eop.data["bands"] = bands assert np.array_equal(eop.data["bands"], bands), "Data numpy array not stored"
def setUpClass(cls): cls.patch = EOPatch.load(cls.TEST_PATCH_FILENAME) cls._prepare_patch(cls.patch) LocalBinaryPatternTask((FeatureType.DATA, 'ndvi', 'lbp'), nb_points=24, radius=3).execute(cls.patch) cls.initial_patch = EOPatch.load(cls.TEST_PATCH_FILENAME) cls._prepare_patch(cls.initial_patch)
def test_invalid_characters(self): eopatch = EOPatch() eopatch.data_timeless['mask.npy'] = np.arange(3 * 3 * 2).reshape( 3, 3, 2) with tempfile.TemporaryDirectory() as tmp_dir_name, self.assertRaises( ValueError): eopatch.save(tmp_dir_name, file_format='npy')
def setUpClass(cls): cls.patch = EOPatch.load(cls.TEST_PATCH_FILENAME) cls._prepare_patch(cls.patch) HOGTask((FeatureType.DATA, 'ndvi', 'hog'), orientations=9, pixels_per_cell=(2, 2), cells_per_block=(2, 2), visualize=True, visualize_feature_name='hog_visu').execute(cls.patch) cls.initial_patch = EOPatch.load(cls.TEST_PATCH_FILENAME) cls._prepare_patch(cls.initial_patch)
def test_rename_feature(self): bands = np.arange(2 * 3 * 3 * 2).reshape(2, 3, 3, 2) eop = EOPatch() eop.data['bands'] = bands eop.rename_feature(FeatureType.DATA, 'bands', 'new_bands') self.assertTrue('new_bands' in eop.data)
def test_get_feature(self): bands = np.arange(2*3*3*2).reshape(2, 3, 3, 2) eop = EOPatch() eop.data['bands'] = bands eop_bands = eop.get_feature(FeatureType.DATA, 'bands') self.assertTrue(np.array_equal(eop_bands, bands), msg="Data numpy array not returned properly")
def test_rename_feature_missing(self): bands = np.arange(2 * 3 * 3 * 2).reshape(2, 3, 3, 2) eop = EOPatch() eop.data['bands'] = bands with self.assertRaises(BaseException, msg='Should fail because there is no `missing_bands` feature in the EOPatch.'): eop.rename_feature(FeatureType.DATA, 'missing_bands', 'new_bands')
def test_partial_copy(self): partial_copy = DeepCopyTask(features=[(FeatureType.MASK_TIMELESS, 'mask'), FeatureType.BBOX]).execute(self.patch) expected_patch = EOPatch(mask_timeless=self.patch.mask_timeless, bbox=self.patch.bbox) self.assertEqual(partial_copy, expected_patch, 'Partial copying was not successful') partial_deepcopy = DeepCopyTask(features=[FeatureType.TIMESTAMP, (FeatureType.SCALAR, 'values')]).execute(self.patch) expected_patch = EOPatch(scalar=self.patch.scalar, timestamp=self.patch.timestamp) self.assertEqual(partial_deepcopy, expected_patch, 'Partial deep copying was not successful')
def test_bbox_feature_type(self): eop = EOPatch() invalid_entries = [ 0, list(range(4)), tuple(range(5)), {}, set(), [1, 2, 4, 3, 4326, 3], 'BBox' ] for entry in invalid_entries: with self.assertRaises((ValueError, TypeError), msg='Invalid bbox entry {} should raise an error'.format(entry)): eop.bbox = entry
def test_timeless_merge(self): eop1 = EOPatch( mask_timeless={ 'mask': np.ones((3, 4, 5), dtype=np.int16), 'mask1': np.ones((5, 4, 3), dtype=np.int16) }) eop2 = EOPatch( mask_timeless={ 'mask': 4 * np.ones((3, 4, 5), dtype=np.int16), 'mask2': np.ones((4, 5, 3), dtype=np.int16) }) with self.assertRaises(ValueError): eop1.merge(eop2) eop = eop1.merge(eop2, timeless_op='concatenate') expected_eop = EOPatch( mask_timeless={ 'mask': np.ones((3, 4, 10), dtype=np.int16), 'mask1': eop1.mask_timeless['mask1'], 'mask2': eop2.mask_timeless['mask2'] }) expected_eop.mask_timeless['mask'][..., 5:] = 4 self.assertEqual(eop, expected_eop) eop = eop1.merge(eop2, eop2, timeless_op='min') expected_eop = EOPatch( mask_timeless={ 'mask': eop1.mask_timeless['mask'], 'mask1': eop1.mask_timeless['mask1'], 'mask2': eop2.mask_timeless['mask2'] }) self.assertEqual(eop, expected_eop)
def execute(self, eopatch=None, *, filename=None): """ Execute method which adds a new feature to the EOPatch :param eopatch: input EOPatch or None if a new EOPatch should be created :type eopatch: EOPatch or None :param filename: filename of tiff file or None if entire path has already been specified in `folder` parameter of task initialization. :type filename: str or None :return: New EOPatch with added raster layer :rtype: EOPatch """ feature_type, feature_name = next(self.feature()) if eopatch is None: eopatch = EOPatch() with rasterio.open(self._get_file_path(filename)) as source: data_bbox = BBox(source.bounds, CRS(source.crs.to_epsg())) if eopatch.bbox is None: eopatch.bbox = data_bbox reading_window = self._get_reading_window(source.width, source.height, data_bbox, eopatch.bbox) data = source.read(window=reading_window, boundless=True, fill_value=self.no_data_value) if self.image_dtype is not None: data = data.astype(self.image_dtype) if not feature_type.is_spatial(): data = data.flatten() if feature_type.is_timeless(): data = np.moveaxis(data, 0, -1) else: channels = data.shape[0] times = self.timestamp_size if times is None: times = len(eopatch.timestamp) if eopatch.timestamp else 1 if channels % times != 0: raise ValueError( 'Cannot import as a time-dependant feature because the number of tiff image channels ' 'is not divisible by the number of timestamps') data = data.reshape((times, channels // times) + data.shape[1:]) data = np.moveaxis(data, 1, -1) eopatch[feature_type][feature_name] = data return eopatch
def test_check_dims(self): bands_2d = np.arange(3 * 3).reshape(3, 3) with self.assertRaises(ValueError): EOPatch(data={'bands': bands_2d}) eop = EOPatch() for feature_type in FeatureType: if feature_type.is_spatial() and not feature_type.is_vector(): with self.assertRaises(ValueError): eop[feature_type][feature_type.value] = bands_2d
def udf_to_eopatch(udf_data): eopatch = EOPatch() for tile in udf_data.raster_collection_tiles: eopatch[(FeatureType.DATA, tile.id)] = tile.data[..., np.newaxis] extent = udf_data.raster_collection_tiles[0].extent bbox = BBox((extent.left, extent.bottom, extent.right, extent.top), CRS.WGS84) eopatch.bbox = bbox return eopatch