diff --git a/xee/ext.py b/xee/ext.py index 36a5316..7471b5e 100644 --- a/xee/ext.py +++ b/xee/ext.py @@ -186,16 +186,19 @@ def __init__( self.geometry = geometry self.primary_dim_name = primary_dim_name or 'time' self.primary_dim_property = primary_dim_property or 'system:time_start' - + + # If crs_arg is None, we try to get it from projection but if + # projection is None, we use a default value ('EPSG:4326'). + # This logic is implemented in self.get_info(). + self.crs_arg = crs + proj = self.get_info.get('projection', {}) + self.crs_arg = self.get_info['crs_arg'] + self.crs = CRS(self.crs_arg) + self.n_images = self.get_info['size'] self._props = self.get_info['props'] # Metadata should apply to all imgs. self._img_info: types.ImageInfo = self.get_info['first'] - - proj = self.get_info.get('projection', {}) - - self.crs_arg = crs or proj.get('crs', proj.get('wkt', 'EPSG:4326')) - self.crs = CRS(self.crs_arg) # Gets the unit i.e. meter, degree etc. self.scale_units = self.crs.axis_info[0].unit_name # Get the dimensions name based on the CRS (scale units). @@ -224,22 +227,24 @@ def __init__( # used for all internal `computePixels()` calls. try: if isinstance(geometry, ee.Geometry): - x_min_0, y_min_0, x_max_0, y_max_0 = _ee_bounds_to_bounds( + x_min, y_min, x_max, y_max = _ee_bounds_to_bounds( self.get_info['bounds'] ) else: + # TODO: Maybe converting the area of use to the desired + # crs and them getting the bounds is a better approach. x_min_0, y_min_0, x_max_0, y_max_0 = self.crs.area_of_use.bounds + x_min, y_min = self.transform(x_min_0, y_min_0) + x_max, y_max = self.transform(x_max_0, y_max_0) + self.bounds = x_min, y_min, x_max, y_max except AttributeError: # `area_of_use` is probable `None`. Parse the geometry from the first # image instead (calculated in self.get_info()) - x_min_0, y_min_0, x_max_0, y_max_0 = _ee_bounds_to_bounds( + x_min, y_min, x_max, y_max = _ee_bounds_to_bounds( self.get_info['bounds'] - ) - - x_min, y_min = self.transform(x_min_0, y_min_0) - x_max, y_max = self.transform(x_max_0, y_max_0) + ) self.bounds = x_min, y_min, x_max, y_max - + max_dtype = self._max_itemsize() # TODO(b/291851322): Consider support for laziness when chunks=None. @@ -260,19 +265,27 @@ def __init__( def get_info(self) -> Dict[str, Any]: """Make all getInfo() calls to EE at once.""" - rpcs = [ - ('size', self.image_collection.size()), - ('props', self.image_collection.toDictionary()), - ('first', self.image_collection.first()), - ] + rpcs = { + 'size': self.image_collection.size(), + 'props': self.image_collection.toDictionary(), + 'first': self.image_collection.first(), + } if isinstance(self.projection, ee.Projection): - rpcs.append(('projection', self.projection)) + rpcs['projection'] = self.projection + + if self.crs_arg is not None: + rpcs['crs_arg'] = self.crs_arg + elif 'projection' in rpcs.keys(): + rpcs['crs_arg'] = rpcs['projection'].crs() + else: + rpcs['crs_arg'] = 'EPSG:4326' if isinstance(self.geometry, ee.Geometry): - rpcs.append(('bounds', self.geometry.bounds())) + # TODO: Is 1 good enough for the max error? + rpcs['bounds'] = self.geometry.bounds(1, rpcs['crs_arg']) else: - rpcs.append(('bounds', self.image_collection.first().geometry().bounds())) + rpcs['bounds'] = self.image_collection.first().geometry().bounds(1, rpcs['crs_arg']) # TODO(#29, #30): This RPC call takes the longest time to compute. This # requires a full scan of the images in the collection, which happens on the @@ -285,18 +298,15 @@ def get_info(self) -> Dict[str, Any]: # client-side. Ideally, this would live behind a xarray-backend-specific # feature flag, since it's not guaranteed that data is this consistent. columns = ['system:id', self.primary_dim_property] - rpcs.append(( - 'properties', - ( - self.image_collection.reduceColumns( - ee.Reducer.toList().repeat(len(columns)), columns - ).get('list') - ), - )) - - info = ee.List([rpc for _, rpc in rpcs]).getInfo() + rpcs['properties'] = ( + self.image_collection.reduceColumns( + ee.Reducer.toList().repeat(len(columns)), columns + ).get('list') + ) - return dict(zip((name for name, _ in rpcs), info)) + info = ee.List([rpc for _, rpc in rpcs.items()]).getInfo() + + return dict(zip((name for name, _ in rpcs.items()), info)) @property def image_collection_properties(self) -> Tuple[List[str], List[str]]: