pypromice 1.5.3__py3-none-any.whl → 1.7.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.

Potentially problematic release.


This version of pypromice might be problematic. Click here for more details.

Files changed (67) hide show
  1. pypromice/__init__.py +2 -0
  2. pypromice/{qc → core/qc}/github_data_issues.py +22 -13
  3. pypromice/{qc → core/qc}/percentiles/compute_thresholds.py +2 -2
  4. pypromice/{qc → core/qc}/persistence.py +22 -29
  5. pypromice/{process → core/qc}/value_clipping.py +3 -3
  6. pypromice/core/resampling.py +142 -0
  7. pypromice/core/variables/__init__.py +1 -0
  8. pypromice/core/variables/air_temperature.py +64 -0
  9. pypromice/core/variables/gps.py +221 -0
  10. pypromice/core/variables/humidity.py +111 -0
  11. pypromice/core/variables/precipitation.py +108 -0
  12. pypromice/core/variables/pressure_transducer_depth.py +79 -0
  13. pypromice/core/variables/radiation.py +422 -0
  14. pypromice/core/variables/station_boom_height.py +75 -0
  15. pypromice/core/variables/station_pose.py +375 -0
  16. pypromice/io/bufr/__init__.py +0 -0
  17. pypromice/{postprocess → io/bufr}/bufr_to_csv.py +1 -1
  18. pypromice/{postprocess → io/bufr}/create_bufr_files.py +2 -2
  19. pypromice/{postprocess → io/bufr}/get_bufr.py +6 -6
  20. pypromice/{postprocess → io/bufr}/real_time_utilities.py +3 -3
  21. pypromice/io/ingest/__init__.py +0 -0
  22. pypromice/{utilities → io/ingest}/git.py +1 -3
  23. pypromice/io/ingest/l0.py +294 -0
  24. pypromice/io/ingest/l0_repository.py +103 -0
  25. pypromice/io/ingest/toa5.py +87 -0
  26. pypromice/{process → io}/write.py +1 -1
  27. pypromice/pipeline/L0toL1.py +291 -0
  28. pypromice/pipeline/L1toL2.py +233 -0
  29. pypromice/{process → pipeline}/L2toL3.py +113 -118
  30. pypromice/pipeline/__init__.py +4 -0
  31. pypromice/{process → pipeline}/aws.py +10 -82
  32. pypromice/{process → pipeline}/get_l2.py +2 -2
  33. pypromice/{process → pipeline}/get_l2tol3.py +19 -22
  34. pypromice/{process → pipeline}/join_l2.py +31 -32
  35. pypromice/{process → pipeline}/join_l3.py +16 -14
  36. pypromice/{process → pipeline}/resample.py +75 -51
  37. pypromice/{process → pipeline}/utilities.py +0 -22
  38. pypromice/resources/file_attributes.csv +4 -4
  39. pypromice/resources/variable_aliases_GC-Net.csv +2 -2
  40. pypromice/resources/variables.csv +27 -24
  41. {pypromice-1.5.3.dist-info → pypromice-1.7.0.dist-info}/METADATA +1 -2
  42. pypromice-1.7.0.dist-info/RECORD +65 -0
  43. pypromice-1.7.0.dist-info/entry_points.txt +12 -0
  44. pypromice/get/__init__.py +0 -1
  45. pypromice/get/get.py +0 -211
  46. pypromice/get/get_promice_data.py +0 -56
  47. pypromice/process/L0toL1.py +0 -564
  48. pypromice/process/L1toL2.py +0 -824
  49. pypromice/process/__init__.py +0 -4
  50. pypromice/process/load.py +0 -161
  51. pypromice-1.5.3.dist-info/RECORD +0 -54
  52. pypromice-1.5.3.dist-info/entry_points.txt +0 -13
  53. /pypromice/{postprocess → core}/__init__.py +0 -0
  54. /pypromice/{utilities → core}/dependency_graph.py +0 -0
  55. /pypromice/{qc → core/qc}/__init__.py +0 -0
  56. /pypromice/{qc → core/qc}/percentiles/__init__.py +0 -0
  57. /pypromice/{qc → core/qc}/percentiles/outlier_detector.py +0 -0
  58. /pypromice/{qc → core/qc}/percentiles/thresholds.csv +0 -0
  59. /pypromice/{process → core/variables}/wind.py +0 -0
  60. /pypromice/{utilities → io}/__init__.py +0 -0
  61. /pypromice/{postprocess → io/bufr}/bufr_utilities.py +0 -0
  62. /pypromice/{postprocess → io/bufr}/positions_seed.csv +0 -0
  63. /pypromice/{station_configuration.py → io/bufr/station_configuration.py} +0 -0
  64. /pypromice/{postprocess → io}/make_metadata_csv.py +0 -0
  65. {pypromice-1.5.3.dist-info → pypromice-1.7.0.dist-info}/WHEEL +0 -0
  66. {pypromice-1.5.3.dist-info → pypromice-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
  67. {pypromice-1.5.3.dist-info → pypromice-1.7.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,375 @@
1
+ __all__ = ["convert_and_filter_tilt", "apply_tilt_factor",
2
+ "smooth_tilt_with_moving_window", "interpolate_tilt",
3
+ "interpolate_rotation", "calculate_spherical_tilt",
4
+ "calculate_declination", "calculate_hour_angle",
5
+ "calculate_sun_direction_degrees", "calculate_zenith",
6
+ "calculate_angle_difference"]
7
+
8
+ import numpy as np
9
+ import xarray as xr
10
+ import pandas as pd
11
+
12
+ tilt_smoothing_win_size = 7 # Station tilt smoothing window size
13
+ tilt_stddev_threshold = 0.2 # Station tilt interpolation standard deviation threshold
14
+ rot_stddev_threshold = 4 # Station rotation interpolation standard deviation threshold
15
+ tilt_threshold = -100 # Station tilt threshold
16
+ deg2rad = np.pi / 180 # Degrees to radians conversion
17
+ rad2deg = 1 / deg2rad # Radians to degrees conversion
18
+
19
+
20
+ def apply_tilt_factor(tilt: xr.DataArray,
21
+ tilt_correction_factor: float
22
+ ) -> xr.DataArray:
23
+ """Apply tilt correction factor to station tilt values
24
+
25
+ Parameters
26
+ ----------
27
+ tilt : xr.DataArray
28
+ Tilt array (either 'tilt_x' or 'tilt_y')
29
+ tilt_correction_factor : float
30
+ Correction factor to apply to tilt measurements
31
+
32
+ Returns
33
+ -------
34
+ xr.DataArray
35
+ Corrected tilt measurements
36
+ """
37
+ return tilt * tilt_correction_factor
38
+
39
+
40
+ def convert_and_filter_tilt(tilt: xr.DataArray
41
+ ) -> xr.DataArray:
42
+ """Convert station tilt from voltage to degrees,
43
+ and filter tilt with given threshold. Voltage-to-degrees
44
+ conversion is based on the equation in 3.2.9 in Fausto
45
+ et al. (2021) https://doi.org/10.5194/essd-13-3819-2021
46
+
47
+ Parameters
48
+ ----------
49
+ tilt : xr.DataArray
50
+ Array (either 'tilt_x' or 'tilt_y'), tilt values (voltage)
51
+
52
+ Returns
53
+ -------
54
+ xr.DataArray
55
+ Array (either 'tilt_x' or 'tilt_y'), tilt values (degrees)
56
+ """
57
+ # IDL version:
58
+ # notOKtiltX = where(tiltX lt -100, complement=OKtiltX) & notOKtiltY = where(tiltY lt -100, complement=OKtiltY)
59
+ # tiltX = tiltX/10.
60
+ # tiltnonzero = where(tiltX ne 0 and tiltX gt -40 and tiltX lt 40)
61
+ # if n_elements(tiltnonzero) ne 1 then tiltX[tiltnonzero] = tiltX[tiltnonzero]/abs(tiltX[tiltnonzero])*(-0.49*(abs(tiltX[tiltnonzero]))^4 + 3.6*(abs(tiltX[tiltnonzero]))^3 - 10.4*(abs(tiltX[tiltnonzero]))^2 +21.1*(abs(tiltX[tiltnonzero])))
62
+ # tiltY = tiltY/10.
63
+ # tiltnonzero = where(tiltY ne 0 and tiltY gt -40 and tiltY lt 40)
64
+ # if n_elements(tiltnonzero) ne 1 then tiltY[tiltnonzero] = tiltY[tiltnonzero]/abs(tiltY[tiltnonzero])*(-0.49*(abs(tiltY[tiltnonzero]))^4 + 3.6*(abs(tiltY[tiltnonzero]))^3 - 10.4*(abs(tiltY[tiltnonzero]))^2 +21.1*(abs(tiltY[tiltnonzero])))
65
+
66
+ # if n_elements(OKtiltX) gt 1 then tiltX[notOKtiltX] = interpol(tiltX[OKtiltX],OKtiltX,notOKtiltX) ; Interpolate over gaps for radiation correction; set to -999 again below.
67
+
68
+ # Define valid tilt values and create mask
69
+ notOKtilt = (tilt < tilt_threshold)
70
+ OKtilt = (tilt >= tilt_threshold)
71
+
72
+ # Convert tilt values
73
+ dst = tilt / 10
74
+ nz = (dst != 0) & (np.abs(dst) < 40)
75
+ dst = dst.where(~nz, other = dst / np.abs(dst)
76
+ * (-0.49
77
+ * (np.abs(dst))**4 + 3.6
78
+ * (np.abs(dst))**3 - 10.4
79
+ * (np.abs(dst))**2 + 21.1
80
+ * (np.abs(dst))))
81
+
82
+ # Apply filtering mask
83
+ dst = dst.where(~notOKtilt)
84
+
85
+ # TODO: Filling w/o considering time gaps to re-create IDL/GDL outputs.
86
+ # Should fill with coordinate not False. Also consider 'max_gap' option?
87
+ return dst.interpolate_na(dim='time', use_coordinate=False)
88
+
89
+
90
+ def smooth_tilt_with_moving_window(tilt: xr.DataArray
91
+ ) -> tuple[str, np.ndarray]:
92
+ """Smooth tilt values using the pandas 'rolling' window method
93
+ e.g. a value of 7 spans 70 minutes using 10-minute data.
94
+ This is translated from the previous IDL/GDL smoothing algorithm:
95
+ tiltX = smooth(tiltX,7,/EDGE_MIRROR,MISSING=-999) & tiltY = smooth(tiltY,7,/EDGE_MIRROR, MISSING=-999)
96
+ endif
97
+ In Python, this should be
98
+ dstxy = dstxy.rolling(time=7, win_type='boxcar', center=True).mean()
99
+ But the EDGE_MIRROR makes it a bit more complicated
100
+
101
+ Parameters
102
+ ----------
103
+ tilt : xr.DataArray
104
+ Array (either 'tilt_x' or 'tilt_y'), tilt values (can be in degrees or voltage)
105
+
106
+ Returns
107
+ -------
108
+ tdf_rolling : tuple, as: (str, numpy.ndarray)
109
+ The numpy array is the tilt values, smoothed with a rolling mean
110
+ """
111
+ s = int(tilt_smoothing_win_size/2)
112
+ tdf = tilt.to_dataframe()
113
+ mirror_start = tdf.iloc[:s][::-1]
114
+ mirror_end = tdf.iloc[-s:][::-1]
115
+ mirrored_tdf = pd.concat([mirror_start, tdf, mirror_end])
116
+
117
+ tdf_rolling = (
118
+ ("time"),
119
+ mirrored_tdf.rolling(
120
+ tilt_smoothing_win_size, win_type="boxcar", min_periods=1, center=True
121
+ ).mean()[s:-s].values.flatten()
122
+ )
123
+ return tdf_rolling
124
+
125
+
126
+ def interpolate_tilt(tilt: xr.DataArray,
127
+ ) -> xr.DataArray:
128
+ """Interpolate (fill data gaps) and smooth station tilt
129
+ using a moving standard deviation over a 3-day sliding
130
+ window.
131
+
132
+ Parameters
133
+ ----------
134
+ tilt : xr.DataArray
135
+ Either X or Y tilt inclinometer measurements
136
+
137
+ Returns
138
+ -------
139
+ xr.DataArray
140
+ Either X or Y smoothed tilt inclinometer measurements
141
+ """
142
+ # We calculate the moving standard deviation over a 3-day sliding window
143
+ # hourly resampling is necessary to make sure the same threshold can be used
144
+ # for 10 min and hourly data
145
+ moving_std_gap_filled = tilt.to_series().resample("h").median().rolling(
146
+ 3*24, center=True, min_periods=2
147
+ ).std().reindex(tilt.time, method="bfill").values
148
+
149
+ # We select the good timestamps and gapfill assuming that
150
+ # - when tilt goes missing the last available value is used
151
+ # - when tilt is not available for the very first time steps, the first
152
+ # good value is used for backfill
153
+ return tilt.where(
154
+ moving_std_gap_filled < tilt_stddev_threshold
155
+ ).ffill(dim="time").bfill(dim="time")
156
+
157
+
158
+ def interpolate_rotation(rot: xr.DataArray,
159
+ threshold=4):
160
+ """Interpolate and smooth station rotation
161
+
162
+ Parameters
163
+ ----------
164
+ rot : xr.DataArray
165
+ Rotation measurements from inclinometer
166
+ threshold : float
167
+ threshold used in a standard deviation based filter
168
+
169
+ Returns
170
+ -------
171
+ xr.DataArray
172
+ smoothed rotation measurements from inclinometer
173
+ """
174
+ moving_std_gap_filled = rot.to_series().resample("h").median().rolling(
175
+ 3*24, center=True, min_periods=2
176
+ ).std().reindex(rot.time, method="bfill").values
177
+
178
+ # Same as for interpolate_tilt() with, in addition:
179
+ # - a resampling to daily values
180
+ # - a two-week median smoothing
181
+ # - a resampling from these daily values to the original temporal resolution
182
+ return ("time", (rot.where(moving_std_gap_filled < rot_stddev_threshold)
183
+ .ffill(dim="time")
184
+ .to_series().resample("D").median()
185
+ .rolling(7*2,center=True,min_periods=2).median()
186
+ .reindex(rot.time, method="bfill").values
187
+ ))
188
+
189
+
190
+ def calculate_spherical_tilt(
191
+ tilt_x: xr.DataArray,
192
+ tilt_y: xr.DataArray
193
+ ) -> tuple[xr.DataArray, xr.DataArray]:
194
+ """Calculate station tilt
195
+
196
+ Parameters
197
+ ----------
198
+ tilt_x : xr.DataArray
199
+ X tilt inclinometer measurements
200
+ tilt_y : xr.DataArray
201
+ Y tilt inclinometer measurements
202
+
203
+ Returns
204
+ -------
205
+ phi_sensor_rad : xr.DataArray
206
+ Spherical tilt coordinates
207
+ theta_sensor_rad : xr.DataArray
208
+ Total tilt of sensor, where 0 is horizontal
209
+ """
210
+ # Tilt as radians
211
+ tx = tilt_x * deg2rad
212
+ ty = tilt_y * deg2rad
213
+
214
+ # Calculate cartesian coordinates
215
+ X = np.sin(tx) * np.cos(tx) * np.sin(ty)**2 + np.sin(tx) * np.cos(ty)**2
216
+ Y = np.sin(ty) * np.cos(ty) * np.sin(tx)**2 + np.sin(ty) * np.cos(tx)**2
217
+ Z = np.cos(tx) * np.cos(ty) + np.sin(tx)**2 * np.sin(ty)**2
218
+
219
+ # Calculate spherical coordinates
220
+ phi_sensor_rad = -np.pi /2 - np.arctan(Y/X)
221
+ phi_sensor_rad[X > 0] += np.pi
222
+ phi_sensor_rad[(X == 0) & (Y < 0)] = np.pi
223
+ phi_sensor_rad[(X == 0) & (Y == 0)] = 0
224
+ phi_sensor_rad[phi_sensor_rad < 0] += 2*np.pi
225
+
226
+ # Total tilt of the sensor, i.e. 0 when horizontal
227
+ theta_sensor_rad = np.arccos(Z / (X**2 + Y**2 + Z**2)**0.5)
228
+ return phi_sensor_rad, theta_sensor_rad
229
+
230
+
231
+ def calculate_declination(doy: xr.DataArray,
232
+ hour: xr.DataArray,
233
+ minute: xr.DataArray
234
+ ) -> xr.DataArray:
235
+ """Calculate sun declination based on time
236
+
237
+ Parameters
238
+ ----------
239
+ doy : xr.DataArray
240
+ Day of year
241
+ hour : xr.DataArray
242
+ Hour of day
243
+ minute : xr.DataArray
244
+ Minute of hour
245
+
246
+ Returns
247
+ -------
248
+ xr.DataArray
249
+ Sun declination in radians
250
+ """
251
+ d0_rad = 2 * np.pi * (doy + (hour + minute / 60) / 24 -1) / 365
252
+ return np.arcsin(0.006918 - 0.399912
253
+ * np.cos(d0_rad) + 0.070257
254
+ * np.sin(d0_rad) - 0.006758
255
+ * np.cos(2 * d0_rad) + 0.000907
256
+ * np.sin(2 * d0_rad) - 0.002697
257
+ * np.cos(3 * d0_rad) + 0.00148
258
+ * np.sin(3 * d0_rad))
259
+
260
+
261
+ def calculate_hour_angle(hour: xr.DataArray,
262
+ minute: xr.DataArray,
263
+ lon: float
264
+ ) -> xr.DataArray:
265
+ """Calculate hour angle of sun based on time and longitude. Make sure that
266
+ time is set to UTC and longitude is positive when west. Hour angle should
267
+ be 0 at noon
268
+
269
+ Parameters
270
+ ----------
271
+ hour : xr.DataArray
272
+ Hour of day
273
+ minute : xr.DataArray
274
+ Minute of hour
275
+ lon : float
276
+ Longitude
277
+
278
+ Returns
279
+ -------
280
+ xr.DataArray
281
+ Hour angle of sun
282
+ """
283
+ return 2 * np.pi * (((hour + minute / 60) / 24 - 0.5) - lon/360)
284
+ # ; - 15.*timezone/360.)
285
+
286
+
287
+ def calculate_sun_direction_degrees(HourAngle_rad: xr.DataArray
288
+ ) -> xr.DataArray:
289
+ """Calculate sun direction as degrees. This is an alternative to
290
+ calculate_hour_angle that is currently not implemented into the official
291
+ L0>>L3 workflow. Here, 180 degrees is at noon (NH), as opposed to
292
+ HourAngle
293
+
294
+ Parameters
295
+ ----------
296
+ HourAngle_rad : xr.DataArray
297
+ Sun hour angle in radians
298
+
299
+ Returns
300
+ -------
301
+ DirectionSun_deg : xr.DataArray
302
+ Sun direction in degrees
303
+ """
304
+ DirectionSun_deg = HourAngle_rad * 180/np.pi - 180
305
+ DirectionSun_deg[DirectionSun_deg < 0] += 360
306
+ DirectionSun_deg[DirectionSun_deg < 0] += 360
307
+ return DirectionSun_deg
308
+
309
+
310
+ def calculate_zenith(lat: float,
311
+ Declination_rad: xr.DataArray,
312
+ HourAngle_rad: xr.DataArray
313
+ ) -> tuple[xr.DataArray, xr.DataArray]:
314
+ """Calculate sun zenith in radians and degrees
315
+
316
+ Parameters
317
+ ----------
318
+ lat : float
319
+ Latitude
320
+ Declination_rad : xr.DataArray
321
+ Sun declination in radians
322
+ HourAngle_rad : xr.DataArray
323
+ Sun hour angle in radians
324
+
325
+ Returns
326
+ -------
327
+ ZenithAngle_rad : xr.DataArray
328
+ Zenith angle in radians
329
+ ZenithAngle_deg : xr.DataArray
330
+ Zenith angle in degrees
331
+ """
332
+ ZenithAngle_rad = np.arccos(np.cos(lat * deg2rad)
333
+ * np.cos(Declination_rad)
334
+ * np.cos(HourAngle_rad)
335
+ + np.sin(lat * deg2rad)
336
+ * np.sin(Declination_rad))
337
+
338
+ ZenithAngle_deg = ZenithAngle_rad * rad2deg
339
+ return ZenithAngle_rad, ZenithAngle_deg
340
+
341
+
342
+ def calculate_angle_difference(ZenithAngle_rad: xr.DataArray,
343
+ HourAngle_rad: xr.DataArray,
344
+ phi_sensor_rad: xr.DataArray,
345
+ theta_sensor_rad: xr.DataArray
346
+ ) -> xr.DataArray:
347
+ """Calculate angle between sun and upper sensor (to determine when sun is
348
+ in sight of upper radiometer sensor)
349
+
350
+ Parameters
351
+ ----------
352
+ ZenithAngle_rad : xr.DataArray
353
+ Zenith angle in radians
354
+ HourAngle_rad : xr.DataArray
355
+ Sun hour angle in radians
356
+ phi_sensor_rad : xarray.DataArray
357
+ Spherical tilt coordinates
358
+ theta_sensor_rad : xarray.DataArray
359
+ Total tilt of sensor, where 0 is horizontal
360
+
361
+ Returns
362
+ -------
363
+ xr.DataArray
364
+ Angle between sun and sensor
365
+ """
366
+ return 180 / np.pi * np.arccos(np.sin(ZenithAngle_rad)
367
+ * np.cos(HourAngle_rad + np.pi)
368
+ * np.sin(theta_sensor_rad)
369
+ * np.cos(phi_sensor_rad)
370
+ + np.sin(ZenithAngle_rad)
371
+ * np.sin(HourAngle_rad + np.pi)
372
+ * np.sin(theta_sensor_rad)
373
+ * np.sin(phi_sensor_rad)
374
+ + np.cos(ZenithAngle_rad)
375
+ * np.cos(theta_sensor_rad))
File without changes
@@ -3,7 +3,7 @@ from pathlib import Path
3
3
 
4
4
  import pandas as pd
5
5
 
6
- from pypromice.postprocess.bufr_utilities import read_bufr_file
6
+ from pypromice.io.bufr.bufr_utilities import read_bufr_file
7
7
 
8
8
 
9
9
  def main():
@@ -3,9 +3,9 @@ from pathlib import Path
3
3
  from typing import Sequence, List
4
4
 
5
5
  import pandas as pd
6
- from pypromice.station_configuration import load_station_configuration_mapping
6
+ from pypromice.io.bufr.station_configuration import load_station_configuration_mapping
7
7
 
8
- from pypromice.postprocess.get_bufr import (
8
+ from pypromice.io.bufr.get_bufr import (
9
9
  get_bufr,
10
10
  DEFAULT_LIN_REG_TIME_LIMIT,
11
11
  DEFAULT_POSITION_SEED_PATH,
@@ -23,11 +23,11 @@ from typing import List, Dict, Optional, Sequence, Mapping
23
23
  import numpy as np
24
24
  import pandas as pd
25
25
 
26
- from pypromice.postprocess.bufr_utilities import write_bufr_message, BUFRVariables
27
- from pypromice.postprocess.real_time_utilities import get_latest_data
26
+ from pypromice.io.bufr.bufr_utilities import write_bufr_message, BUFRVariables
27
+ from pypromice.io.bufr.real_time_utilities import get_latest_data
28
28
 
29
29
 
30
- from pypromice.station_configuration import (
30
+ from pypromice.io.bufr.station_configuration import (
31
31
  StationConfiguration,
32
32
  load_station_configuration_mapping,
33
33
  )
@@ -45,7 +45,7 @@ REQUIRED_KEYS = (
45
45
  "gps_lat_fit",
46
46
  "gps_lon_fit",
47
47
  "gps_alt_fit",
48
- "z_boom_u_smooth",
48
+ "z_boom_cor_u_smooth",
49
49
  )
50
50
 
51
51
 
@@ -335,7 +335,7 @@ def get_bufr_variables(
335
335
  heightOfSensorAboveLocalGroundOrDeckOfMarinePlatformTempRH = np.nan
336
336
  else:
337
337
  heightOfSensorAboveLocalGroundOrDeckOfMarinePlatformTempRH = (
338
- data["z_boom_u_smooth"]
338
+ data["z_boom_cor_u_smooth"]
339
339
  + station_configuration.temperature_from_sonic_ranger
340
340
  )
341
341
 
@@ -343,7 +343,7 @@ def get_bufr_variables(
343
343
  heightOfSensorAboveLocalGroundOrDeckOfMarinePlatformWSPD = np.nan
344
344
  else:
345
345
  heightOfSensorAboveLocalGroundOrDeckOfMarinePlatformWSPD = (
346
- data["z_boom_u_smooth"] + station_configuration.anemometer_from_sonic_ranger
346
+ data["z_boom_cor_u_smooth"] + station_configuration.anemometer_from_sonic_ranger
347
347
  )
348
348
 
349
349
  output_row = BUFRVariables(
@@ -29,14 +29,14 @@ def get_latest_data(
29
29
 
30
30
  * A valid timestamp is a timestamp with relevant instantaneous variables. See source code.
31
31
  * Location smoothing: Fit a linear regression model on gps coordinate over the period lin_reg_time_limit to determine latest values.
32
- * z_boom: Apply rolling window median filter smooth data
32
+ * z_boom_cor_u: Apply rolling window median filter smooth data
33
33
 
34
34
  The output series contains the same variables as the input dataframe plus smoothed variables:
35
35
 
36
36
  * gps_lat_fit
37
37
  * gps_lon_fit
38
38
  * gps_alt_fit
39
- * z_boom_u_smooth
39
+ * z_boom_cor_u_smooth
40
40
 
41
41
  Parameters
42
42
  ----------
@@ -73,7 +73,7 @@ def get_latest_data(
73
73
 
74
74
  # Apply smoothing to z_boom_u
75
75
  # require at least 2 hourly obs? Sometimes seeing once/day data for z_boom_u
76
- df_limited = rolling_window(df_limited, "z_boom_u", "72h", 2, 3)
76
+ df_limited = rolling_window(df_limited, "z_boom_cor_u", "72h", 2, 3)
77
77
 
78
78
  # limit to single most recent valid row (convert to series)
79
79
  s_current = df_limited.loc[last_valid_index]
File without changes
@@ -1,9 +1,7 @@
1
+ import logging
1
2
  import subprocess
2
- import os
3
3
  from pathlib import Path
4
4
 
5
- import logging
6
-
7
5
  logger = logging.getLogger(__name__)
8
6
 
9
7