H:\SEAMCAT\STG_30 Sept 2011 CPH\contribution to STG30 rev3\LocationProbability_rev1.java

    import java.awt.Color;

    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.text.DecimalFormat;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Locale;
    import java.util.Vector;

    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JProgressBar;

    import org.seamcat.model.plugin.*;

    /**
     *
     *
     * {@literal }
     *
     * <p>
     * <strong>CollectPositionData</strong> records the simulated positions of the
     * victim receiver and the levels of the wanted and unwanted signals.</br> It
     * gives the option to show the location distribution combined with dRSS, C/I,
     * C(I+N) as well as the location probability.</br> It does not change any
     * simulated result.
     * </p>
     * <p>
     * To draw the figures it uses the class StdDraw. For documentation, see Section
     * 1.5 of <i>Introduction to Programming in Java: An Interdisciplinary Approach,
     * Spring 2007 preliminary version</i> and <a href
     * ="http://www.cs.princeton.edu/introcs/15inout">http://www.cs.princeton.edu
     * /introcs/15inout</a>
     * </p>
     *
     * @author Karl Koch <a href= "mailto: adhoc@heiseka.de">adhoc@heiseka.de</a>
     * @version rev1 26-August-2011
     * bug fix on considering the pixels below the required location probability when calculating the probabilities of exceeding the protection limit
     */
    public class LocationProbability_rev1

    implements PostProcessingPlugin, ConsistencyCheck {

            private PluginDistribution defaultDistribution;
            private String filename = ""; // left empty as it is user dependent
            private String defaultPath = "";
            private String pathToSave; // combines defaultPath and filename
            private boolean shouldBeSaved = false; // flag whether the output file should be generated
            private Vector<String> outputFormat = null; // list for combobox output
            private Vector<String> outputFigure = null; // list for figure to be drawn
            private Vector<String> criterion = null; // list for the protection criterion to be used for the calculation of exceeding limits
            private int outputFormatIndex = 1; // sets .xml as default
            private int outputFigureIndex = 3; // default LP EBU
            private int criterionIndex = 1; // // default C/(I+N)
            private int currentEvent;
            private int totalEvents;
            private double[] oneShot; // used to copy not changed positions
            private String header;
            private int countVector;
            private double maxDistance = 0;
            private Transceiver rWt; // needed to record the distance between Vr and Wt
            private CollectedData singleResult = new CollectedData(); // new object containing the simulated values of a single shot
            private Vector<CollectedData> simulatedResults = null; // collects all singleResult
            private boolean multipleLinks = false;
            private double rCoverN = 20; // in dB
            private double rCoverI = 20;
            private double rIoverN = 0;
            private double simulationRadius = 6.7; // in km
            private double locationProbability = 95.0; // in %
            private Vector<Double> rLP; // collects the calculated location probabilities
            private double minDRSS = -86.15;// dRSS required for LP = 95%
            private double STDDEV = 5.5; // standard deviation
            private double stddevInterferer = 0; // standard deviation
            private DecimalFormat df = new DecimalFormat();
            private Color notAffected;
            private String sNotAffected = "100,100,100";
            private boolean sholdShowCalculatedResults = true;
            private boolean useEBU;
            private int numberOfPixelsBelowLP;
            private int numberOfPixelsInterfered;
            private int numberOfEventsToBeConsidered;

            public void init(ParameterFactory param) {
                    defaultDistribution = param.createDistribution(
                                    PluginDistribution.DistributionType.PolarDistance, 0, 1);
                    defaultDistribution.trial();

                    /** fills the fields of the combobox */
                    outputFormat = new Vector<String>();
                    outputFormat.add(".txt");
                    outputFormat.add(".xml");
                    outputFormat.add("");

                    outputFigure = new Vector<String>();
                    outputFigure.add("dRSS ");
                    outputFigure.add("C/I ");
                    outputFigure.add("C/(N+I)");
                    outputFigure.add("Location Probability (EBU)");
                    outputFigure.add("dRSS Location Probability");
                    outputFigure.add("Pixel distribution");
                    outputFigure.add("none");

                    criterion = new Vector<String>();
                    criterion.add("C/I");
                    criterion.add("C/(I + N)");
                    criterion.add("I/N");
            }

            public void cleanUp() {
                    // nothing to do
            }

            public String getDescription() {
                    return "This plug-in is to collect data in terms of positions and levels";
            }

            /**
             * method called after each snapshot = the 'heart' of the plugin :)
             */
            public void process(ScenarioInfo scenario) throws Exception {

                    currentEvent = scenario.getCurrentEventNumber();

                    if (currentEvent <= scenario.getNumberOfInterferingLinks()) {
                            // makes sure that all variables from the workspace are available and initializes the values
                            initPlugin(scenario);

                    } else if (currentEvent == totalEvents) { // end of the simulation
                            setNumberOfPixelsBelowLP(scenario);
                            setNumberOfPixelsInterfered(scenario);
                            calculateLocationProbability(scenario);
                            if (shouldBeSaved)
                                    storeResults(scenario);
                            try {
                                    showResults(scenario);
                            } catch (Exception e) {
                                    e.printStackTrace();
                            }
                    } else if (currentEvent > scenario.getNumberOfInterferingLinks()) {
                            // to start collecting data with the first interfering link
                            readPosition(scenario);
                            readDRSS(scenario);
                            readIRSS(scenario);
                    }

            }

            /**
             *
             * @param scenario
             */
            private void initPlugin(ScenarioInfo scenario) {
                    totalEvents = scenario.getTotalNumberOfEvents();
                    setNumberOfEventsToBeConsidered(scenario);
                    initWorkspace(scenario);
                    if (outputFigureIndex == 3) { // EBU approach only
                            setUseEBU(true);
                    } else {
                            setUseEBU(false);
                    }
                    /**
                     * forces the use of decimal point independent on the Locale and formats
                     * the output
                     */
                    df = (DecimalFormat) DecimalFormat.getInstance(Locale.US);
                    df.applyPattern("###.0#");

                    simulatedResults = new Vector<CollectedData>(); // CollectedData of the data simulated

                    notAffected = getColorNotAffected(sNotAffected); // may become useless

                    countVector = 0; // vector to the rows of the table

                    header = "event;x;y;dRSS;iRSS;noiseFloor;multiple;ilk;CoverN"; // used only for the .txt-output
                    maxDistance = 0; // reset in case the simulation radius has been changed

                    if (outputFormatIndex == 0 && filename.indexOf(".") == -1)
                            filename += ".txt";
                    else if (outputFormatIndex == 1 && filename.indexOf(".") == -1)
                            filename += ".xml";

                    if (filename.indexOf(".") == -1) {// sets xml as default in case no extension selected
                            outputFormatIndex = 1;
                            filename += ".xml";
                    }
            }

            /**
             * {@literal tries to avoid an exception }
             */
            private boolean checkFilenameAndPath() {
                    if (filename.equals("") || defaultPath.equals("")) {
                            return false;
                    } else {
                            return true;
                    }
            }

            /**
             *
             * @param scenario
             */
            private void initWorkspace(ScenarioInfo scenario) {
                    rWt = scenario.getVictimLink().getTransmitter(); // needed to get the max distance
                    double radius = scenario.getVictimLink().getReceiver()
                                    .getDistanceTo(rWt);
                    if (radius > maxDistance)
                            maxDistance = radius; // used to scale the plot

                    rCoverN = scenario.getVictimLink().getReceiver().getRequiredCNIRatio(); // means  C/(I+N)
                    rCoverI = scenario.getVictimLink().getReceiver().getRequiredCIRatio();
                    rIoverN = scenario.getVictimLink().getReceiver().getRequiredINRatio();
            }

            /**
             *
             * @param scenario
             */
            private void storeResults(ScenarioInfo scenario) {
                    /** the extension of the file name defines the output format */
                    String part = filename.substring(filename.indexOf(".") + 1);
                    if (part.equals("txt"))
                            saveResults(scenario); // as .txt file
                    else if (part.equals("xml"))
                            saveResultsXML(scenario);
                    /*
                     * else if (part.equals("csv")) { saveResults(scenario); // as .csv file
                     * } // doesn't work correctly as the format is wrong
                     */
                    else {
                            // TODO if other extension should be added
                    }
            }

            /**
             *
             * @param scenario
             * @throws Exception
             */
            private void showResults(ScenarioInfo scenario) throws Exception {
                    /**
                     * selects the kind of figure and data to be shown as a graph
                     */
                    switch (outputFigureIndex) {
                            case 0: {
                                    setUseEBU(false);
                                    drawDRSS_Colored(scenario);
                                    break;
                            }
                            case 1: {
                                    setUseEBU(false);
                                    drawCoverIColored(scenario);
                                    break;
                            }
                            case 2: {
                                    setUseEBU(false);
                                    drawCoverNplusI_Colored(scenario);
                                    break;
                            }
                            case 3: {// EBU approach
                                    setUseEBU(true);
                                    drawLocationProbability(scenario);
                                    break;
                            }
                            case 4: {
                                    setUseEBU(false);
                                    drawLocationProbability(scenario);
                                    break;
                            }
                            case 5: {
                                    setUseEBU(false);
                                    drawPixelsAffected(scenario);
                                    break;
                            }
                            default: {
                                    setUseEBU(false);
                                    // do nothing
                            }
                    }
                    /** show message with simulated results */
                    if (sholdShowCalculatedResults) {
                            if (rLP.size() == 0)
                                    calculateLocationProbability(scenario); // to ensure that LP distribution is available
                            try {
                                    showSimulatedResults(scenario);
                            } catch (Exception e) {
                                    e.printStackTrace();
                            }
                    }
            }

            private void setUseEBU(boolean useEBU) {
                    this.useEBU = useEBU;

            }

            public int getNumberOfParameters() {
                    return 12;
            }

            public ParameterType getParameterType(int id) {
                    switch (id) {
                            case 1: {
                                    return ParameterType.String; // filename for the output
                            }
                            case 2: {
                                    return ParameterType.String; // default path for the output files
                            }
                            case 3: {
                                    return ParameterType.Integer; // outputFormatIndex
                            }
                            case 4: {
                                    return ParameterType.Boolean; // flag to save output
                            }
                            case 5: {
                                    return ParameterType.Integer; // flag for drawing the figure
                            }
                            case 6: {
                                    return ParameterType.Double; // simulation radius
                            }
                            case 7: {
                                    return ParameterType.Double; // location probability
                            }
                            case 8: {
                                    return ParameterType.Double; // dRSS
                            }
                            case 9: {
                                    return ParameterType.Double; // stddev of dRSS
                            }
                            case 10: {
                                    return ParameterType.Double; // stddev of interferer
                            }
                            case 11: {
                                    return ParameterType.Integer; // to protection criterion
                            }
                            case 12: {
                                    return ParameterType.Boolean; // flag to showing calculated results
                            }
                            default: {
                                    throw new IllegalArgumentException("illegal parameter id");
                            }

                    }
            }

            public void setParameterValue(int id, Object value) {
                    try {
                            switch (id) {
                                    case 1: {
                                            this.filename = (String) value;
                                            break;
                                    }
                                    case 2: {
                                            this.defaultPath = (String) value;
                                            break;
                                    }
                                    case 3: {
                                            this.outputFormatIndex = (Integer) value;
                                            break;
                                    }
                                    case 4: {
                                            this.shouldBeSaved = (Boolean) value;
                                            break;
                                    }
                                    case 5: {
                                            this.outputFigureIndex = (Integer) value;
                                            break;
                                    }
                                    case 6: {
                                            this.simulationRadius = (Double) value;
                                            break;
                                    }
                                    case 7: {
                                            this.locationProbability = (Double) value;
                                            break;
                                    }
                                    case 8: {
                                            this.minDRSS = (Double) value;
                                            break;
                                    }
                                    case 9: {
                                            this.STDDEV = (Double) value;
                                            break;
                                    }
                                    case 10: {
                                            this.stddevInterferer = (Double) value;
                                            break;
                                    }
                                    case 11: {
                                            this.criterionIndex = (Integer) value;
                                            break;
                                    }
                                    case 12: {
                                            this.sholdShowCalculatedResults = (Boolean) value;
                                            break;
                                    }
                                    default: {
                                            throw new IllegalArgumentException("illegal parameter id");
                                    }
                            }
                    } catch (Exception e) {

                    }
            }

            public Object getParameterValue(int id) {
                    switch (id) {
                            case 1: {
                                    return this.filename;
                            }
                            case 2: {
                                    return this.defaultPath;
                            }
                            case 3: {
                                    return this.outputFormatIndex;
                            }
                            case 4: {
                                    return this.shouldBeSaved;
                            }
                            case 5: {
                                    return this.outputFigureIndex;
                            }
                            case 6: {
                                    return this.simulationRadius;
                            }
                            case 7: {
                                    return this.locationProbability;
                            }
                            case 8: {
                                    return this.minDRSS;
                            }
                            case 9: {
                                    return this.STDDEV;
                            }
                            case 10: {
                                    return this.stddevInterferer;
                            }
                            case 11: {
                                    return this.criterionIndex;
                            }
                            case 12: {
                                    return this.sholdShowCalculatedResults;
                            }
                            default: {
                                    throw new IllegalArgumentException("illegal parameter id");
                            }

                    }
            }

            public String getParameterName(int id) {
                    switch (id) {
                            case 1: {
                                    return "file name of the output data";
                            }

                            case 2: {
                                    return "default path ";
                            }
                            case 3: {
                                    return "output format ";
                            }

                            case 4: {
                                    return "save output file ";
                            }
                            case 5: {
                                    return "parameter to be drawn";
                            }

                            case 6: {
                                    return "simulation radius  [km]";
                            }
                            case 7: {
                                    return "location probability [%]";
                            }
                            case 8: {
                                    return "minimum wanted Signal  [dBm]";
                            }
                            case 9: {
                                    return "standard deviation of the wanted signal [dB]";
                            }
                            case 10: {
                                    return "standard deviation of the interfering signal [dB]";
                            }
                            case 11: {
                                    return "protection criterion to be used for limit calculations";
                            }
                            case 12: {
                                    return "show calculated results ";
                            }
                            default: {
                                    throw new IllegalArgumentException("illegal parameter id");
                            }

                    }
            }

            /* check consistency of the workspace */
            public boolean check(ScenarioInfo scenario) {
                    boolean checkPropagationModel = true;
                    String warning = "<html><br>";
                    warning += "<br/><br/><strong>Post Processing Plugin: </strong>";
                    warning += "<br />Please ensure that the values of <br/><strong>C/I, C/(I+N) and I/N</strong><br/>"
                                    + "are defined as you want, even if there is still a consitency warning."
                                    + "<br>";

                    if (shouldBeSaved && !checkFilenameAndPath()) {
                            filename = "outputData.xml";
                            defaultPath = "C:";
                            pathToSave = defaultPath + "\\" + filename;
                            warning += "<br />Due to the location for the output files has not been defined,<br />the collected data will be saved onto <strong>"
                                            + pathToSave
                                            + "</strong> <br /> and the corresponding DTD onto <strong>C:\\result.dtd</strong>";

                    }
                    checkPropagationModel = false;
                    warning += "</html>";

                    if (checkPropagationModel == false) {
                            scenario.addConsistencyWarning(warning);
                            return false;
                    } else {
                            return true;
                    }
            }

            @Override
            public Vector<String> getAllowedParameterValues(int index) {

                    switch (index) {
                            case 3:
                                    return this.outputFormat;

                            case 5:
                                    return this.outputFigure;

                            case 11:
                                    return this.criterion;

                    }
                    return null;
            }

            /**
             * methods added
             *
             */

            /**
             * {@literal adds the current event number and the positions x and y of the victim to the current row; }
             * {@literal oneShot[] collects the values of event, x, y and dRSS which are not changed in case different interfering links have to be considered}
             *
             * @param scenario
             */
            private void readPosition(ScenarioInfo scenario) {
                    oneShot = new double[4]; // reset to zero
                    oneShot[0] = currentEvent;
                    oneShot[1] = scenario.getVictimLink().getReceiver().getPositionX();
                    oneShot[2] = scenario.getVictimLink().getReceiver().getPositionY();
                    double radius = scenario.getVictimLink().getReceiver()
                                    .getDistanceTo(rWt);
                    if (radius > maxDistance)
                            maxDistance = radius; // updates the max distance simulated; needed for the correct scaling of the plot
            }

            /**
             * {@literal adds the dRSS to the current row}
             *
             * @param scenario
             */
            private void readDRSS(ScenarioInfo scenario) {
                    oneShot[3] = scenario.getVictimLink().getDRSSValue();
            }

            /**
             * {@literal adds the iRSS and the index of the interfering link to the table; }
             * {@literal in case more than one interfering link exist the values for event, x, y and dRSS are copied}
             *
             * @param scenario
             * @throws Exception
             */
            private void readIRSS(ScenarioInfo scenario) {
                    List<InterferingLink> ilks = scenario.getInterferingLinks();
                    if (scenario.getNumberOfInterferingLinks() == 1)
                            multipleLinks = false;
                    else
                            multipleLinks = true;
                    for (InterferingLink link : ilks) {
                            singleResult = new CollectedData();
                            singleResult.event = (int) oneShot[0];
                            singleResult.x = oneShot[1];
                            singleResult.y = oneShot[2];
                            singleResult.dRSS = oneShot[3];
                            singleResult.iRSS = link.getIRSSUnwanted();
                            singleResult.cOverI = Math.abs(singleResult.dRSS
                                            - singleResult.iRSS);
                            singleResult.noiseFloor = getNoiseFloor(scenario);
                            //                      singleResult.noiseFloor = noiseFloor;
                            singleResult.isMultipleILK = multipleLinks;
                            singleResult.ilk = link.getLinkIndex();
                            try {
                                    singleResult.cOverN = getCoverNplusI(scenario);
                            } catch (Exception e) {
                                    e.printStackTrace();
                            }
                            singleResult.cIverN = getIoverN(scenario);
                            simulatedResults.add(singleResult);
                            countVector++; // Counter for the rows of the resulting table
                    }

            }

            private double getNoiseFloor(ScenarioInfo scenario) {
                    return scenario.getVictimLink().getReceiver().getNoiseFloor().trial();
            }

            /**
             * {@literal stores the generated table as text file }
             *
             * @param scenario
             */
            private void saveResults(ScenarioInfo scenario) {
                    pathToSave = defaultPath + "\\" + filename;
                    int fSize = (int) (scenario.getNumberOfInterferingLinks() * 6 * 20
                                    * totalEvents / 1024.0 / 1024.0 + 1); //
                    ProgressBarStoreFile progressstore = new ProgressBarStoreFile(
                                    "Saving TXT file in progress (about " + fSize + " MB)");
                    progressstore.init();
                    progressstore.progressBar.setMinimum(0);
                    progressstore.progressBar.setMaximum(countVector);
                    try {
                            BufferedWriter out = new BufferedWriter(new FileWriter(pathToSave));

                            out.write(header); // header of the columns of the table
                            out.newLine();

                            for (int i = 0; i < countVector; i++) {
                                    out.write(simulatedResults.get(i).event + ";");
                                    out.write(simulatedResults.get(i).x + ";");
                                    out.write(simulatedResults.get(i).y + ";");
                                    out.write(simulatedResults.get(i).dRSS + ";");
                                    out.write(simulatedResults.get(i).iRSS + ";");
                                    out.write(simulatedResults.get(i).noiseFloor + ";");
                                    out.write(simulatedResults.get(i).isMultipleILK + ";");
                                    out.write(simulatedResults.get(i).ilk + ";");
                                    out.write(simulatedResults.get(i).cOverN + "");
                                    out.newLine();
                                    progressstore.progressBar.setValue(i + 1);
                            }
                            out.flush();
                            out.close();
                            progressstore.stop();
                    } catch (IOException e) {
                            e.printStackTrace();
                    }

            }

            /**
             * {@literal saveResultsXML stores the result as XML file}
             */
            private void saveResultsXML(ScenarioInfo scenario) {
                    pathToSave = defaultPath + "\\" + filename;
                    int fSize = (int) (scenario.getNumberOfInterferingLinks() * 7 * 32
                                    * totalEvents / 1024.0 / 1024.0 + 1); // seven columns each 32 bytes
                    ProgressBarStoreFile progressstore = new ProgressBarStoreFile(
                                    "Saving XML file in progress (about " + fSize + " MB)");
                    progressstore.init();
                    progressstore.progressBar.setMinimum(0);
                    progressstore.progressBar.setMaximum(countVector);
                    try {
                            BufferedWriter out = new BufferedWriter(new FileWriter(pathToSave));
                            String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>";
                            String xmlRoot = "result";
                            String xmlElement = "event";

                            out.write(xmlDeclaration);
                            out.newLine();
                            out.write("<" + xmlRoot + ">");
                            out.newLine();
                            for (int i = 0; i < countVector; i++) {
                                    String element = "<" + xmlElement;
                                    element += " eventNr = \"" + simulatedResults.get(i).event;
                                    element += " \" x = \"" + simulatedResults.get(i).x;
                                    element += " \" y = \"" + simulatedResults.get(i).y;
                                    element += " \" dRSS = \"" + simulatedResults.get(i).dRSS;
                                    element += " \" iRSS = \"" + simulatedResults.get(i).iRSS;
                                    element += " \" noiseFloor = \""
                                                    + simulatedResults.get(i).noiseFloor;
                                    element += " \" multiple = \""
                                                    + simulatedResults.get(i).isMultipleILK;
                                    element += " \" ilk = \"" + simulatedResults.get(i).ilk;
                                    element += " \" CoverI = \"" + simulatedResults.get(i).cOverN
                                                    + "\">";
                                    element += "</" + xmlElement + ">";
                                    out.write(element);
                                    out.newLine();
                                    progressstore.progressBar.setValue(i + 1);
                            }
                            out.write("</" + xmlRoot + ">");
                            out.flush();
                            out.close();
                            storeDTD(); // saves the corresponding xml namespace as result.dtd
                            progressstore.stop();
                    } catch (IOException e) {
                            e.printStackTrace();
                    }
            }

            /**
             * {@literal storeDTD generates the DTD needed for the above XML file to that path the result has been saved}
             */
            private void storeDTD() {
                    try {
                            BufferedWriter out = new BufferedWriter(new FileWriter(defaultPath
                                            + "\\result.dtd"));
                            String DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <!ELEMENT result ((event+))> <!ELEMENT event EMPTY>"
                                            + "<!ATTLIST event      dRSS CDATA #REQUIRED    eventNr CDATA #REQUIRED "
                                            + "     iRSS CDATA #REQUIRED    noiseFloor CDATA #REQUIRED ilk CDATA #REQUIRED  x CDATA #REQUIRED       y CDATA #REQUIRED CoverI CDATA #REQUIRED multiple CDATA #REQUIRED>";

                            out.write(DTD);
                            out.flush();
                            out.close();
                    } catch (IOException e) {
                            e.printStackTrace();
                    }
            }

            /**
             * {@literal draws a figure using the class StdDraw} For additional
             * documentation, see <a
             * href="http://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
             * <i>Introduction to Programming in Java: An Interdisciplinary Approach</i>
             * by Robert Sedgewick and Kevin Wayne.
             *
             */

            /**
             * {@literal calculates the location probability of a pixel and collects is on a vector}
             *
             * @param scenario
             * @throws Exception
             */
            private void calculateLocationProbability(ScenarioInfo scenario)
                            throws Exception {
                    rLP = new Vector<Double>();
                    double testDRSS;
                    double deltaFactor = 0;
                    double percentage;
                    double tCoverNplusI = 0;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            testDRSS = simulatedResults.get(i).dRSS;
                            if (!simulatedResults.firstElement().isMultipleILK) {// single interfering link
                                    if (isUseEBU()) { // use the EBU approach considering C/(I+N)
                                            double tIRSS = simulatedResults.get(i).iRSS;
                                            tCoverNplusI = 10 * Math
                                                            .log10(Math.pow(10, (testDRSS / 10))
                                                                            / (Math.pow(10,
                                                                                            (simulatedResults.get(i).iRSS / 10)) + Math.pow(
                                                                                            10,
                                                                                            (simulatedResults.get(i).noiseFloor / 10))));

                                            deltaFactor = tCoverNplusI - rCoverN;
                                    } else { // only dRSS
                                            deltaFactor = testDRSS - minDRSS;
                                    }
                            } else {
                                    if (isUseEBU()) { // use the EBU approach considering C/(I+N)
                                            tCoverNplusI = 10 * Math
                                                            .log10(Math.pow(10, (testDRSS / 10))
                                                                            / (Math.pow(
                                                                                            10,
                                                                                            (getSumOfInterfernce(i, scenario) / 10.)) + Math.pow(
                                                                                            10,
                                                                                            (simulatedResults.get(i).noiseFloor / 10))));
                                            deltaFactor = tCoverNplusI - rCoverN;
                                    } else { // only dRSS
                                            deltaFactor = testDRSS - minDRSS;
                                    }
                                    i += scenario.getNumberOfInterferingLinks() - 1; // jumps to the next pixel
                            }
                            // in case stddev of interferer should be considered
                            double rSTDEEVcombined = Math.sqrt(STDDEV * STDDEV
                                            + stddevInterferer * stddevInterferer);
                            deltaFactor /= rSTDEEVcombined;

                            percentage = getPercentageSevenTrials(deltaFactor); // iterative approach

                            if (isUseEBU()) {
                                    if (tCoverNplusI <= 0)
                                            percentage = 0; //
                            } else {
                                    //      percentage = 100 - percentage; // as the location probability of the wanted signal
                            }
                            rLP.add(percentage);
                    }
            }

            /**
             *
             * @param i
             *            actual pixel index
             * @param scenario
             * @return integrated iRSS
             */
            private double getSumOfInterfernce(int i, ScenarioInfo scenario) {
                    double sumOfInterference = 0;
                    for (int j = 0; j < scenario.getNumberOfInterferingLinks(); j++) {
                            sumOfInterference += Math.pow(10,
                                            (simulatedResults.get(i + j).iRSS) / 10);
                    }
                    return 10 * Math.log10(sumOfInterference);
            }

            /**
             *
             * @return flag whether EBU approach should be used
             */
            private boolean isUseEBU() {
                    return this.useEBU;
            }

            /**
             *
             * @return highest value of location probability calculated
             */
            private double getMaxLP() {
                    double maxLP = 0;
                    for (int i = 0; i < rLP.size(); i++) {
                            if (rLP.get(i) > maxLP) {
                                    maxLP = rLP.get(i);
                            }
                    }
                    return maxLP;
            }

            /**
             *
             * @param scenario
             * @param j
             *            current pixel ID
             * @return corresponds to whether affected or not and defines the colour
             */
            private int getPixelStatus(ScenarioInfo scenario, int j) {
                    int rStatus = 2;
                    if (simulatedResults.get(j).dRSS < minDRSS) {
                            rStatus = 0;// not affected
                    } else if (!simulatedResults.get(j).isInterfered) {
                            rStatus = 1; // green
                    } else if (simulatedResults.get(j).isInterfered) {
                            rStatus = 2; // red
                    }
                    return rStatus;
            }

            /**
             * {@literal shows a message with simulated results }
             *
             * @param scenario
             * @throws Exception
             */
            private void showSimulatedResults(ScenarioInfo scenario) throws Exception {
                    if (rLP.size() == 0)
                            calculateLocationProbability(scenario); // to ensure that LP distribution is available

                    String msg = "Pixels not meeting min dRSS:     "
                                    + getNumberOfPixelsBelowLP() + "\n";
                    msg += "Pixels with interferer:                 "
                                    + getNumberOfPixelsInterfered() + "\n";
                    msg += "Number of pixels generated:      "
                                    + getNumberOfEventsToBeConsidered()
                                    + " ("
                                    + (df.format(getNumberOfEventsToBeConsidered()
                                                    / (maxDistance * maxDistance * Math.PI)))
                                    + "/sqkm)\n\n";
                    msg += "Probability of exceeding the limit of "
                                    + criterion.get(criterionIndex)
                                    + " = "
                                    + df.format(getCriterionLimit())
                                    + " dB due to interference:   "
                                    + (df.format((double) ((getNumberOfPixelsInterfered())
                                                    / (double) (getNumberOfEventsToBeConsidered() - getNumberOfPixelsBelowLP()) * 100.0)))
                                    + "%\n";
                    msg += "\nPercentage below minimum wanted Signal level:    "
                                    + (df.format((double) ((getNumberOfPixelsBelowLP())
                                                    / (double) (getNumberOfEventsToBeConsidered()) * 100.0)))
                                    + "%";
                    if (isUseEBU()) {
                            double degradation = ((double) (getNumberOfPixelsNotMeetingLP() - getNumberOfPixelsBelowLP()) / (double) (getNumberOfEventsToBeConsidered() - getNumberOfPixelsBelowLP())) * 100;

                            msg += "\nDegradation of location probability of "
                                            + locationProbability + "%:          "
                                            + (df.format(degradation)) + "%";
                    }
                    msg += "         ";// to expand the width

                    JFrame frame = new JFrame("Simulation results");
                    frame.setResizable(true);
                    frame.setSize(400, 400);
                    JOptionPane.showMessageDialog(frame, msg,
                                    "Simulation result of post processsing (LP="
                                                    + locationProbability + "%)",
                                    JOptionPane.INFORMATION_MESSAGE);
            }

            /**
             *
             * @return total number of pixels below required LP
             */
            private int getNumberOfPixelsNotMeetingLP() {
                    int k = 0;
                    for (int i = 0; i < rLP.size(); i++) {
                            if (rLP.get(i) < locationProbability) {
                                    k++;
                            }
                    }
                    return k;
            }

            /**
             *
             * @param scenario
             * @return number of pixels not meeting the limit caused only by noise floor
             * @throws Exception
             */
            private int getNumberOfPixelsEmpty(ScenarioInfo scenario) throws Exception {
                    int k = 0;
                    if (!simulatedResults.firstElement().isMultipleILK) { // single interfering link
                            for (int i = 0; i < simulatedResults.size(); i++) {
                                    if (simulatedResults.get(i).dRSS <= minDRSS) { // changed to <= instead of <
                                            k++;
                                    }
                            }
                    } else {
                            for (int i = 0; i < simulatedResults.size(); i++) {
                                    if (simulatedResults.get(i).dRSS <= minDRSS) {// changed to <= instead of <
                                            k++;
                                            i += scenario.getNumberOfInterferingLinks() - 1; // skips to next pixel
                                    }
                            }
                    }
                    return k;
            }

            /**
             *
             * @param scenario
             * @return number of pixels not meeting the limit
             */
            private int getNumberOfPixelsInterfered(ScenarioInfo scenario) {
                    int k = 0;

                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (!simulatedResults.firstElement().isMultipleILK) {// single interfering link
                                    if (getLimitExceeded(i)) {
                                            k++;
                                    }
                            } else {// more than one interfering link
                                    if (getLimitExceededMultiple(i, scenario)) {
                                            k++;
                                    }
                                    i += scenario.getNumberOfInterferingLinks() - 1; // jumps to next pixel
                            }
                    }
                    return k;
            }

            private boolean getLimitExceededMultiple(int i, ScenarioInfo scenario) {
                    // TODO Auto-generated method stub
                    double sumOfInterference = getSumOfInterfernce(i, scenario);
                    if (getLimitExceeded(i, sumOfInterference)) {
                            simulatedResults.get(i).isInterfered = true;
                            return true;
                    } else {
                            simulatedResults.get(i).isInterfered = false;
                            return false;
                    }
            }

            /**
             * {@literal shows a colour scaled distribution of C/I}
             *
             * @param scenario
             */
            private void drawCoverIColored(ScenarioInfo scenario) {
                    scaleFigure();
                    double highestCoverI = getHighestCoverI();
                    double lowestCoverI = getLowestCoverI();
                    double rCoverI = 0;
                    double range = Math.abs(highestCoverI - lowestCoverI);

                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (!simulatedResults.get(i).isMultipleILK) {
                                    rCoverI = simulatedResults.get(i).cOverI;
                            } else {
                                    rCoverI = getCoverImultiple(scenario, i); // gets the lowest CoverI for that pixel
                                    i += scenario.getNumberOfInterferingLinks() - 1;
                            }

                            Color colorAtIndex = getColor(rCoverI - lowestCoverI, range);
                            StdDraw.setPenColor(colorAtIndex);

                            StdDraw.filledSquare(simulatedResults.get(i).x,
                                            simulatedResults.get(i).y, 0.05, false);
                    }

                    /** legend */
                    drawScaling(lowestCoverI, highestCoverI, maxDistance, 20, " dB");
                    StdDraw.setPenColor(StdDraw.BLACK);
                    StdDraw.text(0, 1.05 * maxDistance, "C/I distribution");
                    StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                    + df.format(maxDistance) + " km");
                    StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                    (totalEvents - scenario.getNumberOfInterferingLinks())
                                                    + " events");

                    if (scenario.getNumberOfInterferingLinks() > 1) {
                            StdDraw.text(0.8 * maxDistance, -1 * maxDistance,
                                            scenario.getNumberOfInterferingLinks()
                                                            + " interfering links");
                    }
                    StdDraw.show();
            }

            /**
             * {@literal shows a colour scaled distribution of C/(N+I)}
             *
             * @param scenario
             */
            private void drawCoverNplusI_Colored(ScenarioInfo scenario) {

                    scaleFigure();

                    double lowestCoverN = getLowestCoverN();
                    double highestCoverN = getHighestCoverN();
                    double range = highestCoverN - lowestCoverN;
                    double testCoverN = 0;

                    for (int i = 0; i < simulatedResults.size(); i++) {
                            testCoverN = simulatedResults.get(i).cOverN;
                            if (simulatedResults.firstElement().isMultipleILK) {// more than one interfering link
                                    int j = 1;
                                    do {
                                            if (simulatedResults.get(i + j).cOverN < testCoverN) {
                                                    testCoverN = simulatedResults.get(i + j).cOverN;
                                                    j++;
                                            } else {
                                                    j++;
                                            }
                                    } while (j < scenario.getNumberOfInterferingLinks());
                                    i += scenario.getNumberOfInterferingLinks() - 1; // skips to the next pixel
                            }
                            Color colorAtIndex = getColor(testCoverN - lowestCoverN, range);
                            StdDraw.setPenColor(colorAtIndex);
                            StdDraw.filledSquare(simulatedResults.get(i).x,
                                            simulatedResults.get(i).y, 0.05, false);
                    }

                    /** legend */
                    drawScaling(lowestCoverN, highestCoverN, maxDistance, rCoverN, " dB");
                    StdDraw.setPenColor(StdDraw.BLACK);
                    StdDraw.text(0, 1.05 * maxDistance, "C/(N+I) distribution");
                    StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                    + df.format(maxDistance) + " km");
                    StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                    (totalEvents - scenario.getNumberOfInterferingLinks())
                                                    + " events");

                    if (scenario.getNumberOfInterferingLinks() > 1) {
                            StdDraw.text(0.8 * maxDistance, -1 * maxDistance,
                                            scenario.getNumberOfInterferingLinks()
                                                            + " interfering links");
                    }
                    StdDraw.show();

            }

            /**
             * {@literal draws a colour scaled map of the dRSS distribution}
             *
             * @param scenario
             */
            private void drawDRSS_Colored(ScenarioInfo scenario) {
                    scaleFigure();

                    double lowestDRSSS = getLowestDRSS();
                    double highestDRSSS = getHighestDRSS();
                    double range = highestDRSSS - lowestDRSSS;

                    for (int i = 0; i < simulatedResults.size(); i++) {
                            Color colorAtIndex = getColor(simulatedResults.get(i).dRSS
                                            - lowestDRSSS, range);
                            StdDraw.setPenColor(colorAtIndex);
                            StdDraw.filledSquare(simulatedResults.get(i).x,
                                            simulatedResults.get(i).y, 0.04, false);
                    }
                    /** legend */
                    drawScaling(getLowestDRSS(), getHighestDRSS(), maxDistance, -77.1,
                                    " dBm");
                    StdDraw.setPenColor(StdDraw.BLACK);
                    StdDraw.text(0, 1.05 * maxDistance, "dRSS distribution");
                    StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                    + df.format(maxDistance) + " km");
                    StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                    (totalEvents - scenario.getNumberOfInterferingLinks())
                                                    + " events");
                    StdDraw.show();

            }

            /**
             * {@literal shows a colour scaled distribution of the dRSS location probability}
             *
             * @param scenario
             */
            private void drawLocationProbability(ScenarioInfo scenario) {
                    scaleFigure();
                    double lowestLPnotZero = getLowestLPnotZero();
                    double maxLP = getMaxLP();
                    double range = maxLP - lowestLPnotZero;
                    int j = -1; // increased to zero on the first step of the loop
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            j++;
                            double percentage = rLP.get(j);

                            StdDraw.setPenColor(getColor(percentage - lowestLPnotZero, range));

                            if (percentage < locationProbability
                                            && simulatedResults.get(i).iRSS > minDRSS && isUseEBU()) {
                                    StdDraw.setPenColor(StdDraw.WHITE);
                            }

                            StdDraw.filledSquare(simulatedResults.get(i).x,
                                            simulatedResults.get(i).y, 0.04, false);
                            if (simulatedResults.firstElement().isMultipleILK) { // jumps to the next pixel
                                    i += scenario.getNumberOfInterferingLinks() - 1;
                            }
                    }

                    drawScaling(lowestLPnotZero, maxLP, maxDistance, locationProbability,
                                    "%");
                    String assumedModelName = scenario.getVictimLink()
                                    .getPropagationModel().getAssumedModel().name();
                    if (assumedModelName.equals("NoModelDefined")) {
                            assumedModelName = "User-defined dRSS";
                    }
                    StdDraw.setPenColor(StdDraw.BLACK);
                    if (!isUseEBU()) {
                            double resultingLP = (double) (100 - (getNumberOfPixelsBelowLP())
                                            / (double) (getNumberOfEventsToBeConsidered()) * 100);
                            StdDraw.text(0, 1.11 * maxDistance,
                                            "dRSS Location Propability distribution - "
                                                            + assumedModelName);
                            StdDraw.text(0, 1.05 * maxDistance,
                                            "Resulting Coverage Propability " + df.format(resultingLP)
                                                            + "%");
                    } else {
                            double degradation = ((double) (getNumberOfPixelsNotMeetingLP() - getNumberOfPixelsBelowLP()) / (double) (getNumberOfEventsToBeConsidered() - getNumberOfPixelsBelowLP())) * 100;

                            StdDraw.text(
                                            0,
                                            1.11 * maxDistance,
                                            "Location Propability distribution for "
                                                            + (df.format((double) (100 - (getNumberOfPixelsBelowLP())
                                                                            / (double) (getNumberOfEventsToBeConsidered())
                                                                            * 100.0))) + "% coverage - "
                                                            + assumedModelName);
                            StdDraw.text(
                                            0,
                                            1.05 * maxDistance,
                                            "Location Propability degradation relative to "
                                                            + locationProbability + "%  =  "
                                                            + df.format(degradation) + "%");
                    }
                    StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                    + df.format(maxDistance) + " km");
                    StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                    (totalEvents - scenario.getNumberOfInterferingLinks())
                                                    + " events");

                    /*              if (isUseEBU()) {
                                            double degradation =
                                                            ((double) (getNumberOfPixelsNotMeetingLP() - getNumberOfPixelsBelowLP()) / (double) (getNumberOfEventsToBeConsidered())) * 100;
                                            StdDraw.text(-0.85 * maxDistance, -0.98 * maxDistance,
                                                            "Location Propability degradation: " + df.format(degradation) + "%");
                                    }*/

                    StdDraw.show();

            }

            /**
             * {@literal shows pixels not affected, interfered and not interfered}
             *
             * @param scenario
             */
            private void drawPixelsAffected(ScenarioInfo scenario) {
                    scaleFigure();
                    int pixelStatus = 0; // not affected
                    Color[] colorStatus = new Color[] { notAffected, new Color(0, 255, 0),
                                    StdDraw.RED };

                    int k = 0;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (!simulatedResults.firstElement().isMultipleILK) {// single interfering link
                                    pixelStatus = getPixelStatus(scenario, i);
                                    k = i;
                            } else {
                                    if (simulatedResults.get(i).isInterfered) {
                                            pixelStatus = 2;
                                            k = i;
                                            i += scenario.getNumberOfInterferingLinks() - 1;
                                    } else {
                                            pixelStatus = 0;
                                            int j = 0;
                                            do {
                                                    if (pixelStatus < getPixelStatus(scenario, (i + j))) {
                                                            pixelStatus = getPixelStatus(scenario, (i + j));
                                                            k = i + j;
                                                            j++;
                                                    } else {
                                                            j++;
                                                    }
                                            } while (j < scenario.getNumberOfInterferingLinks());
                                            i += scenario.getNumberOfInterferingLinks() - 1;
                                    }
                            }
                            StdDraw.setPenColor(colorStatus[pixelStatus]);
                            StdDraw.filledSquare(simulatedResults.get(k).x,
                                            simulatedResults.get(k).y, 0.05, false);
                    }

                    /* legend */
                    StdDraw.setPenColor(colorStatus[0]);
                    StdDraw.text(-0.9 * maxDistance, -1 * maxDistance, "LP below "
                                    + locationProbability + "%");
                    StdDraw.setPenColor(colorStatus[1]);
                    StdDraw.text(-0.9 * maxDistance, -0.95 * maxDistance, "not interfered");
                    StdDraw.setPenColor(colorStatus[2]);
                    StdDraw.text(-0.9 * maxDistance, -0.90 * maxDistance, "interfered");
                    StdDraw.setPenColor(StdDraw.BLACK);
                    StdDraw.text(0, 1.1 * maxDistance, "Pixel distribution - LP = "
                                    + locationProbability + "%");
                    StdDraw.text(0, 1.05 * maxDistance, "Interference criterion: "
                                    + criterion.get(criterionIndex));
                    StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                    + df.format(maxDistance) + " km");
                    StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                    (totalEvents - scenario.getNumberOfInterferingLinks())
                                                    + " events");
                    if (scenario.getNumberOfInterferingLinks() > 1) {
                            StdDraw.text(0.8 * maxDistance, -1 * maxDistance,
                                            scenario.getNumberOfInterferingLinks()
                                                            + " interfering links");
                    } /*else {
                            StdDraw.text(0.0 * maxDistance, -1.05 * maxDistance, scenario.getInterferingLink(1).getTransmitter()
                                            .getSuppliedPower()
                                            + " dBm");
                            }*/
                    StdDraw.setPenColor(StdDraw.CYAN);
                    StdDraw.circle(0, 0, simulationRadius);
                    StdDraw.setPenColor(StdDraw.DARK_GRAY);
                    StdDraw.circle(0, 0, maxDistance);
                    StdDraw.show();
            }

            /**
             *
             * @param lowest
             * @param max
             * @param distance
             * @param reference
             *            if zero: ignored
             * @param s
             *            = dimension of the parameter, e.g. % for probability
             */
            private void drawScaling(double lowest, double max, double distance,
                            double reference, String s) {
                    Color rDot;
                    double x0 = -0.95 * maxDistance;
                    double y0 = -1.08 * maxDistance;
                    double y = 0.025;
                    double x = 0.2;

                    for (int i = 0; i < 512; i++) {
                            rDot = getColor(i, 512);
                            StdDraw.setPenColor(rDot);
                            StdDraw.line(x0 + i * y, y0, x0 + i * y, y0 + x, false);
                    }

                    StdDraw.setPenColor(new Color(0, 0, 255));
                    StdDraw.text(1.15 * x0, y0, df.format(lowest) + s);
                    StdDraw.setPenColor(new Color(0, 255, 0));
                    StdDraw.text(x0 + 545 * y, y0, df.format(max) + s);
                    if (reference != 0) {
                            // FIX
                            if (max == lowest) {
                                    if (max < reference)
                                            max = reference;
                                    else
                                            lowest = reference;
                            }
                            StdDraw.setPenColor(getColor((reference - lowest), (max - lowest)));
                            StdDraw.text(x0 + 512 * (reference - lowest) / (max - lowest) * y,
                                            y0 + 2 * x, df.format(reference) + s);
                    }

                    StdDraw.setPenColor(StdDraw.CYAN);
                    StdDraw.circle(0, 0, simulationRadius);
                    StdDraw.setPenColor(StdDraw.DARK_GRAY);
                    StdDraw.circle(0, 0, maxDistance);

            }

            /**
             *
             * @param value
             *            to be scaled
             * @param range
             *            of scaling
             * @return corresponding colour red and blue combined
             */
            private Color getColor(double value, double range) {
                    Color rColor = new Color(0, 0, 0);
                    double i = ((value / range) * 511);
                    if (value == 0)
                            i = 0;
                    if (i > 255) {
                            return rColor = getColorGreen(i);
                    }
                    if (i <= 255) {
                            if (value < 0) {
                                    rColor = new Color(255, 255, 255);
                            } else {
                                    rColor = new Color((int) (i), 0, 255 - (int) (i));
                            }
                    }
                    return rColor;
            }

            /**
             *
             * @param value
             *            to be scaled
             * @return corresponding colour including green
             */
            private Color getColorGreen(double value) {
                    Color rColor;
                    int i = (int) (value - 256);
                    if (value < 0) {
                            rColor = new Color(255, 255, 255);
                    } else {
                            rColor = new Color(255 - i, i, 0);
                    }
                    return rColor;
            }

            /**
             * {@literal mainly a place marker }
             *
             * @param color
             * @return defined colour
             */
            private Color getColorNotAffected(String color) {
                    String[] colors = color.split(",");
                    int red = Integer.parseInt(colors[0]);
                    int green = Integer.parseInt(colors[1]);
                    int blue = Integer.parseInt(colors[2]);
                    return new Color(red, green, blue);
            }

            /**
             *
             * @param scenario
             * @param i
             *            pixel to be checked
             * @return lowest C/I of this pixel
             */
            private double getCoverImultiple(ScenarioInfo scenario, int i) {
                    double tCoverI = simulatedResults.get(i).cOverI;
                    int j = 1; // selects the next link
                    do {
                            if (simulatedResults.get(i + j).cOverI < tCoverI) {
                                    tCoverI = simulatedResults.get(i + j).cOverI;
                                    j++;// selects the next link
                            } else {
                                    j++;// selects the next link
                            }
                    } while (j < scenario.getNumberOfInterferingLinks());

                    return tCoverI;
            }

            /**
             *
             * @param scenario
             * @return C/(I+N)
             * @throws Exception
             */
            private double getCoverNplusI(ScenarioInfo scenario) throws Exception {
                    double CoverN = 0; // Initialise
                    CoverN = 10 * Math.log10(Math.pow(10, ((singleResult.dRSS) / 10))
                                    / ((Math.pow(10, (singleResult.iRSS / 10)) + Math.pow(10,
                                                    (singleResult.noiseFloor / 10)))));

                    return CoverN;
            }

            /**
             *
             * @return protection criterion to be used for calculation
             */
            private double getCriterionLimit() {
                    switch (criterionIndex) {
                            case 0:
                                    return rCoverI;
                            case 1:
                                    return rCoverN;
                            case 2:
                                    return rIoverN;
                            default:
                                    return (rCoverN);
                    }
            }

            /**
             *
             * @return highest CoverI
             */
            private double getHighestCoverI() {
                    double highest = -100;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (simulatedResults.get(i).cOverI > highest) {
                                    highest = simulatedResults.get(i).cOverI;
                            }
                    }
                    return highest;
            }

            /**
             *
             * @return highest CoverN
             */
            private double getHighestCoverN() {
                    double highest = -100;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (simulatedResults.get(i).cOverN > highest) {
                                    highest = simulatedResults.get(i).cOverN;
                            }
                    }
                    return highest;
            }

            /**
             *
             * @return highest dRSS
             */
            private double getHighestDRSS() {
                    double highest = -100;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (simulatedResults.get(i).dRSS > highest) {
                                    highest = simulatedResults.get(i).dRSS;
                            }
                    }
                    return highest;
            }

            /**
             *
             * @param scenario
             * @return I/N
             */
            private double getIoverN(ScenarioInfo scenario) {
                    double rIoverN = 10 * Math.log10(((Math.pow(10,
                                    (singleResult.iRSS / 10)) + Math.pow(10,
                                    (singleResult.noiseFloor / 10)))));

                    rIoverN = 10 * Math.log10(((Math.pow(10, (minDRSS / 10)) + Math.pow(10,
                                    (singleResult.noiseFloor / 10)))));

                    return rIoverN;
            }

            /**
             *
             * @param i
             *            index of current location
             * @return protection criterion exceeded or not
             */
            private boolean getLimitExceeded(int i) {
                    boolean isInterfered = false;
                    switch (criterionIndex) {
                            case 0: { // C/I
                                    if (simulatedResults.get(i).dRSS < (simulatedResults.get(i).iRSS + rCoverI)
                                                    && simulatedResults.get(i).dRSS > minDRSS) {
                                            simulatedResults.get(i).isInterfered = true;
                                            isInterfered = true; // exceeded
                                    }
                                    break;
                            }
                            case 1: {// C/(I+N)
                                    if (simulatedResults.get(i).dRSS < (simulatedResults.get(i).iRSS + rCoverN)
                                                    && simulatedResults.get(i).dRSS > minDRSS) {
                                            simulatedResults.get(i).isInterfered = true;
                                            isInterfered = true; // exceeded
                                    }
                                    break;
                            }
                            case 2: {// I/N
                                    if (simulatedResults.get(i).iRSS >= (simulatedResults.get(i).noiseFloor + rIoverN)
                                                    && simulatedResults.get(i).dRSS > minDRSS) {
                                            simulatedResults.get(i).isInterfered = true;
                                            isInterfered = true; // exceeded
                                    }
                                    break;
                            }
                            default:
                                    isInterfered = false;

                    }
                    return isInterfered;
            }

            private boolean getLimitExceeded(int i, double sum) {
                    boolean isInterfered = false;
                    switch (criterionIndex) {
                            case 0: { // C/I
                                    if (simulatedResults.get(i).dRSS < (sum + rCoverI)
                                                    && simulatedResults.get(i).dRSS > minDRSS) {
                                            simulatedResults.get(i).isInterfered = true;
                                            isInterfered = true; // exceeded
                                    }
                                    break;
                            }
                            case 1: {// C/(I+N)
                                    double includeNoise = 10 * Math.log10(Math.pow(10, (sum / 10))
                                                    + Math.pow(10,
                                                                    (simulatedResults.get(i).noiseFloor / 10)));
                                    if (simulatedResults.get(i).dRSS < (includeNoise + rCoverN)
                                                    && simulatedResults.get(i).dRSS > minDRSS) {
                                            simulatedResults.get(i).isInterfered = true;
                                            isInterfered = true; // exceeded
                                    }
                                    break;
                            }
                            case 2: {// I/N
                                    if (sum >= (simulatedResults.get(i).noiseFloor + rIoverN)
                                                    && simulatedResults.get(i).dRSS > minDRSS) {
                                            simulatedResults.get(i).isInterfered = true;
                                            isInterfered = true; // exceeded
                                    }
                                    break;
                            }
                            default:
                                    isInterfered = false;

                    }
                    return isInterfered;
            }

            /**
             * {@literal this method is taken from the propagation model P1546-3}
             *
             * @param x
             *            locationProbability
             * @return correction factor
             */
            private double getLocationProbabilityFactor(double x) throws Exception {
                    double Q, t, xi;
                    double c0, c1, c2, d1, d2, d3;
                    x /= 100;
                    try {
                            if (x > 0.5) {
                                    x = 1 - x;
                            }
                            c0 = 2.515517;
                            c1 = 0.802853;
                            c2 = 0.010328;
                            d1 = 1.432788;
                            d2 = 0.189269;
                            d3 = 0.001308;

                            t = Math.sqrt((-2 * Math.log(x)));
                            xi = (((c2 * t + c1) * t) + c0)
                                            / (((d3 * t + d2) * t + d1) * t + 1);
                            if (x <= 0.5) {
                                    Q = t - xi;
                            } else {
                                    Q = -(t - xi);
                            }
                            return Q;
                    } catch (Exception e) {
                            throw new Exception(e.getMessage());
                    }
            }

            /**
             *
             * @return lowest CoverI
             */
            private double getLowestCoverI() {
                    double lowest = 1000;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (simulatedResults.get(i).cOverI < lowest) {
                                    lowest = simulatedResults.get(i).cOverI;
                            }
                    }
                    return lowest;
            }

            /**
             *
             * @return lowest CoverN
             */
            private double getLowestCoverN() {
                    double lowest = 100;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (simulatedResults.get(i).cOverN < lowest) {
                                    lowest = simulatedResults.get(i).cOverN;
                            }
                    }
                    return lowest;
            }

            /**
             *
             * @return lowest dRSS
             */
            private double getLowestDRSS() {
                    double lowest = 100;
                    for (int i = 0; i < simulatedResults.size(); i++) {
                            if (simulatedResults.get(i).dRSS < lowest) {
                                    lowest = simulatedResults.get(i).dRSS;
                            }
                    }
                    return lowest;
            }

            /**
             *
             * @return lowest level not zero
             */
            private double getLowestLPnotZero() {
                    double[] tLP = new double[rLP.size()]; // leaves the order of the global rLP unchanged
                    for (int i = 0; i < tLP.length; i++) {
                            tLP[i] = rLP.get(i);
                    }
                    Arrays.sort(tLP);

                    int i = -1; // increased by 1 entering the loop
                    do {
                            i++;
                    } while (tLP[i] <= 0);
                    double lowest = tLP[i];
                    return lowest;
            }

            /**
             * {@literal defines the size and scales the graph}
             */
            private void scaleFigure() {
                    StdDraw.setCanvasSize(900, 900);
                    StdDraw.setXscale((-1.2) * maxDistance, 1.2 * maxDistance);
                    StdDraw.setYscale((-1.2) * maxDistance, 1.2 * maxDistance);
            }

            /**
             * {@literal this method has been derived from a so called iterative approach}
             *
             * @param deltaFactor2
             * @return corresponding location probability
             */
            private double getPercentageSevenTrials(double deltaFactor2) {

                    double rPmid = 0;
                    double rProbabilityFactor = 0;
                    double rPmin = 0;
                    double rPmax = 99.999;
                    double erfcMax = 5;
                    double erfcMin = 0;
                    try {
                            erfcMax = getLocationProbabilityFactor(rPmax);
                    } catch (Exception e1) {
                            e1.printStackTrace();
                    }
                    erfcMin = -erfcMax; // symmetrical
                    try { // locationProbability is reference
                            rProbabilityFactor = getLocationProbabilityFactor(locationProbability);
                    } catch (Exception e1) {
                            e1.printStackTrace();
                    }
                    double delta = deltaFactor2 + rProbabilityFactor;
                    if (delta > erfcMax) {
                            return rPmax; // limits the valid range
                    } else if (delta < erfcMin) {
                            return (100 - rPmax);
                    } else {
                            double erfc = 0;
                            while (true) { // endless loop
                                    rPmid = (rPmax - rPmin) / 2 + rPmin;
                                    try {
                                            erfc = getLocationProbabilityFactor(rPmid);
                                    } catch (Exception e) {
                                            e.printStackTrace();
                                    }
                                    if (delta < 0)
                                            erfc *= -1;
                                    if (erfc < erfcMin)
                                            erfc = erfcMin;
                                    if (Math.abs(erfc - delta) < 0.001) {
                                            break; // leaves the loop
                                    } else {
                                            if (erfc < delta) {
                                                    rPmin = rPmid;
                                            } else
                                                    rPmax = rPmid;
                                    }
                            }
                            return rPmid;
                    }
            }

            /**
             * @return the numberOfPixelsBelowLP
             */
            private int getNumberOfPixelsBelowLP() {
                    return numberOfPixelsBelowLP;
            }

            /**
             * @param numberOfPixelsBelowLP
             *            the numberOfPixelsBelowLP to set
             * @param scenario
             */
            private void setNumberOfPixelsBelowLP(ScenarioInfo scenario) {
                    try {
                            this.numberOfPixelsBelowLP = getNumberOfPixelsEmpty(scenario);
                    } catch (Exception e) {
                            e.printStackTrace();
                    }
            }

            /**
             * @return the numberOfPixelsInterfered
             */
            private int getNumberOfPixelsInterfered() {
                    return numberOfPixelsInterfered;
            }

            /**
             * @param numberOfPixelsInterfered
             *            the numberOfPixelsInterfered to set
             * @param scenario
             */
            private void setNumberOfPixelsInterfered(ScenarioInfo scenario) {
                    this.numberOfPixelsInterfered = getNumberOfPixelsInterfered(scenario);
            }

            /**
             * @return the numberOfEventsToBeConsidered
             */
            private int getNumberOfEventsToBeConsidered() {
                    return numberOfEventsToBeConsidered;
            }

            /**
             * @param numberOfEventsToBeConsidered
             *            the numberOfEventsToBeConsidered to set
             */
            private void setNumberOfEventsToBeConsidered(ScenarioInfo scenario) {
                    this.numberOfEventsToBeConsidered = scenario.getTotalNumberOfEvents()
                                    - scenario.getNumberOfInterferingLinks();
            }
    }

    /*-------------------------------------*/

    class CollectedData {
            int event;
            double x;
            double y;
            double dRSS;
            double iRSS;
            int ilk;
            double cOverN;
            double cOverI;
            double cIverN;
            double noiseFloor;
            boolean isMultipleILK;
            boolean isInterfered;
    }

    class ProgressBarStoreFile {
            JProgressBar progressBar;
            JFrame frame;

            public ProgressBarStoreFile(String label) {
                    this.frame = new JFrame(label);
                    this.progressBar = new JProgressBar(0, 100);
            }

            public void init() {
                    int width = 400;
                    int height = 50;
                    progressBar.setStringPainted(true);
                    progressBar.setForeground(new Color(200, 200, 50));
                    frame.setSize(width, height);
                    frame.setLocationRelativeTo(null);
                    frame.setResizable(false);
                    frame.getContentPane().add(progressBar);
                    frame.setVisible(true);
            }

            public void stop() {
                    frame.dispose();
                    frame.setVisible(false);
            }
    }