summaryrefslogtreecommitdiffstats
path: root/DataStructure/SingleBTS.java
diff options
context:
space:
mode:
Diffstat (limited to 'DataStructure/SingleBTS.java')
-rw-r--r--DataStructure/SingleBTS.java775
1 files changed, 775 insertions, 0 deletions
diff --git a/DataStructure/SingleBTS.java b/DataStructure/SingleBTS.java
new file mode 100644
index 0000000..5d7be6a
--- /dev/null
+++ b/DataStructure/SingleBTS.java
@@ -0,0 +1,775 @@
+package DataStructure;
+
+import java.io.Serializable;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+
+public class SingleBTS implements Comparable<SingleBTS>, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ public int ARFCN; // BTS-Frequency
+
+ public String name; // Name of BTS
+ public Date time; // used to distinguish usedBTS;
+ public LinkedList<Boolean> interpolated = new LinkedList<Boolean>();
+ // Is this BTS interpolated or measured?
+ public boolean fullBTS; // Is this a fully Measured BTS? Does it have UL, TA
+ // and so on...
+ public int TA; // Timing-Advance
+ public int BS_POWER; // BaseSation Power
+ public int MS_TO; // MS_TO
+ public int MS_PWR; // L1_MS_PWR
+ // public GPScoordinate coord; // where was the BTS found?
+ private ArrayList<Double> RXul = new ArrayList<Double>(); // Strength
+ // Up-link
+ private ArrayList<Double> RXdl = new ArrayList<Double>(); // Strength
+ // Down-Link
+ public int reason; // SMS, call, LocationUpdate...
+
+ public double distance; // Distance to BTS in km
+
+ public GPScoordinate coordinate;
+ private double varDL; // Stores variance if this SingleBTS is
+ // interpolated
+ public double mode; // maximum probability density in dBm
+
+ // public double ulQ = -1;
+ public ArrayList<Double> dlQsub = new ArrayList<Double>();
+ // public ArrayList<Double> dlQfull = new ArrayList<Double>();
+ public ArrayList<Double> ulQsub = new ArrayList<Double>();
+
+ // public ArrayList<Double> ulQfull = new ArrayList<Double>();
+
+ // Constructor
+ public SingleBTS(int ARFCN, double RXul, double RXdl, boolean interpolated,
+ Date time, String name) {
+ this.ARFCN = ARFCN;
+ if (RXul != 0)
+ this.addUl(RXul);
+ this.addDl(RXdl);
+ this.interpolated.add(interpolated);
+ // this.interpolated = interpolated;
+ this.time = time;
+ this.name = name;
+ }
+
+ public SingleBTS(int ARFCN, double RXul, double RXdl, boolean interpolated,
+ Date time, String name, double varDL) {
+ this(ARFCN, RXul, RXdl, interpolated, time, name);
+ this.varDL = varDL;
+
+ }
+
+ /*
+ * // Constructor without boolean without time public SingleBTS(int ARFCN,
+ * int RXul, int RXdl, int TA) { this(ARFCN, RXul, RXdl, TA, false, null); }
+ *
+ * // Constructor with date public SingleBTS(int ARFCN, int RXul, int RXdl,
+ * int TA, Date time) { this(ARFCN, RXul, RXdl, TA, false, time); }
+ */
+
+ public SingleBTS(int ARFCN, int RXul, int RXdl, boolean interpolated,
+ Date timestamp, String name, int TA, int BS_POWER, int MS_TO,
+ int mS_PWR) {
+ this.ARFCN = ARFCN;
+
+ this.addUl(RXul);
+ this.addDl(RXdl);
+
+ this.interpolated.add(interpolated);
+ // this.interpolated = interpolated;
+ this.time = timestamp;
+ this.name = name;
+ this.TA = TA;
+ this.BS_POWER = BS_POWER;
+ this.MS_TO = MS_TO;
+
+ }
+
+ // "empty" constructor to do averaging
+ public SingleBTS(int ARFCN, String name) {
+ this.ARFCN = ARFCN;
+ this.name = name;
+ this.reason = 2;
+ time = new Date();
+ }
+
+ public void addUl(double RXul) {
+ // a Measurement of 0 will not happen!
+ if (RXul != 0) {
+ if (RXul > 0) {
+ // RXul is in mW
+ this.RXul.add(RXul);
+ } else {
+ // RXul is in dBmw
+ double value = Math.pow(10, RXul / 10d);
+ this.RXul.add(value);
+ }
+ // it gets automatically a full BTS
+ fullBTS = true;
+ }
+ }
+
+ public double getDLQsub() {
+ if (dlQsub.size() == 0) {
+ return -10000;
+ }
+ if (dlQsub.size() == 1) {
+ return dlQsub.get(0);
+ }
+
+ int result = 0;
+ for (int i = 0; i < dlQsub.size(); i++) {
+ result += dlQsub.get(i);
+ }
+ return ((double) result / dlQsub.size());
+ }
+
+ public double getULQsub() {
+ if (ulQsub.size() == 0) {
+ return -10000;
+ }
+ if (ulQsub.size() == 1) {
+ return ulQsub.get(0);
+ }
+
+ int result = 0;
+ for (int i = 0; i < ulQsub.size(); i++) {
+ result += ulQsub.get(i);
+ }
+ return ((double) result / ulQsub.size());
+ }
+
+ /*
+ * public double getULQfull() { if (ulQfull.size() == 0) { return -10000; }
+ * if (ulQfull.size() == 1) { return ulQfull.get(0); }
+ *
+ * int result = 0; for (int i = 0; i < ulQfull.size(); i++) { result +=
+ * ulQfull.get(i); } return ((double) result / ulQfull.size()); }
+ */
+
+ /*
+ * public double getDLQfull() { if (dlQfull.size() == 0) { return 9; } if
+ * (dlQfull.size() == 1) { return dlQfull.get(0); }
+ *
+ * int result = 0; for (int i = 0; i < dlQfull.size(); i++) { result +=
+ * dlQfull.get(i); } return ((double) result / dlQfull.size()); }
+ */
+
+ public double getUldB() {
+ if (RXul.isEmpty())
+ return Double.NaN;
+ double sum = 0;
+ for (Double ul : RXul) {
+ sum = sum + ul;
+ }
+ // average
+ sum = sum / RXul.size();
+ // to dbm
+ double dbm = 10 * Math.log10(sum);
+ return (dbm);
+ }
+
+ public double getULmW() {
+ if (RXul.isEmpty())
+ return 0;
+ double sum = 0;
+ for (Double ul : RXul) {
+ sum = sum + ul;
+ }
+ return (sum / RXul.size());
+ }
+
+ public double getDLmW() {
+ if (RXdl.isEmpty())
+ return 0;
+ double sum = 0;
+ for (Double dl : RXdl) {
+ sum = sum + dl;
+ }
+ return (sum / RXdl.size());
+ }
+
+ public void addDl(double RXdl) {
+ if (RXdl != 0) {
+ if (RXdl > 0) {
+ // RXdl is in mW
+ this.RXdl.add(RXdl);
+ } else {
+ // RXul is in dBmW
+ double value = Math.pow(10, RXdl / 10d);
+ this.RXdl.add(value);
+ }
+ }
+ }
+
+ public double getDldB() {
+ if (RXdl.isEmpty())
+ return Double.NaN;
+ double sum = 0;
+ for (Double dl : RXdl) {
+ sum = sum + dl;
+ }
+ // average
+ sum = sum / RXdl.size();
+ // to dB
+ double dbm = 10 * Math.log10(sum);
+ return (dbm);
+ }
+
+ /**
+ * Returns average of dB-Values. No prior transform to mW before averaging.
+ * Seems wrong!
+ *
+ * @return
+ */
+ public double getStrictDLdBAverage() {
+ if (mode == 0) {
+ double sum = 0;
+ for (Double x : RXdl) {
+ sum += 10 * Math.log10(x);
+ }
+ sum = sum / getDLcount();
+ // mode = sum;
+ return sum;
+ } else
+ return mode;
+ }
+
+ /**
+ * Adds measurements from another SingleBTS. Provided BTS is only added if:
+ * BTS is not null, ARFCN of BTS matches
+ *
+ * @param BTS
+ * The BTS that should be added
+ */
+ public void addBTSMeasure(SingleBTS BTS) {
+ if (BTS != null && BTS.ARFCN == this.ARFCN) {
+ addUl(BTS.getUldB());
+ addDl(BTS.getDldB());
+ // this.dlQsub.addAll(BTS.dlQsub);
+ // this.dlQfull.addAll(BTS.dlQfull);
+ this.ulQsub.addAll(BTS.ulQsub);
+ // this.ulQfull.addAll(BTS.ulQfull);
+ this.dlQsub.addAll(BTS.dlQsub);
+ if (BTS.BS_POWER != 0)
+ this.BS_POWER = BTS.BS_POWER;
+ if (BTS.MS_PWR != 0)
+ this.MS_PWR = BTS.MS_PWR;
+ if (BTS.MS_TO != 0)
+ this.MS_TO = BTS.MS_TO;
+ if (BTS.TA != 0)
+ this.TA = BTS.TA;
+ if (BTS.time != null)
+ this.time = BTS.time;
+ if (!this.fullBTS)
+ this.fullBTS = BTS.fullBTS;
+ }
+ }
+
+ public double getVarianceULmW() {
+ /*
+ * Variance: calculate avarage calculate for each measurement x:
+ * (x-average)² sum up and divide by number of measurements
+ */
+ double average = getULmW();
+ double variance = 0;
+ for (double xi : RXul) {
+ variance += Math.pow(xi - average, 2);
+ }
+ return variance / getULcount();
+
+ }
+
+ public double getVarianceDLmW() {
+
+ /*
+ * Variance: calculate avarage calculate for each measurement x:
+ * (x-average)² sum up and divide by number of measurements
+ */
+ double average = getDLmW();
+ double variance = 0;
+ for (double xi : RXdl) {
+ variance += Math.pow(xi - average, 2);
+ }
+ return variance / getDLcount();
+ }
+
+ @SuppressWarnings("unused")
+ public double getVarianceDLdB() {
+ // HACK: always return sigma 5 (Variance 25 = 5^2)!!!
+ if (true) {
+ // return 8; // std of 4 if no user present
+ // return 12.5; // std of 5 if a user present
+ // was 2.5!
+ // return 16;
+ return 25;
+ }
+
+ // if (RXdl.isEmpty()) {
+ // return 0;
+ // }
+
+ // if (isInterpolated()) {
+ // return varDL;
+ // }
+
+ double variance = 0;
+
+ // TODO: set average to getAverageDLdB(). Then calculate variance!
+
+ // calculate average of dB values (no Tranform to mW and back)
+ double average = 0;
+ for (double value : RXdl) {
+ average += 10 * Math.log10(value);
+ }
+ average = average / getDLcount();
+
+ for (double xi : RXdl) {
+ variance += Math.pow(10 * Math.log10(xi) - average, 2);
+ }
+ variance = variance / getDLcount();
+ // double variance = 10 * Math.log10(getVarianceDLmW());
+
+ if (variance == Double.NaN) {
+ System.out.println("NaN in Variance");
+ }
+
+ return variance;
+ }
+
+ public double getVarianceULdB() {
+ if (RXdl.isEmpty()) {
+ return 0;
+ }
+
+ double variance = 0;
+
+ // calculate simple average of dB values (no tranform to mW)
+ double average = 0;
+ for (double value : RXul) {
+ average += 10 * Math.log10(value);
+ }
+ average = average / getULcount();
+
+ for (double xi : RXul) {
+ variance += Math.pow(10 * Math.log10(xi) - average, 2);
+ }
+ variance = variance / getULcount();
+ // double variance = 10 * Math.log10(getVarianceDLmW());
+ return variance;
+ }
+
+ public double getTrueVarianceDLdB() {
+ if (RXdl.isEmpty()) {
+ return 5;
+ }
+
+ if (isInterpolated()) {
+ return varDL;
+ }
+
+ double variance = 0;
+
+ // TODO: set average to getAverageDLdB(). Then calculate variance!
+
+ // calculate average of dB values (no Tranform to mW and back)
+ double average = 0;
+ for (double value : RXdl) {
+ average += 10 * Math.log10(value);
+ }
+ average = average / getDLcount();
+
+ for (double xi : RXdl) {
+ variance += Math.pow(10 * Math.log10(xi) - average, 2);
+ }
+ variance = variance / getDLcount();
+ // double variance = 10 * Math.log10(getVarianceDLmW());
+
+ if (variance == Double.NaN) {
+ System.out.println("NaN in Variance");
+ }
+
+ return variance;
+ }
+
+ public int getULcount() {
+ return RXul.size();
+ }
+
+ public int getDLcount() {
+ return RXdl.size();
+ }
+
+ public int minDLdB() {
+ double minmW = minDLmW();
+ if (((int) (10 * Math.log10(minmW))) == 33) {
+ System.out.print("min falsch");
+ }
+ double minDLdB = (10 * Math.log10(minmW));
+ if (minDLdB == Double.NEGATIVE_INFINITY) {
+ return -111;
+ }
+
+ return (int) minDLdB;
+ }
+
+ public double minDLmW() {
+ if (RXdl.isEmpty()) {
+ return 0;
+ }
+
+ double min = 2000;
+ for (Double measure : RXdl) {
+ if (measure < min)
+ min = measure;
+ }
+ return min;
+ }
+
+ public int minULdB() {
+ double minmW = minULmW();
+
+ double mindB = 10 * Math.log10(minmW);
+
+ if (mindB == Double.NEGATIVE_INFINITY) {
+ return -111;
+ }
+
+ return (int) (mindB);
+ }
+
+ public double minULmW() {
+ if (RXul.isEmpty()) {
+ return 0;
+ }
+
+ double min = 2000;
+ for (Double measure : RXul) {
+ if (measure < min)
+ min = measure;
+ }
+ return min;
+ }
+
+ public int maxDLdB() {
+ double maxmW = maxDLmW();
+ return (int) (10 * Math.log10(maxmW));
+ }
+
+ public double maxDLmW() {
+ double max = -2000;
+ for (Double measure : RXdl) {
+ if (measure > max) {
+ max = measure;
+ }
+ }
+ return max;
+ }
+
+ public int maxULdB() {
+ double maxmW = maxULmW();
+ return (int) (10 * Math.log10(maxmW));
+ }
+
+ public double maxULmW() {
+ double max = -2000;
+ for (Double measure : RXul) {
+ if (measure > max) {
+ max = measure;
+ }
+ }
+ return max;
+ }
+
+ // returns "ARFCN;RXul;RXdl;TA"
+ public String toString() {
+ if (RXdl.size() == 1 && RXul.size() == 1) {
+ return (name + ":" + ARFCN + "; UL:" + (int) (getUldB()) + "; DL:"
+ + (int) (getDldB()) + " Mode:" + getStrictDLdBAverage()
+ + " " + time.toString());
+ } else {
+
+ String dl = getDLString();
+ String ul = getULString();
+
+ return (name + ": " + ARFCN + "; " + ul + " " + dl + " " + time
+ .toString());
+ }
+ }
+
+ public String ULtoString() {
+ return getULString() + " " + time.toString();
+ }
+
+ public String DLtoString() {
+ return getDLString() + " Mode: " + getStrictDLdBAverage() + ", "
+ + time.toString();
+ }
+
+ private String getULString() {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(3);
+ String ul = "UL(min:" + minULdB() + ",max:" + maxULdB() + ",varDL:"
+ + nf.format(getVarianceULdB()) + "avg:" + nf.format(getUldB())
+ + "),#meas:" + RXul.size();
+ return ul;
+ }
+
+ public String getDLString() {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(3);
+ // String variance = Double.toString(getVarianceDLdB());
+ // String variancevariable = Double.toString(varDL);
+ String dl = "DL(min:" + minDLdB() + ",max:" + maxDLdB() + ",varDL:"
+ + nf.format(getVarianceDLdB()) + "avg:" + nf.format(getDldB())
+ + "),#meas:" + RXdl.size();
+ return dl;
+ }
+
+ // make SingleBTS comparable to SingleBTS!
+ public int compareTo(SingleBTS comperator) {
+ if (this.time == null || comperator.time == null) {
+ throw new NullPointerException(
+ "one of the SingleBTS objects is null!");
+ }
+ if (this.time.getTime() > comperator.time.getTime()) {
+ return 1;
+ } else if (this.time.getTime() < comperator.time.getTime()) {
+ return -1;
+ } else
+ return 0;
+
+ }
+
+ public int compareTo(Date timestamp) {
+ if (this.time == null || timestamp == null) {
+ throw new NullPointerException("objects is null!");
+ }
+ if (this.time.getTime() > timestamp.getTime()) {
+ return 1;
+ } else if (this.time.getTime() < timestamp.getTime()) {
+ return -1;
+ } else
+ return 0;
+
+ }
+
+ public boolean newlyInterpolated() {
+ if (interpolated == null || interpolated.isEmpty())
+ return false;
+ return interpolated.get(interpolated.size() - 1);
+ }
+
+ /**
+ * remove outlier with Grubb's test. see
+ * http://www.graphpad.com/articles/outlier.htm
+ */
+ public void removeOutlier() {
+ // if (RXul.size() < 4)
+ // System.out.println("Too few data points: UL! " + RXul.size());
+ // if (RXdl.size() < 4)
+ // System.out.println("Too few data points: DL! " + RXdl.size());
+ boolean outlier = true;
+ // loop until no more outlier is found
+ while (outlier) {
+ outlier = false;
+ double maxUL = maxULdB();
+ double minUL = minULdB();
+ double maxDL = maxDLdB();
+ double minDL = minDLdB();
+
+ // calculate Z for each. Use dBm values. They are in normal
+ // distribution
+ double maxULZ = Math.abs(getUldB() - maxUL)
+ / Math.sqrt(getVarianceULdB());
+ double minULZ = Math.abs(getUldB() - minUL)
+ / Math.sqrt(getVarianceULdB());
+ double maxDLZ = Math.abs(getStrictDLdBAverage() - maxDL)
+ / Math.sqrt(getTrueVarianceDLdB());
+ double minDLZ = Math.abs(getStrictDLdBAverage() - minDL)
+ / Math.sqrt(getTrueVarianceDLdB());
+
+ // check for probability < 95% that it is within the gauss curve
+ if (maxULZ > getCritZ(getULcount()) && RXul.size() > 2) {
+ RXul.remove((Object) maxULmW());
+ outlier = true;
+ // start again from the beginning: continue
+ continue;
+ // System.out.println("Outlier UL removed: " + maxUL);
+ }
+ if (minULZ > getCritZ(getULcount()) && RXul.size() > 2) {
+ RXul.remove((Object) minULmW());
+ outlier = true;
+ continue;
+ // System.out.println("Outlier UL removed: " + minUL);
+ }
+ if (maxDLZ > getCritZ(getDLcount()) && RXdl.size() > 2) {
+ RXdl.remove((Object) maxDLmW());
+ outlier = true;
+ continue;
+ // System.out.println("Outlier DL removed: " + maxDL);
+ }
+ if (minDLZ > getCritZ(getDLcount()) && RXdl.size() > 2) {
+ RXdl.remove((Object) minDLmW());
+ outlier = true;
+ continue;
+ // System.out.println("Outlier DL removed: " + minDL);
+ }
+
+ }
+
+ }
+
+ // search for arfcn!
+ public int compareTo(int arfcn) {
+ if (this.ARFCN > arfcn)
+ return 1;
+ if (this.ARFCN < arfcn)
+ return -1;
+ else
+ return 0;
+
+ }
+
+ // resets UL and DL
+ public void clear() {
+ RXdl.clear();
+ RXul.clear();
+
+ }
+
+ public boolean isInterpolated() {
+ if (interpolated == null || interpolated.isEmpty()) {
+ return false;
+ } else {
+ return interpolated.getLast(); // damit die Log-Interpolation
+ // wieder
+ // funktioniert, muss das hier auf
+ // getFirst() stehen
+ // return interpolated.getFirst();
+ }
+ }
+
+ // show critical values for Z
+ private float getCritZ(int N) {
+ if (N == 3)
+ return 1.15f;
+ if (N == 4)
+ return 1.48f;
+ if (N == 5)
+ return 1.71f;
+ if (N == 6)
+ return 1.89f;
+ if (N == 7)
+ return 2.02f;
+ if (N == 8)
+ return 2.13f;
+ if (N == 9)
+ return 2.21f;
+ if (N == 10)
+ return 2.29f;
+ if (N == 11)
+ return 2.34f;
+ if (N == 12)
+ return 2.41f;
+ if (N == 13)
+ return 2.46f;
+ if (N == 14)
+ return 2.51f;
+ if (N == 15)
+ return 2.55f;
+ if (N == 16)
+ return 2.59f;
+ if (N == 17)
+ return 2.62f;
+ if (N == 18)
+ return 2.65f;
+ if (N == 19)
+ return 2.68f;
+ if (N == 20)
+ return 2.73f;
+ if (N == 21)
+ return 2.73f;
+ if (N == 22)
+ return 2.76f;
+ if (N == 23)
+ return 2.78f;
+ if (N == 24)
+ return 2.80f;
+ if (N == 25)
+ return 2.82f;
+ if (N == 26)
+ return 2.84f;
+ if (N == 27)
+ return 2.86f;
+ if (N == 28)
+ return 2.88f;
+ if (N == 29)
+ return 2.89f;
+ if (N == 30)
+ return 2.91f;
+ if (N == 31)
+ return 2.92f;
+ if (N == 32)
+ return 2.94f;
+ if (N == 33)
+ return 2.95f;
+ if (N == 34)
+ return 2.97f;
+ if (N == 35)
+ return 2.98f;
+ if (N == 36)
+ return 2.99f;
+ if (N == 37)
+ return 3.00f;
+ if (N == 38)
+ return 3.01f;
+ if (N == 39)
+ return 3.03f;
+ if (N >= 40 && N < 50)
+ return 3.04f;
+ if (N >= 50 && N < 60)
+ return 3.13f;
+ if (N >= 60 && N < 70)
+ return 3.20f;
+ if (N >= 70 && N < 80)
+ return 3.26f;
+ if (N >= 80 && N < 90)
+ return 3.31f;
+ if (N >= 90 && N < 100)
+ return 3.35f;
+ if (N >= 100 && N < 110)
+ return 3.38f;
+ if (N >= 110 && N < 120)
+ return 3.42f;
+ if (N >= 120 && N < 130)
+ return 3.44f;
+ if (N >= 130 && N < 140)
+ return 3.47f;
+ if (N >= 140 && N < 150)
+ return 3.49f;
+ if (N >= 150 && N < 160)
+ return 3.52f;
+ else
+ return 3.7f;
+ }
+
+ /**
+ * Sets the Variance for DL in mW. Works only if this BTS is interpolated!
+ *
+ * @param varDL
+ */
+ public void setVarDLdB(double var) {
+ if (isInterpolated()) {
+ this.varDL = var;
+ } else {
+ System.out.println("kann Variance nicht setzen!");
+ }
+
+ }
+
+}