cloudnetpy 1.49.9__py3-none-any.whl → 1.87.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudnetpy/categorize/__init__.py +1 -2
- cloudnetpy/categorize/atmos_utils.py +297 -67
- cloudnetpy/categorize/attenuation.py +31 -0
- cloudnetpy/categorize/attenuations/__init__.py +37 -0
- cloudnetpy/categorize/attenuations/gas_attenuation.py +30 -0
- cloudnetpy/categorize/attenuations/liquid_attenuation.py +84 -0
- cloudnetpy/categorize/attenuations/melting_attenuation.py +78 -0
- cloudnetpy/categorize/attenuations/rain_attenuation.py +84 -0
- cloudnetpy/categorize/categorize.py +332 -156
- cloudnetpy/categorize/classify.py +127 -125
- cloudnetpy/categorize/containers.py +107 -76
- cloudnetpy/categorize/disdrometer.py +40 -0
- cloudnetpy/categorize/droplet.py +23 -21
- cloudnetpy/categorize/falling.py +53 -24
- cloudnetpy/categorize/freezing.py +25 -12
- cloudnetpy/categorize/insects.py +35 -23
- cloudnetpy/categorize/itu.py +243 -0
- cloudnetpy/categorize/lidar.py +36 -41
- cloudnetpy/categorize/melting.py +34 -26
- cloudnetpy/categorize/model.py +84 -37
- cloudnetpy/categorize/mwr.py +18 -14
- cloudnetpy/categorize/radar.py +215 -102
- cloudnetpy/cli.py +578 -0
- cloudnetpy/cloudnetarray.py +43 -89
- cloudnetpy/concat_lib.py +218 -78
- cloudnetpy/constants.py +28 -10
- cloudnetpy/datasource.py +61 -86
- cloudnetpy/exceptions.py +49 -20
- cloudnetpy/instruments/__init__.py +5 -0
- cloudnetpy/instruments/basta.py +29 -12
- cloudnetpy/instruments/bowtie.py +135 -0
- cloudnetpy/instruments/ceilo.py +138 -115
- cloudnetpy/instruments/ceilometer.py +164 -80
- cloudnetpy/instruments/cl61d.py +21 -5
- cloudnetpy/instruments/cloudnet_instrument.py +74 -36
- cloudnetpy/instruments/copernicus.py +108 -30
- cloudnetpy/instruments/da10.py +54 -0
- cloudnetpy/instruments/disdrometer/common.py +126 -223
- cloudnetpy/instruments/disdrometer/parsivel.py +453 -94
- cloudnetpy/instruments/disdrometer/thies.py +254 -87
- cloudnetpy/instruments/fd12p.py +201 -0
- cloudnetpy/instruments/galileo.py +65 -23
- cloudnetpy/instruments/hatpro.py +123 -49
- cloudnetpy/instruments/instruments.py +113 -1
- cloudnetpy/instruments/lufft.py +39 -17
- cloudnetpy/instruments/mira.py +268 -61
- cloudnetpy/instruments/mrr.py +187 -0
- cloudnetpy/instruments/nc_lidar.py +19 -8
- cloudnetpy/instruments/nc_radar.py +109 -55
- cloudnetpy/instruments/pollyxt.py +135 -51
- cloudnetpy/instruments/radiometrics.py +313 -59
- cloudnetpy/instruments/rain_e_h3.py +171 -0
- cloudnetpy/instruments/rpg.py +321 -189
- cloudnetpy/instruments/rpg_reader.py +74 -40
- cloudnetpy/instruments/toa5.py +49 -0
- cloudnetpy/instruments/vaisala.py +95 -343
- cloudnetpy/instruments/weather_station.py +774 -105
- cloudnetpy/metadata.py +90 -19
- cloudnetpy/model_evaluation/file_handler.py +55 -52
- cloudnetpy/model_evaluation/metadata.py +46 -20
- cloudnetpy/model_evaluation/model_metadata.py +1 -1
- cloudnetpy/model_evaluation/plotting/plot_tools.py +32 -37
- cloudnetpy/model_evaluation/plotting/plotting.py +327 -117
- cloudnetpy/model_evaluation/products/advance_methods.py +92 -83
- cloudnetpy/model_evaluation/products/grid_methods.py +88 -63
- cloudnetpy/model_evaluation/products/model_products.py +43 -35
- cloudnetpy/model_evaluation/products/observation_products.py +41 -35
- cloudnetpy/model_evaluation/products/product_resampling.py +17 -7
- cloudnetpy/model_evaluation/products/tools.py +29 -20
- cloudnetpy/model_evaluation/statistics/statistical_methods.py +30 -20
- cloudnetpy/model_evaluation/tests/e2e/conftest.py +3 -3
- cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +9 -5
- cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +15 -14
- cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +9 -5
- cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +15 -14
- cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +9 -5
- cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +15 -14
- cloudnetpy/model_evaluation/tests/unit/conftest.py +42 -41
- cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +41 -48
- cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +216 -194
- cloudnetpy/model_evaluation/tests/unit/test_model_products.py +23 -21
- cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +37 -38
- cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +43 -40
- cloudnetpy/model_evaluation/tests/unit/test_plotting.py +30 -36
- cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +68 -31
- cloudnetpy/model_evaluation/tests/unit/test_tools.py +33 -26
- cloudnetpy/model_evaluation/utils.py +2 -1
- cloudnetpy/output.py +170 -111
- cloudnetpy/plotting/__init__.py +2 -1
- cloudnetpy/plotting/plot_meta.py +562 -822
- cloudnetpy/plotting/plotting.py +1142 -704
- cloudnetpy/products/__init__.py +1 -0
- cloudnetpy/products/classification.py +370 -88
- cloudnetpy/products/der.py +85 -55
- cloudnetpy/products/drizzle.py +77 -34
- cloudnetpy/products/drizzle_error.py +15 -11
- cloudnetpy/products/drizzle_tools.py +79 -59
- cloudnetpy/products/epsilon.py +211 -0
- cloudnetpy/products/ier.py +27 -50
- cloudnetpy/products/iwc.py +55 -48
- cloudnetpy/products/lwc.py +96 -70
- cloudnetpy/products/mwr_tools.py +186 -0
- cloudnetpy/products/product_tools.py +170 -128
- cloudnetpy/utils.py +455 -240
- cloudnetpy/version.py +2 -2
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info}/METADATA +44 -40
- cloudnetpy-1.87.3.dist-info/RECORD +127 -0
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info}/WHEEL +1 -1
- cloudnetpy-1.87.3.dist-info/entry_points.txt +2 -0
- docs/source/conf.py +2 -2
- cloudnetpy/categorize/atmos.py +0 -361
- cloudnetpy/products/mwr_multi.py +0 -68
- cloudnetpy/products/mwr_single.py +0 -75
- cloudnetpy-1.49.9.dist-info/RECORD +0 -112
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info/licenses}/LICENSE +0 -0
- {cloudnetpy-1.49.9.dist-info → cloudnetpy-1.87.3.dist-info}/top_level.txt +0 -0
|
@@ -15,11 +15,15 @@ test_file_model = (
|
|
|
15
15
|
test_file_product = f"{ROOT_PATH}/cloudnetpy/model_evaluation/tests/data/20190517_mace-head_categorize.nc"
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def _process():
|
|
18
|
+
def _process() -> None:
|
|
19
19
|
tmp_dir = TemporaryDirectory()
|
|
20
20
|
temp_file = f"{tmp_dir.name}/xx.nc"
|
|
21
21
|
product_resampling.process_L3_day_product(
|
|
22
|
-
"ecmwf",
|
|
22
|
+
"ecmwf",
|
|
23
|
+
"cf",
|
|
24
|
+
[test_file_model],
|
|
25
|
+
test_file_product,
|
|
26
|
+
temp_file,
|
|
23
27
|
)
|
|
24
28
|
try:
|
|
25
29
|
subprocess.call(
|
|
@@ -29,20 +33,20 @@ def _process():
|
|
|
29
33
|
f"{SCRIPT_PATH}/tests.py",
|
|
30
34
|
"--full_path",
|
|
31
35
|
temp_file,
|
|
32
|
-
]
|
|
36
|
+
],
|
|
33
37
|
)
|
|
34
38
|
except subprocess.CalledProcessError:
|
|
35
39
|
raise
|
|
36
40
|
tmp_dir.cleanup()
|
|
37
41
|
|
|
38
42
|
|
|
39
|
-
def main():
|
|
43
|
+
def main() -> None:
|
|
40
44
|
_process()
|
|
41
45
|
|
|
42
46
|
|
|
43
47
|
if __name__ == "__main__":
|
|
44
48
|
parser = argparse.ArgumentParser(
|
|
45
|
-
description="Model evaluation Cloud fraction processing e2e test."
|
|
49
|
+
description="Model evaluation Cloud fraction processing e2e test.",
|
|
46
50
|
)
|
|
47
51
|
ARGS = parser.parse_args()
|
|
48
52
|
main()
|
|
@@ -6,18 +6,18 @@ class TestCloudFractionProcessing:
|
|
|
6
6
|
product = "cf"
|
|
7
7
|
|
|
8
8
|
@pytest.fixture(autouse=True)
|
|
9
|
-
def _fetch_params(self, params):
|
|
9
|
+
def _fetch_params(self, params) -> None:
|
|
10
10
|
self.full_path = params["full_path"]
|
|
11
11
|
|
|
12
|
-
@pytest.mark.reprocess
|
|
13
|
-
def test_that_has_correct_attributes(self):
|
|
12
|
+
@pytest.mark.reprocess()
|
|
13
|
+
def test_that_has_correct_attributes(self) -> None:
|
|
14
14
|
nc = netCDF4.Dataset(self.full_path)
|
|
15
15
|
assert nc.location == "Mace-Head"
|
|
16
16
|
assert nc.year == "2019"
|
|
17
17
|
assert nc.month == "05"
|
|
18
18
|
assert nc.day == "17"
|
|
19
19
|
assert nc.title == "Downsampled Cf of ecmwf from Mace-Head"
|
|
20
|
-
assert nc.cloudnet_file_type == "
|
|
20
|
+
assert nc.cloudnet_file_type == "l3-cf"
|
|
21
21
|
assert nc.Conventions == "CF-1.8"
|
|
22
22
|
assert (
|
|
23
23
|
nc.source
|
|
@@ -25,31 +25,32 @@ class TestCloudFractionProcessing:
|
|
|
25
25
|
)
|
|
26
26
|
nc.close()
|
|
27
27
|
|
|
28
|
-
@pytest.mark.reprocess
|
|
28
|
+
@pytest.mark.reprocess()
|
|
29
29
|
@pytest.mark.parametrize(
|
|
30
|
-
"key",
|
|
30
|
+
"key",
|
|
31
|
+
["cf_V_ecmwf", "cf_A_ecmwf", "cf_V_adv_ecmwf", "cf_A_adv_ecmwf"],
|
|
31
32
|
)
|
|
32
|
-
def test_that_has_correct_product_variables(self, key):
|
|
33
|
+
def test_that_has_correct_product_variables(self, key) -> None:
|
|
33
34
|
nc = netCDF4.Dataset(self.full_path)
|
|
34
|
-
assert key in nc.variables
|
|
35
|
+
assert key in nc.variables
|
|
35
36
|
nc.close()
|
|
36
37
|
|
|
37
|
-
@pytest.mark.reprocess
|
|
38
|
+
@pytest.mark.reprocess()
|
|
38
39
|
@pytest.mark.parametrize(
|
|
39
40
|
"key",
|
|
40
41
|
["time", "level", "latitude", "longitude", "horizontal_resolution"],
|
|
41
42
|
)
|
|
42
|
-
def test_that_has_correct_model_variables(self, key):
|
|
43
|
+
def test_that_has_correct_model_variables(self, key) -> None:
|
|
43
44
|
nc = netCDF4.Dataset(self.full_path)
|
|
44
|
-
assert key in nc.variables
|
|
45
|
+
assert key in nc.variables
|
|
45
46
|
nc.close()
|
|
46
47
|
|
|
47
|
-
@pytest.mark.reprocess
|
|
48
|
+
@pytest.mark.reprocess()
|
|
48
49
|
@pytest.mark.parametrize(
|
|
49
50
|
"key",
|
|
50
51
|
["ecmwf_forecast_time", "ecmwf_height", "ecmwf_cf", "ecmwf_cf_cirrus"],
|
|
51
52
|
)
|
|
52
|
-
def test_that_has_correct_cycle_variables(self, key):
|
|
53
|
+
def test_that_has_correct_cycle_variables(self, key) -> None:
|
|
53
54
|
nc = netCDF4.Dataset(self.full_path)
|
|
54
|
-
assert key in nc.variables
|
|
55
|
+
assert key in nc.variables
|
|
55
56
|
nc.close()
|
|
@@ -19,11 +19,15 @@ test_file_model = (
|
|
|
19
19
|
test_file_product = f"{ROOT_PATH}/cloudnetpy/model_evaluation/tests/data/20190517_mace-head_iwc-Z-T-method.nc"
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def _process():
|
|
22
|
+
def _process() -> None:
|
|
23
23
|
tmp_dir = TemporaryDirectory()
|
|
24
24
|
temp_file = f"{tmp_dir.name}/xx.nc"
|
|
25
25
|
product_resampling.process_L3_day_product(
|
|
26
|
-
"ecmwf",
|
|
26
|
+
"ecmwf",
|
|
27
|
+
"iwc",
|
|
28
|
+
[test_file_model],
|
|
29
|
+
test_file_product,
|
|
30
|
+
temp_file,
|
|
27
31
|
)
|
|
28
32
|
try:
|
|
29
33
|
subprocess.call(
|
|
@@ -33,20 +37,20 @@ def _process():
|
|
|
33
37
|
f"{SCRIPT_PATH}/tests.py",
|
|
34
38
|
"--full_path",
|
|
35
39
|
temp_file,
|
|
36
|
-
]
|
|
40
|
+
],
|
|
37
41
|
)
|
|
38
42
|
except subprocess.CalledProcessError:
|
|
39
43
|
raise
|
|
40
44
|
tmp_dir.cleanup()
|
|
41
45
|
|
|
42
46
|
|
|
43
|
-
def main():
|
|
47
|
+
def main() -> None:
|
|
44
48
|
_process()
|
|
45
49
|
|
|
46
50
|
|
|
47
51
|
if __name__ == "__main__":
|
|
48
52
|
parser = argparse.ArgumentParser(
|
|
49
|
-
description="Model evaluation Ice water content processing e2e test."
|
|
53
|
+
description="Model evaluation Ice water content processing e2e test.",
|
|
50
54
|
)
|
|
51
55
|
ARGS = parser.parse_args()
|
|
52
56
|
main()
|
|
@@ -6,18 +6,18 @@ class TestCloudFractionProcessing:
|
|
|
6
6
|
product = "iwc"
|
|
7
7
|
|
|
8
8
|
@pytest.fixture(autouse=True)
|
|
9
|
-
def _fetch_params(self, params):
|
|
9
|
+
def _fetch_params(self, params) -> None:
|
|
10
10
|
self.full_path = params["full_path"]
|
|
11
11
|
|
|
12
|
-
@pytest.mark.reprocess
|
|
13
|
-
def test_that_has_correct_attributes(self):
|
|
12
|
+
@pytest.mark.reprocess()
|
|
13
|
+
def test_that_has_correct_attributes(self) -> None:
|
|
14
14
|
nc = netCDF4.Dataset(self.full_path)
|
|
15
15
|
assert nc.location == "Mace-Head"
|
|
16
16
|
assert nc.year == "2019"
|
|
17
17
|
assert nc.month == "05"
|
|
18
18
|
assert nc.day == "17"
|
|
19
19
|
assert nc.title == "Downsampled Iwc of ecmwf from Mace-Head"
|
|
20
|
-
assert nc.cloudnet_file_type == "
|
|
20
|
+
assert nc.cloudnet_file_type == "l3-iwc"
|
|
21
21
|
assert nc.Conventions == "CF-1.8"
|
|
22
22
|
assert (
|
|
23
23
|
nc.source
|
|
@@ -25,7 +25,7 @@ class TestCloudFractionProcessing:
|
|
|
25
25
|
)
|
|
26
26
|
nc.close()
|
|
27
27
|
|
|
28
|
-
@pytest.mark.reprocess
|
|
28
|
+
@pytest.mark.reprocess()
|
|
29
29
|
@pytest.mark.parametrize(
|
|
30
30
|
"key",
|
|
31
31
|
[
|
|
@@ -37,26 +37,27 @@ class TestCloudFractionProcessing:
|
|
|
37
37
|
"iwc_rain_adv_ecmwf",
|
|
38
38
|
],
|
|
39
39
|
)
|
|
40
|
-
def test_that_has_correct_product_variables(self, key):
|
|
40
|
+
def test_that_has_correct_product_variables(self, key) -> None:
|
|
41
41
|
nc = netCDF4.Dataset(self.full_path)
|
|
42
|
-
assert key in nc.variables
|
|
42
|
+
assert key in nc.variables
|
|
43
43
|
nc.close()
|
|
44
44
|
|
|
45
|
-
@pytest.mark.reprocess
|
|
45
|
+
@pytest.mark.reprocess()
|
|
46
46
|
@pytest.mark.parametrize(
|
|
47
47
|
"key",
|
|
48
48
|
["time", "level", "latitude", "longitude", "horizontal_resolution"],
|
|
49
49
|
)
|
|
50
|
-
def test_that_has_correct_model_variables(self, key):
|
|
50
|
+
def test_that_has_correct_model_variables(self, key) -> None:
|
|
51
51
|
nc = netCDF4.Dataset(self.full_path)
|
|
52
|
-
assert key in nc.variables
|
|
52
|
+
assert key in nc.variables
|
|
53
53
|
nc.close()
|
|
54
54
|
|
|
55
|
-
@pytest.mark.reprocess
|
|
55
|
+
@pytest.mark.reprocess()
|
|
56
56
|
@pytest.mark.parametrize(
|
|
57
|
-
"key",
|
|
57
|
+
"key",
|
|
58
|
+
["ecmwf_forecast_time", "ecmwf_height", "ecmwf_iwc"],
|
|
58
59
|
)
|
|
59
|
-
def test_that_has_correct_cycle_variables(self, key):
|
|
60
|
+
def test_that_has_correct_cycle_variables(self, key) -> None:
|
|
60
61
|
nc = netCDF4.Dataset(self.full_path)
|
|
61
|
-
assert key in nc.variables
|
|
62
|
+
assert key in nc.variables
|
|
62
63
|
nc.close()
|
|
@@ -15,11 +15,15 @@ test_file_model = (
|
|
|
15
15
|
test_file_product = f"{ROOT_PATH}/cloudnetpy/model_evaluation/tests/data/20190517_mace-head_lwc-scaled-adiabatic.nc"
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def _process():
|
|
18
|
+
def _process() -> None:
|
|
19
19
|
tmp_dir = TemporaryDirectory()
|
|
20
20
|
temp_file = f"{tmp_dir.name}/xx.nc"
|
|
21
21
|
product_resampling.process_L3_day_product(
|
|
22
|
-
"ecmwf",
|
|
22
|
+
"ecmwf",
|
|
23
|
+
"lwc",
|
|
24
|
+
[test_file_model],
|
|
25
|
+
test_file_product,
|
|
26
|
+
temp_file,
|
|
23
27
|
)
|
|
24
28
|
try:
|
|
25
29
|
subprocess.call(
|
|
@@ -29,20 +33,20 @@ def _process():
|
|
|
29
33
|
f"{SCRIPT_PATH}/tests.py",
|
|
30
34
|
"--full_path",
|
|
31
35
|
temp_file,
|
|
32
|
-
]
|
|
36
|
+
],
|
|
33
37
|
)
|
|
34
38
|
except subprocess.CalledProcessError:
|
|
35
39
|
raise
|
|
36
40
|
tmp_dir.cleanup()
|
|
37
41
|
|
|
38
42
|
|
|
39
|
-
def main():
|
|
43
|
+
def main() -> None:
|
|
40
44
|
_process()
|
|
41
45
|
|
|
42
46
|
|
|
43
47
|
if __name__ == "__main__":
|
|
44
48
|
parser = argparse.ArgumentParser(
|
|
45
|
-
description="Model evaluation liquid water content processing e2e test."
|
|
49
|
+
description="Model evaluation liquid water content processing e2e test.",
|
|
46
50
|
)
|
|
47
51
|
ARGS = parser.parse_args()
|
|
48
52
|
main()
|
|
@@ -6,18 +6,18 @@ class TestCloudFractionProcessing:
|
|
|
6
6
|
product = "lwc"
|
|
7
7
|
|
|
8
8
|
@pytest.fixture(autouse=True)
|
|
9
|
-
def _fetch_params(self, params):
|
|
9
|
+
def _fetch_params(self, params) -> None:
|
|
10
10
|
self.full_path = params["full_path"]
|
|
11
11
|
|
|
12
|
-
@pytest.mark.reprocess
|
|
13
|
-
def test_that_has_correct_attributes(self):
|
|
12
|
+
@pytest.mark.reprocess()
|
|
13
|
+
def test_that_has_correct_attributes(self) -> None:
|
|
14
14
|
nc = netCDF4.Dataset(self.full_path)
|
|
15
15
|
assert nc.location == "Mace-Head"
|
|
16
16
|
assert nc.year == "2019"
|
|
17
17
|
assert nc.month == "05"
|
|
18
18
|
assert nc.day == "17"
|
|
19
19
|
assert nc.title == "Downsampled Lwc of ecmwf from Mace-Head"
|
|
20
|
-
assert nc.cloudnet_file_type == "
|
|
20
|
+
assert nc.cloudnet_file_type == "l3-lwc"
|
|
21
21
|
assert nc.Conventions == "CF-1.8"
|
|
22
22
|
assert (
|
|
23
23
|
nc.source
|
|
@@ -25,28 +25,29 @@ class TestCloudFractionProcessing:
|
|
|
25
25
|
)
|
|
26
26
|
nc.close()
|
|
27
27
|
|
|
28
|
-
@pytest.mark.reprocess
|
|
28
|
+
@pytest.mark.reprocess()
|
|
29
29
|
@pytest.mark.parametrize("key", ["lwc_ecmwf", "lwc_adv_ecmwf"])
|
|
30
|
-
def test_that_has_correct_product_variables(self, key):
|
|
30
|
+
def test_that_has_correct_product_variables(self, key) -> None:
|
|
31
31
|
nc = netCDF4.Dataset(self.full_path)
|
|
32
|
-
assert key in nc.variables
|
|
32
|
+
assert key in nc.variables
|
|
33
33
|
nc.close()
|
|
34
34
|
|
|
35
|
-
@pytest.mark.reprocess
|
|
35
|
+
@pytest.mark.reprocess()
|
|
36
36
|
@pytest.mark.parametrize(
|
|
37
37
|
"key",
|
|
38
38
|
["time", "level", "latitude", "longitude", "horizontal_resolution"],
|
|
39
39
|
)
|
|
40
|
-
def test_that_has_correct_model_variables(self, key):
|
|
40
|
+
def test_that_has_correct_model_variables(self, key) -> None:
|
|
41
41
|
nc = netCDF4.Dataset(self.full_path)
|
|
42
|
-
assert key in nc.variables
|
|
42
|
+
assert key in nc.variables
|
|
43
43
|
nc.close()
|
|
44
44
|
|
|
45
|
-
@pytest.mark.reprocess
|
|
45
|
+
@pytest.mark.reprocess()
|
|
46
46
|
@pytest.mark.parametrize(
|
|
47
|
-
"key",
|
|
47
|
+
"key",
|
|
48
|
+
["ecmwf_forecast_time", "ecmwf_height", "ecmwf_lwc"],
|
|
48
49
|
)
|
|
49
|
-
def test_that_has_correct_cycle_variables(self, key):
|
|
50
|
+
def test_that_has_correct_cycle_variables(self, key) -> None:
|
|
50
51
|
nc = netCDF4.Dataset(self.full_path)
|
|
51
|
-
assert key in nc.variables
|
|
52
|
+
assert key in nc.variables
|
|
52
53
|
nc.close()
|
|
@@ -3,10 +3,11 @@ from datetime import date
|
|
|
3
3
|
import netCDF4
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pytest
|
|
6
|
+
from numpy import ma
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
@pytest.fixture(scope="session")
|
|
9
|
-
def file_metadata():
|
|
10
|
+
def file_metadata() -> dict:
|
|
10
11
|
year, month, day = "2019", "05", "23"
|
|
11
12
|
return {
|
|
12
13
|
"year": year,
|
|
@@ -19,7 +20,7 @@ def file_metadata():
|
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
@pytest.fixture(scope="session")
|
|
22
|
-
def model_file(tmpdir_factory, file_metadata):
|
|
23
|
+
def model_file(tmpdir_factory, file_metadata) -> str:
|
|
23
24
|
file_name = tmpdir_factory.mktemp("data").join("file.nc")
|
|
24
25
|
root_grp = netCDF4.Dataset(file_name, "w", format="NETCDF4_CLASSIC")
|
|
25
26
|
time = 3
|
|
@@ -28,7 +29,7 @@ def model_file(tmpdir_factory, file_metadata):
|
|
|
28
29
|
root_grp.createDimension("level", level)
|
|
29
30
|
_create_global_attributes(root_grp, file_metadata)
|
|
30
31
|
var = root_grp.createVariable("time", "f8", "time")
|
|
31
|
-
var[:] =
|
|
32
|
+
var[:] = ma.array([2, 6, 10])
|
|
32
33
|
var = root_grp.createVariable("level", "f8", "level")
|
|
33
34
|
var[:] = level
|
|
34
35
|
var = root_grp.createVariable("latitude", "f8")
|
|
@@ -38,30 +39,30 @@ def model_file(tmpdir_factory, file_metadata):
|
|
|
38
39
|
var = root_grp.createVariable("horizontal_resolution", "f8")
|
|
39
40
|
var[:] = 9
|
|
40
41
|
var = root_grp.createVariable("height", "f8", ("time", "level"))
|
|
41
|
-
var[:] =
|
|
42
|
+
var[:] = ma.array([[10, 14], [8, 14], [9, 15]])
|
|
42
43
|
var.units = "km"
|
|
43
44
|
var = root_grp.createVariable("forecast_time", "f8", "time")
|
|
44
|
-
var[:] =
|
|
45
|
+
var[:] = ma.array([1, 5, 10])
|
|
45
46
|
var = root_grp.createVariable("cloud_fraction", "f8", ("time", "level"))
|
|
46
|
-
var[:] =
|
|
47
|
+
var[:] = ma.array([[0, 2], [3, 6], [5, 8]])
|
|
47
48
|
var = root_grp.createVariable("qi", "f8", ("time", "level"))
|
|
48
|
-
var[:] =
|
|
49
|
+
var[:] = ma.array([[0.01, 0.00], [0.02, 0.03], [0.06, 0.08]])
|
|
49
50
|
var = root_grp.createVariable("ql", "f8", ("time", "level"))
|
|
50
|
-
var[:] =
|
|
51
|
+
var[:] = ma.array([[0.008, 0.09], [0.004, 0.007], [0.0001, 0.0002]])
|
|
51
52
|
var = root_grp.createVariable("temperature", "f8", ("time", "level"))
|
|
52
|
-
var[:] =
|
|
53
|
+
var[:] = ma.array([[300, 301], [302, 299], [305, 298]])
|
|
53
54
|
var = root_grp.createVariable("pressure", "f8", ("time", "level"))
|
|
54
|
-
var[:] =
|
|
55
|
+
var[:] = ma.array([[1000, 1001], [1010, 1003], [1020, 1005]])
|
|
55
56
|
var = root_grp.createVariable("uwind", "f8", ("time", "level"))
|
|
56
|
-
var[:] =
|
|
57
|
+
var[:] = ma.array([[1, 2], [2, 2], [3, 1]])
|
|
57
58
|
var = root_grp.createVariable("vwind", "f8", ("time", "level"))
|
|
58
|
-
var[:] =
|
|
59
|
+
var[:] = ma.array([[3, 1], [2, 1], [5, 2]])
|
|
59
60
|
root_grp.close()
|
|
60
61
|
return file_name
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
@pytest.fixture(scope="session")
|
|
64
|
-
def obs_file(tmpdir_factory, file_metadata):
|
|
65
|
+
def obs_file(tmpdir_factory, file_metadata) -> str:
|
|
65
66
|
file_name = tmpdir_factory.mktemp("data").join("file.nc")
|
|
66
67
|
root_grp = netCDF4.Dataset(file_name, "w", format="NETCDF4_CLASSIC")
|
|
67
68
|
time = 6
|
|
@@ -70,9 +71,9 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
70
71
|
root_grp.createDimension("height", height)
|
|
71
72
|
_create_global_attributes(root_grp, file_metadata)
|
|
72
73
|
var = root_grp.createVariable("time", "f8", "time")
|
|
73
|
-
var[:] =
|
|
74
|
+
var[:] = ma.array([0, 2, 4, 6, 8, 10])
|
|
74
75
|
var = root_grp.createVariable("height", "f8", "height")
|
|
75
|
-
var[:] =
|
|
76
|
+
var[:] = ma.array([8, 9, 12, 15])
|
|
76
77
|
var.units = "km"
|
|
77
78
|
var = root_grp.createVariable("latitude", "f8")
|
|
78
79
|
var[:] = 1
|
|
@@ -84,11 +85,11 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
84
85
|
var = root_grp.createVariable("radar_frequency", "f8")
|
|
85
86
|
var[:] = 35.5
|
|
86
87
|
var = root_grp.createVariable("rainrate", "i4", "time")
|
|
87
|
-
var[:] =
|
|
88
|
+
var[:] = ma.array([1, 2, 0, 10, 5, 13])
|
|
88
89
|
var = root_grp.createVariable("Z_sensitivity", "f8", "height")
|
|
89
|
-
var[:] =
|
|
90
|
+
var[:] = ma.array([0.1, 0.2, 0.0, 1.0])
|
|
90
91
|
var = root_grp.createVariable("category_bits", "i4", ("time", "height"))
|
|
91
|
-
var[:] =
|
|
92
|
+
var[:] = ma.array(
|
|
92
93
|
[
|
|
93
94
|
[0, 1, 2, 0],
|
|
94
95
|
[2, 8, 4, 1],
|
|
@@ -96,10 +97,10 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
96
97
|
[4, 4, 0, 1],
|
|
97
98
|
[0, 8, 16, 16],
|
|
98
99
|
[32, 2, 8, 32],
|
|
99
|
-
]
|
|
100
|
+
],
|
|
100
101
|
)
|
|
101
102
|
var = root_grp.createVariable("quality_bits", "i4", ("time", "height"))
|
|
102
|
-
var[:] =
|
|
103
|
+
var[:] = ma.array(
|
|
103
104
|
[
|
|
104
105
|
[0, 1, 2, 4],
|
|
105
106
|
[8, 16, 32, 16],
|
|
@@ -107,10 +108,10 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
107
108
|
[0, 1, 2, 4],
|
|
108
109
|
[8, 16, 32, 16],
|
|
109
110
|
[8, 4, 2, 1],
|
|
110
|
-
]
|
|
111
|
+
],
|
|
111
112
|
)
|
|
112
113
|
var = root_grp.createVariable("iwc", "f8", ("time", "height"))
|
|
113
|
-
var[:] =
|
|
114
|
+
var[:] = ma.array(
|
|
114
115
|
[
|
|
115
116
|
[0.01, 0.02, 0.06, 0.01],
|
|
116
117
|
[0.02, 0.06, 0.00, 0.03],
|
|
@@ -118,10 +119,10 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
118
119
|
[0.01, 0.02, 0.06, 0.01],
|
|
119
120
|
[0.02, 0.06, 0.00, 0.03],
|
|
120
121
|
[0.08, 0.00, 0.03, 0.08],
|
|
121
|
-
]
|
|
122
|
+
],
|
|
122
123
|
)
|
|
123
124
|
var = root_grp.createVariable("iwc_retrieval_status", "f8", ("time", "height"))
|
|
124
|
-
var[:] =
|
|
125
|
+
var[:] = ma.array(
|
|
125
126
|
[
|
|
126
127
|
[1, 2, 6, 1],
|
|
127
128
|
[2, 6, 5, 3],
|
|
@@ -129,10 +130,10 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
129
130
|
[1, 2, 6, 7],
|
|
130
131
|
[4, 6, 5, 3],
|
|
131
132
|
[7, 5, 3, 4],
|
|
132
|
-
]
|
|
133
|
+
],
|
|
133
134
|
)
|
|
134
135
|
var = root_grp.createVariable("lwc", "f8", ("time", "height"))
|
|
135
|
-
var[:] =
|
|
136
|
+
var[:] = ma.array(
|
|
136
137
|
[
|
|
137
138
|
[0.08, 0.04, 0.01, 0.08],
|
|
138
139
|
[0.04, 0.01, 0.09, 0.07],
|
|
@@ -140,10 +141,10 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
140
141
|
[0.08, 0.04, 0.01, 0.08],
|
|
141
142
|
[0.04, 0.01, 0.09, 0.07],
|
|
142
143
|
[0.02, 0.09, 0.07, 0.02],
|
|
143
|
-
]
|
|
144
|
+
],
|
|
144
145
|
)
|
|
145
146
|
var = root_grp.createVariable("data", "i4", ("time", "height"))
|
|
146
|
-
var[:] =
|
|
147
|
+
var[:] = ma.array(
|
|
147
148
|
[
|
|
148
149
|
[2, 4, 3, 6],
|
|
149
150
|
[7, 1, 9, 7],
|
|
@@ -151,14 +152,14 @@ def obs_file(tmpdir_factory, file_metadata):
|
|
|
151
152
|
[3, 5, 1, 0],
|
|
152
153
|
[2, 5, 6, 1],
|
|
153
154
|
[2, 9, 7, 2],
|
|
154
|
-
]
|
|
155
|
+
],
|
|
155
156
|
)
|
|
156
157
|
root_grp.close()
|
|
157
158
|
return file_name
|
|
158
159
|
|
|
159
160
|
|
|
160
161
|
@pytest.fixture(scope="session")
|
|
161
|
-
def regrid_file(tmpdir_factory, file_metadata):
|
|
162
|
+
def regrid_file(tmpdir_factory, file_metadata) -> str:
|
|
162
163
|
file_name = tmpdir_factory.mktemp("data").join("file.nc")
|
|
163
164
|
root_grp = netCDF4.Dataset(file_name, "w", format="NETCDF4_CLASSIC")
|
|
164
165
|
time = 3
|
|
@@ -167,7 +168,7 @@ def regrid_file(tmpdir_factory, file_metadata):
|
|
|
167
168
|
root_grp.createDimension("level", level)
|
|
168
169
|
_create_global_attributes(root_grp, file_metadata)
|
|
169
170
|
var = root_grp.createVariable("time", "f8", "time")
|
|
170
|
-
var[:] =
|
|
171
|
+
var[:] = ma.array([2, 6, 10])
|
|
171
172
|
var = root_grp.createVariable("level", "f8", "level")
|
|
172
173
|
var[:] = level
|
|
173
174
|
var = root_grp.createVariable("latitude", "f8")
|
|
@@ -177,27 +178,27 @@ def regrid_file(tmpdir_factory, file_metadata):
|
|
|
177
178
|
var = root_grp.createVariable("horizontal_resolution", "f8")
|
|
178
179
|
var[:] = 9
|
|
179
180
|
var = root_grp.createVariable("ecmwf_height", "f8", ("time", "level"))
|
|
180
|
-
var[:] =
|
|
181
|
+
var[:] = ma.array([[10, 14], [8, 14], [9, 15]])
|
|
181
182
|
var = root_grp.createVariable("ecmwf_forecast_time", "f8", "time")
|
|
182
|
-
var[:] =
|
|
183
|
+
var[:] = ma.array([1, 5, 10])
|
|
183
184
|
var = root_grp.createVariable("ecmwf_cf", "f8", ("time", "level"))
|
|
184
|
-
var[:] =
|
|
185
|
+
var[:] = ma.array([[0, 2], [3, 6], [5, 8]])
|
|
185
186
|
var = root_grp.createVariable("ecmwf_cf_cirrus", "f8", ("time", "level"))
|
|
186
|
-
var[:] =
|
|
187
|
+
var[:] = ma.array([[0, 2], [3, 6], [5, 7]])
|
|
187
188
|
var = root_grp.createVariable("ecmwf_cf_snow", "f8", ("time", "level"))
|
|
188
|
-
var[:] =
|
|
189
|
+
var[:] = ma.array([[0, 2], [4, 6], [5, 8]])
|
|
189
190
|
var = root_grp.createVariable("cf_ecmwf", "f8", ("time", "level"))
|
|
190
|
-
var[:] =
|
|
191
|
+
var[:] = ma.array([[0, 2], [3, 6], [5, 8]])
|
|
191
192
|
var = root_grp.createVariable("cf_adv_ecmwf", "f8", ("time", "level"))
|
|
192
|
-
var[:] =
|
|
193
|
+
var[:] = ma.array([[0, 2], [3, 6], [5, 8]])
|
|
193
194
|
var = root_grp.createVariable("temperature", "f8", ("time", "level"))
|
|
194
|
-
var[:] =
|
|
195
|
+
var[:] = ma.array([[300, 301], [302, 299], [305, 298]])
|
|
195
196
|
var = root_grp.createVariable("pressure", "f8", ("time", "level"))
|
|
196
|
-
var[:] =
|
|
197
|
+
var[:] = ma.array([[1000, 1001], [1010, 1003], [1020, 1005]])
|
|
197
198
|
root_grp.close()
|
|
198
199
|
return file_name
|
|
199
200
|
|
|
200
201
|
|
|
201
|
-
def _create_global_attributes(root_grp, meta):
|
|
202
|
+
def _create_global_attributes(root_grp, meta) -> None:
|
|
202
203
|
for key in ("year", "month", "day", "location"):
|
|
203
204
|
setattr(root_grp, key, meta[key])
|