summaryrefslogtreecommitdiffstats
path: root/DataStructure
diff options
context:
space:
mode:
Diffstat (limited to 'DataStructure')
-rw-r--r--DataStructure/BayesAll.java380
-rw-r--r--DataStructure/GPScoordinate.java88
-rw-r--r--DataStructure/GSMMap.java1275
-rw-r--r--DataStructure/GSMMapInterpolatorOld.java200
-rw-r--r--DataStructure/GoogleOut.java598
-rw-r--r--DataStructure/Interpolator.java366
-rw-r--r--DataStructure/MeasurementReport.java60
-rw-r--r--DataStructure/MobilePhone.java337
-rw-r--r--DataStructure/NormDistribution.java77
-rw-r--r--DataStructure/PhoneContainer.java106
-rw-r--r--DataStructure/PossibilityObject.java21
-rw-r--r--DataStructure/ResultScore.java54
-rw-r--r--DataStructure/ScoreElement.java21
-rw-r--r--DataStructure/SingleBTS.java775
-rw-r--r--DataStructure/Weight.java19
-rw-r--r--DataStructure/gsmBayes.java752
-rw-r--r--DataStructure/jdom.jarbin0 -> 152797 bytes
-rw-r--r--DataStructure/ratioElem.java114
18 files changed, 5243 insertions, 0 deletions
diff --git a/DataStructure/BayesAll.java b/DataStructure/BayesAll.java
new file mode 100644
index 0000000..27ab797
--- /dev/null
+++ b/DataStructure/BayesAll.java
@@ -0,0 +1,380 @@
+package DataStructure;
+
+import helper.ListBTS;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class BayesAll {
+ GSMMap map;
+ // ArrayList<SingleBTS> MR;
+ ArrayList<ratioElem>[][] RatioMap;
+ boolean[][] hasElement;
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ }
+
+ public BayesAll(Interpolator map) {
+ this.map = map;
+ hasElement = map.getAllocation();
+
+ // Compute ALL Ratios for GSMmap
+ RatioMap = computeMapRatio();
+
+ }
+
+ public BayesAll(GSMMap map) {
+ this.map = map;
+ hasElement = map.getAllocation();
+ RatioMap = computeMapRatio();
+ }
+
+ public double[][] locate(ArrayList<SingleBTS> MR, double confidence) {
+
+ SingleBTS[] content = ListBTS.content(MR);
+ // check if MR only has one BTS inside!
+ if (content == null || content.length <= 1) {
+ // only one or zero BTS. mark all tiles where this BTS is received!
+ // get BTS
+
+ return markOneBTS(content);
+ }
+
+ // Compute ALL Ratios out of mobile phone's MR
+ ArrayList<ratioElem> RSSVector = computeAllRatios(MR);
+
+ // Compute scoremap
+ double[][] scoremap = computeScoreMap(RSSVector);
+
+ if (confidence >= 1)
+ return scoremap;
+ else
+ return toConfidence(scoremap, confidence);
+ }
+
+ /**
+ * This returns the distribution if only one BTS is measured
+ *
+ * @param singleBTS
+ * @return
+ */
+ private double[][] markOneBTS(SingleBTS[] singleBTS) {
+ int count = 0;
+ double[][] scoremap = new double[map.Xcoords.length][map.Ycoords.length];
+
+ if (singleBTS == null) {
+ long numberOfTiles = map.countTilesWMeasures();
+ for (int x = 0; x < map.Xcoords.length; x++) {
+ for (int y = 0; y < map.Ycoords.length; y++) {
+ if (hasElement[x][y]) {
+ scoremap[x][y] = 1d / (double) numberOfTiles;
+ }
+ }
+ }
+ }
+
+ // count tiles where this bts is measured
+ for (int x = 0; x < map.Xcoords.length; x++) {
+ for (int y = 0; y < map.Ycoords.length; y++) {
+ if (ListBTS.contains(map.map[x][y], singleBTS[0])) {
+ count++;
+ }
+ }
+ }
+
+ // give every tile a equal distributed possibility
+ for (int x = 0; x < map.Xcoords.length; x++) {
+ for (int y = 0; y < map.Ycoords.length; y++) {
+ if (ListBTS.contains(map.map[x][y], singleBTS[0])) {
+ scoremap[x][y] = 1d / (double) count;
+ }
+ }
+ }
+
+ return scoremap;
+ }
+
+ private double[][] computeScoreMap(ArrayList<ratioElem> RSSVector) {
+ double[][] score = new double[map.Xcoords.length][map.Ycoords.length];
+ // Compute possibility that this RSSVector was measured in RatioMap as
+ // TODO: Thread!!!
+ computeTotalProbability totalProbRunnable = new computeTotalProbability(
+ RSSVector);
+ Thread totalProbThread = new Thread(totalProbRunnable);
+ totalProbThread.start();
+ // double totalProbability = computeTotalProb(RSSVector);
+ // now we have P(S) (=totalProb that RSSVector appears in map)
+ double numberOfTiles = map.countTilesWMeasures();
+ // compute Bayes with RSSVector
+ for (int x = 0; x < RatioMap.length; x++) {
+ for (int y = 0; y < RatioMap[0].length; y++) {
+ if (hasElement[x][y]) {
+ score[x][y] = (ProbabilityForRSSVector(RSSVector,
+ RatioMap[x][y]) * (1 / numberOfTiles));
+ // / totalProbability;
+ }
+ }
+ }
+
+ // division with total Probability
+ try {
+ totalProbThread.join();
+ double totalProbability = totalProbRunnable.totalProbability;
+ for (int x = 0; x < RatioMap.length; x++) {
+ for (int y = 0; y < RatioMap[0].length; y++) {
+ if (hasElement[x][y]) {
+ score[x][y] = score[x][y] / totalProbability;
+ }
+ }
+
+ }
+
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return score;
+ }
+
+ /**
+ * Computes Probability that this RSSVector is seen in the Map
+ *
+ * @param RSSVector
+ * @return
+ */
+ @SuppressWarnings("unused")
+ private double computeTotalProb(ArrayList<ratioElem> RSSVector) {
+ double totalProb = 0;
+ // go through all valid Elements in RatioMap. Sum up the possibilities
+ // for each tile
+ for (int x = 0; x < RatioMap.length; x++) {
+ for (int y = 0; y < RatioMap[0].length; y++) {
+ if (hasElement[x][y])
+ totalProb += ProbabilityForRSSVector(RSSVector,
+ RatioMap[x][y]);
+ }
+
+ /*
+ * int y = 0; while (y < RatioMap[0].length) { possibilityThread
+ * threadable1 = new possibilityThread( RSSVector, x, y); Thread
+ * thread1 = new Thread(threadable1); if (hasElement[x][y])
+ * thread1.start(); y++; possibilityThread threadable2 = new
+ * possibilityThread( RSSVector, x, y); Thread thread2 = new
+ * Thread(threadable2); if (y < RatioMap[0].length &&
+ * hasElement[x][y]) thread2.start(); y++; try { thread1.join();
+ * thread2.join(); } catch (InterruptedException e) {
+ * e.printStackTrace(); } // Threads fertig.
+ *
+ * }
+ */
+ }
+
+ double numberOfTiles = map.countTilesWMeasures();
+ totalProb = totalProb / numberOfTiles;
+ return totalProb;
+ }
+
+ private double ProbabilityForRSSVector(ArrayList<ratioElem> MRphone,
+ ArrayList<ratioElem> MRmap) {
+
+ double probability = 1;
+ boolean thereWasAHit = false;
+ for (int i = 0; i < MRphone.size(); i++) {
+ // when there is no measurement from phone, go to next ratio element
+ if (MRphone.get(i) != null) {
+ if (MRmap.get(i) == null)
+ return 0;
+ probability *= MRphone.get(i).probability(MRmap.get(i));
+ thereWasAHit = true;
+ }
+
+ }
+
+ if (thereWasAHit)
+ return probability;
+ else
+ return 0;
+ }
+
+ /**
+ * Creates Ratios out of map (all possible ratios!)
+ *
+ * @return
+ */
+ private ArrayList<ratioElem>[][] computeMapRatio() {
+ ArrayList<ratioElem>[][] result = new ArrayList[map.Xcoords.length][map.Ycoords.length];
+
+ // int size = sumOfRatio(map.content().length - 1);
+ // result initilisieren und füllen
+ for (int x = 0; x < map.Xcoords.length; x++) {
+ for (int y = 0; y < map.Ycoords.length; y++) {
+ if (hasElement[x][y]) {
+ // result[x][y] = new ArrayList<ratioElem>(size);
+
+ result[x][y] = (computeAllRatios(map.map[x][y]));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns all possible Ratios that can be built with GSM-Map's content out
+ * of MR. Not available Ratios get stored as null
+ *
+ * @return
+ */
+ private ArrayList<ratioElem> computeAllRatios(ArrayList<SingleBTS> MR) {
+ SingleBTS[] content = map.content();
+ ArrayList<ratioElem> result = new ArrayList<ratioElem>(
+ sumOfRatio(content.length - 1));
+ // get ratio between every BTS and the others
+ for (int i = 0; i < content.length; i++) {
+ for (int j = i + 1; j < content.length; j++) {
+ SingleBTS top = ListBTS.getARFCN(MR, content[i]);
+ SingleBTS bottom = ListBTS.getARFCN(MR, content[j]);
+ if (top == null || bottom == null) {
+ result.add(null);
+ } else {
+ result.add(new ratioElem(top, bottom));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Computes all Ratios that can be built out of MR
+ *
+ * @param MR
+ * @return
+ */
+ @SuppressWarnings("unused")
+ private ArrayList<ratioElem> computeRatios(ArrayList<SingleBTS> MR) {
+ ArrayList<ratioElem> result = new ArrayList<ratioElem>(
+ sumOfRatio(MR.size() - 1));
+ for (int i = 0; i < MR.size(); i++) {
+ for (int j = i + 1; j < MR.size(); j++) {
+ result.add(new ratioElem(MR.get(i), MR.get(j)));
+ }
+ }
+ return result;
+ }
+
+ private static int sumOfRatio(int n) {
+ return n == 0 ? 1 : n + sumOfRatio(n - 1);
+ }
+
+ public double[][] toConfidence(double[][] scoremap, double confidence) {
+ if (confidence >= 1) {
+ return scoremap;
+ }
+
+ // scoremap to possibility objects (faster...)
+ PossibilityObject[] possibilities = toPossibility(scoremap);
+ double sum_confidence = 0;
+ double[][] result = new double[scoremap.length][scoremap[0].length];
+ int boundary = possibilities.length - 1;
+ while (sum_confidence < confidence) {
+ // run from highest element to lowest.
+ // as long as confidence is not reached: store current element in
+ // result
+ sum_confidence += possibilities[boundary].possibility;
+ int x = possibilities[boundary].x;
+ int y = possibilities[boundary].y;
+ result[x][y] = possibilities[boundary].possibility;
+ boundary--;
+ }
+ // result = PossObjToScoremap(possibilities, boundary, result);
+
+ /*
+ * double max = 0; int xmax = 0; int ymax = 0; for (int x = 0; x <
+ * scoremap.length; x++) { for (int y = 0; y < scoremap[0].length; y++)
+ * { if (scoremap[x][y] > max) { max = scoremap[x][y]; xmax = x; ymax =
+ * y; }
+ *
+ * } } // max found.
+ *
+ * result[xmax][ymax] = scoremap[xmax][ymax]; sum_confidence +=
+ * scoremap[xmax][ymax]; scoremap[xmax][ymax] = 0; }
+ */
+ return result;
+
+ }
+
+ /**
+ * Makes a scoremap to a SORTED one dimensional PossibilityObject Array.
+ * Calculates the entropy on the way and prints to Console
+ *
+ * @param scoremap
+ * @return
+ */
+ public PossibilityObject[] toPossibility(double[][] scoremap) {
+ int gsmmapsize = (int) map.countTilesWMeasures();
+ // PossibilityObject[] possibilities = new
+ // PossibilityObject[gsmmapsize];
+ ArrayList<PossibilityObject> result = new ArrayList<PossibilityObject>(
+ gsmmapsize);
+ double entropy = 0;
+ for (int x = 0; x < scoremap.length; x++) {
+ for (int y = 0; y < scoremap[0].length; y++) {
+ if (hasElement[x][y] && scoremap[x][y] > 0) {
+ entropy = entropy + scoremap[x][y]
+ * ((Math.log(scoremap[x][y])) / Math.log(2));
+
+ PossibilityObject current = new PossibilityObject();
+ current.possibility = scoremap[x][y];
+ current.x = x;
+ current.y = y;
+ result.add(current);
+ }
+ }
+
+ }
+
+ System.out.println("Entropy dieser Karte: " + (entropy * (-1))
+ + " max. Entropy: " + (Math.log(gsmmapsize) / Math.log(2)));
+ PossibilityObject[] possibilities = result
+ .toArray(new PossibilityObject[1]);
+ Arrays.sort(possibilities);
+ return possibilities;
+ }
+
+ class computeTotalProbability implements Runnable {
+ private ArrayList<ratioElem> RSSVector;
+ public double totalProbability;
+
+ public computeTotalProbability(ArrayList<ratioElem> RSSVector) {
+ this.RSSVector = RSSVector;
+ }
+
+ @Override
+ public void run() {
+ double totalProb = 0;
+ // go through all valid Elements in RatioMap. Sum up the
+ // possibilities
+ // for each tile
+ for (int x = 0; x < RatioMap.length; x++) {
+ for (int y = 0; y < RatioMap[0].length; y++) {
+ if (hasElement[x][y])
+ totalProb += ProbabilityForRSSVector(RSSVector,
+ RatioMap[x][y]);
+ }
+
+ }
+
+ double numberOfTiles = map.countTilesWMeasures();
+ totalProb = totalProb / numberOfTiles;
+ totalProbability = totalProb;
+ }
+
+ }
+
+}
diff --git a/DataStructure/GPScoordinate.java b/DataStructure/GPScoordinate.java
new file mode 100644
index 0000000..dee0748
--- /dev/null
+++ b/DataStructure/GPScoordinate.java
@@ -0,0 +1,88 @@
+/**
+ *
+ */
+package DataStructure;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author richy
+ *
+ */
+@SuppressWarnings("serial")
+public class GPScoordinate implements Comparable<Date>, Serializable {
+ public Date time;
+ public double coord1;
+ public char coord1NS;
+ public double coord2;
+ public char coord2EW;
+ public boolean isGood;
+ public String coord1S;
+ public String coord2S;
+
+ // Constructor
+ public GPScoordinate(Date time, double coord1, char coord1NS,
+ double coord2, char coord2EW, boolean isGood) {
+ this.time = time;
+ this.coord1 = coord1;
+ this.coord1NS = coord1NS;
+ this.coord2 = coord2;
+ this.coord2EW = coord2EW;
+ this.isGood = isGood;
+
+ }
+
+ public boolean equals(GPScoordinate gps2) {
+ return (coord1 == gps2.coord1 && coord2 == gps2.coord2);
+ }
+
+ public String toString() {
+ String time = "noDate";
+ if (this.time != null)
+ time = this.time.toString();
+ return (Double.toString(coord1) + coord1NS + ";"
+ + Double.toString(coord2) + coord2EW + ";" + isGood + ";" + time);
+ }
+
+ public Double getCoord1AsDezim() {
+ // int whole = (int) coord1;
+ // double floor = (coord1 - whole) * 60;
+ // return (whole + floor);
+ return coord1;
+ }
+
+ public Double getCoord2AsDezim() {
+ // int whole = (int) coord2;
+ // double floor = (coord2 - whole) * 60;
+ // return (whole + floor);
+ return coord2;
+ }
+
+ 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 isValid() {
+ if (time == null || time.getTime() < 10l) {
+ return false;
+ }
+ if (!isGood) {
+ return false;
+ }
+ if (coord1 == 0 || coord2 == 0) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/DataStructure/GSMMap.java b/DataStructure/GSMMap.java
new file mode 100644
index 0000000..88f573c
--- /dev/null
+++ b/DataStructure/GSMMap.java
@@ -0,0 +1,1275 @@
+package DataStructure;
+
+import helper.ListBTS;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.geom.Point2D;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Serializable;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+import org.jdesktop.swingx.JXMapViewer;
+import org.jdesktop.swingx.mapviewer.GeoPosition;
+import org.jdesktop.swingx.painter.Painter;
+
+import Parse.sqlreader;
+
+public class GSMMap implements Painter<JXMapViewer>, Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7231890635513775719L;
+ public double minX;
+ public double maxX;
+ public double minY;
+ public double maxY;
+ public double[] Xcoords;
+ public double[] Ycoords;
+ public double accuracy;
+ public ArrayList<SingleBTS>[][] map;
+ // public ArrayList<SingleBTS>[][] buffer;
+ public SingleBTS[] btsnames; // names of BTS from sql databse
+ private SingleBTS[] btsarray; // btsarray from sqlreader.
+ private GPScoordinate[] gpsarray;
+ public long IMSI;
+ private int matrixsize;
+ private boolean isAveraged = false;
+ private SingleBTS[] mapcontent;
+ public int numberOfCoordinates;
+ public PaintEnum whatToPaint = PaintEnum.DL;
+ public int indexToPaint;
+
+ // Constructor
+ public GSMMap(sqlreader SQL, double accuracy) {
+ // search for min and max Y,X Coords
+ this.accuracy = accuracy;
+ numberOfCoordinates = SQL.gpsarray.length;
+ gpsarray = SQL.gpsarray; // measured GPS coordinates
+ btsarray = SQL.btsarray; // corresponding found BTS
+ btsnames = SQL.BtsNames;
+ this.IMSI = SQL.IMSI;
+ minX = MapHelper.getMinX(gpsarray, 0d);
+ maxX = MapHelper.getMaxX(gpsarray, 0d);
+ minY = MapHelper.getMinY(gpsarray, 0d);
+ maxY = MapHelper.getMaxY(gpsarray, 0d);
+ Xcoords = MapHelper.createArray(minX, maxX, accuracy); // 90°
+ Ycoords = MapHelper.createArray(minY, maxY, accuracy); // 180°
+ // create Array with inside ArrayList
+ ArrayList<SingleBTS>[][] map = new ArrayList[Xcoords.length][Ycoords.length];
+ this.map = map;
+ // initializa map
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ map[x][y] = new ArrayList<SingleBTS>();
+ }
+ }
+
+ // fill map
+ for (int i = 0; i < gpsarray.length; i++) {
+ add(gpsarray[i], btsarray[i]);
+ }
+
+ }
+
+ public void add(GPScoordinate gps, SingleBTS bts) {
+ int x = searchBestX(gps.coord2);
+ int y = searchBestY(gps.coord1);
+ map[x][y].add(bts);
+
+ }
+
+ public void add(GPScoordinate gps, ArrayList<SingleBTS> list) {
+ if (list == null)
+ return;
+ int x = searchBestX(gps.coord2);
+ int y = searchBestY(gps.coord1);
+ map[x][y].addAll(list);
+ }
+
+ /**
+ * Averages all MR that fall into one tile. Does not depend on usedBTS from
+ * sql
+ */
+ public void average() {
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ SingleBTS[] content = MapHelper.content(map[x][y]);
+ if (content != null) {
+ map[x][y] = generateAveragedList(map[x][y], content);
+ }
+ }
+ }
+ // after averaging the distances can be calculated pretty fast
+ calc_distances();
+ isAveraged = true;
+
+ }
+
+ /**
+ * calculates distance for every measurement report in the gsm map. Reports
+ * distance = 0 if Distance can not be computed
+ */
+ public void calc_distances() {
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ for (int z = 0; z < map[x][y].size(); z++) {
+ SingleBTS corr = corrBTS(map[x][y].get(z));
+ if (corr == null) {
+ // if Distance could not be calculated, skip
+ map[x][y].get(z).distance = 0.0;
+ } else {
+ // corresponding BTS was found
+ GPScoordinate coord1 = corr.coordinate;
+ GPScoordinate coord2 = getCoord(x, y);
+ map[x][y].get(z).distance = helper.Distance.calc(
+ coord1, coord2);
+ }
+ }
+
+ }
+ }
+ }
+
+ /**
+ * returns corresponding BTS from SQL-arfcn table for this MR
+ *
+ * @param mr
+ * your MR
+ * @return BTS that fits to this MR. Null if not found
+ */
+ private SingleBTS corrBTS(SingleBTS mr) {
+ for (int i = 0; i < btsnames.length; i++) {
+ if (mr.ARFCN == btsnames[i].ARFCN)
+ return btsnames[i];
+ }
+ return null;
+ }
+
+ private SingleBTS corrBTS(int arfcn) {
+ SingleBTS element = new SingleBTS(arfcn, "whatever");
+ return corrBTS(element);
+ }
+
+ public GPScoordinate getCoord(int x, int y) {
+ return new GPScoordinate(null, Ycoords[y], 'N', Xcoords[x], 'E', true);
+ }
+
+ /**
+ * Gets all BTSs that occur in the GSMmap. Note: this may be different from
+ * the BTSarray. There may be BTSs that are not stored in the sql database.
+ * For example: E-Plus BTSs
+ *
+ * @return Array with BTSs that occur in the GSMmap
+ */
+ public SingleBTS[] getUniqueBTSlist() {
+
+ ArrayList<SingleBTS> BTSlist = new ArrayList<SingleBTS>();
+ for (int x = 0; x < btsarray.length; x++) {
+ BTSlist.add(btsarray[x]);
+ }
+ return helper.ListBTS.content(BTSlist);
+
+ }
+
+ private ArrayList<SingleBTS> generateAveragedList(
+ ArrayList<SingleBTS> List, SingleBTS[] content) {
+ ArrayList<SingleBTS> output = new ArrayList<SingleBTS>();
+ // traverse every unique BTS
+ for (SingleBTS singleBTS : content) {
+ // initialize with ARFCN and Name
+ SingleBTS current = new SingleBTS(singleBTS.ARFCN, singleBTS.name);
+ // add everything from list. SingleBTS-Class takes only correct BTSs
+ for (SingleBTS measure : List) {
+ current.addBTSMeasure(measure);
+ }
+ output.add(current);
+ }
+
+ return output;
+ }
+
+ /**
+ * @param coord
+ * Coordinate in DEC
+ * @return Index where this coordinate is located within the GSMmap (x-axis)
+ */
+ public int searchBestX(double coord) {
+ // search for best fit in array
+ int found = (int) Math.round(((coord - minX) / accuracy));
+ if (found > Xcoords.length) {
+ System.out.println("gesucht nach: " + coord);
+ }
+ return found;
+ }
+
+ /**
+ * @param coord
+ * Coordinate in DEC
+ * @return Index where this coordinate is located within the GSMmap (y-axis)
+ */
+ public int searchBestY(double coord) {
+ // search for best fit in array
+ int found = (int) Math.round(((coord - minY) / accuracy));
+ // if (found == 8)
+ // System.out.println("Gesucht nach: " + coord + " Gefunden bei " +
+ // found);
+ return found;
+ }
+
+ public ArrayList<SingleBTS> getBTSList(GPScoordinate gps) {
+ int x = searchBestX(gps.coord2);
+ int y = searchBestY(gps.coord1);
+ return map[x][y];
+ }
+
+ public ArrayList<SingleBTS> getBTSList(double coordX, double coordY) {
+ // you could create a new GPScoordinate and use
+ // getBTSList(GPScoordinate)
+ // but maybe it's slower?
+ int x = searchBestX(coordX);
+ int y = searchBestY(coordY);
+ return map[x][y];
+
+ }
+
+ public SingleBTS getFirstBTS() {
+ return btsarray[0];
+ }
+
+ /**
+ * gets all the BTS that are stored in this map. content is ordered as the
+ * BTS appear in the map (or lets say... not sorted at all)
+ *
+ * @return
+ */
+ public SingleBTS[] content() {
+ if (mapcontent == null || mapcontent.length == 0) {
+ mapcontent = ListBTS.content(Arrays.asList(btsarray));
+ }
+
+ return mapcontent;
+ }
+
+ /**
+ * gets all BTS in this map that are not from the RZ-GSM
+ *
+ * @return
+ */
+ public SingleBTS[] contentForeignBTS() {
+ content(); // fill mapcontent
+ LinkedList<SingleBTS> result = new LinkedList<SingleBTS>();
+ for (int i = 0; i < mapcontent.length; i++) {
+
+ if (!ListBTS.contains(Arrays.asList(btsnames), mapcontent[i])) {
+ // current Element is not a RZ-GSM bts. Store it
+ result.add(mapcontent[i]);
+ }
+ }
+ if (result == null || result.isEmpty()) {
+ return null;
+ } else {
+ return result.toArray(new SingleBTS[1]);
+ }
+
+ }
+
+ /**
+ * Gets the first BTS out of the map that matches the arfcn of the given one
+ *
+ * @param bts
+ * @return
+ */
+ public SingleBTS getFirstBTSmatch(SingleBTS bts) {
+ for (SingleBTS element : btsarray) {
+ if (element.ARFCN == bts.ARFCN)
+ return element;
+ }
+ return null;
+ }
+
+ public boolean contains(SingleBTS bts) {
+ for (SingleBTS element : btsarray) {
+ if (element.ARFCN == bts.ARFCN)
+ return true;
+ }
+ return false;
+ }
+
+ public void gnuPlotSignalStrength(int ARFCN, int phonecount)
+ throws IOException {
+ // for each Tile: check if ARFCN exists. If so, ouput a file
+ // To calculate decimal deg. to meters, see
+ // http://www.sunearthtools.com/dp/tools/conversion.php?lang=eng
+ int placecount = 0;
+ // coordinates of BTS 877
+ // int BTSXCoord = searchBestX(7.834994d);
+ // int BTSYCoord = searchBestY(48.012708d);
+ File output = new File(IMSI + ".dat");
+ FileWriter fw = new FileWriter(output);
+ fw.append("#Uplink, Mobile Phone: " + IMSI);
+ fw.append("\r\n");
+ fw.append("#x y min max variance");
+ fw.append("\r\n");
+ // for every tile in GSMMap
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ for (SingleBTS bts : map[x][y]) {
+ // only full BTS are able to be drawn (uplink)
+ if (bts.ARFCN == ARFCN && bts.fullBTS) {
+ placecount++;
+ // double distance = Math.sqrt(Math.pow(x - BTSXCoord,
+ // 2)
+ // + Math.pow(y - BTSYCoord, 2));
+ double distance = helper.Distance.calc(48.012708,
+ 7.834994, Ycoords[y], Xcoords[x]);
+ // to meters (rough guess): one tile is 8m*8m
+ // distance = distance * 8;
+ // output Signalstrength, min, max and variance
+ NumberFormat nf = DecimalFormat.getInstance(Locale.US);
+ nf.setMaximumFractionDigits(15);
+ fw.append(distance + " " + nf.format(bts.getULmW())
+ + " " + nf.format(bts.minULmW()) + " "
+ + nf.format(bts.maxULmW()) + " "
+ + bts.getVarianceULmW());
+ fw.append("\r\n");
+ }
+ }
+ }
+ }
+ fw.close();
+ }
+
+ /**
+ * Outputs all receivable DLs for given phones. Distance to BTS with arfcn
+ * distanceARFCN is calculated
+ *
+ * @param arfcn
+ * @param distanceArfcn
+ * @throws IOException
+ */
+ public void gnuPlotDLAll(int[] arfcn, int distanceArfcn) throws IOException {
+ File output = new File("delta" + IMSI + ".dat");
+ FileWriter fw = new FileWriter(output);
+ fw.append("#DL all BTS\r\n");
+ String BTSs = "";
+ for (int i : arfcn) {
+ BTSs += "arfcn:" + Integer.toString(i) + " ";
+ }
+ fw.append("#Place " + BTSs + " 877UL 880UL \r\n");
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ if (map[x][y] == null || map[x][y].isEmpty()) {
+ continue;
+ }
+ SingleBTS reference = corrBTS(distanceArfcn);
+ fw.append(Double.toString(helper.Distance.calc(
+ reference.coordinate, getCoord(x, y))));
+ // TODO: here, distance to specified arfcn
+ fw.append(Integer.toString(x * Xcoords.length + y) + " ");
+ for (int i : arfcn) {
+ SingleBTS current = helper.ListBTS.getARFCN(map[x][y], i);
+
+ if (current != null) {
+ fw.append(Double.toString(current.getDldB()) + " ");
+ } else {
+ fw.append("NaN ");
+ }
+
+ }
+ SingleBTS uplink = helper.ListBTS.getARFCN(map[x][y], 877);
+ if (uplink != null && uplink.getUldB() != 0) {
+ fw.append(uplink.getUldB() + " ");
+ } else {
+ fw.append("NaN ");
+ }
+ uplink = helper.ListBTS.getARFCN(map[x][y], 880);
+ if (uplink != null && uplink.getUldB() != 0) {
+ fw.append(uplink.getUldB() + " ");
+ } else {
+ fw.append("NaN ");
+ }
+ fw.append("\r\n");
+
+ }
+ }
+ fw.close();
+ }
+
+ public void gnuPlotDeltaBTS(int ARFCN1, int ARFCN2) throws IOException {
+ // draw the ratio of ARFCN1/ARFCN2 and output in a GNUPlot readable file
+
+ // create FileWriter
+ File output = new File("delta" + IMSI + ".dat");
+ FileWriter fw = new FileWriter(output);
+ fw.append("# Delta between BTS " + ARFCN1 + " and " + ARFCN2
+ + " in dBm and mW\r\n");
+ fw.append("# Delta(dBm) Delta(mW) Ratio(dBm) Ratio(mW) DL:"
+ + ARFCN1
+ + " DL:"
+ + ARFCN2
+ + " Delta(strict_dBm) Ratio(strict_dBm) Carrier_Ratio(to 101 dB) \r\n");
+ SingleBTS bts1 = null;
+ SingleBTS bts2 = null;
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ bts1 = null;
+ bts2 = null;
+ for (SingleBTS bts : map[x][y]) {
+ if (bts.ARFCN == ARFCN1) {
+ bts1 = bts;
+ }
+ if (bts.ARFCN == ARFCN2) {
+ bts2 = bts;
+ }
+ }
+ // check if both BTS were found
+ if (bts1 != null && bts2 != null) {
+ // make the output. Only Downlink possible!
+ fw.append((bts1.getDldB() - bts2.getDldB())
+ + " "
+ + (bts1.getDLmW() - bts2.getDLmW())
+ + " "
+ + (bts1.getDldB() / bts2.getDldB())
+ + " "
+ + (bts1.getDLmW() / bts2.getDLmW())
+ + " "
+ + bts1.getDldB()
+ + " "
+ + bts2.getDldB()
+ + " "
+ + (bts1.getStrictDLdBAverage() - bts2
+ .getStrictDLdBAverage())
+ + " "
+ + (bts1.getStrictDLdBAverage() / bts2
+ .getStrictDLdBAverage())
+ + " "
+ + (10 * Math.log10(bts2.getDLmW() / bts1.getDLmW()))
+ + "\r\n");
+
+ }
+ }
+ }
+ fw.close();
+
+ }
+
+ /**
+ * removes outliers in each MR. Needs average() first. Otherwise each
+ * SingleBTS only holds one MR!
+ */
+ public void removeOutlier() {
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ for (int z = 0; z < map[x][y].size(); z++) {
+ map[x][y].get(z).removeOutlier();
+ }
+
+ }
+ }
+
+ }
+
+ public double getDistance(int x1, int x2, int y1, int y2) {
+ return helper.Distance.calc(Ycoords[y1], Xcoords[x1], Ycoords[y2],
+ Xcoords[x2]);
+
+ }
+
+ /**
+ * Extrapolations the map. For every Point a square eith size size*size is
+ * examined. A log function gets derived and the current point is calculated
+ *
+ * @param size
+ * @return not yet implemented
+ */
+ public boolean extrapolate(int size) {
+ matrixsize = size;
+ // System.out
+ // .println("WARNING: not correct implemented. map overrides buffer. Therefor UL-part of existing BTSs in map where only DL is available will not be stored");
+ // this might not be a problem: on places where a DL exists but no UL,
+ // the phone will always connect to the better cell, so a UL will
+ // actually never be received (only partyl correct)
+
+ // create buffer to store extrapolation
+ // buffer = new ArrayList[map.length][map[0].length];//not needed
+ // initialize
+ // for (int map2X = 0; map2X < buffer.length; map2X++) {
+ // for (int map2Y = 0; map2Y < buffer[0].length; map2Y++) {
+ // buffer[map2X][map2Y] = new ArrayList<SingleBTS>();
+ // }
+ // }
+
+ // take one of the BTS from the sql table arfcn
+ // traverse every place of the map
+ // try if extrapolation is needed or possible
+ // boundary of 3
+
+ // do RZ-GSM BTS first
+ for (SingleBTS extrapolateThis : btsnames) {
+ for (int x = size; x < Xcoords.length - size; x++) {
+ for (int y = size; y < Ycoords.length - size; y++) {
+ checkAndDoExtrapolation(x, y, extrapolateThis);
+ }
+ }
+ }
+
+ // do foreign BTS afterwards
+
+ // unset interpolated flag to prepare for new run. This means that
+ // getSurrounding will get the newly interpolated MR in the next run
+ unsetInterpolated();
+
+ for (SingleBTS extrapolateThis : contentForeignBTS()) {
+ for (int x = size; x < Xcoords.length - size; x++) {
+ for (int y = size; y < Ycoords.length - size; y++) {
+ extrapolateForeignDL(x, y, extrapolateThis);
+ }
+ }
+ }
+
+ // now do the extrapolation for foreign BTS. Calculate a delta between
+ // two BTS
+ // extrapolateForeign();
+
+ return false;
+ }
+
+ /*
+ * private void extrapolateForeign() { SingleBTS[] foreign =
+ * contentForeignBTS(); for (SingleBTS extrapolateThis : foreign) { for (int
+ * x = 2; x < Xcoords.length - 2; x++) { for (int y = 2; y < Ycoords.length
+ * - 2; y++) { for (int i = 0; i < directions.values().length; i++) {
+ * extrapolateForeignDL(directions.values()[i], x, y, extrapolateThis); } }
+ * }
+ *
+ * }
+ *
+ * }
+ */
+
+ /**
+ *
+ * @param direction
+ * which direction to extrapolate
+ * @param x
+ * map coordinate
+ * @param y
+ * map coordinate
+ * @param extrapolateThis
+ * BTS to extrapolate
+ */
+ private void extrapolateForeignDL(int x, int y, SingleBTS extrapolateThis) {
+ SingleBTS bts1 = null;
+ SingleBTS bts2 = null;
+ for (int i = 0; i < directions.values().length; i++) {
+ directions direction = directions.values()[i];
+ switch (direction) {
+ case DOWN:
+ bts1 = ListBTS.getARFCN(map[x - 1][y], extrapolateThis);
+ bts2 = ListBTS.getARFCN(map[x - 2][y], extrapolateThis);
+ break;
+ case UP:
+ bts1 = ListBTS.getARFCN(map[x + 1][y], extrapolateThis);
+ bts2 = ListBTS.getARFCN(map[x + 2][y], extrapolateThis);
+ break;
+ case LEFT:
+ bts1 = ListBTS.getARFCN(map[x][y - 1], extrapolateThis);
+ bts2 = ListBTS.getARFCN(map[x][y - 2], extrapolateThis);
+ break;
+ case RIGHT:
+ bts1 = ListBTS.getARFCN(map[x][y + 1], extrapolateThis);
+ bts2 = ListBTS.getARFCN(map[x][y + 2], extrapolateThis);
+ break;
+ case UPLEFT:
+ bts1 = ListBTS.getARFCN(map[x][y + 1], extrapolateThis);
+ bts2 = ListBTS.getARFCN(map[x][y + 2], extrapolateThis);
+ break;
+ default:
+ break;
+ }
+ // do interpolation. Average extrapolated bts between all.
+ insertForeignBTS(x, y, bts1, bts2, extrapolateThis);
+
+ }
+
+ }
+
+ /**
+ * Gets two BTS values, extrapolates from bts1 to bts2 and then guesses
+ * bts3. Bts3 gets updated or inserted into map[x][y].
+ *
+ * @param x
+ * @param y
+ * @param bts1
+ * @param bts2
+ * @param extrapolateThis
+ */
+ private void insertForeignBTS(int x, int y, SingleBTS bts1, SingleBTS bts2,
+ SingleBTS extrapolateThis) {
+ // boolean contains = ListBTS.contains(map[x][y], extrapolateThis);
+ // check if map[x][y]already contains the corresponding bts
+ if (bts1 == null || bts2 == null)
+ return; // nothing one can do
+ SingleBTS update = null;
+ if (ListBTS.contains(map[x][y], extrapolateThis)) {
+ if (!ListBTS.getARFCN(map[x][y], extrapolateThis).isInterpolated()) {
+ return;// is already measured! Do not change!
+ }
+ // map[x][y] contains a corresponding bts that is interpolated.
+ // update it
+ update = ListBTS.removeARFCN(map[x][y], extrapolateThis);
+
+ } else {
+ update = new SingleBTS(extrapolateThis.ARFCN, extrapolateThis.name);
+
+ }
+ update.interpolated.add(true);
+ // TODO: völlig falsch hier!!!
+ double DL = bts1.getDldB() + bts2.getDldB();
+ DL = DL / 2d;
+ update.addDl(DL);
+ // insert into map[x][y]
+ map[x][y].add(update);
+
+ }
+
+ /**
+ * adds a new boolean value (false) to each SingleBTS. A new extrapolation
+ * round starts. This means, that extrapolated BTS from the last run may now
+ * be used for extrapolation
+ */
+ private void unsetInterpolated() {
+ for (int x = 0; x < map.length; x++) {
+ for (int y = 0; y < map[0].length; y++) {
+ for (int z = 0; z < map[x][y].size(); z++) {
+ map[x][y].get(z).interpolated.add(false);
+ }
+ }
+ }
+
+ }
+
+ public boolean hasAMeasurement(int x, int y) {
+ boolean result = !(map[x][y] == null || map[x][y].isEmpty());
+ return result;
+ }
+
+ public boolean[][] getAllocation() {
+ boolean[][] result = new boolean[Xcoords.length][Ycoords.length];
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ result[x][y] = hasAMeasurement(x, y);
+ }
+ }
+ return result;
+ }
+
+ public long countTilesWMeasures() {
+ boolean[][] allocation = getAllocation();
+ long count = 0;
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ if (allocation[x][y])
+ count++;
+ }
+
+ }
+ return count;
+ }
+
+ /*
+ * private void merge() { for (int x = 0; x < map.length; x++) { for (int y
+ * = 0; y < map[0].length; y++) { if (map[x][y] != null &&
+ * !map[x][y].isEmpty()) { buffer[x][y] = map[x][y]; } } } map = buffer;
+ *
+ * }
+ */
+
+ /**
+ * Checks what kind of extrapolation is needed, if any
+ *
+ * @param x
+ * Coordinate in GSM map
+ * @param y
+ * Coordinate in GSM map
+ * @param extrapolateThis
+ * what BTS should be interpolated
+ */
+ private void checkAndDoExtrapolation(int x, int y, SingleBTS extrapolateThis) {
+ // check current x/y coordinate if extrapolateThis is existing
+ if (helper.ListBTS.contains(map[x][y], extrapolateThis)) {
+ if (helper.ListBTS.containsUL(map[x][y], extrapolateThis)) {
+ return; // nothing to do
+ }
+ // only uplink must be interpolated
+ tryExtrapolateUL(x, y, extrapolateThis);
+ } else {
+ tryExtrapolateDL(x, y, extrapolateThis);
+ // uplink and downlink must be interpolated.
+ // only downlink here. it the next run, the uplink will be
+ // interpolated
+ }
+
+ }
+
+ private boolean tryExtrapolateUL(int x, int y, SingleBTS extrapolateThis) {
+ // check if extrapolateThis is a foreign BTS
+ if (isForeign(extrapolateThis)) {
+ // extrapolateThis is not a RZ-GSM BTS. Uplink not available
+ return false;
+ }
+
+ // TODO: create copy of map. Place Extrapolation inside of this copy.
+ // Merge both at the end
+ // get Distance of this place to coordinates in extrapolateThis
+ double xval = helper.Distance.calc(extrapolateThis.coordinate,
+ getCoord(x, y));
+ ArrayList<SingleBTS> surrounding = getSurrounding(x, y, matrixsize,
+ extrapolateThis);
+
+ // create empty array
+
+ // do extrapolation
+ if (surrounding != null && !surrounding.isEmpty()) {
+ SingleBTS extrapolated = helper.Extrapolate.extrapolateLogUL(
+ surrounding, xval, extrapolateThis, 49);
+ if (extrapolated == null) {
+ return false;
+ } else {
+ // take out the extrapolated BTS from map. Update UL,
+ // reintegrate
+ SingleBTS element = helper.ListBTS.removeARFCN(map[x][y],
+ extrapolateThis);
+ element.addUl(extrapolated.getUldB());
+ element.interpolated.add(true);
+ element.distance = xval;
+ map[x][y].add(element);
+ // buffer[x][y].add(element);
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private boolean tryExtrapolateDL(int x, int y, SingleBTS extrapolateThis) {
+
+ // if (isForeign(extrapolateThis)) {
+ // do interpolation step by step because distances to corresponding
+ // BTS is unknown.
+ // eight directions and some special cases
+ // extrapolateForeignDL(x, y, extrapolateThis);
+ // return true;
+ // }
+
+ // TODO: create copy of map. Place Extrapolation inside of this copy.
+ // Merge both at the end
+ // get x/y Distance to corresponding this BTS
+
+ // extrapolate to value of x:
+ // double xval = helper.Distance.calc(extrapolateThis.coordinate.coord1,
+ // extrapolateThis.coordinate.coord2, Ycoords[y], Xcoords[x]);
+ double xval = helper.Distance.calc(extrapolateThis.coordinate,
+ getCoord(x, y));
+
+ ArrayList<SingleBTS> surrounding = getSurrounding(x, y, matrixsize,
+ extrapolateThis);
+ SingleBTS extrapolated = helper.Extrapolate.extrapolateLogDL(
+ surrounding, xval, extrapolateThis, 44);
+
+ // add extrapolated BTS to GSM map only if not null. Add distance
+ if (extrapolated != null) {
+ extrapolated.distance = xval;
+ extrapolated.interpolated.add(true);
+ map[x][y].add(extrapolated);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Copies all SingleBTS of given surrounding into one linked list. If a
+ * Measurement was newly interpolated, it will be ignored and not added to
+ * the list
+ *
+ * @param x
+ * GSM map coordinate
+ * @param y
+ * GSm map coordinate
+ * @param size
+ * size of matrix where size specifies length and width. must be
+ * unequal
+ * @param extrapolateThis
+ * indicates which BTS.arfcn should be taken. Only matching
+ * arfcn's are copied to the list
+ * @return linked list with all bts in that area. Null if no matching BTS
+ * where found
+ */
+ private ArrayList<SingleBTS> getSurrounding(int x, int y, int size,
+ SingleBTS extrapolateThis) {
+ int max = (size - 1) / 2;
+ ArrayList<SingleBTS> list = new ArrayList<SingleBTS>();
+ // int max_x = map.length;
+ // int max_y = map[0].length;
+ for (int i = -1 * ((size - 1) / 2); i <= max; i++) {
+ for (int j = -1 * ((size - 1) / 2); j <= max; j++) {
+ // check boundaries
+ if (x + i > 0 && x + i < map.length && y + j > 0
+ && y + j < map[0].length) {
+ for (SingleBTS element : map[x + i][y + j]) {
+ if (element.ARFCN == extrapolateThis.ARFCN
+ && !element.newlyInterpolated()) {
+ // Boundaries okay, arfcn okay, was not interpolated
+ // in the last run
+ list.add(element);
+ }
+ }
+ }
+ }
+ }
+ // remove null elements
+ return helper.ListBTS.removeNullElements(list);
+
+ }
+
+ /**
+ * returns true if the BTS arfcn is not part of the RZ-GSM. Note that no
+ * check is done if arfcn is contained within the map
+ *
+ * @param arfcn
+ * which BTS to check
+ * @return True if arfcn is foreign. That means it is not part of the RZ-GSM
+ */
+ public boolean isForeign(SingleBTS arfcn) {
+ return (!ListBTS.contains(Arrays.asList(btsnames), arfcn));
+ }
+
+ /**
+ *
+ * @param MRlist
+ * Live MR from SQL database or List of Measurements to search
+ * @param thresholddBm
+ * take each MR +/- threshold_dB. Elements that are within
+ * threshold_dB get returned
+ * @return Coordinates that match to ANY of the provided MR, not to all! It
+ * is not the intersection!
+ */
+ public ArrayList<GPScoordinate> find(List<SingleBTS> MRlist,
+ double thresholddBm) {
+ // check if map got averaged
+ if (!isAveraged) {
+ System.out.println("Needs Average first!");
+ return null; // mabye average the MRlist first?
+ }
+
+ LinkedList<GPScoordinate> result = new LinkedList<GPScoordinate>();
+ // Iterator over MRlist
+ Iterator<SingleBTS> itr = MRlist.iterator();
+ while (itr.hasNext()) {
+ SingleBTS MR = itr.next();
+ result.addAll(find(MR, thresholddBm));
+ }
+ return new ArrayList<GPScoordinate>(result);
+
+ }
+
+ /**
+ *
+ * @param MR
+ * One measurement point
+ * @param thresholddBm
+ * search within this threshold_dB for coordinates
+ * (threshold_dB+/-MR)
+ * @return coordinates that match to the MR
+ */
+ public ArrayList<GPScoordinate> find(SingleBTS MR, double thresholddBm) {
+ LinkedList<GPScoordinate> result = new LinkedList<GPScoordinate>();
+ SingleBTS reference;
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ if (helper.ListBTS.contains(map[x][y], MR)) {
+ // test DL first
+ reference = helper.ListBTS.getARFCN(map[x][y], MR);
+ if ((reference.getDldB() + thresholddBm > MR.getDldB())
+ && (MR.getDldB() > reference.getDldB()
+ - thresholddBm)) {
+ // the MR fits with this coordinate
+ result.add(getCoord(x, y));
+ }
+ // test UL
+ reference = helper.ListBTS.getARFCN(map[x][y], MR);
+ if ((reference.getUldB() + thresholddBm > MR.getUldB())
+ && (MR.getUldB() > reference.getUldB()
+ - thresholddBm)) {
+ // the MR fits with this coordinate
+ result.add(getCoord(x, y));
+ }
+
+ }
+ }
+ }
+ return new ArrayList<GPScoordinate>(result);
+ }
+
+ public void merge(GSMMap map2) {
+ // TODO: check & possible increase boundaries first!
+ for (int x = 0; x < map2.Xcoords.length; x++) {
+ for (int y = 0; y < map2.Ycoords.length; y++) {
+ add(map2.getCoord(x, y), map2.map[x][y]);
+ average();
+ }
+ }
+ }
+
+ private enum directions {
+ UP, DOWN, LEFT, RIGHT, UPLEFT, UPRIGHT, DOWNRIGHT, DOWNLEFT, LEFTRIGHT, UPDOWN
+ }
+
+ public enum PaintEnum {
+ variance, UL, DL, DLexpected, BERSubUL, BERSubDL, OverallCoverageDL, OverallCoverageBER
+ }
+
+ @Override
+ public void paint(Graphics2D g, JXMapViewer OSmap, int w, int h) {
+ // TODO Auto-generated method stub
+ g = (Graphics2D) g.create();
+ g.setColor(Color.BLACK);
+ g.drawString(whatToPaint.toString(), 50, 30);
+ // convert from viewport to world bitmap
+ Rectangle rect = ((org.jdesktop.swingx.JXMapViewer) OSmap)
+ .getViewportBounds();
+ g.translate(-rect.x, -rect.y);
+
+ // draw each rectangle
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ SingleBTS current = ListBTS.getARFCN(map[x][y],
+ content()[indexToPaint]);
+ if (current != null
+ || whatToPaint == PaintEnum.OverallCoverageDL
+ || whatToPaint == PaintEnum.OverallCoverageBER) {
+ // if (hasAMeasurement(x, y)) {
+ // try {
+ // draw it
+ double coordX = Xcoords[x];
+ double coordY = Ycoords[y];
+ // double accuracy = accuracy;
+ Polygon tile = new Polygon();
+
+ GeoPosition pos1 = new GeoPosition(coordY - accuracy / 2,
+ coordX + accuracy / 2);
+ GeoPosition pos2 = new GeoPosition(coordY + accuracy / 2,
+ coordX + accuracy / 2);
+ GeoPosition pos3 = new GeoPosition(coordY + accuracy / 2,
+ coordX - accuracy / 2);
+ GeoPosition pos4 = new GeoPosition(coordY - accuracy / 2,
+ coordX - accuracy / 2);
+ Point2D pt1 = OSmap.getTileFactory().geoToPixel(pos1,
+ OSmap.getZoom());
+ Point2D pt2 = OSmap.getTileFactory().geoToPixel(pos2,
+ OSmap.getZoom());
+ Point2D pt3 = OSmap.getTileFactory().geoToPixel(pos3,
+ OSmap.getZoom());
+ Point2D pt4 = OSmap.getTileFactory().geoToPixel(pos4,
+ OSmap.getZoom());
+
+ // finally, draw it!
+ tile.addPoint((int) pt1.getX(), (int) pt1.getY());
+ tile.addPoint((int) pt2.getX(), (int) pt2.getY());
+ tile.addPoint((int) pt3.getX(), (int) pt3.getY());
+ tile.addPoint((int) pt4.getX(), (int) pt4.getY());
+ // Depending to what is set in whatToPaint
+ Color color = null;
+ if (whatToPaint == PaintEnum.DL) {
+ color = getColordB((int) current.getDldB());
+
+ } else if (whatToPaint == PaintEnum.DLexpected) {
+ // color = getColorStd(current.getVarianceDLdB());
+ color = getColordB((int) current.getStrictDLdBAverage());
+ } else if (whatToPaint == PaintEnum.variance) {
+ color = getColorStd(current.getTrueVarianceDLdB());
+ } else if (whatToPaint == PaintEnum.BERSubUL) {
+ if (current.ulQsub.isEmpty() || current.getULQsub() < 0)
+ continue;
+ color = getColorBER(current.getULQsub());
+ } else if (whatToPaint == PaintEnum.BERSubDL) {
+ if (current.dlQsub.isEmpty() || current.getDLQsub() < 0)
+ continue;
+ color = getColorBER(current.getDLQsub());
+ } else if (whatToPaint == PaintEnum.OverallCoverageDL
+ && hasAMeasurement(x, y)) {
+ SingleBTS bts1 = ListBTS.getARFCN(map[x][y], 880);
+ SingleBTS bts2 = ListBTS.getARFCN(map[x][y], 877);
+ if (bts1 != null && bts2 != null) {
+ // double bts1 = ListBTS.getARFCN(map[x][y],
+ // 880).getStrictDLdBAverage();
+ color = getColordB((int) Math.max(
+ bts1.getStrictDLdBAverage(),
+ bts2.getStrictDLdBAverage()));
+ } else if (bts2 != null) {
+ color = getColordB((int) bts2
+ .getStrictDLdBAverage());
+ } else if (bts1 != null) {
+ color = getColordB((int) bts1
+ .getStrictDLdBAverage());
+ }
+ } else if (whatToPaint == PaintEnum.OverallCoverageBER
+ && hasAMeasurement(x, y)) {
+ SingleBTS bts1 = ListBTS.getARFCN(map[x][y], 880);
+ SingleBTS bts2 = ListBTS.getARFCN(map[x][y], 877);
+ if (bts1 != null && bts2 != null) {
+ // double bts1 = ListBTS.getARFCN(map[x][y],
+ // 880).getStrictDLdBAverage();
+ color = getColorBER((int) Math.max(
+ bts1.getULQsub(), bts2.getULQsub()));
+ } else if (bts2 != null) {
+ color = getColorBER((int) bts2.getULQsub());
+ } else if (bts1 != null) {
+ color = getColorBER((int) bts1.getULQsub());
+ }
+ }
+ if (color != null) {
+ g.setColor(color);
+ g.fill(tile);
+ // g.setColor(Color.black);
+ // g.draw(tile);
+ // g.draw(tile);
+ }
+ try {
+ // Messungen schwarz umranden
+ if (!current.isInterpolated()) {
+ // g.setColor(Color.BLACK);
+ // g.draw(tile);
+ }
+ } catch (NullPointerException e) {
+
+ }
+
+ }
+ }
+ }
+ g.dispose();
+ }
+
+ private Color getColorBER(double dlQ) {
+ // between 0...7
+ int green = 0;
+ int red = 0;
+ if (dlQ < 3.5) {
+ green = 255;
+ red = (int) (255 * (dlQ / 3.5));
+ } else {
+ red = 255;
+ green = 255 - ((int) (255 * ((dlQ - 3.5) / 3.5)));
+ if (green < 0)
+ green = 0;
+ }
+
+ if (green < 0 || red < 0)
+ return null;
+
+ if (green > 255)
+ green = 255;
+ if (red > 255)
+ red = 255;
+
+ return new Color(red, green, 0, 185);
+ }
+
+ private Color getColordB(int strength) {
+
+ int green = 0;
+ int red = 0;
+ // yellow at -75
+ if (strength > -75) {
+ green = 255;
+ red = 256 - Math.abs((256 / 28) * (-75 - strength));
+
+ } else {
+ // transient green from now on
+ red = 255;
+ green = Math.abs((256 / 34) * (-110 - strength));
+ }
+ // int green = 256 - Math.abs((256 / 90) * (-120 - strength));
+ // int red = Math.abs((256 / 90) * (-120 - strength));
+ // int result = red << 24 | green
+ if ((green > 255) || (red > 255))
+ System.out.println("Zu groß bei strength= " + strength + ",Rot: "
+ + red + "Grün: " + green);
+ if (green > 255)
+ green = 255;
+ if (red > 255)
+ red = 255;
+ // return ("7f00" + Integer.toHexString(red) +
+ // Integer.toHexString(green));
+ // return ("ff00" + Integer.toHexString(red) +
+ // Integer.toHexString(green));
+ // return ("ff00" + Integer.toHexString(red) +
+ // Integer.toHexString(green));
+
+ Color result = new Color(red, green, 0, 185);
+
+ // return ("ff00" + Integer.toHexString(green) +
+ // Integer.toHexString(red));
+ return result;
+
+ }
+
+ private Color getColorStd(double var) {
+
+ double std = Math.sqrt(var);
+ // Std between 0...7
+ int green = 0;
+ int red = 0;
+ if (std < 3.5) {
+ green = 255;
+ red = (int) (255 * (std / 3.5));
+ } else {
+ red = 255;
+ green = 255 - ((int) (255 * ((std - 3.5) / 3.5)));
+ if (green < 0)
+ green = 0;
+ }
+ if (green > 255)
+ green = 255;
+ if (red > 255)
+ red = 255;
+
+ return new Color(red, green, 0, 185);
+ }
+
+ @SuppressWarnings("unused")
+ private Color getColorVar(double var) {
+ // let var be between 0 and 40
+ // 0...5: only a shade of green
+ // 5...15: between green and red
+ // 15...20: red
+ double middle = 25;
+
+ int green = 0;
+ int red = 0;
+ if (var < middle) {
+ green = 255;
+ red = (int) (255 * (var / middle));
+ } else {
+ red = 255;
+ green = 255 - ((int) (255 * ((var - middle) / middle)));
+ if (green < 0)
+ green = 0;
+ }
+ if (green > 255)
+ green = 255;
+ if (red > 255)
+ red = 255;
+
+ if (var > 20) {
+ // System.out.println("Brakepoiint");
+ }
+
+ return new Color(red, green, 0, 185);
+ }
+
+}
+
+final class MapHelper {
+ static public double getMaxX(GPScoordinate[] gps, double offset) {
+ double max = -181;
+ for (GPScoordinate current : gps) {
+ if (current.coord2 > max)
+ max = current.coord2;
+ }
+ return max;
+ // return max + offset;
+
+ }
+
+ static public double getMinX(GPScoordinate[] gps, double offset) {
+ double min = 181;
+ for (GPScoordinate current : gps) {
+ if (current.coord2 < min)
+ min = current.coord2;
+ }
+ return min;
+ // return min - offset;
+ }
+
+ static public double getMaxY(GPScoordinate[] gps, double offset) {
+ double max = -181;
+ for (GPScoordinate current : gps) {
+ if (current.coord1 > max)
+ max = current.coord1;
+ }
+ return max;
+ // return max + offset;
+ }
+
+ static public double getMinY(GPScoordinate[] gps, double offset) {
+ double min = 181;
+ for (GPScoordinate current : gps) {
+ if (current.coord1 < min)
+ min = current.coord1;
+ }
+ return min;
+ // return min - offset;
+ }
+
+ static public double[] createArray(double begin, double end, double accuracy) {
+ // add 1 to make sure even the last measurement fits in and doesn't
+ // through index out of bounds!
+ int size = (int) Math.ceil((end - begin) / accuracy) + 1;
+ double[] array = new double[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = i * accuracy + begin;
+ }
+ return array;
+ }
+
+ /**
+ * ListBTS all the unique SingleBTS's that occur in this list
+ *
+ * @param list
+ * ListBTS with SingleBTS's
+ * @return Array with the unique SingleBTS's. That is, every BTS in this
+ * Array occurs also in the list. Null if the list was empty
+ */
+ static SingleBTS[] content(ArrayList<SingleBTS> list) {
+ // get first element of list.
+ // traverse list and delete every occurence of first element
+ // get next element
+ // copy list to destroy reference
+ ArrayList<SingleBTS> list2 = (ArrayList<SingleBTS>) list.clone();
+ if (list2.isEmpty())
+ return null;
+ // int count = 0;
+ ArrayList<SingleBTS> output = new ArrayList<SingleBTS>();
+ while (!list2.isEmpty()) {
+ SingleBTS bts = list2.get(0);
+ list2.remove(0);
+ output.add(bts);
+ // remove the just added bts from the BTS-list
+ for (int i = 0; i < list2.size(); i++) {
+ if (list2.get(i).ARFCN == bts.ARFCN) {
+ list2.remove(i);
+ i--;
+
+ }
+
+ }
+
+ }
+ return output.toArray(new SingleBTS[1]);
+ }
+}
diff --git a/DataStructure/GSMMapInterpolatorOld.java b/DataStructure/GSMMapInterpolatorOld.java
new file mode 100644
index 0000000..eff8057
--- /dev/null
+++ b/DataStructure/GSMMapInterpolatorOld.java
@@ -0,0 +1,200 @@
+package DataStructure;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import Parse.sqlreader;
+
+@SuppressWarnings("serial")
+public class GSMMapInterpolatorOld extends GSMMap {
+
+ public GSMMapInterpolatorOld(sqlreader SQL, double accuracy) {
+ super(SQL, accuracy);
+ // TODO Auto-generated constructor stub
+ }
+
+ public void interpolate() {
+ for (SingleBTS currentBTS : this.btsnames) {
+ // go through every known BTS
+ interpolateBTS(currentBTS);
+
+ }
+ }
+
+ private void interpolateBTS(SingleBTS currentBTS) {
+ // add security bounds
+ for (int x = 2; x < this.Xcoords.length - 2; x++) {
+ for (int y = 2; y < this.Ycoords.length - 2; y++) {
+ // check if interpolation is needed
+ if (!InterpolateHelper.listContains(currentBTS, this.map[x][y])) {
+ // try to interpolate
+ SingleBTS interpolated = tryInterpolation(currentBTS, x, y);
+ if (interpolated != null)
+ // maybe the list is empty. then create list
+ if (map[x][y] == null) {
+ ArrayList<SingleBTS> list = new ArrayList<SingleBTS>();
+ list.add(interpolated);
+ map[x][y] = list;
+ } else {
+ map[x][y].add(interpolated);
+ }
+
+ }
+
+ }
+ }
+
+ }
+
+ private SingleBTS tryInterpolation(SingleBTS btsName, int x, int y) {
+ int interpolated = 0;
+ // do interpolation for left,right,up,down
+ SingleBTS left = interpolate1to2(btsName, x - 2, x - 1, y, y);
+ SingleBTS right = interpolate1to2(btsName, x + 2, x + 1, y, y);
+ SingleBTS down = interpolate1to2(btsName, x, x, y + 2, y + 1);
+ SingleBTS up = interpolate1to2(btsName, x, x, y - 2, y - 1);
+ SingleBTS between = interpolateInBetween(btsName, x, y);
+ if (left != null)
+ interpolated++;
+ if (right != null)
+ interpolated++;
+ if (down != null)
+ interpolated++;
+ if (up != null)
+ interpolated++;
+ if (between != null)
+ interpolated++;
+ if (interpolated > 1) {
+ // interpolation successfull!
+ SingleBTS element = new SingleBTS(btsName.ARFCN, 0, 0, true,
+ new Date(), btsName.name);
+ // prepare element for averaging
+ element.clear();
+ // nothing bad will happen if one of these BTSs are null!
+ element.addBTSMeasure(left);
+ element.addBTSMeasure(right);
+ element.addBTSMeasure(down);
+ element.addBTSMeasure(up);
+ element.addBTSMeasure(between);
+ if (element.getDldB() > -121 && element.getUldB() > -121)
+ if (element.getDldB() < -29 && element.getUldB() < -29)
+ return element;
+
+ }
+ return null;
+
+ }
+
+ private SingleBTS interpolate1to2(SingleBTS btsName, int x1, int x2,
+ int y1, int y2) {
+
+ SingleBTS first = InterpolateHelper.getFromList(btsName, map[x1][y1]);
+ SingleBTS second = InterpolateHelper.getFromList(btsName, map[x2][y2]);
+ // prepare returning BTS
+
+ if (first != null && second != null) {
+ // interpolation for these two elements possible
+ double deltaDL = second.getDldB() - first.getDldB();
+ double deltaUL = second.getUldB() - first.getUldB();
+ // add the value of log10(0.005). one Array cell is 5*5m big! See
+ // the
+ // Youngs Model!
+
+ // TODO: careful! double gets castet to int. Do correct
+ // interpolation here!
+
+ double DL = deltaDL + second.getDldB();
+ double UL = deltaUL + second.getUldB();
+ SingleBTS element = new SingleBTS(first.ARFCN, (int) UL, (int) DL,
+ true, new Date(), first.name);
+ // first.interpolated = true;
+ return element;
+ }
+
+ return null;
+ }
+
+ private SingleBTS interpolateInBetween(SingleBTS btsName, int x, int y) {
+ // take one from the left, one from the right
+ // one from the top, one from the bottom
+ // one from the diagonal and one from the other diagonal
+ // prepare interpolated element!
+ SingleBTS element = new SingleBTS(btsName.ARFCN, 0, 0, true,
+ new Date(), btsName.name);
+ element.clear();
+
+ // to check if a correct interpolation was done
+ boolean[] done = { false, false, false, false };
+
+ // diagonal leftAndRight
+ SingleBTS first = InterpolateHelper.getFromList(btsName,
+ map[x - 1][y + 1]);
+ SingleBTS third = InterpolateHelper.getFromList(btsName,
+ map[x + 1][y - 1]);
+ if (first != null && third != null) {
+ element.addBTSMeasure(first);
+ element.addBTSMeasure(third);
+ done[0] = true;
+ }
+
+ // diagonal rightAndLeft
+ first = InterpolateHelper.getFromList(btsName, map[x + 1][y + 1]);
+ third = InterpolateHelper.getFromList(btsName, map[x - 1][y - 1]);
+ if (first != null && third != null) {
+ element.addBTSMeasure(first);
+ element.addBTSMeasure(third);
+ done[1] = true;
+ }
+
+ // leftAndRight
+ first = InterpolateHelper.getFromList(btsName, map[x - 1][y]);
+ third = InterpolateHelper.getFromList(btsName, map[x + 1][y]);
+ if (first != null && third != null) {
+ element.addBTSMeasure(first);
+ element.addBTSMeasure(third);
+ done[2] = true;
+ }
+
+ // bottomAndTop
+ first = InterpolateHelper.getFromList(btsName, map[x][y + 1]);
+ third = InterpolateHelper.getFromList(btsName, map[x][y - 1]);
+ if (first != null && third != null) {
+ element.addBTSMeasure(first);
+ element.addBTSMeasure(third);
+ done[3] = true;
+ }
+
+ // return the BTS only if at least one Interpolation worked out
+ for (int i = 0; i < done.length; i++) {
+ if (done[i])
+ return element;
+ }
+ return null;
+
+ }
+}
+
+final class InterpolateHelper {
+
+ public static boolean listContains(SingleBTS bts, List<SingleBTS> btsList) {
+ for (SingleBTS listBTS : btsList) {
+ if (bts.ARFCN == listBTS.ARFCN)
+ return true;
+ }
+ return false;
+ }
+
+ // get the Element containing the ARFCN of btsName. Returns null, if no
+ // Element found!
+ public static SingleBTS getFromList(SingleBTS btsName,
+ List<SingleBTS> btslist) {
+ for (SingleBTS listBTS : btslist) {
+ if (listBTS.ARFCN == btsName.ARFCN)
+ return listBTS;
+
+ }
+ return null;
+ }
+
+}
diff --git a/DataStructure/GoogleOut.java b/DataStructure/GoogleOut.java
new file mode 100644
index 0000000..0d96e33
--- /dev/null
+++ b/DataStructure/GoogleOut.java
@@ -0,0 +1,598 @@
+package DataStructure;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class GoogleOut {
+ private BufferedWriter br;
+ private LinkedList<MeasurementReport> MRlog;
+ // private LinkedList<GPScoordinate> GPSlog;
+ private double accuracy = 0.00004;
+ private GSMMap map;
+ private double[] Xcoords;
+ private double[] Ycoords;
+ private String fileName;
+
+ public GoogleOut(GSMMap map, String fileName) {
+ this.map = map;
+ this.fileName = fileName;
+ }
+
+ // Constructor
+ public void write() throws IOException {
+ // this.map = map;
+ Xcoords = map.Xcoords;
+ Ycoords = map.Ycoords;
+ br = new BufferedWriter(new FileWriter(new File(fileName)));
+ writeHeader();
+
+ // Downlink
+ // write Folder and Polygons for each BTS in the database
+ SingleBTS[] btsNames = map.btsnames; // change here to plot e-plus bts
+ for (SingleBTS singleBTSDL : btsNames) {
+ if (map.contains(singleBTSDL)) {
+ // if the GSMmap contains at least one of this BTS, do it
+ writeFolderDesc(singleBTSDL, false);
+ writePlacemarks(singleBTSDL, false);
+ br.write("</Folder> \n");
+ }
+
+ }
+
+ // Uplink (RZ-GSM)
+ for (SingleBTS singleBTSDL : btsNames) {
+ if (map.contains(singleBTSDL)) {
+ // if the GSMmap contains at least one of this BTS, do it
+ writeFolderDesc(singleBTSDL, true);
+ writePlacemarks(singleBTSDL, true);
+ br.write("</Folder> \n");
+ }
+
+ }
+
+ // Downlink (foreign BTSs). Actually one could just change BTSnames =
+ // map.content() in the beginning
+ SingleBTS[] foreign = map.contentForeignBTS();
+ if (foreign != null) {
+ for (SingleBTS foreignBTS : foreign) {
+ writeFolderDesc(foreignBTS, false);
+ writePlacemarks(foreignBTS, false);
+ br.write("</Folder> \n");
+ }
+ }
+
+ br.write("</Document>");
+ br.write("</kml>");
+ br.flush();
+ br.close();
+ }
+
+ /**
+ * Writes Header for the folder: Foldername, Up/Downlink, LookAt,...
+ *
+ * @param btsname
+ * @param uplink
+ * @throws IOException
+ */
+ private void writeFolderDesc(SingleBTS btsname, boolean uplink)
+ throws IOException {
+ SingleBTS foundBTS = map.getFirstBTSmatch(btsname);
+ String upDown;
+ if (uplink)
+ upDown = "Uplink: ";
+ else
+ upDown = "Downlink: ";
+
+ // br.write("<open>1</open>\n");
+ br.write(" <Folder>\n");
+ br.write("<name>MR " + upDown + "" + btsname.ARFCN + ": "
+ + btsname.name + "</name>\n");
+ br.write(" <visibility>1</visibility>\n");
+ br.write("<description>MR from " + foundBTS.time.toString()
+ + "</description>\n");
+ br.write(" <LookAt>\n");
+ br.write("<longitude>" + (map.maxX + map.minX) / 2 + "</longitude>\n");
+ br.write("<latitude>" + (map.maxY + map.minY) / 2 + "</latitude>\n");
+ br.write("<altitude>0</altitude>\n");
+ br.write("<heading>0.0</heading>\n");
+ br.write("<tilt>0</tilt>\n");
+ br.write("<range>276.0</range>\n");
+ br.write("</LookAt>\n");
+
+ }
+
+ private void writePlacemarks(SingleBTS btsName, boolean uplink)
+ throws IOException {
+ // was a BTS written to file?
+ // Polygon Description for every Measured BTS
+ for (double gpsX : Xcoords) {
+ for (double gpsY : Ycoords) {
+ // because within GSMmap, every cell of the array is
+ // initialized, no null pointer exception will occur. only a
+ // empty list will be "thrown" but it doesn't hurt
+ ArrayList<SingleBTS> currentBTSList = map
+ .getBTSList(gpsX, gpsY);
+
+ // traverse the ListBTS to find out if a BTS with the current
+ // name
+ // exists on this coordinate. Tell if a BTS was written to file
+
+ writePlacemarkDetails(currentBTSList, btsName, gpsX, gpsY,
+ uplink);
+
+ }
+
+ }
+
+ // Polygon Coordinates
+ }
+
+ private void writePlacemarkDetails(List<SingleBTS> btsList,
+ SingleBTS btsName, double coordX, double coordY, boolean uplink)
+ throws IOException {
+ // if the current field was empty, so is the btsList. But still it is
+ // initilized, so there is no nullpointer exception!
+ String name;
+ for (SingleBTS singleBTS : btsList) {
+ // maybe its null, then continue with next
+ if (singleBTS == null)
+ continue;
+
+ // get correct output String for UL or DL
+ if (uplink)
+ name = singleBTS.ULtoString();
+ else
+ name = singleBTS.DLtoString();
+ // you can only draw uplink if you've got a FullBTS!
+ if ((singleBTS.ARFCN == btsName.ARFCN && (!uplink || singleBTS.fullBTS))) {
+ if (uplink)
+ name = singleBTS.ULtoString();
+ else
+ name = singleBTS.DLtoString();
+ // draw it!
+ br.write("<Placemark> \n");
+ br.write("<visibility>1</visibility>\n");
+ br.write("<name>" + name + "</name>\n");
+
+ writeStyleIdentifier(singleBTS, uplink);
+
+ br.write("<Polygon>\n");
+ br.write("<tessellate>1</tessellate>\n");
+ br.write("<outerBoundaryIs>\n");
+ br.write("<LinearRing>\n");
+ br.write("<coordinates>\n");
+
+ writePolygonCoordinates(coordX, coordY, map.accuracy);
+
+ br.write("</coordinates>\n");
+ br.write("</LinearRing>\n");
+ br.write("</outerBoundaryIs>\n");
+ br.write("</Polygon>\n");
+ br.write("</Placemark>\n");
+
+ // if (singleBTS.name.equals("neuer Name")) {
+ // System.out.print("hier! " + coordX + "/" + coordY);
+ // System.out.println(" Xcoord results to array "
+ // + map.searchBestX(coordX));
+ // }
+
+ }
+
+ }
+ }
+
+ private void writeStyleIdentifier(SingleBTS bts, boolean uplink)
+ throws IOException {
+ int btsRXvalue;
+ if (uplink)
+ btsRXvalue = (int) bts.getUldB();
+ else
+ btsRXvalue = (int) bts.getDldB();
+
+ if (bts.isInterpolated()) {
+ // no FullBTS but interpolated: draw black line("#I")
+ br.write("<styleUrl>#I" + btsRXvalue + "</styleUrl>\n");
+ } else if (bts.fullBTS) {
+ // show the nice FullBTS line around
+ br.write("<styleUrl>#F" + btsRXvalue + "</styleUrl>\n");
+ } else {
+ // no line
+ br.write("<styleUrl>#" + btsRXvalue + "</styleUrl>\n");
+ }
+
+ }
+
+ private void writePolygonCoordinates(double coordX, double coordY,
+ double accuracy) throws IOException {
+ double accuracyX = accuracy / 2;
+ double accuracyY = accuracy;
+ // Point 1
+ br.write(coordX - accuracyX + "," + coordY + accuracyY + ",0,\n");
+ // Point 2
+ br.write(coordX + accuracyX + "," + coordY + accuracyY + ",0,\n");
+ // Point3
+ br.write(coordX + accuracyX + "," + (coordY - accuracyY) + ",0,\n");
+ // Point4
+ br.write((coordX - accuracyX) + "," + (coordY - accuracyY) + ",0,\n");
+ // End: Point 1
+ br.write((coordX - accuracyX) + "," + coordY + accuracyY + ",0\n");
+
+ }
+
+ public GoogleOut(LinkedList<GPScoordinate> GPSlog,
+ LinkedList<MeasurementReport> MRlog, String fileName)
+ throws IOException {
+ this.MRlog = MRlog;
+ // this.GPSlog = GPSlog;
+
+ br = new BufferedWriter(new FileWriter(new File(fileName)));
+ // write header
+ writeHeader();
+ // write viewpoint
+ br.write("<open>1</open>");
+ br.write(" <Folder>");
+ br.write("<name>Measurement Report " + map.IMSI + "</name>");
+ br.write(" <visibility>1</visibility>");
+ br.write("<description>MR from " + GPSlog.getFirst().time.toString()
+ + "</description>");
+ br.write(" <LookAt>");
+ br.write("<longitude>" + GPSlog.getFirst().coord2 + "</longitude>");
+ br.write("<latitude>" + GPSlog.getFirst().coord1 + "</latitude>");
+ br.write("<altitude>0</altitude>");
+ br.write("<heading>-34.82469740081282</heading>");
+ br.write("<tilt>0</tilt>");
+ br.write("<range>276.7870053764046</range>");
+ br.write("</LookAt>");
+
+ // write content
+ int i = 0;
+ int discarded = 0;
+ Iterator<GPScoordinate> GPSitr = GPSlog.iterator();
+ while (GPSitr.hasNext()) {
+ GPScoordinate GPS = GPSitr.next();
+ MeasurementReport MR = MRlog.get(i);
+
+ // do nothing if Time is not valid
+ if (Math.abs(MR.time.getTime() - GPS.time.getTime()) < 3000) {
+
+ br.write("<Placemark> \n");
+ br.write("<visibility>1</visibility>");
+ br.write("<name>" + MR.toString() + "</name>");
+ // br.write("<PolyStyle>");
+ // br.write("<color>bf00ff00</color>");
+ // br.write("</PolyStyle>");
+
+ // dl: Downlink - Network to phone
+ // up: Uplink - Phone to Network (has better perception for some
+ // reason)
+ br.write("<styleUrl>#" + MRlog.get(i).getFirstBTSdl()
+ + "</styleUrl>");
+
+ br.write("<Polygon>");
+ br.write("<tessellate>1</tessellate>");
+ br.write("<outerBoundaryIs>");
+ br.write("<LinearRing>");
+ br.write("<coordinates>");
+ // Point 1
+ System.out.println("this should not be started anymore");
+ br.write(GPS.coord2 - accuracy + "," + GPS.coord1 + accuracy
+ + ",0,");
+ // Point 2
+ br.write(GPS.coord2 + accuracy + "," + GPS.coord1 + accuracy
+ + ",0,");
+ // Point3
+ br.write(GPS.coord2 + accuracy + "," + (GPS.coord1 - accuracy)
+ + ",0,");
+ // Point4
+ br.write((GPS.coord2 - accuracy) + ","
+ + (GPS.coord1 - accuracy) + ",0,");
+ // End: Point 1
+ br.write((GPS.coord2 - accuracy) + "," + GPS.coord1 + accuracy
+ + ",0");
+
+ br.write("</coordinates>");
+ br.write("</LinearRing>");
+ br.write("</outerBoundaryIs>");
+ br.write("</Polygon>");
+ br.write("</Placemark>\n");
+ } else {
+ discarded++;
+
+ }
+
+ i++;
+ }
+ br.write("</Folder>");
+ br.write("</Document>");
+ br.write("</kml>");
+ br.flush();
+ br.close();
+ System.out.println("Discarded Coordinates: " + discarded);
+
+ }
+
+ @SuppressWarnings("unused")
+ private int getMin() {
+ Iterator<MeasurementReport> itr = MRlog.iterator();
+ MeasurementReport current;
+ int min = 0;
+ while (itr.hasNext()) {
+ current = itr.next();
+ if (current.getFirstBTSul() < min)
+ min = current.getFirstBTSul();
+ }
+ return min;
+
+ }
+
+ @SuppressWarnings("unused")
+ private int getMax() {
+ Iterator<MeasurementReport> itr = MRlog.iterator();
+ MeasurementReport current;
+ int max = -999;
+ while (itr.hasNext()) {
+ current = itr.next();
+ if (current.getFirstBTSul() > max)
+ max = current.getFirstBTSul();
+ }
+ return max;
+ }
+
+ @SuppressWarnings("unused")
+ private int getSteps() {
+ Iterator<MeasurementReport> itr = MRlog.iterator();
+ int i = 0;
+ while (itr.hasNext()) {
+ itr.next();
+ i++;
+ }
+ return i;
+ }
+
+ @SuppressWarnings("unused")
+ private String toHex(int i) {
+ String out = Integer.toHexString(Math.abs(i));
+ if (out.length() == 4)
+ return (out + "000");
+ if (out.length() == 5)
+ return (out + "00");
+ if (out.length() == 6)
+ return (out + "0");
+ if (out.length() == 7)
+ return (out);
+ return out;
+
+ }
+
+ // strength -30 to -120
+ // yellow at -75
+ private String getColor(int strength) {
+ int green = 0;
+ int red = 0;
+ // yellow at -75
+ if (strength > -75) {
+ green = 255;
+ red = 256 - Math.abs((256 / 45) * (-75 - strength));
+
+ } else {
+ // transient green from now on
+ red = 255;
+ green = Math.abs((256 / 45) * (-120 - strength));
+ }
+ // int green = 256 - Math.abs((256 / 90) * (-120 - strength));
+ // int red = Math.abs((256 / 90) * (-120 - strength));
+ // int result = red << 24 | green
+ if ((green > 255) || (red > 255))
+ System.out.println("Zu groß bei strength= " + strength + ",Rot: "
+ + red + "Grün: " + green);
+ if (green > 255)
+ green = 255;
+ if (red > 255)
+ red = 255;
+ // return ("7f00" + Integer.toHexString(red) +
+ // Integer.toHexString(green));
+ // return ("ff00" + Integer.toHexString(red) +
+ // Integer.toHexString(green));
+ // return ("ff00" + Integer.toHexString(red) +
+ // Integer.toHexString(green));
+ return ("ff00" + Integer.toHexString(green) + Integer.toHexString(red));
+
+ }
+
+ private void writeHeader() throws IOException {
+ br.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ br.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
+ br.write(" <Document>\n");
+ br.write("<name>Measurement Report " + map.IMSI + "</name>\n");
+ br.write("<open>1</open>\n");
+
+ // style: color for signal strength from -30db to -120db
+ // color red = #FF0000 (16711680)
+ // color green = #00FF00 (65280)
+
+ // styles for normal BTS
+ for (int style = -30; style >= -120; style--) {
+
+ // int step = (16711680 - 65280) / getSteps();
+ // for (int i = getMin(); i <= getMax(); i++) {
+
+ br.write("<Style id=\"" + style + "\"> \n");
+ br.write("<PolyStyle> \n");
+ br.write("<color>" + getColor(style) + "</color> \n");
+ br.write("</PolyStyle> \n");
+ br.write("<LineStyle>\n");
+ // br.write("<color>" + getColor(style) + "</color>\n");
+ br.write("<color>" + 00000000 + "</color>\n");
+ br.write("</LineStyle>\n");
+ br.write("</Style> \n");
+ }
+
+ // styles for Full BTS: full white ffffff, no transparency:ff
+ for (int style = -30; style >= -120; style--) {
+ br.write("<Style id=\"F" + style + "\"> \n");
+ br.write("<PolyStyle> \n");
+ br.write("<color>" + getColor(style) + "</color> \n");
+ br.write("</PolyStyle> \n");
+ br.write("<LineStyle>\n");
+ // // br.write("<color>" + getColor(style) + "</color>\n");
+ br.write("<color>" + "ffffffff" + "</color>\n");
+ br.write("<width>2</width>\n");
+ br.write("</LineStyle>\n");
+ br.write("</Style> \n");
+ }
+
+ // styles for Interpolated BTS: full black 000000, no transparency:ff
+ for (int style = -30; style >= -120; style--) {
+ br.write("<Style id=\"I" + style + "\">\n");
+ br.write("<PolyStyle>\n");
+ br.write("<color>" + getColor(style) + "</color>\n");
+ br.write("</PolyStyle>\n");
+ br.write("<LineStyle>\n");
+ // br.write("<color>" + getColor(style) + "</color>\n");
+ br.write("<color>" + "ff000000" + "</color>\n");
+ br.write("<width>2</width>\n");
+ br.write("</LineStyle>\n");
+ br.write("</Style>\n");
+ }
+
+ }
+
+ /**
+ * Writes Probabilitymap to file.
+ *
+ * @param scoremap
+ * @param file
+ * @throws IOException
+ */
+ public void writeProbability(double[][] scoremap, String file)
+ throws IOException {
+ BufferedWriter br = new BufferedWriter(new FileWriter(new File(file)));
+ writeProbHeader(br);
+ for (int x = 0; x < map.Xcoords.length; x++) {
+ for (int y = 0; y < map.Ycoords.length; y++) {
+ if (scoremap[x][y] > 0) {
+ writeProbabilityLandmark(x, y, scoremap, br);
+ }
+ }
+ }
+ br.write("</Folder> \n");
+ br.write("</Document>");
+ br.write("</kml>");
+ br.flush();
+ br.close();
+ }
+
+ private void writeProbabilityLandmark(int x, int y, double[][] scoremap,
+ BufferedWriter br) throws IOException {
+ int score = (int) (scoremap[x][y] * 100);
+
+ br.write("<Placemark> \n");
+ br.write("<visibility>1</visibility>\n");
+ br.write("<name>" + score + "</name>\n");
+
+ br.write("<styleUrl>#" + score + "</styleUrl>\n");
+
+ br.write("<Polygon>\n");
+ br.write("<tessellate>1</tessellate>\n");
+ br.write("<outerBoundaryIs>\n");
+ br.write("<LinearRing>\n");
+ br.write("<coordinates>\n");
+
+ // draw the square
+ double accuracyX = map.accuracy;
+ double accuracyY = map.accuracy;
+ double coordX = map.Xcoords[x];
+ double coordY = map.Ycoords[y];
+ br.write(coordX - accuracyX + "," + coordY + accuracyY + ",0,\n");
+ // Point 2
+ br.write(coordX + accuracyX + "," + coordY + accuracyY + ",0,\n");
+ // Point3
+ br.write(coordX + accuracyX + "," + (coordY - accuracyY) + ",0,\n");
+ // Point4
+ br.write((coordX - accuracyX) + "," + (coordY - accuracyY) + ",0,\n");
+ // End: Point 1
+ br.write((coordX - accuracy) + "," + coordY + accuracy + ",0\n");
+
+ br.write("</coordinates>\n");
+ br.write("</LinearRing>\n");
+ br.write("</outerBoundaryIs>\n");
+ br.write("</Polygon>\n");
+ br.write("</Placemark>\n");
+
+ }
+
+ private void writeProbHeader(BufferedWriter br) throws IOException {
+ br.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ br.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
+ br.write(" <Document>\n");
+ br.write("<name> Probability map </name> \n");
+ br.flush();
+ br.write("<open>1</open>\n");
+
+ // style: color for probability from 0% to 100%
+ // color red = #FF0000 (16711680)
+ // color green = #00FF00 (65280)
+
+ // styles for probability
+ for (int style = 0; style <= 100; style++) {
+
+ // int step = (16711680 - 65280) / getSteps();
+ // for (int i = getMin(); i <= getMax(); i++) {
+
+ br.write("<Style id=\"" + style + "\"> \n");
+ br.write("<PolyStyle> \n");
+ br.write("<color>" + getProbabilityColor(style) + "</color> \n");
+ br.write("</PolyStyle> \n");
+ br.write("<LineStyle>\n");
+ // br.write("<color>" + getColor(style) + "</color>\n");
+ br.write("<color>" + 00000000 + "</color>\n");
+ br.write("</LineStyle>\n");
+ br.write("</Style> \n");
+ }
+ br.write(" <Folder>\n");
+ br.write("<name>Probability</name>");
+ br.write(" <visibility>1</visibility>\n");
+ br.write("<description>Probability Map</description>\n");
+ br.write(" <LookAt>\n");
+ br.write("<longitude>" + (map.maxX + map.minX) / 2 + "</longitude>\n");
+ br.write("<latitude>" + (map.maxY + map.minY) / 2 + "</latitude>\n");
+ br.write("<altitude>0</altitude>\n");
+ br.write("<heading>0.0</heading>\n");
+ br.write("<tilt>0</tilt>\n");
+ br.write("<range>276.0</range>\n");
+ br.write("</LookAt>\n");
+
+ }
+
+ private String getProbabilityColor(int probability) {
+
+ int greenp = (int) (probability * 2.55);
+ return ("ff00" + Integer.toHexString(greenp) + "00");
+
+ /*
+ * // probability is from 0 - 100 int green = 0; int red = 0; // yellow
+ * at -75 if (probability > 70) { green = 255; red = 256 - Math.abs((256
+ * / 30) * (-70 - probability));
+ *
+ * } else { // transient green from now on red = 255; green =
+ * Math.abs((256 / 70) * (-30 - probability)); } // int green = 256 -
+ * Math.abs((256 / 90) * (-120 - strength)); // int red = Math.abs((256
+ * / 90) * (-120 - strength)); // int result = red << 24 | green if
+ * ((green > 255) || (red > 255))
+ * System.out.println("Zu groß bei strength= " + probability + ",Rot: "
+ * + red + "Grün: " + green); if (green > 255) green = 255; if (red >
+ * 255) red = 255; // return ("7f00" + Integer.toHexString(red) + //
+ * Integer.toHexString(green)); // return ("ff00" +
+ * Integer.toHexString(red) + // Integer.toHexString(green)); // return
+ * ("ff00" + Integer.toHexString(red) + // Integer.toHexString(green));
+ * return ("ff00" + Integer.toHexString(green) +
+ * Integer.toHexString(red));
+ */
+ }
+}
diff --git a/DataStructure/Interpolator.java b/DataStructure/Interpolator.java
new file mode 100644
index 0000000..3869255
--- /dev/null
+++ b/DataStructure/Interpolator.java
@@ -0,0 +1,366 @@
+package DataStructure;
+
+import helper.ListBTS;
+
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Date;
+
+import voronoi.voronoi;
+import Parse.sqlreader;
+
+public class Interpolator extends GSMMap {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1388761837460629751L;
+ public ArrayList<SingleBTS>[][] buffer;
+
+ public Interpolator(sqlreader SQL, double accuracy) {
+ super(SQL, accuracy);
+ // initialize buffer
+ buffer = new ArrayList[this.Xcoords.length][this.Ycoords.length];
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ buffer[x][y] = new ArrayList<SingleBTS>();
+ }
+ }
+
+ }
+
+ /**
+ * Interpolates every Point on the map,every arfcn
+ */
+ public void interpolateVR() {
+ // get starting time
+ long start = new Date().getTime();
+
+ // average first!
+ // average();
+ // removeOutlier();
+ SingleBTS[] content = content();
+ int success = 0;
+ int failure = 0;
+ int number = Xcoords.length * Ycoords.length * content.length;
+ // traverse each bts
+ for (int i = 0; i < content.length; i++) {
+ // for (int i = 2; i < 3; i++) {
+ // initialize voronoi with current arfcn
+ voronoi primary = new voronoi();
+ primary.sortNode(this, content[i].ARFCN, 1);
+ primary.generateVoronoi(0, Xcoords.length * 3.5, 0,
+ Ycoords.length * 3.5);
+ // now, traverse each point. Check if interpolation is needed!
+ // loop is a little tricky because of threats!
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ // this is a crucial point for parallelism. Change this if
+ // statement
+ // if (ListBTS.contains(map[x][y], content[i])) {
+ // this coordinates already contains this bts
+ // continue;
+ // }
+ // System.out.print("Interpoliere bei:" + x + "," + y
+ // + ", arfcn " + content[i].ARFCN);
+
+ // make it parallel?
+ interpolateThread it1 = new interpolateThread(x, y,
+ content[i], primary);
+ Thread it1T = new Thread(it1);
+ try {
+ if (!ListBTS.contains(map[x][y], content[i])) {
+ it1T.start();
+ // success++;
+ }
+ } catch (Exception e) {
+ failure++;
+ }
+
+ y++;
+
+ interpolateThread it2 = new interpolateThread(x, y,
+ content[i], primary);
+ Thread it2T = new Thread(it2);
+ try {
+ if (checkBounds(x, y)
+ && !ListBTS.contains(map[x][y], content[i])) {
+ it2T.start();
+ // success++;
+ }
+ } catch (Exception e) {
+ failure++;
+ }
+
+ y++;
+
+ interpolateThread it3 = new interpolateThread(x, y,
+ content[i], primary);
+ Thread it3T = new Thread(it3);
+ try {
+ if (checkBounds(x, y)
+ && !ListBTS.contains(map[x][y], content[i])) {
+ it3T.start();
+ // success++;
+ }
+ } catch (Exception e) {
+ failure++;
+ }
+
+ y++;
+ interpolateThread it4 = new interpolateThread(x, y,
+ content[i], primary);
+
+ Thread it4T = new Thread(it4);
+ try {
+ if (checkBounds(x, y)
+ && !ListBTS.contains(map[x][y], content[i])) {
+ it4T.start();
+ // success++;
+ }
+ } catch (Exception e) {
+ failure++;
+ }
+
+ // y++;
+ // interpolateThread it5 = new interpolateThread(x, y,
+ // content[i], primary);
+
+ // Thread it5T = new Thread(it5);
+ // try {
+ // if (checkBounds(x, y)
+ // && !ListBTS.contains(map[x][y], content[i])) {
+ // it5T.start();
+ // success++;
+ // }
+ // } catch (Exception e) {
+ // failure++;
+ // }
+
+ // success += 5;
+ success += 4;
+ if (success % 200 == 0) {
+ // calc ETA
+ long difference = new Date().getTime() - start;
+ int resttime = (int) (difference / success * (number - success));
+ resttime = (resttime / 1000) / 60;
+ System.out.println("Total: " + number + " current: "
+ + success + " rest: " + resttime
+ + " min; current ARFCN: " + content[i].ARFCN
+ + ", Index:" + i + "/" + content.length);
+
+ }
+
+ try {
+ it1T.join();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ try {
+ it2T.join();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ try {
+ it3T.join();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ try {
+ it4T.join();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ // try {
+ // it5T.join();
+ // } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ // e.printStackTrace();
+ // }
+
+ // interpolateAT(x, y, content[i], primary);
+ // //singleThread
+
+ // } catch (Exception e) {
+ // System.out.println("Fehler bei:" + x + "," + y);
+ // failure++;
+ // }
+
+ }
+ }
+ }
+ mergebuffer();
+ System.out.println("Fertig!");
+ }
+
+ private boolean checkBounds(int x, int y) {
+ return (x < Xcoords.length && y < Ycoords.length);
+ }
+
+ /**
+ * Takes map[x][y]. Inserts an interpolated BTS on this point if neccessary
+ *
+ * @param x
+ * @param y
+ * @param arfcn
+ * @param primary
+ * original Voronoi without the current Interpolationpoint
+ */
+ private void interpolateAT(int x, int y, SingleBTS interpolateThis,
+ voronoi primary) {
+ if (!ListBTS.contains(map[x][y], interpolateThis)) {
+ // do it!
+
+ voronoi secondary = new voronoi();
+ secondary.sortNode((GSMMap) this, interpolateThis.ARFCN, 1, x, y);
+ secondary.generateVoronoi(0, 4000, 0, 4000);
+
+ // get area of polygon for current x,y
+ // double area = secondary.areaOf(x, y);
+ Path2D region = secondary.getPoly(x, y);
+ double area = secondary.area(region);
+ if (region == null) {
+ return;
+ }
+ // get Neighbors of x,y
+ ArrayList<Point2D> neighbors = secondary.getDirectNeighbors(x, y);
+
+ // calculate intersection of voronoi region for each neighbor
+ ArrayList<Weight> weights = new ArrayList<Weight>(neighbors.size());
+ for (int i = 0; i < neighbors.size(); i++) {
+ int neighX = (int) neighbors.get(i).getX();
+ int neighY = (int) neighbors.get(i).getY();
+ // double area2 = primary.areaOf(currentx, currenty);
+
+ Path2D underling = primary.getPoly(neighX, neighY);
+ if (underling == null) {
+ // one of the neighbors doesn't have a vornoi region.
+ // this happens at the bounds of the gsm map:a infinit big
+ // polygon
+ continue;
+ // TODO: das continue könnte zu problemen führen, weil dann
+ // auch kein weights element an dieser Stelle eingefügt wird
+ // und das Array somit an dieser Stelle auch null ist
+ // TODO: warum ist temporary manchmal null?!!!!!!!
+ }
+ // intersection between both voronoi regions
+ double intersectA = primary.intersectArea(region, underling);
+ Weight new_element = new Weight();
+ new_element.weight = intersectA / area;
+ new_element.bts = ListBTS.getARFCN(map[neighX][neighY],
+ interpolateThis);
+ weights.add(new_element);
+ }
+
+ // now, traverse weights, get sum of weights (to check if it equals
+ // one)
+ double newDL = 0;
+ double mode = 0;
+ double var = 0;
+ double DlQualsub = 0;
+ // double DlQualFull = 0;
+ double UlQualsub = 0;
+ // double UlQualFull = 0;
+ double sum_of_weights = 0;
+ for (int i = 0; i < weights.size(); i++) {
+ if (weights.get(i) == null)
+ continue;
+ sum_of_weights += weights.get(i).weight;
+ }
+
+ // calculate with weights and normalize
+ for (int i = 0; i < weights.size(); i++) {
+ if (weights.get(i) == null)
+ continue;
+ // HACK: normalize weights
+ weights.get(i).weight = weights.get(i).weight / sum_of_weights;
+ // calulate
+ newDL = newDL + weights.get(i).weight
+ * weights.get(i).bts.getDLmW();
+ mode = mode + weights.get(i).weight
+ * weights.get(i).bts.getStrictDLdBAverage();
+ var = var + weights.get(i).weight
+ * weights.get(i).bts.getTrueVarianceDLdB();
+ DlQualsub = DlQualsub + weights.get(i).weight
+ * weights.get(i).bts.getDLQsub();
+ // DlQualFull = DlQualFull + weights.get(i).weight
+ // * weights.get(i).bts.getDLQfull();
+ UlQualsub = UlQualsub + weights.get(i).weight
+ * weights.get(i).bts.getULQsub();
+ // UlQualFull = UlQualFull + weights.get(i).weight
+ // * weights.get(i).bts.getULQfull();
+
+ // weights.get(i).bts.
+ }
+
+ // map[x][y] doesn't contain the just interpolated bts
+ SingleBTS temp = new SingleBTS(interpolateThis.ARFCN,
+ interpolateThis.name + "I");
+ temp.addDl(newDL);
+ temp.dlQsub.add(DlQualsub);
+ // temp.dlQfull.add(DlQualFull);
+ temp.ulQsub.add(UlQualsub);
+ // temp.ulQfull.add(UlQualFull);
+ temp.interpolated.add(true);
+ temp.setVarDLdB(var);
+ temp.mode = mode;
+ buffer[x][y].add(temp);
+
+ }
+
+ }
+
+ private void mergebuffer() {
+ for (int x = 0; x < Xcoords.length; x++) {
+ for (int y = 0; y < Ycoords.length; y++) {
+ if (map[x][y].isEmpty()) {
+ map[x][y] = buffer[x][y];
+ } else {
+ mergeSingleBTS(x, y);
+ }
+ }
+ }
+ }
+
+ /**
+ * If map[x][y] contains measurements, check if some BTS are missing and
+ * merge with buffer
+ *
+ * @param x
+ * @param y
+ */
+ private void mergeSingleBTS(int x, int y) {
+ for (SingleBTS current : buffer[x][y]) {
+ if (!ListBTS.contains(map[x][y], current)) {
+ map[x][y].add(current);
+ }
+ }
+
+ }
+
+ class interpolateThread implements Runnable {
+ public int x;
+ public int y;
+ public SingleBTS what;
+ public voronoi primary;
+
+ @Override
+ public void run() {
+ if (x < Xcoords.length && y < Ycoords.length)
+ interpolateAT(x, y, what, primary);
+ }
+
+ public interpolateThread(int x, int y, SingleBTS what, voronoi primary) {
+ this.x = x;
+ this.y = y;
+ this.what = what;
+ this.primary = primary;
+ }
+
+ }
+
+}
diff --git a/DataStructure/MeasurementReport.java b/DataStructure/MeasurementReport.java
new file mode 100644
index 0000000..ee06667
--- /dev/null
+++ b/DataStructure/MeasurementReport.java
@@ -0,0 +1,60 @@
+package DataStructure;
+
+import java.util.Date;
+import java.util.LinkedList;
+
+public class MeasurementReport {
+ private LinkedList<SingleBTS> MR = new LinkedList<SingleBTS>();
+ public Date time = new Date();
+
+ // Constructor
+ public MeasurementReport() {
+ // MR = new LinkedList<SingleBTS>();
+ }
+
+ // TODO: think of a way to get data out of this structure (eg. as array,
+ // etc.)
+
+ // add a new BTS to list
+ public void add(SingleBTS BTS) {
+ // SingleBTS current;
+ // int i = 0;
+ // BTS with same frequency already existing? If so, average
+ // while ((!MR.isEmpty()) && (current = MR.get(i)) != null) {
+ // if (current.ARFCN == BTS.ARFCN) {
+ // System.out.println("DEBUG: Element found. Averaging");
+ // current.addBTSMeasure(BTS);
+ // MR.remove(i);
+ // MR.add(i, current);
+ // break; // only one duplicate BTS should exist
+ // } else {
+ MR.add(BTS);
+ // }
+ // }
+ }
+
+ public void add(String SqlStatement) {
+ String[] answers = SqlStatement.split(",");
+ // WARNING get only first BTS here. Problem: ARFCN is unknown!
+ SingleBTS BTS = new SingleBTS(123, Integer.parseInt(answers[3]),
+ Integer.parseInt(answers[13]), false, null, "unknown");
+ add(BTS);
+
+ }
+
+ // returns RX-Quality of first BTS in the Measurement
+ public String toString() {
+ return time.toString() + ";" + MR.getFirst().toString();
+
+ }
+
+ public int getFirstBTSul() {
+ return (int) MR.getFirst().getUldB();
+ }
+
+ public int getFirstBTSdl() {
+ return (int) MR.getFirst().getDldB();
+ }
+}
+
+// Stores single BTS information
diff --git a/DataStructure/MobilePhone.java b/DataStructure/MobilePhone.java
new file mode 100644
index 0000000..2276bb6
--- /dev/null
+++ b/DataStructure/MobilePhone.java
@@ -0,0 +1,337 @@
+package DataStructure;
+
+import helper.ListBTS;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Date;
+
+import org.jdesktop.swingx.JXMapViewer;
+import org.jdesktop.swingx.mapviewer.GeoPosition;
+import org.jdesktop.swingx.painter.Painter;
+
+public class MobilePhone implements Painter<JXMapViewer> {
+ public ArrayList<SingleBTS> MR;
+ public long IMSI;
+ public double[][] scoremap;
+ public GSMMap gsmmap;
+ public Color color;
+ public boolean timeSensitiv = false;
+ public double confidence;
+ public BayesAll bayes;
+ public GPScoordinate correctCoordinate;
+ public String name = "";
+ public Date time = new Date();
+
+ // private int maxProbX;
+ // private int maxProbY;
+
+ public MobilePhone() {
+ MR = new ArrayList<SingleBTS>();
+ }
+
+ public MobilePhone(BayesAll bayes) {
+ MR = new ArrayList<SingleBTS>();
+ this.bayes = bayes;
+
+ }
+
+ private void DrawDetails(Graphics2D g, double highestScore, int tileCount) {
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, 300, 25);
+ g.setColor(Color.BLACK);
+ g.drawString("Score tile: " + highestScore + "\n\r #Tiles: "
+ + tileCount, 5, 10);
+ Date time;
+ if (timeSensitiv) {
+ time = this.time;
+ } else {
+ time = MR.get(0).time;
+ }
+ g.drawString(name + " " + time, 5, 20);
+
+ }
+
+ public void average() {
+
+ }
+
+ public String toString() {
+ return IMSI + " " + MR;
+ }
+
+ /**
+ * Returns (and stores in scoremap) the possibility that this Mobile Phone
+ * falls within the tile. Dimensions and Coordinates of scoremap are that of
+ * map. Must be run before this Phone gets drawn!
+ *
+ * @param map
+ * @return
+ */
+ public double[][] locate(GSMMap map, boolean dropNaN) {
+ scoremap = gsmBayes.computeScore(MR, map);
+ this.gsmmap = map;
+
+ return scoremap;
+ }
+
+ public double[][] locate(double confidence) {
+ this.gsmmap = this.bayes.map;
+ this.confidence = confidence;
+ timeSensitiv = false;
+ ArrayList<SingleBTS> averagedMR = ListBTS.generateAveragedList(MR);
+
+ // remove outlier!
+ // for (int i = 0; i < averagedMR.size(); i++) {
+ // averagedMR.get(i).removeOutlier();
+ // }
+ scoremap = bayes.locate(averagedMR, confidence);
+ if (correctCoordinate != null) {
+ System.out.println(localizationAccuracy());
+ }
+ return scoremap;
+ }
+
+ /**
+ * Returns (and stores) the possibility that this Mobile Phone falls within
+ * the tile. Possibilities get summed up until they are greater or equal
+ * confidence. Dimensions and Coordinates of scoremap are that of map
+ *
+ * @param map
+ * @return
+ */
+ public double[][] locate(GSMMap map, double confidence, boolean dropNaN) {
+ scoremap = gsmBayes.toConfidence(gsmBayes.computeScore(MR, map),
+ confidence);
+ gsmmap = map;
+ this.confidence = confidence;
+ return scoremap;
+ }
+
+ public double[][] locateTimeSensitiv(GSMMap map, double confidence,
+ long time, boolean dropNaN) {
+ gsmmap = map;
+ this.confidence = confidence;
+ ArrayList<SingleBTS> temporalMR = filterTime(MR, time);
+ temporalMR = ListBTS.generateAveragedList(temporalMR);
+ scoremap = gsmBayes.toConfidence(
+ gsmBayes.computeScore(temporalMR, map), confidence);
+ return scoremap;
+ }
+
+ public double[][] locateTimeSensitiv(double confidence, long time) {
+ this.gsmmap = this.bayes.map;
+ this.confidence = confidence;
+ timeSensitiv = true;
+ this.time = new Date(time);
+ ArrayList<SingleBTS> temporalMR = filterTime(MR, time);
+ temporalMR = ListBTS.generateAveragedList(temporalMR);
+ scoremap = bayes.locate(temporalMR, confidence);
+
+ // sum up scoremap!!!!
+ double sum = 0;
+ for (int x = 0; x < scoremap.length; x++) {
+ for (int y = 0; y < scoremap[0].length; y++) {
+ sum += scoremap[x][y];
+ }
+ }
+ // System.out.println("Summe scoremap: " + sum);
+
+ return scoremap;
+
+ }
+
+ /**
+ * Returns entries in MR that are +/- 1 second within time
+ *
+ * @param MR
+ * @param time
+ * @return
+ */
+ private ArrayList<SingleBTS> filterTime(ArrayList<SingleBTS> MR, long time) {
+ ArrayList<SingleBTS> temporalMR = new ArrayList<SingleBTS>(20);
+ for (SingleBTS current : MR) {
+ if (Math.abs(current.time.getTime() - time) <= 1001) {
+ temporalMR.add(current);
+ }
+ }
+ return temporalMR;
+ }
+
+ @Override
+ public void paint(Graphics2D g, JXMapViewer map, int w, int h) {
+ // locate(gsmmap);
+
+ g = (Graphics2D) g.create();
+
+ // convert from viewport to world bitmap
+ Rectangle rect = ((org.jdesktop.swingx.JXMapViewer) map)
+ .getViewportBounds();
+ g.translate(-rect.x, -rect.y);
+ // maxProbX = 0;
+ // maxProbY = 0;
+ double currentscore = 0;
+ int tileCounter = 0;
+ Polygon maxTile = null;
+ // now, draw
+ for (int x = 0; x < scoremap.length; x++) {
+ for (int y = 0; y < scoremap[0].length; y++) {
+
+ if (scoremap[x][y] > 0) {
+ tileCounter++;
+ double coordX = gsmmap.Xcoords[x];
+ double coordY = gsmmap.Ycoords[y];
+ double accuracy = gsmmap.accuracy;
+ Polygon tile = new Polygon();
+
+ GeoPosition pos1 = new GeoPosition(coordY - accuracy / 2,
+ coordX + accuracy / 2);
+ GeoPosition pos2 = new GeoPosition(coordY + accuracy / 2,
+ coordX + accuracy / 2);
+ GeoPosition pos3 = new GeoPosition(coordY + accuracy / 2,
+ coordX - accuracy / 2);
+ GeoPosition pos4 = new GeoPosition(coordY - accuracy / 2,
+ coordX - accuracy / 2);
+ Point2D pt1 = map.getTileFactory().geoToPixel(pos1,
+ map.getZoom());
+ Point2D pt2 = map.getTileFactory().geoToPixel(pos2,
+ map.getZoom());
+ Point2D pt3 = map.getTileFactory().geoToPixel(pos3,
+ map.getZoom());
+ Point2D pt4 = map.getTileFactory().geoToPixel(pos4,
+ map.getZoom());
+ Color c = getColor(scoremap[x][y]);
+ // g.setColor(new Color(255, 0, 0, 255));
+ g.setColor(c);
+ tile.addPoint((int) pt1.getX(), (int) pt1.getY());
+ tile.addPoint((int) pt2.getX(), (int) pt2.getY());
+ tile.addPoint((int) pt3.getX(), (int) pt3.getY());
+ tile.addPoint((int) pt4.getX(), (int) pt4.getY());
+ g.fill(tile);
+ g.draw(tile);
+ if (scoremap[x][y] >= currentscore) {
+ // update x, y of biggest score
+ currentscore = scoremap[x][y];
+ // maxProbX = x;
+ // maxProbY = y;
+ maxTile = tile;
+ }
+ }
+ }
+ }
+
+ // g.translate(-rect.x, -rect.y);
+ try {
+ g.setColor(Color.red);
+ g.draw(maxTile);
+ } catch (NullPointerException e) {
+
+ }
+
+ if (correctCoordinate != null) {
+ // draw a circle where the correct position of this phone is
+ double latitude = correctCoordinate.coord1;
+ double longitude = correctCoordinate.coord2;
+ GeoPosition correct = new GeoPosition(latitude, longitude);
+ Point2D circle = map.getTileFactory().geoToPixel(correct,
+ map.getZoom());
+ g.setColor(Color.RED);
+ g.drawOval((int) circle.getX() - 5, (int) circle.getY() - 5, 10, 10);
+ }
+ // translate back to Monitor coordinates
+ g.translate(rect.x, rect.y);
+ DrawDetails(g, currentscore, tileCounter);
+ g.dispose();
+
+ }
+
+ /**
+ * After a localization was done, you can output details for this
+ * localization
+ *
+ * @return
+ */
+ public String localizationAccuracy() {
+ try {
+ // get maximum possible tile
+ PossibilityObject[] possibilities = bayes.toPossibility(scoremap);
+ PossibilityObject mostPossible = possibilities[possibilities.length - 1];
+ // x,y for most possible coord
+ int x = mostPossible.x;
+ int y = mostPossible.y;
+ GPScoordinate possibleCoord = new GPScoordinate(new Date(),
+ gsmmap.Ycoords[y], 'N', gsmmap.Xcoords[x], 'E', true);
+
+ // distance between correct localization and possibleCoord
+ double distance = helper.Distance.calc(possibleCoord,
+ correctCoordinate);
+ // get distance of tile that is maximum away from correct location
+ double radius = maxError();
+ String result = "Distance to correct position: " + distance * 1000
+ + "m. Most away tile: " + radius * 1000
+ + "m from correct position";
+ return result;
+
+ } catch (NullPointerException e) {
+ // System.out.println("ERROR: cannot aquire most possible location");
+ return "";
+ }
+
+ }
+
+ private double maxError() {
+ double maxDistance = 0;
+ double correctN = correctCoordinate.coord1;
+ double correctE = correctCoordinate.coord2;
+ for (int x = 0; x < scoremap.length; x++) {
+ for (int y = 0; y < scoremap[0].length; y++) {
+ if (scoremap[x][y] > 0) {
+ double currentDistance = helper.Distance.calc(correctN,
+ correctE, gsmmap.Ycoords[y], gsmmap.Xcoords[x]);
+ maxDistance = Math.max(maxDistance, currentDistance);
+ }
+ }
+ }
+ return maxDistance;
+ }
+
+ private Color getColor(double d) {
+ // d between 0...confidence
+ // Color between black and green???
+ // int green = (int) (d * 255);
+ // return new Color(0, green, 0, 100);
+
+ // r+b means probability of 1/2!!!
+ int color = (int) ((d / confidence) * 255);
+ // lets say half of confidence is already full pink!
+ color = color * 2;
+ if (color > 255)
+ color = 255;
+ return new Color(color, 0, color, 255);
+ }
+
+ public long getMinTime() {
+ long time = MR.get(0).time.getTime();
+ for (int i = 1; i < MR.size(); i++) {
+ if (MR.get(i).time.getTime() < time) {
+ time = MR.get(i).time.getTime();
+ }
+ }
+ return time;
+ }
+
+ public long getMaxTime() {
+ long time = MR.get(0).time.getTime();
+ for (int i = 1; i < MR.size(); i++) {
+ if (MR.get(i).time.getTime() > time) {
+ time = MR.get(i).time.getTime();
+ }
+ }
+ return time;
+ }
+
+}
diff --git a/DataStructure/NormDistribution.java b/DataStructure/NormDistribution.java
new file mode 100644
index 0000000..109d4fa
--- /dev/null
+++ b/DataStructure/NormDistribution.java
@@ -0,0 +1,77 @@
+package DataStructure;
+
+class NormDistribution {
+ double variance;
+ double mean;
+ static final double sqrtPI = 2.506628274631000502415765284811d;
+
+ public static void main(String args[]) {
+ NormDistribution one = new NormDistribution(5.12, 10);
+ NormDistribution two = new NormDistribution(5.12, 10);
+ NormDistribution three = new NormDistribution(0, 4);
+ System.out.println(one.intersection(two));
+ System.out.println("value at max: " + three.valueAt(2));
+ }
+
+ public NormDistribution(double mean, double variance) {
+ this.mean = mean;
+ this.variance = variance;
+ }
+
+ public double valueAt(double x) {
+ double std = Math.sqrt(variance);
+ // double sqrtPI = Math.sqrt(2 * Math.PI);
+
+ double exp = Math.exp(((Math.pow((x - mean), 2)) / variance) / (-2));
+ double result = (1 / (std * sqrtPI)) * exp;
+ return result;
+ }
+
+ /**
+ * Calculates the intersection area of both Distributions
+ *
+ * @param distribution
+ * @return
+ */
+ public double intersection(NormDistribution distribution) {
+
+ // return one, if both distributions are alike? (speedup)
+ if (Math.abs(this.mean - distribution.mean) < 0.01
+ && Math.abs(this.variance - distribution.variance) < 0.01) {
+ return 0.998;
+ }
+
+ // if (variance < 0.1 && distribution.variance < 0.1
+ // && Math.abs(mean - distribution.mean) < 0.1) {
+ // return 1;
+ // }
+
+ // get plus/minus 3*sigma Intervall (95% of the values)
+ double begin = -3.5
+ * Math.sqrt(Math.min(variance, distribution.variance))
+ + Math.min(mean, distribution.mean);
+ ;
+ double end = 3.5 * Math.sqrt(Math.max(variance, distribution.variance))
+ + Math.max(mean, distribution.mean);
+ // get stepwidth for integration.
+ double step = (end - begin) / 42; // Resolution: 42 steps!
+ // what if rounding errors appear and step == 0?
+ if (step < 0.0000001) {
+ return 0;
+ }
+
+ double area = 0;
+ end -= step;
+
+ for (double x0 = begin; x0 <= end; x0 += step) {
+ // get min value
+ double x1 = x0 + step;
+ double fx0 = Math.min(valueAt(x0), distribution.valueAt(x0));
+ double fx1 = Math.min(valueAt(x1), distribution.valueAt(x1));
+ area += fx0 * (x1 - x0) + ((x1 - x0) * (fx1 - fx0)) / 2;
+ }
+
+ return area;
+ }
+
+} \ No newline at end of file
diff --git a/DataStructure/PhoneContainer.java b/DataStructure/PhoneContainer.java
new file mode 100644
index 0000000..efcc24c
--- /dev/null
+++ b/DataStructure/PhoneContainer.java
@@ -0,0 +1,106 @@
+package DataStructure;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.util.ArrayList;
+import java.util.Random;
+
+import org.jdesktop.swingx.JXMapViewer;
+import org.jdesktop.swingx.painter.Painter;
+
+public class PhoneContainer implements Painter<JXMapViewer> {
+
+ private ArrayList<MobilePhone> phones = new ArrayList<MobilePhone>();
+ private ArrayList<ImsiColor> colors = new ArrayList<ImsiColor>();
+
+ public PhoneContainer() {
+
+ }
+
+ /**
+ * Adds the phone to the JXMAP-Painter. Assigns a random Color if phone is
+ * new. Make sure phone is already initialized. That means, locate method is
+ * already called. This container takes MobilEPhone Objects and draws them
+ * all!
+ *
+ * @param phone
+ */
+ public void add(MobilePhone phone) {
+ // look if Phone is already inside
+ int index = findIMSI(phone);
+ if (index > -1) {
+ // phone is there at position index
+ Color intermediate = phones.get(index).color;
+ phone.color = intermediate;
+ phones.set(index, phone);
+ } else {
+
+ Random r = new Random();
+ phone.color = new Color(r.nextInt(256), r.nextInt(256),
+ r.nextInt(256));
+ phones.add(phone);
+ }
+
+ // oder Farbe durch einen Hash auf die IMSI machen...
+
+ }
+
+ private int findIMSI(MobilePhone phone) {
+ for (int i = 0; i < phones.size(); i++) {
+ if (phones.get(i).IMSI == phone.IMSI) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Removes all Phones from Painter list. Colors for each phone (IMSI) is
+ * remembered
+ */
+ public void removeAll() {
+ phones.clear();
+ }
+
+ @Override
+ /**
+ * HACK: Outputs only two phones now! For Journal. Remove test for IMSI afterwards
+ */
+ public void paint(Graphics2D g, JXMapViewer map, int w, int h) {
+ for (MobilePhone phone : phones) {
+ if (phone.IMSI == 262230000000003L
+ || phone.IMSI == 262230000000013L) {
+ // g.setColor(phone.color);
+ g.setColor(getColor(phone));
+
+ phone.paint(g, map, w, h);
+ }
+ }
+ g.dispose();
+
+ }
+
+ private Color getColor(MobilePhone phone) {
+ // search if IMSI already in list
+ for (int i = 0; i < colors.size(); i++) {
+ if (colors.get(i).IMSI == phone.IMSI) {
+ return colors.get(i).c;
+ }
+ }
+ Random r = new Random();
+ Color result = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
+ colors.add(new ImsiColor(phone.IMSI, result));
+ return result;
+ }
+
+}
+
+class ImsiColor {
+ public long IMSI;
+ public Color c;
+
+ public ImsiColor(long IMSI, Color c) {
+ this.IMSI = IMSI;
+ this.c = c;
+ }
+}
diff --git a/DataStructure/PossibilityObject.java b/DataStructure/PossibilityObject.java
new file mode 100644
index 0000000..9718012
--- /dev/null
+++ b/DataStructure/PossibilityObject.java
@@ -0,0 +1,21 @@
+package DataStructure;
+
+class PossibilityObject implements Comparable<PossibilityObject> {
+ double possibility;
+ int x;
+ int y;
+
+ @Override
+ public int compareTo(PossibilityObject comperator) {
+ if (this == null || comperator == null) {
+ throw new NullPointerException(
+ "one of the Possiblity objects is null!");
+ }
+ if (this.possibility > comperator.possibility) {
+ return 1;
+ } else if (this.possibility < comperator.possibility) {
+ return -1;
+ } else
+ return 0;
+ }
+}
diff --git a/DataStructure/ResultScore.java b/DataStructure/ResultScore.java
new file mode 100644
index 0000000..9d498ec
--- /dev/null
+++ b/DataStructure/ResultScore.java
@@ -0,0 +1,54 @@
+package DataStructure;
+
+import helper.ListGPS;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+public class ResultScore {
+ ArrayList<ScoreElement> scores = new ArrayList<ScoreElement>();
+ GSMMap map;
+
+ /**
+ * Gets score for every Coordinate
+ *
+ * @param list
+ */
+ public ResultScore(GSMMap map) {
+ this.map = map;
+
+ }
+
+ public ArrayList<ScoreElement> find(LinkedList<SingleBTS> MR,
+ double thresholdDBm) {
+ ArrayList<GPScoordinate> places = map.find(MR, thresholdDBm);
+ GPScoordinate[] content = ListGPS.content(places);
+ for (GPScoordinate curr_content : content) {
+ // take every Coordinate once. Build a ScoreElement with it.Traverse
+ // the whole list
+ ScoreElement curr_score = new ScoreElement(curr_content);
+ for (GPScoordinate curr_place : places) {
+ curr_score.add(curr_place);
+ }
+ scores.add(curr_score);
+
+ // traverse every coordinate from gsm.find. check every tile if all
+ // mesurements match. if not, score gets low
+
+ // then, check BTS relations!
+
+ }
+ return scores;
+ }
+
+ private void checkRatio(LinkedList<SingleBTS> MR) {
+ // calculate ratios from MR first
+ // compare with ratios that occur in scores.gps
+
+ }
+}
+
+class ratio {
+ SingleBTS first;
+ SingleBTS second;
+}
diff --git a/DataStructure/ScoreElement.java b/DataStructure/ScoreElement.java
new file mode 100644
index 0000000..c5ed85a
--- /dev/null
+++ b/DataStructure/ScoreElement.java
@@ -0,0 +1,21 @@
+package DataStructure;
+
+class ScoreElement {
+ public int occurrence; // how often was this coordinate chosen based on
+ // Signalstrength
+ public int ratio_hit; // how often was this coordinate chosen based on
+ // SignalRatio
+ public GPScoordinate gps;
+ private double score;
+
+ public ScoreElement(GPScoordinate reference) {
+ gps = reference;
+ }
+
+ public void add(GPScoordinate gps) {
+ if (this.gps.equals(gps)) {
+ score++;
+ }
+
+ }
+}
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!");
+ }
+
+ }
+
+}
diff --git a/DataStructure/Weight.java b/DataStructure/Weight.java
new file mode 100644
index 0000000..a22ab9f
--- /dev/null
+++ b/DataStructure/Weight.java
@@ -0,0 +1,19 @@
+package DataStructure;
+
+public class Weight {
+ int x;
+ int y;
+ SingleBTS bts;
+ double weight;
+ double area;
+
+ public Weight(int x, int y, double weight) {
+ this.x = x;
+ this.y = y;
+ this.weight = weight;
+ }
+
+ public Weight() {
+
+ }
+}
diff --git a/DataStructure/gsmBayes.java b/DataStructure/gsmBayes.java
new file mode 100644
index 0000000..2490633
--- /dev/null
+++ b/DataStructure/gsmBayes.java
@@ -0,0 +1,752 @@
+package DataStructure;
+
+import helper.ListBTS;
+
+import java.awt.Point;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+public class gsmBayes {
+ GSMMap map;
+
+ public static void main(String[] args) throws FileNotFoundException,
+ IOException, ClassNotFoundException {
+
+ NormDistribution one = new NormDistribution(30, 0.21);
+ NormDistribution two = new NormDistribution(30, 0.21);
+ System.out.println(one.intersection(two) + " " + two.intersection(one));
+
+ // System.out.println(10 * Math.log10(0.0));
+
+ // Comparator test
+ // ArrayList<SingleBTS> testlist = new ArrayList<SingleBTS>();
+ // testlist.add(new SingleBTS(999, "letzte"));
+ // testlist.add(new SingleBTS(124, "zweite"));
+ // testlist.add(new SingleBTS(123, "erste"));
+ // ArrayList<SingleBTS> testlistcopy = new
+ // ArrayList<SingleBTS>(testlist);
+ // Collections.copy(testlistcopy, testlist);
+
+ // Collections.sort(testlist, new BTSArfcnComparator());
+ // testlist.get(0).name = "blabla";
+ // System.out.println(testlist);
+ // System.out.println(testlistcopy);
+
+ // gsmmap object einlesen
+ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
+ "interpolatedGSMMap.obj"));
+ GSMMap map = (GSMMap) ois.readObject();
+ System.out.println("Start");
+ // ArrayList<SingleBTS> MR = getMR106();
+ ArrayList<SingleBTS> MR = subtractBTS(getMensa(), 0);
+ double[][] scoremap = computeScore(MR, map);
+ System.out.println("fertig");
+
+ double maxSingleProbability = 0;
+ double sumOfProbabilities = 0;
+ for (int x = 0; x < scoremap.length; x++) {
+ for (int y = 0; y < scoremap[0].length; y++) {
+ if (scoremap[x][y] > 0) {
+ // System.out.println("positive Wahrsch. gefunden! "
+ // + scoremap[x][y]);
+ if (scoremap[x][y] > maxSingleProbability) {
+ maxSingleProbability = scoremap[x][y];
+ System.out.println("neues Maximum bei " + x + "/" + y
+ + " !");
+ }
+ sumOfProbabilities += scoremap[x][y];
+ // sind das vll. die falschen Wahrscheinlihckeiten?
+ // P(RSS|Kachel) = 1 oder
+ // P(Kachel|RSS) = 1?
+ }
+ }
+ }
+ System.out.println("Summe: " + sumOfProbabilities + ", maximum: "
+ + maxSingleProbability);
+ GoogleOut out = new GoogleOut(map, "bla");
+ // out.write();
+
+ // fill up to confidence level
+ double[][] confidence = toConfidence(scoremap, 0.75);
+
+ double confidencesum = 0;
+ for (int x = 0; x < confidence.length; x++) {
+ for (int y = 0; y < confidence[0].length; y++) {
+ confidencesum += confidence[x][y];
+ }
+ }
+ System.out.println("Confidence level bei: " + confidencesum);
+
+ out.writeProbability(confidence, "probabilities.kml");
+
+ }
+
+ /**
+ * Returns all tiles until they sum up to confidence. scoremap gets
+ * destroyed
+ *
+ * @param scoremap
+ * @param d
+ * @return
+ */
+ public static double[][] toConfidence(double[][] scoremap, double confidence) {
+ if (confidence == 1 || confidence > 1) {
+ return scoremap;
+ }
+
+ // scoremap to possibility objects (faster...)
+ PossibilityObject[] possibilities = toPossibility(scoremap);
+ double sum_confidence = 0;
+ double[][] result = new double[scoremap.length][scoremap[0].length];
+ int boundary = possibilities.length - 1;
+ while (sum_confidence < confidence) {
+ sum_confidence += possibilities[boundary].possibility;
+ int x = possibilities[boundary].x;
+ int y = possibilities[boundary].y;
+ result[x][y] = possibilities[boundary].possibility;
+ boundary--;
+ }
+ // result = PossObjToScoremap(possibilities, boundary, result);
+
+ /*
+ * double max = 0; int xmax = 0; int ymax = 0; for (int x = 0; x <
+ * scoremap.length; x++) { for (int y = 0; y < scoremap[0].length; y++)
+ * { if (scoremap[x][y] > max) { max = scoremap[x][y]; xmax = x; ymax =
+ * y; }
+ *
+ * } } // max found.
+ *
+ * result[xmax][ymax] = scoremap[xmax][ymax]; sum_confidence +=
+ * scoremap[xmax][ymax]; scoremap[xmax][ymax] = 0; }
+ */
+ return result;
+
+ }
+
+ @SuppressWarnings("unused")
+ private static double[][] PossObjToScoremap(
+ PossibilityObject[] possibilities, int boundary, double[][] result) {
+ for (int i = possibilities.length - 1; i <= boundary; i--) {
+ int x = possibilities[i].x;
+ int y = possibilities[i].y;
+ result[x][y] = possibilities[i].possibility;
+ }
+
+ return result;
+ }
+
+ @SuppressWarnings("unused")
+ private static ArrayList<SingleBTS> gettheater() {
+ ArrayList<SingleBTS> MR2 = new ArrayList<SingleBTS>();
+ ArrayList<SingleBTS> MR = new ArrayList<SingleBTS>();
+ MR.add(new SingleBTS(806, Double.NaN, -101, true, new Date(), "lookup",
+ 1));
+ MR.add(new SingleBTS(817, Double.NaN, -96, true, new Date(), "lookup",
+ 1));
+ MR.add(new SingleBTS(815, Double.NaN, -92, true, new Date(), "lookup",
+ 12));
+ MR.add(new SingleBTS(823, Double.NaN, -97, true, new Date(), "lookup",
+ 0.25));
+ MR.add(new SingleBTS(871, Double.NaN, -90, true, new Date(), "lookup",
+ 1));
+ MR.add(new SingleBTS(877, Double.NaN, -101, true, new Date(), "lookup",
+ 1));
+
+ MR2.add(new SingleBTS(806, Double.NaN, -101, true, new Date(), "lookup"));
+ MR2.add(new SingleBTS(817, Double.NaN, -96, true, new Date(), "lookup"));
+ MR2.add(new SingleBTS(815, Double.NaN, -92, true, new Date(), "lookup"));
+ MR2.add(new SingleBTS(823, Double.NaN, -97, true, new Date(), "lookup"));
+ MR2.add(new SingleBTS(871, Double.NaN, -90, true, new Date(), "lookup"));
+ MR2.add(new SingleBTS(877, Double.NaN, -101, true, new Date(), "lookup"));
+ return MR;
+ }
+
+ @SuppressWarnings("unused")
+ private static ArrayList<SingleBTS> getArt() {
+ ArrayList<SingleBTS> MR = new ArrayList<SingleBTS>();
+ MR.add(new SingleBTS(806, Double.NaN, -90, true, new Date(), "lookup",
+ 3.33));
+ MR.add(new SingleBTS(817, Double.NaN, -90, true, new Date(), "lookup",
+ 2.28));
+ MR.add(new SingleBTS(815, Double.NaN, -88, true, new Date(), "lookup",
+ 2.05));
+ MR.add(new SingleBTS(823, Double.NaN, -76, true, new Date(), "lookup",
+ 9));
+ MR.add(new SingleBTS(880, Double.NaN, -96, true, new Date(), "lookup",
+ 4));
+ MR.add(new SingleBTS(877, Double.NaN, -65, true, new Date(), "lookup",
+ 3.77));
+ return MR;
+ }
+
+ @SuppressWarnings("unused")
+ private static ArrayList<SingleBTS> getMR101() {
+ ArrayList<SingleBTS> MR = new ArrayList<SingleBTS>();
+ MR.add(new SingleBTS(806, Double.NaN, -94, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(817, Double.NaN, -92, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(815, Double.NaN, -88, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(823, Double.NaN, -79, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(880, Double.NaN, -97, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(877, Double.NaN, -84, true, new Date(), "lookup"));
+ return MR;
+ }
+
+ @SuppressWarnings("unused")
+ private static ArrayList<SingleBTS> getMR106() {
+ ArrayList<SingleBTS> MR = new ArrayList<SingleBTS>();
+ MR.add(new SingleBTS(806, Double.NaN, -98, true, new Date(), "lookup",
+ 0.25));
+ MR.add(new SingleBTS(817, Double.NaN, -89, true, new Date(), "lookup",
+ 0.25));
+ MR.add(new SingleBTS(815, Double.NaN, -85, true, new Date(), "lookup",
+ 0.25));
+ MR.add(new SingleBTS(823, Double.NaN, -90, true, new Date(), "lookup",
+ 0));
+ MR.add(new SingleBTS(880, Double.NaN, -98, true, new Date(), "lookup",
+ 0));
+ MR.add(new SingleBTS(877, Double.NaN, -102, true, new Date(), "lookup",
+ 6.25));
+ return MR;
+ }
+
+ @SuppressWarnings("unused")
+ private static ArrayList<SingleBTS> get79() {
+ ArrayList<SingleBTS> MR = new ArrayList<SingleBTS>();
+
+ MR.add(new SingleBTS(806, Double.NaN, -88, true, new Date(), "lookup",
+ 2.64));
+ MR.add(new SingleBTS(817, Double.NaN, -90, true, new Date(), "lookup",
+ 2.05));
+ MR.add(new SingleBTS(815, Double.NaN, -86, true, new Date(), "lookup",
+ 1.42));
+ MR.add(new SingleBTS(823, Double.NaN, -87, true, new Date(), "lookup",
+ 1.57));
+ MR.add(new SingleBTS(871, Double.NaN, -63, true, new Date(), "lookup",
+ 25.4));
+ MR.add(new SingleBTS(880, Double.NaN, -83, true, new Date(), "lookup",
+ 0.658));
+ MR.add(new SingleBTS(877, Double.NaN, -93, true, new Date(), "lookup",
+ 10));
+
+ ArrayList<SingleBTS> MR2 = new ArrayList<SingleBTS>();
+ MR2.add(new SingleBTS(806, Double.NaN, -87, true, new Date(), "lookup",
+ 2.04));
+ MR2.add(new SingleBTS(817, Double.NaN, -91, true, new Date(), "lookup",
+ 2.25));
+ MR2.add(new SingleBTS(815, Double.NaN, -88, true, new Date(), "lookup",
+ 1.32));
+ MR2.add(new SingleBTS(823, Double.NaN, -85, true, new Date(), "lookup",
+ 1.47));
+ MR2.add(new SingleBTS(871, Double.NaN, -62, true, new Date(), "lookup",
+ 20.4));
+ MR2.add(new SingleBTS(880, Double.NaN, -81, true, new Date(), "lookup",
+ 10.658));
+ MR2.add(new SingleBTS(877, Double.NaN, -97, true, new Date(), "lookup",
+ 10));
+
+ /*
+ * MR.add(new SingleBTS(806, Double.NaN, -88, true, new Date(),
+ * "lookup")); MR.add(new SingleBTS(817, Double.NaN, -90, true, new
+ * Date(), "lookup")); MR.add(new SingleBTS(815, Double.NaN, -86, true,
+ * new Date(), "lookup")); MR.add(new SingleBTS(823, Double.NaN, -87,
+ * true, new Date(), "lookup")); MR.add(new SingleBTS(871, Double.NaN,
+ * -63, true, new Date(), "lookup")); MR.add(new SingleBTS(880,
+ * Double.NaN, -83, true, new Date(), "lookup")); MR.add(new
+ * SingleBTS(877, Double.NaN, -93, true, new Date(), "lookup"));
+ */
+ System.out.println("slightly altered");
+ return MR;
+ }
+
+ @SuppressWarnings("unused")
+ private static ArrayList<SingleBTS> getBermuda() {
+ ArrayList<SingleBTS> MR = new ArrayList<SingleBTS>();
+
+ MR.add(new SingleBTS(806, Double.NaN, -93, true, new Date(), "lookup",
+ 3.4));
+ MR.add(new SingleBTS(817, Double.NaN, -88, true, new Date(), "lookup",
+ 5.65));
+ MR.add(new SingleBTS(815, Double.NaN, -85, true, new Date(), "lookup",
+ 5.1));
+ MR.add(new SingleBTS(823, Double.NaN, -47, true, new Date(), "lookup",
+ 12.36));
+ MR.add(new SingleBTS(880, Double.NaN, -92, true, new Date(), "lookup",
+ 10.6));
+ MR.add(new SingleBTS(877, Double.NaN, -68, true, new Date(), "lookup",
+ 9.1));
+ return MR;
+ }
+
+ private static ArrayList<SingleBTS> getMensa() {
+ ArrayList<SingleBTS> MR = new ArrayList<SingleBTS>();
+ MR.add(new SingleBTS(806, Double.NaN, -95, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(817, Double.NaN, -91, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(815, Double.NaN, -86, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(823, Double.NaN, -86, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(871, Double.NaN, -75, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(880, Double.NaN, -74, true, new Date(), "lookup"));
+ MR.add(new SingleBTS(877, Double.NaN, -87, true, new Date(), "lookup"));
+ return MR;
+ }
+
+ private static ArrayList<SingleBTS> subtractBTS(ArrayList<SingleBTS> MR,
+ double value) {
+ ArrayList<SingleBTS> result = new ArrayList<SingleBTS>();
+ for (int i = 0; i < MR.size(); i++) {
+ int arfcn = MR.get(i).ARFCN;
+ double RXul = MR.get(i).getUldB();
+ double RXdl = MR.get(i).getDldB();
+ double var = MR.get(i).getVarianceDLdB();
+ SingleBTS element = new SingleBTS(arfcn, RXul, RXdl, true,
+ new Date(), "lookup", var);
+ result.add(element);
+ }
+ return result;
+ }
+
+ public gsmBayes(GSMMap map) {
+ this.map = map;
+ // generate difference between multiple BTSs.
+ // For example: arfcn 877 - arfcn 880, 877-823,...
+ // get OpenBSC arfcn's to calculate ratios
+
+ // go over all tiles and calculate the probability that this RSS-vector
+ // falls within this tile. Use the gaussian assumption here!
+ // than, return all tiles until they sum up to confidence
+
+ }
+
+ /**
+ * Makes a scoremap to a SORTED one dimensional PossibilityObject Array.
+ * Calculates the entropy on the way and prints to Console
+ *
+ * @param scoremap
+ * @return
+ */
+ private static PossibilityObject[] toPossibility(double[][] scoremap) {
+ int gsmmapsize = (scoremap.length + 1) * (scoremap[0].length + 1);
+ // PossibilityObject[] possibilities = new
+ // PossibilityObject[gsmmapsize];
+ ArrayList<PossibilityObject> result = new ArrayList<PossibilityObject>(
+ gsmmapsize);
+ double entropy = 0;
+ for (int x = 0; x < scoremap.length; x++) {
+ for (int y = 0; y < scoremap[0].length; y++) {
+ if (scoremap[x][y] != 0) {
+ entropy = entropy + scoremap[x][y]
+ * (Math.log(scoremap[x][y]));
+ }
+ PossibilityObject current = new PossibilityObject();
+ current.possibility = scoremap[x][y];
+ current.x = x;
+ current.y = y;
+ result.add(current);
+ }
+
+ }
+
+ System.out.println("Entropy dieser Wahrscheibnlichkeitskarte: "
+ + (entropy * (-1)));
+ PossibilityObject[] possibilities = result
+ .toArray(new PossibilityObject[1]);
+ Arrays.sort(possibilities);
+ return possibilities;
+ }
+
+ /**
+ * Returns all possible tiles that fall within the confidence. Output is the
+ * tile coordinate within the gsm map. DO NOT USE IN THE MOMENT!!!!!
+ *
+ * @param MR
+ * The measurement from the phone that you want to locate
+ * @return
+ */
+ @SuppressWarnings("unused")
+ static private Point[] search(List<SingleBTS> MR, GSMMap map,
+ double confidence) {
+ double[][] possibility = new double[map.Xcoords.length][map.Ycoords.length];
+ double rssProbability = 0;
+ rssProbability = getProbOfMR(map);
+
+ for (int x = 0; x < map.Xcoords.length; x++) {
+ for (int y = 0; y < map.Ycoords.length; y++) {
+ possibility[x][y] = getPossibility(map.map[x][y], MR,
+ rssProbability);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Computes just raw score (not probability) for each tile with given MR
+ *
+ * @param MR
+ * @param map
+ * @return
+ */
+ static public double[][] computeScore(List<SingleBTS> MR, GSMMap map) {
+
+ // get Vector how to sort!!! Important so that subtraction with NaN
+ // doesnÄt destroy too much Information!
+ SingleBTS[] sortVector = getSortVector(MR, map.content());
+ // sortVector = MR.toArray(new SingleBTS[0]);
+ ArrayList<SingleBTS> sortedMR = substituteMR(MR, sortVector);
+ // get ratio map
+ ratioElem[][][] ratiomap = getRatio(map, sortVector);
+
+ // get RatioVector for MR:
+ // make a (shallow) copy of MR to work with
+ // ArrayList<SingleBTS> sortedMR = new ArrayList<SingleBTS>(MR);
+ // take the measured MR. Make it to a complete Measurement vector.
+ // SingleBTS[] content = map.content();
+ // Arrays.sort(content, new BTSArfcnComparator());
+ // sortedMR = substituteMR(sortedMR, content);
+ // now MR is a complete Vector
+ // sort MR: ascending arfcn. Its the same order as in ratiomap
+ // Collections.sort(sortedMR, new BTSArfcnComparator());
+
+ // get Ratio out of sortedMR (MeasurementReportRatio)
+ ratioElem[] MRRatio = new ratioElem[sortedMR.size() - 1];
+ for (int i = 0; i < sortedMR.size() - 1; i++) {
+ MRRatio[i] = new ratioElem(sortedMR.get(i), sortedMR.get(i + 1));
+ }
+
+ // now we can do the Bayes stuff with sortedMR and ratioElem
+ // first get probability that sortedMR appears in ratiomap
+ double[][] probabilitymap = doBayes(MRRatio, ratiomap);
+
+ return probabilitymap;
+ }
+
+ private static SingleBTS[] getSortVector(List<SingleBTS> mR,
+ SingleBTS[] content) {
+ ArrayList<SingleBTS> result = new ArrayList<SingleBTS>(content.length);
+ ArrayList<SingleBTS> NaNs = new ArrayList<SingleBTS>(content.length);
+ for (int i = 0; i < content.length; i++) {
+ SingleBTS element = ListBTS.getARFCN(mR, content[i]);
+ if (element != null) {
+ result.add(element);
+ } else {
+ NaNs.add(new SingleBTS(content[i].ARFCN, Double.NaN,
+ Double.NaN, true, new Date(), content[i].name));
+ }
+ }
+
+ result.addAll(NaNs);
+
+ return result.toArray(new SingleBTS[content.length]);
+ }
+
+ private static double[][] doBayes(ratioElem[] MRRatio,
+ ratioElem[][][] ratiomap) {
+
+ double[][] score = new double[ratiomap.length][ratiomap[0].length];
+ double totalProb = 0;
+ for (int x = 0; x < ratiomap.length; x++) {
+ for (int y = 0; y < ratiomap[0].length; y++) {
+ // if (x == 48 && y == 14) {
+ // System.out.println("halt!");
+ // }
+ totalProb += getProbOfSingleHit(ratiomap[x][y], MRRatio);
+ }
+ }
+ double numberTiles = (ratiomap.length * ratiomap[0].length);
+ totalProb = totalProb / numberTiles;
+
+ // now we have P(S):totalProb
+
+ for (int x = 0; x < ratiomap.length; x++) {
+ for (int y = 0; y < ratiomap[0].length; y++) {
+ score[x][y] = (getProbOfSingleHit(MRRatio, ratiomap[x][y]) * (1 / numberTiles))
+ / totalProb;
+ }
+ }
+
+ return score;
+ }
+
+ private static double getProbOfSingleHit(ratioElem[] MapRatio,
+ ratioElem[] MRRatio) {
+ double probability = 1;
+ // for now: MR is without variance! and only Downlink!
+ for (int i = 0; i < MapRatio.length; i++) {
+ probability *= MapRatio[i].probability(MRRatio[i]);
+ }
+
+ if (probability > 0) {
+ // System.out.println("Probability größer 0! gut! Debug");
+ }
+ if (Double.isNaN(probability)) {
+ System.out.println("Probability = NaN");
+ }
+
+ return probability;
+ }
+
+ /**
+ * Sort content before use! Takes a list of measurements (MR) and checks if
+ * it contains all the elements given in content. If not, this element gets
+ * added with NaN value. MR itself is not altered. Elements are ordered
+ * accordingly to content. If content was ordered to e.g. arfcn, so the
+ * result. At the end, all Ratios with NaN get pushed
+ *
+ * @param mR
+ * @param content
+ * @return
+ */
+ private static ArrayList<SingleBTS> substituteMR(List<SingleBTS> mR,
+ SingleBTS[] content) {
+ // TODO Auto-generated method stub
+ ArrayList<SingleBTS> result = new ArrayList<SingleBTS>(content.length);
+ // ArrayList<SingleBTS> NaNs = new ArrayList<SingleBTS>(content.length);
+ SingleBTS element;
+ for (int i = 0; i < content.length; i++) {
+ if ((element = helper.ListBTS.getARFCN(mR, content[i])) != null) {
+ // result.add(element);
+ } else {
+ // BTS not there. Put in Double.NaN instead!
+ element = new SingleBTS(content[i].ARFCN, Double.NaN,
+ Double.NaN, true, new Date(), content[i].name);
+ // element = new SingleBTS(content[i].ARFCN, -999, -999, true,
+ // new Date(), content[i].name);
+ // NaNs.add(element);
+
+ }
+ // Collections.sort(NaNs, new BTSArfcnComparator());
+ result.add(element);
+ // result.addAll(NaNs);
+ }
+
+ // now, sort NaN
+
+ return result;
+ }
+
+ /**
+ * Returns all Ratios out of MapElement that can be build using the
+ * measurements from MR. Non existing elements are substituted with NaN.
+ *
+ * @param MR
+ * that is to be located
+ * @return
+ */
+ private static ratioElem[][][] getRatio(GSMMap map, SingleBTS[] sortVector) {
+
+ // sort the map content. This makes sure that RSSVector is sorted
+ // accordingly
+ SingleBTS[] content = sortVector;
+ // Arrays.sort(content, new BTSArfcnComparator());
+
+ // create ratioMap
+ ratioElem[][][] ratiomap = new ratioElem[map.Xcoords.length][map.Ycoords.length][content.length - 1];
+
+ // built ratio for every cell in map
+ for (int x = 0; x < map.Xcoords.length; x++) {
+ for (int y = 0; y < map.Ycoords.length; y++) {
+ // substitute map at position [x][y] to get full Vector
+ // ArrayList<SingleBTS> RSSVector = new ArrayList<SingleBTS>(
+ // map.map[x][y]);
+ ArrayList<SingleBTS> RSSVector = substituteMR(map.map[x][y],
+ sortVector);
+
+ // debug: only if RSSVector has some stuff inside
+ // if (!RSSVector.isEmpty() && RSSVector.get(0).getDldB() < 0) {
+ // System.out.println("etwas da!");
+ // }
+
+ // get full vector
+ // RSSVector = substituteMR(RSSVector, content);
+ // sort the vector. Not needed. already sorted
+ // Collections.sort(RSSVector, new BTSArfcnComparator());
+ // built ratios
+ for (int i = 0; i < content.length - 1; i++) {
+ ratiomap[x][y][i] = new ratioElem(RSSVector.get(i),
+ RSSVector.get(i + 1));
+ }
+ }
+ }
+
+ // TODO Auto-generated method stub
+ return ratiomap;
+ }
+
+ /**
+ * Returns the probability that this measurement is received within map
+ *
+ * @param map
+ * @return
+ */
+ private static double getProbOfMR(GSMMap map) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ * Calculates the possibility that MR was received on this tile's
+ * RSS-Vector.
+ *
+ * @param rssVector
+ * @param MR
+ * @param PRssV
+ * Probability that MR is received
+ * @return
+ */
+ private static double getPossibility(ArrayList<SingleBTS> rssVector,
+ List<SingleBTS> MR, double PRssV) {
+ // get all ratios out of MR. Compare with rssVector
+
+ // TODO Auto-generated method stub
+ return 0;
+ }
+}
+
+/*
+ * class ratioBTS { SingleBTS own; SingleBTS second;
+ *
+ * public ratioBTS(SingleBTS ownBTS, SingleBTS second) { this.own = ownBTS;
+ * this.second = second; }
+ *
+ * public double getRatioDL() { return own.getDldB() - second.getDldB(); }
+ *
+ * public double getRatioUL() { if (own.fullBTS && second.fullBTS) { return
+ * own.getUldB() - second.getUldB(); } return Double.NaN; } }
+ */
+
+/**
+ * Comperator that computes the ARFCN of this bts
+ *
+ * @author richy
+ *
+ */
+class BTSArfcnComparator implements Comparator<SingleBTS> {
+
+ public int compare(SingleBTS bts1, SingleBTS bts2) {
+
+ if (((SingleBTS) bts1).ARFCN > ((SingleBTS) bts2).ARFCN) {
+ return 1;
+ } else if (((SingleBTS) bts1).ARFCN < ((SingleBTS) bts2).ARFCN) {
+ return -1;
+ } else
+ return 0;
+
+ }
+}
+
+/**
+ * Everything in dBm!
+ *
+ * @author richy
+ *
+ */
+class ratioElem2 {
+ SingleBTS top;
+ SingleBTS bottom;
+ double ratioDL;
+ double ratioUL;
+ double varDL;
+ double varUL;
+
+ public ratioElem2(SingleBTS top, SingleBTS bottom) {
+ this.top = top;
+ this.bottom = bottom;
+
+ // double topUL = top.getDldB();
+ // double bottomUL = bottom.getDldB();
+
+ ratioDL = top.getDldB() - bottom.getDldB();
+ ratioUL = top.getUldB() - bottom.getUldB();
+ // varDL = Math.sqrt(Math.pow(top.getVarianceDLdB(), 2));
+ // - Math.pow(bottom.getVarianceDLdB(), 2));
+ // varUL = Math.sqrt(Math.pow(top.getVarianceULdB(), 2)
+ // - Math.pow(bottom.getVarianceULdB(), 2));
+ varDL = top.getVarianceDLdB() + bottom.getVarianceDLdB();
+ varUL = top.getVarianceULdB() + bottom.getVarianceULdB();
+ // if (varDL != 0 && varDL != Double.NaN) {
+ // System.out.println("var ungleich 0");
+ // }
+ }
+
+ public String toString() {
+ return "RatioDL: " + ratioDL + ", varDl: " + varDL;
+ }
+
+ public double probability(ratioElem vector) {
+
+ if (top.ARFCN != vector.top.ARFCN
+ || bottom.ARFCN != vector.bottom.ARFCN) {
+ System.out.println("Sortierung falsch!");
+ }
+
+ if (Double.isNaN(vector.ratioDL) || Double.isNaN(this.ratioDL)) {
+ if (Double.isNaN(vector.ratioDL) && Double.isNaN(this.ratioDL)) {
+ // ratio between both bts cannot been built. This means top or
+ // bottom bts is not received. let's say a cell phone has a poor
+ // antenna, than this would not neccesarily mean that the
+ // probability of beeing there is one. It can although be used
+ // to
+ // boost the probability
+ return 1;
+ } else
+ return 0;
+ }
+
+ if (vector.varDL == 0 && this.varDL == 0) {
+ if (Math.abs(vector.ratioDL - this.ratioDL) <= 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ /*
+ * if (this.ratioDL == Double.NaN && vector.ratioDL == Double.NaN) {
+ * return 1; } else if (this.ratioDL != Double.NaN && vector.ratioDL ==
+ * Double.NaN) { return Double.MIN_VALUE; } else if (this.ratioDL ==
+ * Double.NaN && vector.ratioDL != Double.NaN) { return
+ * Double.MIN_VALUE; } else if (this.ratioDL == 0 && vector.ratioDL ==
+ * 0) { return 1; } else if (this.ratioDL == 0 && vector.ratioDL ==
+ * Double.NaN) { return 1; } else if (this.ratioDL == Double.NaN &&
+ * vector.ratioDL == 0) { return 1; }
+ *
+ * else
+ */if (vector.varDL == 0 && this.varDL != 0) {
+ // compute just value at given point. No integration!
+ double std = Math.sqrt(varDL);
+ double x = vector.ratioDL;
+ double u = this.ratioDL;
+ double sqrtPI = Math.sqrt(2 * Math.PI);
+ double exp = Math.exp(-0.5 * Math.pow((x - u) / std, 2));
+ double result = (1 / (std * sqrtPI)) * exp;
+ if (Double.isNaN(result))
+ return 0;
+ return result;
+ } else if (this.varDL == 0 && vector.varDL != 0) {
+ // compute just value at given point. No integration!
+ double std = Math.sqrt(vector.varDL);
+ double x = ratioDL;
+ double u = vector.ratioDL;
+ double sqrtPI = Math.sqrt(2 * Math.PI);
+ double exp = Math.exp(-0.5 * Math.pow((x - u) / std, 2));
+ double result = (1 / (std * sqrtPI)) * exp;
+ if (Double.isNaN(result))
+ return 0;
+ return result;
+ } else {
+ // integration!
+ // System.out.println("Integration now implemented!");
+ return new NormDistribution(ratioDL, varDL)
+ .intersection(new NormDistribution(vector.ratioDL,
+ vector.varDL));
+
+ }
+
+ }
+
+}
diff --git a/DataStructure/jdom.jar b/DataStructure/jdom.jar
new file mode 100644
index 0000000..65a1b3f
--- /dev/null
+++ b/DataStructure/jdom.jar
Binary files differ
diff --git a/DataStructure/ratioElem.java b/DataStructure/ratioElem.java
new file mode 100644
index 0000000..365f2f8
--- /dev/null
+++ b/DataStructure/ratioElem.java
@@ -0,0 +1,114 @@
+package DataStructure;
+
+class ratioElem {
+ SingleBTS top;
+ SingleBTS bottom;
+ double ratioDL;
+ double ratioUL;
+ double varDL;
+ double varUL;
+
+ public ratioElem(SingleBTS top, SingleBTS bottom) {
+ // if (top==null||bottom==null){
+ // return null;
+ // }
+
+ this.top = top;
+ this.bottom = bottom;
+
+ // double topUL = top.getDldB();
+ // double bottomUL = bottom.getDldB();
+
+ // ratioDL = top.getDldB() - bottom.getDldB();
+ ratioDL = top.getStrictDLdBAverage() - bottom.getStrictDLdBAverage();
+ ratioUL = top.getUldB() - bottom.getUldB();
+ // varDL = Math.sqrt(Math.pow(top.getVarianceDLdB(), 2));
+ // - Math.pow(bottom.getVarianceDLdB(), 2));
+ // varUL = Math.sqrt(Math.pow(top.getVarianceULdB(), 2)
+ // - Math.pow(bottom.getVarianceULdB(), 2));
+ varDL = top.getVarianceDLdB() + bottom.getVarianceDLdB();
+ varUL = top.getVarianceULdB() + bottom.getVarianceULdB();
+ // if (varDL != 0 && varDL != Double.NaN) {
+ // System.out.println("var ungleich 0");
+ // }
+ }
+
+ public String toString() {
+ return "RatioDL: " + ratioDL + ", varDl: " + varDL + " (" + top.ARFCN
+ + "-" + bottom.ARFCN + ")";
+ }
+
+ public double probability(ratioElem vector) {
+
+ if (top.ARFCN != vector.top.ARFCN
+ || bottom.ARFCN != vector.bottom.ARFCN) {
+ System.out.println("Sortierung falsch!");
+ }
+
+ if (Double.isNaN(vector.ratioDL) || Double.isNaN(this.ratioDL)) {
+ System.out.println("das sollte nicht passieren");
+ if (Double.isNaN(vector.ratioDL) && Double.isNaN(this.ratioDL)) {
+ // ratio between both bts cannot been built. This means top or
+ // bottom bts is not received. let's say a cell phone has a poor
+ // antenna, than this would not neccesarily mean that the
+ // probability of beeing there is one. It can although be used
+ // to
+ // boost the probability
+ return 1;
+ } else
+ return 0;
+ }
+
+ if (vector.varDL == 0 && this.varDL == 0) {
+ if (Math.abs(vector.ratioDL - this.ratioDL) <= 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ /*
+ * if (this.ratioDL == Double.NaN && vector.ratioDL == Double.NaN) {
+ * return 1; } else if (this.ratioDL != Double.NaN && vector.ratioDL ==
+ * Double.NaN) { return Double.MIN_VALUE; } else if (this.ratioDL ==
+ * Double.NaN && vector.ratioDL != Double.NaN) { return
+ * Double.MIN_VALUE; } else if (this.ratioDL == 0 && vector.ratioDL ==
+ * 0) { return 1; } else if (this.ratioDL == 0 && vector.ratioDL ==
+ * Double.NaN) { return 1; } else if (this.ratioDL == Double.NaN &&
+ * vector.ratioDL == 0) { return 1; }
+ *
+ * else
+ */if (vector.varDL == 0 && this.varDL != 0) {
+ // compute just value at given point. No integration!
+ double std = Math.sqrt(varDL);
+ double x = vector.ratioDL;
+ double u = this.ratioDL;
+ double sqrtPI = Math.sqrt(2 * Math.PI);
+ double exp = Math.exp(-0.5 * Math.pow((x - u) / std, 2));
+ double result = (1 / (std * sqrtPI)) * exp;
+ if (Double.isNaN(result))
+ return 0;
+ return result;
+ } else if (this.varDL == 0 && vector.varDL != 0) {
+ // compute just value at given point. No integration!
+ double std = Math.sqrt(vector.varDL);
+ double x = ratioDL;
+ double u = vector.ratioDL;
+ double sqrtPI = Math.sqrt(2 * Math.PI);
+ double exp = Math.exp(-0.5 * Math.pow((x - u) / std, 2));
+ double result = (1 / (std * sqrtPI)) * exp;
+ if (Double.isNaN(result))
+ return 0;
+ return result;
+ } else {
+ // integration!
+ // System.out.println("Integration now implemented!");
+ return new NormDistribution(ratioDL, varDL)
+ .intersection(new NormDistribution(vector.ratioDL,
+ vector.varDL));
+
+ }
+
+ }
+
+}