/* * Copyright 2004-2010 Information & Software Engineering Group (188/1) * Institute of Software Technology and Interactive Systems * Vienna University of Technology, Austria * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.tuwien.ifs.somtoolbox.reportgenerator.QEContainers; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Vector; import java.util.logging.Logger; import at.tuwien.ifs.somtoolbox.layers.GrowingLayer; import at.tuwien.ifs.somtoolbox.layers.LayerAccessException; import at.tuwien.ifs.somtoolbox.layers.Unit; import at.tuwien.ifs.somtoolbox.reportgenerator.SemanticClass; import at.tuwien.ifs.somtoolbox.reportgenerator.SemanticInterpreterGrid; import at.tuwien.ifs.somtoolbox.reportgenerator.SemanticNode; import at.tuwien.ifs.somtoolbox.reportgenerator.TestRunResult; /** * @author Martin Waitzbauer (0226025) * @version $Id: QMContainer.java 3590 2010-05-21 10:43:45Z mayer $ */ public class QMContainer { HashMap<String, double[][]> UnitQualities; HashMap<String, Double> UnitMAXQualities; HashMap<String, Double> UnitMINQualities; HashMap<String, Double> MapQualities; HashMap<String, int[][]> UnitQualitiesClassified; public ArrayList<String> UnitQualityMeasureNames; SemanticInterpreterGrid sGrid; private ArrayList<String> damagedcriteriaQM = new ArrayList<String>();; private HashMap<Integer, String> QualityIdentifier = new HashMap<Integer, String>(); TestRunResult run; public static int NUMBER_OF_CLASSES = 5; public QMContainer(TestRunResult run) { UnitQualities = new HashMap<String, double[][]>(); MapQualities = new HashMap<String, Double>(); UnitQualitiesClassified = new HashMap<String, int[][]>(); UnitMAXQualities = new HashMap<String, Double>(); UnitMINQualities = new HashMap<String, Double>(); UnitQualityMeasureNames = new ArrayList<String>(); this.run = run; writeQualityIdentifier(); } public void putUnitQualities(String Name, double[][] units) { this.UnitQualities.put(Name, units); if (!this.UnitQualityMeasureNames.contains(Name)) { this.UnitQualityMeasureNames.add(Name); } } public double[][] getUnitQualities(String Name) { return UnitQualities.get(Name); } public void putMapQualities(String Name, double measure) { this.MapQualities.put(Name, measure); } /** * returns the maximal Value of the quality measure with "Name"as identifier * * @return an Unit Array storing the Unit(s) with the biggest Value * @param Area null if whole grid is admitted, != null ifi want a Part only */ public Unit[] getMaxUnit(String Name, Unit[] Area) { double[][] errors; double maxError; Vector<Integer> argmaxx = new Vector<Integer>(); Vector<Integer> argmaxy = new Vector<Integer>(); Unit[] units = null; errors = this.UnitQualities.get(Name); maxError = Double.MIN_VALUE; argmaxx.add(new Integer(0)); argmaxy.add(new Integer(0)); if (errors != null) { try { if (Area != null) { for (Unit u : Area) { if (errors[u.getXPos()][u.getYPos()] > maxError && run.getGrowingSOM().getLayer().hasMappedInput(u.getXPos(), u.getYPos())) { // new maximum maxError = errors[u.getXPos()][u.getYPos()]; argmaxx.removeAllElements(); argmaxy.removeAllElements(); argmaxx.add(new Integer(u.getXPos())); argmaxy.add(new Integer(u.getYPos())); } else if (errors[u.getXPos()][u.getYPos()] == maxError && run.getGrowingSOM().getLayer().hasMappedInput(u.getXPos(), u.getYPos())) { // additional minimum argmaxx.add(new Integer(u.getXPos())); argmaxy.add(new Integer(u.getYPos())); } } } else { for (int i = 0; i < errors.length; i++) { for (int j = 0; j < errors[i].length; j++) { // look whether the te is smaller if (errors[i][j] > maxError && run.getGrowingSOM().getLayer().hasMappedInput(i, j)) { // new maximum maxError = errors[i][j]; argmaxx.removeAllElements(); argmaxy.removeAllElements(); argmaxx.add(new Integer(i)); argmaxy.add(new Integer(j)); } else if (errors[i][j] == maxError && run.getGrowingSOM().getLayer().hasMappedInput(i, j)) { // additional minimum argmaxx.add(new Integer(i)); argmaxy.add(new Integer(j)); } } } this.UnitMAXQualities.put(Name, maxError); } units = new Unit[argmaxx.size()]; for (int i = 0; i < argmaxx.size(); i++) { units[i] = this.run.getGrowingSOM().getLayer().getUnit(argmaxx.get(i).intValue(), argmaxy.get(i).intValue()); } return units; } catch (LayerAccessException e) { Logger.getLogger("at.tuwien.ifs.somtoolbox.reports").warning( "Cannot calculate max value of units on SOM from run " + this.run.getRunId() + ". Reason: " + e); return null; } } else { return null; } } /** * returns the minimal Value of the quality measure with "Name"as identifier * * @return an Unit Array storing the Unit(s) with the smallest Value * @param Area != null if i want area selection, null if whole grid */ public Unit[] getMinUnit(String Name, Unit[] Area) { double[][] errors; double minError; Vector<Integer> argmaxx = new Vector<Integer>(); Vector<Integer> argmaxy = new Vector<Integer>(); Unit[] units = null; errors = this.UnitQualities.get(Name); minError = Double.MAX_VALUE; argmaxx.add(new Integer(0)); argmaxy.add(new Integer(0)); if (errors != null) { try { if (Area != null) { for (Unit u : Area) { if (errors[u.getXPos()][u.getYPos()] != 0 && errors[u.getXPos()][u.getYPos()] < minError && run.getGrowingSOM().getLayer().hasMappedInput(u.getXPos(), u.getYPos())) { // new minimium minError = errors[u.getXPos()][u.getYPos()]; argmaxx.removeAllElements(); argmaxy.removeAllElements(); argmaxx.add(new Integer(u.getXPos())); argmaxy.add(new Integer(u.getYPos())); } else if (errors[u.getXPos()][u.getYPos()] == minError && run.getGrowingSOM().getLayer().hasMappedInput(u.getXPos(), u.getYPos())) { // additional minimum argmaxx.add(new Integer(u.getXPos())); argmaxy.add(new Integer(u.getYPos())); } } } else { for (int i = 0; i < errors.length; i++) { for (int j = 0; j < errors[i].length; j++) { // look whether the te is smaller if (errors[i][j] != 0 && errors[i][j] < minError && run.getGrowingSOM().getLayer().hasMappedInput(i, j)) { // new maximium minError = errors[i][j]; argmaxx.removeAllElements(); argmaxy.removeAllElements(); argmaxx.add(new Integer(i)); argmaxy.add(new Integer(j)); } else if (errors[i][j] == minError && run.getGrowingSOM().getLayer().hasMappedInput(i, j)) { // additional minimum argmaxx.add(new Integer(i)); argmaxy.add(new Integer(j)); } } } this.UnitMINQualities.put(Name, minError); } units = new Unit[argmaxx.size()]; for (int i = 0; i < argmaxx.size(); i++) { units[i] = this.run.getGrowingSOM().getLayer().getUnit(argmaxx.get(i).intValue(), argmaxy.get(i).intValue()); } return units; } catch (LayerAccessException e) { Logger.getLogger("at.tuwien.ifs.somtoolbox.reports").warning( "Cannot calculate min value of units on SOM from run " + this.run.getRunId() + ". Reason: " + e); return null; } } return null; } /** Puts all the Values of the QM identified with "Name" in "Classes" 1-5 (strong - very weak) */ public void classifyUnits(String Name) { // int z = 77; // if (Name.equals("Silhouette Value")) { // z = 7; // } // Unit[] minU = this.getMinUnit(Name, null); // Unit[] maxU = this.getMaxUnit(Name, null); double[][] currQual = this.UnitQualities.get(Name); int[][] currclassQual = new int[currQual.length][currQual[0].length]; double min = -1, max = -1; if (this.UnitMINQualities.containsKey(Name)) { min = this.UnitMINQualities.get(Name); } if (this.UnitMAXQualities.containsKey(Name)) { max = this.UnitMAXQualities.get(Name); } // double span = max - min; for (int i = 0; i < currQual.length; i++) { for (int j = 0; j < currQual[i].length; j++) { int k = 0; /* * while(!((min+kstep) < currQual[i][j] && (min+(k+1)step > currQual[i][j])) ){ // Look in wich class my Unit is k++; } */ // double v = currQual[i][j]; if (run.getGrowingSOM().getLayer().hasMappedInput(i, j)) { k = (int) Math.round((currQual[i][j] - min) / (max - min) * 4) + 1; } currclassQual[i][j] = k; } } this.UnitQualitiesClassified.put(Name, currclassQual); } /** Returns the int [] of classified units for identifier Name */ public int[][] getClassifiedUnits(String Name) { return this.UnitQualitiesClassified.get(Name); } /** Computes the number of classified units for the given class and identifier */ public int getNumberOfClassifiedUnits(String Name, int clss) { int[][] values = this.UnitQualitiesClassified.get(Name); int counter = 0; for (int[] value : values) { for (int element : value) { if (element == clss) { counter++; } } } return counter++; } /** * NOT USEDCURRENTLY returns the average distance from all units, classified with "clss" from QM "Name" * * @param Name * @return */ /* * public double getAverageDistance(String Name, int clss){ ArrayList temp = new ArrayList(); double out = 0.0 ; int [][] values = (int[][]) * this.UnitQualitiesClassified.get(Name); for(int i = 0; i < values.length;i++){ for(int j = 0; j < values[i].length;j++){ if(values[i][j] == * clss){ int [] tempcoords = new int[2]; tempcoords[0]=i; tempcoords[1]=j; temp.add(tempcoords); } } } return out; } */ /** Returns the map qualities of the given quality measure */ public Double getMapQualities(String Name) { return this.MapQualities.get(Name); } /** * creates an image visualizing the Quality Measure "Name" of this SOM the image is saved under the given path and * name, although a prefix run_runId_ is added to the image name * * @param outputDir the path to the output dir where the image shall be saved (must exists, is neither checked nor * created) * @param filename the name under which the image (together with the prefix run_[runId]_ ) is saved * @return true if everything worked fine, false if there was any problem. False does neither assure that the image * exists, nor that is does not */ public boolean createQualityMeasureImage(String outputDir, String filename, String Name) { boolean out = false; if (Name.equals("Quantization Error")) { out = this.run.createQuantizationErrorImage(outputDir, filename, 0); } if (Name.equals("Mean Quantization Error")) { out = this.run.createQuantizationErrorImage(outputDir, filename, 1); } if (Name.equals("Silhouette Value")) { out = this.run.createSilouetteImage(outputDir, filename, 0); } if (Name.equals("Topographic Error")) { out = this.run.createTopographicErrorImage(outputDir, filename); } if (Name.equals("Intrinisic Distance")) { out = this.run.createIntrinsicDistanceImage(outputDir, filename); } return out; } public double getUnitMAXQualities(String Name) { return this.UnitMAXQualities.get(Name); } public double getUnitMINQualities(String Name) { return this.UnitMINQualities.get(Name); } /** * Returns the string representation of the given int value<br/> * FIXME: refactor this! */ public String getClassIdentifier(int c) { String out = ""; switch (c) { case 5: out = "very high"; break; case 4: out = "high"; break; case 3: out = "intermediate"; break; case 2: out = "low"; break; case 1: out = "very low"; break; default: out = "not such class known!"; } return out; } /** * Returns the maximum of the selected classified Region * * @param region null if whole Grid * @param Name QM Identifier * @return the maximum of the selected classified Region */ public int getMaximumClassifiedRegionValue(Unit[] region, String Name) { int[][] classArray = this.UnitQualitiesClassified.get(Name); int max = Integer.MIN_VALUE; if (region != null) { for (Unit u : region) { if (classArray[u.getXPos()][u.getYPos()] > max & classArray[u.getXPos()][u.getYPos()] != 0) { // 0 if unit has no Inputs max = classArray[u.getXPos()][u.getYPos()]; } } } else { // whole Grid for (int[] element : classArray) { for (int element2 : element) { if (element2 > max) { max = element2; } } } } return max; } /** * Returns the minimum of the selected classified Region * * @param region null if whole Grid * @param Name QM Identifier * @return the minimum of the selected classified Region */ public int getMinimumClassifiedRegionValue(Unit[] region, String Name) { int[][] classArray = this.UnitQualitiesClassified.get(Name); int min = Integer.MAX_VALUE; if (region != null) { for (Unit u : region) { if (classArray[u.getXPos()][u.getYPos()] < min && classArray[u.getXPos()][u.getYPos()] != 0) { // == 0 if unit has no Inputs min = classArray[u.getXPos()][u.getYPos()]; } } } else { // whole Grid for (int[] element : classArray) { for (int element2 : element) { if (element2 < min) { min = element2; } } } } return min; } /** * Compares the 2 QM with each other,i.e looks through all units (only in the Region if region != NULL) and looks * for similar values at the same Units (TRY: Enlarge the search radius to a certain neighbourhood radius (1)) * * @param type 1 = Max-Max, 2 = Min-Min, 3 = Max-Min, 4 = Min-Max Compares according to Min /Max Values return a * Array [0] gives the percentage of similarity, [1] gives the absolute difference in strength between * max/min 1/2, [2] the region of intersection(1-9) */ public double[] compareQualities(String Name1, String Name2, Unit[] Region, int type) { int[][] classArray1 = this.UnitQualitiesClassified.get(Name1); int[][] classArray2 = this.UnitQualitiesClassified.get(Name2); double[] out = new double[2]; int minmax1 = 0, minmax2 = 0; int counter1 = 0, counter2 = 0; if (type == 1) { // Max-Max Report minmax1 = this.getMaximumClassifiedRegionValue(null, Name1); minmax2 = this.getMaximumClassifiedRegionValue(null, Name2); } if (type == 2) { // Min-Min Report minmax1 = this.getMinimumClassifiedRegionValue(null, Name1); minmax2 = this.getMinimumClassifiedRegionValue(null, Name2); } if (type == 3) { // Max-Min Report minmax1 = this.getMaximumClassifiedRegionValue(null, Name1); minmax2 = this.getMinimumClassifiedRegionValue(null, Name2); } if (type == 4) { // Min-Max Report minmax1 = this.getMinimumClassifiedRegionValue(null, Name1); minmax2 = this.getMaximumClassifiedRegionValue(null, Name2); } for (Unit u : Region) { // we have a wanted value if (classArray1[u.getXPos()][u.getYPos()] == minmax1 || classArray1[u.getXPos()][u.getYPos()] == minmax1 - 1 || classArray1[u.getXPos()][u.getYPos()] == minmax1 + 1) { counter1++; if (classArray2[u.getXPos()][u.getYPos()] == minmax2 || classArray2[u.getXPos()][u.getYPos()] == minmax2 - 1 || classArray2[u.getXPos()][u.getYPos()] == minmax2 + 1) { counter2++; } } } out[0] = counter1 > 0 ? (double) counter2 / (double) counter1 : 0.0; out[1] = minmax1 - minmax2; return out; } /** * Returns an array of Units, witch have Intersection of QM Name1 & Name 2 with the given type of operation */ public ArrayList<Unit> getComparedQMRegionOccurances(String Name1, String Name2, Unit[] Region, int type) { int[][] classArray1 = this.UnitQualitiesClassified.get(Name1); int[][] classArray2 = this.UnitQualitiesClassified.get(Name2); ArrayList<Unit> out = new ArrayList<Unit>(); int minmax1 = 0, minmax2 = 0; int counter1 = 0; if (type == 1) { // Max-Max Report minmax1 = this.getMaximumClassifiedRegionValue(null, Name1); minmax2 = this.getMaximumClassifiedRegionValue(null, Name2); } if (type == 2) { // Min-Min Report minmax1 = this.getMinimumClassifiedRegionValue(null, Name1); minmax2 = this.getMinimumClassifiedRegionValue(null, Name2); } if (type == 3) { // Max-Min Report minmax1 = this.getMaximumClassifiedRegionValue(null, Name1); minmax2 = this.getMinimumClassifiedRegionValue(null, Name2); } if (type == 4) { // Min-Max Report minmax1 = this.getMinimumClassifiedRegionValue(null, Name1); minmax2 = this.getMaximumClassifiedRegionValue(null, Name2); } for (Unit u : Region) { // we have a wanted value if (classArray1[u.getXPos()][u.getYPos()] == minmax1 || classArray1[u.getXPos()][u.getYPos()] == minmax1 - 1 || classArray1[u.getXPos()][u.getYPos()] == minmax1 + 1) { counter1++; if (classArray2[u.getXPos()][u.getYPos()] == minmax2 || classArray2[u.getXPos()][u.getYPos()] == minmax2 - 1 || classArray2[u.getXPos()][u.getYPos()] == minmax2 + 1) { out.add(u); } } } return out; } /** * Sets the SemanticGrid for calculations PLEASE NOTE: only the "Master- Grid can be set here" -> wich is the Grid * over the full Map, inluding all ClassReports */ public void setsGrid(SemanticInterpreterGrid sGrid) { this.sGrid = sGrid; } /** * Returns an array with the original identification configuration , of how the qualifier QM should behave on * MAXIMUM / MINIMUM Value * * @param qualifier the QM * @param type 1= max, 2 = Min * @return an Array of arraylists, built up as following: out[0] = high Density out[1] = low Density out[2] = mixed * classes out[3] = one class out[4] = Units on Map edges out[5] = Units not on Map edges out[6] = Having * neighboring empty units out[7] = having no neighboring empt unist out[8] = Units on Cluster edges out[9] * = Units in Clusters out[10] = Big Distance of mapped Vectors to Prototype vector. out[11] = Small * Distance of mapped Vectors to Prototype vector. out[12] = Big average Distance of mapped Vectors compared * to each other. out[13] = Small average Distance of mapped Vectors compared to each other. out[14] = Input * Vectors equally distributed over the Map out[15] = Input Vectors not equally distributed over the Map * out[16] = Intra Cluster Distances == 0, Inter Cluster Distances != 0 out[17] = Intra Cluster Distances != * 0, Inter Cluster Distances == 0 */ public QMConfigurationProfile getOriginalConfiguration(String qualifier, int type) { QMConfigurationProfile out_array = new QMConfigurationProfile(18); if (type == 1) { // return how the QM should be ideally in the original configuration when looked at MAXIMUM // Values if (qualifier.equals("Topographic Error")) { out_array.createNewElement(0); out_array.insert(0, 1.0); out_array.createNewElement(2); out_array.insert(2, 1.0); out_array.createNewElement(4); out_array.insert(4, 1.0); out_array.createNewElement(6); out_array.insert(6, 1.0); out_array.createNewElement(8); out_array.insert(8, 1.0); } if (qualifier.equals("Quantization Error")) { out_array.createNewElement(10); out_array.insert(10, 1.0); } if (qualifier.equals("Silhouette Value")) { out_array.createNewElement(16); out_array.insert(16, 1.0); } if (qualifier.equals("Mean Quantization Error")) { out_array.createNewElement(1); out_array.insert(1, 1.0); out_array.createNewElement(2); out_array.insert(2, 1.0); out_array.createNewElement(4); out_array.insert(4, 1.0); out_array.createNewElement(12); out_array.insert(12, 1.0); } if (qualifier.equals("Intrinsic Distance")) { // Mixture of Quantization Error & Topographic Error out_array.createNewElement(10); out_array.insert(10, 1.0); out_array.createNewElement(0); out_array.insert(0, 1.0); out_array.createNewElement(2); out_array.insert(2, 1.0); out_array.createNewElement(4); out_array.insert(4, 1.0); out_array.createNewElement(6); out_array.insert(6, 1.0); out_array.createNewElement(8); out_array.insert(8, 1.0); } if (qualifier.equals("Entropy Error")) { out_array.createNewElement(14); out_array.insert(14, 1.0); } } if (type == 2) { // return how the QM should be ideally in the original configuration when looked at MINIMUM // Values if (qualifier.equals("Topographic Error")) { out_array.createNewElement(1); out_array.insert(1, 1.0); out_array.createNewElement(3); out_array.insert(3, 1.0); out_array.createNewElement(5); out_array.insert(5, 1.0); out_array.createNewElement(7); out_array.insert(7, 1.0); out_array.createNewElement(9); out_array.insert(9, 1.0); } if (qualifier.equals("Quantization Error")) { out_array.createNewElement(11); out_array.insert(11, 1.0); } if (qualifier.equals("Mean Quantization Error")) { out_array.createNewElement(0); out_array.insert(0, 1.0); out_array.createNewElement(3); out_array.insert(3, 1.0); out_array.createNewElement(5); out_array.insert(5, 1.0); out_array.createNewElement(11); out_array.insert(11, 1.0); } if (qualifier.equals("Intrinsic Distance")) { // Mixture of Quantization Error & Topographic Error out_array.createNewElement(11); out_array.insert(11, 1.0); out_array.createNewElement(1); out_array.insert(1, 1.0); out_array.createNewElement(3); out_array.insert(3, 1.0); out_array.createNewElement(5); out_array.insert(5, 1.0); out_array.createNewElement(7); out_array.insert(7, 1.0); out_array.createNewElement(9); out_array.insert(9, 1.0); } if (qualifier.equals("Entropy Error")) { out_array.createNewElement(15); out_array.insert(15, 1.0); } if (qualifier.equals("Silhouette Value")) { out_array.createNewElement(17); out_array.insert(17, 1.0); } } if (out_array.isEmpty()) { return null; } else { return out_array; } } /** * Returns an array with the actual identification configuration , of how the qualifier QM behaves * * @param qualifier the QM * @param units the units witch are tested * @param type 1 = MAX, 2 = MIN * @return an Array of arraylists, built up as following: out[0] = high Density out[1] = low Density out[2] = mixed * classes out[3] = one class out[4] = Units on Map edges out[5] = Units not on Map edges out[6] = Having * neighboring empty units out[7] = having no neighboring empt unist out[8] = Units on Cluster edges out[9] * = Units in Clusters out[10] = Big Distance of mapped Vectors to Prototype vector. out[11] = Small * Distance of mapped Vectors to Prototype vector. out[12] = Big average Distance of mapped Vectors compared * to each other. out[13] = Small average Distance of mapped Vectors compared to each other. out[14] = Input * Vectors equally distributed over the Map out[15] = Input Vectors not equally distributed over the Map * out[16] = Intra Cluster Distances == 0, Inter Cluster Distances != 0 out[17] = Intra Cluster Distances != * 0, Inter Cluster Distances == 0 */ public QMConfigurationProfile getActualConfiguration(String qualifier, Unit[] units, int type) { QMConfigurationProfile out_array = new QMConfigurationProfile(18); if (type == 1) { // WHat should be taken into account when looked at MAX properties if (qualifier.equals("Mean Quantization Error")) { out_array.createNewElement(1); out_array.createNewElement(2); out_array.createNewElement(4); out_array.createNewElement(12); out_array.insert(12, 1.0); // no need for further calculations for (Unit unit : units) { // Test all units Boolean hasMixedClasses = this.hasMixedClasses(unit); if (this.hasLowDensity(unit) == false) { out_array.insert(1, unit); } if (this.isOnMapEdge(unit) == false) { out_array.insert(4, unit); } if (hasMixedClasses == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(2))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(2)); } } else { if (hasMixedClasses == false) { out_array.insert(2, unit); } } } String pLD_MQE = units.length - out_array.lengthOfElement(1) + " / " + units.length;// 1.0 // -(double)out_array[1].size()/(double)units.length; out_array.insert(1, 0, pLD_MQE); String pLMC_MQE = units.length - out_array.lengthOfElement(2) + " / " + units.length;// 1.0 - // (double)out_array[2].size()/(double)units.length; out_array.insert(2, 0, pLMC_MQE); String pME_MQE = units.length - out_array.lengthOfElement(4) + " / " + units.length;// 1.0 - // (double)out_array[4].size()/(double)units.length; out_array.insert(4, 0, pME_MQE); } if (qualifier.equals("Topographic Error")) { out_array.createNewElement(0); out_array.createNewElement(2); out_array.createNewElement(4); out_array.createNewElement(6); out_array.createNewElement(8); for (Unit unit : units) { // Test all units boolean HighDens = this.hasHighDensity(unit); Boolean hasMixedClasses = this.hasMixedClasses(unit); boolean isMapedge = this.isOnMapEdge(unit); ArrayList<SemanticClass> isClusterEdge = this.isOnClusterEdge(unit); Boolean neighborsempty = this.hasNeighboringEmptyUnits(unit); if (HighDens == false) { out_array.insert(0, unit); } if (hasMixedClasses == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(2))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(2)); } } else { if (hasMixedClasses == false) { out_array.insert(2, unit); } } if (isMapedge == false) { out_array.insert(4, unit); } if (isClusterEdge == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(8))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(8)); } } else { if (isClusterEdge.size() == 0) { out_array.insert(8, unit); } } if (neighborsempty == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(6))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(6)); } } else { if (neighborsempty == false) { out_array.insert(6, unit); } } } String pHD_TE = units.length - out_array.lengthOfElement(0) + " / " + units.length;// 1.0 // -(double)out_array[1].size()/(double)units.length; out_array.insert(0, 0, pHD_TE); String pLMC_TE = units.length - out_array.lengthOfElement(2) + " / " + units.length;// 1.0 - // (double)out_array[2].size()/(double)units.length; out_array.insert(2, 0, pLMC_TE); String pME_TE = units.length - out_array.lengthOfElement(4) + " / " + units.length;// 1.0 - // (double)out_array[4].size()/(double)units.length; out_array.insert(4, 0, pME_TE); String pNE_TE = units.length - out_array.lengthOfElement(6) + " / " + units.length; out_array.insert(6, 0, pNE_TE); String pCE_TE = units.length - out_array.lengthOfElement(8) + " / " + units.length; out_array.insert(8, 0, pCE_TE); } if (qualifier.equals("Intrinsic Distance")) { // Pnly evaluate the TE Part out_array.createNewElement(0); out_array.createNewElement(2); out_array.createNewElement(4); out_array.createNewElement(6); out_array.createNewElement(8); for (Unit unit : units) { // Test all units Boolean hasMixedClasses = this.hasMixedClasses(unit); ArrayList<SemanticClass> isClusterEdge = this.isOnClusterEdge(unit); Boolean neighborsempty = this.hasNeighboringEmptyUnits(unit); if (this.hasHighDensity(unit) == false) { out_array.insert(0, unit); } if (hasMixedClasses == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(2))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(2)); } } else { if (hasMixedClasses == false) { out_array.insert(2, unit); } } if (this.isOnMapEdge(unit) == false) { out_array.insert(4, unit); } if (isClusterEdge == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(8))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(8)); } } else { if (isClusterEdge.size() == 0) { out_array.insert(8, unit); } } if (neighborsempty == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(6))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(6)); } } else { if (neighborsempty == false) { out_array.insert(6, unit); } } } String pHD_TE = units.length - out_array.lengthOfElement(0) + " / " + units.length;// 1.0 // -(double)out_array[1].size()/(double)units.length; out_array.insert(0, 0, pHD_TE); String pLMC_TE = units.length - out_array.lengthOfElement(2) + " / " + units.length;// 1.0 - // (double)out_array[2].size()/(double)units.length; out_array.insert(2, 0, pLMC_TE); String pME_TE = units.length - out_array.lengthOfElement(4) + " / " + units.length;// 1.0 - // (double)out_array[4].size()/(double)units.length; out_array.insert(4, 0, pME_TE); String pNE_TE = units.length - out_array.lengthOfElement(6) + " / " + units.length; out_array.insert(6, 0, pNE_TE); String pCE_TE = units.length - out_array.lengthOfElement(8) + " / " + units.length; out_array.insert(8, 0, pCE_TE); } } if (type == 2) { // WHat should be taken into account when looked at MIN properties if (qualifier.equals("Mean Quantization Error")) { out_array.createNewElement(0); out_array.createNewElement(3); out_array.createNewElement(5); out_array.createNewElement(13); out_array.insert(13, 1.0); // no need for further calculations for (Unit unit : units) { // Test all units Boolean hasSingleClasses = this.hasSingleClass(unit); boolean isMapedge = this.isOnMapEdge(unit); if (this.hasHighDensity(unit) == false) { out_array.insert(0, unit); } if (hasSingleClasses == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(2))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(2)); } } else { if (hasSingleClasses == false) { out_array.insert(3, unit); } } if (isMapedge == true) { out_array.insert(5, unit); } } String pHD_MQE = units.length - out_array.lengthOfElement(0) + " / " + units.length;// 1.0 // -(double)out_array[1].size()/(double)units.length; out_array.insert(0, 0, pHD_MQE); String pLSC_MQE = units.length - out_array.lengthOfElement(3) + " / " + units.length;// 1.0 - // (double)out_array[2].size()/(double)units.length; out_array.insert(3, 0, pLSC_MQE); String pnME_MQE = units.length - out_array.lengthOfElement(5) + " / " + units.length;// 1.0 - // (double)out_array[4].size()/(double)units.length; out_array.insert(5, 0, pnME_MQE); } if (qualifier.equals("Topographic Error")) { out_array.createNewElement(1); out_array.createNewElement(3); out_array.createNewElement(5); out_array.createNewElement(7); out_array.createNewElement(9); for (int i = 0; i < units.length; i++) { // Test all units Boolean isSingleClasses = this.hasSingleClass(units[i]); ArrayList<SemanticClass> isNotClusterEdge = this.isOnClusterEdge(units[i]); Boolean Noneighborsempty = this.hasNeighboringEmptyUnits(units[i]); if (Noneighborsempty != null) { Noneighborsempty = !Noneighborsempty; } if (this.hasLowDensity(units[i]) == false) { out_array.insert(1, units[i]); } if (isSingleClasses == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(3))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(3)); } } else { if (isSingleClasses == false) { out_array.insert(3, units[i]); } } if (!this.isOnMapEdge(units[i]) == false) { out_array.insert(5, units[i]); } if (isNotClusterEdge == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(9))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(9)); } } else { if (isNotClusterEdge.size() != 0) { out_array.insert(9, units[i]); } } if (Noneighborsempty == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(7))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(7)); } } else { if (Noneighborsempty == false) { out_array.insert(7, units[i]); } } } String pHD_TE = units.length - out_array.lengthOfElement(1) + " / " + units.length;// 1.0 // -(double)out_array[1].size()/(double)units.length; out_array.insert(1, 0, pHD_TE); String pLMC_TE = units.length - out_array.lengthOfElement(3) + " / " + units.length;// 1.0 - // (double)out_array[2].size()/(double)units.length; out_array.insert(3, 0, pLMC_TE); String pME_TE = units.length - out_array.lengthOfElement(5) + " / " + units.length;// 1.0 - // (double)out_array[4].size()/(double)units.length; out_array.insert(5, 0, pME_TE); String pNE_TE = units.length - out_array.lengthOfElement(7) + " / " + units.length; out_array.insert(7, 0, pNE_TE); String pCE_TE = units.length - out_array.lengthOfElement(9) + " / " + units.length; out_array.insert(9, 0, pCE_TE); } if (qualifier.equals("Intrinsic Distance")) { // Only evaluate the Topographic Error part out_array.createNewElement(1); out_array.createNewElement(3); out_array.createNewElement(5); out_array.createNewElement(7); out_array.createNewElement(9); for (int i = 0; i < units.length; i++) { // Test all units Boolean isSingleClasses = this.hasSingleClass(units[i]); ArrayList<SemanticClass> isNotClusterEdge = this.isOnClusterEdge(units[i]); Boolean Noneighborsempty = this.hasNeighboringEmptyUnits(units[i]); if (Noneighborsempty != null) { Noneighborsempty = !Noneighborsempty; } if (this.hasLowDensity(units[i]) == false) { out_array.insert(1, units[i]); } if (isSingleClasses == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(3))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(3)); } } else { if (isSingleClasses == false) { out_array.insert(3, units[i]); } } if (!this.isOnMapEdge(units[i]) == false) { out_array.insert(5, units[i]); } if (isNotClusterEdge == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(9))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(9)); } } else { if (isNotClusterEdge.size() != 0) { out_array.insert(9, units[i]); } } if (Noneighborsempty == null) { if (!this.damagedcriteriaQM.contains(this.getQualityIdentifier(7))) { this.damagedcriteriaQM.add(this.getQualityIdentifier(7)); } } else { if (Noneighborsempty == false) { out_array.insert(7, units[i]); } } } String pHD_TE = units.length - out_array.lengthOfElement(1) + " / " + units.length;// 1.0 // -(double)out_array[1].size()/(double)units.length; out_array.insert(1, 0, pHD_TE); String pLMC_TE = units.length - out_array.lengthOfElement(3) + " / " + units.length;// 1.0 - // (double)out_array[2].size()/(double)units.length; out_array.insert(3, 0, pLMC_TE); String pME_TE = units.length - out_array.lengthOfElement(5) + " / " + units.length;// 1.0 - // (double)out_array[4].size()/(double)units.length; out_array.insert(5, 0, pME_TE); String pNE_TE = units.length - out_array.lengthOfElement(7) + " / " + units.length; out_array.insert(7, 0, pNE_TE); String pCE_TE = units.length - out_array.lengthOfElement(9) + " / " + units.length; out_array.insert(9, 0, pCE_TE); } } if (out_array.isEmpty()) { return null; } else { return out_array; } } /** * Tests whether the Unit U is having a High Mapped Input Density.<br/> * This is made upon an assumption, we say a unit is highly dense when the average value of the first 15% of units * with highest values is equal or above that value that */ public boolean hasHighDensity(Unit u) { Unit[] units = this.run.getGrowingSOM().getLayer().getAllUnits(); double InputCount = 0.0; for (Unit unit : units) { if (unit.getNumberOfMappedInputs() > 0) { InputCount++; } } double f15p = InputCount / units.length * 15.0; int[] ValuesOff15P = new int[(int) f15p]; int f15pCounter = 0; ArrayList<Integer> alreadyUsed = new ArrayList<Integer>(); while (f15pCounter < f15p) { int MaxMapped = Integer.MIN_VALUE; for (Unit unit : units) { int inputs = unit.getNumberOfMappedInputs(); if (inputs > MaxMapped && !alreadyUsed.contains(inputs)) { MaxMapped = inputs; } } // *Fetch all values with current MaxMapped Max*/ for (Unit unit : units) { int inputs = unit.getNumberOfMappedInputs(); if (inputs == MaxMapped) { if (f15pCounter < f15p) { ValuesOff15P[f15pCounter] = MaxMapped; f15pCounter++; if (!alreadyUsed.contains(MaxMapped)) { alreadyUsed.add(MaxMapped); } } } } } // Build average, then Compare it to actual unit int f15pAverage = 0; for (int element : ValuesOff15P) { f15pAverage += element; } f15pAverage = (int) Math.round((double) (f15pAverage / ValuesOff15P.length)); if (u.getNumberOfMappedInputs() >= f15pAverage) { return true; } else { return false; } } /** Returns true if the Unit has a low density */ public boolean hasLowDensity(Unit u) { return !this.hasHighDensity(u); } /** * Returns whether there are mixed classes on the Unit. If no class file was used during report Creation, die * measure is left out */ public Boolean hasMixedClasses(Unit u) { int[] coords = new int[2]; Boolean out = null; coords[0] = u.getXPos(); coords[1] = u.getYPos(); SemanticNode n = this.getNode(coords); if (n != null && n.empty != null) { if (n.Classes != null) { if (n.Classes.size() > 1) { out = true; } else { out = false; } } else { out = false; } } return out; } public Boolean hasSingleClass(Unit u) { Boolean b = hasMixedClasses(u); if (b != null) { return !b; } else { return b; } } /** * tests whether a unit is on the edge of the map<br> * FIXME: this should go to {@link GrowingLayer} */ public boolean isOnMapEdge(Unit u) { // int x = u.getXPos(); // int y = u.getYPos(); for (int x_new = -1; x_new <= 1; x_new++) { for (int y_new = -1; y_new <= 1; y_new++) { int[] c = new int[2]; c[0] = u.getXPos() + x_new; c[1] = u.getYPos() + y_new; SemanticNode s = this.getNode(c); if (s == null) { return true; } } } return false; } /** * returns a ArrayList with all classes for witch unit u resembles a Cluster Edge Unit for those classes. this need * a clss file to b presents, returns null otherwise */ public ArrayList<SemanticClass> isOnClusterEdge(Unit u) { ArrayList<SemanticClass> out = null; if (this.sGrid.SemanticClassesIndex != null) { Iterator<SemanticClass> clsses = sGrid.SemanticClassesIndex.values().iterator(); out = new ArrayList<SemanticClass>(); while (clsses.hasNext()) { SemanticClass s = clsses.next(); ArrayList<SemanticNode> edgeNodes = s.getEdgeNodes(); for (int i = 0; i < edgeNodes.size(); i++) { SemanticNode n = edgeNodes.get(i); if (n.realCoordinates[0] == u.getXPos() && n.realCoordinates[1] == u.getYPos()) { out.add(s); break; } } } } return out; } /** * * Returns true if 8-fold neighbourhood shows any Units with no Inputs. Need a class file to b presents, returns * null otherwise<br/> * FIXME: this should be move to {@link GrowingLayer} */ public Boolean hasNeighboringEmptyUnits(Unit u) { Boolean out = null; boolean wasempty = false; for (int x_new = -1; x_new <= 1; x_new++) { for (int y_new = -1; y_new <= 1; y_new++) { int[] c = new int[2]; c[0] = u.getXPos() + x_new; c[1] = u.getYPos() + y_new; if (c[0] >= 0 && c[0] <= this.sGrid.XLength - 1 && c[1] >= 0 && c[1] <= this.sGrid.YLength - 1 && c[0] != u.getXPos() && c[1] != u.getYPos()) { SemanticNode s = this.getNode(c); if (s != null) { out = s.containsNoClasses(); // true if no classes , null if no class file was given if (out != null) { if (out) { wasempty = true; // save the variable, in case the next unit gives false for #out# } } } } } } if (wasempty) { out = true; } // out will be either false or, if no class file was present out will stay null return out; } /** returns the Semantic Node for given coordinates. a node is null if no class file was attached */ private SemanticNode getNode(int[] c) { SemanticNode node = null; int[] coords; if (this.sGrid.labels != null) { for (SemanticNode[] label : this.sGrid.labels) { for (SemanticNode element : label) { coords = element.realCoordinates; if (coords[0] == c[0] && coords[1] == c[1]) { node = element; } } } } return node; } /** * Returns a String Representation of the Meaning of the Position of the ArrayList Array * * @param quality_list_index gives a Description to the Index of the quality List below quality_list[0] = high * Density quality_list[1] = low Density quality_list[2] = mixed classes quality_list[3] = one class * quality_list[4] = Units on Map edges quality_list[5] = Units not on Map edges quality_list[6] = Having * neighboring empty units quality_list[7] = having no neighboring empt unist quality_list[8] = Units on * Cluster edges quality_list[9] = Units in Clusters quality_list[10] = Big Distance of mapped Vectors to * Prototype vector. quality_list[11] = Small Distance of mapped Vectors to Prototype vector. * quality_list[12] = Big average Distance of mapped Vectors compared to each other. quality_list[13] = * Small average Distance of mapped Vectors compared to each other. quality_list[14] = Input Vectors * equally distributed over the Map quality_list[15] = Input Vectors not equally distributed over the Map * quality_list[16] = Intra Cluster Distances == 0, Inter Cluster Distances != 0 quality_list[17] = Intra * Cluster Distances != 0, Inter Cluster Distances == 0 */ public String getQualityIdentifier(int quality_list_index) { String out = this.QualityIdentifier.get(quality_list_index); if (out == null) { out = "Error Occurded, check getQualityIdentifier(int quality_list_index)..."; } return out; } public ArrayList<String> getClassFileDependantQualities() { return this.damagedcriteriaQM; } public void clearDamagedCriteriaList() { this.damagedcriteriaQM.clear(); } public void writeQualityIdentifier() { this.QualityIdentifier.put(0, "High Density"); this.QualityIdentifier.put(1, "Low Density"); this.QualityIdentifier.put(2, "Mixed Classes"); this.QualityIdentifier.put(3, "Single Class"); this.QualityIdentifier.put(4, "units on Map Edges"); this.QualityIdentifier.put(5, "Units not on Map Edges"); this.QualityIdentifier.put(6, "Units having neighboring empty Units"); this.QualityIdentifier.put(7, "Units having no neighboring empty Units"); this.QualityIdentifier.put(8, "Units on Class Cluster Edges"); this.QualityIdentifier.put(9, "Units inside Clusters"); this.QualityIdentifier.put(10, "Big Distance of mapped Vectors to Prototype vector"); this.QualityIdentifier.put(11, "Small Distance of mapped Vectors to Prototype vector"); this.QualityIdentifier.put(12, "Big average Distance of mapped Vectors compared to each other"); this.QualityIdentifier.put(13, "Small average Distance of mapped Vectors compared to each other"); this.QualityIdentifier.put(14, "Input Vectors equally distributed over the Map"); this.QualityIdentifier.put(15, "Input Vectors not equally distributed over the Map"); this.QualityIdentifier.put(16, "Intra Cluster Distances equal to 0, Inter Cluster Distances not 0"); this.QualityIdentifier.put(17, "Intra Cluster Distances not 0, Inter Cluster Distances equal to 0"); } }