apmtools 0.2.14__tar.gz → 0.2.16__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: apmtools
3
- Version: 0.2.014
3
+ Version: 0.2.016
4
4
  Summary: A collection of tools for processing air pollution monitoring data
5
5
  Project-URL: Homepage, https://github.com/federlorenz/apmtools
6
6
  Author-email: Federico Lorenzetti <lorenzetti.federico@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "apmtools"
7
- version = "0.2.014"
7
+ version = "0.2.016"
8
8
  authors = [
9
9
  { name="Federico Lorenzetti", email="lorenzetti.federico@gmail.com" },
10
10
  ]
@@ -44,7 +44,10 @@ def _default_x(data: pd.DataFrame) -> str:
44
44
  for column in data.columns
45
45
  if pd.api.types.is_datetime64_any_dtype(data[column])
46
46
  ]
47
- return str(datetime_columns[0] if datetime_columns else data.columns[0])
47
+ if "time" in datetime_columns:
48
+ return "time"
49
+ else:
50
+ return str(datetime_columns[0] if datetime_columns else data.columns[0])
48
51
 
49
52
  def _default_group(data: pd.DataFrame) -> str | None:
50
53
  """Return ``identifier`` when available."""
@@ -52,13 +55,49 @@ def _default_group(data: pd.DataFrame) -> str | None:
52
55
 
53
56
  def _numeric_columns(data: pd.DataFrame) -> list[str]:
54
57
  """Return numeric column names as strings."""
55
- return [
58
+ return sorted([
56
59
  str(column)
57
60
  for column in data.columns
58
61
  if pd.api.types.is_numeric_dtype(data[column])
59
- ]
62
+ ])
63
+
64
+
65
+ def _categorical_columns(data: pd.DataFrame) -> list[str]:
66
+ """Return categorical column names as strings."""
67
+ return sorted(
68
+ [
69
+ str(column)
70
+ for column in data.columns
71
+ if not pd.api.types.is_numeric_dtype(data[column])
72
+ and not pd.api.types.is_datetime64_any_dtype(data[column])
73
+ ],
74
+ key=str.casefold,
75
+ )
60
76
 
61
77
 
78
+ def _datetime_columns(data: pd.DataFrame) -> list[str]:
79
+ """Return datetime column names as strings."""
80
+ return sorted(
81
+ [
82
+ str(column)
83
+ for column in data.columns
84
+ if pd.api.types.is_datetime64_any_dtype(data[column])
85
+ ],
86
+ key=str.casefold,
87
+ )
88
+
89
+
90
+ def _timedelta_columns(data: pd.DataFrame) -> list[str]:
91
+ """Return timedelta column names as strings."""
92
+ return sorted(
93
+ [
94
+ str(column)
95
+ for column in data.columns
96
+ if pd.api.types.is_timedelta64_dtype(data[column])
97
+ ],
98
+ key=str.casefold,
99
+ )
100
+
62
101
  def _normalise_y(data: pd.DataFrame, x: str, y: str | Sequence[str] | None) -> list[str]:
63
102
  """Validate and normalise an initial Y selection."""
64
103
  numeric = _numeric_columns(data)
@@ -71,6 +110,12 @@ def _normalise_y(data: pd.DataFrame, x: str, y: str | Sequence[str] | None) -> l
71
110
  return [str(column) for column in values]
72
111
 
73
112
 
113
+ def _alphabetical(values) -> list[str]:
114
+ """Return string values sorted alphabetically, case-insensitively."""
115
+ return sorted((str(value) for value in values), key=str.casefold)
116
+
117
+
118
+
74
119
  def _subset_choices(data: pd.DataFrame, column: str) -> tuple[dict[str, str], dict[str, object]]:
75
120
  """Build stable Shiny choices and their corresponding original values."""
76
121
  values = pd.unique(data[column].dropna())
@@ -250,9 +295,10 @@ def create_summary_app(
250
295
  raise ValueError(
251
296
  "Cannot create a Shiny application from an empty Summary.")
252
297
 
253
- columns = [str(c) for c in summary.columns]
298
+ columns = _alphabetical(summary.columns)
254
299
  column_map = {str(c): c for c in summary.columns}
255
- numeric_columns = _numeric_columns(summary)
300
+ numeric_columns = _alphabetical(_numeric_columns(summary))
301
+ categorical_columns = _categorical_columns(summary)
256
302
 
257
303
  x = _default_x(summary) if x is None else str(x)
258
304
  if x not in column_map:
@@ -281,12 +327,8 @@ def create_summary_app(
281
327
  ui.h4("Plot controls"),
282
328
  ui.input_select("plot_type", "Plot type",
283
329
  choices=PLOT_TYPES, selected=plot_type),
284
- ui.input_select("x", "X-axis / category",
285
- choices=columns, selected=x),
286
- ui.input_selectize(
287
- "y", "Y-axis / variable", choices=numeric_columns,
288
- selected=initial_y, multiple=True,
289
- ),
330
+ ui.output_ui("x_control"),
331
+ ui.output_ui("y_control"),
290
332
  ui.input_selectize(
291
333
  "group_by", "Group by",
292
334
  choices={c: c for c in columns},
@@ -338,6 +380,43 @@ def create_summary_app(
338
380
  )
339
381
 
340
382
  def server(input, output, session):
383
+ @render.ui
384
+ def x_control():
385
+ """Use categorical X choices for boxplots; all columns otherwise."""
386
+ if input.plot_type() == "box":
387
+ if not categorical_columns:
388
+ return ui.help_text(
389
+ "Boxplots require at least one categorical column for the X axis."
390
+ )
391
+ selected = x if x in categorical_columns else categorical_columns[0]
392
+ return ui.input_select(
393
+ "x", "X-axis / category",
394
+ choices={c: c for c in categorical_columns},
395
+ selected=selected,
396
+ )
397
+ return ui.input_select(
398
+ "x", "X-axis / category",
399
+ choices={c: c for c in columns},
400
+ selected=x,
401
+ )
402
+
403
+ @render.ui
404
+ def y_control():
405
+ """Boxplots accept one numeric Y variable; other plots accept many."""
406
+ if input.plot_type() == "box":
407
+ selected = initial_y[0] if initial_y else (
408
+ numeric_columns[0] if numeric_columns else None)
409
+ return ui.input_select(
410
+ "y", "Y-axis / variable",
411
+ choices={c: c for c in numeric_columns},
412
+ selected=selected,
413
+ )
414
+ return ui.input_selectize(
415
+ "y", "Y-axis / variable",
416
+ choices={c: c for c in numeric_columns},
417
+ selected=initial_y, multiple=True,
418
+ )
419
+
341
420
  @render.ui
342
421
  def subset_filters():
343
422
  """Render one value selector for every selected subset column."""
@@ -395,7 +474,9 @@ def create_summary_app(
395
474
  @reactive.calc
396
475
  def selected_data():
397
476
  current = filtered_summary()
398
- selected_y = list(input.y())
477
+ y_input = input.y()
478
+ selected_y = ([y_input] if isinstance(
479
+ y_input, str) else list(y_input or []))
399
480
  if not selected_y:
400
481
  return pd.DataFrame()
401
482
 
@@ -405,9 +486,18 @@ def create_summary_app(
405
486
  frequency = FREQUENCIES[input.frequency()]
406
487
  aggregate = AGGREGATES[input.aggregate()]
407
488
 
489
+ # A boxplot's categorical X must survive group_stat(). Include it
490
+ # as a statistical grouping key when frequency aggregation is used,
491
+ # without turning it into a colour/group selection in the UI.
492
+ if input.plot_type() == "box":
493
+ selected_x = input.x()
494
+ if selected_x in column_map:
495
+ box_x = column_map[selected_x]
496
+ if box_x not in grouping_by:
497
+ grouping_by = [*grouping_by, box_x]
498
+
408
499
  # All selected grouping columns are passed directly to
409
- # Summary.group_stat() when a frequency is selected. With raw
410
- # data they remain plotting-only grouping columns.
500
+ # Summary.group_stat() when a frequency is selected.
411
501
  if frequency is not None:
412
502
  current = _aggregate(current, y_columns,
413
503
  frequency, grouping_by, aggregate)
@@ -419,7 +509,9 @@ def create_summary_app(
419
509
  plot_df = selected_data()
420
510
  selected_plot = input.plot_type()
421
511
  selected_x = input.x()
422
- selected_y = list(input.y())
512
+ y_input = input.y()
513
+ selected_y = ([y_input] if isinstance(
514
+ y_input, str) else list(y_input or []))
423
515
  selected_groups = list(input.group_by())
424
516
  frequency = FREQUENCIES[input.frequency()]
425
517
 
@@ -441,7 +533,12 @@ def create_summary_app(
441
533
  y_columns = _aggregated_value_columns(
442
534
  plot_df, selected_y_columns, aggregate
443
535
  )
444
- x_column = frequency
536
+ if selected_plot == "box":
537
+ if selected_x not in column_map:
538
+ return px.scatter(title="Select a categorical X variable for the boxplot")
539
+ x_column = column_map[selected_x]
540
+ else:
541
+ x_column = frequency
445
542
 
446
543
  if x_column not in plot_df.columns:
447
544
  return px.scatter(
@@ -511,18 +608,23 @@ def create_summary_app(
511
608
  opacity=0.65 if len(y_columns) > 1 else 1.0,
512
609
  )
513
610
  elif selected_plot == "box":
514
- if not group_columns:
515
- long_df = plot_df[y_columns].melt(
516
- var_name="variable", value_name="value")
517
- fig = px.box(long_df, x="variable",
518
- y="value", points="outliers")
611
+ # Boxplots are distributions of one numerical variable across
612
+ # categories. X is therefore always the selected categorical
613
+ # column and Y is exactly one numerical variable.
614
+ if x_column not in categorical_columns:
615
+ return px.scatter(
616
+ title="Boxplots require a categorical variable on the X axis"
617
+ )
618
+ y_column = y_columns[0]
619
+ if group_columns:
620
+ fig = px.box(
621
+ plot_df, x=x_column, y=y_column,
622
+ color="__plot_group", points="outliers",
623
+ )
519
624
  else:
520
- group_column = "__plot_group"
521
- long_df = plot_df[[group_column, *y_columns]].melt(
522
- id_vars=[group_column], var_name="variable", value_name="value",
625
+ fig = px.box(
626
+ plot_df, x=x_column, y=y_column, points="outliers"
523
627
  )
524
- fig = px.box(long_df, x="variable", y="value",
525
- color=group_column, points="outliers")
526
628
  elif selected_plot == "bar":
527
629
  if not group_columns:
528
630
  fig = px.bar(plot_df, x=x_column,
@@ -0,0 +1,386 @@
1
+ upas_units = {'AccelComplianceCnt': '#',
2
+ 'AccelComplianceHrs': 'hrs',
3
+ 'AccelT': '°C',
4
+ 'AccelX': 'mg',
5
+ 'AccelXMax': 'mg',
6
+ 'AccelXMin': 'mg',
7
+ 'AccelXVar': 'mg',
8
+ 'AccelY': 'mg',
9
+ 'AccelYMax': 'mg',
10
+ 'AccelYMin': 'mg',
11
+ 'AccelYVar': 'mg',
12
+ 'AccelZ': 'mg',
13
+ 'AccelZMax': 'mg',
14
+ 'AccelZMin': 'mg',
15
+ 'AccelZVar': 'mg',
16
+ 'AtmoAlt': 'm',
17
+ 'AtmoDensity': 'g L-1',
18
+ 'AtmoP': 'hPa',
19
+ 'AtmoRH': '%',
20
+ 'AtmoT': '°C',
21
+ 'BCS1': 'bool',
22
+ 'BCS2': 'bool',
23
+ 'BC_NPG': 'bool',
24
+ 'BFGenergy': 'integer',
25
+ 'BattVolt': 'V',
26
+ 'BatteryCharge': '%',
27
+ 'CO2': 'ppm',
28
+ 'Charging': 'bool',
29
+ 'DateTimeUTC': 'HH:MM:SS',
30
+ 'Dead': 'bool',
31
+ 'ExtPow': '-',
32
+ 'FLOWCTL': 's',
33
+ 'FdpT': '°C',
34
+ 'FilterDP': 'Pa',
35
+ 'GPSQual': '-',
36
+ 'GPSRT': 's',
37
+ 'GPSalt': 'm',
38
+ 'GPShDOP': '-',
39
+ 'GPSlat': 'decimalDegree',
40
+ 'GPSlon': 'decimalDegree',
41
+ 'GPSsat': '#',
42
+ 'GPSspeed': 'm s-1',
43
+ 'HighVisRaw': '-',
44
+ 'IRRaw': '-',
45
+ 'LUX': 'lux',
46
+ 'LowVisRaw': '-',
47
+ 'MFSVout': 'V',
48
+ 'MassFlow': 'g min-1',
49
+ 'MassFlowFactory': 'g min-1',
50
+ 'NOXRaw': '-',
51
+ 'OverallFlowFactory': 'L min-1',
52
+ 'OverallFlowOffset': 'L min-1',
53
+ 'OverallFlowRate': 'L min-1)',
54
+ 'PCB1T': '°C',
55
+ 'PCB2P': 'hPa',
56
+ 'PCB2T': '°C',
57
+ 'PM0_5NC': '# cm-3',
58
+ 'PM0_5NCVar': '# cm-3',
59
+ 'PM10MC': 'µg m-3',
60
+ 'PM10MCVar': 'µg m-3',
61
+ 'PM10NC': '# cm-3',
62
+ 'PM10NCVar': '# cm-3',
63
+ 'PM1MC': 'µg m-3',
64
+ 'PM1MCVar': 'µg m-3',
65
+ 'PM1NC': '# cm-3',
66
+ 'PM1NCVar': '# cm-3',
67
+ 'PM2_5MC': 'μg/m3',
68
+ 'PM2_5MCVar': 'µg m-3',
69
+ 'PM2_5NC': '# cm-3',
70
+ 'PM2_5NCVar': '# cm-3',
71
+ 'PM2_5SampledMass': 'µg',
72
+ 'PM2_5SampledMassFactory': 'μg',
73
+ 'PM2_5SampledMassOffset': 'μg',
74
+ 'PM4MC': 'µg m-3',
75
+ 'PM4MCVar': 'µg m-3',
76
+ 'PM4NC': '# cm-3',
77
+ 'PM4NCVar': '# cm-3',
78
+ 'PMFanErrorCnt': '#',
79
+ 'PMFanSpeedWarn': '#',
80
+ 'PMLaserErrorCnt': '#',
81
+ 'PMMeasCnt': '#',
82
+ 'PMReadingErrorCnt': '#',
83
+ 'PMtypicalParticleSize': 'µm',
84
+ 'PMtypicalParticleSizeVar': 'µm',
85
+ 'PT100R': 'Ω',
86
+ 'PumpPow1': 'integer',
87
+ 'PumpPow2': 'integer',
88
+ 'PumpV': 'V',
89
+ 'PumpingFlowFactory': 'L min-1',
90
+ 'PumpingFlowOffset': 'L min-1',
91
+ 'PumpingFlowRate': 'L min-1)',
92
+ 'PumpsON': 'bool',
93
+ 'RotX': 'mdeg s-1',
94
+ 'RotXMax': 'mdeg s-1',
95
+ 'RotXMin': 'mdeg s-1',
96
+ 'RotXVar': 'mdeg s-1',
97
+ 'RotY': 'mdeg s-1',
98
+ 'RotYMax': 'mdeg s-1',
99
+ 'RotYMin': 'mdeg s-1',
100
+ 'RotYVar': 'mdeg s-1',
101
+ 'RotZ': 'mdeg s-1',
102
+ 'RotZMax': 'mdeg s-1',
103
+ 'RotZMin': 'mdeg s-1',
104
+ 'RotZVar': 'mdeg s-1',
105
+ 'SCDRH': '%',
106
+ 'SCDT': '°C',
107
+ 'SD_DATAW': 's',
108
+ 'SD_HEADW': 's',
109
+ 'SampleTime': '',
110
+ 'SampledVolume': 'L',
111
+ 'SampledVolumeFactory': 'L',
112
+ 'SampledVolumeOffset': 'L',
113
+ 'StepCount': '#',
114
+ 'TPumpsOFF': 's',
115
+ 'TPumpsON': 's',
116
+ 'U12T': '°C',
117
+ 'U29P': '°C',
118
+ 'U29T': '°C',
119
+ 'UVRaw': '-',
120
+ 'UVindex': '-',
121
+ 'UnixTime': 's',
122
+ 'VOCRaw': '-',
123
+ 'XDown': '%',
124
+ 'Xup': '%',
125
+ 'Ydown': '%',
126
+ 'Yup': '%',
127
+ 'Zdown': '%',
128
+ 'Zup': '%',
129
+ 'cartridgeid': '-',
130
+ 'end': 'YYYY-MM-DDTHH:MM:SS',
131
+ 'index': '-',
132
+ 'length': 'days HH:MM:SS',
133
+ 'pm25': 'µg m-3',
134
+ 'pm25correctedrh': 'µg m-3',
135
+ 'start': 'YYYY-MM-DDTHH:MM:SS',
136
+ 'time': 'YYYY-MM-DDTHH:MM:SS',
137
+ 'upasid': '-',
138
+ 'v3_3': 'V',
139
+ 'v5': 'V'}
140
+
141
+ upas_datatype = {'AccelComplianceCnt': 'integer',
142
+ 'AccelComplianceHrs': 'timedelta',
143
+ 'AccelT': 'numeric',
144
+ 'AccelX': 'numeric',
145
+ 'AccelXMax': 'numeric',
146
+ 'AccelXMin': 'numeric',
147
+ 'AccelXVar': 'numeric',
148
+ 'AccelY': 'numeric',
149
+ 'AccelYMax': 'numeric',
150
+ 'AccelYMin': 'numeric',
151
+ 'AccelYVar': 'numeric',
152
+ 'AccelZ': 'numeric',
153
+ 'AccelZMax': 'numeric',
154
+ 'AccelZMin': 'numeric',
155
+ 'AccelZVar': 'numeric',
156
+ 'AtmoAlt': 'numeric',
157
+ 'AtmoDensity': 'numeric',
158
+ 'AtmoP': 'numeric',
159
+ 'AtmoRH': 'numeric',
160
+ 'AtmoT': 'numeric',
161
+ 'BCS1': 'bool',
162
+ 'BCS2': 'bool',
163
+ 'BC_NPG': 'bool',
164
+ 'BFGenergy': 'integer',
165
+ 'BattVolt': 'numeric',
166
+ 'BatteryCharge': '%',
167
+ 'CO2': 'numeric',
168
+ 'Charging': 'bool',
169
+ 'DateTimeUTC': 'datetime',
170
+ 'Dead': 'bool',
171
+ 'ExtPow': 'bool',
172
+ 'FLOWCTL': 'timedelta',
173
+ 'FdpT': 'numeric',
174
+ 'FilterDP': 'numeric',
175
+ 'GPSQual': 'text',
176
+ 'GPSRT': 'timedelta',
177
+ 'GPSalt': 'numeric',
178
+ 'GPShDOP': '',
179
+ 'GPSlat': 'numeric',
180
+ 'GPSlon': 'numeric',
181
+ 'GPSsat': 'integer',
182
+ 'GPSspeed': 'numeric',
183
+ 'HighVisRaw': '',
184
+ 'IRRaw': '',
185
+ 'LUX': 'numeric',
186
+ 'LowVisRaw': '',
187
+ 'MFSVout': 'numeric',
188
+ 'MassFlow': 'numeric',
189
+ 'MassFlowFactory': 'numeric',
190
+ 'NOXRaw': 'numeric',
191
+ 'OverallFlowFactory': 'numeric',
192
+ 'OverallFlowOffset': 'numeric',
193
+ 'OverallFlowRate': 'numeric',
194
+ 'PCB1T': 'numeric',
195
+ 'PCB2P': 'numeric',
196
+ 'PCB2T': 'numeric',
197
+ 'PM0_5NC': 'integer',
198
+ 'PM0_5NCVar': 'numeric',
199
+ 'PM10MC': 'numeric',
200
+ 'PM10MCVar': 'numeric',
201
+ 'PM10NC': 'numeric',
202
+ 'PM10NCVar': 'numeric',
203
+ 'PM1MC': 'numeric',
204
+ 'PM1MCVar': 'numeric',
205
+ 'PM1NC': 'numeric',
206
+ 'PM1NCVar': 'numeric',
207
+ 'PM2_5MC': 'numeric',
208
+ 'PM2_5MCVar': 'numeric',
209
+ 'PM2_5NC': 'numeric',
210
+ 'PM2_5NCVar': 'numeric',
211
+ 'PM2_5SampledMass': 'numeric',
212
+ 'PM2_5SampledMassFactory': 'numeric',
213
+ 'PM2_5SampledMassOffset': 'numeric',
214
+ 'PM4MC': 'numeric',
215
+ 'PM4MCVar': 'numeric',
216
+ 'PM4NC': 'numeric',
217
+ 'PM4NCVar': 'numeric',
218
+ 'PMFanErrorCnt': 'numeric',
219
+ 'PMFanSpeedWarn': 'bool',
220
+ 'PMLaserErrorCnt': 'numeric',
221
+ 'PMMeasCnt': 'numeric',
222
+ 'PMReadingErrorCnt': 'numeric',
223
+ 'PMtypicalParticleSize': 'numeric',
224
+ 'PMtypicalParticleSizeVar': 'numeric',
225
+ 'PT100R': 'numeric',
226
+ 'PumpPow1': 'numeric',
227
+ 'PumpPow2': 'numeric',
228
+ 'PumpV': 'numeric',
229
+ 'PumpingFlowFactory': 'numeric',
230
+ 'PumpingFlowOffset': 'numeric',
231
+ 'PumpingFlowRate': 'numeric',
232
+ 'PumpsON': 'bool',
233
+ 'RotX': 'numeric',
234
+ 'RotXMax': 'numeric',
235
+ 'RotXMin': 'numeric',
236
+ 'RotXVar': 'numeric',
237
+ 'RotY': 'numeric',
238
+ 'RotYMax': 'numeric',
239
+ 'RotYMin': 'numeric',
240
+ 'RotYVar': 'numeric',
241
+ 'RotZ': 'numeric',
242
+ 'RotZMax': 'numeric',
243
+ 'RotZMin': 'numeric',
244
+ 'RotZVar': 'numeric',
245
+ 'SCDRH': 'numeric',
246
+ 'SCDT': 'numeric',
247
+ 'SD_DATAW': 'timedelta',
248
+ 'SD_HEADW': 'timedelta',
249
+ 'SampleTime': 'datetime',
250
+ 'SampledVolume': 'numeric',
251
+ 'SampledVolumeFactory': 'numeric',
252
+ 'SampledVolumeOffset': 'numeric',
253
+ 'StepCount': 'numeric',
254
+ 'TPumpsOFF': 'bool',
255
+ 'TPumpsON': 'bool',
256
+ 'U12T': 'numeric',
257
+ 'U29P': 'numeric',
258
+ 'U29T': 'numeric',
259
+ 'UVRaw': 'numeric',
260
+ 'UVindex': 'numeric',
261
+ 'UnixTime': 'datetime',
262
+ 'VOCRaw': 'numeric',
263
+ 'XDown': 'numeric',
264
+ 'Xup': 'numeric',
265
+ 'Ydown': 'numeric',
266
+ 'Yup': 'numeric',
267
+ 'Zdown': 'numeric',
268
+ 'Zup': 'numeric',
269
+ 'end': 'datetime',
270
+ 'length': 'timedelta',
271
+ 'pm25': 'numeric',
272
+ 'pm25correctedrh': 'numeric',
273
+ 'start': 'datetime',
274
+ 'time': 'datetime',
275
+ 'v3_3': 'numeric',
276
+ 'v5': 'numeric'}
277
+
278
+ lascar_units = {"CO(ppm)":"ppm"}
279
+
280
+ lascar_datatype = {"CO(ppm)": "numeric",
281
+ 'start': "datetime",
282
+ 'end': "datetime",
283
+ 'length': "timedelta",
284
+ 'time': "datetime"}
285
+
286
+ purple_units = {'mac_address':"-",
287
+ 'firmware_ver':"-",
288
+ 'hardware':"-",
289
+ 'current_temp_f':"F",
290
+ 'current_humidity':"%",
291
+ 'current_dewpoint_f':"F",
292
+ 'pressure':"mBar",
293
+ 'adc':"",
294
+ 'mem':"",
295
+ 'rssi':"",
296
+ 'uptime':"",
297
+ 'pm1_0_cf_1': "μg m-3",
298
+ 'pm2_5_cf_1': "μg m-3",
299
+ 'pm10_0_cf_1': "μg m-3",
300
+ 'pm1_0_atm': "μg m-3",
301
+ 'pm2_5_atm': "μg m-3",
302
+ 'pm10_0_atm': "μg m-3",
303
+ 'pm2.5_aqi_cf_1': "μg m-3",
304
+ 'pm2.5_aqi_atm': "μg m-3",
305
+ 'p_0_3_um':"#",
306
+ 'p_0_5_um':"#",
307
+ 'p_1_0_um':"#",
308
+ 'p_2_5_um':"#",
309
+ 'p_5_0_um':"#",
310
+ 'p_10_0_um':"#",
311
+ 'pm1_0_cf_1_b': "μg m-3",
312
+ 'pm2_5_cf_1_b': "μg m-3",
313
+ 'pm10_0_cf_1_b': "μg m-3",
314
+ 'pm1_0_atm_b': "μg m-3",
315
+ 'pm2_5_atm_b': "μg m-3",
316
+ 'pm10_0_atm_b': "μg m-3",
317
+ 'pm2.5_aqi_cf_1_b': "μg m-3",
318
+ 'pm2.5_aqi_atm_b': "μg m-3",
319
+ 'p_0_3_um_b':"#",
320
+ 'p_0_5_um_b':"#",
321
+ 'p_1_0_um_b':"#",
322
+ 'p_2_5_um_b':"#",
323
+ 'p_5_0_um_b':"#",
324
+ 'p_10_0_um_b':"#",
325
+ 'gas':"",
326
+ 'pm_adj': "μg m-3"}
327
+
328
+ purple_datatype = {'mac_address': "text",
329
+ 'firmware_ver': "text",
330
+ 'hardware': "text",
331
+ 'current_temp_f': "numeric",
332
+ 'current_humidity': "numeric",
333
+ 'current_dewpoint_f': "numeric",
334
+ 'pressure': "numeric",
335
+ 'adc': "text",
336
+ 'mem': "text",
337
+ 'rssi': "text",
338
+ 'uptime': "text",
339
+ 'pm1_0_c': "numeric",
340
+ 'PumpingFlowFactory': 'numeric',
341
+ 'PumpingFlowOffset': 'numeric',
342
+ 'PumpingFlowRate': 'numeric',
343
+ 'PumpsON': 'bool',
344
+ 'RotX': 'numeric',
345
+ 'RotXMax': 'numeric',
346
+ 'RotXMin': 'numeric',
347
+ 'RotXVar': 'numeric',
348
+ 'RotY': 'numeric',
349
+ 'RotYMax': 'numeric',
350
+ 'RotYMin': 'numeric',
351
+ 'RotYVar': 'numeric',
352
+ 'RotZ': 'numeric',
353
+ 'pm1_0_cf_1': "numeric",
354
+ 'pm2_5_cf_1': "numeric",
355
+ 'pm10_0_cf_1': "numeric",
356
+ 'pm1_0_atm': "numeric",
357
+ 'pm2_5_atm': "numeric",
358
+ 'pm10_0_atm': "numeric",
359
+ 'pm2.5_aqi_cf_1': "numeric",
360
+ 'pm2.5_aqi_atm': "numeric",
361
+ 'p_0_3_um': "numeric",
362
+ 'p_0_5_um': "numeric",
363
+ 'p_1_0_um': "numeric",
364
+ 'p_2_5_um': "numeric",
365
+ 'p_5_0_um': "numeric",
366
+ 'p_10_0_um': "numeric",
367
+ 'pm1_0_cf_1_b': "numeric",
368
+ 'pm2_5_cf_1_b': "numeric",
369
+ 'pm10_0_cf_1_b': "numeric",
370
+ 'pm1_0_atm_b': "numeric",
371
+ 'pm2_5_atm_b': "numeric",
372
+ 'pm10_0_atm_b': "numeric",
373
+ 'pm2.5_aqi_cf_1_b': "numeric",
374
+ 'pm2.5_aqi_atm_b': "numeric",
375
+ 'p_0_3_um_b': "numeric",
376
+ 'p_0_5_um_b': "numeric",
377
+ 'p_1_0_um_b': "numeric",
378
+ 'p_2_5_um_b': "numeric",
379
+ 'p_5_0_um_b': "numeric",
380
+ 'p_10_0_um_b': "numeric",
381
+ 'gas': "text",
382
+ 'pm_adj': "numeric",
383
+ 'start':"datetime",
384
+ 'end':"datetime",
385
+ 'length':"timedelta",
386
+ 'time':"datetime"}
@@ -1,155 +0,0 @@
1
- upas_units= {'PumpingFlowRate':"",
2
- 'OverallFlowRate':"",
3
- 'SampledVolume':"",
4
- 'FilterDP':"",
5
- 'BatteryCharge':"",
6
- 'AtmoT':"",
7
- 'AtmoP':"",
8
- 'AtmoRH':"",
9
- 'AtmoDensity':"",
10
- 'AtmoAlt':"",
11
- 'GPSQual':"",
12
- 'GPSlat':"",
13
- 'GPSlon':"",
14
- 'GPSalt':"",
15
- 'GPSsat':"",
16
- 'GPSspeed':"",
17
- 'GPShDOP':"",
18
- 'AccelX':"",
19
- 'AccelXVar':"",
20
- 'AccelXMin':"",
21
- 'AccelXMax':"",
22
- 'AccelY':"",
23
- 'AccelYVar':"",
24
- 'AccelYMin':"",
25
- 'AccelYMax':"",
26
- 'AccelZ':"",
27
- 'AccelZVar':"",
28
- 'AccelZMin':"",
29
- 'AccelZMax':"",
30
- 'RotX':"",
31
- 'RotXVar':"",
32
- 'RotXMin':"",
33
- 'RotXMax':"",
34
- 'RotY':"",
35
- 'RotYVar':"",
36
- 'RotYMin':"",
37
- 'RotYMax':"",
38
- 'RotZ':"",
39
- 'RotZVar':"",
40
- 'RotZMin':"",
41
- 'RotZMax':"",
42
- 'Xup':"",
43
- 'XDown':"",
44
- 'Yup':"",
45
- 'Ydown':"",
46
- 'Zup':"",
47
- 'Zdown':"",
48
- 'StepCount':"",
49
- 'LUX':"",
50
- 'UVindex':"",
51
- 'HighVisRaw':"",
52
- 'LowVisRaw':"",
53
- 'IRRaw':"",
54
- 'UVRaw':"",
55
- 'PMMeasCnt':"",
56
- 'PM1MC':"",
57
- 'PM1MCVar':"",
58
- 'PM2_5MC': "μg/m3",
59
- 'PM2_5MCVar':"",
60
- 'PM4MC':"",
61
- 'PM4MCVar':"",
62
- 'PM10MC':"",
63
- 'PM10MCVar':"",
64
- 'PM0_5NC':"",
65
- 'PM0_5NCVar':"",
66
- 'PM1NC':"",
67
- 'PM1NCVar':"",
68
- 'PM2_5NC':"",
69
- 'PM2_5NCVar':"",
70
- 'PM4NC':"",
71
- 'PM4NCVar':"",
72
- 'PM10NC':"",
73
- 'PM10NCVar':"",
74
- 'PMtypicalParticleSize':"",
75
- 'PMtypicalParticleSizeVar':"",
76
- 'PM2_5SampledMass':"",
77
- 'PMReadingErrorCnt':"",
78
- 'PMFanErrorCnt':"",
79
- 'PMLaserErrorCnt':"",
80
- 'PMFanSpeedWarn':"",
81
- 'PCB1T':"",
82
- 'PCB2T':"",
83
- 'FdpT':"",
84
- 'AccelT':"",
85
- 'PT100R':"",
86
- 'PCB2P':"",
87
- 'PumpPow1':"",
88
- 'PumpPow2':"",
89
- 'PumpV':"",
90
- 'MassFlow':"",
91
- 'MFSVout':"",
92
- 'BFGenergy':"",
93
- 'BattVolt':"",
94
- 'v3_3':"",
95
- 'v5':"",
96
- 'PumpsON':"",
97
- 'Dead':"",
98
- 'BCS1':"",
99
- 'BCS2':"",
100
- 'BC_NPG':"",
101
- 'FLOWCTL':"",
102
- 'GPSRT':"",
103
- 'SD_DATAW':"",
104
- 'SD_HEADW':"",
105
- 'TPumpsOFF':"",
106
- 'TPumpsON':"",
107
- 'CO2':"",
108
- 'SCDT':"",
109
- 'SCDRH':"",
110
- 'VOCRaw':"",
111
- 'NOXRaw':""}
112
-
113
- lascar_units = {"CO(ppm)":"ppm"}
114
-
115
- purple_units = {'mac_address':"",
116
- 'firmware_ver':"",
117
- 'hardware':"",
118
- 'current_temp_f':"",
119
- 'current_humidity':"",
120
- 'current_dewpoint_f':"",
121
- 'pressure':"",
122
- 'adc':"",
123
- 'mem':"",
124
- 'rssi':"",
125
- 'uptime':"",
126
- 'pm1_0_cf_1':"",
127
- 'pm2_5_cf_1':"",
128
- 'pm10_0_cf_1':"",
129
- 'pm1_0_atm':"",
130
- 'pm2_5_atm':"",
131
- 'pm10_0_atm':"",
132
- 'pm2.5_aqi_cf_1':"",
133
- 'pm2.5_aqi_atm':"",
134
- 'p_0_3_um':"",
135
- 'p_0_5_um':"",
136
- 'p_1_0_um':"",
137
- 'p_2_5_um':"",
138
- 'p_5_0_um':"",
139
- 'p_10_0_um':"",
140
- 'pm1_0_cf_1_b':"",
141
- 'pm2_5_cf_1_b':"",
142
- 'pm10_0_cf_1_b':"",
143
- 'pm1_0_atm_b':"",
144
- 'pm2_5_atm_b':"",
145
- 'pm10_0_atm_b':"",
146
- 'pm2.5_aqi_cf_1_b':"",
147
- 'pm2.5_aqi_atm_b':"",
148
- 'p_0_3_um_b':"",
149
- 'p_0_5_um_b':"",
150
- 'p_1_0_um_b':"",
151
- 'p_2_5_um_b':"",
152
- 'p_5_0_um_b':"",
153
- 'p_10_0_um_b':"",
154
- 'gas':"",
155
- 'pm_adj': "μg/m3"}
File without changes
File without changes
File without changes