1919Tests on Black marble.
2020"""
2121
22- import unittest
23- import os
22+ import gzip
23+ import io
24+ from pathlib import Path
2425import tarfile
26+ from tempfile import TemporaryDirectory
27+ import unittest
28+
2529import affine
2630import numpy as np
2731import scipy .sparse as sparse
28-
32+ from PIL import Image
2933from shapely .geometry import Polygon
30- from pathlib import Path
31- from tempfile import TemporaryDirectory
3234from osgeo import gdal
35+
3336from climada .entity .exposures .litpop import nightlight
3437from climada .util .constants import (SYSTEM_DIR , CONFIG )
3538from climada .util import (files_handler , ureg )
3841NOAA_RESOLUTION_DEG = (30 * ureg .arc_second ).to (ureg .deg ).magnitude
3942
4043def init_test_shape ():
44+ """provide a rectangular shape"""
4145 bounds = (14.18 , 35.78 , 14.58 , 36.09 )
4246 # (min_lon, max_lon, min_lat, max_lat)
4347
@@ -52,7 +56,7 @@ class TestNightlight(unittest.TestCase):
5256 """Test litpop.nightlight"""
5357
5458 def test_load_nasa_nl_shape_single_tile (self ):
55- """ Test that the function returns a np.ndarray containing
59+ """ Test that the function returns a np.ndarray containing
5660 the cropped .tif image values. Test that
5761 just one layer is returned. """
5862
@@ -63,28 +67,28 @@ def test_load_nasa_nl_shape_single_tile(self):
6367 # Test cropped output
6468 out_image , meta = nightlight .load_nasa_nl_shape_single_tile (geometry = shape , path = path )
6569 self .assertIsInstance (out_image , np .ndarray )
66- self .assertEqual (len (out_image .shape ), 2 )
70+ self .assertEqual (len (out_image .shape ), 2 )
6771
6872 # Test meta ouput
6973 self .assertEqual (meta ['height' ],out_image .shape [0 ])
7074 self .assertEqual (meta ['width' ],out_image .shape [1 ])
7175 self .assertEqual (meta ['driver' ], 'GTiff' )
72- self .assertEqual (meta ['transform' ], affine .Affine (0.004166666666666667 , 0.0 , 14.179166666666667 ,
73- 0.0 , - 0.004166666666666667 , 36.09166666666667 ))
76+ self .assertEqual (meta ['transform' ], affine .Affine (0.004166666666666667 , 0.0 ,
77+ 14.179166666666667 , 0.0 , - 0.004166666666666667 , 36.09166666666667 ))
7478 # Test raises
7579 with self .assertRaises (IndexError ) as cm :
7680 nightlight .load_nasa_nl_shape_single_tile (geometry = shape , path = path , layer = 4 )
77- self .assertEqual ("BlackMarble_2016_C1_geo_gray.tif has only 3 layers, layer 4 can't be accessed." ,
78- str (cm .exception ))
81+ self .assertEqual ("BlackMarble_2016_C1_geo_gray.tif has only 3 layers,"
82+ " layer 4 can't be accessed." , str (cm .exception ))
7983 # Test logger
8084 with self .assertLogs ('climada.entity.exposures.litpop.nightlight' , level = 'DEBUG' ) as cm :
8185 nightlight .load_nasa_nl_shape_single_tile (geometry = shape , path = path )
8286 self .assertIn ('Read cropped BlackMarble_2016_C1_geo_gray.tif as np.ndarray.' , cm .output [0 ])
83-
87+
8488 def test_read_bm_files (self ):
8589 """" Test that read_bm_files function read NASA BlackMarble GeoTiff and output
8690 an array and a gdal DataSet."""
87-
91+
8892 # Download 'BlackMarble_2016_A1_geo_gray.tif' in the temporary directory and create a path
8993 temp_dir = TemporaryDirectory ()
9094 urls = CONFIG .exposures .litpop .nightlights .nasa_sites .list ()
@@ -114,7 +118,7 @@ def test_read_bm_files(self):
114118
115119 def test_download_nl_files (self ):
116120 """ Test that BlackMarble GeoTiff files are downloaded. """
117-
121+
118122 # Test Raises
119123 temp_dir = TemporaryDirectory ()
120124 with self .assertRaises (ValueError ) as cm :
@@ -148,86 +152,106 @@ def test_download_nl_files(self):
148152 temp_dir .cleanup ()
149153
150154 def test_unzip_tif_to_py (self ):
151- """ Test that .gz files are unzipped and read as a sparse matrix,
155+ """ Test that .gz files are unzipped and read as a sparse matrix,
152156 file_name is correct and logger message recorded. """
153157
154- path_file_tif_gz = str (Path ( SYSTEM_DIR , 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' ))
158+ path_file_tif_gz = str (SYSTEM_DIR . joinpath ( 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' ))
155159 with self .assertLogs ('climada.entity.exposures.litpop.nightlight' , level = 'INFO' ) as cm :
156160 file_name , night = nightlight .unzip_tif_to_py (path_file_tif_gz )
157161 self .assertIn (f'Unzipping file { path_file_tif_gz } ' , cm .output [0 ])
158162 self .assertEqual (str (file_name ), 'F182013.v4c_web.stable_lights.avg_vis.tif' )
159163 self .assertIsInstance (night , sparse ._csr .csr_matrix )
160- os . remove ( Path ( SYSTEM_DIR , 'F182013.v4c_web.stable_lights.avg_vis.p' ))
164+ SYSTEM_DIR . joinpath ( 'F182013.v4c_web.stable_lights.avg_vis.p' ). unlink ( )
161165
162166 def test_load_nightlight_noaa (self ):
163- """ Test that data is downloaded if not present in SYSTEM_DIR,
164- or not downloaded if present. Test the three outputs of the
165- function."""
166-
167- # Using an already existing file and without providing arguments
167+ """ Test that data is not downloaded if a .tif.gz file is present
168+ in SYSTEM_DIR. """
169+
170+ # initialization
171+ sat_name = 'E99'
172+ year = 2013
173+ pattern = f"{ sat_name } { year } .v4c_web.stable_lights.avg_vis"
174+ gzfile = f"{ pattern } .tif.gz"
175+ pfile = f"{ pattern } .p"
176+ tiffile = f"{ pattern } .tif"
177+
178+ # create an empty image
179+ image = np .zeros ((100 , 100 ), dtype = np .uint8 )
180+ pilim = Image .fromarray (image )
181+
182+ # save the image as .tif.gz
183+ with io .BytesIO () as mem :
184+ pilim .save (mem , "tiff" )
185+ # compressed image to a gzip file
186+ with gzip .GzipFile (SYSTEM_DIR .joinpath (gzfile ), 'wb' ) as f :
187+ f .write (mem .getvalue ())
188+ SYSTEM_DIR .joinpath (pfile ).unlink (missing_ok = True )
189+
190+ # using already existing file and without providing arguments
168191 night , coord_nl , fn_light = nightlight .load_nightlight_noaa ()
169192 self .assertIsInstance (night , sparse ._csr .csr_matrix )
170- self .assertIn ('F182013.v4c_web.stable_lights.avg_vis.tif' , str (fn_light ))
193+ self .assertIn (tiffile , str (fn_light ))
171194 self .assertTrue (np .array_equal (np .array ([[- 65 , NOAA_RESOLUTION_DEG ],
172195 [- 180 , NOAA_RESOLUTION_DEG ]]),coord_nl ))
173- os .remove (SYSTEM_DIR .joinpath ('F182013.v4c_web.stable_lights.avg_vis.p' ))
174- # With arguments
175- night , coord_nl , fn_light = nightlight .load_nightlight_noaa (ref_year = 2010 , sat_name = 'F18' )
196+ SYSTEM_DIR .joinpath (pfile ).unlink ()
197+
198+ # with arguments
199+ night , coord_nl , fn_light = nightlight .load_nightlight_noaa (ref_year = year , sat_name = sat_name )
176200 self .assertIsInstance (night , sparse ._csr .csr_matrix )
177- self .assertIn ('F182010.v4d_web.stable_lights.avg_vis' , str (fn_light ))
178- file = str ( SYSTEM_DIR .joinpath ('F182010.v4d_web.stable_lights.avg_vis.p' ))
179- os . remove ( file )
201+ self .assertIn (tiffile , str (fn_light ))
202+ SYSTEM_DIR .joinpath (pfile ). unlink ()
203+ SYSTEM_DIR . joinpath ( gzfile ). unlink ( )
180204
181- # Test raises from wrong input agruments
205+ # test raises from wrong input agruments
182206 with self .assertRaises (ValueError ) as cm :
183207 night , coord_nl , fn_light = nightlight .load_nightlight_noaa (
184- ref_year = 2050 , sat_name = 'F150' )
185- self .assertEqual ('Nightlight intensities for year 2050 and satellite F150 do not exist.' ,
208+ ref_year = 2050 , sat_name = 'F150' )
209+ self .assertEqual ('Nightlight intensities for year 2050 and satellite F150 do not exist.' ,
186210 str (cm .exception ))
187211
188212 def test_untar_noaa_stable_nighlight (self ):
189- """ Testing that input .tar file is moved into SYSTEM_DIR,
190- tif.gz file is extracted from .tar file and moved into SYSTEM_DIR,
213+ """ Testing that input .tar file is moved into SYSTEM_DIR,
214+ tif.gz file is extracted from .tar file and moved into SYSTEM_DIR,
191215 exception are raised when no .tif.gz file is present in the tar file,
192- and the logger message is recorded if more then one .tif.gz is present in
216+ and the logger message is recorded if more then one .tif.gz is present in
193217 .tar file. """
194218
195219 # Create path to .tif.gz and .csv files already existing in SYSTEM_DIR
196- path_tif_gz_1 = Path (SYSTEM_DIR , 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
197- path_csv = Path (SYSTEM_DIR , 'GDP_TWN_IMF_WEO_data.csv' )
198- path_tar = Path (SYSTEM_DIR , 'sample.tar' )
220+ path_tif_gz_1 = Path (SYSTEM_DIR , 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
221+ path_csv = Path (SYSTEM_DIR , 'GDP_TWN_IMF_WEO_data.csv' )
222+ path_tar = Path (SYSTEM_DIR , 'sample.tar' )
199223
200- # Create .tar file and add .tif.gz and .csv
224+ # Create .tar file and add .tif.gz and .csv
201225 file_tar = tarfile .open (path_tar , "w" ) #create the tar file
202- file_tar .add (name = path_tif_gz_1 , recursive = False , arcname = 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
226+ file_tar .add (name = path_tif_gz_1 , recursive = False , arcname = 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
203227 file_tar .close ()
204228
205229 # Test that the files has been moved
206230 path_to_test = nightlight .untar_noaa_stable_nightlight (path_tar )
207231 self .assertTrue (path_to_test .exists ())
208232 self .assertTrue (path_tar .exists ())
209- os . remove ( path_tar )
233+ path_tar . unlink ( )
210234
211235 # Put no .tif.gz file in .tar file and check raises
212- path_tar = Path (SYSTEM_DIR , 'sample.tar' )
236+ path_tar = Path (SYSTEM_DIR , 'sample.tar' )
213237 file_tar = tarfile .open (path_tar , "w" ) #create the tar file
214- file_tar .add (name = path_csv , recursive = False , arcname = 'GDP_TWN_IMF_WEO_data.csv' )
238+ file_tar .add (name = path_csv , recursive = False , arcname = 'GDP_TWN_IMF_WEO_data.csv' )
215239 file_tar .close ()
216240 with self .assertRaises (ValueError ) as cm :
217241 nightlight .untar_noaa_stable_nightlight (path_tar )
218242 self .assertEqual ('No stable light intensities for selected year and satellite '
219243 f'in file { path_tar } ' ,str (cm .exception ))
220- os . remove ( path_tar )
244+ path_tar . unlink ( )
221245
222- # Test logger with having two .tif.gz file in .tar file
246+ # Test logger with having two .tif.gz file in .tar file
223247 file_tar = tarfile .open (path_tar , "w" ) #create the tar file
224- file_tar .add (name = path_tif_gz_1 , recursive = False , arcname = 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
225- file_tar .add (name = path_tif_gz_1 , recursive = False , arcname = 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
248+ file_tar .add (name = path_tif_gz_1 , recursive = False , arcname = 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
249+ file_tar .add (name = path_tif_gz_1 , recursive = False , arcname = 'F182013.v4c_web.stable_lights.avg_vis.tif.gz' )
226250 file_tar .close ()
227251 with self .assertLogs ('climada.entity.exposures.litpop.nightlight' , level = 'WARNING' ) as cm :
228252 nightlight .untar_noaa_stable_nightlight (path_tar )
229253 self .assertIn ('found more than one potential intensity file in' , cm .output [0 ])
230- os . remove ( path_tar )
254+ path_tar . unlink ( )
231255
232256# Execute Tests
233257if __name__ == "__main__" :
0 commit comments