cloudnetpy 1.81.2__tar.gz → 1.82.1__tar.gz

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.
Files changed (132) hide show
  1. {cloudnetpy-1.81.2/cloudnetpy.egg-info → cloudnetpy-1.82.1}/PKG-INFO +1 -1
  2. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/hatpro.py +7 -1
  3. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/weather_station.py +12 -0
  4. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/output.py +38 -32
  5. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/mwr_tools.py +16 -19
  6. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/version.py +2 -2
  7. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1/cloudnetpy.egg-info}/PKG-INFO +1 -1
  8. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/LICENSE +0 -0
  9. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/MANIFEST.in +0 -0
  10. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/README.md +0 -0
  11. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/__init__.py +0 -0
  12. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/__init__.py +0 -0
  13. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/atmos_utils.py +0 -0
  14. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/attenuation.py +0 -0
  15. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/attenuations/__init__.py +0 -0
  16. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/attenuations/gas_attenuation.py +0 -0
  17. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/attenuations/liquid_attenuation.py +0 -0
  18. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/attenuations/melting_attenuation.py +0 -0
  19. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/attenuations/rain_attenuation.py +0 -0
  20. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/categorize.py +0 -0
  21. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/classify.py +0 -0
  22. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/containers.py +0 -0
  23. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/disdrometer.py +0 -0
  24. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/droplet.py +0 -0
  25. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/falling.py +0 -0
  26. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/freezing.py +0 -0
  27. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/insects.py +0 -0
  28. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/itu.py +0 -0
  29. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/lidar.py +0 -0
  30. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/melting.py +0 -0
  31. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/model.py +0 -0
  32. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/mwr.py +0 -0
  33. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/categorize/radar.py +0 -0
  34. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/cli.py +0 -0
  35. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/cloudnetarray.py +0 -0
  36. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/concat_lib.py +0 -0
  37. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/constants.py +0 -0
  38. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/datasource.py +0 -0
  39. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/exceptions.py +0 -0
  40. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/__init__.py +0 -0
  41. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/basta.py +0 -0
  42. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/bowtie.py +0 -0
  43. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/ceilo.py +0 -0
  44. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/ceilometer.py +0 -0
  45. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/cl61d.py +0 -0
  46. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/cloudnet_instrument.py +0 -0
  47. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/copernicus.py +0 -0
  48. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/disdrometer/__init__.py +0 -0
  49. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/disdrometer/common.py +0 -0
  50. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/disdrometer/parsivel.py +0 -0
  51. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/disdrometer/thies.py +0 -0
  52. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/fd12p.py +0 -0
  53. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/galileo.py +0 -0
  54. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/instruments.py +0 -0
  55. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/lufft.py +0 -0
  56. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/mira.py +0 -0
  57. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/mrr.py +0 -0
  58. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/nc_lidar.py +0 -0
  59. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/nc_radar.py +0 -0
  60. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/pollyxt.py +0 -0
  61. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/radiometrics.py +0 -0
  62. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/rain_e_h3.py +0 -0
  63. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/rpg.py +0 -0
  64. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/rpg_reader.py +0 -0
  65. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/toa5.py +0 -0
  66. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/instruments/vaisala.py +0 -0
  67. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/metadata.py +0 -0
  68. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/__init__.py +0 -0
  69. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/file_handler.py +0 -0
  70. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/metadata.py +0 -0
  71. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/model_metadata.py +0 -0
  72. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/plotting/__init__.py +0 -0
  73. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/plotting/plot_meta.py +0 -0
  74. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/plotting/plot_tools.py +0 -0
  75. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/plotting/plotting.py +0 -0
  76. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/products/__init__.py +0 -0
  77. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/products/advance_methods.py +0 -0
  78. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/products/grid_methods.py +0 -0
  79. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/products/model_products.py +0 -0
  80. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/products/observation_products.py +0 -0
  81. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/products/product_resampling.py +0 -0
  82. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/products/tools.py +0 -0
  83. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/statistics/__init__.py +0 -0
  84. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/statistics/statistical_methods.py +0 -0
  85. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/__init__.py +0 -0
  86. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/__init__.py +0 -0
  87. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/conftest.py +0 -0
  88. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/__init__.py +0 -0
  89. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/main.py +0 -0
  90. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_cf/tests.py +0 -0
  91. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/__init__.py +0 -0
  92. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/main.py +0 -0
  93. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_iwc/tests.py +0 -0
  94. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/__init__.py +0 -0
  95. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/main.py +0 -0
  96. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/e2e/process_lwc/tests.py +0 -0
  97. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/__init__.py +0 -0
  98. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/conftest.py +0 -0
  99. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_advance_methods.py +0 -0
  100. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_grid_methods.py +0 -0
  101. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_model_products.py +0 -0
  102. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_observation_products.py +0 -0
  103. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_plot_tools.py +0 -0
  104. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_plotting.py +0 -0
  105. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_statistical_methods.py +0 -0
  106. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/tests/unit/test_tools.py +0 -0
  107. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/model_evaluation/utils.py +0 -0
  108. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/plotting/__init__.py +0 -0
  109. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/plotting/plot_meta.py +0 -0
  110. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/plotting/plotting.py +0 -0
  111. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/__init__.py +0 -0
  112. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/classification.py +0 -0
  113. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/der.py +0 -0
  114. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/drizzle.py +0 -0
  115. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/drizzle_error.py +0 -0
  116. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/drizzle_tools.py +0 -0
  117. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/epsilon.py +0 -0
  118. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/ier.py +0 -0
  119. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/iwc.py +0 -0
  120. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/lwc.py +0 -0
  121. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/mie_lu_tables.nc +0 -0
  122. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/products/product_tools.py +0 -0
  123. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/py.typed +0 -0
  124. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy/utils.py +0 -0
  125. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy.egg-info/SOURCES.txt +0 -0
  126. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy.egg-info/dependency_links.txt +0 -0
  127. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy.egg-info/entry_points.txt +0 -0
  128. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy.egg-info/requires.txt +0 -0
  129. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/cloudnetpy.egg-info/top_level.txt +0 -0
  130. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/docs/source/conf.py +0 -0
  131. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/pyproject.toml +0 -0
  132. {cloudnetpy-1.81.2 → cloudnetpy-1.82.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.81.2
3
+ Version: 1.82.1
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -42,6 +42,7 @@ def hatpro2l1c(
42
42
  output_file: str | PathLike,
43
43
  site_meta: dict,
44
44
  instrument_type: IType = "hatpro",
45
+ lidar_file: str | PathLike | None = None,
45
46
  uuid: str | UUID | None = None,
46
47
  date: str | datetime.date | None = None,
47
48
  ) -> UUID:
@@ -52,6 +53,7 @@ def hatpro2l1c(
52
53
  output_file: Output file name.
53
54
  site_meta: Dictionary containing information about the site and instrument
54
55
  instrument_type: Specific type of the RPG microwave radiometer.
56
+ lidar_file: Path to a lidar file.
55
57
  uuid: Set specific UUID for the file.
56
58
  date: Expected date in the input files.
57
59
 
@@ -71,6 +73,7 @@ def hatpro2l1c(
71
73
  str(mwr_dir),
72
74
  instrument_type=instrument_type,
73
75
  output_file=str(output_file),
76
+ lidar_path=lidar_file,
74
77
  coeff_files=coeff_files,
75
78
  instrument_config=site_meta,
76
79
  date=date,
@@ -133,7 +136,10 @@ def hatpro2l1c(
133
136
  nc.mwrpy_version = mwrpy_version
134
137
  nc.mwrpy_coefficients = ", ".join(site_meta["coefficientLinks"])
135
138
  nc.history = nc.history.replace("mwr", "mwr-l1c")
136
-
139
+ if lidar_file is not None:
140
+ with netCDF4.Dataset(lidar_file) as lidar_nc:
141
+ nc.source = f"{nc.source}\n{lidar_nc.source}"
142
+ nc.history = f"{nc.history}\n{lidar_nc.history}"
137
143
  return uuid
138
144
 
139
145
 
@@ -79,12 +79,14 @@ def ws2nc(
79
79
  ws.add_date()
80
80
  ws.add_site_geolocation()
81
81
  ws.add_data()
82
+ ws.remove_duplicate_timestamps()
82
83
  ws.convert_temperature_and_humidity()
83
84
  ws.convert_pressure()
84
85
  ws.convert_rainfall_rate()
85
86
  ws.convert_rainfall_amount()
86
87
  ws.normalize_cumulative_amount("rainfall_amount")
87
88
  ws.calculate_rainfall_amount()
89
+ ws.wrap_wind_direction()
88
90
  attributes = output.add_time_attribute({}, ws.date)
89
91
  output.update_attributes(ws.data, attributes)
90
92
  output.save_level1b(ws, output_file, uuid)
@@ -148,6 +150,16 @@ class WS(CSVFile):
148
150
  def convert_rainfall_amount(self) -> None:
149
151
  pass
150
152
 
153
+ def wrap_wind_direction(self) -> None:
154
+ if "wind_direction" not in self.data:
155
+ return
156
+ # Wrap values little outside of [0, 360), keep original values
157
+ # otherwise.
158
+ threshold = 2
159
+ values = self.data["wind_direction"].data
160
+ values[(values > -threshold) & (values < 0)] += 360
161
+ values[(values >= 360) & (values < 360 + threshold)] -= 360
162
+
151
163
 
152
164
  class PalaiseauWS(WS):
153
165
  def __init__(self, filenames: Sequence[str | PathLike], site_meta: dict) -> None:
@@ -197,46 +197,52 @@ def get_source_uuids(data: Observations | list[netCDF4.Dataset | DataSource]) ->
197
197
  def merge_history(
198
198
  nc: netCDF4.Dataset, file_type: str, data: Observations | DataSource
199
199
  ) -> None:
200
- """Merges history fields from one or several files and creates a new record.
200
+ """Merges history fields from one or several files and creates a new record."""
201
+
202
+ def extract_history(obj: DataSource | Observations) -> list[str]:
203
+ if hasattr(obj, "dataset") and hasattr(obj.dataset, "history"):
204
+ history = obj.dataset.history
205
+ if isinstance(obj, Model):
206
+ return [history.split("\n")[-1]]
207
+ return history.split("\n")
208
+ return []
209
+
210
+ histories: list[str] = []
211
+ if isinstance(data, DataSource):
212
+ histories.extend(extract_history(data))
213
+ elif isinstance(data, Observations):
214
+ for field in fields(data):
215
+ histories.extend(extract_history(getattr(data, field.name)))
201
216
 
202
- Args:
203
- nc: The netCDF Dataset instance.
204
- file_type: Long description of the file.
205
- data: Dictionary of objects with history attribute.
217
+ # Remove duplicates
218
+ histories = list(dict.fromkeys(histories))
206
219
 
207
- """
220
+ def parse_time(line: str) -> datetime.datetime:
221
+ try:
222
+ return datetime.datetime.strptime(
223
+ line.split(" - ")[0].strip(), "%Y-%m-%d %H:%M:%S %z"
224
+ )
225
+ except ValueError:
226
+ return datetime.datetime.min.replace(
227
+ tzinfo=datetime.timezone.utc
228
+ ) # malformed lines to bottom
229
+
230
+ histories.sort(key=parse_time, reverse=True)
208
231
  new_record = f"{utils.get_time()} - {file_type} file created"
209
- histories = []
210
- if (
211
- isinstance(data, DataSource)
212
- and hasattr(data, "dataset")
213
- and hasattr(data.dataset, "history")
214
- ):
215
- history = data.dataset.history
216
- histories.append(history)
217
- if isinstance(data, Observations):
218
- for field in fields(data):
219
- obj = getattr(data, field.name)
220
- if hasattr(obj, "dataset") and hasattr(obj.dataset, "history"):
221
- history = obj.dataset.history
222
- history = history.split("\n")[-1] if isinstance(obj, Model) else history
223
- histories.append(history)
224
- histories.sort(reverse=True)
225
- old_history = [f"\n{history}" for history in histories]
226
- old_history_str = "".join(old_history)
227
- nc.history = f"{new_record}{old_history_str}"
232
+ nc.history = new_record + "".join(f"\n{h}" for h in histories)
228
233
 
229
234
 
230
235
  def add_source_instruments(nc: netCDF4.Dataset, data: Observations) -> None:
231
236
  """Adds source attribute to categorize file."""
232
- sources = []
233
- for field in fields(data):
234
- obj = getattr(data, field.name)
235
- if hasattr(obj, "source"):
236
- sources.append(obj.source)
237
+ sources = {
238
+ src
239
+ for field in fields(data)
240
+ for obj in [getattr(data, field.name)]
241
+ if hasattr(obj, "source")
242
+ for src in obj.source.split("\n")
243
+ }
237
244
  if sources:
238
- formatted_sources = [sources[0]] + [f"\n{source}" for source in sources[1:]]
239
- nc.source = "".join(formatted_sources)
245
+ nc.source = "\n".join(sorted(sources))
240
246
 
241
247
 
242
248
  def init_file(
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import tempfile
3
3
  from os import PathLike
4
- from typing import TYPE_CHECKING, Literal
4
+ from typing import Literal
5
5
  from uuid import UUID
6
6
 
7
7
  import netCDF4
@@ -16,14 +16,12 @@ from mwrpy.version import __version__ as mwrpy_version
16
16
  from cloudnetpy import output, utils
17
17
  from cloudnetpy.exceptions import ValidTimeStampError
18
18
 
19
- if TYPE_CHECKING:
20
- from collections.abc import Callable
21
-
22
19
 
23
20
  def generate_mwr_single(
24
21
  mwr_l1c_file: str | PathLike,
25
22
  output_file: str | PathLike,
26
23
  uuid: str | UUID | None = None,
24
+ lwp_offset: tuple[float | None, float | None] = (None, None),
27
25
  ) -> UUID:
28
26
  """Generates MWR single-pointing product including liquid water path, integrated
29
27
  water vapor, etc. from zenith measurements.
@@ -32,6 +30,7 @@ def generate_mwr_single(
32
30
  mwr_l1c_file: The Level 1C MWR file to be processed.
33
31
  output_file: The file path where the output file should be saved.
34
32
  uuid: The UUID, if any, associated with the output file. Defaults to None.
33
+ lwp_offset: Optional offset to apply to the liquid water path.
35
34
 
36
35
  Returns:
37
36
  UUID of generated file.
@@ -39,13 +38,14 @@ def generate_mwr_single(
39
38
  Example:
40
39
  >>> generate_mwr_single('input_mwr_l1c_file', 'output_file', 'abcdefg1234567')
41
40
  """
42
- return _generate_product(mwr_l1c_file, output_file, uuid, "single")
41
+ return _generate_product(mwr_l1c_file, output_file, uuid, "single", lwp_offset)
43
42
 
44
43
 
45
44
  def generate_mwr_lhumpro(
46
45
  mwr_l1c_file: str | PathLike,
47
46
  output_file: str | PathLike,
48
47
  uuid: str | UUID | None = None,
48
+ lwp_offset: tuple[float | None, float | None] = (None, None),
49
49
  ) -> UUID:
50
50
  """Generates LHUMPRO single-pointing product including liquid water path, integrated
51
51
  water vapor, etc. from zenith measurements.
@@ -54,6 +54,7 @@ def generate_mwr_lhumpro(
54
54
  mwr_l1c_file: The Level 1C MWR file to be processed.
55
55
  output_file: The file path where the output file should be saved.
56
56
  uuid: The UUID, if any, associated with the output file. Defaults to None.
57
+ lwp_offset: Optional offset to apply to the liquid water path.
57
58
 
58
59
  Returns:
59
60
  UUID of generated file.
@@ -61,7 +62,7 @@ def generate_mwr_lhumpro(
61
62
  Example:
62
63
  >>> generate_mwr_lhumpro('input_mwr_l1c_file', 'output_file', 'abcdefg1234567')
63
64
  """
64
- return _generate_product(mwr_l1c_file, output_file, uuid, "lhumpro")
65
+ return _generate_product(mwr_l1c_file, output_file, uuid, "lhumpro", lwp_offset)
65
66
 
66
67
 
67
68
  def generate_mwr_multi(
@@ -88,24 +89,20 @@ def _generate_product(
88
89
  mwr_l1c_file: str | PathLike,
89
90
  output_file: str | PathLike,
90
91
  uuid: str | UUID | None,
91
- product: Literal["multi", "single", "lhumpro"],
92
+ product: Literal["single", "multi", "lhumpro"],
93
+ lwp_offset: tuple[float | None, float | None] = (None, None),
92
94
  ) -> UUID:
93
95
  uuid = utils.get_uuid(uuid)
94
- fun: Callable
95
- if product == "multi":
96
- fun = gen_multi
97
- elif product == "single":
98
- fun = gen_single
99
- elif product == "lhumpro":
100
- fun = gen_lhumpro
101
- product = "single"
102
- else:
103
- msg = f"Invalid product: {product}"
104
- raise ValueError(msg)
105
96
  with tempfile.TemporaryDirectory() as temp_dir:
106
97
  coeffs = _read_mwrpy_coeffs(mwr_l1c_file, temp_dir)
107
98
  try:
108
- fun(None, mwr_l1c_file, output_file, coeff_files=coeffs)
99
+ if product == "multi":
100
+ gen_multi(None, mwr_l1c_file, output_file, coeffs)
101
+ elif product == "single":
102
+ gen_single(None, mwr_l1c_file, output_file, lwp_offset, coeffs)
103
+ else:
104
+ gen_lhumpro(None, mwr_l1c_file, output_file, lwp_offset, coeffs)
105
+ product = "single"
109
106
  except MissingInputData as err:
110
107
  raise ValidTimeStampError from err
111
108
  with (
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
- MINOR = 81
3
- PATCH = 2
2
+ MINOR = 82
3
+ PATCH = 1
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.81.2
3
+ Version: 1.82.1
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
File without changes
File without changes
File without changes
File without changes
File without changes