pypromice 1.3.2__py3-none-any.whl → 1.3.4__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.

@@ -57,7 +57,9 @@ def toL1(L0, vars_df, T_0=273.15, tilt_threshold=-100):
57
57
  ds['ulr'] = ((ds['ulr'] * 10) / ds.attrs['ulr_eng_coef']) + 5.67E-8*(ds['t_rad'] + T_0)**4
58
58
 
59
59
  ds['z_boom_u'] = _reformatArray(ds['z_boom_u']) # Reformat boom height
60
- ds['z_boom_u'] = ds['z_boom_u'] * ((ds['t_u'] + T_0)/T_0)**0.5 # Adjust sonic ranger readings for sensitivity to air temperature
60
+
61
+ ds['t_u_interp'] = interpTemp(ds['t_u'], vars_df)
62
+ ds['z_boom_u'] = ds['z_boom_u'] * ((ds['t_u_interp'] + T_0)/T_0)**0.5 # Adjust sonic ranger readings for sensitivity to air temperature
61
63
 
62
64
  if ds['gps_lat'].dtype.kind == 'O': # Decode and reformat GPS information
63
65
  if 'NH' in ds['gps_lat'].dropna(dim='time').values[1]:
@@ -113,7 +115,8 @@ def toL1(L0, vars_df, T_0=273.15, tilt_threshold=-100):
113
115
 
114
116
  elif ds.attrs['number_of_booms']==2: # 2-boom processing
115
117
  ds['z_boom_l'] = _reformatArray(ds['z_boom_l']) # Reformat boom height
116
- ds['z_boom_l'] = ds['z_boom_l'] * ((ds['t_l'] + T_0)/T_0)**0.5 # Adjust sonic ranger readings for sensitivity to air temperature
118
+ ds['t_l_interp'] = interpTemp(ds['t_l'], vars_df)
119
+ ds['z_boom_l'] = ds['z_boom_l'] * ((ds['t_l_interp']+ T_0)/T_0)**0.5 # Adjust sonic ranger readings for sensitivity to air temperature
117
120
 
118
121
  ds = clip_values(ds, vars_df)
119
122
  for key in ['hygroclip_t_offset', 'dsr_eng_coef', 'usr_eng_coef',
@@ -169,14 +172,16 @@ def addTimeShift(ds, vars_df):
169
172
  elif ds.attrs['format'] == 'STM':
170
173
  # hourly-averaged, non-transmitted
171
174
  # shift everything except instantaneous, any logger type
172
- df_a = df_a.shift(periods=-1, freq="H")
175
+ df_a = df_a.shift(periods=-1, freq="h")
173
176
  df_out = pd.concat([df_a, df_i], axis=1) # different columns, same datetime indices
177
+ df_out = df_out.sort_index()
174
178
  elif ds.attrs['format'] == 'TX':
175
179
  if ds.attrs['logger_type'] == 'CR1000X':
176
180
  # v3, data is hourly all year long
177
181
  # shift everything except instantaneous
178
182
  df_a = df_a.shift(periods=-1, freq="H")
179
183
  df_out = pd.concat([df_a, df_i], axis=1) # different columns, same datetime indices
184
+ df_out = df_out.sort_index()
180
185
  elif ds.attrs['logger_type'] == 'CR1000':
181
186
  # v2, data is hourly (6-hr for instantaneous) for DOY 100-300, otherwise daily at 00 UTC
182
187
  # shift non-instantaneous hourly for DOY 100-300, else do not shift daily
@@ -186,7 +191,7 @@ def addTimeShift(ds, vars_df):
186
191
  df_a_daily_2 = df_a.loc[(df_a['doy'] > 300)]
187
192
 
188
193
  # shift the hourly ave data
189
- df_a_hourly = df_a_hourly.shift(periods=-1, freq="H")
194
+ df_a_hourly = df_a_hourly.shift(periods=-1, freq="h")
190
195
 
191
196
  # stitch everything back together
192
197
  df_concat_u = pd.concat([df_a_daily_1, df_a_daily_2, df_a_hourly], axis=0) # same columns, different datetime indices
@@ -254,6 +259,41 @@ def getPressDepth(z_pt, p, pt_antifreeze, pt_z_factor, pt_z_coef, pt_z_p_coef):
254
259
 
255
260
  return z_pt_cor, z_pt
256
261
 
262
+
263
+ def interpTemp(temp, var_configurations, max_interp=pd.Timedelta(12,'h')):
264
+ '''Clip and interpolate temperature dataset for use in corrections
265
+
266
+ Parameters
267
+ ----------
268
+ temp : `xarray.DataArray`
269
+ Array of temperature data
270
+ vars_df : `pandas.DataFrame`
271
+ Dataframe to retrieve attribute hi-lo values from for temperature clipping
272
+ max_interp : `pandas.Timedelta`
273
+ Maximum time steps to interpolate across. The default is 12 hours.
274
+
275
+ Returns
276
+ -------
277
+ temp_interp : `xarray.DataArray`
278
+ Array of interpolatedtemperature data
279
+ '''
280
+ # Determine if upper or lower temperature array
281
+ var = temp.name.lower()
282
+
283
+ # Find range threshold and use it to clip measurements
284
+ cols = ["lo", "hi", "OOL"]
285
+ assert set(cols) <= set(var_configurations.columns)
286
+ variable_limits = var_configurations[cols].dropna(how="all")
287
+ temp = temp.where(temp >= variable_limits.loc[var,'lo'])
288
+ temp = temp.where(temp <= variable_limits.loc[var, 'hi'])
289
+
290
+ # Drop duplicates and interpolate across NaN values
291
+ # temp_interp = temp.drop_duplicates(dim='time', keep='first')
292
+ temp_interp = temp.interpolate_na(dim='time', max_gap=max_interp)
293
+
294
+ return temp_interp
295
+
296
+
257
297
  def smoothTilt(tilt, win_size):
258
298
  '''Smooth tilt values using a rolling window. This is translated from the
259
299
  previous IDL/GDL smoothing algorithm:
@@ -29,22 +29,14 @@ def clip_values(
29
29
 
30
30
  variable_limits = var_configurations[cols].dropna(how="all")
31
31
  for var, row in variable_limits.iterrows():
32
+
32
33
  if var not in list(ds.variables):
33
34
  continue
34
35
 
35
- if var in ["rh_u_cor", "rh_l_cor"]:
36
- ds[var] = ds[var].where(ds[var] >= row.lo, other=0)
37
- ds[var] = ds[var].where(ds[var] <= row.hi, other=100)
38
-
39
- # Mask out invalid corrections based on uncorrected var
40
- var_uncor = var.split("_cor")[0]
41
- ds[var] = ds[var].where(~np.isnan(ds[var_uncor]), other=np.nan)
42
-
43
- else:
44
- if ~np.isnan(row.lo):
45
- ds[var] = ds[var].where(ds[var] >= row.lo)
46
- if ~np.isnan(row.hi):
47
- ds[var] = ds[var].where(ds[var] <= row.hi)
36
+ if ~np.isnan(row.lo):
37
+ ds[var] = ds[var].where(ds[var] >= row.lo)
38
+ if ~np.isnan(row.hi):
39
+ ds[var] = ds[var].where(ds[var] <= row.hi)
48
40
 
49
41
  other_vars = row.OOL
50
42
  if isinstance(other_vars, str) and ~ds[var].isnull().all():
@@ -56,4 +48,5 @@ def clip_values(
56
48
  ds[var] = ds[var].where(ds[var] >= row.lo)
57
49
  if ~np.isnan(row.hi):
58
50
  ds[var] = ds[var].where(ds[var] <= row.hi)
51
+
59
52
  return ds
@@ -5,12 +5,12 @@ p_u,air_pressure,Air pressure (upper boom),hPa,650,1100,z_pt z_pt_cor dshf_u dlh
5
5
  p_l,air_pressure,Air pressure (lower boom),hPa,650,1100,dshf_l dlhf_l qh_l,two-boom,all,4,physicalMeasurement,time lat lon alt,False,
6
6
  t_u,air_temperature,Air temperature (upper boom),degrees_C,-80,40,rh_u_cor cc dsr_cor usr_cor z_boom z_stake dshf_u dlhf_u qh_u,all,all,4,physicalMeasurement,time lat lon alt,False,
7
7
  t_l,air_temperature,Air temperature (lower boom),degrees_C,-80,40,rh_l_cor z_boom_l dshf_l dlhf_l qh_l ,two-boom,all,4,physicalMeasurement,time lat lon alt,False,PT100 temperature at boom
8
- rh_u,relative_humidity,Relative humidity (upper boom),%,0,150,rh_u_cor,all,all,4,physicalMeasurement,time lat lon alt,False,
8
+ rh_u,relative_humidity,Relative humidity (upper boom),%,0,100,rh_u_cor,all,all,4,physicalMeasurement,time lat lon alt,False,
9
9
  rh_u_cor,relative_humidity_corrected,Relative humidity (upper boom) - corrected,%,0,150,dshf_u dlhf_u qh_u,all,all,4,modelResult,time lat lon alt,False,
10
- qh_u,specific_humidity,Specific humidity (upper boom),%,0,100,,all,all,4,modelResult,time lat lon alt,False,Derived value (L2 or later)
11
- rh_l,relative_humidity,Relative humidity (lower boom),%,0,150,rh_l_cor,two-boom,all,4,physicalMeasurement,time lat lon alt,False,
10
+ qh_u,specific_humidity,Specific humidity (upper boom),kg/kg,0,100,,all,all,4,modelResult,time lat lon alt,False,Derived value (L2 or later)
11
+ rh_l,relative_humidity,Relative humidity (lower boom),%,0,100,rh_l_cor,two-boom,all,4,physicalMeasurement,time lat lon alt,False,
12
12
  rh_l_cor,relative_humidity_corrected,Relative humidity (lower boom) - corrected,%,0,150,dshf_l dlhf_l qh_l,two-boom,all,4,modelResult,time lat lon alt,False,
13
- qh_l,specific_humidity,Specific humidity (lower boom),%,0,100,,two-boom,all,4,modelResult,time lat lon alt,False,Derived value (L2 or later)
13
+ qh_l,specific_humidity,Specific humidity (lower boom),kg/kg,0,100,,two-boom,all,4,modelResult,time lat lon alt,False,Derived value (L2 or later)
14
14
  wspd_u,wind_speed,Wind speed (upper boom),m s-1,0,100,"wdir_u wspd_x_u wspd_y_u dshf_u dlhf_u qh_u, precip_u",all,all,4,physicalMeasurement,time lat lon alt,False,
15
15
  wspd_l,wind_speed,Wind speed (lower boom),m s-1,0,100,"wdir_l wspd_x_l wspd_y_l dshf_l dlhf_l qh_l , precip_l",two-boom,all,4,physicalMeasurement,time lat lon alt,False,
16
16
  wdir_u,wind_from_direction,Wind from direction (upper boom),degrees,1,360,wspd_x_u wspd_y_u,all,all,4,physicalMeasurement,time lat lon alt,False,
@@ -81,14 +81,12 @@ fan_dc_l,fan_current,Fan current (lower boom),mA,0,200,,two-boom,all,2,physicalM
81
81
  freq_vw,frequency_of_precipitation_wire_vibration,Frequency of vibrating wire in precipitation gauge,Hz,0,10000,precip_u,,all,,physicalMeasurement,time lat lon alt,True,L0 only
82
82
  t_log,temperature_of_logger,Logger temperature,degrees_C,-80,40,,one-boom,all,4,physicalMeasurement,time lat lon alt,True,LoggerTemperature(C)
83
83
  t_rad,temperature_of_radiation_sensor,Radiation sensor temperature,degrees_C,-80,40,t_surf dlr ulr,all,all,4,physicalMeasurement,time lat lon alt,False,
84
- p_i,air_pressure,Air pressure (instantaneous) minus 1000,hPa,-350,100,,all,TX,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
85
- t_i,air_temperature,Air temperature (instantaneous),degrees_C,-80,40,,all,TX,4,physicalMeasurement,time lat lon alt,True,"PT100 temperature at boom, for meteorological observations"
86
- rh_i,relative_humidity,Relative humidity (instantaneous),%,0,150,rh_i_cor,all,TX,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
87
- rh_i_cor,relative_humidity_corrected,Relative humidity (instantaneous) – corrected,%,0,100,,all,TX,4,modelResult,time lat lon alt,True,For meteorological observations
88
- wspd_i,wind_speed,Wind speed (instantaneous),m s-1,0,100,wdir_i wspd_x_i wspd_y_i,all,TX,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
89
- wdir_i,wind_from_direction,Wind from direction (instantaneous),degrees,1,360,wspd_x_i wspd_y_i,all,TX,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
90
- wspd_x_i,wind_speed_from_x_direction,Wind speed from x direction (instantaneous),m s-1,-100,100,wdir_i wspd_i,all,TX,4,modelResult,time lat lon alt,True,For meteorological observations
91
- wspd_y_i,wind_speed_from_y_direction,Wind speed from y direction (instantaneous),m s-1,-100,100,wdir_i wspd_i,all,TX,4,modelResult,time lat lon alt,True,For meteorological observations
92
- msg_i,message,Message string (instantaneous),-,,,,all,TX,,qualityInformation,time lat lon alt,True,For meteorological observations
93
- msg_lat,message_latitude,latitude from modem (email text),degrees_north,50,83,,all,all,6,coordinate,time lat lon alt,True,
94
- msg_lon,message_longitude,longitude from modem (email text),degrees_east,-72,13,,all,all,6,coordinate,time lat lon alt,True,
84
+ p_i,air_pressure,Air pressure (instantaneous) minus 1000,hPa,-350,100,,all,all,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
85
+ t_i,air_temperature,Air temperature (instantaneous),degrees_C,-80,40,,all,all,4,physicalMeasurement,time lat lon alt,True,"PT100 temperature at boom, for meteorological observations"
86
+ rh_i,relative_humidity,Relative humidity (instantaneous),%,0,150,rh_i_cor,all,all,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
87
+ rh_i_cor,relative_humidity_corrected,Relative humidity (instantaneous) – corrected,%,0,100,,all,all,4,modelResult,time lat lon alt,True,For meteorological observations
88
+ wspd_i,wind_speed,Wind speed (instantaneous),m s-1,0,100,wdir_i wspd_x_i wspd_y_i,all,all,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
89
+ wdir_i,wind_from_direction,Wind from direction (instantaneous),degrees,1,360,wspd_x_i wspd_y_i,all,all,4,physicalMeasurement,time lat lon alt,True,For meteorological observations
90
+ wspd_x_i,wind_speed_from_x_direction,Wind speed from x direction (instantaneous),m s-1,-100,100,wdir_i wspd_i,all,all,4,modelResult,time lat lon alt,True,For meteorological observations
91
+ wspd_y_i,wind_speed_from_y_direction,Wind speed from y direction (instantaneous),m s-1,-100,100,wdir_i wspd_i,all,all,4,modelResult,time lat lon alt,True,For meteorological observations
92
+ msg_i,message,Message string (instantaneous),-,,,,all,all,,qualityInformation,time lat lon alt,True,For meteorological observations
@@ -17,8 +17,7 @@ logger = logging.getLogger(__name__)
17
17
 
18
18
 
19
19
  def flagNAN(ds_in,
20
- flag_url='https://raw.githubusercontent.com/GEUS-Glaciology-and-Climate/PROMICE-AWS-data-issues/master/flags/',
21
- flag_dir='local/flags/'):
20
+ flag_dir='../PROMICE-AWS-data-issues/flags'):
22
21
  '''Read flagged data from .csv file. For each variable, and downstream
23
22
  dependents, flag as invalid (or other) if set in the flag .csv
24
23
 
@@ -26,8 +25,6 @@ def flagNAN(ds_in,
26
25
  ----------
27
26
  ds_in : xr.Dataset
28
27
  Level 0 dataset
29
- flag_url : str
30
- URL to directory where .csv flag files can be found
31
28
  flag_dir : str
32
29
  File directory where .csv flag files can be found
33
30
 
@@ -36,13 +33,10 @@ def flagNAN(ds_in,
36
33
  ds : xr.Dataset
37
34
  Level 0 data with flagged data
38
35
  '''
39
- ds = ds_in.copy()
36
+ ds = ds_in.copy(deep=True)
40
37
  df = None
41
38
 
42
- df = _getDF(flag_url + ds.attrs["station_id"] + ".csv",
43
- os.path.join(flag_dir, ds.attrs["station_id"] + ".csv"),
44
- # download = False, # only for working on draft local flag'n'fix files
45
- )
39
+ df = _getDF(os.path.join(flag_dir, ds.attrs["station_id"] + ".csv"))
46
40
 
47
41
  if isinstance(df, pd.DataFrame):
48
42
  df.t0 = pd.to_datetime(df.t0).dt.tz_localize(None)
@@ -80,8 +74,7 @@ def flagNAN(ds_in,
80
74
 
81
75
 
82
76
  def adjustTime(ds,
83
- adj_url="https://raw.githubusercontent.com/GEUS-Glaciology-and-Climate/PROMICE-AWS-data-issues/master/adjustments/",
84
- adj_dir='local/adjustments/',
77
+ adj_dir='../PROMICE-AWS-data-issues/adjustments/',
85
78
  var_list=[], skip_var=[]):
86
79
  '''Read adjustment data from .csv file. Only applies the "time_shift" adjustment
87
80
 
@@ -89,8 +82,6 @@ def adjustTime(ds,
89
82
  ----------
90
83
  ds : xr.Dataset
91
84
  Level 0 dataset
92
- adj_url : str
93
- URL to directory where .csv adjustment files can be found
94
85
  adj_dir : str
95
86
  File directory where .csv adjustment files can be found
96
87
 
@@ -99,11 +90,10 @@ def adjustTime(ds,
99
90
  ds : xr.Dataset
100
91
  Level 0 data with flagged data
101
92
  '''
102
- ds_out = ds.copy()
93
+ ds_out = ds.copy(deep=True)
103
94
  adj_info=None
104
95
 
105
- adj_info = _getDF(adj_url + ds.attrs["station_id"] + ".csv",
106
- os.path.join(adj_dir, ds.attrs["station_id"] + ".csv"),)
96
+ adj_info = _getDF(os.path.join(adj_dir, ds.attrs["station_id"] + ".csv"))
107
97
 
108
98
  if isinstance(adj_info, pd.DataFrame):
109
99
 
@@ -145,8 +135,7 @@ def adjustTime(ds,
145
135
 
146
136
 
147
137
  def adjustData(ds,
148
- adj_url="https://raw.githubusercontent.com/GEUS-Glaciology-and-Climate/PROMICE-AWS-data-issues/master/adjustments/",
149
- adj_dir='local/adjustments/',
138
+ adj_dir='../PROMICE-AWS-data-issues/adjustments/',
150
139
  var_list=[], skip_var=[]):
151
140
  '''Read adjustment data from .csv file. For each variable, and downstream
152
141
  dependents, adjust data accordingly if set in the adjustment .csv
@@ -155,8 +144,6 @@ def adjustData(ds,
155
144
  ----------
156
145
  ds : xr.Dataset
157
146
  Level 0 dataset
158
- adj_url : str
159
- URL to directory where .csv adjustment files can be found
160
147
  adj_dir : str
161
148
  File directory where .csv adjustment files can be found
162
149
 
@@ -165,24 +152,19 @@ def adjustData(ds,
165
152
  ds : xr.Dataset
166
153
  Level 0 data with flagged data
167
154
  '''
168
- ds_out = ds.copy()
155
+ ds_out = ds.copy(deep=True)
169
156
  adj_info=None
170
- adj_info = _getDF(adj_url + ds.attrs["station_id"] + ".csv",
171
- os.path.join(adj_dir, ds.attrs["station_id"] + ".csv"),
172
- # download = False, # only for working on draft local flag'n'fix files
173
- )
157
+ adj_info = _getDF(os.path.join(adj_dir, ds.attrs["station_id"] + ".csv"))
174
158
 
175
159
  if isinstance(adj_info, pd.DataFrame):
176
160
  # removing potential time shifts from the adjustment list
177
161
  adj_info = adj_info.loc[adj_info.adjust_function != "time_shift", :]
178
162
 
179
- # if t1 is left empty, then adjustment is applied until the end of the file
180
- adj_info.loc[adj_info.t0.isnull(), "t0"] = ds_out.time.values[0]
181
- adj_info.loc[adj_info.t1.isnull(), "t1"] = ds_out.time.values[-1]
182
- # making all timestamps timezone naive (compatibility with xarray)
183
- adj_info.t0 = pd.to_datetime(adj_info.t0).dt.tz_localize(None)
184
- adj_info.t1 = pd.to_datetime(adj_info.t1).dt.tz_localize(None)
185
-
163
+ # making sure that t0 and t1 columns are object dtype then replaceing nan with None
164
+ adj_info[['t0','t1']] = adj_info[['t0','t1']].astype(object)
165
+ adj_info.loc[adj_info.t1.isnull()|(adj_info.t1==''), "t1"] = None
166
+ adj_info.loc[adj_info.t0.isnull()|(adj_info.t0==''), "t0"] = None
167
+
186
168
  # if "*" is in the variable name then we interpret it as regex
187
169
  selec = adj_info['variable'].str.contains('\*') & (adj_info['variable'] != "*")
188
170
  for ind in adj_info.loc[selec, :].index:
@@ -217,104 +199,104 @@ def adjustData(ds,
217
199
  adj_info.loc[var].adjust_function,
218
200
  adj_info.loc[var].adjust_value,
219
201
  ):
220
- if (t0 > pd.to_datetime(ds_out.time.values[-1])) | (t1 < pd.to_datetime(ds_out.time.values[0])):
202
+ # making all timestamps timezone naive (compatibility with xarray)
203
+ if isinstance(t0, str):
204
+ t0 = pd.to_datetime(t0, utc=True).tz_localize(None)
205
+ if isinstance(t1, str):
206
+ t1 = pd.to_datetime(t1, utc=True).tz_localize(None)
207
+
208
+ index_slice = dict(time=slice(t0, t1))
209
+
210
+ if len(ds_out[var].loc[index_slice].time.time) == 0:
211
+ logger.info("Time range does not intersect with dataset")
221
212
  continue
213
+
222
214
  logger.info(f'---> {t0} {t1} {var} {func} {val}')
215
+
223
216
  if func == "add":
224
- ds_out[var].loc[dict(time=slice(t0, t1))] = ds_out[var].loc[dict(time=slice(t0, t1))].values + val
217
+ ds_out[var].loc[index_slice] = ds_out[var].loc[index_slice].values + val
225
218
  # flagging adjusted values
226
219
  # if var + "_adj_flag" not in ds_out.columns:
227
220
  # ds_out[var + "_adj_flag"] = 0
228
- # msk = ds_out[var].loc[dict(time=slice(t0, t1))])].notnull()
229
- # ind = ds_out[var].loc[dict(time=slice(t0, t1))])].loc[msk].time
221
+ # msk = ds_out[var].loc[index_slice])].notnull()
222
+ # ind = ds_out[var].loc[index_slice])].loc[msk].time
230
223
  # ds_out.loc[ind, var + "_adj_flag"] = 1
231
224
 
232
225
  if func == "multiply":
233
- ds_out[var].loc[dict(time=slice(t0, t1))] = ds_out[var].loc[dict(time=slice(t0, t1))].values * val
226
+ ds_out[var].loc[index_slice] = ds_out[var].loc[index_slice].values * val
234
227
  if "DW" in var:
235
- ds_out[var].loc[dict(time=slice(t0, t1))] = ds_out[var].loc[dict(time=slice(t0, t1))] % 360
228
+ ds_out[var].loc[index_slice] = ds_out[var].loc[index_slice] % 360
236
229
  # flagging adjusted values
237
230
  # if var + "_adj_flag" not in ds_out.columns:
238
231
  # ds_out[var + "_adj_flag"] = 0
239
- # msk = ds_out[var].loc[dict(time=slice(t0, t1))].notnull()
240
- # ind = ds_out[var].loc[dict(time=slice(t0, t1))].loc[msk].time
232
+ # msk = ds_out[var].loc[index_slice].notnull()
233
+ # ind = ds_out[var].loc[index_slice].loc[msk].time
241
234
  # ds_out.loc[ind, var + "_adj_flag"] = 1
242
235
 
243
236
  if func == "min_filter":
244
- tmp = ds_out[var].loc[dict(time=slice(t0, t1))].values
237
+ tmp = ds_out[var].loc[index_slice].values
245
238
  tmp[tmp < val] = np.nan
246
239
 
247
240
  if func == "max_filter":
248
- tmp = ds_out[var].loc[dict(time=slice(t0, t1))].values
241
+ tmp = ds_out[var].loc[index_slice].values
249
242
  tmp[tmp > val] = np.nan
250
- ds_out[var].loc[dict(time=slice(t0, t1))] = tmp
243
+ ds_out[var].loc[index_slice] = tmp
251
244
 
252
245
  if func == "upper_perc_filter":
253
- tmp = ds_out[var].loc[dict(time=slice(t0, t1))].copy()
254
- df_w = ds_out[var].loc[dict(time=slice(t0, t1))].resample("14D").quantile(1 - val / 100)
255
- df_w = ds_out[var].loc[dict(time=slice(t0, t1))].resample("14D").var()
246
+ tmp = ds_out[var].loc[index_slice].copy()
247
+ df_w = ds_out[var].loc[index_slice].resample(time="14D").quantile(1 - val / 100)
248
+ df_w = ds_out[var].loc[index_slice].resample(time="14D").var()
256
249
  for m_start, m_end in zip(df_w.time[:-2], df_w.time[1:]):
257
250
  msk = (tmp.time >= m_start) & (tmp.time < m_end)
258
251
  values_month = tmp.loc[msk].values
259
252
  values_month[values_month < df_w.loc[m_start]] = np.nan
260
253
  tmp.loc[msk] = values_month
261
254
 
262
- ds_out[var].loc[dict(time=slice(t0, t1))] = tmp.values
255
+ ds_out[var].loc[index_slice] = tmp.values
263
256
 
264
257
  if func == "biweekly_upper_range_filter":
265
- tmp = ds_out[var].loc[dict(time=slice(t0, t1))].copy()
266
- df_max = ds_out[var].loc[dict(time=slice(t0, t1))].resample("14D").max()
267
- for m_start, m_end in zip(df_max.time[:-2], df_max.time[1:]):
268
- msk = (tmp.time >= m_start) & (tmp.time < m_end)
269
- lim = df_max.loc[m_start] - val
270
- values_month = tmp.loc[msk].values
271
- values_month[values_month < lim] = np.nan
272
- tmp.loc[msk] = values_month
273
- # remaining samples following outside of the last 2 weeks window
274
- msk = tmp.time >= m_end
275
- lim = df_max.loc[m_start] - val
276
- values_month = tmp.loc[msk].values
277
- values_month[values_month < lim] = np.nan
278
- tmp.loc[msk] = values_month
279
- # updating original pandas
280
- ds_out[var].loc[dict(time=slice(t0, t1))] = tmp.values
258
+ df_max = (
259
+ ds_out[var].loc[index_slice].copy(deep=True)
260
+ .resample(time="14D",offset='7D').max()
261
+ .sel(time=ds_out[var].loc[index_slice].time.values, method='ffill')
262
+ )
263
+ df_max['time'] = ds_out[var].loc[index_slice].time
264
+ # updating original pandas
265
+ ds_out[var].loc[index_slice] = ds_out[var].loc[index_slice].where(ds_out[var].loc[index_slice] > df_max-val)
266
+
281
267
 
282
268
  if func == "hampel_filter":
283
- tmp = ds_out[var].loc[dict(time=slice(t0, t1))]
269
+ tmp = ds_out[var].loc[index_slice]
284
270
  tmp = _hampel(tmp, k=7 * 24, t0=val)
285
- ds_out[var].loc[dict(time=slice(t0, t1))] = tmp.values
271
+ ds_out[var].loc[index_slice] = tmp.values
286
272
 
287
273
  if func == "grad_filter":
288
- tmp = ds_out[var].loc[dict(time=slice(t0, t1))].copy()
289
- msk = ds_out[var].loc[dict(time=slice(t0, t1))].copy().diff()
274
+ tmp = ds_out[var].loc[index_slice].copy()
275
+ msk = ds_out[var].loc[index_slice].copy().diff()
290
276
  tmp[np.roll(msk.abs() > val, -1)] = np.nan
291
- ds_out[var].loc[dict(time=slice(t0, t1))] = tmp
277
+ ds_out[var].loc[index_slice] = tmp
292
278
 
293
279
  if "swap_with_" in func:
294
280
  var2 = func[10:]
295
- val_var = ds_out[var].loc[dict(time=slice(t0, t1))].values.copy()
296
- val_var2 = ds_out[var2].loc[dict(time=slice(t0, t1))].values.copy()
297
- ds_out[var2].loc[dict(time=slice(t0, t1))] = val_var
298
- ds_out[var].loc[dict(time=slice(t0, t1))] = val_var2
281
+ val_var = ds_out[var].loc[index_slice].values.copy()
282
+ val_var2 = ds_out[var2].loc[index_slice].values.copy()
283
+ ds_out[var2].loc[index_slice] = val_var
284
+ ds_out[var].loc[index_slice] = val_var2
299
285
 
300
286
  if func == "rotate":
301
- ds_out[var].loc[dict(time=slice(t0, t1))] = (ds_out[var].loc[dict(time=slice(t0, t1))].values + val) % 360
287
+ ds_out[var].loc[index_slice] = (ds_out[var].loc[index_slice].values + val) % 360
302
288
 
303
289
  return ds_out
304
290
 
305
291
 
306
- def _getDF(flag_url, flag_file, download=True):
292
+ def _getDF(flag_file):
307
293
  '''Get dataframe from flag or adjust file. First attempt to retrieve from
308
294
  URL. If this fails then attempt to retrieve from local file
309
295
 
310
296
  Parameters
311
297
  ----------
312
- flag_url : str
313
- URL address to file
314
298
  flag_file : str
315
299
  Local path to file
316
- download : bool
317
- Flag to download file from URL
318
300
 
319
301
  Returns
320
302
  -------
@@ -322,17 +304,7 @@ def _getDF(flag_url, flag_file, download=True):
322
304
  Flag or adjustment dataframe
323
305
  '''
324
306
 
325
- # Download local copy as csv
326
- if download==True:
327
- os.makedirs(os.path.dirname(flag_file), exist_ok = True)
328
-
329
- try:
330
- urllib.request.urlretrieve(flag_url, flag_file)
331
- logger.info(f"Downloaded a {flag_file.split('/')[-2][:-1],} file to {flag_file}")
332
- except (HTTPError, URLError) as e:
333
- logger.info(f"Unable to download {flag_file.split('/')[-2][:-1],} file, using local file: {flag_file}")
334
- else:
335
- logger.info(f"Using local {flag_file.split('/')[-2][:-1],} file: {flag_file}")
307
+ logger.info(f"Using file: {flag_file}")
336
308
 
337
309
  if os.path.isfile(flag_file):
338
310
  df = pd.read_csv(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypromice
3
- Version: 1.3.2
3
+ Version: 1.3.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
@@ -27,6 +27,7 @@ Requires-Dist: scikit-learn >=1.1.0
27
27
  Requires-Dist: Bottleneck
28
28
  Requires-Dist: netcdf4
29
29
  Requires-Dist: pyDataverse
30
+ Requires-Dist: eccodes
30
31
 
31
32
  # pypromice
32
33
  [![PyPI version](https://badge.fury.io/py/pypromice.svg)](https://badge.fury.io/py/pypromice) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/pypromice/badges/version.svg)](https://anaconda.org/conda-forge/pypromice) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/pypromice/badges/platforms.svg)](https://anaconda.org/conda-forge/pypromice) [![](<https://img.shields.io/badge/Dataverse DOI-10.22008/FK2/3TSBF0-orange>)](https://www.doi.org/10.22008/FK2/3TSBF0) [![DOI](https://joss.theoj.org/papers/10.21105/joss.05298/status.svg)](https://doi.org/10.21105/joss.05298) [![Documentation Status](https://readthedocs.org/projects/pypromice/badge/?version=latest)](https://pypromice.readthedocs.io/en/latest/?badge=latest)
@@ -3,10 +3,13 @@ pypromice/get/__init__.py,sha256=n2L6P9EeUsdjsHaeU7BEanBjlkCBX9csGseT8z-laew,32
3
3
  pypromice/get/get.py,sha256=tPrHyllrukGotOR8PjBYJb5tcuL4S_t6WP7wvhbWkg8,7688
4
4
  pypromice/get/get_promice_data.py,sha256=bluNCaP50iRlWBzdEOXLrSPepOQdGB7SeQLkTWiqK4c,1806
5
5
  pypromice/postprocess/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- pypromice/postprocess/csv2bufr.py,sha256=9IyhGyk5VRmlIvkNDsj2yuOkCaaeNT3vJ0umtc8aeNw,20046
7
- pypromice/postprocess/get_bufr.py,sha256=tM3LruCTYYxNG6IBKwf6mx76eCXEHJf5Y2fjRw6HGow,10855
8
- pypromice/postprocess/wmo_config.py,sha256=5ln5vaenG6dz8SppESzE8rrHXkJib-qM1z8SbCNh7n8,8413
9
- pypromice/process/L0toL1.py,sha256=lxL6HRqnrQhUKsEoteUaV4oD8YeMUvzRBOqi8oOd_kA,21384
6
+ pypromice/postprocess/bufr_to_csv.py,sha256=RQZSJ3rC5v-R76rLQf60HNhgH7JQL3WhzXGgySHUyRg,317
7
+ pypromice/postprocess/bufr_utilities.py,sha256=P9hAdYvW-G04cZalV5hm65S8JjZ4ppEKlHkdbzSthtI,17032
8
+ pypromice/postprocess/get_bufr.py,sha256=H8n-LE9KbU70FT1vPdKvd__L2runQSeZpRDCXm9RlBs,20790
9
+ pypromice/postprocess/positions_seed.csv,sha256=0kVCQ8UfEALdeXNYCddmwxpseRqLRudbFStqp_bZRBw,224
10
+ pypromice/postprocess/real_time_utilities.py,sha256=hmJJ0t_dq6nU-VjFOgnWC_hAksECy6gOUw3jblgeekQ,8710
11
+ pypromice/postprocess/station_configurations.toml,sha256=o_NOXTjf8KBNPSa2vQBtSZZPCymIjixTNniVvwUtltk,17025
12
+ pypromice/process/L0toL1.py,sha256=eQw_cJjEEOj4zOuONp1SxTSDXPG5S0SIVlac7tuSlsc,22818
10
13
  pypromice/process/L1toL2.py,sha256=IYrZ9okxGzuJK3dfthk3C75RjsU9yNCgvELK7H41iQg,25538
11
14
  pypromice/process/L2toL3.py,sha256=LnpxGgk1auTHLhef4JUx6iWEhraKoXCRkVsyWI2oYR4,18238
12
15
  pypromice/process/__init__.py,sha256=xvd0I-9nIyVw4M4qjgkQ5vXYpNuKcVSkIVIROQsZDo0,147
@@ -14,10 +17,10 @@ pypromice/process/aws.py,sha256=fIQqOP3WrCBs17a4kMxXzVD-8OD3Mlagy3OxJ-ys_mw,2984
14
17
  pypromice/process/get_l3.py,sha256=jwb5nO22d9Pk5I3SrijkXbTwgqnmqVdxQn0_ACMabH0,1656
15
18
  pypromice/process/join_l3.py,sha256=aAu_7vCSVhigcU2siMOdkz7DL1iA9smImWKNQOYgS3M,4979
16
19
  pypromice/process/metadata.csv,sha256=Zp8Z40m23ohQfzUdLT4z43uHGFvx39rODXZHpUuYn6M,7055
17
- pypromice/process/value_clipping.py,sha256=KTSIENWQz8OcIeoZharXJO-lNrW3yCjmXcclmN-HjzE,1966
18
- pypromice/process/variables.csv,sha256=kXCBlDVjbBgxwow86Xnl-fY48Dh07ZUFasdIehINJzY,13571
20
+ pypromice/process/value_clipping.py,sha256=FkBiDT_HK_BDFiVjB7NdWH-_nab7vONG9LOd2PpEBI8,1573
21
+ pypromice/process/variables.csv,sha256=l6yqVNWlUntnTrXm6u1nrK8ZcrwpMmb_60Hhj-xfli0,13340
19
22
  pypromice/qc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- pypromice/qc/github_data_issues.py,sha256=GvqLEb5_bE_9K5706KwHqb9XzlEA-MLinpcJf495IKY,15646
23
+ pypromice/qc/github_data_issues.py,sha256=DAu2F2HuPSYO_JICKI8-N8zGlbkVOsW6vr1qtMPfe5k,13537
21
24
  pypromice/qc/persistence.py,sha256=TuXxbedsekR1LSBdc0V9xypvlj8mkSE3xqI-U9xqcnY,4647
22
25
  pypromice/qc/persistence_test.py,sha256=DbltqVnnKmxV5T-UiF3AGVMXSVsbzqjYRqhVV1pAL9c,5771
23
26
  pypromice/qc/percentiles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -42,9 +45,9 @@ pypromice/tx/get_watsontx.py,sha256=vFSuDs_vvkATe_6WCF8OLVsx7Wa-MxLATZRfP9qUZqI,
42
45
  pypromice/tx/payload_formats.csv,sha256=4pClTt5qjdB4XViDY2QzuLeJY5EBkEBia0E7Y-aMLVo,7726
43
46
  pypromice/tx/payload_types.csv,sha256=C1-xCmHytAqqAzgzPwBLWqabzWu6s6tKAd8AjVd935s,457
44
47
  pypromice/tx/tx.py,sha256=s1ADVUwX0hoykFMSo_BDgopsIUWTJh2l7KJ05nMNmQg,33692
45
- pypromice-1.3.2.dist-info/LICENSE.txt,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
46
- pypromice-1.3.2.dist-info/METADATA,sha256=oEA0M7Yo-xcAAUw_AAx4qs4fK0OMG0I8IMsbDOrUb10,5073
47
- pypromice-1.3.2.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
48
- pypromice-1.3.2.dist-info/entry_points.txt,sha256=XQW0vu3Jj7lkA0C2_wuOUU6NaWMlbTkZBxK2GN7oDGg,356
49
- pypromice-1.3.2.dist-info/top_level.txt,sha256=cBdfwgSbWDQq3a07nKRjrfmLC7jdaYXs98GG58HpTks,10
50
- pypromice-1.3.2.dist-info/RECORD,,
48
+ pypromice-1.3.4.dist-info/LICENSE.txt,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
49
+ pypromice-1.3.4.dist-info/METADATA,sha256=uCKUJ1oPZZCZqfy8X9W_QhfQIfg27pS8IMEOHHkdZnY,5096
50
+ pypromice-1.3.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
51
+ pypromice-1.3.4.dist-info/entry_points.txt,sha256=8CGN4oJByZuvVFt9rL8HG41F11XL2L6aSe-EPjHTkkE,352
52
+ pypromice-1.3.4.dist-info/top_level.txt,sha256=cBdfwgSbWDQq3a07nKRjrfmLC7jdaYXs98GG58HpTks,10
53
+ pypromice-1.3.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.3)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,5 +1,5 @@
1
1
  [console_scripts]
2
- get_bufr = pypromice.postprocess.get_bufr:get_bufr
2
+ get_bufr = pypromice.postprocess.get_bufr:main
3
3
  get_l0tx = pypromice.tx.get_l0tx:get_l0tx
4
4
  get_l3 = pypromice.process.get_l3:get_l3
5
5
  get_msg = pypromice.tx.get_msg:get_msg