Skip to content
This repository was archived by the owner on May 25, 2024. It is now read-only.

Commit f7c57c9

Browse files
committed
add port_wifi_indoor_positioning
1 parent 06e75d4 commit f7c57c9

File tree

7 files changed

+130
-4
lines changed

7 files changed

+130
-4
lines changed

MANIFEST

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ micromlgen/decisiontree.py
66
micromlgen/gaussiannb.py
77
micromlgen/logisticregression.py
88
micromlgen/micromlgen.py
9-
micromlgen/patches.py
109
micromlgen/pca.py
1110
micromlgen/platforms.py
1211
micromlgen/randomforest.py
1312
micromlgen/rvm.py
1413
micromlgen/sefr.py
1514
micromlgen/svm.py
1615
micromlgen/utils.py
16+
micromlgen/templates/_skeleton.jinja
1717
micromlgen/templates/classmap.jinja
1818
micromlgen/templates/dot.jinja
1919
micromlgen/templates/testset.jinja

micromlgen/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
import micromlgen.platforms as platforms
22
from micromlgen.micromlgen import port
33
from micromlgen.utils import port_testset, port_trainset
4+
from micromlgen.wifiindoorpositioning import port_wifi_indoor_positioning

micromlgen/micromlgen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ def port(
3333
return port_gaussiannb(**locals())
3434
elif is_pca(clf):
3535
return port_pca(**locals())
36-
raise TypeError('clf MUST be one of SVC, LinearSVC, OneClassSVC, RVC, DecisionTree, RandomForest, LogisticRegression, GaussianNB, SEFR, PCA')
36+
raise TypeError('clf MUST be one of %s' % ', '.join(platforms.ALLOWED_CLASSIFIERS))

micromlgen/platforms.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,17 @@
33
ALL = [
44
ARDUINO,
55
ATTINY
6+
]
7+
8+
ALLOWED_CLASSIFIERS = [
9+
'SVC',
10+
'LinearSVC',
11+
'OneClassSVC',
12+
'RVC',
13+
'SEFR',
14+
'DecisionTree',
15+
'RandomForest',
16+
'GaussianNB',
17+
'LogisticRegression',
18+
'PCA'
619
]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
namespace Eloquent {
4+
namespace Projects {
5+
class WifiIndoorPositioning {
6+
public:
7+
/**
8+
* Get feature vector
9+
*/
10+
float* getFeatures() {
11+
static float features[{{ X[0]|length }}] = {0};
12+
uint8_t numNetworks = WiFi.scanNetworks();
13+
14+
for (uint8_t i = 0; i < {{ X[0]|length }}; i++) {
15+
features[i] = 0;
16+
}
17+
18+
for (uint8_t i = 0; i < numNetworks; i++) {
19+
int featureIdx = ssidToFeatureIdx(WiFi.SSID(i));
20+
21+
if (featureIdx >= 0) {
22+
features[featureIdx] = WiFi.RSSI(i);
23+
}
24+
}
25+
26+
return features;
27+
}
28+
29+
protected:
30+
/**
31+
* Convert SSID to featureIdx
32+
*/
33+
int ssidToFeatureIdx(String ssid) {
34+
{% for network, idx in networkmap.items() %}
35+
if (ssid.equals("{{ network }}"))
36+
return {{ idx }};
37+
{% endfor %}
38+
39+
return -1;
40+
}
41+
};
42+
}
43+
}

micromlgen/wifiindoorpositioning.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import json
2+
import numpy as np
3+
from micromlgen.utils import jinja
4+
5+
6+
def parse_samples(samples, parser):
7+
for line in samples.split('\n'):
8+
if '{' in line and '}' in line:
9+
data = json.loads(line)
10+
info = {k: v for k, v in data.items() if k.startswith('__')}
11+
networks = {k: v for k, v in data.items() if not k.startswith('__')}
12+
yield parser(info, networks)
13+
14+
15+
def get_classmap(samples):
16+
"""Get {location: classIdx} mapping"""
17+
18+
def parser(info, networks):
19+
return info['__location']
20+
21+
locations = list(parse_samples(samples, parser))
22+
return {location: i for i, location in enumerate(sorted(set(locations)))}
23+
24+
25+
def get_networkmap(samples):
26+
"""Get {network: featureIdx} mapping"""
27+
28+
def parser(info, networks):
29+
return networks.keys()
30+
31+
networks = [list(x) for x in parse_samples(samples, parser)]
32+
networks = [network for sub in networks for network in sub]
33+
return {network: i for i, network in enumerate(sorted(set(networks)))}
34+
35+
36+
def get_x(samples, networkmap):
37+
"""Get features array"""
38+
39+
def parser(info, networks):
40+
x = [0] * len(networkmap)
41+
for network, rssi in networks.items():
42+
x[networkmap.get(network)] = rssi
43+
return x
44+
45+
return np.asarray(list(parse_samples(samples, parser)), dtype=np.int8)
46+
47+
48+
def get_y(samples, classmap):
49+
"""Get locationIdx array"""
50+
51+
def parser(info, networks):
52+
location = info['__location']
53+
assert location in classmap, 'Unknown location %s' % location
54+
return classmap[location]
55+
56+
return np.asarray(list(parse_samples(samples, parser)))
57+
58+
59+
def port_wifi_indoor_positioning(samples):
60+
classmap = get_classmap(samples)
61+
networkmap = get_networkmap(samples)
62+
X = get_x(samples, networkmap)
63+
y = get_y(samples, classmap)
64+
# classmap is flipped wrt the format `port` expects: flip it
65+
classmap = {v: k for k, v in classmap.items()}
66+
return X, y, classmap, jinja('wifiindoorpositioning/wifiindoorpositioning.jinja', {
67+
'X': X,
68+
'networkmap': networkmap
69+
})

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
setup(
88
name = 'micromlgen',
99
packages = ['micromlgen'],
10-
version = '1.1.7',
10+
version = '1.1.8',
1111
license='MIT',
1212
description = 'Generate C code for microcontrollers from Python\'s sklearn classifiers',
1313
author = 'Simone Salerno',
1414
author_email = 'eloquentarduino@gmail.com',
1515
url = 'https://github.com/eloquentarduino/micromlgen',
16-
download_url = 'https://github.com/eloquentarduino/micromlgen/archive/v_117.tar.gz',
16+
download_url = 'https://github.com/eloquentarduino/micromlgen/archive/v_118.tar.gz',
1717
keywords = [
1818
'ML',
1919
'microcontrollers',

0 commit comments

Comments
 (0)