def test_rectify_2x2_to_13x13_none(self): src_ds = self.new_source_dataset() output_geom = ImageGeom(size=(13, 13), x_min=10.0, y_min=50.0, xy_res=0.5) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) self.assertIsNone(dst_ds) output_geom = ImageGeom(size=(13, 13), x_min=-10.0, y_min=50.0, xy_res=0.5) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) self.assertIsNone(dst_ds) output_geom = ImageGeom(size=(13, 13), x_min=0.0, y_min=58.0, xy_res=0.5) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) self.assertIsNone(dst_ds) output_geom = ImageGeom(size=(13, 13), x_min=0.0, y_min=42.0, xy_res=0.5) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) self.assertIsNone(dst_ds)
def test_rectify_2x2_to_13x13(self): src_ds = self.new_source_dataset() output_geom = ImageGeom(size=(13, 13), x_min=-0.25, y_min=49.75, xy_res=0.5) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) lon, lat, rad = self._assert_shape_and_dim(dst_ds, 13, 13) np.testing.assert_almost_equal(lon.values, np.array([0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5., 5.5, 6.], dtype=lon.dtype)) np.testing.assert_almost_equal(lat.values, np.array([50., 50.5, 51.0, 51.5, 52.0, 52.5, 53.0, 53.5, 54.0, 54.5, 55., 55.5, 56.], dtype=lat.dtype)) np.testing.assert_almost_equal(rad.values, np.array([ [nan, nan, nan, nan, 4.0, nan, nan, nan, nan, nan, nan, nan, nan], [nan, nan, nan, 4.0, 4.0, 4.0, nan, nan, nan, nan, nan, nan, nan], [nan, nan, 3.0, 4.0, 4.0, 4.0, 4.0, nan, nan, nan, nan, nan, nan], [nan, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 2.0, nan, nan, nan, nan], [3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 2.0, 2.0, 2.0, nan, nan, nan], [nan, 3.0, 3.0, 3.0, 3.0, 3.0, 1.0, 2.0, 2.0, 2.0, 2.0, nan, nan], [nan, 3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0], [nan, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, nan, nan], [nan, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, nan, nan, nan, nan], [nan, nan, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, nan, nan, nan, nan, nan], [nan, nan, 1.0, 1.0, 1.0, 1.0, nan, nan, nan, nan, nan, nan, nan], [nan, nan, 1.0, 1.0, nan, nan, nan, nan, nan, nan, nan, nan, nan], [nan, nan, 1.0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan] ], dtype=rad.dtype))
def test_rectify_2x2_to_13x13_antimeridian(self): src_ds = self.new_source_dataset_antimeridian() output_geom = ImageGeom(size=(13, 13), x_min=177.75, y_min=49.75, xy_res=0.5) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) self.assertIsNotNone(dst_ds) lon, lat, rad = self._assert_shape_and_dim(dst_ds, 13, 13) np.testing.assert_almost_equal(lon.values, np.array([178., 178.5, 179., 179.5, 180., -179.5, -179., -178.5, -178., -177.5, -177., -176.5, -176.], dtype=lon.dtype)) np.testing.assert_almost_equal(lat.values, np.array([50., 50.5, 51.0, 51.5, 52.0, 52.5, 53.0, 53.5, 54.0, 54.5, 55., 55.5, 56.], dtype=lat.dtype)) np.testing.assert_almost_equal(rad.values, np.array([ [nan, nan, nan, nan, 4.0, nan, nan, nan, nan, nan, nan, nan, nan], [nan, nan, nan, 4.0, 4.0, 4.0, nan, nan, nan, nan, nan, nan, nan], [nan, nan, 3.0, 4.0, 4.0, 4.0, 4.0, nan, nan, nan, nan, nan, nan], [nan, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 2.0, nan, nan, nan, nan], [3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 2.0, 2.0, 2.0, nan, nan, nan], [nan, 3.0, 3.0, 3.0, 3.0, 3.0, 1.0, 2.0, 2.0, 2.0, 2.0, nan, nan], [nan, 3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0], [nan, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, nan, nan], [nan, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, nan, nan, nan, nan], [nan, nan, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, nan, nan, nan, nan, nan], [nan, nan, 1.0, 1.0, 1.0, 1.0, nan, nan, nan, nan, nan, nan, nan], [nan, nan, 1.0, 1.0, nan, nan, nan, nan, nan, nan, nan, nan, nan], [nan, nan, 1.0, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan] ], dtype=rad.dtype))
def test_rectify_2x2_to_7x7_subset(self): src_ds = self.new_source_dataset() output_geom = ImageGeom(size=(7, 7), x_min=1.5, y_min=50.5, xy_res=1.0) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) lon, lat, rad = self._assert_shape_and_dim(dst_ds, (7, 7)) np.testing.assert_almost_equal( lon.values, np.array([2.0, 3.0, 4.0, 5., 6., 7., 8.], dtype=lon.dtype)) np.testing.assert_almost_equal( lat.values, np.array([51.0, 52.0, 53.0, 54.0, 55., 56., 57.], dtype=lat.dtype)) np.testing.assert_almost_equal( rad.values, np.array([ [4.0, 4.0, nan, nan, nan, nan, nan], [3.0, 4.0, 2.0, nan, nan, nan, nan], [3.0, 1.0, 2.0, 2.0, 2.0, nan, nan], [1.0, 1.0, 2.0, nan, nan, nan, nan], [1.0, nan, nan, nan, nan, nan, nan], [nan, nan, nan, nan, nan, nan, nan], [nan, nan, nan, nan, nan, nan, nan], ], dtype=rad.dtype))
def test_rectify_2x2_to_13x13_output_ij_names(self): src_ds = self.new_source_dataset() output_geom = ImageGeom(size=(13, 13), x_min=-0.25, y_min=49.75, xy_res=0.5) dst_ds = rectify_dataset(src_ds, output_geom=output_geom, output_ij_names=('source_i', 'source_j')) lon, lat, rad, source_i, source_j = self._assert_shape_and_dim( dst_ds, (13, 13), var_names=('rad', 'source_i', 'source_j')) np.testing.assert_almost_equal( lon.values, np.array([ 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5., 5.5, 6. ], dtype=lon.dtype)) np.testing.assert_almost_equal( lat.values, np.array([ 50., 50.5, 51.0, 51.5, 52.0, 52.5, 53.0, 53.5, 54.0, 54.5, 55., 55.5, 56. ], dtype=lat.dtype)) np.testing.assert_almost_equal(rad.values, self.expected_rad_13x13(rad.dtype)) np.testing.assert_almost_equal(np.floor(source_i.values + 0.5), self.expected_i_13x13()) np.testing.assert_almost_equal(np.floor(source_j.values + 0.5), self.expected_j_13x13())
def test_rectify_2x2_to_13x13_dask_13x3(self): src_ds = self.new_source_dataset() output_geom = ImageGeom(size=(13, 13), x_min=-0.25, y_min=49.75, xy_res=0.5, tile_size=(13, 3)) dst_ds = rectify_dataset(src_ds, output_geom=output_geom) lon, lat, rad = self._assert_shape_and_dim(dst_ds, (13, 13), chunks=((3, 3, 3, 3, 1), (13, ))) np.testing.assert_almost_equal( lon.values, np.array([ 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5., 5.5, 6. ], dtype=lon.dtype)) np.testing.assert_almost_equal( lat.values, np.array([ 50., 50.5, 51.0, 51.5, 52.0, 52.5, 53.0, 53.5, 54.0, 54.5, 55., 55.5, 56. ], dtype=lat.dtype)) np.testing.assert_almost_equal(rad.values, self.expected_rad_13x13(rad.dtype))
def test_rectify_dataset(self): src_ds = create_s2plus_dataset() expected_data = np.array( [[ 0.033001, 0.018002, 0.018002, 0.018002, 0.007999, 0.007999, 0.008999, 0.008999, 0.008999, 0.021 ], [ 0.041, 0.022999, 0.022999, 0.022999, 0.007, 0.007, 0.009998, 0.009998, 0.009998, 0.021 ], [ 0.036999, 0.022999, 0.022999, 0.022999, 0.007999, 0.007999, 0.008999, 0.008999, 0.023998, 0.023998 ], [ 0.036999, 0.022999, 0.022999, 0.022999, 0.007999, 0.007999, 0.008999, 0.008999, 0.023998, 0.023998 ], [ 0.028, 0.021, 0.021, 0.021, 0.009998, 0.009998, 0.008999, 0.008999, 0.022999, 0.022999 ], [ 0.025002, 0.019001, 0.019001, 0.019001, 0.008999, 0.008999, 0.012001, 0.012001, 0.022999, nan ], [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]]) dst_ds = rectify_dataset(src_ds, tile_size=None) self.assertEqual(None, dst_ds.rrs_665.chunks) np.testing.assert_almost_equal(dst_ds.rrs_665.values, expected_data) dst_ds = rectify_dataset(src_ds, tile_size=5) self.assertEqual(((5, 2), (5, 5)), dst_ds.rrs_665.chunks) np.testing.assert_almost_equal(dst_ds.rrs_665.values, expected_data) dst_ds = rectify_dataset(src_ds, tile_size=None, is_y_reversed=True) self.assertEqual(None, dst_ds.rrs_665.chunks) np.testing.assert_almost_equal(dst_ds.rrs_665.values, expected_data[::-1]) dst_ds = rectify_dataset(src_ds, tile_size=5, is_y_reversed=True) self.assertEqual(((2, 5), (5, 5)), dst_ds.rrs_665.chunks) np.testing.assert_almost_equal(dst_ds.rrs_665.values, expected_data[::-1])
def process(self, dataset: xr.Dataset, geo_coding: GeoCoding, output_geom: ImageGeom, output_resampling: str, include_non_spatial_vars=False) -> xr.Dataset: """ Perform reprojection using tie-points / ground control points. """ reprojection_info = self.get_reprojection_info(dataset) in_rectification_mode = reprojection_info.xy_gcp_step is None if in_rectification_mode: warn_prefix = 'unsupported argument in np-GCP rectification mode' if reprojection_info.xy_tp_gcp_step is not None: warnings.warn( f'{warn_prefix}: ignoring ' f'reprojection_info.xy_tp_gcp_step = {reprojection_info.xy_tp_gcp_step!r}' ) if output_resampling != 'Nearest': warnings.warn(f'{warn_prefix}: ignoring ' f'dst_resampling = {output_resampling!r}') if include_non_spatial_vars: warnings.warn( f'{warn_prefix}: ignoring ' f'include_non_spatial_vars = {include_non_spatial_vars!r}') geo_coding = geo_coding.derive( x_name=reprojection_info.xy_names[0], y_name=reprojection_info.xy_names[1]) dataset = rectify_dataset(dataset, compute_subset=False, geo_coding=geo_coding, output_geom=output_geom, is_y_axis_inverted=True) if dataset is not None and geo_coding.is_geo_crs and geo_coding.xy_names != ( 'lon', 'lat'): dataset = dataset.rename({ geo_coding.x_name: 'lon', geo_coding.y_name: 'lat' }) return dataset else: return reproject_xy_to_wgs84( dataset, src_xy_var_names=reprojection_info.xy_names, src_xy_tp_var_names=reprojection_info.xy_tp_names, src_xy_crs=reprojection_info.xy_crs, src_xy_gcp_step=reprojection_info.xy_gcp_step or 1, src_xy_tp_gcp_step=reprojection_info.xy_tp_gcp_step or 1, dst_size=output_geom.size, dst_region=output_geom.xy_bbox, dst_resampling=output_resampling, include_non_spatial_vars=include_non_spatial_vars)
def _rectify(input_path: str, xy_names: Optional[Tuple[str, str]], var_names: Optional[Sequence[str]], output_path: str, output_format: Optional[str], output_size: Optional[Tuple[int, int]], output_tile_size: Optional[Tuple[int, int]], output_point: Optional[Tuple[float, float]], output_res: Optional[float], delta: float, dry_run: bool, monitor): from xcube.core.dsio import guess_dataset_format from xcube.core.dsio import open_dataset from xcube.core.dsio import write_dataset from xcube.core.rectify import rectify_dataset from xcube.core.rectify import ImageGeom from xcube.core.sentinel3 import is_sentinel3_product from xcube.core.sentinel3 import open_sentinel3_product if not output_format: output_format = guess_dataset_format(output_path) output_geom = None if output_size is not None and output_point is not None and output_res is not None: output_geom = ImageGeom(size=output_size, x_min=output_point[0], y_min=output_point[1], xy_res=output_res) elif output_size is not None or output_point is not None or output_res is not None: raise click.ClickException( 'SIZE, POINT, and RES must all be given or none of them.') monitor(f'Opening dataset from {input_path!r}...') if is_sentinel3_product(input_path): src_ds = open_sentinel3_product(input_path) else: src_ds = open_dataset(input_path) monitor('Rectifying...') reproj_ds = rectify_dataset(src_ds, xy_names=xy_names, var_names=var_names, output_geom=output_geom, tile_size=output_tile_size, uv_delta=delta) if reproj_ds is None: monitor( f'Dataset {input_path} does not seem to have an intersection with bounding box' ) return monitor(f'Writing rectified dataset to {output_path!r}...') if not dry_run: write_dataset(reproj_ds, output_path, output_format) monitor(f'Done.')
def test_rectify_2x2_to_default(self): src_ds = self.new_source_dataset() dst_ds = rectify_dataset(src_ds) lon, lat, rad = self._assert_shape_and_dim(dst_ds, (4, 4)) np.testing.assert_almost_equal( lon.values, np.array([1.0, 3.0, 5., 7.], dtype=lon.dtype)) np.testing.assert_almost_equal( lat.values, np.array([51.0, 53.0, 55., 57.], dtype=lat.dtype)) np.testing.assert_almost_equal( rad.values, np.array([[3.0, 4.0, nan, nan], [3.0, 1.0, 2.0, nan], [1.0, nan, nan, nan], [nan, nan, nan, nan]], dtype=rad.dtype))
def process(self, dataset: xr.Dataset, geo_coding: GeoCoding, output_geom: ImageGeom, output_resampling: str, include_non_spatial_vars=False) -> xr.Dataset: """ Perform reprojection using tie-points / ground control points. """ reprojection_info = self.get_reprojection_info(dataset) in_rectification_mode = reprojection_info.xy_gcp_step is None if in_rectification_mode: warn_prefix = 'unsupported argument in np-GCP rectification mode' if reprojection_info.xy_tp_gcp_step is not None: warnings.warn( f'{warn_prefix}: ignoring ' f'reprojection_info.xy_tp_gcp_step = {reprojection_info.xy_tp_gcp_step!r}' ) if output_resampling != 'Nearest': warnings.warn(f'{warn_prefix}: ignoring ' f'dst_resampling = {output_resampling!r}') if include_non_spatial_vars: warnings.warn( f'{warn_prefix}: ignoring ' f'include_non_spatial_vars = {include_non_spatial_vars!r}') geo_coding = geo_coding.derive( x_name=reprojection_info.xy_names[0], y_name=reprojection_info.xy_names[1]) dataset = rectify_dataset(dataset, compute_subset=False, geo_coding=geo_coding, output_geom=output_geom, is_y_reversed=True) if output_geom.is_tiled: # The following condition may become true, if we have used rectified_dataset(input, ..., is_y_reverse=True) # In this case y-chunksizes will also be reversed. So that the first chunk is smaller than any other. # Zarr will reject such datasets, when written. if dataset.chunks.get('lat')[0] < dataset.chunks.get( 'lat')[-1]: dataset = dataset.chunk({ 'lat': output_geom.tile_height, 'lon': output_geom.tile_width }) if dataset is not None and geo_coding.is_geo_crs and geo_coding.xy_names != ( 'lon', 'lat'): dataset = dataset.rename({ geo_coding.x_name: 'lon', geo_coding.y_name: 'lat' }) return dataset else: return reproject_xy_to_wgs84( dataset, src_xy_var_names=reprojection_info.xy_names, src_xy_tp_var_names=reprojection_info.xy_tp_names, src_xy_crs=reprojection_info.xy_crs, src_xy_gcp_step=reprojection_info.xy_gcp_step or 1, src_xy_tp_gcp_step=reprojection_info.xy_tp_gcp_step or 1, dst_size=output_geom.size, dst_region=output_geom.xy_bbox, dst_resampling=output_resampling, include_non_spatial_vars=include_non_spatial_vars)