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.
- {apmtools-0.2.14 → apmtools-0.2.16}/PKG-INFO +1 -1
- {apmtools-0.2.14 → apmtools-0.2.16}/pyproject.toml +1 -1
- {apmtools-0.2.14 → apmtools-0.2.16}/src/apmtools/shiny/summary.py +128 -26
- apmtools-0.2.16/src/apmtools/units.py +386 -0
- apmtools-0.2.14/src/apmtools/units.py +0 -155
- {apmtools-0.2.14 → apmtools-0.2.16}/.gitignore +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/LICENSE +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/README.md +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/src/apmtools/__init__.py +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/src/apmtools/classes.py +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/src/apmtools/data_processing.py +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/src/apmtools/functions.py +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/src/apmtools/legacy.py +0 -0
- {apmtools-0.2.14 → apmtools-0.2.16}/src/apmtools/shiny/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: apmtools
|
|
3
|
-
Version: 0.2.
|
|
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>
|
|
@@ -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
|
-
|
|
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 =
|
|
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.
|
|
285
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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
|
-
|
|
521
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|