scdata 1.0.0__tar.gz → 1.0.1__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.
- {scdata-1.0.0/scdata.egg-info → scdata-1.0.1}/PKG-INFO +4 -6
- {scdata-1.0.0 → scdata-1.0.1}/README.md +3 -5
- {scdata-1.0.0 → scdata-1.0.1}/scdata/__init__.py +1 -1
- {scdata-1.0.0 → scdata-1.0.1}/scdata/io/device_file.py +1 -1
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/plot_tools.py +37 -16
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_dispersion_uplot.py +1 -1
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_uplot.py +1 -1
- scdata-1.0.1/scdata/test/tools/combine.py +64 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/units.py +1 -1
- {scdata-1.0.0 → scdata-1.0.1/scdata.egg-info}/PKG-INFO +4 -6
- {scdata-1.0.0 → scdata-1.0.1}/setup.py +1 -1
- scdata-1.0.0/scdata/test/tools/combine.py +0 -60
- {scdata-1.0.0 → scdata-1.0.1}/LICENSE +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/MANIFEST.in +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/requirements.txt +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/_config/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/_config/config.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/_config/custom_logger.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/device.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/alphasense.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/baseline.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/formulae.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/geoseries.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/params.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/regression.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/device/process/timeseries.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/io/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/io/device_api.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/io/model.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/models/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/models/models.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/checks/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/checks/checks.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/dispersion/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/dispersion/dispersion.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/export/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/export/templates/sc_template.html +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/export/to_file.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/box_plot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/heatmap_iplot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/heatmap_plot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/maps.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/scatter_dispersion_grid.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/scatter_iplot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/scatter_plot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/target_diagram.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_dendrogram.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_dispersion_grid.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_dispersion_plot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_iplot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_plot.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/plot/ts_scatter.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/test.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/tools/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/tools/history.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/test/tools/prepare.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/__init__.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/cleaning.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/custom_logger.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/date.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/dictmerge.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/find.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/gets.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/interim/example.csv +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/interim/geodata.csv +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/lazy.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/location.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/report.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/stats.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/uploads/example_upload_1.json +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/uploads/example_zenodo_upload.yaml +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/uploads/report.pdf +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/url_check.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/zenodo.py +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/zenodo_templates/README.md +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/zenodo_templates/template_zenodo_dataset.json +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata/tools/zenodo_templates/template_zenodo_publication.json +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata.egg-info/SOURCES.txt +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata.egg-info/dependency_links.txt +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata.egg-info/not-zip-safe +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata.egg-info/requires.txt +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/scdata.egg-info/top_level.txt +0 -0
- {scdata-1.0.0 → scdata-1.0.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: scdata
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Analysis of sensors and time series data
|
|
5
5
|
Home-page: https://github.com/fablabbcn/smartcitizen-data
|
|
6
6
|
Author: oscgonfer
|
|
@@ -46,21 +46,19 @@ Smart Citizen Data
|
|
|
46
46
|
[](https://zenodo.org/badge/latestdoi/97752018)
|
|
47
47
|
[](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks)
|
|
48
48
|
[](https://badge.fury.io/py/scdata)
|
|
49
|
-
[](https://github.com/fablabbcn/smartcitizen-data/actions/workflows/python-multiple-versions.yml)
|
|
50
50
|
|
|
51
51
|
Welcome to **SmartCitizen Data**. This is a data analysis framework for working with sensor data in different ways:
|
|
52
52
|
|
|
53
53
|
- Interacting with several sensors APIs
|
|
54
54
|
- Clean data, export and calculate metrics
|
|
55
55
|
- Model sensor data and calibrate sensors
|
|
56
|
-
- Generate data visualisations - matplotlib, [plotly](https://plotly.com/) or [uplot](https://leeoniya.github.io/uPlot)
|
|
56
|
+
- Generate data visualisations - matplotlib, ~[plotly](https://plotly.com/)~ or [uplot](https://leeoniya.github.io/uPlot)
|
|
57
57
|
- Generate analysis reports in html or pdf and upload them to [Zenodo](http://zenodo.org)
|
|
58
58
|
|
|
59
|
-
A full documentation of the framework is detailed in [the Smart Citizen Docs](https://docs.smartcitizen.me/Data/Data%20Analysis/).
|
|
60
|
-
|
|
61
59
|
## Installation
|
|
62
60
|
|
|
63
|
-
You can check it out in the [](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks) before installing if you want. Works with `Python 3.*` (tested
|
|
61
|
+
You can check it out in the [](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks) before installing if you want. Works with `Python 3.*` (tested between 3.9 and 3.11).
|
|
64
62
|
|
|
65
63
|
You can just run:
|
|
66
64
|
|
|
@@ -4,21 +4,19 @@ Smart Citizen Data
|
|
|
4
4
|
[](https://zenodo.org/badge/latestdoi/97752018)
|
|
5
5
|
[](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks)
|
|
6
6
|
[](https://badge.fury.io/py/scdata)
|
|
7
|
-
[](https://github.com/fablabbcn/smartcitizen-data/actions/workflows/python-multiple-versions.yml)
|
|
8
8
|
|
|
9
9
|
Welcome to **SmartCitizen Data**. This is a data analysis framework for working with sensor data in different ways:
|
|
10
10
|
|
|
11
11
|
- Interacting with several sensors APIs
|
|
12
12
|
- Clean data, export and calculate metrics
|
|
13
13
|
- Model sensor data and calibrate sensors
|
|
14
|
-
- Generate data visualisations - matplotlib, [plotly](https://plotly.com/) or [uplot](https://leeoniya.github.io/uPlot)
|
|
14
|
+
- Generate data visualisations - matplotlib, ~[plotly](https://plotly.com/)~ or [uplot](https://leeoniya.github.io/uPlot)
|
|
15
15
|
- Generate analysis reports in html or pdf and upload them to [Zenodo](http://zenodo.org)
|
|
16
16
|
|
|
17
|
-
A full documentation of the framework is detailed in [the Smart Citizen Docs](https://docs.smartcitizen.me/Data/Data%20Analysis/).
|
|
18
|
-
|
|
19
17
|
## Installation
|
|
20
18
|
|
|
21
|
-
You can check it out in the [](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks) before installing if you want. Works with `Python 3.*` (tested
|
|
19
|
+
You can check it out in the [](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks) before installing if you want. Works with `Python 3.*` (tested between 3.9 and 3.11).
|
|
22
20
|
|
|
23
21
|
You can just run:
|
|
24
22
|
|
|
@@ -128,7 +128,7 @@ def read_csv_file(path, timezone, frequency=None, clean_na=None, index_name='',
|
|
|
128
128
|
|
|
129
129
|
# Read pandas dataframe
|
|
130
130
|
|
|
131
|
-
df = read_csv(path,
|
|
131
|
+
df = read_csv(path, skiprows=skiprows, sep=sep,
|
|
132
132
|
encoding=encoding, encoding_errors='ignore')
|
|
133
133
|
|
|
134
134
|
flag_found = False
|
|
@@ -93,14 +93,15 @@ def prepare_data(test, traces, options):
|
|
|
93
93
|
logger.warning(f'The trace {traces[trace]} was not placed in any subplot. Assuming subplot #1')
|
|
94
94
|
traces[trace]['subplot'] = 1
|
|
95
95
|
|
|
96
|
+
|
|
96
97
|
ndevs = traces[trace]['devices']
|
|
97
98
|
nchans = traces[trace]['channel']
|
|
98
99
|
|
|
99
100
|
# Make them lists always
|
|
100
101
|
if ndevs == 'all': devices = [device.id for device in test.devices]
|
|
102
|
+
## TODO Make it regex compatible!
|
|
101
103
|
elif type(ndevs) == str or type(ndevs) == int: devices = [ndevs]
|
|
102
104
|
else: devices = ndevs
|
|
103
|
-
print (devices)
|
|
104
105
|
|
|
105
106
|
for ndev in devices:
|
|
106
107
|
|
|
@@ -158,8 +159,23 @@ def prepare_data(test, traces, options):
|
|
|
158
159
|
# Remove column for filtering from dfdev
|
|
159
160
|
dfdev.drop(columns=[col_name], inplace = True)
|
|
160
161
|
|
|
162
|
+
# Resample it
|
|
163
|
+
if options['frequency'] is not None:
|
|
164
|
+
logger.info(f"Resampling at {options['frequency']}")
|
|
165
|
+
|
|
166
|
+
if 'resample' in options:
|
|
167
|
+
|
|
168
|
+
if options['resample'] == 'max': dfdev = dfdev.resample(options['frequency']).max()
|
|
169
|
+
if options['resample'] == 'min': dfdev = dfdev.resample(options['frequency']).min()
|
|
170
|
+
if options['resample'] == 'mean': dfdev = dfdev.resample(options['frequency']).mean()
|
|
171
|
+
|
|
172
|
+
else:
|
|
173
|
+
dfdev = dfdev.resample(options['frequency']).mean()
|
|
174
|
+
|
|
161
175
|
# Combine it in the df
|
|
162
176
|
df = df.combine_first(dfdev)
|
|
177
|
+
|
|
178
|
+
## TODO Is this working?
|
|
163
179
|
# Add average or other extras
|
|
164
180
|
# TODO Check this to simplify
|
|
165
181
|
# https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.core.resample.Resampler.aggregate.html
|
|
@@ -168,15 +184,19 @@ def prepare_data(test, traces, options):
|
|
|
168
184
|
|
|
169
185
|
nextras = list()
|
|
170
186
|
for device in traces[trace]['devices']:
|
|
171
|
-
|
|
172
|
-
|
|
187
|
+
if type(traces[trace]['channel']) == 'list':
|
|
188
|
+
for channel in traces[trace]['channel']:
|
|
189
|
+
nextras.append(f'{channel}_{device}')
|
|
190
|
+
else:
|
|
191
|
+
nextras.append(f"{traces[trace]['channel']}_{device}")
|
|
173
192
|
|
|
174
193
|
if extra == 'bands':
|
|
175
|
-
ubn = channel + f"-{trace}-
|
|
176
|
-
lbn = channel + f"-{trace}-
|
|
194
|
+
ubn = channel + f"-{trace}-UPPER-BAND"
|
|
195
|
+
lbn = channel + f"-{trace}-LOWER-BAND"
|
|
177
196
|
|
|
178
|
-
|
|
179
|
-
df[
|
|
197
|
+
logger.info('Using 3sig bands')
|
|
198
|
+
df[ubn] = df.loc[:, nextras].mean(axis = 1) + 3*df.loc[:, nextras].std(axis = 1)
|
|
199
|
+
df[lbn] = df.loc[:, nextras].mean(axis = 1) - 3*df.loc[:, nextras].std(axis = 1)
|
|
180
200
|
|
|
181
201
|
subplots[traces[trace]['subplot']-1].append(ubn)
|
|
182
202
|
subplots[traces[trace]['subplot']-1].append(lbn)
|
|
@@ -208,18 +228,19 @@ def prepare_data(test, traces, options):
|
|
|
208
228
|
if df.empty:
|
|
209
229
|
logger.error('Empty dataframe for plot')
|
|
210
230
|
return None, None
|
|
211
|
-
# Resample it
|
|
212
|
-
if options['frequency'] is not None:
|
|
213
|
-
logger.info(f"Resampling at {options['frequency']}")
|
|
214
231
|
|
|
215
|
-
|
|
232
|
+
# # Resample it
|
|
233
|
+
# if options['frequency'] is not None:
|
|
234
|
+
# logger.info(f"Resampling at {options['frequency']}")
|
|
216
235
|
|
|
217
|
-
|
|
218
|
-
if options['resample'] == 'min': df = df.resample(options['frequency']).min()
|
|
219
|
-
if options['resample'] == 'mean': df = df.resample(options['frequency']).mean()
|
|
236
|
+
# if 'resample' in options:
|
|
220
237
|
|
|
221
|
-
|
|
222
|
-
|
|
238
|
+
# if options['resample'] == 'max': df = df.resample(options['frequency']).max()
|
|
239
|
+
# if options['resample'] == 'min': df = df.resample(options['frequency']).min()
|
|
240
|
+
# if options['resample'] == 'mean': df = df.resample(options['frequency']).mean()
|
|
241
|
+
|
|
242
|
+
# else:
|
|
243
|
+
# df = df.resample(options['frequency']).mean()
|
|
223
244
|
|
|
224
245
|
# Clean na
|
|
225
246
|
if options['clean_na'] is not None:
|
|
@@ -149,7 +149,7 @@ def ts_dispersion_uplot(self, **kwargs):
|
|
|
149
149
|
|
|
150
150
|
if formatting['join_sbplot']: n_subplots = 1
|
|
151
151
|
else: n_subplots = 2
|
|
152
|
-
udf.index = udf.index.astype(
|
|
152
|
+
udf.index = udf.index.astype('int64')/10**9
|
|
153
153
|
|
|
154
154
|
# Compose subplots lists
|
|
155
155
|
for device in self.devices:
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from pandas import DataFrame
|
|
2
|
+
from scdata.tools.custom_logger import logger
|
|
3
|
+
from scdata.device import Device
|
|
4
|
+
|
|
5
|
+
def combine(self, devices = None, channels = None, resample = True, frequency = '1Min'):
|
|
6
|
+
"""
|
|
7
|
+
Combines devices from a test into a new dataframe, following the
|
|
8
|
+
naming as follows: DEVICE-NAME_READING-NAME
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
devices: list or None
|
|
12
|
+
None
|
|
13
|
+
If None, includes all the devices in self.devices
|
|
14
|
+
channels: list or None
|
|
15
|
+
None
|
|
16
|
+
If None, includes all the readings in self.readings
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
Dataframe if successful or False otherwise
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
dfc = DataFrame()
|
|
23
|
+
if not self.loaded:
|
|
24
|
+
logger.error('Cannot combine data if test is not loaded. Maybe test.load() first?')
|
|
25
|
+
|
|
26
|
+
if devices is None:
|
|
27
|
+
dl = [device.id for device in self.devices]
|
|
28
|
+
else:
|
|
29
|
+
# Only requested AND available
|
|
30
|
+
dl = list(set(devices).intersection([device.id for device in self.devices]))
|
|
31
|
+
if len(dl) != len(devices):
|
|
32
|
+
logger.warning('Requested devices are not all present in devices')
|
|
33
|
+
logger.info(f'Discarding {set(devices).difference([device.id for device in self.devices])}')
|
|
34
|
+
|
|
35
|
+
for device in dl:
|
|
36
|
+
new_names = list()
|
|
37
|
+
|
|
38
|
+
if channels is None:
|
|
39
|
+
channel_list = list(self.get_device(device).data.columns)
|
|
40
|
+
else:
|
|
41
|
+
# Only pick the ones that are actually present
|
|
42
|
+
channel_list = list(set(channels).intersection(list(self.get_device(device).data.columns)))
|
|
43
|
+
|
|
44
|
+
if any([channel not in channel_list for channel in channels]):
|
|
45
|
+
logger.warning(f'Requested channels are not all present in readings for device {device}')
|
|
46
|
+
logger.warning(f'Discarding {list(set(channels).difference(list(self.get_device(device).data.columns)))}')
|
|
47
|
+
|
|
48
|
+
rename = dict()
|
|
49
|
+
|
|
50
|
+
for channel in channel_list:
|
|
51
|
+
rename[channel] = f'{channel}_{self.get_device(device).id}'
|
|
52
|
+
|
|
53
|
+
df = self.get_device(device).data[channel_list].copy()
|
|
54
|
+
df.rename(columns = rename, inplace = True)
|
|
55
|
+
if resample:
|
|
56
|
+
df = df.resample(frequency).mean()
|
|
57
|
+
dfc = dfc.combine_first(df)
|
|
58
|
+
|
|
59
|
+
if dfc.empty:
|
|
60
|
+
logger.error('Error ocurred while combining data. Review data')
|
|
61
|
+
return False
|
|
62
|
+
else:
|
|
63
|
+
logger.info('Data combined successfully')
|
|
64
|
+
return dfc
|
|
@@ -92,7 +92,7 @@ def get_units_convf(sensor, from_units):
|
|
|
92
92
|
else: molecular_weight = 1
|
|
93
93
|
|
|
94
94
|
# Check if channel is in look-up table
|
|
95
|
-
if channel_lut[channel] != from_units and from_units != "":
|
|
95
|
+
if channel_lut[channel] != from_units and from_units != "" and from_units is not None:
|
|
96
96
|
logger.info(f"Converting units for {sensor}. From {from_units} to {channel_lut[channel]}")
|
|
97
97
|
for unit in unit_convertion_lut:
|
|
98
98
|
# Get units
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: scdata
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Analysis of sensors and time series data
|
|
5
5
|
Home-page: https://github.com/fablabbcn/smartcitizen-data
|
|
6
6
|
Author: oscgonfer
|
|
@@ -46,21 +46,19 @@ Smart Citizen Data
|
|
|
46
46
|
[](https://zenodo.org/badge/latestdoi/97752018)
|
|
47
47
|
[](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks)
|
|
48
48
|
[](https://badge.fury.io/py/scdata)
|
|
49
|
-
[](https://github.com/fablabbcn/smartcitizen-data/actions/workflows/python-multiple-versions.yml)
|
|
50
50
|
|
|
51
51
|
Welcome to **SmartCitizen Data**. This is a data analysis framework for working with sensor data in different ways:
|
|
52
52
|
|
|
53
53
|
- Interacting with several sensors APIs
|
|
54
54
|
- Clean data, export and calculate metrics
|
|
55
55
|
- Model sensor data and calibrate sensors
|
|
56
|
-
- Generate data visualisations - matplotlib, [plotly](https://plotly.com/) or [uplot](https://leeoniya.github.io/uPlot)
|
|
56
|
+
- Generate data visualisations - matplotlib, ~[plotly](https://plotly.com/)~ or [uplot](https://leeoniya.github.io/uPlot)
|
|
57
57
|
- Generate analysis reports in html or pdf and upload them to [Zenodo](http://zenodo.org)
|
|
58
58
|
|
|
59
|
-
A full documentation of the framework is detailed in [the Smart Citizen Docs](https://docs.smartcitizen.me/Data/Data%20Analysis/).
|
|
60
|
-
|
|
61
59
|
## Installation
|
|
62
60
|
|
|
63
|
-
You can check it out in the [](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks) before installing if you want. Works with `Python 3.*` (tested
|
|
61
|
+
You can check it out in the [](https://mybinder.org/v2/gh/fablabbcn/smartcitizen-data-framework/master?filepath=%2Fexamples%2Fnotebooks) before installing if you want. Works with `Python 3.*` (tested between 3.9 and 3.11).
|
|
64
62
|
|
|
65
63
|
You can just run:
|
|
66
64
|
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
from pandas import DataFrame
|
|
2
|
-
from scdata.tools.custom_logger import logger
|
|
3
|
-
from scdata.device import Device
|
|
4
|
-
|
|
5
|
-
def combine(self, devices = None, readings = None):
|
|
6
|
-
"""
|
|
7
|
-
Combines devices from a test into a new dataframe, following the
|
|
8
|
-
naming as follows: DEVICE-NAME_READING-NAME
|
|
9
|
-
Parameters
|
|
10
|
-
----------
|
|
11
|
-
devices: list or None
|
|
12
|
-
None
|
|
13
|
-
If None, includes all the devices in self.devices
|
|
14
|
-
readings: list or None
|
|
15
|
-
None
|
|
16
|
-
If None, includes all the readings in self.readings
|
|
17
|
-
Returns
|
|
18
|
-
-------
|
|
19
|
-
Dataframe if successful or False otherwise
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
dfc = DataFrame()
|
|
23
|
-
|
|
24
|
-
if devices is None:
|
|
25
|
-
dl = list(self.devices.keys())
|
|
26
|
-
else:
|
|
27
|
-
# Only pick the ones that are actually present
|
|
28
|
-
dl = list(set(devices).intersection(list(self.devices.keys())))
|
|
29
|
-
if len(dl) != len(devices):
|
|
30
|
-
logger.warning('Requested devices are not all present in devices')
|
|
31
|
-
logger.info(f'Discarding {set(devices).difference(list(self.devices.keys()))}')
|
|
32
|
-
|
|
33
|
-
for device in dl:
|
|
34
|
-
new_names = list()
|
|
35
|
-
|
|
36
|
-
if readings is None:
|
|
37
|
-
rl = list(self.devices[device].readings.columns)
|
|
38
|
-
else:
|
|
39
|
-
# Only pick the ones that are actually present
|
|
40
|
-
rl = list(set(readings).intersection(list(self.devices[device].readings.columns)))
|
|
41
|
-
|
|
42
|
-
if any([reading not in rl for reading in readings]):
|
|
43
|
-
logger.warning(f'Requested readings are not all present in readings for device {device}')
|
|
44
|
-
logger.warning(f'Discarding {list(set(readings).difference(list(self.devices[device].readings.columns)))}')
|
|
45
|
-
|
|
46
|
-
rename = dict()
|
|
47
|
-
|
|
48
|
-
for reading in rl:
|
|
49
|
-
rename[reading] = reading + '_' + self.devices[device].id
|
|
50
|
-
|
|
51
|
-
df = self.devices[device].readings[rl].copy()
|
|
52
|
-
df.rename(columns = rename, inplace = True)
|
|
53
|
-
dfc = dfc.combine_first(df)
|
|
54
|
-
|
|
55
|
-
if dfc.empty:
|
|
56
|
-
logger.error('Error ocurred while combining data. Review data')
|
|
57
|
-
return False
|
|
58
|
-
else:
|
|
59
|
-
logger.info('Data combined successfully')
|
|
60
|
-
return dfc
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scdata-1.0.0 → scdata-1.0.1}/scdata/tools/zenodo_templates/template_zenodo_publication.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|