From 51502826954471db93eaf29ce97fc4ee14aa855a Mon Sep 17 00:00:00 2001 From: ivanzvonkov Date: Sat, 24 Sep 2022 18:02:09 -0400 Subject: [PATCH 1/4] Comprehensive fillna --- openmapflow/engineer.py | 92 +++++++++++-------------------- openmapflow/inference.py | 18 +----- openmapflow/labeled_dataset.py | 28 +++------- openmapflow/torchserve_handler.py | 7 +-- tests/test_engineer.py | 37 +++---------- tests/test_inference.py | 18 ------ tests/test_labeled_dataset.py | 20 +++---- 7 files changed, 58 insertions(+), 162 deletions(-) diff --git a/openmapflow/engineer.py b/openmapflow/engineer.py index cb654ab3..1b0636fc 100644 --- a/openmapflow/engineer.py +++ b/openmapflow/engineer.py @@ -17,17 +17,33 @@ ) +def _fillna(data): + is_nan = np.isnan(data) + if not is_nan.any().item(): + return data + mean_per_time_band = data.mean(axis=(2, 3), skipna=True) + is_nan_any = is_nan.any(axis=(0, 2, 3)).values + is_nan_all = is_nan.all(axis=(0, 2, 3)).values + bands_np = np.array(DYNAMIC_BANDS + STATIC_BANDS) + bands_all_nans = bands_np[is_nan_all] + bands_some_nans = bands_np[is_nan_any & ~is_nan_all] + if bands_all_nans.size > 0: + print(f"WARNING: Bands: {bands_all_nans} have all nan values") + mean_per_time_band[:, is_nan_all] = 0 + if bands_some_nans.size > 0: + print(f"WARNING: Bands: {bands_some_nans} have some nan values") + return data.fillna(mean_per_time_band) + + def load_tif( - filepath: Path, - start_date: Optional[datetime] = None, - num_timesteps: Optional[int] = None, + filepath: Path, start_date: Optional[datetime] = None, fillna: bool = True ): r""" The sentinel files exported from google earth have all the timesteps concatenated together. This function loads a tif files and splits the timesteps - Returns: The loaded xr.DataArray, and the average slope (used for filling nan slopes) + Returns: The loaded xr.DataArray """ xr = import_optional_dependency("xarray") @@ -40,11 +56,11 @@ def load_tif( num_dynamic_bands = num_bands - len(STATIC_BANDS) assert num_dynamic_bands % bands_per_timestep == 0 - if num_timesteps is None: - num_timesteps = num_dynamic_bands // bands_per_timestep + num_timesteps = num_dynamic_bands // bands_per_timestep static_data = da.isel(band=slice(num_bands - len(STATIC_BANDS), num_bands)) - average_slope = np.nanmean(static_data.values[STATIC_BANDS.index("slope"), :, :]) + + # average_slope = np.nanmean(static_data.values[STATIC_BANDS.index("slope"), :, :]) for timestep in range(num_timesteps): time_specific_da = da.isel( @@ -52,6 +68,7 @@ def load_tif( timestep * bands_per_timestep, (timestep + 1) * bands_per_timestep ) ) + # time_specific_da = fillna2(time_specific_da, DYNAMIC_BANDS) time_specific_da = xr.concat([time_specific_da, static_data], "band") time_specific_da["band"] = range(bands_per_timestep + len(STATIC_BANDS)) da_split_by_time.append(time_specific_da) @@ -61,14 +78,15 @@ def load_tif( start_date + timedelta(days=DAYS_PER_TIMESTEP) * i for i in range(len(da_split_by_time)) ] - dynamic_data = xr.concat(da_split_by_time, pd.Index(timesteps, name="time")) + data = xr.concat(da_split_by_time, pd.Index(timesteps, name="time")) else: - dynamic_data = xr.concat( + data = xr.concat( da_split_by_time, pd.Index(range(len(da_split_by_time)), name="time") ) - dynamic_data.attrs["band_descriptions"] = BANDS - - return dynamic_data, average_slope + if fillna: + data = _fillna(data) + data.attrs["band_descriptions"] = BANDS + return data def calculate_ndvi(input_array: np.ndarray) -> np.ndarray: @@ -105,40 +123,6 @@ def calculate_ndvi(input_array: np.ndarray) -> np.ndarray: return np.append(input_array, np.expand_dims(ndvi, -1), axis=-1) -def fillna(array: np.ndarray, average_slope: float) -> Optional[np.ndarray]: - r""" - Given an input array of shape [timesteps, BANDS] - fill NaN values with the mean of each band across the timestep - The slope values may all be nan so average_slope is manually passed - """ - num_dims = len(array.shape) - if num_dims == 2: - bands_index = 1 - mean_per_band = np.nanmean(array, axis=0) - elif num_dims == 3: - bands_index = 2 - mean_per_band = np.nanmean(np.nanmean(array, axis=0), axis=0) - else: - raise ValueError(f"Expected num_dims to be 2 or 3 - got {num_dims}") - - assert array.shape[bands_index] == len(BANDS) - - if np.isnan(mean_per_band).any(): - if (sum(np.isnan(mean_per_band)) == bands_index) & ( - np.isnan(mean_per_band[BANDS.index("slope")]).all() - ): - mean_per_band[BANDS.index("slope")] = average_slope - assert not np.isnan(mean_per_band).any() - else: - return None - for i in range(array.shape[bands_index]): - if num_dims == 2: - array[:, i] = np.nan_to_num(array[:, i], nan=mean_per_band[i]) - elif num_dims == 3: - array[:, :, i] = np.nan_to_num(array[:, :, i], nan=mean_per_band[i]) - return array - - def remove_bands(array: np.ndarray) -> np.ndarray: """ Expects the input to be of shape [timesteps, bands] or @@ -168,12 +152,8 @@ def remove_bands(array: np.ndarray) -> np.ndarray: raise ValueError(error_message) -def process_test_file( - path_to_file: Path, start_date: datetime, num_timesteps: Optional[int] = None -) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: - da, slope = load_tif( - path_to_file, start_date=start_date, num_timesteps=num_timesteps - ) +def process_test_file(path_to_file: Path) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: + da = load_tif(path_to_file) # Process remote sensing data x_np = da.values @@ -181,12 +161,6 @@ def process_test_file( x_np = np.moveaxis(x_np, -1, 0) x_np = calculate_ndvi(x_np) x_np = remove_bands(x_np) - final_x = fillna(x_np, slope) - if final_x is None: - raise RuntimeError( - "fillna on the test instance returned None; " - "does the test instance contain NaN only bands?" - ) # Get lat lons lon, lat = np.meshgrid(da.x.values, da.y.values) @@ -194,4 +168,4 @@ def process_test_file( np.squeeze(lat.reshape(-1, 1), -1), np.squeeze(lon.reshape(-1, 1), -1), ) - return final_x, flat_lat, flat_lon + return x_np, flat_lat, flat_lon diff --git a/openmapflow/inference.py b/openmapflow/inference.py index 4b45ad03..a13f79a3 100644 --- a/openmapflow/inference.py +++ b/openmapflow/inference.py @@ -1,7 +1,5 @@ -import re -from datetime import datetime from pathlib import Path -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional import numpy as np import pandas as pd @@ -43,15 +41,6 @@ def __init__( "Using PyTorch model but PyTorch is not installed. Please pip install torch" ) - @staticmethod - def start_date_from_str(path: Union[Path, str]) -> datetime: - dates = re.findall(r"\d{4}-\d{2}-\d{2}", str(path)) - if len(dates) < 1: - raise ValueError(f"{path} should have at least one date") - start_date_str = dates[0] - start_date = datetime.strptime(start_date_str, "%Y-%m-%d") - return start_date - @staticmethod def _combine_predictions( flat_lat: np.ndarray, flat_lon: np.ndarray, batch_predictions: List[np.ndarray] @@ -84,13 +73,10 @@ def _on_single_batch(self, batch_x_np: np.ndarray) -> np.ndarray: def run( self, local_path: Path, - start_date: Optional[datetime] = None, dest_path: Optional[Path] = None, ) -> pd.DataFrame: """Runs inference on a single tif file.""" - if start_date is None: - start_date = self.start_date_from_str(local_path) - x_np, flat_lat, flat_lon = process_test_file(local_path, start_date) + x_np, flat_lat, flat_lon = process_test_file(local_path) if self.normalizing_dict is not None: x_np = (x_np - self.normalizing_dict["mean"]) / self.normalizing_dict["std"] diff --git a/openmapflow/labeled_dataset.py b/openmapflow/labeled_dataset.py index 61ebed8e..df37d804 100644 --- a/openmapflow/labeled_dataset.py +++ b/openmapflow/labeled_dataset.py @@ -2,7 +2,6 @@ import random import shutil import tempfile -import warnings from dataclasses import dataclass from datetime import date from pathlib import Path @@ -42,7 +41,7 @@ EarthEngineExporter, get_cloud_tif_list, ) -from openmapflow.engineer import calculate_ndvi, fillna, load_tif, remove_bands +from openmapflow.engineer import calculate_ndvi, load_tif, remove_bands from openmapflow.utils import str_to_np, tqdm SEED = 42 @@ -145,21 +144,20 @@ def _find_matching_point( So the function finds the closest grid coordinate to the label coordinate. Additional value is given to a grid coordinate that is close to the center of the tif. """ - tif_slope_tuples = [] + tifs = [] for p in eo_paths: blob = tif_bucket.blob(str(p)) local_path = Path(f"{temp_dir}/{p.name}") if not local_path.exists(): blob.download_to_filename(str(local_path)) - tif_slope_tuples.append(load_tif(local_path)) + tifs.append(load_tif(local_path)) if local_path.exists(): local_path.unlink() - if len(tif_slope_tuples) > 1: + if len(tifs) > 1: min_distance_from_point = np.inf min_distance_from_center = np.inf - for i, tif_slope_tuple in enumerate(tif_slope_tuples): - tif, slope = tif_slope_tuple + for i, tif in enumerate(tifs): lon, lon_idx = _find_nearest(tif.x, label_lon) lat, lat_idx = _find_nearest(tif.y, label_lat) distance_from_point = _distance(label_lat, label_lon, lat, lon) @@ -173,22 +171,16 @@ def _find_matching_point( min_distance_from_center = distance_from_center min_distance_from_point = distance_from_point eo_data = tif.sel(x=lon).sel(y=lat).values - average_slope = slope eo_file = eo_paths[i].name else: - tif, slope = tif_slope_tuples[0] + tif = tifs[0] closest_lon = _find_nearest(tif.x, label_lon)[0] closest_lat = _find_nearest(tif.y, label_lat)[0] eo_data = tif.sel(x=closest_lon).sel(y=closest_lat).values - average_slope = slope eo_file = eo_paths[0].name eo_data = calculate_ndvi(eo_data) eo_data = remove_bands(eo_data) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - eo_data = fillna(eo_data, average_slope) - return eo_data, closest_lon, closest_lat, eo_file @@ -206,7 +198,7 @@ def _find_matching_point_url( with local_path.open("wb") as f: shutil.copyfileobj(r.raw, f) - tif, slope = load_tif(local_path) + tif = load_tif(local_path) if local_path.exists(): local_path.unlink() @@ -214,14 +206,8 @@ def _find_matching_point_url( closest_lat = _find_nearest(tif.y, label_lat)[0] eo_data = tif.sel(x=closest_lon).sel(y=closest_lat).values - average_slope = slope - eo_data = calculate_ndvi(eo_data) eo_data = remove_bands(eo_data) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - eo_data = fillna(eo_data, average_slope) - return eo_data, closest_lon, closest_lat diff --git a/openmapflow/torchserve_handler.py b/openmapflow/torchserve_handler.py index a3db610b..2873b8bd 100644 --- a/openmapflow/torchserve_handler.py +++ b/openmapflow/torchserve_handler.py @@ -126,13 +126,8 @@ def inference(self, data: str, *args, **kwargs) -> Tuple[str, str]: local_src_path = download_file(uri) local_dest_path = Path(tempfile.gettempdir() + f"/pred_{Path(uri).stem}.nc") - start_date = Inference.start_date_from_str(uri) - print(f"HANDLER: Start date: {start_date}") - print("HANDLER: Starting inference") - self.inference_module.run( - local_path=local_src_path, start_date=start_date, dest_path=local_dest_path - ) + self.inference_module.run(local_path=local_src_path, dest_path=local_dest_path) print("HANDLER: Completed inference") dest_uri = upload_file( bucket_name=self.dest_bucket_name, local_path=local_dest_path, src_uri=uri diff --git a/tests/test_engineer.py b/tests/test_engineer.py index f2441a2d..c3a8a995 100644 --- a/tests/test_engineer.py +++ b/tests/test_engineer.py @@ -1,11 +1,10 @@ import unittest -from datetime import datetime from pathlib import Path import numpy as np -from openmapflow.bands import BANDS, DYNAMIC_BANDS, STATIC_BANDS -from openmapflow.engineer import fillna, load_tif, process_test_file +from openmapflow.bands import DYNAMIC_BANDS, STATIC_BANDS +from openmapflow.engineer import load_tif, process_test_file TIF_FILE = Path(__file__).parent / "98-togo_2019-02-06_2020-02-01.tif" @@ -15,7 +14,7 @@ class TestEngineer(unittest.TestCase): def test_load_tif_file(self): - loaded_file, _ = load_tif(TIF_FILE) + loaded_file = load_tif(TIF_FILE) self.assertEqual(loaded_file.shape[0], NUM_TIMESTEPS) self.assertEqual(loaded_file.shape[1], len(DYNAMIC_BANDS) + len(STATIC_BANDS)) @@ -34,33 +33,13 @@ def test_load_tif_file(self): self.assertTrue(((temperature_values) < 329.85).all()) def test_fillna_real(self): - - loaded_file, average_slope = load_tif(TIF_FILE) - - # slope is calculated from neighbouring points, so the - # edges are NaN - for lat_idx in range(loaded_file.shape[2]): - for lon_idx in range(loaded_file.shape[3]): - # we remove the first index to simulate removing B1 and B10 - array = loaded_file.values[:, 2:, lat_idx, lon_idx] - num_timesteps = array.shape[0] - # and we add an array to simulate adding NDVI - array = np.concatenate([array, np.ones([num_timesteps, 1])], axis=1) - new_array = fillna(array, average_slope) - if np.isnan(array[-2]).all(): - self.assertTrue((new_array[-2] == average_slope).all()) - self.assertFalse(np.isnan(new_array).any()) - - def test_fillna_simulated(self): - array = np.array([[1, float("NaN"), 3]] * len(BANDS)).T - expected_array = np.array([[1, 2, 3]] * len(BANDS)).T - new_array = fillna(array, average_slope=1) - self.assertTrue(np.array_equal(new_array, expected_array)) + loaded_file1 = load_tif(TIF_FILE, fillnans=False) + self.assertTrue(np.isnan(loaded_file1).any()) + loaded_file2 = load_tif(TIF_FILE, fillnans=True) + self.assertFalse(np.isnan(loaded_file2).any()) def test_process_test_file(self): - x_np, flat_lat, flat_lon = process_test_file( - TIF_FILE, start_date=datetime(2019, 2, 6, 0, 0) - ) + x_np, flat_lat, flat_lon = process_test_file(TIF_FILE) self.assertEqual(x_np.shape, (289, 12, 18)) self.assertEqual(flat_lat.shape, (289,)) self.assertEqual(flat_lon.shape, (289,)) diff --git a/tests/test_inference.py b/tests/test_inference.py index c3c2606d..770534ef 100644 --- a/tests/test_inference.py +++ b/tests/test_inference.py @@ -1,4 +1,3 @@ -from datetime import datetime from unittest import TestCase import numpy as np @@ -7,23 +6,6 @@ class TestInference(TestCase): - def test_start_date_from_str_expected(self): - actual_start_date = Inference.start_date_from_str( - "98-togo_2019-02-06_2020-02-01" - ) - expected_start_date = datetime(2019, 2, 6, 0, 0) - self.assertEqual(actual_start_date, expected_start_date) - - def test_start_date_from_str_none(self): - self.assertRaises(ValueError, Inference.start_date_from_str, "98-togo") - - def test_start_date_from_str_more_than_2(self): - actual_start_date = Inference.start_date_from_str( - "98-togo_2019-02-06_2020-02-01_2019-02-06_2020-02-01" - ) - expected_start_date = datetime(2019, 2, 6, 0, 0) - self.assertEqual(actual_start_date, expected_start_date) - def test_combine_predictions(self): flat_lat = np.array( [14.95313164, 14.95313164, 14.95313164, 14.95313164, 14.95313164] diff --git a/tests/test_labeled_dataset.py b/tests/test_labeled_dataset.py index 837b485f..1ce4c992 100644 --- a/tests/test_labeled_dataset.py +++ b/tests/test_labeled_dataset.py @@ -61,10 +61,9 @@ class TestLabeledDatasetCustom(TestCase): @skipIf(XARRAY_NOT_INSTALLED, "xarray not installed") @patch("openmapflow.labeled_dataset.load_tif") def test_find_matching_point_from_one(self, mock_load_tif): - mock_data = xr.DataArray( + mock_load_tif.return_value = xr.DataArray( data=np.ones((24, 19, 17, 17)), dims=("time", "band", "y", "x") ) - mock_load_tif.return_value = mock_data, 0.0 labelled_np, closest_lon, closest_lat, source_file = _find_matching_point( eo_paths=[Path("mock")], label_lon=5, @@ -86,12 +85,9 @@ def test_find_matching_point_from_multiple(self, mock_load_tif): def side_effect(path): idx = [i for i, p in enumerate(tif_paths) if p.stem == Path(path).stem][0] - return ( - xr.DataArray( - dims=("time", "band", "y", "x"), - data=np.ones((24, 19, 17, 17)) * idx, - ), - 0.0, + return xr.DataArray( + dims=("time", "band", "y", "x"), + data=np.ones((24, 19, 17, 17)) * idx, ) mock_load_tif.side_effect = side_effect @@ -111,17 +107,15 @@ def side_effect(path): def test_find_matching_point_from_url( self, mock_load_tif, mock_requests, mock_shutil ): - mock_data = xr.DataArray( - data=np.ones((24, 19, 17, 17)), dims=("time", "band", "y", "x") - ) - @dataclass class MockResponse: raw: str = "" status_code: int = 200 mock_requests.get.return_value = MockResponse() - mock_load_tif.return_value = mock_data, 0.0 + mock_load_tif.return_value = xr.DataArray( + data=np.ones((24, 19, 17, 17)), dims=("time", "band", "y", "x") + ) labelled_np, closest_lon, closest_lat = _find_matching_point_url( url="https://mock", label_lon=5, label_lat=5 ) From fecf493895e75be52081d919b68297b9636ae22c Mon Sep 17 00:00:00 2001 From: ivanzvonkov Date: Sat, 24 Sep 2022 18:47:42 -0400 Subject: [PATCH 2/4] unit tests for fillna --- openmapflow/engineer.py | 18 +++++++++++--- tests/test_engineer.py | 54 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/openmapflow/engineer.py b/openmapflow/engineer.py index 1b0636fc..c0b0f0c6 100644 --- a/openmapflow/engineer.py +++ b/openmapflow/engineer.py @@ -18,20 +18,34 @@ def _fillna(data): + """Fill in the missing values in the data array""" + bands_np = np.array(DYNAMIC_BANDS + STATIC_BANDS) + if len(data.shape) != 4: + raise ValueError( + f"Expected data to be 4D (time, band, x, y) - got {data.shape}" + ) + if data.shape[1] != len(bands_np): + raise ValueError( + f"Expected data to have {len(bands_np)} bands - got {data.shape[1]}" + ) + is_nan = np.isnan(data) if not is_nan.any().item(): return data mean_per_time_band = data.mean(axis=(2, 3), skipna=True) is_nan_any = is_nan.any(axis=(0, 2, 3)).values is_nan_all = is_nan.all(axis=(0, 2, 3)).values - bands_np = np.array(DYNAMIC_BANDS + STATIC_BANDS) bands_all_nans = bands_np[is_nan_all] bands_some_nans = bands_np[is_nan_any & ~is_nan_all] if bands_all_nans.size > 0: print(f"WARNING: Bands: {bands_all_nans} have all nan values") + # If a band has all nan values, fill with default: 0 mean_per_time_band[:, is_nan_all] = 0 if bands_some_nans.size > 0: print(f"WARNING: Bands: {bands_some_nans} have some nan values") + if np.isnan(mean_per_time_band).any(): + mean_per_band = mean_per_time_band.mean(axis=0, skipna=True) + return data.fillna(mean_per_band) return data.fillna(mean_per_time_band) @@ -60,8 +74,6 @@ def load_tif( static_data = da.isel(band=slice(num_bands - len(STATIC_BANDS), num_bands)) - # average_slope = np.nanmean(static_data.values[STATIC_BANDS.index("slope"), :, :]) - for timestep in range(num_timesteps): time_specific_da = da.isel( band=slice( diff --git a/tests/test_engineer.py b/tests/test_engineer.py index c3a8a995..fdc894d6 100644 --- a/tests/test_engineer.py +++ b/tests/test_engineer.py @@ -2,16 +2,26 @@ from pathlib import Path import numpy as np +import xarray as xr from openmapflow.bands import DYNAMIC_BANDS, STATIC_BANDS -from openmapflow.engineer import load_tif, process_test_file +from openmapflow.engineer import load_tif, process_test_file, _fillna TIF_FILE = Path(__file__).parent / "98-togo_2019-02-06_2020-02-01.tif" NUM_TIMESTEPS = 12 +BANDS = DYNAMIC_BANDS + STATIC_BANDS class TestEngineer(unittest.TestCase): + def setUp(self): + data = np.ones((NUM_TIMESTEPS, len(BANDS), 17, 17)) + + # Make each band have a unique value + for i in range(len(BANDS)): + data[:, i] = data[:, i] * i + self.xr_data = xr.DataArray(data=data, dims=("time", "band", "y", "x")) + def test_load_tif_file(self): loaded_file = load_tif(TIF_FILE) @@ -32,10 +42,48 @@ def test_load_tif_file(self): # https://en.wikipedia.org/wiki/Highest_temperature_recorded_on_Earth self.assertTrue(((temperature_values) < 329.85).all()) + def test_fillna_identity(self): + self.assertTrue((self.xr_data == _fillna(self.xr_data)).all()) + + def test_fillna_wrong_shape(self): + with self.assertRaises(ValueError): + _fillna(self.xr_data[:, 0]) + with self.assertRaises(ValueError): + _fillna(self.xr_data[:, 1:5]) + + def test_fillna_missing_value(self): + self.xr_data[0, 0, 0, 0] = float("nan") + self.xr_data[5, 2, 5, 5] = float("nan") + self.xr_data[11, 10, 16, 16] = float("nan") + new_xr_data = _fillna(self.xr_data) + self.assertEqual(new_xr_data[0, 0, 0, 0], 0) + self.assertEqual(new_xr_data[5, 2, 5, 5], 2) + self.assertEqual(new_xr_data[11, 10, 16, 16], 10) + + def test_fillna_missing_band(self): + self.xr_data[:, 10, 16, 16] = float("nan") + new_xr_data = _fillna(self.xr_data) + self.assertEqual(new_xr_data[11, 10, 16, 16], 10) + + def test_fillna_missing_band_everywhere(self): + self.xr_data[:, 10, :, :] = float("nan") + new_xr_data = _fillna(self.xr_data) + self.assertEqual(new_xr_data[11, 10, 16, 16], 0) + + def test_fillna_missing_whole_timestep(self): + self.xr_data[3, :, :, :] = float("nan") + new_xr_data = _fillna(self.xr_data) + self.assertTrue((new_xr_data[3] == self.xr_data[4]).all()) + + def test_fillna_missing_everything(self): + self.xr_data[:, ::, :] = float("nan") + new_xr_data = _fillna(self.xr_data) + self.assertTrue((new_xr_data == 0).all()) + def test_fillna_real(self): - loaded_file1 = load_tif(TIF_FILE, fillnans=False) + loaded_file1 = load_tif(TIF_FILE, fillna=False) self.assertTrue(np.isnan(loaded_file1).any()) - loaded_file2 = load_tif(TIF_FILE, fillnans=True) + loaded_file2 = load_tif(TIF_FILE, fillna=True) self.assertFalse(np.isnan(loaded_file2).any()) def test_process_test_file(self): From 6a920ec537dbcd8c89c17ba78391123b2aa19bfe Mon Sep 17 00:00:00 2001 From: ivanzvonkov Date: Sat, 24 Sep 2022 19:15:46 -0400 Subject: [PATCH 3/4] Remove comment --- openmapflow/engineer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmapflow/engineer.py b/openmapflow/engineer.py index c0b0f0c6..f1b451af 100644 --- a/openmapflow/engineer.py +++ b/openmapflow/engineer.py @@ -80,7 +80,6 @@ def load_tif( timestep * bands_per_timestep, (timestep + 1) * bands_per_timestep ) ) - # time_specific_da = fillna2(time_specific_da, DYNAMIC_BANDS) time_specific_da = xr.concat([time_specific_da, static_data], "band") time_specific_da["band"] = range(bands_per_timestep + len(STATIC_BANDS)) da_split_by_time.append(time_specific_da) From ee7ced5db93b4262b64e5c7b3a0256b462ddebbf Mon Sep 17 00:00:00 2001 From: ivanzvonkov Date: Mon, 3 Oct 2022 09:56:22 -0400 Subject: [PATCH 4/4] isort --- tests/test_engineer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_engineer.py b/tests/test_engineer.py index fdc894d6..13b5d468 100644 --- a/tests/test_engineer.py +++ b/tests/test_engineer.py @@ -5,7 +5,7 @@ import xarray as xr from openmapflow.bands import DYNAMIC_BANDS, STATIC_BANDS -from openmapflow.engineer import load_tif, process_test_file, _fillna +from openmapflow.engineer import _fillna, load_tif, process_test_file TIF_FILE = Path(__file__).parent / "98-togo_2019-02-06_2020-02-01.tif"