cloudnetpy 1.71.6__py3-none-any.whl → 1.72.0__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.
@@ -21,6 +21,7 @@ class CloudnetArray:
21
21
  units_from_user: Explicit units, optional.
22
22
  dimensions: Explicit dimension names, optional.
23
23
  data_type: Explicit data type, optional.
24
+ source: Source attribute, optional.
24
25
 
25
26
  """
26
27
 
@@ -31,6 +32,7 @@ class CloudnetArray:
31
32
  units_from_user: str | None = None,
32
33
  dimensions: Sequence[str] | None = None,
33
34
  data_type: str | None = None,
35
+ source: str | None = None,
34
36
  ):
35
37
  self.variable = variable
36
38
  self.name = name
@@ -38,6 +40,7 @@ class CloudnetArray:
38
40
  self.units = units_from_user or self._init_units()
39
41
  self.data_type = data_type or self._init_data_type()
40
42
  self.dimensions = dimensions
43
+ self.source = source
41
44
 
42
45
  def lin2db(self) -> None:
43
46
  """Converts linear units to log."""
@@ -83,15 +86,19 @@ class CloudnetArray:
83
86
  def fetch_attributes(self) -> list:
84
87
  """Returns list of user-defined attributes."""
85
88
  attributes = []
86
- for attr in self.__dict__:
87
- if attr not in (
88
- "variable",
89
- "name",
90
- "data",
91
- "data_type",
92
- "dimensions",
89
+ for key, value in self.__dict__.items():
90
+ if (
91
+ key
92
+ not in (
93
+ "variable",
94
+ "name",
95
+ "data",
96
+ "data_type",
97
+ "dimensions",
98
+ )
99
+ and value is not None
93
100
  ):
94
- attributes.append(attr)
101
+ attributes.append(key)
95
102
  return attributes
96
103
 
97
104
  def set_attributes(self, attributes: MetaData) -> None:
@@ -7,6 +7,7 @@ from numpy import ma
7
7
  from cloudnetpy import utils
8
8
  from cloudnetpy.cloudnetarray import CloudnetArray
9
9
  from cloudnetpy.exceptions import ValidTimeStampError
10
+ from cloudnetpy.instruments.instruments import BASTA, FMCW35, FMCW94, HATPRO, Instrument
10
11
 
11
12
 
12
13
  class CloudnetInstrument:
@@ -16,37 +17,66 @@ class CloudnetInstrument:
16
17
  self.site_meta: dict = {}
17
18
  self.data: dict = {}
18
19
  self.serial_number: str | None = None
20
+ self.instrument: Instrument | None = None
19
21
 
20
22
  def add_site_geolocation(self) -> None:
21
23
  for key in ("latitude", "longitude", "altitude"):
22
24
  value = None
23
- # User-supplied:
24
- if key in self.site_meta:
25
+ source = None
26
+ # From source data (BASTA, RPG-FMCW, HATPRO).
27
+ # Should be the accurate GPS coordinates.
28
+ if (
29
+ value is None
30
+ and self.instrument is not None
31
+ and self.instrument in (BASTA, FMCW94, FMCW35, HATPRO)
32
+ and hasattr(self, "dataset")
33
+ and isinstance(self.dataset, netCDF4.Dataset)
34
+ and key in self.dataset.variables
35
+ and not np.all(ma.getmaskarray(self.dataset[key][:]))
36
+ ):
37
+ value = self.dataset[key][:]
38
+ source = "GPS"
39
+ # User-supplied site coordinate.
40
+ if value is None and key in self.site_meta:
25
41
  value = self.site_meta[key]
26
- # From source global attributes (MIRA):
27
- elif (
28
- hasattr(self, "dataset")
42
+ source = "site coordinates"
43
+ # From source data (CHM15k, CL61, MRR-PRO, Copernicus, Galileo...).
44
+ # Assume value is manually set, so cannot trust it.
45
+ if (
46
+ value is None
47
+ and hasattr(self, "dataset")
48
+ and isinstance(self.dataset, netCDF4.Dataset)
49
+ and key in self.dataset.variables
50
+ and not np.all(ma.getmaskarray(self.dataset[key][:]))
51
+ ):
52
+ value = self.dataset[key][:]
53
+ source = "raw file"
54
+ # From source global attributes (MIRA).
55
+ # Seems to be manually set, so cannot trust it.
56
+ if (
57
+ value is None
58
+ and hasattr(self, "dataset")
29
59
  and isinstance(self.dataset, netCDF4.Dataset)
30
60
  and hasattr(
31
61
  self.dataset,
32
62
  key.capitalize(),
33
63
  )
34
64
  ):
35
- value = self.parse_global_attribute_numeral(key.capitalize())
36
- # From source data (BASTA / RPG):
37
- elif (
38
- hasattr(self, "dataset")
39
- and isinstance(self.dataset, netCDF4.Dataset)
40
- and key in self.dataset.variables
41
- ):
42
- value = self.dataset.variables[key][:]
65
+ value = self._parse_global_attribute_numeral(key.capitalize())
66
+ source = "raw file"
43
67
  if value is not None:
44
68
  value = float(ma.mean(value))
45
- self.data[key] = CloudnetArray(value, key)
69
+ # Convert from 0...360 to -180...180
70
+ if key == "longitude" and value > 180:
71
+ value -= 360
72
+ self.data[key] = CloudnetArray(value, key, source=source)
46
73
 
47
- def parse_global_attribute_numeral(self, key: str) -> float:
74
+ def _parse_global_attribute_numeral(self, key: str) -> float | None:
48
75
  new_str = ""
49
- for char in getattr(self.dataset, key):
76
+ attr = getattr(self.dataset, key)
77
+ if attr == "Unknown":
78
+ return None
79
+ for char in attr:
50
80
  if char.isdigit() or char == ".":
51
81
  new_str += char
52
82
  return float(new_str)
@@ -107,8 +107,8 @@ def hatpro2l1c(
107
107
  hatpro.data["irt"].dimensions = ("time", "ir_channel")
108
108
 
109
109
  for key in ("latitude", "longitude", "altitude"):
110
- if key in site_meta:
111
- hatpro.data[key] = CloudnetArray(site_meta[key], key, data_type="f4")
110
+ value = float(ma.mean(hatpro.data[key].data))
111
+ hatpro.data[key] = CloudnetArray(value, key)
112
112
 
113
113
  attrs_copy = ATTRIBUTES_1B01.copy()
114
114
  attributes = output.add_time_attribute(attrs_copy, hatpro.date)
@@ -157,8 +157,13 @@ def _mask_invalid_data(data_in: dict) -> dict:
157
157
  """Masks zeros and other fill values from data."""
158
158
  data = data_in.copy()
159
159
  fill_values = (-999, 1e-10)
160
+ extra_keys = ("air_temperature", "air_pressure")
160
161
  for name in data:
161
- if np.issubdtype(data[name].dtype, np.integer) or data[name].ndim < 2:
162
+ if (
163
+ np.issubdtype(data[name].dtype, np.integer)
164
+ or data[name].ndim < 2
165
+ and name not in extra_keys
166
+ ):
162
167
  continue
163
168
  data[name] = ma.masked_equal(data[name], 0)
164
169
  for value in fill_values:
cloudnetpy/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 71
3
- PATCH = 6
2
+ MINOR = 72
3
+ PATCH = 0
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.71.6
3
+ Version: 1.72.0
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -39,7 +39,6 @@ Requires-Python: >=3.10
39
39
  Description-Content-Type: text/markdown
40
40
  License-File: LICENSE
41
41
  Requires-Dist: ceilopyter
42
- Requires-Dist: cloudnetpy_qc>=1.15.0
43
42
  Requires-Dist: doppy>=0.5.0
44
43
  Requires-Dist: matplotlib
45
44
  Requires-Dist: mwrpy>=1.2.0
@@ -49,6 +48,7 @@ Requires-Dist: rpgpy>=0.14.5
49
48
  Requires-Dist: scikit-image
50
49
  Requires-Dist: scipy
51
50
  Provides-Extra: test
51
+ Requires-Dist: cloudnetpy_qc; extra == "test"
52
52
  Requires-Dist: mypy; extra == "test"
53
53
  Requires-Dist: pytest; extra == "test"
54
54
  Requires-Dist: pytest-flakefinder; extra == "test"
@@ -1,6 +1,6 @@
1
1
  cloudnetpy/__init__.py,sha256=X_FqY-4yg5GUj5Edo14SToLEos6JIsC3fN-v1FUgQoA,43
2
2
  cloudnetpy/cli.py,sha256=lHkeAErmAijI-Ugpd4DHRHfbZP4SXOake0LIY5Ovv_Q,20782
3
- cloudnetpy/cloudnetarray.py,sha256=Ol1ha4RPAmFZANL__U5CaMKX4oYMXYR6OnjoCZ9w3eo,7077
3
+ cloudnetpy/cloudnetarray.py,sha256=XFyXZwR4QWPyo7WLmvsu7DEELZQp1vi5FZ8F7tX_tM0,7307
4
4
  cloudnetpy/concat_lib.py,sha256=jcLppqAmVHVkykcXBcpwUr8MS_k8v2Xl2xBLmVRE_DI,12624
5
5
  cloudnetpy/constants.py,sha256=YnoSzZm35NDooJfhlulSJBc7g0eSchT3yGytRaTaJEI,845
6
6
  cloudnetpy/datasource.py,sha256=FcWS77jz56gIzwnbafDLdj-HjAyu0P_VtY7gkeVZThU,7952
@@ -9,7 +9,7 @@ cloudnetpy/metadata.py,sha256=BDEpgwZ58PHznc1gi11gtNNV4kFiMAmlHnF4huTy7nw,5982
9
9
  cloudnetpy/output.py,sha256=l0LoOhcGCBrg2EJ4NT1xZ7-UKWdV7X7yQ0fJmhkwJVc,15829
10
10
  cloudnetpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  cloudnetpy/utils.py,sha256=U0iMIKPiKLrLVAfs_u9pPuoWYW1RJHcM8dbLF9a4yIA,29796
12
- cloudnetpy/version.py,sha256=pDKpD1o6SpJO_mS4pVMyx1Z1y_3N7-u7uMi7mxGXhP8,72
12
+ cloudnetpy/version.py,sha256=kFJ4NpGbsPUkAabAFn0Zr_V6oQtTzD-3Hp7JR7KGy50,72
13
13
  cloudnetpy/categorize/__init__.py,sha256=s-SJaysvVpVVo5kidiruWQO6p3gv2TXwY1wEHYO5D6I,44
14
14
  cloudnetpy/categorize/atmos_utils.py,sha256=RcmbKxm2COkE7WEya0mK3yX5rzUbrewRVh3ekm01RtM,10598
15
15
  cloudnetpy/categorize/attenuation.py,sha256=Y_-fzmQTltWTqIZTulJhovC7a6ifpMcaAazDJcnMIOc,990
@@ -37,10 +37,10 @@ cloudnetpy/instruments/basta.py,sha256=Lb_EhQTI93S5Bd9osDbCE_tC8gZreRsHz7D2_dFOj
37
37
  cloudnetpy/instruments/ceilo.py,sha256=rkP6Vo90eS5ZhnKxZpnkuiG5ZEP86lDK8zRqoMY1aqg,9498
38
38
  cloudnetpy/instruments/ceilometer.py,sha256=pdmLVljsuciyKpaGxWxJ_f1IrJK-UrkBC0lSeuirLlU,12095
39
39
  cloudnetpy/instruments/cl61d.py,sha256=g6DNBFju3wYhLFl32DKmC8pUup7y-EupXoUU0fuoGGA,1990
40
- cloudnetpy/instruments/cloudnet_instrument.py,sha256=086GJ6Nfp7sK9ZK8UygJOn-aiVPreez674_gbrOZj4I,5183
40
+ cloudnetpy/instruments/cloudnet_instrument.py,sha256=P9r0gzBx_gdW46vzOH1zDYpfVsEdjJLwDqziZG92o9g,6615
41
41
  cloudnetpy/instruments/copernicus.py,sha256=99idcn6-iKOSvSslNjwFRng3gwlTLFjKPiT1tnVytpQ,6613
42
42
  cloudnetpy/instruments/galileo.py,sha256=BjWE15_S3tTCOmAM5k--oicI3wghKaO0hv9EUBxtbl8,4830
43
- cloudnetpy/instruments/hatpro.py,sha256=7DFULGywPru6tb9LwTl43XJTTfn7yGsHAdW9FY_zw1c,9096
43
+ cloudnetpy/instruments/hatpro.py,sha256=tIwnwM3MmtmR-LrDbUlanoXAze8Y0Pnmvx5jhLdId7Q,9092
44
44
  cloudnetpy/instruments/instruments.py,sha256=97hHMjp8fp2IKihr0XJYY3BrOlBArU7gYwYmt3OxqvU,4124
45
45
  cloudnetpy/instruments/lufft.py,sha256=nIoEKuuFGKq2dLqkX7zW-HpAifefG472tZhKfXE1yoA,4212
46
46
  cloudnetpy/instruments/mira.py,sha256=Wofp8HbiAwJce_IbOLjpEFV07H_Kh4170C9Wygiz-ew,11401
@@ -50,7 +50,7 @@ cloudnetpy/instruments/nc_radar.py,sha256=HlaZeH5939R86ukF8K-P4Kfzb5-CpLB15LU2u9
50
50
  cloudnetpy/instruments/pollyxt.py,sha256=ra7sYQ_cmkC0T9TBYrMN6iiQEZimmWGdW9Ilv61JB-Q,10027
51
51
  cloudnetpy/instruments/radiometrics.py,sha256=ySG4a042XkgjMTG8d20oAPNvFvw9bMwwiqS3zv-JF_w,11825
52
52
  cloudnetpy/instruments/rain_e_h3.py,sha256=9TdpP4UzMBNIt2iE2GL6K9dFldzTHPLOrU8Q3tcosCU,5317
53
- cloudnetpy/instruments/rpg.py,sha256=vfs_eGahPOxFjOIBczNywRwtdutOsJpSNeXZm99SIOo,17438
53
+ cloudnetpy/instruments/rpg.py,sha256=gEQd-yICUoikQnHVpikpHppUrwekdTuIf9Mk1jGxgCY,17566
54
54
  cloudnetpy/instruments/rpg_reader.py,sha256=ThztFuVrWxhmWVAfZTfQDeUiKK1XMTbtv08IBe8GK98,11364
55
55
  cloudnetpy/instruments/toa5.py,sha256=CfmmBMv5iMGaWHIGBK01Rw24cuXC1R1RMNTXkmsm340,1760
56
56
  cloudnetpy/instruments/vaisala.py,sha256=RKAw_fVry4YOUF0i2_-2jLIc6_H85oL8USA4ji9rh0o,4583
@@ -115,10 +115,10 @@ cloudnetpy/products/lwc.py,sha256=sl6Al2tuH3KkCBrPbWTmuz3jlD5UQJ4D6qBsn1tt2CQ,18
115
115
  cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
116
116
  cloudnetpy/products/mwr_tools.py,sha256=rd7UC67O4fsIE5SaHVZ4qWvUJTj41ZGwgQWPwZzOM14,5377
117
117
  cloudnetpy/products/product_tools.py,sha256=uu4l6reuGbPcW3TgttbaSrqIKbyYGhBVTdnC7opKvmg,11101
118
- cloudnetpy-1.71.6.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
118
+ cloudnetpy-1.72.0.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
119
119
  docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
120
- cloudnetpy-1.71.6.dist-info/METADATA,sha256=i-Sofs6QArvcbi7NqFIOJPPpt6HU_TX7GQB6FpL_0nQ,5787
121
- cloudnetpy-1.71.6.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
122
- cloudnetpy-1.71.6.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
123
- cloudnetpy-1.71.6.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
124
- cloudnetpy-1.71.6.dist-info/RECORD,,
120
+ cloudnetpy-1.72.0.dist-info/METADATA,sha256=VVJsfXfV-GMlu84TBWTAHTSzDwJlt7-q3U_RTnSthAE,5796
121
+ cloudnetpy-1.72.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
122
+ cloudnetpy-1.72.0.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
123
+ cloudnetpy-1.72.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
124
+ cloudnetpy-1.72.0.dist-info/RECORD,,