cloudnetpy 1.74.0__py3-none-any.whl → 1.74.2__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.
@@ -150,6 +150,13 @@ HALO = Instrument(
150
150
  model="StreamLine",
151
151
  )
152
152
 
153
+ WINDCUBE_WLS100S = Instrument(
154
+ manufacturer="Vaisala",
155
+ domain="lidar",
156
+ category="Doppler lidar",
157
+ model="WindCube WLS100S",
158
+ )
159
+
153
160
  WINDCUBE_WLS200S = Instrument(
154
161
  manufacturer="Vaisala",
155
162
  domain="lidar",
@@ -157,6 +164,13 @@ WINDCUBE_WLS200S = Instrument(
157
164
  model="WindCube WLS200S",
158
165
  )
159
166
 
167
+ WINDCUBE_WLS400S = Instrument(
168
+ manufacturer="Vaisala",
169
+ domain="lidar",
170
+ category="Doppler lidar",
171
+ model="WindCube WLS400S",
172
+ )
173
+
160
174
  WINDCUBE_WLS70 = Instrument(
161
175
  manufacturer="Vaisala",
162
176
  domain="lidar",
@@ -1,7 +1,10 @@
1
1
  import csv
2
2
  import datetime
3
3
  import math
4
+ import re
5
+ from collections import defaultdict
4
6
  from collections.abc import Iterable
7
+ from os import PathLike
5
8
 
6
9
  import numpy as np
7
10
  from numpy import ma
@@ -59,6 +62,8 @@ def ws2nc(
59
62
  ws = JuelichWS(weather_station_file, site_meta)
60
63
  elif site_meta["name"] == "Lampedusa":
61
64
  ws = LampedusaWS(weather_station_file, site_meta)
65
+ elif site_meta["name"] == "Limassol":
66
+ ws = LimassolWS(weather_station_file, site_meta)
62
67
  else:
63
68
  msg = "Unsupported site"
64
69
  raise ValueError(msg)
@@ -122,6 +127,8 @@ class WS(CSVFile):
122
127
  self.data["rainfall_rate"].data = rainfall_rate / 60 / 1000 # mm/min -> m/s
123
128
 
124
129
  def convert_pressure(self) -> None:
130
+ if "air_pressure" not in self.data:
131
+ return
125
132
  self.data["air_pressure"].data = self.data["air_pressure"][:] * HPA_TO_PA
126
133
 
127
134
  def convert_time(self) -> None:
@@ -539,3 +546,103 @@ class LampedusaWS(WS):
539
546
  "rainfall_rate": raw_data["rain1m"],
540
547
  }
541
548
  return self.format_data(data)
549
+
550
+
551
+ class LimassolWS(WS):
552
+ def __init__(self, filenames: list[str], site_meta: dict):
553
+ super().__init__(site_meta)
554
+ self.filenames = filenames
555
+ self._data = defaultdict(list)
556
+ for filename in filenames:
557
+ for key, values in _parse_sirta(filename).items():
558
+ self._data[key].extend(values)
559
+ self._data["time"] = self._data.pop("Date Time (yyyy-mm-ddThh:mm:ss)")
560
+
561
+ def convert_time(self) -> None:
562
+ decimal_hours = datetime2decimal_hours(self._data["time"])
563
+ self.data["time"] = CloudnetArray(decimal_hours, "time")
564
+
565
+ def screen_timestamps(self, date: str) -> None:
566
+ dates = [str(d.date()) for d in self._data["time"]]
567
+ valid_ind = [ind for ind, d in enumerate(dates) if d == date]
568
+ if not valid_ind:
569
+ raise ValidTimeStampError
570
+ for key in self._data:
571
+ self._data[key] = [
572
+ x for ind, x in enumerate(self._data[key]) if ind in valid_ind
573
+ ]
574
+
575
+ def add_data(self) -> None:
576
+ self.data["air_temperature"] = CloudnetArray(
577
+ np.array(self._data["Air temperature (°C)"]), "air_temperature"
578
+ )
579
+ self.data["relative_humidity"] = CloudnetArray(
580
+ np.array(self._data["Relative humidity (%)"]), "relative_humidity"
581
+ )
582
+ self.data["rainfall_rate"] = CloudnetArray(
583
+ np.array(self._data["Total precipitation (mm)"]), "rainfall_rate"
584
+ )
585
+ # Wind speed and direction are available since 2025-02-13:
586
+ if (
587
+ "Wind speed at 10m (m/s)" in self._data
588
+ and "Wind direction at 10m (degrees)" in self._data
589
+ ):
590
+ self.data["wind_speed"] = CloudnetArray(
591
+ np.array(self._data["Wind speed at 10m (m/s)"]), "wind_speed"
592
+ )
593
+ self.data["wind_direction"] = CloudnetArray(
594
+ np.array(self._data["Wind direction at 10m (degrees)"]),
595
+ "wind_direction",
596
+ )
597
+ else:
598
+ self.data["wind_speed"] = CloudnetArray(
599
+ np.array(self._data["Wind speed (m/s)"]), "wind_speed"
600
+ )
601
+
602
+ def convert_rainfall_rate(self) -> None:
603
+ rainfall_rate = self.data["rainfall_rate"][:]
604
+ self.data["rainfall_rate"].data = (
605
+ rainfall_rate / (10 * 60) / 1000
606
+ ) # mm/(10 min) -> m/s
607
+
608
+
609
+ def _parse_sirta(filename: str | PathLike):
610
+ """Parse SIRTA-style weather station file."""
611
+ with open(filename, "rb") as f:
612
+ raw_content = f.read()
613
+ try:
614
+ content = raw_content.decode("utf-8")
615
+ except UnicodeDecodeError:
616
+ content = raw_content.decode("latin-1")
617
+ lines = [line.strip() for line in content.splitlines()]
618
+ columns: list[str] = []
619
+ output: dict = {}
620
+ for line in lines:
621
+ m = re.fullmatch(r"#\s*Col.\s*(\d+)\s*:\s*(.*)", line)
622
+ if m is None:
623
+ continue
624
+ if m[1] != str(len(columns) + 1):
625
+ msg = f"Expected column {m[1]}, found {len(columns)+1}"
626
+ raise ValueError(msg)
627
+ columns.append(m[2])
628
+ output[m[2]] = []
629
+ for line in lines:
630
+ if not line or line.startswith("#"):
631
+ continue
632
+ values = line.split()
633
+ if len(columns) != len(values):
634
+ continue
635
+ for column, value in zip(columns, values, strict=False):
636
+ parsed: float | datetime.datetime
637
+ if column == "Date Time (yyyy-mm-ddThh:mm:ss)":
638
+ parsed = datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S").replace(
639
+ tzinfo=datetime.timezone.utc
640
+ )
641
+ elif column == "Date Time (yyyy-mm-ddThh:mm:ssZ)":
642
+ parsed = datetime.datetime.strptime(
643
+ value, "%Y-%m-%dT%H:%M:%SZ"
644
+ ).replace(tzinfo=datetime.timezone.utc)
645
+ else:
646
+ parsed = float(value)
647
+ output[column].append(parsed)
648
+ return output
cloudnetpy/version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  MAJOR = 1
2
2
  MINOR = 74
3
- PATCH = 0
3
+ PATCH = 2
4
4
  __version__ = f"{MAJOR}.{MINOR}.{PATCH}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudnetpy
3
- Version: 1.74.0
3
+ Version: 1.74.2
4
4
  Summary: Python package for Cloudnet processing
5
5
  Author: Simo Tukiainen
6
6
  License: MIT License
@@ -9,7 +9,7 @@ cloudnetpy/metadata.py,sha256=lO7BCbVAzFoH3Nq-VuezYX0f7MnbG1Zp11g5GSiuQwM,6189
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=ui6sq8g1HlgfOQO644iNHsRGqpDwS3q-5uGR2y2tOAk,33325
12
- cloudnetpy/version.py,sha256=NyE8VYDVST3jInl97hnM5B9JXFGdkILThRQ42YmU1wA,72
12
+ cloudnetpy/version.py,sha256=4KeWLBeLB8eQA59GiUp8yqCMqR1Ru_4uEvza5rrmzd8,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
@@ -42,7 +42,7 @@ cloudnetpy/instruments/cloudnet_instrument.py,sha256=3qJe8STIvsU8irj79xuElFUZa0j
42
42
  cloudnetpy/instruments/copernicus.py,sha256=99idcn6-iKOSvSslNjwFRng3gwlTLFjKPiT1tnVytpQ,6613
43
43
  cloudnetpy/instruments/galileo.py,sha256=BjWE15_S3tTCOmAM5k--oicI3wghKaO0hv9EUBxtbl8,4830
44
44
  cloudnetpy/instruments/hatpro.py,sha256=D1iTR58ao6zA556LegPDhh4JHozxiup_9mUuLjR0NzE,9006
45
- cloudnetpy/instruments/instruments.py,sha256=97hHMjp8fp2IKihr0XJYY3BrOlBArU7gYwYmt3OxqvU,4124
45
+ cloudnetpy/instruments/instruments.py,sha256=BdtUBvBUpjIyXubirHkP1Xa9mtlF8CgPEnFPokJgyrQ,4408
46
46
  cloudnetpy/instruments/lufft.py,sha256=nIoEKuuFGKq2dLqkX7zW-HpAifefG472tZhKfXE1yoA,4212
47
47
  cloudnetpy/instruments/mira.py,sha256=Wofp8HbiAwJce_IbOLjpEFV07H_Kh4170C9Wygiz-ew,11401
48
48
  cloudnetpy/instruments/mrr.py,sha256=eeAzCp3CiHGauywjwvMUAFwZ4vBOZMcd3IlF8KsrLQo,5711
@@ -55,7 +55,7 @@ cloudnetpy/instruments/rpg.py,sha256=gjvDomyoqSaeS3-X4EuesvWBp32BNoD-CeuvBOP19AI
55
55
  cloudnetpy/instruments/rpg_reader.py,sha256=ThztFuVrWxhmWVAfZTfQDeUiKK1XMTbtv08IBe8GK98,11364
56
56
  cloudnetpy/instruments/toa5.py,sha256=CfmmBMv5iMGaWHIGBK01Rw24cuXC1R1RMNTXkmsm340,1760
57
57
  cloudnetpy/instruments/vaisala.py,sha256=RKAw_fVry4YOUF0i2_-2jLIc6_H85oL8USA4ji9rh0o,4583
58
- cloudnetpy/instruments/weather_station.py,sha256=pg5Rf6A0qkbAYV1NvC1-oQLkwe9-gmLxHJ8CYW7xgYI,20365
58
+ cloudnetpy/instruments/weather_station.py,sha256=Ok2i4RUkbEHdOuXuDPkMPSRp_vAiST7SQeg2amIavyI,24530
59
59
  cloudnetpy/instruments/disdrometer/__init__.py,sha256=lyjwttWvFvuwYxEkusoAvgRcbBmglmOp5HJOpXUqLWo,93
60
60
  cloudnetpy/instruments/disdrometer/common.py,sha256=g52iK2aNp3Z88kovUmGVpC54NZomPa9D871gzO0AmQ4,9267
61
61
  cloudnetpy/instruments/disdrometer/parsivel.py,sha256=HJZrEysQkx9MiIVPDV25CYHpXi_SjgZlgO-otoaKK34,25640
@@ -116,10 +116,10 @@ cloudnetpy/products/lwc.py,sha256=sl6Al2tuH3KkCBrPbWTmuz3jlD5UQJ4D6qBsn1tt2CQ,18
116
116
  cloudnetpy/products/mie_lu_tables.nc,sha256=It4fYpqJXlqOgL8jeZ-PxGzP08PMrELIDVe55y9ob58,16637951
117
117
  cloudnetpy/products/mwr_tools.py,sha256=1SRaQRW6-1svfnUk25sMyWXSwRJ1fg7v48TsMENZQpg,5103
118
118
  cloudnetpy/products/product_tools.py,sha256=uu4l6reuGbPcW3TgttbaSrqIKbyYGhBVTdnC7opKvmg,11101
119
- cloudnetpy-1.74.0.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
119
+ cloudnetpy-1.74.2.dist-info/licenses/LICENSE,sha256=wcZF72bdaoG9XugpyE95Juo7lBQOwLuTKBOhhtANZMM,1094
120
120
  docs/source/conf.py,sha256=IKiFWw6xhUd8NrCg0q7l596Ck1d61XWeVjIFHVSG9Og,1490
121
- cloudnetpy-1.74.0.dist-info/METADATA,sha256=YopNoTclJY-YXuOMqKereaBmfE4KyID0PAwfmzs_wMU,5796
122
- cloudnetpy-1.74.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
123
- cloudnetpy-1.74.0.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
124
- cloudnetpy-1.74.0.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
125
- cloudnetpy-1.74.0.dist-info/RECORD,,
121
+ cloudnetpy-1.74.2.dist-info/METADATA,sha256=TzRIHrIRI_ptfXhtxqSgmB5PG5YiF9YHnR2gUhCSQsE,5796
122
+ cloudnetpy-1.74.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
123
+ cloudnetpy-1.74.2.dist-info/entry_points.txt,sha256=HhY7LwCFk4qFgDlXx_Fy983ZTd831WlhtdPIzV-Y3dY,51
124
+ cloudnetpy-1.74.2.dist-info/top_level.txt,sha256=ibSPWRr6ojS1i11rtBFz2_gkIe68mggj7aeswYfaOo0,16
125
+ cloudnetpy-1.74.2.dist-info/RECORD,,