[Xulu-commits] r59 - in trunk: dist src/edu/bonn/xulu/plugin/model/sleuth

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Oct 2 11:57:33 CEST 2009


Author: rgoetzke
Date: 2009-10-02 11:57:30 +0200 (Fri, 02 Oct 2009)
New Revision: 59

Modified:
   trunk/dist/xulu-doc.zip
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java
Log:


Modified: trunk/dist/xulu-doc.zip
===================================================================
(Binary files differ)

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java	2009-09-14 18:49:09 UTC (rev 58)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidation.java	2009-10-02 09:57:30 UTC (rev 59)
@@ -9,47 +9,48 @@
 import edu.bonn.xulu.model.AbstractStepModel;
 import edu.bonn.xulu.model.XuluModel;
 import edu.bonn.xulu.plugin.data.grid.MultiGrid;
-import edu.bonn.xulu.plugin.model.parallel.demo.AVNTuned;
-import edu.bonn.xulu.plugin.model.parallel.demo.AverageNeighborhoodContentManager;
-import edu.bonn.xulu.plugin.model.parallel.demo.AverageNeighborhoodParallelDemoModel;
 
 /**
- *  This very simple model looks at every grid cell and takes the average 
- *  over a the surrounding cells in a specified neighborhood. It was implemented
- *  as demonstration of the Xulu / V functionality. You can see the parallel version
- *  of this model in {@link AverageNeighborhoodParallelDemoModel} and also a tuned
- *  version using late-merging support in {@link AVNTuned}. 
- * <ol>
- * <li><b>Input Grid ({@code inputGrid}):</b> A grid with input values </li>
- * <li><b>Output Grid ({@code outputGrid}):</b> A grid where the output is
- * stored </li>
- * <li><b>Number of steps ({@code steps}):</b> the number of steps to
- * compute. </li>
- * </ol>
+ * <b>MULTIPLE RESOLUTION COMPARISON</b>
+ * The Multiple Resolution Comparison is a Xulu-plugin that can be used in order to validate modelling results.
+ * In general, the Multiple Resolution Comparison is a method to quantify the agreement between two maps, 
+ * whereby it averages neighbouring pixels of both maps into coarser pixels in order to quantify the agreement between maps at coarser resolutions.
+ * The percent correct tends to rise at coarser resolutions, because it reduces the effect of error due to location. By comparing the results with 
+ * a Multiple Resolution Comparison of a NULL-Model (no change has taken place between t1 and t2), the NULL-Resolution can be identified,
+ * which indicates the resolution at which the modelling result is more accurate than the NULL-Model.<br>
+ * For details refer to:<br>
+ * Costanza,R. (1989): Model Goodness of Fit - A Multiple Resolution Procedure. In: Ecological Modelling, vol. 47, no. 3-4, pp. 199-215.<br>
+ * Pontius Jr, R.G. (2002): Statistical Methods to Partition Effects of Quantity and Location During Comparison of Categorical Maps at Multiple Resolutions. 
+ * In: Photogrammetric Engineering &amp; Remote Sensing, vol. 68, no. 10,  pp. 1041-1049.<br>
+ * Pontius Jr, R.G., Huffaker, D. &amp; K. Denman (2004): Useful Techniques of Validation for Spatially Explicit Land-Change Models. 
+ * In: Ecological Modelling, vol. 179, no. 4, pp. 445-461.<br>
  * 
- * @see AverageNeighborhoodContentManager
- * @author Dominik Appl
+ * @see MultipleResolutionValidationContentManager
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
  * @version 1.0
+ *
  */
 public class MultipleResolutionValidation extends AbstractStepModel {
 
 	/**
-	 * the width/height of the neighborhood region over which the algorithm takes 
-	 * the average
+	 * Contains the actual pixel size (from 1 to n, with n being one coarse cell that contains the whole study area).
+	 * During the MRV it is subsequently aggregated in a geometric progression as a multiple of 2.
 	 */
-	//private int neighborhoodRange = 8;
 	private int neighborhoodRange = 0;
+	
+	/** Array containing the fraction correct for every resolution. */
 	private float[][] resultArray;
+	
 	/**
 	 * Speichert den ContentManager fuer das Modell.
 	 * 
-	 * @see AverageNeighborhoodContentManager
+	 * @see MultipleResolutionValidationContentManager
 	 */
 	protected MultipleResolutionValidationContentManager contManager;
 
 	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
 	// ********** Modellanlauf gehalten werden muessen ***********
-	private PropertyReadAccess RA_steps = null;
+	private PropertyReadAccess RA_steps = null;	//Number of Steps
 	private PropertyReadAccess RA_referenceMap = null; // Reference Map
 	private PropertyReadAccess RA_simulationMap = null;	//Simulation Map
 	private PropertyWriteAccess WA_actualValidation = null; // Output Grid
@@ -66,7 +67,7 @@
 
 
 	/**
-	 * Erzeugt eine neue Instanz des Modells.
+	 * Creates a new model instance.
 	 */
 	public MultipleResolutionValidation() {
 		super(new MultipleResolutionValidationContentManager());
@@ -81,7 +82,7 @@
 	public void performModelInit() {
 		if (contManager == null)
 			return;
-		// Zugriffsrechte aus Ressourcen/Propertys holen
+		// Get access authorisation of resource/properties
 		RA_steps = null;
 		if (contManager.getResource(0).getData() != null)
 			RA_steps = ((ScalarProperty) contManager.getResource(0).getData())
@@ -103,7 +104,7 @@
 			WA_outResults = ((ListProperty) contManager.getResource(5)
 					.getData()).getWriteAccess(this);
 
-		// Variablen belegen mit denen gearbeitet wird
+		//Assign variables to work with
 		steps = RA_steps;
 		referenceMap = (WritableGrid) RA_referenceMap.getValue();
 		simulationMap = (WritableGrid) RA_simulationMap.getValue();
@@ -129,154 +130,170 @@
 	}
 
 	/**
-	 * This very simple model looks at every grid cell and takes the average
-	 * over a the surrounding cells in a specified neighborhood.
-	 * 
-	 * @param stepNo
-	 *            zu modellierender Schritt (beginnend bei 1!)
+	 * Performs the MRV. The function is implemented as a Xulu Step Model, but actually does not need any time steps. So
+	 * the stepNo MUST always be 1. The steps of the coarsening procedure are defined inside of the function. When using a 
+	 * MRV parameter file simply use 1 for the number of steps.
 	 */
 	public void performModelStep(int stepNo) {
 		
 		statusOut.println("Starting step " + stepNo + "...");
 		
-
-		/***********************************************************************
-		 * the overallsum is simply the sum over ALL grid elements. it can be used to
-		 * compare the result of this model with e.g. the parallel version of
-		 * this algorithm.
-		 **********************************************************************/ 
-		int RoverallSum = 0;
-		int RnumClasses = 0;
-		int SoverallSum = 0;
-		int SnumClasses = 0;
-		int correct = 0;
-		double fractionCorrect = 0f;
+		int RoverallSum = 0; //Total number of pixels in Reference Map
+		int RnumClasses = 0; //Total number of classes in Reference Map
+		int SoverallSum = 0; //Total number of pixels in Simulation Map
+		int SnumClasses = 0; //Total number of classes in Simulation Map
+		int correct = 0;	//Number of pixels counted correct
+		double fractionCorrect = 0f;	//Fraction correct
+		long localStartTime = System.currentTimeMillis(); //current Start Time
+		int numSteps = 0;
 		
-
-		long localStartTime = System.currentTimeMillis();
-		//iterate over all cells
+		neighborhoodRange = (int) Math.sqrt(referenceMap.getWidth()*referenceMap.getHeight()); //maximum possible pixel size
+		numSteps = (int) ((int)1+ Math.floor(Math.log(neighborhoodRange)/Math.log(2)));	//calculates how many steps are needed by doubling the pixel size until neighborhoodRange is reached. It is the reverse of an exponential function, which is the logarithm of neighborhoodRange to the basis 2. 2 is added because the calculation starts with 1 and not with 2 (1,2,4,8,16,32,...) and an array starts with 0.
+		statusOut.println("Maximum pixel size (as multiple of original resolution): "+neighborhoodRange);
+		statusOut.println("Number of steps: "+numSteps);
+		resultArray = new float[2][1+numSteps];
 		
-		neighborhoodRange = (int) Math.sqrt(referenceMap.getWidth()*referenceMap.getHeight()); //maximal mögliche Zellengröße
-		statusOut.println(neighborhoodRange);
-		resultArray = new float[1][13];
-		//Fraction correct for original Resolution
+		//Calculation of the fraction correct for the original Resolution
 		for (int x = 0; x < referenceMap.getWidth(); x++)
 			for (int y = 0; y < referenceMap.getHeight(); y++) {
-				float Rtmp = referenceMap.getRasterSampleAsFloat(x, y);
-				float Stmp = simulationMap.getRasterSampleAsFloat(x, y);
-				if (!Float.isNaN(Rtmp) && !Float.isNaN(Stmp)){
-					RoverallSum ++;
-					SoverallSum ++;
+				float Rtmp = referenceMap.getRasterSampleAsFloat(x, y); //get value of each raster cell in reference map
+				float Stmp = simulationMap.getRasterSampleAsFloat(x, y);//get value of each raster cell in simulation map
+				if (!Float.isNaN(Rtmp) && !Float.isNaN(Stmp)){	//if the value is a number, continue ...
+					RoverallSum ++;		//count all cells in reference map
+					SoverallSum ++;		//count all cells in simulation map
 					if (Rtmp > RnumClasses)
-						RnumClasses = (int) Rtmp;
+						RnumClasses = (int) Rtmp;	//Number of classes in reference map. If a higher cell value is detected than the actual RnumClasses, the number of classes is increased to that value
 					if (Stmp > SnumClasses)
-						SnumClasses = (int) Stmp;	
+						SnumClasses = (int) Stmp;	//see RnumClasses
 					if (Rtmp == Stmp)
-						correct++;
+						correct++;		//if the same cell value is detected in the simulation and the reference map, increase the number of correct pixels
 				}
 		}
-		fractionCorrect = (double) correct / (double) RoverallSum;
-		
-		//Anzahl der Pixel pro Klasse
-		for (int i = 1; i <= RnumClasses; i++){
-			int Rj = 0;
-			int Sj = 0;
+		fractionCorrect = (double) correct / (double) RoverallSum;	//divide the number of correct pixels by the number of total pixels
+
+		//Counts pixels per class
+		for (int i = 1; i <= RnumClasses; i++){		//Loop, until you reach the total number of classes
+			int Rj = 0;		//Number of classes in Reference Map
+			int Sj = 0;		//Number of classes in Simulation Map
 			for (int x = 0; x < referenceMap.getWidth(); x++)
 				for (int y = 0; y < referenceMap.getHeight(); y++){
-					float Rtmp = referenceMap.getRasterSampleAsFloat(x, y);
-					float Stmp = simulationMap.getRasterSampleAsFloat(x, y);
+					float Rtmp = referenceMap.getRasterSampleAsFloat(x, y);	//get value of each raster cell in reference map
+					float Stmp = simulationMap.getRasterSampleAsFloat(x, y);//get value of each raster cell in simulation map
 					if (!Float.isNaN(Rtmp))
 						if ((int) Rtmp == i)
-							Rj++;
+							Rj++;	//if cell belongs to category i, count it (for Reference map)
 					if (!Float.isNaN(Stmp))
 						if ((int) Stmp == i)
-							Sj++;
+							Sj++;	//if cell belongs to category i, count it (for Simulation map)
 				}
 			statusOut.println("Klasse "+i+": Referenz("+Rj+"), Simulation("+Sj+")");
 		}
 		
-		int ngrids = 0;
-		for (int r = 1; r <= neighborhoodRange; r = r+r){	//für Zellengröße 1 bis zur max. möglichen Zellengröße wird Statistik durchgeführt
+		int ngrids = 0;		//number of resolution grids
+		float Vg = 0f;	//sum of the individual cell weights for the calculation of the average weighted fit after Pontius (2002)
+		float VgWeights = 0f;	//sum of the cell weights
+		float WeightedAgreement = 0f;	//total weighted agreement over all resolutions after Pontius (2002)
+		for (int r = 1; r <= neighborhoodRange; r = r+r){	//for pixel size 1 up to the maximum pixel size, where one large cell covers the whole area
 			statusOut.println(r);
-			ngrids++;
-			outStep.addGrid();
-			float SumWn = 0f;	//Summe der gewichteten Mittelwerte 
-			int SumCells = 0;	//Summe der Zellen
-			float totalAgreement = 0f;	//Endergebnis
-			for (int x = 0; x < referenceMap.getWidth(); x = x+r)	//für jeden größer werdenden Zellenbereich...
+			ngrids++;		//count the number of grids
+			outStep.addGrid();	//add a grid to the outStep Output GridList
+			float SumWn = 0f;	//Sum of the weighted means 
+			int SumCells = 0;	//Number of the cells
+			float totalAgreement = 0f;	//total agreement is the weighted mean of the fraction correct over all resolution grids
+			for (int x = 0; x < referenceMap.getWidth(); x = x+r)	//for every pixel size...
 				for (int y = 0; y < referenceMap.getHeight(); y = y+r){
-					int nCells = 0;		//Anzahl Zellen pro größerer Zelle
-					float SumMinRS = 0f;	//Summe der Min-Werte bei Vergleich zweier Raster
-					float Wn = 0;	//Gewichtete Zelle
-					for(int x2 = x; x2 < x+r; x2++)	//für jede kleinere Zelle innerhalb der größeren...
+					int nCells = 0;		//number of cells making up a coarse cell
+					float SumMinRS = 0f;	//when two maps are compared, the minimum value is taken (MIN), this value is the sum of all these MINs
+					float Wn = 0;	//weighted cell
+					for(int x2 = x; x2 < x+r; x2++)	//for every cell within a coarse cell...
 						for(int y2 = y; y2 < y+r; y2++){
 							if ( x2 < referenceMap.getMinX() || y2 < referenceMap.getMinY() || x2 > referenceMap.getMinX()+referenceMap.getWidth()-1 || y2 > referenceMap.getMinY()+referenceMap.getHeight()-1 ||
 									Float.isNaN(referenceMap.getRasterSampleAsFloat(x2,y2)))
 								continue;
-							nCells++;	//zähle "positive" Zellen
+							nCells++;	//count all cells that have a value
 						}
-					for (int i = 0; i <= RnumClasses; i++){	//für jede Klasse i
-						int Rn = 0;	//Anzahl in Referenzkarte
-						int Sn = 0;	//Anzahl in Simulationskarte
-						float Rnj = 0f;	//Anteil in Referenzkarte
-						float Snj = 0f;	//Anteil in Simulationskarte
-						float MinRS = 0f;	//Min des Vergleichs zwischen beiden Karten
-						for(int x3 = x; x3 < x+r; x3++)	//für jede kleinere Zelle pro größerer Zelle...
+					for (int i = 0; i <= RnumClasses; i++){	//for every class i
+						int Rn = 0;		//Number of cells in the reference map
+						int Sn = 0;		//Number of cells in the simulation map
+						float Rnj = 0f;	//Portion of cells in the reference map
+						float Snj = 0f;	//Portion of cells in the simulation map
+						float MinRS = 0f;	//Both maps are compared and the Minimum (MIN) for each cell taken
+						for(int x3 = x; x3 < x+r; x3++)	//for every cell within a coarse cell...
 							for(int y3 = y; y3 < y+r; y3++){
 								if ( x3 < referenceMap.getMinX() || y3 < referenceMap.getMinY() || x3 > referenceMap.getMinX()+referenceMap.getWidth()-1 || y3 > referenceMap.getMinY()+referenceMap.getHeight()-1 ||
 										Float.isNaN(referenceMap.getRasterSampleAsFloat(x3,y3)))
 									continue;
-								float Rtmp = referenceMap.getRasterSampleAsFloat(x3, y3);	//hole Wert aus Referenz-Karte und
-								float Stmp = simulationMap.getRasterSampleAsFloat(x3, y3);	//Simulationskarte
+								float Rtmp = referenceMap.getRasterSampleAsFloat(x3, y3);	//get value of each cell in the reference map
+								float Stmp = simulationMap.getRasterSampleAsFloat(x3, y3);	//get value of each cell in the simulation map
 								if ((int) Rtmp == i)
-									Rn++;	//zähle in Referenzkarte Zellen, die zu Klasse i gehören 
+									Rn++;	//count all cells that belong to class i in reference map 
 								if ((int) Stmp == i)
-									Sn++;	//und in Simulationskarte
+									Sn++;	//count all cells that belong to class i in simulation map
 							}
-						if(nCells > 0){	//wenn positive Zellen vorhanden sind...
-							Rnj = (float)Rn / (float)nCells;	//berechne Anteile pro größerer Zelle
-							Snj = (float)Sn / (float)nCells;
+						if(nCells > 0){	//if positive cells are available...
+							Rnj = (float)Rn / (float)nCells;	//compute the portion of these cells within a coarse cell in the reference map
+							Snj = (float)Sn / (float)nCells;	//compute the portion of these cells within a coarse cell in the simulation map
 						}
-						MinRS = Math.min(Rnj, Snj);	//nehme Minimum-Wert des Vergleichs beider Karten
-						SumMinRS += MinRS;	//summiere die Minimum-Werte auf
-						//	statusOut.println(i+" Min"+MinRS+" Anzahl: "+nCells);
+						MinRS = Math.min(Rnj, Snj);	//take for every coarse cell the MIN between R and S of the portion of class i
+						SumMinRS += MinRS;	//Sum all the MIN values
 						
 					}
-					Wn = (float)nCells * SumMinRS;
+					Wn = (float)nCells * SumMinRS;	//all coarse cells are weighted by multiplying the Sum of all MIN values with the number of cells that make up a coarse cell
 					 
-					//	statusOut.println(SumMinRS+", gewichtet: "+Wn);
-					//Erstelle Output-Karten
+					//Compute output maps
 					float WnCell = 0f;
-					for(int x4 = x; x4 < x+r; x4++)	//für jede kleinere Zelle pro größerer Zelle...
+					for(int x4 = x; x4 < x+r; x4++)	//for every cell within a coarse cell...
 						for(int y4 = y; y4 < y+r; y4++){
 							if ( x4 < referenceMap.getMinX() || y4 < referenceMap.getMinY() || x4 > referenceMap.getMinX()+referenceMap.getWidth()-1 || y4 > referenceMap.getMinY()+referenceMap.getHeight()-1 ||
 									Float.isNaN(referenceMap.getRasterSampleAsFloat(x4,y4)))
 								continue;
-							WnCell = Wn / (float)nCells; //pro Zelle wird Mittelwert des Vergleichs genommen
-							actualValidation.setRasterSample( WnCell ,x4 ,y4);	
-							outStep.getGrid(ngrids-1).setRasterSample(WnCell,x4,y4);
+							WnCell = Wn / (float)nCells; //divide the weighted sum of the MIN values by the number of positive cells
+							actualValidation.setRasterSample( WnCell ,x4 ,y4);	//for every pixel in the Actual Comparison Grid take this value
+							outStep.getGrid(ngrids-1).setRasterSample(WnCell,x4,y4);	//and write the same grid into the Output Grid List
 						}
 				
-					SumCells += (float)nCells;	//Summiere alle Zellen auf
-					SumWn += Wn;	//Summiere die gewichteten Anteile auf
+					SumCells += (float)nCells;	//Sum all positive cells in a resolution grid
+					SumWn += Wn;	//Sum all weighted portions in a resolution grid
 				}
+			
 			//Total Agreement:
-			//siehe Pontius...
 			statusOut.println(SumWn+" / "+SumCells);
-			totalAgreement = SumWn / (float)SumCells;	//Ergebnisformel
+			totalAgreement = SumWn / (float)SumCells;	//Main Results
 			statusOut.println(totalAgreement);	
 			outResults.addValue(totalAgreement);
-			resultArray[0][ngrids] = totalAgreement;
-	//	statusOut.println("Gesamt-Pixel: "+RoverallSum);
-	//	statusOut.println("Anzahl Klassen: "+RnumClasses);
-	//	statusOut.println("Fraction Correct: "+fractionCorrect);
+			resultArray[0][ngrids] = r;
+			resultArray[1][ngrids] = totalAgreement;	//write the results in an array 
+			//the result array looks like this:
+			//1	   |2	 |4	   |8    |...
+			//0.876|0.892|0.913|0.948|...
+			Vg += SumWn * totalAgreement;
+			VgWeights += SumWn;
 		}
 		
+		//From here on the results of the Multiple Resolution Comparison are written on the screen
 		
-		System.out.println(resultArray[0][1]+","+resultArray[0][2]+","+resultArray[0][3]+","+
-				resultArray[0][4]+","+resultArray[0][5]+","+resultArray[0][6]+
-				","+resultArray[0][7]+","+resultArray[0][8]+","+resultArray[0][9]+","+resultArray[0][10]+","+resultArray[0][11]+","+resultArray[0][12]);
+		//those variables are needed to compute the weighted average of all fits after Costanza (1989)
+		float w = 0f;	//weight depending on resolution
+		float Fw = 0f;	//weighted fit at certain resolution
+		float SumW = 0f;	//Sum of all weights
+		float SumFw = 0f;	//Sum of all weighted agreements
+		float Ft = 0f;
 		
+		for(int i = 1; i <= ngrids; i++){
+			//print every element of the result array comma separated in one line in the status output
+			System.out.print(resultArray[1][i]+",");
+			//calculations for weighted average after Costanza (1989):
+			w = (float) Math.exp(-0.1*(resultArray[0][i] - 1));
+			Fw = resultArray[1][i]*w;
+			SumW += w;
+			SumFw += Fw;
+		}
+		
+		Ft = SumFw / SumW;	//Final calculation of the weighted average of all fits after Costanza (1989)
+		WeightedAgreement = Vg / VgWeights;	//Final calculation of the weighted average of all fits after Pontius (2002)
+		System.out.print("Ft:"+Ft+",TA:"+WeightedAgreement);	//the result is written directly behind the single fits for every resolution
+		
+		System.out.println("");
 		System.out.print("Finished step " + (stepNo) + " in "
 				+ ((System.currentTimeMillis() - localStartTime)) + " ms");
 		localStartTime = System.currentTimeMillis();

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java	2009-09-14 18:49:09 UTC (rev 58)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/MultipleResolutionValidationContentManager.java	2009-10-02 09:57:30 UTC (rev 59)
@@ -3,7 +3,6 @@
 import edu.bonn.xulu.model.AbstractModelContentManager;
 import edu.bonn.xulu.model.DefaultModelResource;
 import edu.bonn.xulu.model.ModelResource;
-import edu.bonn.xulu.model.PropertiesResource;
 import edu.bonn.xulu.model.ValuePropertyResource;
 import edu.bonn.xulu.plugin.data.grid.MultiGrid;
 import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
@@ -13,21 +12,17 @@
 
 
 /**
- * This class defines and handle the three resources for the models
- * <ol> 
- * <li><b> </li>
- * <li><b> {@link AverageNeighborhoodSerialDemoModel}</b></li>
- * <li><b> {@link AverageNeighborhoodParallelDemoModel}</b></li>
- * <li><b> {@link AVNTuned}</b></li>
- * </ol>
+ * This class defines and handles the resources for the Xulu-Model {@link MultipleResolutionValidation}
+ * 
  * @see ClueModelContentManager
- * @author automatically generated using {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGenerator}
+ * @see AverageNeighborhoodContentManager
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
  * @version 1.0
  */
 public class MultipleResolutionValidationContentManager extends AbstractModelContentManager {
 
   /**
-   * Erzeugt einen neuen ContentManager fuer das Modell {@linkplain AverageNeighborhoodParallelDemoModel}.
+   * Creates a new ContentManager for the Model {@linkplain MultipleResolutionValidation}.
    */
   public MultipleResolutionValidationContentManager() {
     super(6);



More information about the Xulu-commits mailing list