/**
* Global Sensor Networks (GSN) Source Code
* Copyright (c) 2006-2014, Ecole Polytechnique Federale de Lausanne (EPFL)
* <p/>
* This file is part of GSN.
* <p/>
* GSN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* <p/>
* GSN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p/>
* You should have received a copy of the GNU General Public License
* along with GSN. If not, see <http://www.gnu.org/licenses/>.
* <p/>
* File: gsn-tiny/src/tinygsn/model/vsensor/BridgeVirtualSensor.java
*
* @author Do Ngoc Hoan
*/
package tinygsn.model.vsensor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import android.os.Environment;
import org.epfl.locationprivacy.util.Utils;
import tinygsn.beans.DataField;
import tinygsn.beans.DataTypes;
import tinygsn.beans.StaticData;
import tinygsn.beans.StreamElement;
import tinygsn.model.utils.ParameterType;
import tinygsn.model.utils.Parameter;
import weka.classifiers.Classifier;
import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.SerializationHelper;
import static android.os.Debug.startMethodTracing;
import static android.os.Debug.stopMethodTracing;
/*
y_max- <= -2.444118: 5 (31.0/1.0)
y_max- > -2.444118
| z_moment-moment-6 <= 1571.756023
| | coefficient_variation- <= 0.283575
| | | z_percentile-percentile-25 <= 0.68651
| | | | z_mean- <= -5.048177
| | | | | std- <= 0.293853: 2 (2.0)
| | | | | std- > 0.293853: 0 (2.0/1.0)
| | | | z_mean- > -5.048177
| | | | | mode- <= 7.17009
| | | | | | y_mean- <= -2.062379: 1 (9.0/1.0)
| | | | | | y_mean- > -2.062379: 4 (6.0/1.0)
| | | | | mode- > 7.17009: 1 (31.0/1.0)
| | | z_percentile-percentile-25 > 0.68651
| | | | std- <= 0.613081: 1 (2.0/1.0)
| | | | std- > 0.613081: 3 (32.0)
| | coefficient_variation- > 0.283575
| | | z_min- <= -6.830595
| | | | y_mean- <= -2.287655: 0 (17.0)
| | | | y_mean- > -2.287655: 4 (4.0)
| | | z_min- > -6.830595: 4 (12.0/1.0)
| z_moment-moment-6 > 1571.756023: 2 (26.0)
*/
public class ActivityVirtualSensor extends AbstractVirtualSensor {
private static final long serialVersionUID = 772132288546137586L;
private Classifier cls_act;
private String fileName = "activity-julien-norm.model";
private DataField[] outputStructure = new DataField[]{new DataField("activity", DataTypes.DOUBLE)};
private String LOGTAG = "ActivityVirtualSensor";
@Override
public boolean initialize() {
try {
cls_act = (Classifier) SerializationHelper.read(Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/Android/data/tinygsn/" + fileName);
} catch (Exception e) {
return false;
}
return true;
}
@Override
public ArrayList<Parameter> getParameters() {
ArrayList<Parameter> list = new ArrayList<>();
list.add(new Parameter("model_file", ParameterType.EDITBOX));
return list;
}
@Override
protected void initParameter(String key, String value) {
if (key.endsWith("model_file")) {
fileName = value;
}
}
@Override
public void dispose() {
}
@Override
public void dataAvailable(String inputStreamName, StreamElement streamElement) {
}
@Override
public void dataAvailable(String inputStreamName, ArrayList<StreamElement> streamElements) {
if ((boolean) Utils.getBuildConfigValue(StaticData.globalContext, "PERFORMANCE")) {
startMethodTracing("Android/data/tinygsn.gui.android/" + LOGTAG + "_" + inputStreamName + "_" + System.currentTimeMillis());
}
log("dataAvailable_" + LOGTAG + "_" + inputStreamName, "===========================================");
log("dataAvailable_" + LOGTAG + "_" + inputStreamName, "Starting to process data in dataAvailable");
long startLogTime = System.currentTimeMillis();
if (streamElements.size() < 3) return; //too small to compute
double[] x = new double[streamElements.size()];
double[] y = new double[x.length];
double[] z = new double[x.length];
double[] norm = new double[x.length];
double mean_x = 0;
double mean_y = 0;
double mean_z = 0;
double mean_norm = 0;
double std_x = 0;
double std_y = 0;
double std_z = 0;
double std_norm = 0;
double min_x = Double.MAX_VALUE;
double min_y = Double.MAX_VALUE;
double min_z = Double.MAX_VALUE;
double min_norm = Double.MAX_VALUE;
double max_x = Double.MIN_VALUE;
double max_y = Double.MIN_VALUE;
double max_z = Double.MIN_VALUE;
double max_norm = Double.MIN_VALUE;
for (int i = 0; i < x.length; i++) {
Serializable[] d = streamElements.get(i).getData();
x[i] = (Double) d[0];
y[i] = (Double) d[1];
z[i] = (Double) d[2];
norm[i] = Math.sqrt(x[i] * x[i] + y[i] * y[i] + z[i] * z[i]);
mean_x += x[i];
mean_y += y[i];
mean_z += z[i];
mean_norm += norm[i];
std_x += x[i] * x[i];
std_y += y[i] * y[i];
std_z += z[i] * z[i];
std_norm += norm[i] * norm[i];
min_x = x[i] < min_x ? x[i] : min_x;
min_y = y[i] < min_y ? y[i] : min_y;
min_z = z[i] < min_z ? z[i] : min_z;
min_norm = norm[i] < min_norm ? norm[i] : min_norm;
max_x = x[i] < max_x ? x[i] : max_x;
max_y = y[i] < max_y ? y[i] : max_y;
max_z = z[i] < max_z ? z[i] : max_z;
max_norm = norm[i] < max_norm ? norm[i] : max_norm;
}
mean_x /= x.length;
mean_y /= y.length;
mean_z /= z.length;
mean_norm /= norm.length;
std_x = Math.sqrt(std_x / x.length - mean_x * mean_x);
std_y = Math.sqrt(std_y / y.length - mean_y * mean_y);
std_z = Math.sqrt(std_z / z.length - mean_z * mean_z);
std_norm = Math.sqrt(std_norm / norm.length - mean_norm * mean_norm);
double range_x = max_x - min_x;
double range_y = max_y - min_y;
double range_z = max_z - min_z;
double range_norm = max_norm - min_norm;
double cv_x = std_x / mean_x;
double cv_y = std_y / mean_y;
double cv_z = std_z / mean_z;
double cv_norm = std_norm / mean_norm;
double kurt_x = 0;
double kurt_y = 0;
double kurt_z = 0;
double kurt_norm = 0;
for (int i = 0; i < x.length; i++) {
kurt_x += Math.pow(x[i] - mean_x, 4);
kurt_y += Math.pow(y[i] - mean_y, 4);
kurt_z += Math.pow(z[i] - mean_z, 4);
kurt_norm += Math.pow(norm[i] - mean_norm, 4);
}
kurt_x = (kurt_x / x.length) / Math.pow(std_x, 4);
kurt_y = (kurt_y / y.length) / Math.pow(std_y, 4);
kurt_z = (kurt_z / z.length) / Math.pow(std_z, 4);
kurt_norm = (kurt_norm / norm.length) / Math.pow(std_norm, 4);
Arrays.sort(x);
Arrays.sort(y);
Arrays.sort(z);
Arrays.sort(norm);
/* double median_x = x.length % 2 == 1 ? x[(x.length - 1)/2] : x[(x.length)/2] + x[(x.length)/2 - 1] / 2.0;
double median_y = y.length % 2 == 1 ? y[(y.length - 1)/2] : y[(y.length)/2] + y[(y.length)/2 - 1] / 2.0;
double median_z = z.length % 2 == 1 ? z[(z.length - 1)/2] : z[(z.length)/2] + z[(z.length)/2 - 1] / 2.0;
*/
double percent25_x = x[(int) Math.round(x.length / 4.0)];
double percent25_y = y[(int) Math.round(y.length / 4.0)];
double percent25_z = z[(int) Math.round(z.length / 4.0)];
double percent25_norm = norm[(int) Math.round(norm.length / 4.0)];
double percent75_x = x[(int) Math.round(3.0 * x.length / 4)];
double percent75_y = y[(int) Math.round(3.0 * y.length / 4)];
double percent75_z = z[(int) Math.round(3.0 * z.length / 4)];
double percent75_norm = norm[(int) Math.round(3.0 * norm.length / 4)];
/*double[] vector = new double[]{mean_x,std_x,min_x,max_x,range_x,cv_x,kurt_x,percent25_x,percent75_x,
mean_y,std_y,min_y,max_y,range_y,cv_y,kurt_y,percent25_y,percent75_y,
mean_z,std_z,min_z,max_z,range_z,cv_z,kurt_z,percent25_z,percent75_z};
*/
FastVector v = new FastVector();
FastVector classVal = new FastVector();
classVal.addElement("0");
classVal.addElement("1");
classVal.addElement("2");
classVal.addElement("3");
classVal.addElement("4");
classVal.addElement("5");
Attribute label = new Attribute("label", classVal);
v.addElement(label);
Attribute mean = new Attribute("julien-norm-mean-");
v.addElement(mean);
Attribute std = new Attribute("julien-norm-std-");
v.addElement(std);
Attribute min = new Attribute("julien-norm-min-");
v.addElement(min);
Attribute max = new Attribute("julien-norm-max-");
v.addElement(max);
Attribute range = new Attribute("julien-norm-range-");
v.addElement(range);
Attribute cv = new Attribute("julien-norm-coefficient_variation-");
v.addElement(cv);
Attribute kurt = new Attribute("julien-norm-kurtosis-");
v.addElement(kurt);
Attribute p25 = new Attribute("julien-norm-percentile-percentile-25");
v.addElement(p25);
Attribute p75 = new Attribute("julien-norm-percentile-percentile-75");
v.addElement(p75);
Instances dataset = new Instances("Test", v, 0);
Instance i = new Instance(dataset.numAttributes());
i.setValue(mean, mean_norm);
i.setValue(std, std_norm);
i.setValue(min, min_norm);
i.setValue(max, max_norm);
i.setValue(range, range_norm);
i.setValue(cv, cv_norm);
i.setValue(kurt, kurt_norm);
i.setValue(p25, percent25_norm);
i.setValue(p75, percent75_norm);
dataset.add(i);
dataset.setClassIndex(0);
double classe = 0.0;
try {
classe = cls_act.classifyInstance(dataset.instance(0));
} catch (Exception e) {
return;
}
long endLogTime = System.currentTimeMillis();
log("dataAvailable_" + LOGTAG + "_" + inputStreamName, "Total Time to process data in dataAvailable() (without dataProduced()) : " + (endLogTime - startLogTime) + " ms.");
dataProduced(new StreamElement(outputStructure, new Serializable[]{classe}, streamElements.get(streamElements.size() - 1).getTimeStamp()));
if ((boolean) Utils.getBuildConfigValue(StaticData.globalContext, "PERFORMANCE") || (boolean) Utils.getBuildConfigValue(StaticData.globalContext, "GPSPERFORMANCE")) {
stopMethodTracing();
}
}
@Override
public DataField[] getOutputStructure(DataField[] in) {
return outputStructure;
}
}