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
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
3
|
from cloudnetpy.model_evaluation.plotting import plotting as pl
|
|
4
|
+
from cloudnetpy.model_evaluation.plotting.plot_meta import PlotMeta
|
|
4
5
|
|
|
5
6
|
MODEL = "ecmwf"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
VARIABLE_INFO = PlotMeta(
|
|
8
|
+
name="Product",
|
|
9
|
+
cbar="rainbow",
|
|
10
|
+
plot_range=(0, 1),
|
|
11
|
+
plot_scale="linear",
|
|
12
|
+
plot_type="mesh",
|
|
13
|
+
)
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
@pytest.mark.parametrize("key", ["cf_V", "cf_A", "cf_V_adv", "cf_A_adv"])
|
|
14
|
-
def test_get_cf_title(key):
|
|
15
|
-
var = VariableInfo()
|
|
17
|
+
def test_get_cf_title(key) -> None:
|
|
16
18
|
field_name = key + "_" + MODEL
|
|
17
19
|
value = "Product, Volume"
|
|
18
20
|
if "A" in key:
|
|
19
21
|
value = "Product, Area"
|
|
20
|
-
x = pl._get_cf_title(field_name,
|
|
22
|
+
x = pl._get_cf_title(field_name, VARIABLE_INFO)
|
|
21
23
|
assert x == value
|
|
22
24
|
|
|
23
25
|
|
|
24
26
|
@pytest.mark.parametrize("key", ["cf_V", "cf_A", "cf_V_adv", "cf_A_adv"])
|
|
25
|
-
def test_get_cf_title_cycle(key):
|
|
26
|
-
var = VariableInfo()
|
|
27
|
+
def test_get_cf_title_cycle(key) -> None:
|
|
27
28
|
field_name = key + "_" + MODEL + "_001"
|
|
28
29
|
value = "Product, Volume"
|
|
29
30
|
if "A" in key:
|
|
30
31
|
value = "Product, Area"
|
|
31
|
-
x = pl._get_cf_title(field_name,
|
|
32
|
+
x = pl._get_cf_title(field_name, VARIABLE_INFO)
|
|
32
33
|
assert x == value
|
|
33
34
|
|
|
34
35
|
|
|
@@ -43,10 +44,9 @@ def test_get_cf_title_cycle(key):
|
|
|
43
44
|
("iwc_rain_adv", "Product with rain"),
|
|
44
45
|
],
|
|
45
46
|
)
|
|
46
|
-
def test_get_iwc_title(key, value):
|
|
47
|
-
var = VariableInfo()
|
|
47
|
+
def test_get_iwc_title(key, value) -> None:
|
|
48
48
|
field_name = key + "_" + MODEL
|
|
49
|
-
x = pl._get_iwc_title(field_name,
|
|
49
|
+
x = pl._get_iwc_title(field_name, VARIABLE_INFO)
|
|
50
50
|
assert x == value
|
|
51
51
|
|
|
52
52
|
|
|
@@ -61,42 +61,38 @@ def test_get_iwc_title(key, value):
|
|
|
61
61
|
("iwc_rain_adv", "Product with rain"),
|
|
62
62
|
],
|
|
63
63
|
)
|
|
64
|
-
def test_get_iwc_title_cycle(key, value):
|
|
65
|
-
var = VariableInfo()
|
|
64
|
+
def test_get_iwc_title_cycle(key, value) -> None:
|
|
66
65
|
field_name = key + "_" + MODEL + "_001"
|
|
67
|
-
x = pl._get_iwc_title(field_name,
|
|
66
|
+
x = pl._get_iwc_title(field_name, VARIABLE_INFO)
|
|
68
67
|
assert x == value
|
|
69
68
|
|
|
70
69
|
|
|
71
|
-
def test_get_product_title():
|
|
72
|
-
var = VariableInfo()
|
|
70
|
+
def test_get_product_title() -> None:
|
|
73
71
|
value = "Product"
|
|
74
|
-
x = pl._get_product_title(
|
|
72
|
+
x = pl._get_product_title(VARIABLE_INFO)
|
|
75
73
|
assert x == value
|
|
76
74
|
|
|
77
75
|
|
|
78
|
-
def test_get_product_title_cycle():
|
|
79
|
-
var = VariableInfo()
|
|
76
|
+
def test_get_product_title_cycle() -> None:
|
|
80
77
|
value = "Product"
|
|
81
|
-
x = pl._get_product_title(
|
|
78
|
+
x = pl._get_product_title(VARIABLE_INFO)
|
|
82
79
|
assert x == value
|
|
83
80
|
|
|
84
81
|
|
|
85
82
|
@pytest.mark.parametrize(
|
|
86
|
-
"key, title",
|
|
83
|
+
"key, title",
|
|
84
|
+
[("lwc", "Product"), ("lwc_adv", "Product (Advection time)")],
|
|
87
85
|
)
|
|
88
|
-
def test_get_stat_titles(key, title):
|
|
86
|
+
def test_get_stat_titles(key, title) -> None:
|
|
89
87
|
field_name = key + "_" + MODEL
|
|
90
|
-
|
|
91
|
-
x = pl._get_stat_titles(field_name, key, var)
|
|
88
|
+
x = pl._get_stat_titles(field_name, key, VARIABLE_INFO)
|
|
92
89
|
assert x == title
|
|
93
90
|
|
|
94
91
|
|
|
95
92
|
@pytest.mark.parametrize("key", ["cf_V", "cf_A", "cf_V_adv", "cf_A_adv"])
|
|
96
|
-
def test_get_cf_title_stat(key):
|
|
93
|
+
def test_get_cf_title_stat(key) -> None:
|
|
97
94
|
field_name = key + "_" + MODEL
|
|
98
|
-
|
|
99
|
-
x = pl._get_cf_title_stat(field_name, var)
|
|
95
|
+
x = pl._get_cf_title_stat(field_name, VARIABLE_INFO)
|
|
100
96
|
value = "Product volume"
|
|
101
97
|
if "A" in key:
|
|
102
98
|
value = "Product area"
|
|
@@ -111,15 +107,13 @@ def test_get_cf_title_stat(key):
|
|
|
111
107
|
("iwc_rain", "Product with rain"),
|
|
112
108
|
],
|
|
113
109
|
)
|
|
114
|
-
def test_get_iwc_title_stat(key, value):
|
|
110
|
+
def test_get_iwc_title_stat(key, value) -> None:
|
|
115
111
|
field_name = key + "_" + MODEL
|
|
116
|
-
|
|
117
|
-
x = pl._get_iwc_title_stat(field_name, var)
|
|
112
|
+
x = pl._get_iwc_title_stat(field_name, VARIABLE_INFO)
|
|
118
113
|
assert x == value
|
|
119
114
|
|
|
120
115
|
|
|
121
116
|
@pytest.mark.parametrize("key", ["lwc"])
|
|
122
|
-
def test_get_product_title_stat(key):
|
|
123
|
-
|
|
124
|
-
x = pl._get_product_title_stat(var)
|
|
117
|
+
def test_get_product_title_stat(key) -> None:
|
|
118
|
+
x = pl._get_product_title_stat(VARIABLE_INFO)
|
|
125
119
|
assert x == "Product"
|
|
@@ -8,7 +8,7 @@ PRODUCT_cf = ["cf", "ECMWF", "Cloud fraction"]
|
|
|
8
8
|
PRODUCT_iwc = ["iwc", "ECMWF", "Ice water content"]
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def test_relative_error():
|
|
11
|
+
def test_relative_error() -> None:
|
|
12
12
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
13
13
|
observation = ma.array([[3, 2, 5, 4], [4, 6, 8, 4]])
|
|
14
14
|
x, _ = sts.relative_error(model, observation)
|
|
@@ -16,29 +16,35 @@ def test_relative_error():
|
|
|
16
16
|
testing.assert_array_almost_equal(x, compare)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def test_relative_error_mask():
|
|
19
|
+
def test_relative_error_mask() -> None:
|
|
20
20
|
model = ma.array([[1, 2, 2, 3], [2, 1, 10, 1]])
|
|
21
21
|
model.mask = np.array([[0, 0, 0, 1], [0, 1, 0, 1]])
|
|
22
22
|
observation = ma.array([[1, 2, 5, 4], [4, 6, 8, 1]])
|
|
23
23
|
observation.mask = np.array([[1, 0, 0, 1], [0, 0, 0, 1]])
|
|
24
24
|
x, _ = sts.relative_error(model, observation)
|
|
25
25
|
compare = ma.array(
|
|
26
|
-
[
|
|
26
|
+
[
|
|
27
|
+
ma.array([-99, 0.0, -60.0, -99], mask=[True, False, False, True]),
|
|
28
|
+
ma.array([-50.0, -83.33, 25.0, -99], mask=[False, False, False, True]),
|
|
29
|
+
],
|
|
27
30
|
)
|
|
28
31
|
testing.assert_array_almost_equal(x, compare)
|
|
29
32
|
|
|
30
33
|
|
|
31
|
-
def test_relative_error_nan():
|
|
34
|
+
def test_relative_error_nan() -> None:
|
|
32
35
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
33
36
|
observation = ma.array([[3, 2, 5, np.nan], [4, np.nan, 8, 4]])
|
|
34
37
|
x, _ = sts.relative_error(model, observation)
|
|
35
38
|
compare = ma.array(
|
|
36
|
-
[
|
|
39
|
+
[
|
|
40
|
+
ma.array([-66.67, 0.0, -60.0, -99], mask=[False, False, False, True]),
|
|
41
|
+
ma.array([-50.0, -99, 25.0, -75.0], mask=[False, True, False, False]),
|
|
42
|
+
],
|
|
37
43
|
)
|
|
38
44
|
testing.assert_array_almost_equal(x, compare)
|
|
39
45
|
|
|
40
46
|
|
|
41
|
-
def test_absolute_error():
|
|
47
|
+
def test_absolute_error() -> None:
|
|
42
48
|
model = ma.array([[0.1, 0.2, 0.2, 0.3], [0.2, 0.4, 1.0, 0.0]])
|
|
43
49
|
observation = ma.array([[0.2, 0.2, 0.1, 0.4], [0.4, 0.6, 0.8, 0.2]])
|
|
44
50
|
x, _ = sts.absolute_error(model, observation)
|
|
@@ -46,27 +52,35 @@ def test_absolute_error():
|
|
|
46
52
|
testing.assert_array_almost_equal(x, compare)
|
|
47
53
|
|
|
48
54
|
|
|
49
|
-
def test_absolute_error_nan():
|
|
55
|
+
def test_absolute_error_nan() -> None:
|
|
50
56
|
model = ma.array([[0.1, 0.2, 0.2, 0.3], [0.2, 0.4, 1.0, 0.0]])
|
|
51
57
|
observation = ma.array([[0.2, np.nan, 0.1, 0.4], [np.nan, 0.6, 0.8, 0.2]])
|
|
52
58
|
x, _ = sts.absolute_error(model, observation)
|
|
53
|
-
compare = ma.array(
|
|
59
|
+
compare = ma.array(
|
|
60
|
+
[
|
|
61
|
+
ma.array([10.0, -99, -10.0, 10.0], mask=[False, True, False, False]),
|
|
62
|
+
ma.array([-99, 20.0, -20.0, 20.0], mask=[True, False, False, False]),
|
|
63
|
+
],
|
|
64
|
+
)
|
|
54
65
|
testing.assert_array_almost_equal(x, compare)
|
|
55
66
|
|
|
56
67
|
|
|
57
|
-
def test_absolute_error_mask():
|
|
68
|
+
def test_absolute_error_mask() -> None:
|
|
58
69
|
model = ma.array([[0.1, 0.2, 0.2, 0.3], [0.2, 0.4, 1.0, 0.0]])
|
|
59
70
|
model.mask = np.array([[0, 0, 0, 1], [0, 1, 0, 1]])
|
|
60
71
|
observation = ma.array([[0.2, 0.2, 0.1, 0.4], [0.4, 0.6, 0.8, 0.2]])
|
|
61
72
|
observation.mask = np.array([[0, 0, 0, 0], [0, 1, 0, 0]])
|
|
62
73
|
x, _ = sts.absolute_error(model, observation)
|
|
63
74
|
compare = ma.array(
|
|
64
|
-
[
|
|
75
|
+
[
|
|
76
|
+
ma.array([10.0, 0.0, -10.0, -99], mask=[False, False, False, True]),
|
|
77
|
+
ma.array([20.0, -99, -20.0, -99], mask=[False, True, False, True]),
|
|
78
|
+
],
|
|
65
79
|
)
|
|
66
80
|
testing.assert_array_almost_equal(x, compare)
|
|
67
81
|
|
|
68
82
|
|
|
69
|
-
def test_combine_masked_indices():
|
|
83
|
+
def test_combine_masked_indices() -> None:
|
|
70
84
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
71
85
|
observation = ma.array([[3, 2, 5, 4], [4, 6, 8, 4]])
|
|
72
86
|
x, y = sts.combine_masked_indices(model, observation)
|
|
@@ -76,49 +90,72 @@ def test_combine_masked_indices():
|
|
|
76
90
|
testing.assert_array_almost_equal(y, compare_o)
|
|
77
91
|
|
|
78
92
|
|
|
79
|
-
def test_combine_masked_indices_min():
|
|
93
|
+
def test_combine_masked_indices_min() -> None:
|
|
80
94
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
81
95
|
observation = ma.array([[3, 2, 5, 4], [4, 6, 8, 4]])
|
|
82
96
|
x, y = sts.combine_masked_indices(model, observation)
|
|
83
|
-
|
|
84
|
-
|
|
97
|
+
|
|
98
|
+
compare_m = ma.array(
|
|
99
|
+
[
|
|
100
|
+
ma.array([-99, 2, 2, 3], mask=[True, False, False, False]),
|
|
101
|
+
ma.array([2, 4, 10, -99], mask=[True, False, False, True]),
|
|
102
|
+
],
|
|
103
|
+
)
|
|
104
|
+
compare_o = ma.array(
|
|
105
|
+
[
|
|
106
|
+
ma.array([-99, 2, 5, 4], mask=[True, False, False, False]),
|
|
107
|
+
ma.array([4, 6, 8, -99], mask=[True, False, False, True]),
|
|
108
|
+
],
|
|
109
|
+
)
|
|
110
|
+
|
|
85
111
|
testing.assert_array_almost_equal(x, compare_m)
|
|
86
112
|
testing.assert_array_almost_equal(y, compare_o)
|
|
87
113
|
|
|
88
114
|
|
|
89
|
-
def test_combine_masked_indices_mask():
|
|
115
|
+
def test_combine_masked_indices_mask() -> None:
|
|
90
116
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
91
117
|
model.mask = ma.array([[1, 0, 0, 0], [0, 0, 0, 1]])
|
|
92
118
|
observation = ma.array([[3, 2, 1, 4], [4, 6, 8, 4]])
|
|
93
119
|
observation.mask = ma.array([[0, 1, 1, 0], [1, 0, 0, 0]])
|
|
94
120
|
x, y = sts.combine_masked_indices(model, observation)
|
|
95
121
|
model = ma.array(
|
|
96
|
-
[
|
|
122
|
+
[
|
|
123
|
+
ma.array([-99, -99, -99, 3], mask=[True, True, True, False]),
|
|
124
|
+
ma.array([-99, 4, 10, -99], mask=[True, False, False, True]),
|
|
125
|
+
],
|
|
97
126
|
)
|
|
98
127
|
observation = ma.array(
|
|
99
|
-
[
|
|
128
|
+
[
|
|
129
|
+
ma.array([-99, -99, -99, 4], mask=[True, True, True, False]),
|
|
130
|
+
ma.array([-99, 6, 8, -99], mask=[True, False, False, True]),
|
|
131
|
+
],
|
|
100
132
|
)
|
|
101
133
|
testing.assert_array_almost_equal(x, model)
|
|
102
134
|
testing.assert_array_almost_equal(y, observation)
|
|
103
135
|
|
|
104
136
|
|
|
105
|
-
def test_combine_masked_indices_nan():
|
|
137
|
+
def test_combine_masked_indices_nan() -> None:
|
|
106
138
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
107
139
|
observation = ma.array([[np.nan, 2, 5, 4], [4, 6, np.nan, 4]])
|
|
108
140
|
x, y = sts.combine_masked_indices(model, observation)
|
|
109
|
-
model = ma.array(
|
|
141
|
+
model = ma.array(
|
|
142
|
+
[
|
|
143
|
+
ma.array([-99, 2, 2, 3], mask=[True, False, False, False]),
|
|
144
|
+
ma.array([2, 4, -99, 1], mask=[False, False, True, False]),
|
|
145
|
+
],
|
|
146
|
+
)
|
|
110
147
|
testing.assert_array_almost_equal(x, model)
|
|
111
148
|
testing.assert_array_almost_equal(y, observation)
|
|
112
149
|
|
|
113
150
|
|
|
114
|
-
def test_calc_common_area_sum():
|
|
151
|
+
def test_calc_common_area_sum() -> None:
|
|
115
152
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
116
153
|
observation = ma.array([[3, 2, 1, 4], [4, 6, 8, 4]])
|
|
117
154
|
x, _ = sts.calc_common_area_sum(model, observation)
|
|
118
155
|
testing.assert_almost_equal(x, 100)
|
|
119
156
|
|
|
120
157
|
|
|
121
|
-
def test_calc_common_area_sum_min():
|
|
158
|
+
def test_calc_common_area_sum_min() -> None:
|
|
122
159
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
123
160
|
model.mask = ma.array([[1, 0, 0, 0], [0, 0, 0, 1]])
|
|
124
161
|
observation = ma.array([[3, 2, 1, 4], [4, 6, 8, 4]])
|
|
@@ -127,7 +164,7 @@ def test_calc_common_area_sum_min():
|
|
|
127
164
|
testing.assert_almost_equal(x, 60.0)
|
|
128
165
|
|
|
129
166
|
|
|
130
|
-
def test_calc_common_area_sum_nan():
|
|
167
|
+
def test_calc_common_area_sum_nan() -> None:
|
|
131
168
|
model = ma.array([[1, 2, 2, 3], [2, np.nan, 10, 1]])
|
|
132
169
|
model.mask = ma.array([[1, 0, 0, 0], [0, 0, 0, 1]])
|
|
133
170
|
observation = ma.array([[3, 2, 1, 4], [4, 6, np.nan, 4]])
|
|
@@ -136,7 +173,7 @@ def test_calc_common_area_sum_nan():
|
|
|
136
173
|
testing.assert_almost_equal(x, 25.0)
|
|
137
174
|
|
|
138
175
|
|
|
139
|
-
def test_calc_common_area_sum_mask():
|
|
176
|
+
def test_calc_common_area_sum_mask() -> None:
|
|
140
177
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
141
178
|
model.mask = ma.array([[1, 0, 0, 0], [0, 0, 0, 0]])
|
|
142
179
|
observation = ma.array([[3, 2, 1, 4], [4, 6, 8, 4]])
|
|
@@ -145,7 +182,7 @@ def test_calc_common_area_sum_mask():
|
|
|
145
182
|
testing.assert_almost_equal(x, 50.0)
|
|
146
183
|
|
|
147
184
|
|
|
148
|
-
def test_histogram():
|
|
185
|
+
def test_histogram() -> None:
|
|
149
186
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
150
187
|
observation = ma.array([[3, 2, 1, 4], [4, 6, 8, 4]])
|
|
151
188
|
compare_x = np.array([1, 2, 2, 3, 2, 4, 8, 1])
|
|
@@ -155,7 +192,7 @@ def test_histogram():
|
|
|
155
192
|
testing.assert_array_almost_equal(y, compare_y)
|
|
156
193
|
|
|
157
194
|
|
|
158
|
-
def test_histogram_mask():
|
|
195
|
+
def test_histogram_mask() -> None:
|
|
159
196
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
160
197
|
model.mask = ma.array([[1, 0, 0, 0], [0, 0, 0, 1]])
|
|
161
198
|
observation = ma.array([[3, 2, 1, 4], [4, 6, 8, 4]])
|
|
@@ -167,7 +204,7 @@ def test_histogram_mask():
|
|
|
167
204
|
testing.assert_array_almost_equal(y, compare_y)
|
|
168
205
|
|
|
169
206
|
|
|
170
|
-
def test_histogram_nan():
|
|
207
|
+
def test_histogram_nan() -> None:
|
|
171
208
|
model = ma.array([[1, 2, 2, 3], [2, 4, 10, 1]])
|
|
172
209
|
observation = ma.array([[3, np.nan, 1, 4], [np.nan, 6, np.nan, 4]])
|
|
173
210
|
compare_x = np.array([1, 2, 2, 3, 2, 4, 6, 1])
|
|
@@ -177,7 +214,7 @@ def test_histogram_nan():
|
|
|
177
214
|
testing.assert_array_almost_equal(y, compare_y)
|
|
178
215
|
|
|
179
216
|
|
|
180
|
-
def test_vertical_profile():
|
|
217
|
+
def test_vertical_profile() -> None:
|
|
181
218
|
model = ma.array([[0, 2, 2, 3], [2, 4, 10, 1], [4, 6, 6, 8]])
|
|
182
219
|
observation = ma.array([[3, 1, 1, 4], [4, 3, 8, 0], [5, 5, 3, 2]])
|
|
183
220
|
x, y = sts.vertical_profile(model, observation)
|
|
@@ -187,7 +224,7 @@ def test_vertical_profile():
|
|
|
187
224
|
testing.assert_array_almost_equal(y, observation)
|
|
188
225
|
|
|
189
226
|
|
|
190
|
-
def test_vertical_profile_nan():
|
|
227
|
+
def test_vertical_profile_nan() -> None:
|
|
191
228
|
model = ma.array([[0, 2, 2, 3], [2, 4, 10, 1], [4, 6, 6, 8]])
|
|
192
229
|
observation = ma.array([[3, 1, 1, np.nan], [np.nan, 3, 8, 0], [5, 5, 3, 2]])
|
|
193
230
|
x, y = sts.vertical_profile(model, observation)
|
|
@@ -197,14 +234,14 @@ def test_vertical_profile_nan():
|
|
|
197
234
|
testing.assert_array_almost_equal(y, observation)
|
|
198
235
|
|
|
199
236
|
|
|
200
|
-
def test_vertical_profile_mask():
|
|
237
|
+
def test_vertical_profile_mask() -> None:
|
|
201
238
|
model = ma.array([[0, 2, 2, 3], [2, 4, 10, 1], [4, 6, 6, 8]])
|
|
202
239
|
model.mask = ma.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
|
|
203
240
|
observation = ma.array([[3, 1, 1, 4], [4, 3, 8, 0], [5, 5, 3, 2]])
|
|
204
241
|
observation.mask = ma.array([[0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 0, 0]])
|
|
205
242
|
x, y = sts.vertical_profile(model, observation)
|
|
206
243
|
model = ma.array([3, 4, 6, 5.5])
|
|
207
|
-
observation = ma.array([4,
|
|
244
|
+
observation = ma.array([4, -99, 4, 3], mask=[False, True, False, False])
|
|
208
245
|
testing.assert_array_almost_equal(x, model)
|
|
209
246
|
testing.assert_array_almost_equal(y, observation)
|
|
210
247
|
|
|
@@ -216,6 +253,6 @@ def test_vertical_profile_mask():
|
|
|
216
253
|
("vertical", ("ECMWF", "Cloud fraction")),
|
|
217
254
|
],
|
|
218
255
|
)
|
|
219
|
-
def test_day_stat_title(method, title):
|
|
256
|
+
def test_day_stat_title(method, title) -> None:
|
|
220
257
|
x = sts.day_stat_title(method, PRODUCT_cf)
|
|
221
258
|
assert x == title
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from datetime import datetime, timedelta
|
|
1
|
+
from datetime import datetime, timedelta, timezone
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pytest
|
|
@@ -12,61 +12,62 @@ OUTPUT_FILE = "/"
|
|
|
12
12
|
PRODUCT = "iwc"
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def test_model_file_list():
|
|
15
|
+
def test_model_file_list() -> None:
|
|
16
16
|
name = "ec"
|
|
17
17
|
models = ["00_ec_1", "00_ec_2", "00_ec_3"]
|
|
18
18
|
tools.check_model_file_list(name, models)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
def test_model_file_list_fail():
|
|
21
|
+
def test_model_file_list_fail() -> None:
|
|
23
22
|
name = "ec"
|
|
24
23
|
models = ["00_ec_1", "ac_1", "00_ec_2", "00_ec_3"]
|
|
25
|
-
|
|
24
|
+
with pytest.raises(AttributeError):
|
|
25
|
+
tools.check_model_file_list(name, models)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def test_time2datetime():
|
|
28
|
+
def test_time2datetime() -> None:
|
|
29
29
|
time_list = np.array(range(10))
|
|
30
|
-
d = datetime(2020, 4, 7, 0, 0, 0)
|
|
30
|
+
d = datetime(2020, 4, 7, 0, 0, 0, tzinfo=timezone.utc)
|
|
31
31
|
x = tools.time2datetime(time_list, d)
|
|
32
32
|
compare = [
|
|
33
|
-
datetime(2020, 4, 7, 0, 0, 0) + timedelta(hours=1 * x)
|
|
33
|
+
datetime(2020, 4, 7, 0, 0, 0, tzinfo=timezone.utc) + timedelta(hours=1 * x)
|
|
34
|
+
for x in range(10)
|
|
34
35
|
]
|
|
35
36
|
assert all(a == b for a, b in zip(x, compare))
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
def test_rebin_edges():
|
|
39
|
+
def test_rebin_edges() -> None:
|
|
39
40
|
data = np.array([1, 3, 6, 10, 15, 21, 28])
|
|
40
41
|
compare = np.array([-1, 2, 4.5, 8, 12.5, 18, 24.5, 35])
|
|
41
42
|
x = tools.rebin_edges(data)
|
|
42
43
|
testing.assert_array_almost_equal(x, compare)
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
def test_calculate_advection_time_hour(model_file):
|
|
46
|
+
def test_calculate_advection_time_hour(model_file) -> None:
|
|
46
47
|
obj = ModelManager(str(model_file), MODEL, OUTPUT_FILE, PRODUCT)
|
|
47
48
|
h = obj.resolution_h
|
|
48
|
-
v =
|
|
49
|
+
v = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]])
|
|
49
50
|
s = 1
|
|
50
51
|
compare = h * 1000 / v / 60**2
|
|
51
52
|
compare[compare > 1 / s] = 1 / s
|
|
52
53
|
compare = np.asarray([[timedelta(hours=float(t)) for t in tt] for tt in compare])
|
|
53
|
-
x = tools.calculate_advection_time(int(h), v, s)
|
|
54
|
+
x = tools.calculate_advection_time(int(h), ma.masked_array(v), s)
|
|
54
55
|
assert x.all() == compare.all()
|
|
55
56
|
|
|
56
57
|
|
|
57
|
-
def test_calculate_advection_time_10min(model_file):
|
|
58
|
+
def test_calculate_advection_time_10min(model_file) -> None:
|
|
58
59
|
obj = ModelManager(str(model_file), MODEL, OUTPUT_FILE, PRODUCT)
|
|
59
60
|
h = obj.resolution_h
|
|
60
|
-
v =
|
|
61
|
+
v = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]])
|
|
61
62
|
s = 6
|
|
62
63
|
compare = h * 1000 / v / 60**2
|
|
63
64
|
compare[compare > 1 / s] = 1 / s
|
|
64
65
|
compare = np.asarray([[timedelta(hours=float(t)) for t in tt] for tt in compare])
|
|
65
|
-
x = tools.calculate_advection_time(int(h), v, s)
|
|
66
|
+
x = tools.calculate_advection_time(int(h), ma.masked_array(v), s)
|
|
66
67
|
assert x.all() == compare.all()
|
|
67
68
|
|
|
68
69
|
|
|
69
|
-
def test_get_1d_indices():
|
|
70
|
+
def test_get_1d_indices() -> None:
|
|
70
71
|
w = (1, 5)
|
|
71
72
|
d = ma.array([0, 1, 2, 3, 4, 5, 6, 7])
|
|
72
73
|
compare = ma.array([0, 1, 1, 1, 1, 0, 0, 0])
|
|
@@ -74,37 +75,43 @@ def test_get_1d_indices():
|
|
|
74
75
|
testing.assert_array_almost_equal(x, compare)
|
|
75
76
|
|
|
76
77
|
|
|
77
|
-
def test_get_1d_indices_mask():
|
|
78
|
+
def test_get_1d_indices_mask() -> None:
|
|
78
79
|
w = (1, 5)
|
|
79
80
|
d = ma.array([0, 1, 2, 3, 4, 5, 6, 7])
|
|
80
81
|
m = np.array([0, 0, 1, 0, 0, 1, 0, 1], dtype=bool)
|
|
81
82
|
x = tools.get_1d_indices(w, d, m)
|
|
82
83
|
d[m] = ma.masked
|
|
83
|
-
compare = ma.array(
|
|
84
|
+
compare = ma.array(
|
|
85
|
+
[0, 1, -99, 1, 1, -99, 0, -99],
|
|
86
|
+
mask=[False, False, True, False, False, True, False, True],
|
|
87
|
+
)
|
|
84
88
|
testing.assert_array_almost_equal(x, compare)
|
|
85
89
|
|
|
86
90
|
|
|
87
|
-
def test_get_adv_indices():
|
|
91
|
+
def test_get_adv_indices() -> None:
|
|
88
92
|
mt = 3
|
|
89
93
|
at = 4
|
|
90
94
|
d = ma.array([0, 1, 2, 3, 4, 5, 6, 7])
|
|
91
|
-
compare = ma.array([0, 1, 1, 1, 1, 0, 0, 0], dtype=bool)
|
|
95
|
+
compare: ma.MaskedArray = ma.array([0, 1, 1, 1, 1, 0, 0, 0], dtype=bool)
|
|
92
96
|
x = tools.get_adv_indices(mt, at, d)
|
|
93
97
|
testing.assert_array_almost_equal(x, compare)
|
|
94
98
|
|
|
95
99
|
|
|
96
|
-
def test_get_adv_indices_mask():
|
|
100
|
+
def test_get_adv_indices_mask() -> None:
|
|
97
101
|
mt = 3
|
|
98
102
|
at = 4
|
|
99
|
-
d = ma.array([0, 1, 2, 3, 4, 5, 6, 7])
|
|
100
|
-
m = ma.array([0, 0, 1, 0, 0, 1, 0, 1], dtype=bool)
|
|
103
|
+
d: ma.MaskedArray = ma.array([0, 1, 2, 3, 4, 5, 6, 7])
|
|
104
|
+
m: ma.MaskedArray = ma.array([0, 0, 1, 0, 0, 1, 0, 1], dtype=bool)
|
|
101
105
|
x = tools.get_adv_indices(mt, at, d, m)
|
|
102
106
|
d[m] = ma.masked
|
|
103
|
-
compare = ma.array(
|
|
107
|
+
compare = ma.array(
|
|
108
|
+
[0, 1, -99, 1, 1, -99, 0, 0],
|
|
109
|
+
mask=[False, False, True, False, False, True, False, False],
|
|
110
|
+
)
|
|
104
111
|
testing.assert_array_almost_equal(x, compare)
|
|
105
112
|
|
|
106
113
|
|
|
107
|
-
def test_obs_windows_size():
|
|
114
|
+
def test_obs_windows_size() -> None:
|
|
108
115
|
i = np.array([0, 0, 1, 1, 1, 1, 0], dtype=bool)
|
|
109
116
|
j = np.array([0, 1, 1, 1, 0, 0, 0], dtype=bool)
|
|
110
117
|
x = tools.get_obs_window_size(i, j)
|
|
@@ -112,7 +119,7 @@ def test_obs_windows_size():
|
|
|
112
119
|
testing.assert_almost_equal(x, (4, 3))
|
|
113
120
|
|
|
114
121
|
|
|
115
|
-
def test_obs_windows_size_none():
|
|
122
|
+
def test_obs_windows_size_none() -> None:
|
|
116
123
|
i = np.array([0, 0, 1, 1, 1, 1, 0], dtype=bool)
|
|
117
124
|
j = np.array([0, 0, 0, 0, 0, 0, 0], dtype=bool)
|
|
118
125
|
x = tools.get_obs_window_size(i, j)
|