pypromice 1.4.3__tar.gz → 1.4.4__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.

Potentially problematic release.


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

Files changed (59) hide show
  1. {pypromice-1.4.3/src/pypromice.egg-info → pypromice-1.4.4}/PKG-INFO +1 -1
  2. {pypromice-1.4.3 → pypromice-1.4.4}/setup.py +1 -1
  3. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/bufr_utilities.py +2 -1
  4. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/L1toL2.py +30 -24
  5. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/value_clipping.py +15 -12
  6. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/resources/variables.csv +32 -32
  7. pypromice-1.4.4/src/pypromice/utilities/dependency_graph.py +101 -0
  8. {pypromice-1.4.3 → pypromice-1.4.4/src/pypromice.egg-info}/PKG-INFO +1 -1
  9. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice.egg-info/SOURCES.txt +1 -0
  10. {pypromice-1.4.3 → pypromice-1.4.4}/LICENSE.txt +0 -0
  11. {pypromice-1.4.3 → pypromice-1.4.4}/MANIFEST.in +0 -0
  12. {pypromice-1.4.3 → pypromice-1.4.4}/README.md +0 -0
  13. {pypromice-1.4.3 → pypromice-1.4.4}/setup.cfg +0 -0
  14. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/__init__.py +0 -0
  15. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/get/__init__.py +0 -0
  16. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/get/get.py +0 -0
  17. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/get/get_promice_data.py +0 -0
  18. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/__init__.py +0 -0
  19. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/bufr_to_csv.py +0 -0
  20. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/create_bufr_files.py +0 -0
  21. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/get_bufr.py +0 -0
  22. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/make_metadata_csv.py +0 -0
  23. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/positions_seed.csv +0 -0
  24. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/postprocess/real_time_utilities.py +0 -0
  25. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/L0toL1.py +0 -0
  26. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/L2toL3.py +0 -0
  27. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/__init__.py +0 -0
  28. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/aws.py +0 -0
  29. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/get_l2.py +0 -0
  30. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/get_l2tol3.py +0 -0
  31. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/join_l2.py +0 -0
  32. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/join_l3.py +0 -0
  33. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/load.py +0 -0
  34. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/resample.py +0 -0
  35. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/utilities.py +0 -0
  36. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/process/write.py +0 -0
  37. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/qc/__init__.py +0 -0
  38. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/qc/github_data_issues.py +0 -0
  39. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/qc/percentiles/__init__.py +0 -0
  40. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/qc/percentiles/compute_thresholds.py +0 -0
  41. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/qc/percentiles/outlier_detector.py +0 -0
  42. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/qc/percentiles/thresholds.csv +0 -0
  43. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/qc/persistence.py +0 -0
  44. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/resources/__init__.py +0 -0
  45. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/resources/file_attributes.csv +0 -0
  46. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/resources/variable_aliases_GC-Net.csv +0 -0
  47. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/station_configuration.py +0 -0
  48. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/tx/__init__.py +0 -0
  49. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/tx/get_l0tx.py +0 -0
  50. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/tx/get_msg.py +0 -0
  51. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/tx/payload_formats.csv +0 -0
  52. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/tx/payload_types.csv +0 -0
  53. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/tx/tx.py +0 -0
  54. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/utilities/__init__.py +0 -0
  55. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice/utilities/git.py +0 -0
  56. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice.egg-info/dependency_links.txt +0 -0
  57. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice.egg-info/entry_points.txt +0 -0
  58. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice.egg-info/requires.txt +0 -0
  59. {pypromice-1.4.3 → pypromice-1.4.4}/src/pypromice.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypromice
3
- Version: 1.4.3
3
+ Version: 1.4.4
4
4
  Summary: PROMICE/GC-Net data processing toolbox
5
5
  Home-page: https://github.com/GEUS-Glaciology-and-Climate/pypromice
6
6
  Author: GEUS Glaciology and Climate
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="pypromice",
8
- version="1.4.3",
8
+ version="1.4.4",
9
9
  author="GEUS Glaciology and Climate",
10
10
  description="PROMICE/GC-Net data processing toolbox",
11
11
  long_description=long_description,
@@ -120,7 +120,8 @@ class BUFRVariables:
120
120
  )
121
121
  # https://vocabulary-manager.eumetsat.int/vocabularies/BUFR/WMO/32/TABLE_B/012101
122
122
  # Scale: 2, unit: K
123
- airTemperature: float = attrs.field(converter=round_converter(2))
123
+ # NOTE: The expected scale is 2, but our instantanous data is rounded to 1 decimal.
124
+ airTemperature: float = attrs.field(converter=round_converter(1))
124
125
  # There is also a Dewpoint temperature in this template: 012103 which is currently unused.
125
126
  # https://vocabulary-manager.eumetsat.int/vocabularies/BUFR/WMO/32/TABLE_B/012103
126
127
  # Scale: 0, unit: %
@@ -94,7 +94,7 @@ def toL2(
94
94
  .ffill().bfill())
95
95
  mask = (np.abs(ds.gps_alt - baseline_elevation) < 100) & ds.gps_alt.notnull()
96
96
  ds[['gps_alt','gps_lon', 'gps_lat']] = ds[['gps_alt','gps_lon', 'gps_lat']].where(mask)
97
-
97
+
98
98
  # removing dlr and ulr that are missing t_rad
99
99
  # this is done now becasue t_rad can be filtered either manually or with persistence
100
100
  ds['dlr'] = ds.dlr.where(ds.t_rad.notnull())
@@ -113,12 +113,12 @@ def toL2(
113
113
  if ~ds['t_i'].isnull().all():
114
114
  ds['rh_i_cor'] = correctHumidity(ds['rh_i'], ds['t_i'],
115
115
  T_0, T_100, ews, ei0)
116
-
116
+
117
117
  # Determiune cloud cover for on-ice stations
118
118
  cc = calcCloudCoverage(ds['t_u'], T_0, eps_overcast, eps_clear, # Calculate cloud coverage
119
119
  ds['dlr'], ds.attrs['station_id'])
120
120
  ds['cc'] = (('time'), cc.data)
121
-
121
+
122
122
  # Determine surface temperature
123
123
  ds['t_surf'] = calcSurfaceTemperature(T_0, ds['ulr'], ds['dlr'], # Calculate surface temperature
124
124
  emissivity)
@@ -136,7 +136,7 @@ def toL2(
136
136
  else:
137
137
  lat = ds['gps_lat'].mean()
138
138
  lon = ds['gps_lon'].mean()
139
-
139
+
140
140
  # smoothing tilt and rot
141
141
  ds['tilt_x'] = smoothTilt(ds['tilt_x'])
142
142
  ds['tilt_y'] = smoothTilt(ds['tilt_y'])
@@ -151,8 +151,8 @@ def toL2(
151
151
  ZenithAngle_rad, ZenithAngle_deg = calcZenith(lat, Declination_rad, # Calculate zenith
152
152
  HourAngle_rad, deg2rad,
153
153
  rad2deg)
154
-
155
-
154
+
155
+
156
156
  # Correct Downwelling shortwave radiation
157
157
  DifFrac = 0.2 + 0.8 * cc
158
158
  CorFac_all = calcCorrectionFactor(Declination_rad, phi_sensor_rad, # Calculate correction
@@ -186,9 +186,9 @@ def toL2(
186
186
  TOA_crit_nopass = (ds['dsr_cor'] > (0.9 * isr_toa + 10)) # Determine filter
187
187
  ds['dsr_cor'][TOA_crit_nopass] = np.nan # Apply filter and interpolate
188
188
  ds['usr_cor'][TOA_crit_nopass] = np.nan
189
-
190
- ds['dsr_cor'] = ds.dsr_cor.where(ds.dsr.notnull())
191
- ds['usr_cor'] = ds.usr_cor.where(ds.usr.notnull())
189
+
190
+ ds['dsr_cor'] = ds.dsr_cor.where(ds.dsr.notnull())
191
+ ds['usr_cor'] = ds.usr_cor.where(ds.usr.notnull())
192
192
  # # Check sun position
193
193
  # sundown = ZenithAngle_deg >= 90
194
194
  # _checkSunPos(ds, OKalbedos, sundown, sunonlowerdome, TOA_crit_nopass)
@@ -205,27 +205,33 @@ def toL2(
205
205
  ds['precip_l_cor'], ds['precip_l_rate']= correctPrecip(ds['precip_l'],
206
206
  ds['wspd_l'])
207
207
 
208
- # Get directional wind speed
209
- ds['wdir_u'] = ds['wdir_u'].where(ds['wspd_u'] != 0)
210
- ds['wspd_x_u'], ds['wspd_y_u'] = calcDirWindSpeeds(ds['wspd_u'], ds['wdir_u'])
208
+ get_directional_wind_speed(ds) # Get directional wind speed
209
+
210
+ ds = clip_values(ds, vars_df)
211
+ return ds
212
+
213
+ def get_directional_wind_speed(ds: xr.Dataset) -> xr.Dataset:
214
+ """
215
+ Calculate directional wind speed from wind speed and direction and mutates the dataset
216
+ """
217
+
218
+ ds['wdir_u'] = ds['wdir_u'].where(ds['wspd_u'] != 0)
219
+ ds['wspd_x_u'], ds['wspd_y_u'] = calcDirWindSpeeds(ds['wspd_u'], ds['wdir_u'])
211
220
 
212
- if ds.attrs['number_of_booms']==2:
213
- ds['wdir_l'] = ds['wdir_l'].where(ds['wspd_l'] != 0)
221
+ if ds.attrs['number_of_booms']==2:
222
+ ds['wdir_l'] = ds['wdir_l'].where(ds['wspd_l'] != 0)
214
223
  ds['wspd_x_l'], ds['wspd_y_l'] = calcDirWindSpeeds(ds['wspd_l'], ds['wdir_l'])
215
224
 
216
225
  if hasattr(ds, 'wdir_i'):
217
226
  if ~ds['wdir_i'].isnull().all() and ~ds['wspd_i'].isnull().all():
218
- ds['wdir_i'] = ds['wdir_i'].where(ds['wspd_i'] != 0)
219
- ds['wspd_x_i'], ds['wspd_y_i'] = calcDirWindSpeeds(ds['wspd_i'], ds['wdir_i'])
220
-
221
-
222
- ds = clip_values(ds, vars_df)
227
+ ds['wdir_i'] = ds['wdir_i'].where(ds['wspd_i'] != 0)
228
+ ds['wspd_x_i'], ds['wspd_y_i'] = calcDirWindSpeeds(ds['wspd_i'], ds['wdir_i'])
223
229
  return ds
224
230
 
225
231
 
226
232
  def calcDirWindSpeeds(wspd, wdir, deg2rad=np.pi/180):
227
233
  '''Calculate directional wind speed from wind speed and direction
228
-
234
+
229
235
  Parameters
230
236
  ----------
231
237
  wspd : xr.Dataarray
@@ -234,16 +240,16 @@ def calcDirWindSpeeds(wspd, wdir, deg2rad=np.pi/180):
234
240
  Wind direction data array
235
241
  deg2rad : float
236
242
  Degree to radians coefficient. The default is np.pi/180
237
-
243
+
238
244
  Returns
239
245
  -------
240
246
  wspd_x : xr.Dataarray
241
247
  Wind speed in X direction
242
248
  wspd_y : xr.Datarray
243
249
  Wind speed in Y direction
244
- '''
250
+ '''
245
251
  wspd_x = wspd * np.sin(wdir * deg2rad)
246
- wspd_y = wspd * np.cos(wdir * deg2rad)
252
+ wspd_y = wspd * np.cos(wdir * deg2rad)
247
253
  return wspd_x, wspd_y
248
254
 
249
255
 
@@ -328,7 +334,7 @@ def smoothTilt(da: xr.DataArray, threshold=0.2):
328
334
  either X or Y smoothed tilt inclinometer measurements
329
335
  '''
330
336
  # we calculate the moving standard deviation over a 3-day sliding window
331
- # hourly resampling is necessary to make sure the same threshold can be used
337
+ # hourly resampling is necessary to make sure the same threshold can be used
332
338
  # for 10 min and hourly data
333
339
  moving_std_gap_filled = da.to_series().resample('h').median().rolling(
334
340
  3*24, center=True, min_periods=2
@@ -2,6 +2,8 @@ import numpy as np
2
2
  import pandas
3
3
  import xarray
4
4
 
5
+ from pypromice.utilities.dependency_graph import DependencyGraph
6
+
5
7
 
6
8
  def clip_values(
7
9
  ds: xarray.Dataset,
@@ -27,9 +29,15 @@ def clip_values(
27
29
  cols = ["lo", "hi", "OOL"]
28
30
  assert set(cols) <= set(var_configurations.columns)
29
31
 
30
- variable_limits = var_configurations[cols].dropna(how="all")
31
- for var, row in variable_limits.iterrows():
32
+ variable_limits = var_configurations[cols].assign(
33
+ dependents=lambda df: df.OOL.fillna("").str.split(),
34
+ # Find the closure of dependents using the DependencyGraph class
35
+ dependents_closure=lambda df: DependencyGraph.from_child_mapping(
36
+ df.dependents
37
+ ).child_closure_mapping(),
38
+ )
32
39
 
40
+ for var, row in variable_limits.iterrows():
33
41
  if var not in list(ds.variables):
34
42
  continue
35
43
 
@@ -38,15 +46,10 @@ def clip_values(
38
46
  if ~np.isnan(row.hi):
39
47
  ds[var] = ds[var].where(ds[var] <= row.hi)
40
48
 
41
- other_vars = row.OOL
42
- if isinstance(other_vars, str) and ~ds[var].isnull().all():
43
- for o in other_vars.split():
44
- if o not in list(ds.variables):
45
- continue
46
- else:
47
- if ~np.isnan(row.lo):
48
- ds[var] = ds[var].where(ds[var] >= row.lo)
49
- if ~np.isnan(row.hi):
50
- ds[var] = ds[var].where(ds[var] <= row.hi)
49
+ # Flag dependents as NaN if parent is NaN
50
+ for o in row.dependents_closure:
51
+ if o not in list(ds.variables):
52
+ continue
53
+ ds[o] = ds[o].where(ds[var].notnull())
51
54
 
52
55
  return ds
@@ -1,53 +1,53 @@
1
1
  field,standard_name,long_name,units,coverage_content_type,coordinates,instantaneous_hourly,where_to_find,lo,hi,OOL,station_type,L0,L2,L3,max_decimals
2
2
  time,time,Time,yyyy-mm-dd HH:MM:SS,physicalMeasurement,time,,,,,,all,1,1,1,
3
3
  rec,record,Record,-,referenceInformation,time,,L0 or L2,,,,all,1,1,0,0
4
- p_u,air_pressure,Air pressure (upper boom),hPa,physicalMeasurement,time,FALSE,,650,1100,z_pt z_pt_cor dshf_u dlhf_u qh_u,all,1,1,1,4
5
- p_l,air_pressure,Air pressure (lower boom),hPa,physicalMeasurement,time,FALSE,,650,1100,dshf_l dlhf_l qh_l,two-boom,1,1,1,4
6
- t_u,air_temperature,Air temperature (upper boom),degrees_C,physicalMeasurement,time,FALSE,,-80,40,rh_u_cor cc dsr_cor usr_cor z_boom z_stake dshf_u dlhf_u qh_u,all,1,1,1,4
7
- t_l,air_temperature,Air temperature (lower boom),degrees_C,physicalMeasurement,time,FALSE,,-80,40,rh_l_cor z_boom_l dshf_l dlhf_l qh_l,two-boom,1,1,1,4
8
- rh_u,relative_humidity,Relative humidity (upper boom),%,physicalMeasurement,time,FALSE,,0,100,rh_u_cor,all,1,1,1,4
9
- rh_u_cor,relative_humidity_corrected,Relative humidity (upper boom) - corrected,%,modelResult,time,FALSE,L2 or later,0,150,dshf_u dlhf_u qh_u,all,0,1,1,4
10
- qh_u,specific_humidity,Specific humidity (upper boom),kg/kg,modelResult,time,FALSE,L2 or later,0,100,,all,0,1,1,4
11
- rh_l,relative_humidity,Relative humidity (lower boom),%,physicalMeasurement,time,FALSE,,0,100,rh_l_cor,two-boom,1,1,1,4
12
- rh_l_cor,relative_humidity_corrected,Relative humidity (lower boom) - corrected,%,modelResult,time,FALSE,L2 or later,0,150,dshf_l dlhf_l qh_l,two-boom,0,1,1,4
4
+ p_u,air_pressure,Air pressure (upper boom),hPa,physicalMeasurement,time,FALSE,,650,1100,"",all,1,1,1,4
5
+ p_l,air_pressure,Air pressure (lower boom),hPa,physicalMeasurement,time,FALSE,,650,1100,"",two-boom,1,1,1,4
6
+ t_u,air_temperature,Air temperature (upper boom),degrees_C,physicalMeasurement,time,FALSE,,-80,40,"",all,1,1,1,4
7
+ t_l,air_temperature,Air temperature (lower boom),degrees_C,physicalMeasurement,time,FALSE,,-80,40,"",two-boom,1,1,1,4
8
+ rh_u,relative_humidity,Relative humidity (upper boom),%,physicalMeasurement,time,FALSE,,0,100,"",all,1,1,1,4
9
+ rh_u_cor,relative_humidity_corrected,Relative humidity (upper boom) - corrected,%,modelResult,time,FALSE,L2 or later,0,150,"",all,0,1,1,4
10
+ qh_u,specific_humidity,Specific humidity (upper boom),kg/kg,modelResult,time,FALSE,L2 or later,0,100,"",all,0,1,1,4
11
+ rh_l,relative_humidity,Relative humidity (lower boom),%,physicalMeasurement,time,FALSE,,0,100,"",two-boom,1,1,1,4
12
+ rh_l_cor,relative_humidity_corrected,Relative humidity (lower boom) - corrected,%,modelResult,time,FALSE,L2 or later,0,150,"",two-boom,0,1,1,4
13
13
  qh_l,specific_humidity,Specific humidity (lower boom),kg/kg,modelResult,time,FALSE,L2 or later,0,100,,two-boom,0,1,1,4
14
- wspd_u,wind_speed,Wind speed (upper boom),m s-1,physicalMeasurement,time,FALSE,,0,100,"wdir_u wspd_x_u wspd_y_u dshf_u dlhf_u qh_u, precip_u",all,1,1,1,4
15
- wspd_l,wind_speed,Wind speed (lower boom),m s-1,physicalMeasurement,time,FALSE,,0,100,"wdir_l wspd_x_l wspd_y_l dshf_l dlhf_l qh_l , precip_l",two-boom,1,1,1,4
14
+ wspd_u,wind_speed,Wind speed (upper boom),m s-1,physicalMeasurement,time,FALSE,,0,100,wdir_u wspd_x_u wspd_y_u,all,1,1,1,4
15
+ wspd_l,wind_speed,Wind speed (lower boom),m s-1,physicalMeasurement,time,FALSE,,0,100,wdir_l wspd_x_l wspd_y_l,two-boom,1,1,1,4
16
16
  wdir_u,wind_from_direction,Wind from direction (upper boom),degrees,physicalMeasurement,time,FALSE,,1,360,wspd_x_u wspd_y_u,all,1,1,1,4
17
17
  wdir_std_u,wind_from_direction_standard_deviation,Wind from direction (standard deviation),degrees,qualityInformation,time,FALSE,L0 or L2,,,,one-boom,1,1,0,4
18
18
  wdir_l,wind_from_direction,Wind from direction (lower boom),degrees,physicalMeasurement,time,FALSE,,1,360,wspd_x_l wspd_y_l,two-boom,1,1,1,4
19
- wspd_x_u,wind_speed_from_x_direction,Wind speed from x direction (upper boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,wdir_u wspd_u,all,0,1,1,4
20
- wspd_y_u,wind_speed_from_y_direction,Wind speed from y direction (upper boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,wdir_u wspd_u,all,0,1,1,4
21
- wspd_x_l,wind_speed_from_x_direction,Wind speed from x direction (lower boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,wdir_l wspd_l,two-boom,0,1,1,4
22
- wspd_y_l,wind_speed_from_y_direction,Wind speed from y direction (lower boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,wdir_l wspd_l,two-boom,0,1,1,4
23
- dsr,surface_downwelling_shortwave_flux,Downwelling shortwave radiation,W m-2,physicalMeasurement,time,FALSE,,-10,1500,albedo dsr_cor usr_cor,all,1,1,1,4
19
+ wspd_x_u,wind_speed_from_x_direction,Wind speed from x direction (upper boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,"",all,0,1,1,4
20
+ wspd_y_u,wind_speed_from_y_direction,Wind speed from y direction (upper boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,"",all,0,1,1,4
21
+ wspd_x_l,wind_speed_from_x_direction,Wind speed from x direction (lower boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,"",two-boom,0,1,1,4
22
+ wspd_y_l,wind_speed_from_y_direction,Wind speed from y direction (lower boom),m s-1,modelResult,time,FALSE,L0 or L2,-100,100,"",two-boom,0,1,1,4
23
+ dsr,surface_downwelling_shortwave_flux,Downwelling shortwave radiation,W m-2,physicalMeasurement,time,FALSE,,-10,1500,"",all,1,1,1,4
24
24
  dsr_cor,surface_downwelling_shortwave_flux_corrected,Downwelling shortwave radiation - corrected,W m-2,modelResult,time,FALSE,L2 or later,,,,all,0,1,1,4
25
- usr,surface_upwelling_shortwave_flux,Upwelling shortwave radiation,W m-2,physicalMeasurement,time,FALSE,,-10,1000,albedo dsr_cor usr_cor,all,1,1,1,4
25
+ usr,surface_upwelling_shortwave_flux,Upwelling shortwave radiation,W m-2,physicalMeasurement,time,FALSE,,-10,1000,"",all,1,1,1,4
26
26
  usr_cor,surface_upwelling_shortwave_flux_corrected,Upwelling shortwave radiation - corrected,W m-2,modelResult,time,FALSE,L2 or later,0,1000,,all,0,1,1,4
27
27
  albedo,surface_albedo,Albedo,-,modelResult,time,FALSE,L2 or later,,,,all,0,1,1,4
28
- dlr,surface_downwelling_longwave_flux,Downwelling longwave radiation,W m-2,physicalMeasurement,time,FALSE,,50,500,albedo dsr_cor usr_cor cc t_surf,all,1,1,1,4
29
- ulr,surface_upwelling_longwave_flux,Upwelling longwave radiation,W m-2,physicalMeasurement,time,FALSE,,50,500,t_surf,all,1,1,1,4
28
+ dlr,surface_downwelling_longwave_flux,Downwelling longwave radiation,W m-2,physicalMeasurement,time,FALSE,,50,500,"",all,1,1,1,4
29
+ ulr,surface_upwelling_longwave_flux,Upwelling longwave radiation,W m-2,physicalMeasurement,time,FALSE,,50,500,"",all,1,1,1,4
30
30
  cc,cloud_area_fraction,Cloud cover,%,modelResult,time,FALSE,L2 or later,,,,all,0,1,1,4
31
- t_surf,surface_temperature,Surface temperature,C,modelResult,time,FALSE,L2 or later,-80,40,dshf_u dlhf_u qh_u,all,0,1,1,4
31
+ t_surf,surface_temperature,Surface temperature,C,modelResult,time,FALSE,L2 or later,-80,40,"",all,0,1,1,4
32
32
  dlhf_u,surface_downward_latent_heat_flux,Latent heat flux (upper boom),W m-2,modelResult,time,FALSE,L3 or later,,,,all,0,0,1,4
33
33
  dlhf_l,surface_downward_latent_heat_flux,Latent heat flux (lower boom),W m-2,modelResult,time,FALSE,L3 or later,,,,two-boom,0,0,1,4
34
34
  dshf_u,surface_downward_sensible_heat_flux,Sensible heat flux (upper boom),W m-2,modelResult,time,FALSE,L3 or later,,,,all,0,0,1,4
35
35
  dshf_l,surface_downward_sensible_heat_flux,Sensible heat flux (lower boom),W m-2,modelResult,time,FALSE,L3 or later,,,,two-boom,0,0,1,4
36
- z_boom_u,distance_to_surface_from_boom,Upper boom height,m,physicalMeasurement,time,TRUE,,0.3,10,dshf_u dlhf_u qh_u,all,1,1,1,4
36
+ z_boom_u,distance_to_surface_from_boom,Upper boom height,m,physicalMeasurement,time,TRUE,,0.3,10,"",all,1,1,1,4
37
37
  z_boom_q_u,distance_to_surface_from_boom_quality,Upper boom height (quality),-,qualityInformation,time,TRUE,L0 or L2,,,,all,1,1,0,4
38
- z_boom_l,distance_to_surface_from_boom,Lower boom height,m,physicalMeasurement,time,TRUE,,0.3,5,dshf_l dlhf_l qh_l,two-boom,1,1,1,4
38
+ z_boom_l,distance_to_surface_from_boom,Lower boom height,m,physicalMeasurement,time,TRUE,,0.3,5,"",two-boom,1,1,1,4
39
39
  z_boom_q_l,distance_to_surface_from_boom_quality,Lower boom height (quality),-,qualityInformation,time,TRUE,L0 or L2,,,,two-boom,1,1,0,4
40
40
  z_stake,distance_to_surface_from_stake_assembly,Stake height,m,physicalMeasurement,time,TRUE,,0.3,8,,one-boom,1,1,1,4
41
41
  z_stake_q,distance_to_surface_from_stake_assembly_quality,Stake height (quality),-,qualityInformation,time,TRUE,L0 or L2,,,,one-boom,1,1,0,4
42
- z_pt,depth_of_pressure_transducer_in_ice,Depth of pressure transducer in ice,m,physicalMeasurement,time,FALSE,,0,30,z_pt_cor,one-boom,1,1,1,4
42
+ z_pt,depth_of_pressure_transducer_in_ice,Depth of pressure transducer in ice,m,physicalMeasurement,time,FALSE,,0,30,"",one-boom,1,1,1,4
43
43
  z_pt_cor,depth_of_pressure_transducer_in_ice_corrected,Depth of pressure transducer in ice - corrected,m,modelResult,time,FALSE,L2 or later,0,30,,one-boom,0,1,1,4
44
44
  z_surf_combined,height_of_surface_combined,"Surface height combined from multiple sensors, relative to ice surface height at installation",m,modelResult,time,FALSE,L3,,,,all,0,0,1,4
45
45
  z_ice_surf,height_of_ice_surface,"Ice surface height, relative to ice surface height at installation and calculated from pt_cor and z_stake",m,modelResult,time,FALSE,L3,,,,one-boom,0,0,1,4
46
46
  snow_height,height_of_snow,"Snow surface height, relative to ice surface",m,modelResult,time,FALSE,L3,0,,,one-boom,0,0,1,4
47
- precip_u,precipitation,Precipitation (upper boom) (cumulative solid & liquid),mm,physicalMeasurement,time,TRUE,,0,,precip_u_cor precip_u_rate,all,1,1,1,4
47
+ precip_u,precipitation,Precipitation (upper boom) (cumulative solid & liquid),mm,physicalMeasurement,time,TRUE,,0,,"",all,1,1,1,4
48
48
  precip_u_cor,precipitation_corrected,Precipitation (upper boom) (cumulative solid & liquid) – corrected,mm,modelResult,time,TRUE,L2 or later,0,,,all,0,1,1,4
49
49
  precip_u_rate,precipitation_rate,Precipitation rate (upper boom) (cumulative solid & liquid) – corrected,mm,modelResult,time,TRUE,L2 or later,0,,,all,0,1,1,4
50
- precip_l,precipitation,Precipitation (lower boom) (cumulative solid & liquid),mm,physicalMeasurement,time,TRUE,,0,,precip_l_cor precip_l_rate,two-boom,1,1,1,4
50
+ precip_l,precipitation,Precipitation (lower boom) (cumulative solid & liquid),mm,physicalMeasurement,time,TRUE,,0,,"",two-boom,1,1,1,4
51
51
  precip_l_cor,precipitation_corrected,Precipitation (lower boom) (cumulative solid & liquid) – corrected,mm,modelResult,time,TRUE,L2 or later,0,,,two-boom,0,1,1,4
52
52
  precip_l_rate,precipitation_rate,Precipitation rate (lower boom) (cumulative solid & liquid) – corrected,mm,modelResult,time,TRUE,L2 or later,0,,,two-boom,0,1,1,4
53
53
  t_i_1,ice_temperature_at_t1,Ice temperature at sensor 1,degrees_C,physicalMeasurement,time,FALSE,,-80,1,,all,1,1,1,4
@@ -73,8 +73,8 @@ d_t_i_9,depth_of_thermistor_9,Depth of thermistor 9,m,modelResult,time,FALSE,L3,
73
73
  d_t_i_10,depth_of_thermistor_10,Depth of thermistor 10,m,modelResult,time,FALSE,L3,-10,100,,two-boom,0,0,1,4
74
74
  d_t_i_11,depth_of_thermistor_11,Depth of thermistor 11,m,modelResult,time,FALSE,L3,-10,100,,two-boom,0,0,1,4
75
75
  t_i_10m,10m_subsurface_temperature,10 m subsurface temperature,degrees_C,modelResult,time,FALSE,L3,-70,0,,all,0,0,1,4
76
- tilt_x,platform_view_angle_x,Tilt to east,degrees,physicalMeasurement,time,FALSE,,-30,30,dsr_cor usr_cor albedo,all,1,1,1,4
77
- tilt_y,platform_view_angle_y,Tilt to north,degrees,physicalMeasurement,time,FALSE,,-30,30,dsr_cor usr_cor albedo,all,1,1,1,4
76
+ tilt_x,platform_view_angle_x,Tilt to east,degrees,physicalMeasurement,time,FALSE,,-30,30,"",all,1,1,1,4
77
+ tilt_y,platform_view_angle_y,Tilt to north,degrees,physicalMeasurement,time,FALSE,,-30,30,"",all,1,1,1,4
78
78
  rot,platform_azimuth_angle,Station rotation from true North,degrees,physicalMeasurement,time,FALSE,,0,360,,all,1,1,1,2
79
79
  gps_lat,gps_latitude,Latitude,degrees_north,physicalMeasurement,time,TRUE,,50,83,,all,1,1,1,6
80
80
  gps_lon,gps_longitude,Longitude,degrees_east,physicalMeasurement,time,TRUE,,5,70,,all,1,1,1,6
@@ -93,14 +93,14 @@ batt_v_ini,,,-,physicalMeasurement,time,TRUE,L0 or L2,0,30,,,1,1,0,2
93
93
  batt_v_ss,battery_voltage_at_sample_start,Battery voltage (sample start),V,physicalMeasurement,time,TRUE,L0 or L2,0,30,,,1,1,0,2
94
94
  fan_dc_u,fan_current,Fan current (upper boom),mA,physicalMeasurement,time,TRUE,L0 or L2,0,200,,all,1,1,0,2
95
95
  fan_dc_l,fan_current,Fan current (lower boom),mA,physicalMeasurement,time,TRUE,,0,200,,two-boom,1,1,0,2
96
- freq_vw,frequency_of_precipitation_wire_vibration,Frequency of vibrating wire in precipitation gauge,Hz,physicalMeasurement,time,TRUE,L0 or L2,0,10000,precip_u,,1,1,0,
96
+ freq_vw,frequency_of_precipitation_wire_vibration,Frequency of vibrating wire in precipitation gauge,Hz,physicalMeasurement,time,TRUE,L0 or L2,0,10000,"",,1,1,0,
97
97
  t_log,temperature_of_logger,Logger temperature,degrees_C,physicalMeasurement,time,TRUE,,-80,40,,one-boom,1,1,0,4
98
- t_rad,temperature_of_radiation_sensor,Radiation sensor temperature,degrees_C,physicalMeasurement,time,FALSE,,-80,40,t_surf dlr ulr,all,1,1,1,4
98
+ t_rad,temperature_of_radiation_sensor,Radiation sensor temperature,degrees_C,physicalMeasurement,time,FALSE,,-80,40,"",all,1,1,1,4
99
99
  p_i,air_pressure,Air pressure (instantaneous) minus 1000,hPa,physicalMeasurement,time,TRUE,,-350,100,,all,1,1,1,4
100
100
  t_i,air_temperature,Air temperature (instantaneous),degrees_C,physicalMeasurement,time,TRUE,,-80,40,,all,1,1,1,4
101
- rh_i,relative_humidity,Relative humidity (instantaneous),%,physicalMeasurement,time,TRUE,,0,150,rh_i_cor,all,1,1,1,4
101
+ rh_i,relative_humidity,Relative humidity (instantaneous),%,physicalMeasurement,time,TRUE,,0,150,"",all,1,1,1,4
102
102
  rh_i_cor,relative_humidity_corrected,Relative humidity (instantaneous) – corrected,%,modelResult,time,TRUE,L2 or later,0,100,,all,0,1,1,4
103
103
  wspd_i,wind_speed,Wind speed (instantaneous),m s-1,physicalMeasurement,time,TRUE,,0,100,wdir_i wspd_x_i wspd_y_i,all,1,1,1,4
104
104
  wdir_i,wind_from_direction,Wind from direction (instantaneous),degrees,physicalMeasurement,time,TRUE,,1,360,wspd_x_i wspd_y_i,all,1,1,1,4
105
- wspd_x_i,wind_speed_from_x_direction,Wind speed from x direction (instantaneous),m s-1,modelResult,time,TRUE,L2 or later,-100,100,wdir_i wspd_i,all,0,1,1,4
106
- wspd_y_i,wind_speed_from_y_direction,Wind speed from y direction (instantaneous),m s-1,modelResult,time,TRUE,L2 or later,-100,100,wdir_i wspd_i,all,0,1,1,4
105
+ wspd_x_i,wind_speed_from_x_direction,Wind speed from x direction (instantaneous),m s-1,modelResult,time,TRUE,L2 or later,-100,100,"",all,0,1,1,4
106
+ wspd_y_i,wind_speed_from_y_direction,Wind speed from y direction (instantaneous),m s-1,modelResult,time,TRUE,L2 or later,-100,100,"",all,0,1,1,4
@@ -0,0 +1,101 @@
1
+ from typing import Mapping, Set, MutableMapping, Optional
2
+
3
+ import attr
4
+
5
+ __all__ = [
6
+ "DependencyNode",
7
+ "DependencyGraph",
8
+ ]
9
+
10
+
11
+ @attr.define
12
+ class DependencyNode:
13
+ name: str = attr.field()
14
+ parents: Set["DependencyNode"] = attr.field(factory=set)
15
+ children: Set["DependencyNode"] = attr.field(factory=set)
16
+
17
+ def add_child(self, child: "DependencyNode"):
18
+ self.children.add(child)
19
+ child.parents.add(self)
20
+
21
+ def get_children_closure(self, closure: Optional[Set[str]] = None) -> Set[str]:
22
+ is_root = closure is None
23
+ if closure is None:
24
+ closure = set()
25
+ if self.name in closure:
26
+ return closure
27
+ closure.add(self.name)
28
+ for child in self.children:
29
+ closure |= child.get_children_closure(closure)
30
+
31
+ if is_root:
32
+ closure.remove(self.name)
33
+ return closure
34
+
35
+ def get_parents_closure(self, closure: Optional[Set[str]] = None) -> Set[str]:
36
+ is_root = closure is None
37
+ if closure is None:
38
+ closure = set()
39
+ if self.name in closure:
40
+ return closure
41
+ closure.add(self.name)
42
+ for parent in self.parents:
43
+ closure |= parent.get_parents_closure(closure)
44
+
45
+ if is_root:
46
+ closure.remove(self.name)
47
+ return closure
48
+
49
+ def __hash__(self):
50
+ return hash(self.name)
51
+
52
+
53
+ @attr.define
54
+ class DependencyGraph:
55
+ nodes: MutableMapping[str, DependencyNode] = attr.field(factory=dict)
56
+
57
+ def add_node(self, name: str) -> DependencyNode:
58
+ if name not in self.nodes:
59
+ self.nodes[name] = DependencyNode(name)
60
+ return self.nodes[name]
61
+
62
+ def add_edge(self, parent: str, child: str):
63
+ parent_node = self.add_node(parent)
64
+ child_node = self.add_node(child)
65
+ parent_node.add_child(child_node)
66
+
67
+ @classmethod
68
+ def from_child_mapping(cls, mapping: Mapping[str, Set[str]]) -> "DependencyGraph":
69
+ graph = cls()
70
+ for var, children in mapping.items():
71
+ graph.add_node(var)
72
+ for child in children:
73
+ graph.add_edge(var, child)
74
+ return graph
75
+
76
+ @classmethod
77
+ def from_parent_mapping(cls, mapping: Mapping[str, Set[str]]) -> "DependencyGraph":
78
+ graph = cls()
79
+ for var, parents in mapping.items():
80
+ graph.add_node(var)
81
+ for parent in parents:
82
+ graph.add_edge(parent, var)
83
+ return graph
84
+
85
+ def child_mapping(self) -> Mapping[str, Set[str]]:
86
+ return {
87
+ node.name: {child.name for child in node.children}
88
+ for node in self.nodes.values()
89
+ }
90
+
91
+ def child_closure_mapping(self) -> Mapping[str, Set[str]]:
92
+ return {node.name: node.get_children_closure() for node in self.nodes.values()}
93
+
94
+ def parent_mapping(self) -> Mapping[str, Set[str]]:
95
+ return {
96
+ node.name: {parent.name for parent in node.parents}
97
+ for node in self.nodes.values()
98
+ }
99
+
100
+ def parent_closure_mapping(self) -> Mapping[str, Set[str]]:
101
+ return {node.name: node.get_parents_closure() for node in self.nodes.values()}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypromice
3
- Version: 1.4.3
3
+ Version: 1.4.4
4
4
  Summary: PROMICE/GC-Net data processing toolbox
5
5
  Home-page: https://github.com/GEUS-Glaciology-and-Climate/pypromice
6
6
  Author: GEUS Glaciology and Climate
@@ -53,4 +53,5 @@ src/pypromice/tx/payload_formats.csv
53
53
  src/pypromice/tx/payload_types.csv
54
54
  src/pypromice/tx/tx.py
55
55
  src/pypromice/utilities/__init__.py
56
+ src/pypromice/utilities/dependency_graph.py
56
57
  src/pypromice/utilities/git.py
File without changes
File without changes
File without changes
File without changes