def landsat_clean_mask_invalid(dataset): """ Masks out invalid data according to the LANDSAT surface reflectance specifications. See this document: https://landsat.usgs.gov/sites/default/files/documents/ledaps_product_guide.pdf pages 19-20. Parameters ---------- dataset: xarray.Dataset An xarray `Dataset` containing bands such as 'red', 'green', or 'blue'. Returns ------- invalid_mask: xarray.DataArray An xarray DataArray with the same number and order of coordinates as in `dataset`. """ invalid_mask = None data_arr_names = [ arr_name for arr_name in list(dataset.data_vars) if arr_name not in ['pixel_qa', 'radsat_qa', 'cloud_qa'] ] # Only keep data where all bands are in the valid range. for i, data_arr_name in enumerate(data_arr_names): invalid_mask_arr = xr_and(0 < dataset[data_arr_name], dataset[data_arr_name] < 10000) invalid_mask = invalid_mask_arr if i == 0 else xr_and( invalid_mask, invalid_mask_arr) return invalid_mask
def load_simple(dc, platform, product, frac_res=None, abs_res=None, load_params={}, masking_params={}, indiv_masks=None): """ Simplifies loading from the Data Cube by retrieving a dataset along with its mask. Parameters ---------- dc: datacube.api.core.Datacube The Datacube instance to load data with. platform, product: str Strings denoting the platform and product to retrieve data for. frac_res: float The fraction of the original resolution to scale to. Must be postive. Note that this can be greater than 1.0, in which case the resolution is upsampled. abs_res: list-like A list-like of the number of pixels for the x and y axes, respectively. Overrides `frac_res` if specified. load_params: dict, optional A dictionary of parameters for `dc.load()`. Here are some common load parameters: *lat, lon: list-like 2-tuples of minimum and maximum values for latitude and longitude, respectively.* *time: list-like A 2-tuple of the minimum and maximum times for acquisitions.* *measurements: list-like The list of measurements to retrieve from the Datacube.* masking_params: dict, optional A dictionary of keyword arguments for corresponding masking functions. For example: {'cover_types':['cloud']} would retain only clouds for Landsat products, because `landsat_qa_clean_mask()` is used for the Landsat family of platforms. indiv_masks: list A list of masks to return (e.g. ['water']). These do not have to be the same used to create `clean_mask`. Returns ------- dataset: xarray.Dataset The raw data requested. Can be cleaned with `dataset.where(clean_mask)`. clean_mask: xarray.DataArray The clean mask, formed as a logical AND of all masks used. masks: list of xarray.DataArray A list of the masks requested by `indiv_masks`, or `None` if `indiv_masks` is not specified. Raises ------ AssertionError: If no data is retrieved for any platform query. :Authors: John Rattz ([email protected]) """ current_load_params = dict(platform=platform, product=product) current_load_params.update(load_params) dataset = dc.load(**current_load_params) assert len(dataset.dims) > 0, "No data was retrieved." # Scale resolution if specified. if frac_res is not None or abs_res is not None: dataset = xr_scale_res(dataset, frac_res=frac_res, abs_res=abs_res) # Get the clean mask for the appropriate LANDSAT satellite platform. clean_mask = landsat_qa_clean_mask(dataset, platform, **masking_params) # Get the mask for removing data ouside the accepted range of LANDSAT 7 and 8. clean_mask = xr_and(clean_mask, landsat_clean_mask_invalid(dataset)) # Retrieve individual masks. if indiv_masks is None: masks = None else: masks = [] for mask in indiv_masks: masks.append( landsat_qa_clean_mask(dataset, platform, cover_types=[mask])) return dataset, clean_mask, masks