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

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Nov 6 14:34:05 CET 2009


Author: rgoetzke
Date: 2009-11-06 14:33:59 +0100 (Fri, 06 Nov 2009)
New Revision: 65

Added:
   trunk/src/edu/bonn/xulu/plugin/model/mrv/
   trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidation.java
   trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidationContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModification.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModificationContentManager.java
Modified:
   trunk/dist/xulu-doc.zip
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel_MC.java
Log:


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

Added: trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidation.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidation.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidation.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -0,0 +1,319 @@
+package edu.bonn.xulu.plugin.model.mrv;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * <b>MULTIPLE RESOLUTION COMPARISON</b><br>
+ * 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>
+ * <i>Costanza,R. (1989)</i>: Model Goodness of Fit - A Multiple Resolution Procedure. In: Ecological Modelling, vol. 47, no. 3-4, pp. 199-215.<br>
+ * <i>Pontius Jr, R.G. (2002)</i>: 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>
+ * <i>Pontius Jr, R.G., Huffaker, D. &amp; K. Denman (2004)</i>: Useful Techniques of Validation for Spatially Explicit Land-Change Models. 
+ * In: Ecological Modelling, vol. 179, no. 4, pp. 445-461.<br>
+ * 
+ * The following input parameters/images are required:<br>
+ * <ul>
+ *  <li><b>Number of Steps ({@code steps})</b>: Because this plugin is built as a step model, the number of (time) steps always has to be 1.</li>
+ *  <li><b>Reference Map ({@code referenceMap})</b>: A raster containing the reference (observed) land cover.</li>
+ *  <li><b>Simulation Map ({@code simulationMap})</b>: A raster containing the simulated land cover.</li>
+ * </ul>
+ * 
+ * Furthermore the following outputs are created:<br>
+ * <ul>
+ *  <li><b>Actual Validation (@code actualValidation)</b>: A raster containing the actual resolution grid with the fraction correct in every cell</li>
+ *  <li><b>Out Step ({@code outStep})</b>: A Grid List containing a grid (Actual Validation) for every resolution.</li>
+ *  <li><b>Out Results ({@code outResults})</b>: A list containing the total agreement for every resolution.</li>
+ * </ul>
+ * 
+ * Other important values are written to the status output window!<br>
+ * 
+ * @see MultipleResolutionValidationContentManager
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
+ * @version 1.0
+ *
+ */
+public class MultipleResolutionValidation extends AbstractStepModel {
+
+	/**
+	 * 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 = 0;
+	
+	/** Array containing the fraction correct for every resolution. */
+	private float[][] resultArray;
+	
+	/**
+	 * Saves the ContentManager for the model.
+	 * 
+	 * @see MultipleResolutionValidationContentManager
+	 */
+	protected MultipleResolutionValidationContentManager contManager;
+
+	// ********** Read/Write access, that has to be maintained ***
+	// ********** through the whole model run ********************
+	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
+	private PropertyWriteAccess WA_outStep = null;	// Step Results
+	private ListPropertyWriteAccess WA_outResults = null;	//Output Validation Results
+
+	// **************** Variables to work with *******************
+	private PropertyReadAccess steps = null; // Number of steps
+	private WritableGrid referenceMap = null; // Reference Map
+	private WritableGrid simulationMap = null;	// Simulation Map
+	private WritableGrid actualValidation = null; // Output Grid
+	private MultiGrid outStep = null;	//Step Results
+	private ListPropertyWriteAccess outResults = null;	//Output Validation Results
+
+
+	/**
+	 * Creates a new model instance.
+	 */
+	public MultipleResolutionValidation() {
+		super(new MultipleResolutionValidationContentManager());
+		this.contManager = (MultipleResolutionValidationContentManager) super.contManager;
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		if (contManager == null)
+			return;
+		// Get access authorisation of resource/properties
+		RA_steps = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(0).getData())
+					.getReadAccess(this);
+		RA_referenceMap = null;
+		if (contManager.getResource(1).getData() != null)
+			RA_referenceMap = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getReadAccess(this);
+		RA_simulationMap = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_simulationMap = ((ScalarProperty) contManager.getResource(2)
+					.getData()).getReadAccess(this);
+		WA_actualValidation = null;
+		if (contManager.getResource(3).getData() != null)
+			WA_actualValidation = ((ScalarProperty) contManager.getResource(3)
+					.getData()).getWriteAccess(this);
+		WA_outResults = null;
+		if (contManager.getResource(5).getData() != null)
+			WA_outResults = ((ListProperty) contManager.getResource(5)
+					.getData()).getWriteAccess(this);
+
+		//Assign variables to work with
+		steps = RA_steps;
+		referenceMap = (WritableGrid) RA_referenceMap.getValue();
+		simulationMap = (WritableGrid) RA_simulationMap.getValue();
+		actualValidation = (WritableGrid) WA_actualValidation.getValue();
+
+		this.stepCount = steps.getValueAsInt();
+		outStep = (MultiGrid)contManager.getResource(4).getData();
+		outResults = WA_outResults;
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+
+		// free resources
+		releaseAccess(RA_steps);
+		releaseAccess(RA_referenceMap);
+		releaseAccess(RA_simulationMap);
+		releaseAccess(WA_actualValidation);
+		releaseAccess(WA_outStep);
+		releaseAccess(WA_outResults);
+	}
+
+	/**
+	 * 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 + "...");
+		
+		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;
+		
+		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];
+		
+		//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); //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;	//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;	//see RnumClasses
+					if (Rtmp == Stmp)
+						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;	//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);	//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++;	//if cell belongs to category i, count it (for Reference map)
+					if (!Float.isNaN(Stmp))
+						if ((int) Stmp == i)
+							Sj++;	//if cell belongs to category i, count it (for Simulation map)
+				}
+			statusOut.println("Class "+i+": Reference("+Rj+"), Simulation("+Sj+")");
+		}
+		
+		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++;		//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;		//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++;	//count all cells that have a value
+						}
+					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);	//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++;	//count all cells that belong to class i in reference map 
+								if ((int) Stmp == i)
+									Sn++;	//count all cells that belong to class i in simulation map
+							}
+						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);	//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;	//all coarse cells are weighted by multiplying the Sum of all MIN values with the number of cells that make up a coarse cell
+					 
+					//Compute output maps
+					float WnCell = 0f;
+					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; //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;	//Sum all positive cells in a resolution grid
+					SumWn += Wn;	//Sum all weighted portions in a resolution grid
+				}
+			
+			//Total Agreement:
+			statusOut.println(SumWn+" / "+SumCells);
+			totalAgreement = SumWn / (float)SumCells;	//Main Results
+			statusOut.println(totalAgreement);	
+			outResults.addValue(totalAgreement);
+			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
+		
+		//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();
+		System.out.println(" with sum (local calculated): " + RoverallSum);
+		
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidationContentManager.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/mrv/MultipleResolutionValidationContentManager.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -0,0 +1,42 @@
+package edu.bonn.xulu.plugin.model.mrv;
+
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.DefaultModelResource;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ScalarProperty;
+
+
+/**
+ * This class defines and handles the resources for the Xulu-Model {@link MultipleResolutionValidation}
+ * 
+ * @see ClueModelContentManager
+ * @see AverageNeighborhoodContentManager
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
+ * @version 1.0
+ */
+public class MultipleResolutionValidationContentManager extends AbstractModelContentManager {
+
+  /**
+   * Creates a new ContentManager for the Model {@linkplain MultipleResolutionValidation}.
+   */
+  public MultipleResolutionValidationContentManager() {
+    super(6);
+    // Steps
+    resource[0]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+    // Reference Map
+    resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Reference Map",ScalarProperty.class,WritableGrid.class,false);
+    // Simulation Map
+    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Simulation Map",ScalarProperty.class,WritableGrid.class,false);
+    // Actual Validation
+    resource[3]	= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Actual Validation",ScalarProperty.class,WritableGrid.class,false);
+    // Map for every Resolution
+    resource[4]	= new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,"Step Results",MultiGrid.class,false);
+    // Output Values
+    resource[5]	= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Validation Results",ListProperty.class,Double.class,false);
+  }
+}

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -25,7 +25,7 @@
  *  <ul>
  *   <li><b>UGM MonteCarlo ({@link UrbanGrowthModel_MC UrbanGrowthModel_MC})</b>: The same model algorithm like this, but with Monte Carlo Iterations. The resulting map shows the probabilities for new urbanization (@link MultipleResolutionValidation MultipleResolutionValidation)</li>
  *   <li><b>UGM Calibration ({@link UrbanGrowthModelCalibration UrbanGrowthModelCalibration})</b>: The same model algorithm like this, but in order to calibrate the model by finding the correct parameter values with the method of Multiple Resolution Comparison (@link MultipleResolutionValidation)</li>
- *   <li><b>UGM SelfModifying({@link UrbanGrowthModelSelfModifying UrbanGrowthModelSelfModifying})</b>: The same model algorithm like this, but with the possibility of self-modification of the parameter values.</li>
+ *   <li><b>UGM SelfModifying({@link UrbanGrowthModelSelfModification UrbanGrowthModelSelfModifying})</b>: The same model algorithm like this, but with the possibility of self-modification of the parameter values.</li>
  *   <li><b>UGM CalibrationSelfModifying({@link UrbanGrowthModelCalibrationSelfModification UrbanGrowthModelCalibrationSelfModification})</b>: The same model algorithm like this, but in order to calibrate the model by finding the correct parameter values with the method of Multiple Resolution Comparison (@link MultipleResolutionValidation)
  *    While calibrating the model modifies the parameter values.</li>
  *  </ul>
@@ -78,33 +78,33 @@
 
 	// ********** Read/Write access, that has to be maintained ***
 	// ********** through the whole model run ********************
+	protected PropertyReadAccess RA_steps = null; // Number of steps
 	protected PropertyReadAccess RA_inputGrid = null; // Input Grid
 	protected PropertyWriteAccess WA_outputGrid = null; // Output Grid
-	protected PropertyReadAccess RA_steps = null; // Number of steps
 	protected PropertyReadAccess RA_areaRestr = null; //Area Restrictions
+	protected PropertyReadAccess RA_roadGrid = null;	//Road Grid
+	protected PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
 	protected PropertyReadAccess RA_spread = null;	//Spread-Koeffizient
 	protected PropertyReadAccess RA_disp = null;		//Dispersions-Koeffizient
 	protected PropertyReadAccess RA_breed = null;		//Breed-Koeffizient
 	protected PropertyReadAccess RA_roadGravity = null;	//Road-Gravity-Koeffizient
 	protected PropertyReadAccess RA_slope = null;	//Slope-Koeffizient
 	protected PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
-	protected PropertyReadAccess RA_roadGrid = null;	//Road Grid
-	protected PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
 	protected PropertyWriteAccess WA_outStep = null;	// Step Results
 
-	// **************** Variablen mit denen gearbeitet wird *******************
+	// **************** Variables to work with *******************
+	protected PropertyReadAccess steps = null; // Number of steps
 	protected WritableGrid inputGrid = null; // Input Grid
 	protected WritableGrid outputGrid = null; // Output Grid
-	protected PropertyReadAccess steps = null; // Number of steps
 	protected WritableGrid areaRestr = null; //Area Restrictions
+	protected WritableGrid roadGrid = null;	//Road Grid
+	protected WritableGrid slopeGrid = null;	//Slope Grid
 	protected double spread = 0;	//Spread-Koeffizient
 	protected double disp = 0;	//Dispersions-Koeffizient
 	protected double breed = 0;	//Breed-Koeffizient
 	protected double roadGravity = 0;	//Road-Gravity-Koeffizient
 	protected double slope = 0;	//Slope-Koeffizient
 	protected double criticalSlope = 0;	//Critical Slope Value
-	protected WritableGrid roadGrid = null;	//Road Grid
-	protected WritableGrid slopeGrid = null;	//Slope Grid
 	protected MultiGrid outStep = null;	//Step Results
 		
 	/**
@@ -155,54 +155,54 @@
 		if (contManager == null)
 			return;
 		// Get access authorisation of resource/properties
+		RA_steps = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(0).getData())
+					.getReadAccess(this);
 		RA_inputGrid = null;
-		if (contManager.getResource(0).getData() != null)
-			RA_inputGrid = ((ScalarProperty) contManager.getResource(0)
+		if (contManager.getResource(1).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(1)
 					.getData()).getReadAccess(this);
 		WA_outputGrid = null;
-		if (contManager.getResource(1).getData() != null)
-			WA_outputGrid = ((ScalarProperty) contManager.getResource(1)
+		if (contManager.getResource(2).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(2)
 					.getData()).getWriteAccess(this);
-		RA_steps = null;
-		if (contManager.getResource(2).getData() != null)
-			RA_steps = ((ScalarProperty) contManager.getResource(2).getData())
-					.getReadAccess(this);
 		RA_areaRestr = null;
 		if (contManager.getResource(3).getData() != null)
 			RA_areaRestr = ((ScalarProperty) contManager.getResource(3)
 					.getData()).getReadAccess(this);
+		RA_roadGrid = null;
+		if (contManager.getResource(4).getData() != null)
+			RA_roadGrid = ((ScalarProperty) contManager.getResource(4)
+					.getData()).getReadAccess(this);
+		RA_slopeGrid = null;
+		if (contManager.getResource(5).getData() != null)
+			RA_slopeGrid = ((ScalarProperty) contManager.getResource(5)
+					.getData()).getReadAccess(this);
 		RA_spread = null;
-		if (contManager.getResource(4).getData() != null)
-			RA_spread = ((ScalarProperty) contManager.getResource(4).getData())
+		if (contManager.getResource(6).getData() != null)
+			RA_spread = ((ScalarProperty) contManager.getResource(6).getData())
 					.getReadAccess(this);
 		RA_disp = null;
-		if (contManager.getResource(5).getData() != null)
-			RA_disp = ((ScalarProperty) contManager.getResource(5).getData())
+		if (contManager.getResource(7).getData() != null)
+			RA_disp = ((ScalarProperty) contManager.getResource(7).getData())
 					.getReadAccess(this);
 		RA_breed = null;
-		if (contManager.getResource(6).getData() != null)
-			RA_breed = ((ScalarProperty) contManager.getResource(6).getData())
+		if (contManager.getResource(8).getData() != null)
+			RA_breed = ((ScalarProperty) contManager.getResource(8).getData())
 					.getReadAccess(this);
 		RA_roadGravity = null;
-		if (contManager.getResource(7).getData() != null)
-			RA_roadGravity = ((ScalarProperty) contManager.getResource(7).getData())
+		if (contManager.getResource(9).getData() != null)
+			RA_roadGravity = ((ScalarProperty) contManager.getResource(9).getData())
 					.getReadAccess(this);
 		RA_slope = null;
-		if (contManager.getResource(8).getData() != null)
-			RA_slope = ((ScalarProperty) contManager.getResource(8).getData())
+		if (contManager.getResource(10).getData() != null)
+			RA_slope = ((ScalarProperty) contManager.getResource(10).getData())
 					.getReadAccess(this);
 		RA_criticalSlope = null;
-		if (contManager.getResource(9).getData() != null)
-			RA_criticalSlope = ((ScalarProperty) contManager.getResource(9).getData())
+		if (contManager.getResource(11).getData() != null)
+			RA_criticalSlope = ((ScalarProperty) contManager.getResource(11).getData())
 					.getReadAccess(this);
-		RA_roadGrid = null;
-		if (contManager.getResource(10).getData() != null)
-			RA_roadGrid = ((ScalarProperty) contManager.getResource(10)
-					.getData()).getReadAccess(this);
-		RA_slopeGrid = null;
-		if (contManager.getResource(11).getData() != null)
-			RA_slopeGrid = ((ScalarProperty) contManager.getResource(11)
-					.getData()).getReadAccess(this);
 
 		// Assign variables to work with
 		inputGrid = (WritableGrid) RA_inputGrid.getValue();
@@ -234,28 +234,17 @@
 		statusOut.println("Max. Slope: "+slopeMax+" %");
 				
 		//Creates a new Lookup-table
-		slopeLUT = new HashMap<Number,Number>();
+		//slopeLUT = new HashMap<Number,Number>();
 		
 		//assigns for every slope value between 0 and the maximum slope that is below the critical slope the value calculated for the variable "lookup".
 		//all values higher than the critical slope become 1
+
 		int MaxSlopeResistance = 0;
-		double exp = 0.0;
 		MaxSlopeResistance = 100;	//Max slope resistance is 100%
-		exp = (slope / (MaxSlopeResistance / 2.0));
-		double[] lookup = new double[slopeMax+1];
-		Number key = 0;
-		for (int i = 0;i <= slopeMax;i++){
-			if (i <= criticalSlope){
-				double val = (criticalSlope - i) / criticalSlope;
-				lookup[i] = 1 - Math.pow(val,exp);
-				key = i;
-			} else{
-				lookup[i] = 1;
-				key = i;
-			}
-			slopeLUT.put(key,lookup[i]);
-		}	
 		
+		double exp = getSlopeExp(slope,MaxSlopeResistance);
+		slopeLUT = getSlopeLookup(slopeMax,exp,criticalSlope);
+		
 		//raster dimensions
 		areaMinX = inputGrid.getMinX();
 		areaMinY = inputGrid.getMinY();
@@ -282,9 +271,9 @@
 	public void performModelDispose() {
 
 		// free resources
+		releaseAccess(RA_steps);
 		releaseAccess(RA_inputGrid);
 		releaseAccess(WA_outputGrid);
-		releaseAccess(RA_steps);
 		releaseAccess(RA_areaRestr);
 		releaseAccess(RA_spread);
 		releaseAccess(RA_disp);
@@ -325,7 +314,7 @@
 		 * DISPERSION and BREED (Growth Phase 1 and 2)
 		 *****************************************************************/
 		boolean[][] tmpGridDisp = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
-		tmpGridDisp = DispersionGrowth();	//calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
+		tmpGridDisp = DispersionGrowth(disp_value,breed);	//calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
 		int anzDispBreed = 0;	//number of cells urbanized by Dispersion and Breed
 		for (int x = 0; x < inputGrid.getWidth();x++)
 			for(int y = 0; y < inputGrid.getHeight();y++){
@@ -344,7 +333,7 @@
 		 * EDGE
 		 *********************************************************************/
 		boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
-		tmpGridSpread = EdgeGrowth();	//calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
+		tmpGridSpread = EdgeGrowth(spread);	//calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
 		int anzSpread = 0;	//number of cells urbanized by Spread
 		for (int x = 0; x < inputGrid.getWidth();x++)
 			for(int y = 0; y < inputGrid.getHeight();y++){
@@ -361,9 +350,8 @@
 		/*********************************************************************
 		 * ROAD
 		 *********************************************************************/
-		
 		boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
-		tmpGridRoad = RoadGrowth(tmpGrid);	//calls the method "RoadGrowth" to perform the Road weighted growth
+		tmpGridRoad = RoadGrowth(tmpGrid,rg_value,breed,disp);	//calls the method "RoadGrowth" to perform the Road weighted growth
 		int anzRoad = 0;	//number of cells urbanized by Road Growth
 		for (int x = 0; x < inputGrid.getWidth();x++)
 			for(int y = 0; y < inputGrid.getHeight();y++){
@@ -455,7 +443,7 @@
 	 * Takes a slope value from the slope lookup-table depending on the given cell in the slope raster.
 	 * @return slopeDoubleNb
 	 */
-	public double getSlopeValue(int X,int Y){
+	public double getSlopeValue(int X,int Y, HashMap<Number,Number> slopeLUT){
 		int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(X, Y);	//takes a slope value from the slope raster
 		Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);	//looks for that slope value in the Lookup-Table and takes it as a double number
 		double slopeDoubleNb = doubleObjNb.doubleValue();	//converts the double object into a double value.
@@ -463,11 +451,42 @@
 	}
 	
 	/**
+	 * Calculates the exp value that is needed to generate the slope lookup-table 
+	 * @param slope
+	 * @param MaxSlopeResistance
+	 * @return exp
+	 */
+	public double getSlopeExp(double slope, int MaxSlopeResistance){
+		double exp = (slope / (MaxSlopeResistance / 2.0));
+		return exp;
+	}
+	
+	public HashMap<Number,Number> getSlopeLookup(int slopeMax,double exp,double criticalSlope){
+		//Creates a new Lookup-table
+		HashMap<Number, Number> newLUT = new HashMap<Number,Number>();
+		double[] lookup = new double[slopeMax+1];
+		Number key = 0;
+		for (int i = 0;i <= slopeMax;i++){
+			if (i <= criticalSlope){
+				double val = (criticalSlope - i) / criticalSlope;
+				lookup[i] = 1 - Math.pow(val,exp);
+				key = i;
+			} else{
+				lookup[i] = 1;
+				key = i;
+			}
+			newLUT.put(key,lookup[i]);
+			//statusOut.println("Lookup: "+key+", "+lookup[i]);
+		}	
+		return newLUT;
+	}
+	
+	/**
 	 * This is phase 1 of the growth cycle, where spontaneous growth occurs (DISPERSION). Those new cells can turn out to be
 	 * new spreading centers by urbanizing neighboring pixels (BREED {@link BreedGrowth}).
 	 * @return tmpGridDispBreed
 	 */
-	public boolean[][] DispersionGrowth(){
+	public boolean[][] DispersionGrowth(double disp_value,double breed){
 		//DISPERSION
 		int dispRandX = 0;	//x-coordinate for randomly created cell
 		int dispRandY = 0;	//y-coordinate for randomly created cell
@@ -485,7 +504,7 @@
 			if (areaRestr.getRasterSampleAsFloat(dispRandX,dispRandY) != 0 || outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY) == 1)
 	        	continue;		//if a cell is inside an excluded area or already exists, break and continue loop from the beginning
 	        slopeRandDisp = (float) Math.random();	//a random slope value between 0.0 and 1.0
-	        double slopeDouble = getSlopeValue(dispRandX,dispRandY);	//returns the slope value for the cell
+	        double slopeDouble = getSlopeValue(dispRandX,dispRandY,slopeLUT);	//returns the slope value for the cell
 	        if(slopeDouble < slopeRandDisp){	//if the slope value of the pixel is smaller than the slope value
 	        	tmpGridDispBreed[dispRandX][dispRandY] = true;	//true is written in the temporary raster
 	        	anzDispTreffer++;		//count number of dispersion cells
@@ -548,7 +567,7 @@
     			if (areaRestr.getRasterSampleAsFloat(nbBreedX,nbBreedY) != 0)
     				continue;	//if a cell is inside an excluded area, break and continue loop from the beginning
     			RNBreedSlope = (float)Math.random();	//a random slope value between 0.0 and 1.0
-    			double slopeDoubleNb = getSlopeValue(nbBreedX,nbBreedY);	//returns the slope value for the neighboring cells which are available for breed
+    			double slopeDoubleNb = getSlopeValue(nbBreedX,nbBreedY,slopeLUT);	//returns the slope value for the neighboring cells which are available for breed
     			float breedSample = outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);	//takes the value from the input grid
     			if (breedSample == 0f){		//if it is free for urbanization...
     				anzBreedTemp++;		//increase the number of temporary breed cells
@@ -571,7 +590,7 @@
 	 * this time (including the new spontaneous and spreading center pixels).
 	 * @return tmpGridSpread
 	 */
-	public boolean[][] EdgeGrowth(){
+	public boolean[][] EdgeGrowth(double spread){
 		
 		boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
 		//definitions for neighborhood cells
@@ -608,7 +627,7 @@
 						if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
 				        	continue;	//if a cell is inside an excluded area, break and continue loop from the beginning
 						RNEdgeSlope = (float)Math.random();		//a random number to be compared with the slope value
-						double slopeDoubleNb = getSlopeValue(nbX,nbY);	//returns the slope value for the neighboring cells which are available for breed
+						double slopeDoubleNb = getSlopeValue(nbX,nbY,slopeLUT);	//returns the slope value for the neighboring cells which are available for breed
 	        			float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);	//takes the value from the input gridn
 						if (rasterSample == 0f){	//if the value is 0 and thus is possible for urbanization
 							anzTemp++;				//count it
@@ -637,13 +656,14 @@
 	 * @param tmpGrid
 	 * @return tmpGridRoad
 	 */
-	public boolean[][] RoadGrowth(boolean[][] tmpGrid){
+	public boolean[][] RoadGrowth(boolean[][] tmpGrid,double rg_value, double breed, double disp){
 		boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
 		int anzGesamt = countTempUrbanCells(tmpGrid);	//number of urban cells in the temporary cell array
 		int anzRoadTreffer = 0;
 		int[] cellValue = null;	//array of cell values
 		int RSearchRoad = 0;	//Random Road Search Index
 		int r = 1;	//number between 1 and the disp-Value, whih is increased during the follwing while-loop. It determines how many pixels are selected randomly for a possible road trip
+		int anzTempRoadNb = 0;
 		
 		do{
 			RSearchRoad = Math.round((float)Math.random()*anzGesamt);	//a random value between 1 and the total amount of newly urbanized pixels
@@ -660,15 +680,16 @@
 						int tempRoadCell[] = null;		//an array of temporary road cells
 						int tempNbRoadCell[] = null;	//an array of temporary neighboring cells of these road cells
 						if (cellValue[2] == RSearchRoad){	//randomly select a growth pixel to start search for road (by comparing the cell number with the generated random number between 1 and total amount of new cells)
+						//	statusOut.println("Randomly selected road pixel found...");
 							r++;	//increase r, because a potential road trip pixel has been selected
 							float roadValue = roadGrid.getRasterSampleAsFloat(X,Y);	//take the value from the road map for that pixel
 							if (roadValue > 0.0){		//if the value is greater than 0 and thus is a road...
 								tempRoadCell = new int[] {X,Y};		//add its coordinates to the temporary road grid
-								//statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
-								int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1]);	//perform a road walk
+							//	statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
+								int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],disp);	//perform a road walk
 								if(nbCellNew != null){	//if the result of the road walk is positive,...
 									tmpGridRoad[nbCellNew[0]][nbCellNew[1]] = true;		//place a new urban pixel in the temporary Grid
-									anzRoadTreffer++;
+									anzRoadTreffer++;	//?!?
 									int[][] tmpBreedArray = new int[2][2];	//an array containing the x and y coordinates of two breed cells
 									tmpBreedArray = BreedGrowth(nbCellNew[0],nbCellNew[1]);	//this new urban cell can act as a new spreading center:
 									int x1 = tmpBreedArray[0][0];	//x-coordinate of first cell
@@ -683,9 +704,11 @@
 								}
 							} else{		//if the selected pixel has not been a road pixel search in the neighborhood for a road
 								int anzRoadNb = 0;
-								
+						//		statusOut.println("no road cell on first run...");
+							
 								//With a loop look in the neighborhood for a road in an increasing radius until you reach the road gravity value
 								for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){
+								//	statusOut.println("RG_VALUE: "+rg_value+"; ROAD-SEARCH-VALUE = "+roadSearch);
 									if (anzRoadNb > 0)	//if a road is found break and continue from the beginning (the next loops will end here as well until it stops when rg_value ist reached)
 										continue;
 									for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++){
@@ -696,15 +719,16 @@
 											float roadValueNb = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY);		//take the value from the road map for that pixel
 											if (roadValueNb > 0f){	//if the value is greater than 0 and thus is a road...
 												anzRoadNb++;	//increase the number of road neighbors
+									//			statusOut.println("Number of road neighbors: "+anzRoadNb);
 											}
 										}
 									}
 									roadNeighborhoodRange++;	//increase the road neighborhood range
 									RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);		//a random value between 0 and the number of road neighbors
-									int anzTempRoadNb = 0;	//number of temporary road neighbors
+									anzTempRoadNb = 0;	//number of temporary road neighbors
 									for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++){
 										for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){	//again increase the neighborhood in every loop
-						        		//	statusOut.println("TEST-ROAD: "+nbRoadCellsX+","+nbRoadCellsY);
+						        			//statusOut.println("TEST-ROAD: "+nbRoadCellsX+","+nbRoadCellsY);
 											if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
 													Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
 												continue;	//if a cell is outside the raster (NaN), break and continue loop from the beginning
@@ -712,10 +736,11 @@
 											if (roadValueNbTemp > 0f){	//if the value is greater than 0 and thus is a road... 
 												anzTempRoadNb++;	//increase the number of temporary road neighbors
 												tempNbRoadCell = new int[] {nbRoadCellsX,nbRoadCellsY,anzTempRoadNb};	//build an array of neighboring road cells with its coordinates
+											//	statusOut.println("in Array: "+tempNbRoadCell[2]+"Random: "+RSearchNbRoad+"Anzahl temporärer Zellen: "+anzTempRoadNb);
 												if (tempNbRoadCell[2]==RSearchNbRoad){	//check the position in that array with the random number
 													tempRoadCell = tempNbRoadCell;	//the main temporary road cell is moved to this position
 													//statusOut.println("Strasse in Entfernung "+roadSearch+": "+tempRoadCell[0]+","+tempRoadCell[1]+","+tempRoadCell[2]);
-													int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1]);	//perform a road walk
+													int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],disp);	//perform a road walk
 													if(nbCellNew != null){	//if the result of the road walk is positive,...
 														tmpGridRoad[nbCellNew[0]][nbCellNew[1]] = true;	//place a new urban cell in the temporary grid
 														anzRoadTreffer++;
@@ -729,9 +754,11 @@
 										        		tmpGridRoad[x2][y2] = true;
 														anzRoadTreffer += 2;
 													} else{
-											//			statusOut.println("No new road cell found after road search.");
+												//		statusOut.println("No new road cell found after road search.");
 													}
 												}
+											} else{
+											//	statusOut.println("Nothing to find...");
 											}
 										}
 									}
@@ -754,7 +781,7 @@
 	 * @param Y
 	 * @return nbCellNew
 	 */
-	public int[] roadWalk(int X,int Y){
+	public int[] roadWalk(int X,int Y,double disp){
 		boolean end_of_road = false;	//start with the assumption that the end of the road trip is not completed yet	
 		int run = 0;	//distance a cell is moving
 		int run_value = 0;	//maximum moving distance
@@ -823,7 +850,7 @@
 											continue;	//if a cell is inside an excluded area, break and continue loop from the beginning
 										float rasterSample = outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY);	//take the raster value
 										RNRoadSlope = (float)Math.random();	//generate a random number in order to compare it with the slope
-										double slopeDoubleNb = getSlopeValue(nbUrbanizeX,nbUrbanizeY);	//returns the slope value for the neighboring cells which are available for breed
+										double slopeDoubleNb = getSlopeValue(nbUrbanizeX,nbUrbanizeY,slopeLUT);	//returns the slope value for the neighboring cells which are available for breed
 										if (rasterSample == 0f){	//if the raster sample is available for urbanization...
 											NbTemp++;	//count it
 											nbCellTemp = new int[] {nbUrbanizeX,nbUrbanizeY,NbTemp};	//create an array holding the coordinates and the number of that neighbor cell

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibration.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -1,14 +1,7 @@
 package edu.bonn.xulu.plugin.model.sleuth;
 
-import java.awt.Rectangle;
-import java.util.HashMap;
-
-import appl.util.RasterUtil;
-
-import edu.bonn.xulu.model.AbstractStepModel;
 import edu.bonn.xulu.model.XuluModel;
 import edu.bonn.xulu.plugin.data.grid.MultiGrid;
-
 import schmitzm.data.WritableGrid;
 import schmitzm.data.property.ListProperty;
 import schmitzm.data.property.ListPropertyWriteAccess;
@@ -17,210 +10,236 @@
 import schmitzm.data.property.ScalarProperty;
 
 /**
- * @see AverageNeighborhoodContentManager
- * @author Dominik Appl
+ * <b>Calibration of the Urban Growth Model</b><br>
+ *  This model is based on the {@link UrbanGrowthModel Urban Growth Model}, developed by Keith Clarke at the UC Santa Barbara, CA, within the Gigalopolis Project, funded by the
+ *  USGS. It has exactly the same growth rules as its parent class, but runs with n Monte-Carlo Iterations. So the resulting map does not contain the urban extent after a model
+ *  run, but the probability for new urbanization. The more often a cell has been selected for urbanization during the Monte-Carlo Iterations, the higher is that value in the 
+ *  output map. The model performs this procedure for every combination of the different coefficients. There is not a single coefficient value as in the original model, but a starting
+ *  value, a step value and an end value. So, when starting with a coefficient of 5, a step value of 10 and an end value of 25, the model will perform 3 steps (for 5, 15, and 25). Be 
+ *  aware that entering many steps for many coefficients will result in a huge amount of possible combinations. Therefore the calibration should be performed sequential from a coarse
+ *  calibration over a fine calibration to a final calibration. The perforamce of the different model runs is measured by the {@link edu.bonn.xulu.plugin.model.mrv.MultipleResolutionValidation Multiple Resolution Comparison}.
+ *  This validation procedure has been adopted for this class and is integrated in a separate method. The original SLEUTH Urban Growth Model is calibrated by a different procedure.
+ *  For a detailed description refer to {@link UrbanGrowthModel Urban Growth Model}, {@link UrbanGrowthModel_MC Urban Growth Model MC} or 
+ *  {@link edu.bonn.xulu.plugin.model.mrv.MultipleResolutionValidation Multiple Resolution Comparison}
+ *  
+ *  <br>
+ *  In addition to the UGM parameters, these parameters are needed:<br>
+ * <ul>
+ *  <li><b>Spread Start</b>: Spread Starting Coefficient</li>
+ *  <li><b>Spread Step</b>: Spread Step Coefficient</li>
+ *  <li><b>Spread End</b>: Spread End Coefficient</li>
+ *  <li><b>Dispersion Start</b>: Dispersion Starting Coefficient</li>
+ *  <li><b>Dispersion Step</b>: Dispersion Step Coefficient</li>
+ *  <li><b>Dispersion End</b>: Dispersion End Coefficient</li>
+ *  <li><b>Breed Start</b>: Breed Starting Coefficient</li>
+ *  <li><b>Breed Step</b>: Breed Step Coefficient</li>
+ *  <li><b>Breed End</b>: Breed End Coefficient</li>
+ *  <li><b>RoadGravity Start</b>: RoadGravity Starting Coefficient</li>
+ *  <li><b>RoadGravity Step</b>: RoadGravity Step Coefficient</li>
+ *  <li><b>RoadGravity End</b>: RoadGravity End Coefficient</li>
+ *  <li><b>Slope Start</b>: Slope Starting Coefficient</li>
+ *  <li><b>Slope Step</b>: Slope Step Coefficient</li>
+ *  <li><b>Slope End</b>: Slope End Coefficient</li>
+ *  <li><b>Monte Carlo Iterations</b>: The number of Monte Carlo Iterations.</li>
+ *  <li><b>Sum Step Results</b>: List of resulting maps containing the sums over all Monte Carlo Iterations for a single parameter combination.</li>
+ * </ul>
+ * 
+ * @see UrbanGrowthModelCalibrationContentManager
+ * @see UrbanGrowthModel
+ * @see UrbanGrowthModel_MC
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
  * @version 1.0
  */
-public class UrbanGrowthModelCalibration extends AbstractStepModel {
+public class UrbanGrowthModelCalibration extends UrbanGrowthModel {
 
-	private int neighborhoodRange = 0;
-	private float[] resultArray;
-	private float[][] resultArrayFinal;
-	/**
-	 * Speichert den ContentManager fuer das Modell.
-	 */
-	protected UrbanGrowthModelCalibrationContentManager contManager;
+	// ********** Read/Write access, that has to be maintained ***
+	// ********** through the whole model run ********************
+	protected PropertyReadAccess RA_referenceMap = null;	//Observed Validation Grid
+	protected PropertyReadAccess RA_spreadStart = null;	//Spread-Coefficient
+	protected PropertyReadAccess RA_spreadStep = null;	//Spread-Coefficient
+	protected PropertyReadAccess RA_spreadEnd = null;	//Spread-Coefficient
+	protected PropertyReadAccess RA_dispStart = null;		//Dispersion-Coefficient
+	protected PropertyReadAccess RA_dispStep = null;		//Dispersion-Coefficient
+	protected PropertyReadAccess RA_dispEnd = null;		//Dispersion-Coefficient
+	protected PropertyReadAccess RA_breedStart = null;		//Breed-Coefficient
+	protected PropertyReadAccess RA_breedStep = null;		//Breed-Coefficient
+	protected PropertyReadAccess RA_breedEnd = null;		//Breed-Coefficient
+	protected PropertyReadAccess RA_roadGravityStart = null;	//Road-Gravity-Coefficient
+	protected PropertyReadAccess RA_roadGravityStep = null;	//Road-Gravity-Coefficient
+	protected PropertyReadAccess RA_roadGravityEnd = null;	//Road-Gravity-Coefficient
+	protected PropertyReadAccess RA_slopeStart = null;	//Slope-Coefficient
+	protected PropertyReadAccess RA_slopeStep = null;	//Slope-Coefficient
+	protected PropertyReadAccess RA_slopeEnd = null;	//Slope-Coefficient
+	protected PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
+	protected PropertyReadAccess RA_MonteCarlo = null;	//Number of MonteCarlo Iterations
+	protected ListPropertyWriteAccess WA_outResults = null;	//Output Validation Results
+	protected PropertyWriteAccess WA_SumOutStep = null;	// Step Results
+	
 
-	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
-	// ********** Modellanlauf gehalten werden muessen ***********
-	private PropertyReadAccess RA_steps = null; // Number of steps
-	private PropertyReadAccess RA_MonteCarlo = null;	//Number of MonteCarlo Iterations
-	private PropertyReadAccess RA_inputGrid = null; // Input Grid
-	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
-	private PropertyReadAccess RA_areaRestr = null; //Area Restrictions
-	private PropertyReadAccess RA_spreadStart = null;	//Spread-Koeffizient
-	private PropertyReadAccess RA_spreadStep = null;	//Spread-Koeffizient
-	private PropertyReadAccess RA_spreadEnd = null;	//Spread-Koeffizient
-	private PropertyReadAccess RA_dispStart = null;		//Dispersions-Koeffizient
-	private PropertyReadAccess RA_dispStep = null;		//Dispersions-Koeffizient
-	private PropertyReadAccess RA_dispEnd = null;		//Dispersions-Koeffizient
-	private PropertyReadAccess RA_breedStart = null;		//Breed-Koeffizient
-	private PropertyReadAccess RA_breedStep = null;		//Breed-Koeffizient
-	private PropertyReadAccess RA_breedEnd = null;		//Breed-Koeffizient
-	private PropertyReadAccess RA_roadGravityStart = null;	//Road-Gravity-Koeffizient
-	private PropertyReadAccess RA_roadGravityStep = null;	//Road-Gravity-Koeffizient
-	private PropertyReadAccess RA_roadGravityEnd = null;	//Road-Gravity-Koeffizient
-	private PropertyReadAccess RA_slopeStart = null;	//Slope-Koeffizient
-	private PropertyReadAccess RA_slopeStep = null;	//Slope-Koeffizient
-	private PropertyReadAccess RA_slopeEnd = null;	//Slope-Koeffizient
-	private PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
-	private PropertyReadAccess RA_roadGrid = null;	//Road Grid
-	private PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
-	private PropertyReadAccess RA_referenceGrid = null;	//Observed Validation Grid
-	private ListPropertyWriteAccess WA_outResults = null;	//Output Validation Results
-
-	// **************** Variablen mit denen gearbeitet wird *******************
-	private WritableGrid inputGrid = null; // Input Grid
-	private WritableGrid outputGrid = null; // Output Grid
-	private int steps = 0; // Number of steps
-	private int MonteCarlo = 0;	//Number of Monte Carlo Iterations
-	private WritableGrid areaRestr = null; //Area Restrictions
-	protected double spreadStart = 0;	//Spread-Koeffizient
-	protected double spreadStep = 0;	//Spread-Koeffizient
-	protected double spreadEnd = 0;	//Spread-Koeffizient
-	protected double dispStart = 0;	//Dispersions-Koeffizient
-	protected double dispStep = 0;	//Dispersions-Koeffizient
-	protected double dispEnd = 0;	//Dispersions-Koeffizient
-	protected double breedStart = 0;	//Breed-Koeffizient
-	protected double breedStep = 0;	//Breed-Koeffizient
-	protected double breedEnd = 0;	//Breed-Koeffizient
-	protected double roadGravityStart = 0;	//Road-Gravity-Koeffizient
-	protected double roadGravityStep = 0;	//Road-Gravity-Koeffizient
-	protected double roadGravityEnd = 0;	//Road-Gravity-Koeffizient
-	protected double slopeStart = 0;	//Slope-Koeffizient
-	protected double slopeStep = 0;	//Slope-Koeffizient
-	protected double slopeEnd = 0;	//Slope-Koeffizient
+	// **************** Variablen to work with *******************
+	protected WritableGrid referenceMap = null;	//Observed Validation Grid 
+	protected double spreadStart = 0;	//Spread-Coefficient
+	protected double spreadStep = 0;	//Spread-Coefficient
+	protected double spreadEnd = 0;	//Spread-Coefficient
+	protected double dispStart = 0;	//Dispersion-Coefficient
+	protected double dispStep = 0;	//Dispersion-Coefficient
+	protected double dispEnd = 0;	//Dispersion-Coefficient
+	protected double breedStart = 0;	//Breed-Coefficient
+	protected double breedStep = 0;	//Breed-Coefficient
+	protected double breedEnd = 0;	//Breed-Coefficient
+	protected double roadGravityStart = 0;	//Road-Gravity-Coefficient
+	protected double roadGravityStep = 0;	//Road-Gravity-Coefficient
+	protected double roadGravityEnd = 0;	//Road-Gravity-Coefficient
+	protected double slopeStart = 0;	//Slope-Coefficient
+	protected double slopeStep = 0;	//Slope-Coefficient
+	protected double slopeEnd = 0;	//Slope-Coefficient
 	protected double criticalSlope = 0;	//Critical Slope Value
-	private WritableGrid roadGrid = null;	//Road Grid
-	private WritableGrid slopeGrid = null;	//Slope Grid
-	private WritableGrid referenceGrid = null;	//Observed Validation Grid 
-	private ListPropertyWriteAccess outResults = null;	//Output Validation Results
+	protected int MonteCarlo = 0;	//Number of Monte Carlo Iterations
+	protected ListPropertyWriteAccess outResults = null;	//Output Validation Results
+	protected MultiGrid SumOutStep = null;	//Step Results
 		
-	private  static final int[][] NEIGHBOR = new int[][] {
-	      {-1,-1}, {0,-1}, {1,-1},
-	      {-1, 0},         {1, 0},
-	      {-1, 1}, {0, 1}, {1, 1}
-	  };
+	protected int years = 0;
+	protected int neighborhoodRange = 0;
+	protected int numSteps = 0;
+	protected float[] resultArray;
+	protected float[] mrvTempResultArray;
+	protected float[] finalArray;
 	
-	protected  HashMap<Number,Number> slopeLUT;
+	/**
+	 * First Constructor
+	 * @param contManager
+	 */
+	public UrbanGrowthModelCalibration(UrbanGrowthModelCalibrationContentManager contManager) {
+		super(contManager);
+		this.contManager = (UrbanGrowthModelCalibrationContentManager) super.contManager;
+	}
 	
 	/**
-	 * Erzeugt eine neue Instanz des Modells.
+	 * Second Constructor. The Content Manager is the parent content manager as well as the child content manager
 	 */
-	public UrbanGrowthModelCalibration() {
+	public UrbanGrowthModelCalibration(){
 		super(new UrbanGrowthModelCalibrationContentManager());
-		this.contManager = (UrbanGrowthModelCalibrationContentManager) super.contManager;
 	}
-
 	
 	/**
 	 * Initializes the model. Like in the init method of every {@link XuluModel}
 	 * the resources are initalized. 
 	 */
 	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())
 					.getReadAccess(this);
-		RA_MonteCarlo = null;
-		if (contManager.getResource(1).getData() != null)
-			RA_MonteCarlo = ((ScalarProperty) contManager.getResource(1).getData())
-					.getReadAccess(this);
 		RA_inputGrid = null;
-		if (contManager.getResource(2).getData() != null)
-			RA_inputGrid = ((ScalarProperty) contManager.getResource(2)
+		if (contManager.getResource(1).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(1)
 					.getData()).getReadAccess(this);
 		WA_outputGrid = null;
-		if (contManager.getResource(3).getData() != null)
-			WA_outputGrid = ((ScalarProperty) contManager.getResource(3)
+		if (contManager.getResource(2).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(2)
 					.getData()).getWriteAccess(this);
 		RA_areaRestr = null;
-		if (contManager.getResource(4).getData() != null)
-			RA_areaRestr = ((ScalarProperty) contManager.getResource(4)
+		if (contManager.getResource(3).getData() != null)
+			RA_areaRestr = ((ScalarProperty) contManager.getResource(3)
 					.getData()).getReadAccess(this);
 		RA_roadGrid = null;
-		if (contManager.getResource(5).getData() != null)
-			RA_roadGrid = ((ScalarProperty) contManager.getResource(5)
+		if (contManager.getResource(4).getData() != null)
+			RA_roadGrid = ((ScalarProperty) contManager.getResource(4)
 					.getData()).getReadAccess(this);
 		RA_slopeGrid = null;
-		if (contManager.getResource(6).getData() != null)
-			RA_slopeGrid = ((ScalarProperty) contManager.getResource(6)
+		if (contManager.getResource(5).getData() != null)
+			RA_slopeGrid = ((ScalarProperty) contManager.getResource(5)
 					.getData()).getReadAccess(this);
-		RA_referenceGrid = null;
-		if(contManager.getResource(7).getData() != null)
-			RA_referenceGrid = ((ScalarProperty) contManager.getResource(7)
+		RA_referenceMap = null;
+		if(contManager.getResource(6).getData() != null)
+			RA_referenceMap = ((ScalarProperty) contManager.getResource(6)
 					.getData()).getReadAccess(this);
 		RA_spreadStart = null;
-		if (contManager.getResource(8).getData() != null)
-			RA_spreadStart = ((ScalarProperty) contManager.getResource(8).getData())
+		if (contManager.getResource(7).getData() != null)
+			RA_spreadStart = ((ScalarProperty) contManager.getResource(7).getData())
 					.getReadAccess(this);
 		RA_spreadStep = null;
-		if (contManager.getResource(9).getData() != null)
-			RA_spreadStep = ((ScalarProperty) contManager.getResource(9).getData())
+		if (contManager.getResource(8).getData() != null)
+			RA_spreadStep = ((ScalarProperty) contManager.getResource(8).getData())
 					.getReadAccess(this);
 		RA_spreadEnd = null;
-		if (contManager.getResource(10).getData() != null)
-			RA_spreadEnd = ((ScalarProperty) contManager.getResource(10).getData())
+		if (contManager.getResource(9).getData() != null)
+			RA_spreadEnd = ((ScalarProperty) contManager.getResource(9).getData())
 					.getReadAccess(this);
 		RA_dispStart = null;
-		if (contManager.getResource(11).getData() != null)
-			RA_dispStart = ((ScalarProperty) contManager.getResource(11).getData())
+		if (contManager.getResource(10).getData() != null)
+			RA_dispStart = ((ScalarProperty) contManager.getResource(10).getData())
 					.getReadAccess(this);
 		RA_dispStep = null;
-		if (contManager.getResource(12).getData() != null)
-			RA_dispStep = ((ScalarProperty) contManager.getResource(12).getData())
+		if (contManager.getResource(11).getData() != null)
+			RA_dispStep = ((ScalarProperty) contManager.getResource(11).getData())
 					.getReadAccess(this);
 		RA_dispEnd = null;
-		if (contManager.getResource(13).getData() != null)
-			RA_dispEnd = ((ScalarProperty) contManager.getResource(13).getData())
+		if (contManager.getResource(12).getData() != null)
+			RA_dispEnd = ((ScalarProperty) contManager.getResource(12).getData())
 					.getReadAccess(this);
 		RA_breedStart = null;
-		if (contManager.getResource(14).getData() != null)
-			RA_breedStart = ((ScalarProperty) contManager.getResource(14).getData())
+		if (contManager.getResource(13).getData() != null)
+			RA_breedStart = ((ScalarProperty) contManager.getResource(13).getData())
 					.getReadAccess(this);
 		RA_breedStep = null;
-		if (contManager.getResource(15).getData() != null)
-			RA_breedStep = ((ScalarProperty) contManager.getResource(15).getData())
+		if (contManager.getResource(14).getData() != null)
+			RA_breedStep = ((ScalarProperty) contManager.getResource(14).getData())
 					.getReadAccess(this);
 		RA_breedEnd = null;
-		if (contManager.getResource(16).getData() != null)
-			RA_breedEnd = ((ScalarProperty) contManager.getResource(16).getData())
+		if (contManager.getResource(15).getData() != null)
+			RA_breedEnd = ((ScalarProperty) contManager.getResource(15).getData())
 					.getReadAccess(this);
 		RA_roadGravityStart = null;
-		if (contManager.getResource(17).getData() != null)
-			RA_roadGravityStart = ((ScalarProperty) contManager.getResource(17).getData())
+		if (contManager.getResource(16).getData() != null)
+			RA_roadGravityStart = ((ScalarProperty) contManager.getResource(16).getData())
 					.getReadAccess(this);
 		RA_roadGravityStep = null;
-		if (contManager.getResource(18).getData() != null)
-			RA_roadGravityStep = ((ScalarProperty) contManager.getResource(18).getData())
+		if (contManager.getResource(17).getData() != null)
+			RA_roadGravityStep = ((ScalarProperty) contManager.getResource(17).getData())
 					.getReadAccess(this);
 		RA_roadGravityEnd = null;
-		if (contManager.getResource(19).getData() != null)
-			RA_roadGravityEnd = ((ScalarProperty) contManager.getResource(19).getData())
+		if (contManager.getResource(18).getData() != null)
+			RA_roadGravityEnd = ((ScalarProperty) contManager.getResource(18).getData())
 					.getReadAccess(this);
 		RA_slopeStart = null;
-		if (contManager.getResource(20).getData() != null)
-			RA_slopeStart = ((ScalarProperty) contManager.getResource(20).getData())
+		if (contManager.getResource(19).getData() != null)
+			RA_slopeStart = ((ScalarProperty) contManager.getResource(19).getData())
 					.getReadAccess(this);
 		RA_slopeStep = null;
-		if (contManager.getResource(21).getData() != null)
-			RA_slopeStep = ((ScalarProperty) contManager.getResource(21).getData())
+		if (contManager.getResource(20).getData() != null)
+			RA_slopeStep = ((ScalarProperty) contManager.getResource(20).getData())
 					.getReadAccess(this);
 		RA_slopeEnd = null;
-		if (contManager.getResource(22).getData() != null)
-			RA_slopeEnd = ((ScalarProperty) contManager.getResource(22).getData())
+		if (contManager.getResource(21).getData() != null)
+			RA_slopeEnd = ((ScalarProperty) contManager.getResource(21).getData())
 					.getReadAccess(this);
 		RA_criticalSlope = null;
+		if (contManager.getResource(22).getData() != null)
+			RA_criticalSlope = ((ScalarProperty) contManager.getResource(22).getData())
+					.getReadAccess(this);
+		RA_MonteCarlo = null;
 		if (contManager.getResource(23).getData() != null)
-			RA_criticalSlope = ((ScalarProperty) contManager.getResource(23).getData())
+			RA_MonteCarlo = ((ScalarProperty) contManager.getResource(23).getData())
 					.getReadAccess(this);
 		WA_outResults = null;
 		if (contManager.getResource(24).getData() != null)
 			WA_outResults = ((ListProperty) contManager.getResource(24)
 					.getData()).getWriteAccess(this);
 		
-		// Variablen belegen mit denen gearbeitet wird
-		steps = RA_steps.getValueAsInt();
-		MonteCarlo = RA_MonteCarlo.getValueAsInt();
+		
+		// Assign variables to work with
 		inputGrid = (WritableGrid) RA_inputGrid.getValue();
 		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		steps = RA_steps;
 		areaRestr = (WritableGrid) RA_areaRestr.getValue();
-		
-		//this.stepCount = steps.getValueAsInt();
-		stepCount 		= 1;
+		roadGrid = (WritableGrid) RA_roadGrid.getValue();
+	    slopeGrid = (WritableGrid) RA_slopeGrid.getValue();
+		referenceMap 	= (WritableGrid) RA_referenceMap.getValue();	
 	    spreadStart  	= RA_spreadStart.getValueAsDouble();
 	    spreadStep  	= RA_spreadStep.getValueAsDouble();
 	    spreadEnd  		= RA_spreadEnd.getValueAsDouble();
@@ -236,40 +255,35 @@
 	    slopeStart		= RA_slopeStart.getValueAsDouble();
 	    slopeStep		= RA_slopeStep.getValueAsDouble();
 	    slopeEnd		= RA_slopeEnd.getValueAsDouble();
-	    criticalSlope 	= RA_criticalSlope.getValueAsDouble();	
-	    roadGrid 		= (WritableGrid) RA_roadGrid.getValue();
-	    slopeGrid 		= (WritableGrid) RA_slopeGrid.getValue();
-	    referenceGrid 	= (WritableGrid) RA_referenceGrid.getValue();
+	    criticalSlope = RA_criticalSlope.getValueAsDouble();
+	    MonteCarlo 		= RA_MonteCarlo.getValueAsInt();
 		outResults 		= WA_outResults;
+		outStep 		= (MultiGrid)contManager.getResource(25).getData();
+		SumOutStep		= (MultiGrid)contManager.getResource(26).getData();
+		stepCount 		= 1;
+		years 			= steps.getValueAsInt();
 
-		int startAnz = 0;
-		for (int i = 0; i < inputGrid.getWidth();i++ ) {
-			for (int ii = 0; ii < inputGrid.getHeight(); ii++ ) {
-				//if (inputGrid.getRasterSampleAsFloat(i,ii) == 1f);
-				float val = inputGrid.getRasterSampleAsFloat(i,ii);
-				if (val == 1.0 ) {
-					val = 1f;
-					startAnz++;
-				}
-					else val = 0f;
-				
-				inputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
-				outputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
-			}
-		}
+		//count the number of starting individuals
+	    int startAnz = 0;
+		startAnz = countSetIndividuals();
+		
+		statusOut.println("Number of starting cells: "+startAnz);
+		statusOut.println("Neighborhood size: "+NEIGHBOR.length);
+		
+		neighborhoodRange = (int) Math.sqrt(inputGrid.getWidth()*inputGrid.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);
+		
 	}
 
 	/**
 	* like in every model: frees the resources
 	 */
 	public void performModelDispose() {
-
-		// Ressourcen wieder freigeben
-		releaseAccess(RA_steps);
-		releaseAccess(RA_MonteCarlo);
-		releaseAccess(RA_inputGrid);
-		releaseAccess(WA_outputGrid);
-		releaseAccess(RA_areaRestr);
+		super.performModelDispose();
+		
+		releaseAccess(RA_referenceMap);
 		releaseAccess(RA_spreadStart);
 		releaseAccess(RA_spreadStep);
 		releaseAccess(RA_spreadEnd);
@@ -285,883 +299,393 @@
 		releaseAccess(RA_slopeStart);
 		releaseAccess(RA_slopeStep);
 		releaseAccess(RA_slopeEnd);
-		releaseAccess(RA_criticalSlope);
-		releaseAccess(RA_roadGrid);
-		releaseAccess(RA_slopeGrid);
+		releaseAccess(RA_MonteCarlo);
 		releaseAccess(WA_outResults);
+		releaseAccess(WA_SumOutStep);
 	}
 
-	
+	/**
+	 * The main method of the Urban Growth Model. For a detailed description refer to the performModelStep in 
+	 * {@link UrbanGrowthModel UrbanGrowthModel}. The difference is, that the number of steps is not based on
+	 * the years that have to be modelled. The number of steps is always 1, all parameter combinations, Monte Carlo
+	 * Iterations, and time steps are performed within this method. Those combinations are included in different
+	 * for-loops. 
+	 */
 	public void performModelStep(int stepNo) {
 		
-		/**
-		 * Ermitteln der maximalen Hangneigung
-		 */
-		int slopeMax = 0;
-		for (int s = 0; s < inputGrid.getWidth();s++){
-			for(int ss = 0; ss < inputGrid.getHeight();ss++){
-				float slopeVal = slopeGrid.getRasterSampleAsFloat(s,ss);
-				if (slopeVal > slopeMax){
-					slopeMax = (int) slopeVal;		//Maximale Hangneigung im Slope-Bild
-				} 
-			}
-		}
+		//Definition of variables needed in the whole model run
+		long localStartTime = System.currentTimeMillis(); //time measure
+		Float actUrb = null;	//urban cell in the raster
+		int totalSteps = 0;
+		int runs = 0;		
+	
+		//raster dimensions
+		areaMinX = inputGrid.getMinX();
+		areaMinY = inputGrid.getMinY();
+		areaMaxX = inputGrid.getMinX() + inputGrid.getWidth() - 1;
+		areaMaxY = inputGrid.getMinY() + inputGrid.getHeight() - 1;
+		areaWidth = inputGrid.getWidth();
+		areaHeight = inputGrid.getHeight();
+			
+		// Iterate the calibration for:
+		// 1. every slope value between start and end...
+		// 2. every spread value between start und end...
+		// 3. every dispersion value between start und end...
+		// 4. every breed value between start and end...
 		
-		/**
-		 * Definition von Variablen, die als Output des gesamten Kalibrierungsdurchlaufs benötigt werden
-		 */
-		float MCtotalAgreementResult = 0f;
-		int ngrids = 0;
-		int slopeOut = 0;
-		int spreadOut = 0;
-		int dispOut = 0;
-		int breedOut = 0;
-		int roadGravityOut = 0;
-		
-		/**
-		 * Start des gesamten Kalibrierungsdurchlaufs:
-		 * 1. Für jeden Slope-Wert zwischen Start und End...
-		 * 2. Für jeden Spread-Wert zwischen Start und End...
-		 * 3. Für jeden Dispersion-Wert zwischen Start und End...
-		 * 4. Für jeden Breed-Wert zwischen Start und End...
-		 */
-		
 		for(int slope = (int)slopeStart;slope <= (int)slopeEnd; slope = slope+(int)slopeStep){
 			
-			//Variablendefinitionen bzgl. Slope-Berechnungen
-			slopeOut = slope;							//slopeOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von slope
-			slopeLUT = new HashMap<Number,Number>();	//Definition eines Lookup-Tables (HashMap --> jeder Indexwert bekommt einen Wert zugewiesen)
-			int MaxSlopeResistance = 100;				//Hangneigung kann maximal 100% betragen	
-			double exp = 0.0;							
-			exp = (slope / (MaxSlopeResistance / 2));
-			double[] lookup = new double[slopeMax+1];	//ein Array, das slopeMax+1 Stellen lang ist (+1, da Arrays mit der Zahl 0 beginnen)
-			Number key = 0;								//die Zahl key nimmt den Wert des Index für den Lookup-Table an
-		
-			//Aufbau des Lookup-Tables
-			for (int i = 0;i <= slopeMax;i++){							//Für jede Hangneigung zwischen 0% und dem maximal im Bild vorhandenen Wert
-				if (i <= criticalSlope){								//der kleiner als criticalSlope ist
-					double val = (criticalSlope - i) / criticalSlope;	//berechne den Wert val
-					lookup[i] = 1 - Math.pow(val,exp);					//und füge den Wert val hoch exp an der Stelle i in das Array lookup ein
-					key = i;											//Index-Wert ist key
-				} else{													//Ist der Wert größer als criticalSlope
-					lookup[i] = 1;										//wird der Wert 1 in das Array eingefügt
-					key = i;										
-				}
-				slopeLUT.put(key,lookup[i]);							//put platziert die Werte key und den entsprechenden Wert aus dem Array lookup in die HashMap-Tabelle
-//				statusOut.println(slopeLUT.get(key));
-			}	
-		
+			//calculate the maximum slope
+			int slopeMax = 0;
+			slopeMax = getSlopeMax();
+			
+			statusOut.println("Max. Slope: "+slopeMax+" %");
+					
+			//assigns for every slope value between 0 and the maximum slope that is below the critical slope the value calculated for the variable "lookup".
+			//all values higher than the critical slope become 1
 
+			int MaxSlopeResistance = 100;	//Max slope resistance is 100%
+			double exp = getSlopeExp(slope,MaxSlopeResistance);	//calculate the exp value based on the actual slope
+			slopeLUT = getSlopeLookup(slopeMax,exp,criticalSlope);	//generate the lookup-table based on the actual exp-value
+			
 			for(int spread = (int)spreadStart; spread <= (int)spreadEnd; spread = spread+(int)spreadStep){
-				spreadOut = spread;		//spreadOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von spread
 				for(int disp = (int)dispStart; disp <= (int)dispEnd; disp = disp+(int)dispStep){
-					dispOut = disp;		//dispOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von disp
 					for(int breed = (int)breedStart; breed <= (int)breedEnd+1; breed = breed+(int)breedStep){
-						breedOut = breed;	//breedOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von breed
-						for(int roadGravity = (int)roadGravityStart; roadGravity <=(int)roadGravityEnd; roadGravity = roadGravity+(int)roadGravityStep){
-							roadGravityOut = roadGravity;	//roadGravityOut wird als Ausgabewert benötigt und erhält am Anfang der Schleife den Wert von roadGravity
+						for(int roadGravity = (int)roadGravityStart; roadGravity <=(int)roadGravityEnd; roadGravity = roadGravity+(int)roadGravityStep){	
+									
+							//Here the original model algorithm starts. By calibrating the model each parameter combination
+							//is being iterated, so the algorithm is performed n-times. Because a lot of random values are
+							// in the model, each step should be performed a Monte Carlo number of times. The results are 
+							// averaged at the end of the algorithm. 
+							//
+							runs++;
+							mrvTempResultArray = new float[numSteps+2];
+							finalArray = new float[numSteps+2];
+														
+							//coefficient calculations of for growth rules
+							max_RG_value = 100.0;			//Maximum possible road gravity value
+							double disp_value = Math.round((disp*0.005)* Math.sqrt(Math.pow(inputGrid.getWidth(), 2)+(Math.pow(inputGrid.getHeight(), 2))));
+							double rg_value = Math.round((roadGravity/max_RG_value)*((areaWidth + areaHeight)/16));
+							statusOut.println("RG"+roadGravity+" / MaxRG:"+max_RG_value+" * (Width"+areaWidth+" + areaHeight"+areaHeight+") / 16");
 							
-							/**
-							 * An dieser Stelle beginnt der eigentliche Modellalgorithmus des UrbanGrowth-Modells.
-							 * Da bei der Kalibrierung das Modell durch jede mögliche Kombination an Werten durchiteriert,
-							 * wird der Algorithmus x-mal durchlaufen.
-							 * Da häufig Zufallswerte in das Modell eingebaut sind, ist es sinnvoll jeden Iterationsschritt mehrfach durchzuführen
-							 * und die Ergebnisse zu mitteln. Dies geschieht "Monte-Carlo"-mal (Wert wird in Modellparametern angegeben).
-							 * Das bedeutet, dass der Modellalgorithmus zusätzlich in die folgende for-Schleife eingebunden ist.
-							 */
-							float pos1 = 0;	//das hier ist nicht optimal gelöst. Für jede Stelle im Result Array eine eigene Variable definiert, die später ausgelesen wird. Habs nur auf die Schnelle nicht besser hinbekommen
-							float pos2 = 0;
-							float pos3 = 0;
-							float pos4 = 0;
-							float pos5 = 0;
-							float pos6 = 0;
-							float pos7 = 0;
-							float pos8 = 0;
-							float pos9 = 0;
-							float pos10 = 0;
-							float pos11 = 0;
-							float pos12 = 0;
-							for(int MC = 1; MC <= MonteCarlo; MC++){	//führe den Modellalgorithmus 1 bis MC-mal durch
-								RasterUtil.copyInto(inputGrid, outputGrid);		//starte dabei aber mit dem Eingabebild (das Ausgabebild verändert sich nach jedem Modellschritt!!)
-//								statusOut.println("Starting step " + stepNo + "...");
-//								statusOut.println(steps);
-								
+							max_search_index = Math.round(4*((int)rg_value*(1+(int)rg_value)));	//area in which to look for a road cell
+							statusOut.println("MaxSearchIndex: "+max_search_index);
+														
+							for(int MC = 1; MC <= MonteCarlo; MC++){	//perform the model algoith 1-MC times
+								statusOut.println("Performing "+MonteCarlo+" Monte Carlo Iterations (years: "+stepNo);
+								totalSteps++;
 								/**
-								 * Der Modelllauf muss so oft wiederholt werden, wie Jahre für den Kalibrierungsmodus angegeben wurden.
-								 * Für die anschließende Bewertung der Ergebnisse zählt nur das Bild des Schlussjahres
+								 * The model run is being performed for every time step. For the final evaluation 
+								 * only the image of the final step is needed.
 								 */
-									for(int timeSteps = 1;timeSteps <=steps;timeSteps++){	
-										//Dimensionen des Rasters werden definiert
-										int areaMinX = outputGrid.getMinX();								
-										int areaMinY = outputGrid.getMinY();
-										int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
-										int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
-										int areaWidth = outputGrid.getWidth();
-										int areaHeight = outputGrid.getHeight();
-										
-										//weitere Variablendefinitionen
-										long localStartTime = System.currentTimeMillis();
-										boolean anyBodyAlive = false;
-		
-										boolean[][] tmpGrid = new boolean[outputGrid.getWidth()][outputGrid.getHeight()];	//temporäres Raster, in das true und false geschrieben wird, je nachdem ob Siedlung nach Modellschritt vorhanden ist oder nicht
-										Float actUrb = null;
-		
-										int nbX = 0; // X-Koordinate einer Nachbarzelle
-										int nbY = 0; // Y-Koordinate einer Nachbarzelle
-										int[] nbCell = null;
-	    
-										int anzSpreadTreffer = 0;
-										int anzDispTreffer = 0;
-										int anzBreedTreffer = 0;
-		
-										// Variablen, die für den DISPERSION Bereich benötigt werden
-										double disp_value = Math.round((disp*0.005)* Math.sqrt(Math.pow(outputGrid.getWidth(), 2)+(Math.pow(outputGrid.getHeight(), 2))));
-										int dispRandX = 0;
-										int dispRandY = 0;
-										float slopeRandDisp = 0;
-		
-										// Variablen, die für den ROAD GRAVITY Bereich benötigt werden
-										double max_RG_value = 100.0;
-										double rg_value = Math.round((roadGravity/max_RG_value)*((areaWidth + areaHeight)/16)); 
-										double max_search_index = Math.round(4*((int)rg_value*(1+(int)rg_value)));
-//										statusOut.println("RG-Value:"+rg_value);
-//										statusOut.println("Max-SearchIndex"+max_search_index);
-		
+								for(int timeSteps = 1;timeSteps <=years;timeSteps++){	
+									statusOut.println("Year "+timeSteps);
+									boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+									
+									/*****************************************************************
+									 * DISPERSION and BREED (Growth Phase 1 and 2)
+									 *****************************************************************/
+									boolean[][] tmpGridDisp = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+									tmpGridDisp = DispersionGrowth(disp_value,breed);	//calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
+									int anzDispBreed = 0;	//number of cells urbanized by Dispersion and Breed
+									for (int x = 0; x < inputGrid.getWidth();x++)
+										for(int y = 0; y < inputGrid.getHeight();y++){
+											int X = inputGrid.getMinX() + x;
+											int Y = inputGrid.getMinY() + y;
+											if (tmpGridDisp[X][Y]==true){
+												anzDispBreed++;
+												tmpGrid[X][Y] = true;	//write the temporary Dispersion and Breed Cells to the overall temporary Cell array
+											}		
+										}
+									statusOut.println("Number of Spontaneous and New Spreading Center Cells: "+anzDispBreed);
+									writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
+									
+									/*********************************************************************
+									 * EDGE
+									 *********************************************************************/
+									boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+									tmpGridSpread = EdgeGrowth(spread);	//calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
+									int anzSpread = 0;	//number of cells urbanized by Spread
+									for (int x = 0; x < inputGrid.getWidth();x++)
+										for(int y = 0; y < inputGrid.getHeight();y++){
+											int X = inputGrid.getMinX() + x;
+											int Y = inputGrid.getMinY() + y;
+											if (tmpGridSpread[X][Y]==true){
+												anzSpread++;
+												tmpGrid[X][Y] = true;	//write the temporary Spread cells to the overall temporary Cell array
+											}		
+										}
+									statusOut.println("Number of Edge Growth Cells: "+anzSpread);
+									writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
+								
+									/*********************************************************************
+									 * ROAD
+									 *********************************************************************/
+									boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+									statusOut.println("Start Road Growth...");
+									tmpGridRoad = RoadGrowth(tmpGrid,rg_value,breed,disp);	//calls the method "RoadGrowth" to perform the Road weighted growth
+									statusOut.println("Road things returned...");
+									int anzRoad = 0;	//number of cells urbanized by Road Growth
+									for (int x = 0; x < inputGrid.getWidth();x++)
+										for(int y = 0; y < inputGrid.getHeight();y++){
+											int X = inputGrid.getMinX() + x;
+											int Y = inputGrid.getMinY() + y;
+											if (tmpGridRoad[X][Y]==true){
+												anzRoad++;
+												tmpGrid[X][Y] = true;	//write the temporary Road Growth cells to the overall temporary Cell array
+											}		
+										}
+									statusOut.println("Number of Road Growth Cells: "+anzRoad);
+									writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
 
-										/*****************************************************************
-										 * DISPERSION and BREED
-										 *****************************************************************/
+									// Here the main modeling algorithm ends. Next the temporary raster is written in the output raster. 
+									//With the outputGrid the next time step is calculated until the maximum number of time steps
+									//is reached. After that the next Monte Carlo iteration is performed for the specific parameter combination. 									
+									
+									// Write the temporary Grid to the Output Grid
+									int anzGesamt = 0;
+									for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+										for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
+											
+											int X = inputGrid.getMinX() + x;
+											int Y = inputGrid.getMinY() + y;
 										
-										//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
-										//-->Beginn einer do-while-Schleife
-										int p = 0;	
-										do{
-											dispRandX = Math.round((float) Math.random()*areaWidth);											//Zufallsposition in X-Richtung
-											dispRandY = Math.round((float) Math.random()*areaHeight);											//Zufallsposition in Y-Richtung
-											if ( dispRandX < areaMinX || dispRandY < areaMinY || dispRandX > areaMaxX || dispRandY > areaMaxY ||
-													Float.isNaN(outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY)) ) 						//wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-												continue;
-											if (areaRestr.getRasterSampleAsFloat(dispRandX,dispRandY) != 0 || outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY) == 1)
-												continue;																						//wenn in Area Restriction oder wenn schon Siedlung da ist, mach weiter
-											slopeRandDisp = (float) Math.random();																//Zufallszahl zum Abgleich mit Slope-Koeffizient
-											int getSlope = (int) slopeGrid.getRasterSampleAsFloat(dispRandX,dispRandY);							//holt sich den Slope-Wert aus dem Slope-Raster
-											Double doubleObj = (Double)slopeLUT.get(getSlope);													//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-											double slopeDouble = doubleObj.doubleValue();														//konvertiert Double-Objekt in double-Wert
-	//	      								statusOut.println(getSlope+","+slopeDouble+"----Random: "+slopeRandDisp);
-											if(slopeDouble < slopeRandDisp){			//wenn der Slope-Wert kleiner als der Wert der Zufallszahl ist
-												tmpGrid[dispRandX][dispRandY] = true;	//wird "true" ins temporäre Raster geschrieben (neue Siedlung entsteht!!)
-												anzDispTreffer++;						//Anzahl der Disp-Treffer wird hochgezählt
-												
-												//
-												//hier beginnt der BREED Bereich
-												//
-												//Variablendefinitionen
-												float breedRnd = (float) Math.random()*100;
-												int nbBreedX  = 0;
-												int nbBreedY  = 0;
-												int breedNb	  = 0;
-												float NbValue = 0f;
-												if (tmpGrid[dispRandX][dispRandY] == true && breedRnd < breed)	//wenn durch DISPERSION neue Zellen entstanden sind UND der Breed-Zufallswert kleiner als der Breed-Wert ist
-													breedNb = calculateNeighbors(dispRandX,dispRandY,NbValue);	//werden die Nachbarzellen dieser neuen Zellen gezählt, und zwar alle, die zur weiteren Besiedlung zur Verfügung stehen (--> Funktion calculateNeighbors)
-		        			       
-												int RNBreed1 = 0;
-												int RNBreed2 = 0;
-												float RNBreedSlope = 0f;
-		        
-												if (breedNb >= 2 && tmpGrid[dispRandX][dispRandY] == true){		//sind mehr als 2 Nachbarzellen verfügbar und die Koordinate X/Y true...
-													int anzBreedTemp = 0;
-													int[] nbPossibleBreedUrban = null;
-													RNBreed1 = 1 + Math.round((float)Math.random()*(breedNb-1));	//werden 2 Zufallszahlen zwischen 1 und breedNb erzeugt
-													RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));
-													if (RNBreed2 == RNBreed1)										//falls beide Zufallszahlen den gleichen Wert haben sollten, wird die zweite Zahl nochmal erzeugt
-														RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));	
-													for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){	//die Nachbarn jeder Zelle müssen nochmal durchgezählt werden, um zu bestimmen, welche per Zufallswert in Siedlung umgewandelt werden soll
-														nbBreedX = dispRandX+NEIGHBOR[cellBreed][0];
-														nbBreedY = dispRandY+NEIGHBOR[cellBreed][1];
-														if ( nbBreedX < areaMinX || nbBreedY < areaMinY || nbBreedX > areaMaxX || nbBreedY > areaMaxY ||
-																Float.isNaN(outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-															continue;
-														if (areaRestr.getRasterSampleAsFloat(nbBreedX,nbBreedY) != 0)
-															continue;
-														RNBreedSlope = (float)Math.random();	 										//Zufallszahl zum Abgleich mit Slope-Koeffizient
-														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt sich den Slope-Wert aus dem Slope-Raster
-														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);							//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-														double slopeDoubleNb = doubleObjNb.doubleValue();								//konvertiert Double-Objekt in double-Wert
-														float breedSample = outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt den Wert aus dem Output-Raster
-														if (breedSample == 0f){													//ist der Wert aus dem Output-Raster 0
-															anzBreedTemp++;														//wird die Zahl der zur Verfügung stehenden Zellen hochgezählt
-															nbPossibleBreedUrban = new int[] {nbBreedX,nbBreedY,anzBreedTemp};	//und die Nummer und Koordinaten der jeweiligen Zellen in ein Array geschrieben 
-															if (nbPossibleBreedUrban[2] == RNBreed1 || nbPossibleBreedUrban[2] == RNBreed2 && slopeDoubleNb < RNBreedSlope){	//entspricht die Nummer einer der zuvor erstellten Zufallswerte...
-																tmpGrid[nbBreedX][nbBreedY] = true;								//wird in das temporäre Raster "true" geschrieben (--> neue Siedlung durch BREED entstanden!!)
-																anzBreedTreffer++;												//die Anzahl der BREED-Treffer wird gezählt
-															}	
-														}
-													}
-												} 
-											} p++;		//der Wert p wird hochgezählt, bis der Disp-Wert erreicht ist
-		       
-										} while (p < disp_value);	//while, statt for-Schleife, da Überprüfung erst am Ende vorgenommen werden kann
-																	//am Anfang der Schleife ist noch nicht klar, ob alle Pixel verteilt werden können
-																	//da ein Teil in Ausschlussflächen etc. landen würde
-										//ENDE DISPERSION UND BREED WACHSTUM
-	
-										/*********************************************************************
-										 * EDGE
-										 *********************************************************************/
-		
-										//iterate over all cells
-										for (int x = 0; x < outputGrid.getWidth(); x++)
-											for (int y = 0; y < outputGrid.getHeight(); y++) {		//für jede Zelle in x/y-Richtung
-												
-												//Dimensionen des Rasters
-												int areaMinXadd = areaMinX + x;								
-												int areaMinYadd = areaMinY + y;
-												
-												//Variablendefinitionen
-												int anzNachbarn = 0;
-												int noNachbarn = 0;
-				
-												for (int nbCellIdx = 0; nbCellIdx < NEIGHBOR.length; nbCellIdx++) {	//zählt alle Nachbarn jeder Rasterzelle durch
-													checkBreakingCommands();
-													nbX = x+NEIGHBOR[nbCellIdx][0];		//Nachbarschaft der Zellen
-													nbY = y+NEIGHBOR[nbCellIdx][1];
-													nbCell = new int[] {nbX,nbY};		//jede Nachbarzelle
-													if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
-															Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-														continue;
-													if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
-														continue;
-													float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
-													if (rasterSample > 0f)		//ist Nachbarzelle urban (1), wird sie als anzNachbarn gezählt
-														anzNachbarn++;
-													if (rasterSample == 0f)		//ist sie nicht urban (0), wird sie als noNachbarn gezählt		
-														noNachbarn++;
-												}
-				
-												boolean lebt = outputGrid.getRasterSampleAsFloat(areaMinXadd , areaMinYadd ) > 0f;	//eine Zelle lebt, wenn sie 1 ist
-				
-												//hier ist die Abfrage wieviele Nachbarzellen am Leben sind
-												//daraus ergibt sich, ob im tmpGrid die entsprechende Zelle
-												//true oder false ist
-				
-												float SpR = (float) Math.random()*100;						//eine Zufallszahl zwischen 0 und 1
-												int RN = 0; 	//hier wird eine Integer-Zufallszahl reingeschrieben
-				
-												if (lebt && (anzNachbarn>=2) && (SpR < spread) && (noNachbarn >=1)) {	//wenn eine Zelle lebt, mindestens 2 lebende Nachbarzellen hat, der Spread-Koeffizient größer als die für die Zelle berechnete Zufallszahl und mindestens einen nicht lebenden Nachbarn hat
-													
-													//Variablendefinitionen
-													int anzTemp = 0;
-													int[] nbPossibleUrban = null;
-													RN = 1 + Math.round((float)Math.random()*(noNachbarn-1));
-													float RNEdgeSlope = 0;
-													int nbUrbanX = 0;
-													int nbUrbanY = 0;
-													
-													for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){	//dann starte eine Schleife
-														checkBreakingCommands();
-														nbX = x+NEIGHBOR[nbCellChange][0];
-														nbY = y+NEIGHBOR[nbCellChange][1];
-														if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
-																Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-															continue;
-														if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
-															continue;
-														RNEdgeSlope = (float)Math.random();									//Zufallszahl zum Abgleich mit Slope-Koeffizient
-														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbX,nbY);	//holt sich den Slope-Wert aus dem Slope-Raster
-														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);				//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-														double slopeDoubleNb = doubleObjNb.doubleValue();					//konvertiert Double-Objekt in double-Wert
-														float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);	//holt die Werte aus den jeweiligen Nachbarzellen
-														if (rasterSample == 0f){	//wenn der Wert 0 ist
-															anzTemp++;				//wird Anzahl der möglichen Zellen erhöht
-															nbPossibleUrban = new int[] {nbX,nbY,anzTemp};	//Koordinaten und Nummern dieser Zellen werden in Array geschrieben 
-															int urbanNbTemp = 0;
-															float NbValueEdge = 1f;
-															if (nbPossibleUrban[2] == RN){	//wenn Nummer im "PossibleUrban"-Array der Zufallszahl entspricht, die zwischen 1 und Anzahl der möglichen Zellen liegt...
-																							//damit die Städte nicht zu sehr "ausfransen" steht eine Zelle nur zur Umwandlung zur Verfügung, wenn auch sie mind. 2 urbane Nachbarn hat
-																urbanNbTemp = calculateNeighbors(nbX,nbY,NbValueEdge);
-																if (urbanNbTemp >= 2 && tmpGrid[nbX][nbY]==false && slopeDoubleNb < RNEdgeSlope){
-																	tmpGrid[nbX][nbY] = true;	//wird true ins temporäre Raster geschrieben
-																	anzSpreadTreffer++;			//und die Anzahl der Spread-Treffer gezählt
-																}
-															} 
-														}
-														nbCell = new int[] {nbX,nbY,(int) rasterSample};	//die Nummer und Koordinaten der jeweiligen Zellen wird in ein Array geschrieben
-													}
-												}
-												if (anzNachbarn>0) anyBodyAlive = true;		
-											}	//ENDE EDGE-WACHSTUM
-		
-										/*********************************************************************
-										 * ROAD
-										 *********************************************************************/
+											if (tmpGrid[x][y] == true)
+												anzGesamt++;
+											
+											boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f;	//a cell is alive, when it is 1
+											if (tmpGrid[x][y] == false)	//if there is nothing in the temporary raster
+												tmpGrid[x][y] = lebt;	//take the values from the current output raster
 										
-										//Variablendefinitionen
-										int anzGesamt = 0;
-										int[] cellValue = null;
-										int RSearchRoad = 0;
-										int r = 1;	//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
-										//Rectangle gridBounds = new Rectangle(0, 0, outputGrid.getWidth(), outputGrid.getHeight()); //ein Rechteck wird definiert
-		
-										//For-Schleife zählt alle als true markierten Zellen im Temp-Raster
-										for (int x = 0; x < outputGrid.getWidth();x++)
-											for(int y = 0; y < outputGrid.getHeight();y++){
-												int X = outputGrid.getMinX() + x;
-												int Y = outputGrid.getMinY() + y;
-												if (tmpGrid[X][Y]==true){
-													anzGesamt++;
-												}		
-											}
-		
-										//Beginn einer do-while-Schleife
-										do{
-											//Variablendefinitionen
-											RSearchRoad = Math.round((float)Math.random()*anzGesamt);	//Zufallszahl zwischen 1 und Anzahl aller bisher neu hinzugekommener Pixel
-											int anzTruePixels = 0;
-											int roadNeighborhoodRange = 0;
-											int RSearchNbRoad = 0;
-												for (int x = 0; x < outputGrid.getWidth();x++){		//gesamtes Raster wird durchsucht
-													for(int y = 0; y < outputGrid.getHeight();y++){
-														int X = outputGrid.getMinX() + x;
-														int Y = outputGrid.getMinY() + y;
-														if (tmpGrid[X][Y]==true){
-															anzTruePixels++;		//wird true-Pixel gefunden, wird anzTruePixels hochgezählt
-															cellValue = new int[] {X,Y,anzTruePixels};	//und Koordinaten in Array geschrieben
-															int tempRoadCell[] = null;
-															int tempNbRoadCell[] = null;
-															if (cellValue[2] == RSearchRoad){	//eins der neu entstandenen Pixel wird nach Zufallsprinzip ausgewählt
-																//statusOut.println(cellValue[0]+","+cellValue[1]+","+cellValue[2]);
-																//statusOut.println(r+","+RSearchRoad);
-																r++;							//Anzahl der so gefundenen Zellen wird hochgezählt, bis Road-Koeffizient erreicht wird
-																//JETZT NACH STRAßE SUCHEN!!
-																float roadValue = roadGrid.getRasterSampleAsFloat(X,Y);	//An Koordinate X/Y wird Wert aus roadGrid geholt
-																//		statusOut.println(roadValue);
-																if (roadValue > 0.0){					//wenn Wert > 0 ist...
-																	tempRoadCell = new int[] {X,Y};		//wird an Koordinate X/Y eine temporäre Straßenzelle platziert (bzw. Koordinaten in Array geschrieben
-					//												statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
-																	int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],disp);	//von dieser Koordinate aus wird ein Road-Walk gestartete (siehe Funktion roadWalk!!)
-																	if(nbCellNew != null){									//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
-																		tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;			//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
-					//													statusOut.println(nbCellNew.length);
-					//													statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
-					//													statusOut.println("++++++++++++++++++++++++++++++++++++++++");
-																		
-																		//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
-																		//nochmals ein "Breed" aus.
-																		
-																		//Variablendefinitionen
-																		float nbRoadBreed = 0f;
-																		int nbRoadBreedNeighbors = 0;
-																		nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);	//Nachbarzellen der neuen Zelle werden gezählt
-																		int RNRoadBreed1 = 0;
-																		int RNRoadBreed2 = 0;
-																		int nbRoadBreedX = 0;
-																		int nbRoadBreedY = 0;
-																		int anzRoadBreedTreffer = 0;
-							        
-																		if (nbRoadBreedNeighbors >= 2){	//sind mehr als 2 potenzielle Nachbarzellen verfügbar
-																			int anzBreedTemp = 0;
-																			int[] nbPossibleBreedUrban = null;
-																			RNRoadBreed1 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																			RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																			float RNRoadBreedSlope = 0f;
-																			if (RNRoadBreed2 == RNRoadBreed1)
-																				RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));	
-																			for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){
-																				nbRoadBreedX = nbCellNew[0]+NEIGHBOR[cellBreed][0];
-																				nbRoadBreedY = nbCellNew[1]+NEIGHBOR[cellBreed][1];
-																				if ( nbRoadBreedX < areaMinX || nbRoadBreedY < areaMinY || nbRoadBreedX > areaMaxX || nbRoadBreedY > areaMaxY ||
-																						Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																					continue;
-																				if (areaRestr.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY) != 0)
-																					continue;
-																				RNRoadBreedSlope = (float)Math.random();											//Zufallszahl zum Abgleich mit Slope-Koeffizient
-																				int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt sich den Slope-Wert aus dem Slope-Raster
-																				Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);								//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-																				double slopeDoubleNb = doubleObjNb.doubleValue();									//konvertiert Double-Objekt in double-Wert
-																				float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt die Werte aus den jeweiligen Nachbarzellen
-																				if (breedSample == 0f){			//hat die Nachbarzelle den Wert 0 wird anzBreedTemp hochgezählt
-																					anzBreedTemp++;
-																					nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};		//und Koordinaten dieser Zelle in Array geschrieben
-																					if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){	//stimmt der Wert mit einer der beiden Zufallszahlen überein und ist laut Slope-Wert Besiedlung erlaubt...
-																						tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;					//..wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle erstellt!)
-																						anzRoadBreedTreffer++;										//Anzahl der durch Breed nach RoadWalk erzeugten Zellen wird hochgezählt
-						//																statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
-																					}
-																				}
-																			}
-																		}
-																	} else{		//kommt nach Road-Walk nichts zurück...
-																		//	statusOut.println("Keine neue Zelle gefunden");
-																	}
-																//ist an der Stelle, an der eine neue Zelle entstanden war keine Straße, wird im Folgenden in ihrer Nähe danach gesucht...
-																} else{	
-																	
-																	int anzRoadNb = 0;
-								
-																	//HIER MIT FOR SCHLEIFE RECHTECK WACHSEN LASSEN!!!
-																	for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){		//vergrößere die Nachbarschaft, bis rg_value erreicht ist
-																		if (anzRoadNb > 0)		//höre auf, sobald Straße in der Nachbarschaft gefunden wurde
-																			continue;
-																		for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++)
-																			for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){
-																				//if (gridBounds.contains(nbRoadCellsX, nbRoadCellsY))
-																				if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
-																						Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																					continue;
-																			//	if (areaRestr.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY) != 0)
-																			//		continue;
-																				float roadValueNb = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY);	//hole Wert aus Straßenraster
-																				if (roadValueNb > 0f)	//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNb hoch
-																					anzRoadNb++;
-																				
-																				//statusOut.println("Strasse in Entfernung 1: "+anzRoadNb+","+nbRoadCellsX+","+nbRoadCellsY);
-																			}
-																		roadNeighborhoodRange++;	
-																		RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);
-																		//statusOut.println("--> Zyklus "+roadNeighborhoodRange+"Nachbarn: "+anzRoadNb);
-																		//statusOut.println(RSearchNbRoad);
-																		int anzTempRoadNb = 0;
-																		for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++){
-																			for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){
-						        	//											statusOut.println("TEST-ROAD: "+nbRoadCellsX+","+nbRoadCellsY);
-											//									if (gridBounds.contains(nbRoadCellsX, nbRoadCellsY))
-																				if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
-																						Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																					continue;
-																	//			if (areaRestr.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY) != 0)
-																	//				continue;
-																				float roadValueNbTemp = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY);	//hole Wert aus Straßenraster
-																				if (roadValueNbTemp > 0f){									//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNbTemp hoch
-																					anzTempRoadNb++;
-																					tempNbRoadCell = new int[] {nbRoadCellsX,nbRoadCellsY,anzTempRoadNb};	//schreibe die Koordinaten in ein Array
-																					if (tempNbRoadCell[2]==RSearchNbRoad){					//Wenn der Wert im Array dem vorher definierten Zufallswert entspricht...
-																						//statusOut.println("Treffer: "+tempNbRoadCell[0]+","+tempNbRoadCell[1]+","+tempNbRoadCell[2]);
-																						tempRoadCell = tempNbRoadCell;						//...wird die temporäre Straßenzelle an diese Position verschoben
-											//											statusOut.println("Strasse in Entfernung "+roadSearch+": "+tempRoadCell[0]+","+tempRoadCell[1]+","+tempRoadCell[2]);
-																						int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],disp);	//von dort aus wird ein Road-Walk durchgeführt (--> siehe Funktion roadWalk!)
-																						if(nbCellNew != null){												//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
-																							tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;						//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
-//																							statusOut.println(nbCellNew.length);
-//																							statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
-//																							statusOut.println("++++++++++++++++++++++++++++++++++++++++");
-																							//Variablendefinitionen
-																							
-																							float nbRoadBreed = 0f;
-																							int nbRoadBreedNeighbors = 0;
-																							nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);
-																							int RNRoadBreed1 = 0;
-																							int RNRoadBreed2 = 0;
-																							int nbRoadBreedX = 0;
-																							int nbRoadBreedY = 0;
-																							int anzRoadBreedTreffer = 0;
-																						
-																							//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
-																							//nochmals ein "Breed" aus. (GLEICHE FUNKTION WIE OBEN!!)
-												        
-																							if (nbRoadBreedNeighbors >= 2){
-																								int anzBreedTemp = 0;
-																								int[] nbPossibleBreedUrban = null;
-																								RNRoadBreed1 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																								RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																								float RNRoadBreedSlope = 0f;
-																								if (RNRoadBreed2 == RNRoadBreed1)
-																									RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));	
-																								for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){
-																									nbRoadBreedX = nbCellNew[0]+NEIGHBOR[cellBreed][0];
-																									nbRoadBreedY = nbCellNew[1]+NEIGHBOR[cellBreed][1];
-																									if ( nbRoadBreedX < areaMinX || nbRoadBreedY < areaMinY || nbRoadBreedX > areaMaxX || nbRoadBreedY > areaMaxY ||
-																											Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																										continue;
-																									if (areaRestr.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY) != 0)
-																										continue;
-																									RNRoadBreedSlope = (float)Math.random();
-																									int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
-																									Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
-																									double slopeDoubleNb = doubleObjNb.doubleValue();
-																									float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
-																									if (breedSample == 0f){
-																										anzBreedTemp++;
-																										nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};
-																										if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){
-																											tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;
-																											anzRoadBreedTreffer++;
-																											//statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
-																										}
-																									}
-																								}
-												        									}
-																						} else{			//sind nicht mind. 2 Nachbarzellen gefunden worden...
-																							//statusOut.println("Keine neue Zelle gefunden");
-																						}
-																					}
-																				}
-																			}
-																		}
-																	}
-																}
-															}
-														}	
-													}
-												}
-			
-										} while (r <= breed);
-		
-										//		statusOut.println("Spread-Treffer: "+anzSpreadTreffer);
-										//		statusOut.println("Dispersion-Treffer: "+anzDispTreffer);
-										//		statusOut.println("Breed-Treffer: "+anzBreedTreffer);
-										//		statusOut.println("Treffer gesamt: "+anzGesamt);
-		
-										//		outStep.addGrid();
-		
-
-										/**
-										 * Hier endet der eigentliche Modellalgorithmus des Urban Growth Modells.
-										 * Als nächstes wird das was ins temporäre grid geschrieben wurde ins outputGrid geschrieben.
-										 * Mit dem outputGrid wird dann im nächsten Zeitschritt weitergerechnet, bis die maximale Anzahl
-										 * an Jahren erreicht ist. Danach wird die nächste Kombination an Koeffizienten gewählt.
-										 */
+											outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);	//write the results in the output raster
+											actUrb  = (Float)outputGrid.getRasterSample(x,y);	//the actual urban extent
+										}
+									}
+									statusOut.println("Urban pixels at step "+timeSteps+": "+anzGesamt);
+									
+									if (timeSteps == years){
+										outStep.addGrid();	//add a raster to the GridList
 										
-										// TempGrid auf das echte Grid schreiben
-										for (int y = 1; y < outputGrid.getHeight()-1;y++ ) 
-											for (int x = 1; x < outputGrid.getWidth()-1; x++ ) {
-				
-												int X = outputGrid.getMinX() + x;
-												int Y = outputGrid.getMinY() + y;
-				
-												boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f;	//eine Zelle lebt, wenn sie 1 ist
-												if (tmpGrid[x][y] == false)	//wenn im temporären Raster nichts drinsteht...
-													tmpGrid[x][y] = lebt;	//wird der Wert aus dem Ausgangsraster übernommen
-					
-
-												outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);	
-												actUrb  = (Float)outputGrid.getRasterSample(x,y);
-												// outStep.getGrid(stepNo-1).setRasterSample(actUrb,x,y);
+										// Write the temporary Grid to the Output Grid
+										for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+											for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
+												actUrb  = (Float)outputGrid.getRasterSample(x,y);	//the actual urban extent
+												outStep.getGrid(MC-1).setRasterSample(actUrb,x,y);	//put the layer in the raster list containing the step results
 											}
-										
-										if (!anyBodyAlive) {
-											stepCount = stepNo;
-											//statusOut.println("Lebt keiner mehr... höre hier auf!");
 										}
-		
-										//RasterUtil.copyInto(outputGrid, inputGrid);
-										//	System.out.println("Finished step " + (stepNo) + " in "
-										//			+ ((System.currentTimeMillis() - localStartTime)) + " ms\n");
-										localStartTime = System.currentTimeMillis();
-		
-									}	//HIER ENDET DER ZEITSCHRITT. DIE SCHLEIFE WIRD DURCHLAUFEN, BIS MAX JAHRE ERREICHT SIND.
-		
-									/**
-									 * +++++ MULTIPLE RESOLUTION VALIDATION ++++++
-									 * Sind alle Zeitschritte durchlaufen, wird das Endergebnis validiert.
-									 * Als Validierungsmethode wurde die Multiple Resolution Validation ausgewählt (siehe
-									 * Costanza(1989), Pontius (2002), Pontius et al. (2005), Lesschen et al. (2005),
-									 * Pontius et al. (2008a), Pontius et al. (2008b))
-									 * Für das SLEUTH-Modell werden eigentlich eine Reihe an Landschaftsmaßen zur Validierung
-									 * verwendet (siehe Clarke et al. (1997), Dietzel et al. (2007)), wie z.B. LeeSallee
-									 * oder OSM. Da für die spätere Validierung der Modellierungsergebnisse und zum Vergleich mit 
-									 * anderen Modelltypen die Multiple Resolution Validation verwendet wird, wird sie auch zur
-									 * Bewertung der Kalibrierungsschritte verwendet.
-									 */
+										WritableGrid simulationMap = outStep.getGrid(MC-1);		//write the final step result to the grid list
+										float[] mrv = MultipleResolutionComparison(simulationMap);	//perform the MRV
+										for(int i = 0;i < mrv.length;i++){
+											statusOut.println(mrv[i]);
+											mrvTempResultArray[i] += mrv[i];
+										}
+									}
+								}	//END OF THE TIME STEPS
+								
+								if (MC == MonteCarlo){
+									SumOutStep.addGrid();	//add a final raster to the GridList (contains the sum of all iterations)
 									
-									//Variablendefinitionen
-									int RoverallSum = 0;
-									int RnumClasses = 0;
-									int SoverallSum = 0;
-									int SnumClasses = 0;
-									int correct = 0;
-									double fractionCorrect = 0f;
-		
-
-									long localStartTime = System.currentTimeMillis();
-									neighborhoodRange = (int) Math.sqrt(referenceGrid.getWidth()*referenceGrid.getHeight()); //maximal mögliche Zellengröße
-									//statusOut.println(neighborhoodRange);
-									resultArray = new float[13];		//!!!!!!!!! Ergebnis-Array
-									resultArrayFinal = new float[MonteCarlo-1][10];	//?????????????
+									//statusOut.println("Step Grids: "+outStep.getGridCount());
 									
-									//Für die Ausgangs-Auflösung wird berechnet, wieviel % der Pixel zwischen Modell und Referenz übereinstimmen
-									for (int x = 0; x < referenceGrid.getWidth(); x++)
-										for (int y = 0; y < referenceGrid.getHeight(); y++) {
-											float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
-											float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
-											if (!Float.isNaN(Rtmp) && !Float.isNaN(Stmp)){
-												RoverallSum ++;
-												SoverallSum ++;
-												if (Rtmp > RnumClasses)
-													RnumClasses = (int) Rtmp;
-												if (Stmp > SnumClasses)
-													SnumClasses = (int) Stmp;	
-												if (Rtmp == Stmp)
-													correct++;
+									for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+										for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {	//for every pixel...
+											float sumUrb = 0; 	//sum of pixel values
+											for (int gridNo = 0; gridNo < MC; gridNo++){	//look in every grid of the GridList
+												float tempUrb = (Float) outStep.getGrid(gridNo).getRasterSample(x,y);	//take the pixel value
+												sumUrb  += tempUrb;		//and add its value
 											}
+											SumOutStep.getGrid(runs-1).setRasterSample(sumUrb,x,y);	//put the layer in the raster list containing the step results
 										}
-									fractionCorrect = (double) correct / (double) RoverallSum;
-		
-									//Anzahl der Pixel pro Klasse
-									for (int i = 1; i <= RnumClasses; i++){
-										int Rj = 0;
-										int Sj = 0;
-										for (int x = 0; x < referenceGrid.getWidth(); x++)
-											for (int y = 0; y < referenceGrid.getHeight(); y++){
-												float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
-												float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
-												if (!Float.isNaN(Rtmp))
-													if ((int) Rtmp == i)
-														Rj++;
-												if (!Float.isNaN(Stmp))
-													if ((int) Stmp == i)
-														Sj++;
-											}
-										//statusOut.println("Klasse "+i+": Referenz("+Rj+"), Simulation("+Sj+")");
 									}
-		
-									ngrids = 0;
 									
-									//Die eigentliche Validierung wird für alle Zellengrößen von 1 (Ausgangsauflösung) bis "neighborhoodRange" durchgeführt
-									for (int r1 = 1; r1 <= neighborhoodRange; r1 = r1+r1){	//für Zellengröße 1 bis zur max. möglichen Zellengröße wird Statistik durchgeführt
-										//statusOut.println(r1);	
-										ngrids++;
-										float SumWn = 0f;	//Summe der gewichteten Mittelwerte 
-										int SumCells = 0;	//Summe der Zellen
-										float totalAgreement = 0f;	//Endergebnis
-										for (int x = 0; x < referenceGrid.getWidth(); x = x+r1)	//für jeden größer werdenden Zellenbereich...
-											for (int y = 0; y < referenceGrid.getHeight(); y = y+r1){	//was folgt passiert innerhalb einer größeren Rasterzelle
-												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+r1; x2++)	//für jede kleinere Zelle innerhalb der größeren...
-													for(int y2 = y; y2 < y+r1; y2++){
-														if ( x2 < referenceGrid.getMinX() || y2 < referenceGrid.getMinY() || x2 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y2 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
-																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x2,y2)))
-															continue;
-														nCells++;	//zähle "positive" Zellen
-													}
-												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+r1; x3++)	//für jede kleinere Zelle pro größerer Zelle...
-														for(int y3 = y; y3 < y+r1; y3++){
-															if ( x3 < referenceGrid.getMinX() || y3 < referenceGrid.getMinY() || x3 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y3 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
-																	Float.isNaN(referenceGrid.getRasterSampleAsFloat(x3,y3)))
-																continue;
-															float Rtmp = referenceGrid.getRasterSampleAsFloat(x3, y3);	//hole Wert aus Referenz-Karte und
-															float Stmp = outputGrid.getRasterSampleAsFloat(x3, y3);	//Simulationskarte
-															if ((int) Rtmp == i)
-																Rn++;	//zähle in Referenzkarte Zellen, die zu Klasse i gehören 
-															if ((int) Stmp == i)
-																Sn++;	//und in Simulationskarte
-														}
-													if(nCells > 0){	//wenn positive Zellen vorhanden sind...
-														Rnj = (float)Rn / (float)nCells;	//berechne Anteile pro größerer Zelle
-														Snj = (float)Sn / (float)nCells;
-													}
-													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);	
-												}
-												
-												Wn = (float)nCells * SumMinRS;
-												//	statusOut.println(SumMinRS+", gewichtet: "+Wn);
-												//Erstelle Output-Karten
-												float WnCell = 0f;
-												for(int x4 = x; x4 < x+r1; x4++)	//für jede kleinere Zelle pro größerer Zelle...
-													for(int y4 = y; y4 < y+r1; y4++){
-														if ( x4 < referenceGrid.getMinX() || y4 < referenceGrid.getMinY() || x4 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y4 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
-																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x4,y4)))
-															continue;
-														WnCell = Wn / (float)nCells; //pro Zelle wird Mittelwert des Vergleichs genommen
-														//actualValidation.setRasterSample( WnCell ,x4 ,y4);	
-													}
-				
-												SumCells += (float)nCells;	//Summiere alle Zellen auf
-												SumWn += Wn;	//Summiere die gewichteten Anteile auf
-											}		//hier endet die Berechnung innerhalb einer größeren Rasterzelle
-										
-										
-										//Total Agreement:
-										//statusOut.println(SumWn+" / "+SumCells);
-										totalAgreement = SumWn / (float)SumCells;	//Ergebnisformel
-										//statusOut.println(totalAgreement);	
-
-										outResults.addValue(totalAgreement);
-										resultArray[ngrids] = totalAgreement;
-
-										//	statusOut.println("Gesamt-Pixel: "+RoverallSum);
-										//	statusOut.println("Anzahl Klassen: "+RnumClasses);
-										//	statusOut.println("Fraction Correct: "+fractionCorrect);
-										
-									}	//Hier endet die Berechnung pro Auflösung
-		
-								//	System.out.println("(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
-								//			resultArray[1]+","+resultArray[2]+","+resultArray[3]+","+resultArray[4]+","+resultArray[5]+","+resultArray[6]+
-								//			","+resultArray[7]+","+resultArray[8]+","+resultArray[9]);
-																		
-									//Führe jede Position einzeln auf. Das sollte noch automatisiert werden !!!
-									pos1 += resultArray[1];
-									pos2 += resultArray[2];
-									pos3 += resultArray[3];
-									pos4 += resultArray[4];
-									pos5 += resultArray[5];
-									pos6 += resultArray[6];
-									pos7 += resultArray[7];
-									pos8 += resultArray[8];
-									pos9 += resultArray[9];
-									pos10 += resultArray[10];
-									pos11 += resultArray[11];
-									pos12 += resultArray[12];
-									//	System.out.print("Finished step " + (stepNo) + " in "
-									//			+ ((System.currentTimeMillis() - localStartTime)) + " ms");
-									localStartTime = System.currentTimeMillis();
-									//	System.out.println(" with sum (local calculated): " + RoverallSum);
-							}	//!!!!!!!!!! Hier endet ein Monte-Carlo-Schritt
-							
-							System.out.println("-->(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
-									pos1/MonteCarlo+","+pos2/MonteCarlo+","+pos3/MonteCarlo+","+pos4/MonteCarlo+","+pos5/MonteCarlo+","+pos6/MonteCarlo+
-											","+pos7/MonteCarlo+","+pos8/MonteCarlo+","+pos9/MonteCarlo+","+pos10/MonteCarlo+","+pos11/MonteCarlo+","+pos12/MonteCarlo);
-						}	//Ende RoadGravity-Koeffizient
-					}	//Ende Breed-Koeffizient
-				}	//Ende Disp-Koeffizient
-			}	//Ende Spread-Koeffizient
-		}	//Ende Slope-Koeffizient
-	}	//Ende Model-Step
-	
-	private int[] roadWalk(int X,int Y,double disp){
-//		statusOut.println(X+","+Y);
-		boolean end_of_road;
-		end_of_road = false;
-		int run = 0;
-		int run_value = 0;
-		int[] nbCellNew = null;
-		int[] nbCellTemp = null;
-		while(!end_of_road){
-			end_of_road = true;
-			int nbRoadX = 0;
-			int nbRoadY = 0;
-			int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
-			int areaMinY = outputGrid.getMinY();
-			int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
-			int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
-			int roadNb = 0;
-			int roadNbTemp = 0;
-			int RN = 0;
-						
-			int[] nbCell = null;
-			for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
-				nbRoadX = X+NEIGHBOR[nbRoadCells][0];
-				nbRoadY = Y+NEIGHBOR[nbRoadCells][1];
-				if ( nbRoadX < areaMinX || nbRoadY < areaMinY || nbRoadX > areaMaxX || nbRoadY > areaMaxY ||
-			               Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-			             continue;
-				//if (areaRestr.getRasterSampleAsFloat(nbRoadX,nbRoadY) != 0)
-		        //	continue;
-				float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY);
-				if (roadSample > 0f)
-					roadNb++;
-			}
-	//		statusOut.println("Nachbarn von temporaerer Strassenzelle: "+roadNb);
-			
-			if (roadNb > 0){
-				RN = 1 + Math.round((float)Math.random()*(roadNb-1));
-			
-				for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
-					nbRoadX = X+NEIGHBOR[nbRoadCells][0];
-					nbRoadY = Y+NEIGHBOR[nbRoadCells][1];
-					if ( nbRoadX < areaMinX || nbRoadY < areaMinY || nbRoadX > areaMaxX || nbRoadY > areaMaxY ||
-							Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-			             	continue;
-					float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY);
-					if (roadSample > 0f){
-						roadNbTemp++;
-						nbCell = new int[] {nbRoadX,nbRoadY,roadNbTemp};
-						if (nbCell[2] == RN){
-//							statusOut.println("Nachbarzelle gefunden: "+nbCell[0]+","+nbCell[1]+","+nbCell[2]);
-							end_of_road = false;
-							run++;
-							X = nbRoadX;
-							Y = nbRoadY;
-							float roadSample2 = roadGrid.getRasterSampleAsFloat(X,Y);
-							run_value = (int) (roadSample2 / 100 * disp);
-					//		statusOut.println("Run: "+run);
-					//		statusOut.println("Run_Value: "+run_value);
-					//		statusOut.println(X+","+Y+","+roadSample2);
-							if (run > run_value){
-								end_of_road = true;
-					//			statusOut.println("Endzelle erreicht!! Run:"+run+"RunValue: "+run_value);
-								float NbValue = 0f; 
-								int Nb = calculateNeighbors(X,Y,NbValue);
-					//			statusOut.println("moegliche Nachbarzellen nach RoadWalk: "+Nb);
-								RN = 1 + Math.round((float)Math.random()*(Nb-1));
-				//				statusOut.println("Random: "+RN);
-								if (Nb > 0){
-									int nbUrbanizeX = 0;
-									int nbUrbanizeY = 0;
-									int NbTemp = 0;
-									float RNRoadSlope = 0f;
-						//			statusOut.println(X+","+Y);
-									for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){
-										nbUrbanizeX = X+NEIGHBOR[urbanizeCells][0];
-										nbUrbanizeY = Y+NEIGHBOR[urbanizeCells][1];
-										if ( nbUrbanizeX < areaMinX || nbUrbanizeY < areaMinY || nbUrbanizeX > areaMaxX || nbUrbanizeY > areaMaxY ||
-												Float.isNaN(outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-											continue;
-										if (areaRestr.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY) != 0)
-											continue;
-										float rasterSample = outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY);
-										RNRoadSlope = (float)Math.random();
-					        			int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY);
-					        			Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
-					        			double slopeDoubleNb = doubleObjNb.doubleValue();
-										if (rasterSample == 0f){
-											NbTemp++;
-											nbCellTemp = new int[] {nbUrbanizeX,nbUrbanizeY,NbTemp};
-											if (nbCellTemp[2] == RN && slopeDoubleNb < RNRoadSlope){
-												nbCellNew = new int[] {nbCellTemp[0],nbCellTemp[1],nbCellTemp[2]};
-											}
-										}	
+									System.out.print("Slope: "+slope+" Spread: "+spread+" Disp: "+disp+" Breed: "+breed+" Road: "+roadGravity+" : ");
+									
+									for(int i = 0;i < mrvTempResultArray.length-2;i++){
+										//print every element of the result array comma separated in one line in the status output
+										finalArray[i] = mrvTempResultArray[i]/MonteCarlo;
+										System.out.print(finalArray[i]+",");
 									}
+									System.out.print("//Weighted Averages (FT, WA): ");
+									for(int j = 0;j < 2;j++){
+										//print every element of the result array comma separated in one line in the status output
+										finalArray[numSteps+j] = mrvTempResultArray[j]/MonteCarlo;
+										System.out.print(finalArray[j]+",");
+									}
+									for (int grids = MC-1; grids >= 0; grids--){
+										outStep.removeGrid(grids); 				//empty GridList
+									}
+									//statusOut.println("Step Grids nach leeren: "+outStep.getGridCount());
+							
+								} 
+								countSetIndividuals();
 								
-							} else{
-								nbCellNew = null;
-							}	break;
+							}	System.out.println("");
+							
+							//END OF THE MONTE CARLO ITERATIONS
+						}	//END OF ROADGRAVITY COMBINATION
+					}	//END OF BREED COMBINATION
+				}	//END OF DISP COMBINATION
+			}	//END OF SPREAD COMBINATION
+		}	//END OF SLOPE COMBINATION
+		System.out.println("Finished "  + " in " + ((System.currentTimeMillis() - localStartTime)) + " ms\n");
+	}	//END OF MODEL STEP
+	
+	/**
+	 * <b>MULTIPLE RESOLUTION VALIDATION</b><br>
+	 * When all time steps are run, the result is being evaluated. Therefore the 
+	 * Multiple Resolution Comparison is chosen (refer to ostanza(1989), Pontius (2002), 
+	 * Pontius et al. (2005), Lesschen et al. (2005), Pontius et al. (2008a), Pontius et al. (2008b))
+	 * For the original SLEUTH model a number of landscape measures are used for validation
+	 * (refer to Clarke et al. (1997), Dietzel et al. (2007)), like e.g. the LeeSallee
+	 * or OSM. Because the same method (MRV) is used within XULU to compare the results of different models,
+	 * it was also chosen to evaluate the performance of the different calibration steps of the Urban Growth Model.
+	 */
+	public float[] MultipleResolutionComparison(WritableGrid simulationMap){
+		//Variablendefinitionen
+		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
+//		int numSteps = 0;
+							
+	//	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[numSteps+2];
+		
+		for (int x = 0; x < referenceMap.getWidth(); x++)
+			for (int y = 0; y < referenceMap.getHeight(); 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) && !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;	//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;	//see RnumClasses
+					if (Rtmp == Stmp)
+						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;	//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);	//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++;	//if cell belongs to category i, count it (for Reference map)
+					if (!Float.isNaN(Stmp))
+						if ((int) Stmp == i)
+							Sj++;	//if cell belongs to category i, count it (for Simulation map)
+				}
+			statusOut.println("Class "+i+": Reference("+Rj+"), Simulation("+Sj+")");
+		}
+		
+		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++;		//count the number of grids
+			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;		//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++;	//count all cells that have a value
 						}
+					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);	//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++;	//count all cells that belong to class i in reference map 
+								if ((int) Stmp == i)
+									Sn++;	//count all cells that belong to class i in simulation map
+							}
+						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);	//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;	//all coarse cells are weighted by multiplying the Sum of all MIN values with the number of cells that make up a coarse cell
+										
+					SumCells += (float)nCells;	//Sum all positive cells in a resolution grid
+					SumWn += Wn;	//Sum all weighted portions in a resolution grid
 				}
-			}
 			
-			}
+			//Total Agreement:
+			//statusOut.println(SumWn+" / "+SumCells);
+			totalAgreement = SumWn / (float)SumCells;	//Main Results
+			//statusOut.println(totalAgreement);	
+			outResults.addValue(totalAgreement);
+			//resultArray[0][ngrids-1] = r;
+			resultArray[ngrids-1] = 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;
 		}
-		return nbCellNew;
+		
+		//From here on the results of the Multiple Resolution Comparison are written on the screen
+		
+		//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 = 0; i <= ngrids-1; i++){
+//			System.out.print(resultArray[i]+",");
+			//calculations for weighted average after Costanza (1989):
+			w = (float) Math.exp(-0.1*(resultArray[i] - 1));
+			Fw = resultArray[i]*w;
+			SumW += w;
+			SumFw += Fw;
 		}
-	
-	private int calculateNeighbors(int X, int Y, float NbValue){
-		int nbX = 0;
-		int nbY = 0;
-		int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
-		int areaMinY = outputGrid.getMinY();
-		int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
-		int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
-		int Nb = 0;
-		for (int nbCells = 0; nbCells < NEIGHBOR.length; nbCells++){
-			nbX = X+NEIGHBOR[nbCells][0];
-			nbY = Y+NEIGHBOR[nbCells][1];
-			if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
-		               Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-		             continue;
-			if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
-	        	continue;
-			float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
-			if (rasterSample == NbValue)
-				Nb++;
-		}
-	//	statusOut.println("..."+Nb+"...");
-		return Nb;
+		
+		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
+		resultArray[numSteps] = Ft;
+//		System.out.println("");
+//		System.out.println(resultArray[numSteps+1]);
+		resultArray[numSteps+1] = WeightedAgreement;
+//		System.out.println(resultArray[numSteps+2]);
+		return resultArray;	
 	}
-	
-	protected static boolean checkNoData(int x, int y, WritableGrid grid) {
-	    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
-	  }
 }

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationContentManager.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -4,48 +4,47 @@
 import schmitzm.data.property.ListProperty;
 import schmitzm.data.property.ScalarProperty;
 import edu.bonn.xulu.data.XuluDataException;
-import edu.bonn.xulu.model.AbstractModelContentManager;
 import edu.bonn.xulu.model.DefaultModelResource;
 import edu.bonn.xulu.model.ModelResource;
 import edu.bonn.xulu.model.ValuePropertyResource;
 import edu.bonn.xulu.plugin.data.grid.MultiGrid;
 
 
-public class UrbanGrowthModelCalibrationContentManager extends AbstractModelContentManager {
+public class UrbanGrowthModelCalibrationContentManager extends UrbanGrowthModelContentManager {
 	
-	public UrbanGrowthModelCalibrationContentManager() {
-		super(25);
+	public UrbanGrowthModelCalibrationContentManager(int additionalRes) {
+		super(14+additionalRes);	//14, because in the parent class are 12 resources (+14 = 26)
 	    
-		resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
-		resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of MonteCarlo Iterations",ScalarProperty.class,Integer.class,false);
-		resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
-		resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
-	    resource[5] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[6] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Reference Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[8] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[9] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[10] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[12]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[13]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[14]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[15]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[16]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[17]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[18]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[19]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[20]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[21]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[22]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[23]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
+	    resource[6] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Reference Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[8] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[9] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[10]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[12]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[13]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[14]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[15]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[16]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[17]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[18]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[19]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Start",ScalarProperty.class,Double.class,false);
+	    resource[20]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Step",ScalarProperty.class,Double.class,false);
+	    resource[21]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient End",ScalarProperty.class,Double.class,false);
+	    resource[22]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
+	    resource[23]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of MonteCarlo Iterations",ScalarProperty.class,Integer.class,false);
 	    resource[24]= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Validation Results",ListProperty.class,Float.class,false);
+	    resource[25]= new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,"Step Results",MultiGrid.class,false);
+	    resource[26]= new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,"Sum Step Results",MultiGrid.class,false);
 	 	// ===== Ressourcen Bezeichnungen lokalisieren =====
 	    resetCaptions(null);
 	}
+
+	public UrbanGrowthModelCalibrationContentManager() {
+		this(0);
+		
+	}
 	
-	
 	@Override
 	public void checkAndError() throws XuluDataException {
 		// TODO Auto-generated method stub

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModification.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -1,96 +1,47 @@
 package edu.bonn.xulu.plugin.model.sleuth;
 
-import java.awt.Rectangle;
-import java.util.HashMap;
-
-import appl.util.RasterUtil;
-
-import edu.bonn.xulu.model.AbstractStepModel;
 import edu.bonn.xulu.model.XuluModel;
-import edu.bonn.xulu.plugin.data.grid.MultiGrid;
-
 import schmitzm.data.WritableGrid;
-import schmitzm.data.property.ListProperty;
-import schmitzm.data.property.ListPropertyWriteAccess;
 import schmitzm.data.property.PropertyReadAccess;
-import schmitzm.data.property.PropertyWriteAccess;
 import schmitzm.data.property.ScalarProperty;
 
 /**
- * @see AverageNeighborhoodContentManager
- * @author Dominik Appl
+ * <b>Calibration of the Urban Growth Model with Self Modification</b><br>
+ *  This model is based on the {@link UrbanGrowthModelCalibration Urban Growth Model Calibration}, which is a deviation of the {@link UrbanGrowthModel Urban Growth Model} developed by Keith Clarke at the UC Santa Barbara, CA, 
+ *  within the Gigalopolis Project, funded by the USGS. In addition to the calibration routine a number of main input parameters is modified during each time step. When the growth rate exceeds or falls below certain
+ *  critical values the coefficients are modified. For a detailed description refer to the <a href="http://www.ncgia.ucsb.edu/projects/gig/v2/About/gwSelfMod.htm">SLEUTH Homepage</a>.
+ *  
+ *  <br>
+ *  In addition to the UGM Calibration Coefficients, these parameters are needed:<br>
+ * <ul>
+ *  <li><b>Road Gravity Sensitivity</b>: Influences the roadGravity coefficient</li>
+ *  <li><b>Slope Sensitivity</b>: Influences the slope coefficient</li>
+ *  <li><b>Critical Low</b>: When growth rate falls below this value, the coefficients are altered</li>
+ *  <li><b>Critical High</b>: When growth rate exceeds this value, the coefficients are altered</li>
+ *  <li><b>Boom</b>: Boom Phase. The Coefficients are increased by this value.</li>
+ *  <li><b>Bust</b>: Bust Phase. The Coefficients are decreased by this value.</li>
+ * </ul>
+ * 
+ * @see UrbanGrowthModelCalibrationSelfModificationContentManager
+ * @see UrbanGrowthModelCalibration
+ * @see UrbanGrowthModelSelfModification
+ * @see UrbanGrowthModel
+ * @see UrbanGrowthModel_MC
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
  * @version 1.0
  */
-public class UrbanGrowthModelCalibrationSelfModification extends AbstractStepModel {
+public class UrbanGrowthModelCalibrationSelfModification extends UrbanGrowthModelCalibration {
 
-	private int neighborhoodRange = 0;
-	private float[] resultArray;
-	private float[][] resultArrayFinal;
-	/**
-	 * Speichert den ContentManager fuer das Modell.
-	 */
-	protected UrbanGrowthModelCalibrationSelfModificationContentManager contManager;
-
-	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
-	// ********** Modellanlauf gehalten werden muessen ***********
-	private PropertyReadAccess RA_steps = null; // Number of steps
-	private PropertyReadAccess RA_MonteCarlo = null;	//Number of MonteCarlo Iterations
-	private PropertyReadAccess RA_inputGrid = null; // Input Grid
-	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
-	private PropertyReadAccess RA_areaRestr = null; //Area Restrictions
-	private PropertyReadAccess RA_spreadStart = null;	//Spread-Koeffizient
-	private PropertyReadAccess RA_spreadStep = null;	//Spread-Koeffizient
-	private PropertyReadAccess RA_spreadEnd = null;	//Spread-Koeffizient
-	private PropertyReadAccess RA_dispStart = null;		//Dispersions-Koeffizient
-	private PropertyReadAccess RA_dispStep = null;		//Dispersions-Koeffizient
-	private PropertyReadAccess RA_dispEnd = null;		//Dispersions-Koeffizient
-	private PropertyReadAccess RA_breedStart = null;		//Breed-Koeffizient
-	private PropertyReadAccess RA_breedStep = null;		//Breed-Koeffizient
-	private PropertyReadAccess RA_breedEnd = null;		//Breed-Koeffizient
-	private PropertyReadAccess RA_roadGravityStart = null;	//Road-Gravity-Koeffizient
-	private PropertyReadAccess RA_roadGravityStep = null;	//Road-Gravity-Koeffizient
-	private PropertyReadAccess RA_roadGravityEnd = null;	//Road-Gravity-Koeffizient
-	private PropertyReadAccess RA_slopeStart = null;	//Slope-Koeffizient
-	private PropertyReadAccess RA_slopeStep = null;	//Slope-Koeffizient
-	private PropertyReadAccess RA_slopeEnd = null;	//Slope-Koeffizient
-	private PropertyReadAccess RA_criticalSlope = null;	//Critical Slope Value
-	private PropertyReadAccess RA_roadGrid = null;	//Road Grid
-	private PropertyReadAccess RA_slopeGrid = null;	//Slope Grid
-	private PropertyReadAccess RA_referenceGrid = null;	//Observed Validation Grid
-	private ListPropertyWriteAccess WA_outResults = null;	//Output Validation Results
-	private PropertyReadAccess RA_roadGravSens = null;	//RoadGravity Sensitivity
-	private PropertyReadAccess RA_slopeSens = null;	//Slope Sensitivity
-	private PropertyReadAccess RA_criticalLow = null;	//Critical Low
-	private PropertyReadAccess RA_criticalHigh = null;	//Critical High
-	private PropertyReadAccess RA_Boom = null;	//Boom
-	private PropertyReadAccess RA_Bust = null;	//Bust
+	// ********** Read/Write access, that has to be maintained ***
+	// ********** through the whole model run ********************
+	protected PropertyReadAccess RA_roadGravSens = null;	//RoadGravity Sensitivity
+	protected PropertyReadAccess RA_slopeSens = null;	//Slope Sensitivity
+	protected PropertyReadAccess RA_criticalLow = null;	//Critical Low
+	protected PropertyReadAccess RA_criticalHigh = null;	//Critical High
+	protected PropertyReadAccess RA_Boom = null;	//Boom
+	protected PropertyReadAccess RA_Bust = null;	//Bust
 	
-	// **************** Variablen mit denen gearbeitet wird *******************
-	private WritableGrid inputGrid = null; // Input Grid
-	private WritableGrid outputGrid = null; // Output Grid
-	private int steps = 0; // Number of steps
-	private int MonteCarlo = 0;	//Number of Monte Carlo Iterations
-	private WritableGrid areaRestr = null; //Area Restrictions
-	protected double spreadStart = 0;	//Spread-Koeffizient
-	protected double spreadStep = 0;	//Spread-Koeffizient
-	protected double spreadEnd = 0;	//Spread-Koeffizient
-	protected double dispStart = 0;	//Dispersions-Koeffizient
-	protected double dispStep = 0;	//Dispersions-Koeffizient
-	protected double dispEnd = 0;	//Dispersions-Koeffizient
-	protected double breedStart = 0;	//Breed-Koeffizient
-	protected double breedStep = 0;	//Breed-Koeffizient
-	protected double breedEnd = 0;	//Breed-Koeffizient
-	protected double roadGravityStart = 0;	//Road-Gravity-Koeffizient
-	protected double roadGravityStep = 0;	//Road-Gravity-Koeffizient
-	protected double roadGravityEnd = 0;	//Road-Gravity-Koeffizient
-	protected double slopeStart = 0;	//Slope-Koeffizient
-	protected double slopeStep = 0;	//Slope-Koeffizient
-	protected double slopeEnd = 0;	//Slope-Koeffizient
-	protected double criticalSlope = 0;	//Critical Slope Value
-	private WritableGrid roadGrid = null;	//Road Grid
-	private WritableGrid slopeGrid = null;	//Slope Grid
-	private WritableGrid referenceGrid = null;	//Observed Validation Grid 
-	private ListPropertyWriteAccess outResults = null;	//Output Validation Results
+	// **************** Variablen to work with *******************
 	protected double roadGravSens = 0;	//RoadGravity Sensitivity
 	protected double slopeSens = 0;	//Slope Sensitivity
 	protected double criticalLow = 0;	//critical Low
@@ -98,255 +49,85 @@
 	protected double boom = 0;	//Boom
 	protected double bust = 0;	//Bust
 	
-	private  static final int[][] NEIGHBOR = new int[][] {
-	      {-1,-1}, {0,-1}, {1,-1},
-	      {-1, 0},         {1, 0},
-	      {-1, 1}, {0, 1}, {1, 1}
-	  };
+	protected int slopeMax = 0;
+	protected int totalPixels = 0;
+	protected int excldCount = 0;
 	
-	protected  HashMap<Number,Number> slopeLUT;
-	private int slopeMax = 0;
-	private int totalPixels = 0;
-	private int excldCount = 0;
+	/**
+	 * First Constructor
+	 * @param contManager
+	 */
+	public UrbanGrowthModelCalibrationSelfModification(UrbanGrowthModelCalibrationSelfModificationContentManager contManager) {
+		super(contManager);
+		//this.contManager = (UrbanGrowthModelCalibrationSelfModificationContentManager) super.contManager;
+	}
 	
 	/**
-	 * Erzeugt eine neue Instanz des Modells.
+	 * Second Constructor. The Content Manager is the parent content manager as well as the child content manager
 	 */
-	public UrbanGrowthModelCalibrationSelfModification() {
+	public UrbanGrowthModelCalibrationSelfModification(){
 		super(new UrbanGrowthModelCalibrationSelfModificationContentManager());
-		this.contManager = (UrbanGrowthModelCalibrationSelfModificationContentManager) super.contManager;
 	}
 
-	
 	/**
 	 * Initializes the model. Like in the init method of every {@link XuluModel}
 	 * the resources are initalized. 
 	 */
 	public void performModelInit() {
-		if (contManager == null)
-			return;
-		// Zugriffsrechte aus Ressourcen/Propertys holen
-		RA_steps = null;
-		if (contManager.getResource(0).getData() != null)
-			RA_steps = ((ScalarProperty) contManager.getResource(0).getData())
-					.getReadAccess(this);
-		RA_MonteCarlo = null;
-		if (contManager.getResource(1).getData() != null)
-			RA_MonteCarlo = ((ScalarProperty) contManager.getResource(1).getData())
-					.getReadAccess(this);
-		RA_inputGrid = null;
-		if (contManager.getResource(2).getData() != null)
-			RA_inputGrid = ((ScalarProperty) contManager.getResource(2)
-					.getData()).getReadAccess(this);
-		WA_outputGrid = null;
-		if (contManager.getResource(3).getData() != null)
-			WA_outputGrid = ((ScalarProperty) contManager.getResource(3)
-					.getData()).getWriteAccess(this);
-		RA_areaRestr = null;
-		if (contManager.getResource(4).getData() != null)
-			RA_areaRestr = ((ScalarProperty) contManager.getResource(4)
-					.getData()).getReadAccess(this);
-		RA_roadGrid = null;
-		if (contManager.getResource(5).getData() != null)
-			RA_roadGrid = ((ScalarProperty) contManager.getResource(5)
-					.getData()).getReadAccess(this);
-		RA_slopeGrid = null;
-		if (contManager.getResource(6).getData() != null)
-			RA_slopeGrid = ((ScalarProperty) contManager.getResource(6)
-					.getData()).getReadAccess(this);
-		RA_referenceGrid = null;
-		if(contManager.getResource(7).getData() != null)
-			RA_referenceGrid = ((ScalarProperty) contManager.getResource(7)
-					.getData()).getReadAccess(this);
-		RA_spreadStart = null;
-		if (contManager.getResource(8).getData() != null)
-			RA_spreadStart = ((ScalarProperty) contManager.getResource(8).getData())
-					.getReadAccess(this);
-		RA_spreadStep = null;
-		if (contManager.getResource(9).getData() != null)
-			RA_spreadStep = ((ScalarProperty) contManager.getResource(9).getData())
-					.getReadAccess(this);
-		RA_spreadEnd = null;
-		if (contManager.getResource(10).getData() != null)
-			RA_spreadEnd = ((ScalarProperty) contManager.getResource(10).getData())
-					.getReadAccess(this);
-		RA_dispStart = null;
-		if (contManager.getResource(11).getData() != null)
-			RA_dispStart = ((ScalarProperty) contManager.getResource(11).getData())
-					.getReadAccess(this);
-		RA_dispStep = null;
-		if (contManager.getResource(12).getData() != null)
-			RA_dispStep = ((ScalarProperty) contManager.getResource(12).getData())
-					.getReadAccess(this);
-		RA_dispEnd = null;
-		if (contManager.getResource(13).getData() != null)
-			RA_dispEnd = ((ScalarProperty) contManager.getResource(13).getData())
-					.getReadAccess(this);
-		RA_breedStart = null;
-		if (contManager.getResource(14).getData() != null)
-			RA_breedStart = ((ScalarProperty) contManager.getResource(14).getData())
-					.getReadAccess(this);
-		RA_breedStep = null;
-		if (contManager.getResource(15).getData() != null)
-			RA_breedStep = ((ScalarProperty) contManager.getResource(15).getData())
-					.getReadAccess(this);
-		RA_breedEnd = null;
-		if (contManager.getResource(16).getData() != null)
-			RA_breedEnd = ((ScalarProperty) contManager.getResource(16).getData())
-					.getReadAccess(this);
-		RA_roadGravityStart = null;
-		if (contManager.getResource(17).getData() != null)
-			RA_roadGravityStart = ((ScalarProperty) contManager.getResource(17).getData())
-					.getReadAccess(this);
-		RA_roadGravityStep = null;
-		if (contManager.getResource(18).getData() != null)
-			RA_roadGravityStep = ((ScalarProperty) contManager.getResource(18).getData())
-					.getReadAccess(this);
-		RA_roadGravityEnd = null;
-		if (contManager.getResource(19).getData() != null)
-			RA_roadGravityEnd = ((ScalarProperty) contManager.getResource(19).getData())
-					.getReadAccess(this);
-		RA_slopeStart = null;
-		if (contManager.getResource(20).getData() != null)
-			RA_slopeStart = ((ScalarProperty) contManager.getResource(20).getData())
-					.getReadAccess(this);
-		RA_slopeStep = null;
-		if (contManager.getResource(21).getData() != null)
-			RA_slopeStep = ((ScalarProperty) contManager.getResource(21).getData())
-					.getReadAccess(this);
-		RA_slopeEnd = null;
-		if (contManager.getResource(22).getData() != null)
-			RA_slopeEnd = ((ScalarProperty) contManager.getResource(22).getData())
-					.getReadAccess(this);
-		RA_criticalSlope = null;
-		if (contManager.getResource(23).getData() != null)
-			RA_criticalSlope = ((ScalarProperty) contManager.getResource(23).getData())
-					.getReadAccess(this);
-		WA_outResults = null;
-		if (contManager.getResource(24).getData() != null)
-			WA_outResults = ((ListProperty) contManager.getResource(24)
-					.getData()).getWriteAccess(this);
+		super.performModelInit();
+		this.contManager = (UrbanGrowthModelCalibrationSelfModificationContentManager) super.contManager;
+	
 		RA_roadGravSens = null;
-		if (contManager.getResource(25).getData() != null)
-			RA_roadGravSens = ((ScalarProperty) contManager.getResource(25).getData())
+		if (contManager.getResource(27).getData() != null)
+			RA_roadGravSens = ((ScalarProperty) contManager.getResource(27).getData())
 					.getReadAccess(this);
 		RA_slopeSens = null;
-		if (contManager.getResource(26).getData() != null)
-			RA_slopeSens = ((ScalarProperty) contManager.getResource(26).getData())
+		if (contManager.getResource(28).getData() != null)
+			RA_slopeSens = ((ScalarProperty) contManager.getResource(28).getData())
 					.getReadAccess(this);
 		RA_criticalLow = null;
-		if (contManager.getResource(27).getData() != null)
-			RA_criticalLow = ((ScalarProperty) contManager.getResource(27).getData())
+		if (contManager.getResource(29).getData() != null)
+			RA_criticalLow = ((ScalarProperty) contManager.getResource(29).getData())
 					.getReadAccess(this);
 		RA_criticalHigh = null;
-		if (contManager.getResource(28).getData() != null)
-			RA_criticalHigh = ((ScalarProperty) contManager.getResource(28).getData())
+		if (contManager.getResource(30).getData() != null)
+			RA_criticalHigh = ((ScalarProperty) contManager.getResource(30).getData())
 					.getReadAccess(this);
 		RA_Boom = null;
-		if (contManager.getResource(29).getData() != null)
-			RA_Boom = ((ScalarProperty) contManager.getResource(29).getData())
+		if (contManager.getResource(31).getData() != null)
+			RA_Boom = ((ScalarProperty) contManager.getResource(31).getData())
 					.getReadAccess(this);
 		RA_Bust = null;
-		if (contManager.getResource(30).getData() != null)
-			RA_Bust = ((ScalarProperty) contManager.getResource(30).getData())
+		if (contManager.getResource(32).getData() != null)
+			RA_Bust = ((ScalarProperty) contManager.getResource(32).getData())
 					.getReadAccess(this);
 		
-		// Variablen belegen mit denen gearbeitet wird
-		steps = RA_steps.getValueAsInt();
-		MonteCarlo = RA_MonteCarlo.getValueAsInt();
-		inputGrid = (WritableGrid) RA_inputGrid.getValue();
-		outputGrid = (WritableGrid) WA_outputGrid.getValue();
-		areaRestr = (WritableGrid) RA_areaRestr.getValue();
-		
-		//this.stepCount = steps.getValueAsInt();
-		stepCount 		= 1;
-	    spreadStart  	= RA_spreadStart.getValueAsDouble();
-	    spreadStep  	= RA_spreadStep.getValueAsDouble();
-	    spreadEnd  		= RA_spreadEnd.getValueAsDouble();
-	    dispStart		= RA_dispStart.getValueAsDouble();
-	    dispStep		= RA_dispStep.getValueAsDouble();
-	    dispEnd			= RA_dispEnd.getValueAsDouble();
-	    breedStart		= RA_breedStart.getValueAsDouble();
-	    breedStep		= RA_breedStep.getValueAsDouble();
-	    breedEnd		= RA_breedEnd.getValueAsDouble();
-	    roadGravityStart= RA_roadGravityStart.getValueAsDouble();
-	    roadGravityStep = RA_roadGravityStep.getValueAsDouble();
-	    roadGravityEnd 	= RA_roadGravityEnd.getValueAsDouble();
-	    slopeStart		= RA_slopeStart.getValueAsDouble();
-	    slopeStep		= RA_slopeStep.getValueAsDouble();
-	    slopeEnd		= RA_slopeEnd.getValueAsDouble();
-	    criticalSlope 	= RA_criticalSlope.getValueAsDouble();	
-	    roadGrid 		= (WritableGrid) RA_roadGrid.getValue();
-	    slopeGrid 		= (WritableGrid) RA_slopeGrid.getValue();
-	    referenceGrid 	= (WritableGrid) RA_referenceGrid.getValue();
-		outResults 		= WA_outResults;
+		// Assign variables to work with
 		roadGravSens = RA_roadGravSens.getValueAsDouble();
 	    slopeSens = RA_slopeSens.getValueAsDouble();
 	    criticalLow = RA_criticalLow.getValueAsDouble();
 	    criticalHigh = RA_criticalHigh.getValueAsDouble();
 	    boom = RA_Boom.getValueAsDouble();
 	    bust = RA_Bust.getValueAsDouble();
-
-		int startAnz = 0;
-		for (int i = 0; i < inputGrid.getWidth();i++ ) {
-			for (int ii = 0; ii < inputGrid.getHeight(); ii++ ) {
-				//if (inputGrid.getRasterSampleAsFloat(i,ii) == 1f);
-				float val = inputGrid.getRasterSampleAsFloat(i,ii);
-				if (val == 1.0 ) {
-					val = 1f;
-					startAnz++;
-				}
-					else val = 0f;
-				
-				inputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
-				outputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
-			}
-		}
-		
+	    
+		//Calculate total amount of pixels and number of excluded pixels
 		for (int x = 0; x < inputGrid.getWidth();x++ ) 
 			for (int y = 0; y < inputGrid.getHeight(); y++ ) {
 				if ( x < inputGrid.getMinX() || y < inputGrid.getMinY() || x > inputGrid.getMinX()+inputGrid.getWidth()-1 || y > inputGrid.getMinY()+inputGrid.getHeight()-1 ||
-			            Float.isNaN(outputGrid.getRasterSampleAsFloat(x,y)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
+			            Float.isNaN(outputGrid.getRasterSampleAsFloat(x,y)) ) //ignore neighbor, if outside the raster
 			             continue;
 				totalPixels++;
 				if (areaRestr.getRasterSampleAsFloat(x,y) != 0 && !Float.isNaN(areaRestr.getRasterSampleAsFloat(x,y)))
-		        	//continue;	//wenn in Area Restriction oder wenn schon Siedlung da ist, mach weiter
-				//if (inputGrid.getRasterSampleAsFloat(i,ii) == 1f);
 					excldCount++;
 			}
-		
 	}
 
 	/**
 	* like in every model: frees the resources
 	 */
 	public void performModelDispose() {
-
-		// Ressourcen wieder freigeben
-		releaseAccess(RA_steps);
-		releaseAccess(RA_MonteCarlo);
-		releaseAccess(RA_inputGrid);
-		releaseAccess(WA_outputGrid);
-		releaseAccess(RA_areaRestr);
-		releaseAccess(RA_spreadStart);
-		releaseAccess(RA_spreadStep);
-		releaseAccess(RA_spreadEnd);
-		releaseAccess(RA_dispStart);
-		releaseAccess(RA_dispStep);
-		releaseAccess(RA_dispEnd);
-		releaseAccess(RA_breedStart);
-		releaseAccess(RA_breedStep);
-		releaseAccess(RA_breedEnd);
-		releaseAccess(RA_roadGravityStart);
-		releaseAccess(RA_roadGravityStep);
-		releaseAccess(RA_roadGravityEnd);
-		releaseAccess(RA_slopeStart);
-		releaseAccess(RA_slopeStep);
-		releaseAccess(RA_slopeEnd);
-		releaseAccess(RA_criticalSlope);
-		releaseAccess(RA_roadGrid);
-		releaseAccess(RA_slopeGrid);
-		releaseAccess(WA_outResults);
+		super.performModelDispose();
+		//free resources
 		releaseAccess(RA_roadGravSens);
 		releaseAccess(RA_slopeSens);
 		releaseAccess(RA_criticalLow);
@@ -355,40 +136,42 @@
 		releaseAccess(RA_Bust);
 	}
 
-	
+	/**
+	 * The main method of the Urban Growth Model. For a detailed description refer to the performModelStep in 
+	 * {@link UrbanGrowthModel UrbanGrowthModel} and {@link UrbanGrowthModelCalibration Urban Growth Model Calibration}. 
+	 * The difference to the plain UGM Calibration model is the Self Modification of several coefficients.
+	 */
 	public void performModelStep(int stepNo) {
-		
-		/**
-		 * Ermitteln der maximalen Hangneigung
-		 */
-		int slopeMax = 0;
-		for (int s = 0; s < inputGrid.getWidth();s++){
-			for(int ss = 0; ss < inputGrid.getHeight();ss++){
-				float slopeVal = slopeGrid.getRasterSampleAsFloat(s,ss);
-				if (slopeVal > slopeMax){
-					slopeMax = (int) slopeVal;		//Maximale Hangneigung im Slope-Bild
-				} 
-			}
-		}
-		
-		/**
-		 * Definition von Variablen, die als Output des gesamten Kalibrierungsdurchlaufs benötigt werden
-		 */
-		float MCtotalAgreementResult = 0f;
-		int ngrids = 0;
+
+		//Definition of variables needed in the whole model run
 		double slopeF = 0;
 		double spreadF = 0;
 		double dispF = 0;
 		double breedF = 0;
 		double roadGravityF = 0;
+		double growthRate = 0;
+		int thisYear = 0;
+		int roadCount = 0;
 		
-		/**
-		 * Start des gesamten Kalibrierungsdurchlaufs:
-		 * 1. Für jeden Slope-Wert zwischen Start und End...
-		 * 2. Für jeden Spread-Wert zwischen Start und End...
-		 * 3. Für jeden Dispersion-Wert zwischen Start und End...
-		 * 4. Für jeden Breed-Wert zwischen Start und End...
-		 */
+		//Definition of variables needed in the whole model run
+		long localStartTime = System.currentTimeMillis(); //time measure
+		Float actUrb = null;	//urban cell in the raster
+		int totalSteps = 0;
+		int runs = 0;		
+	
+		//raster dimensions
+		areaMinX = inputGrid.getMinX();
+		areaMinY = inputGrid.getMinY();
+		areaMaxX = inputGrid.getMinX() + inputGrid.getWidth() - 1;
+		areaMaxY = inputGrid.getMinY() + inputGrid.getHeight() - 1;
+		areaWidth = inputGrid.getWidth();
+		areaHeight = inputGrid.getHeight();
+			
+		// Iterate the calibration for:
+		// 1. every slope value between start and end...
+		// 2. every spread value between start und end...
+		// 3. every dispersion value between start und end...
+		// 4. every breed value between start and end...
 		
 		for(int slope = (int)slopeStart;slope <= (int)slopeEnd; slope = slope+(int)slopeStep){
 			for(int spread = (int)spreadStart; spread <= (int)spreadEnd; spread = spread+(int)spreadStep){
@@ -396,537 +179,152 @@
 					for(int breed = (int)breedStart; breed <= (int)breedEnd+1; breed = breed+(int)breedStep){
 						for(int roadGravity = (int)roadGravityStart; roadGravity <=(int)roadGravityEnd; roadGravity = roadGravity+(int)roadGravityStep){
 														
-							/**
-							 * An dieser Stelle beginnt der eigentliche Modellalgorithmus des UrbanGrowth-Modells.
-							 * Da bei der Kalibrierung das Modell durch jede mögliche Kombination an Werten durchiteriert,
-							 * wird der Algorithmus x-mal durchlaufen.
-							 * Da häufig Zufallswerte in das Modell eingebaut sind, ist es sinnvoll jeden Iterationsschritt mehrfach durchzuführen
-							 * und die Ergebnisse zu mitteln. Dies geschieht "Monte-Carlo"-mal (Wert wird in Modellparametern angegeben).
-							 * Das bedeutet, dass der Modellalgorithmus zusätzlich in die folgende for-Schleife eingebunden ist.
-							 */
-							float pos1 = 0;	//das hier ist nicht optimal gelöst. Für jede Stelle im Result Array eine eigene Variable definiert, die später ausgelesen wird. Habs nur auf die Schnelle nicht besser hinbekommen
-							float pos2 = 0;
-							float pos3 = 0;
-							float pos4 = 0;
-							float pos5 = 0;
-							float pos6 = 0;
-							float pos7 = 0;
-							float pos8 = 0;
-							float pos9 = 0;
-							float pos10 = 0;
-							float pos11 = 0;
-							float pos12 = 0;
-							for(int MC = 1; MC <= MonteCarlo; MC++){	//führe den Modellalgorithmus 1 bis MC-mal durch
-								RasterUtil.copyInto(inputGrid, outputGrid);		//starte dabei aber mit dem Eingabebild (das Ausgabebild verändert sich nach jedem Modellschritt!!)
-//								statusOut.println("Starting step " + stepNo + "...");
-//								statusOut.println(steps);
+							//Here the original model algorithm starts. By calibrating the model each parameter combination
+							//is being iterated, so the algorithm is performed n-times. Because a lot of random values are
+							// in the model, each step should be performed a Monte Carlo number of times. The results are 
+							// averaged at the end of the algorithm. 
+							//
+							runs++;
+							mrvTempResultArray = new float[numSteps+2];
+							finalArray = new float[numSteps+2];
+
+							
+														
+							for(int MC = 1; MC <= MonteCarlo; MC++){	//perform the model algoith 1-MC times
+								statusOut.println("Performing "+MonteCarlo+" Monte Carlo Iterations (MC: "+MC+")");
+								totalSteps++;
 								
-								//Koeffizienten werden für jeden Iterationsschritt zurückgesetzt. Innerhalb eines MC-Laufs können die Koeffizienten modifiziert werden 
-								slopeF = (double)slope;		//slopeF erhält am Beginn der Schleife den Wert von slope und kann innerhalb der Schleife modifiziert werden
-								spreadF = (double)spread;		//spreadF erhält am Beginn der Schleife den Wert von spread und kann innerhalb der Schleife modifiziert werden
-								dispF = (double) disp;		//dispF erhält am Beginn der Schleife den Wert von disp und kann innerhalb der Schleife modifiziert werden
-								breedF = (double)breed;	//breedF erhält am Beginn der Schleife den Wert von breed und kann innerhalb der Schleife modifiziert werden
-								roadGravityF = (double) roadGravity;	//roadGravityF erhält am Beginn der Schleife den Wert von roadGravity und kann innerhalb der Schleife modifiziert werden
+								//In every Iteration the coefficients are set to their defined values. Within an iteration those coefficients can be modified in every step. 
+								slopeF = (double)slope;		//slopeF is slope at the beginning of the loop and is modified within the loop.
+								spreadF = (double)spread;		//spreadF is spread at the beginning of the loop and is modified within the loop.
+								dispF = (double) disp;		//dispF is disp at the beginning of the loop and is modified within the loop.
+								breedF = (double)breed;	//breedF is breed at the beginning of the loop and is modified within the loop.
+								roadGravityF = (double) roadGravity;	//roadGravityF is roadGravity at the beginning of the loop and is modified within the loop.
 								
 								/**
-								 * Der Modelllauf muss so oft wiederholt werden, wie Jahre für den Kalibrierungsmodus angegeben wurden.
-								 * Für die anschließende Bewertung der Ergebnisse zählt nur das Bild des Schlussjahres
+								 * The model run is being performed for every time step. For the final evaluation 
+								 * only the image of the final step is needed.
 								 */
-									for(int timeSteps = 1;timeSteps <=steps;timeSteps++){	
-										//Dimensionen des Rasters werden definiert
-										int areaMinX = outputGrid.getMinX();								
-										int areaMinY = outputGrid.getMinY();
-										int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
-										int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
-										int areaWidth = outputGrid.getWidth();
-										int areaHeight = outputGrid.getHeight();
+									for(int timeSteps = 1;timeSteps <=years;timeSteps++){
+									
+										statusOut.println("Year "+timeSteps);
+										boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+
+										//recalculate the slope values
+										slopeMax = getSlopeMax();
+										int MaxSlopeResistance = 100;
+										double exp = getSlopeExp(slopeF,MaxSlopeResistance);	//calculate the exp value based on the actual slope
+										slopeLUT = getSlopeLookup(slopeMax,exp,criticalSlope);	//generate the lookup-table based on the actual exp-value
+										//statusOut.println("SlopeMax, slope exp: "+slopeMax+", "+exp);
 										
-										//weitere Variablendefinitionen
-										long localStartTime = System.currentTimeMillis();
-										boolean anyBodyAlive = false;
-		
-										boolean[][] tmpGrid = new boolean[outputGrid.getWidth()][outputGrid.getHeight()];	//temporäres Raster, in das true und false geschrieben wird, je nachdem ob Siedlung nach Modellschritt vorhanden ist oder nicht
-										Float actUrb = null;
-		
-										int nbX = 0; // X-Koordinate einer Nachbarzelle
-										int nbY = 0; // Y-Koordinate einer Nachbarzelle
-										int[] nbCell = null;
-	    
-										int anzSpreadTreffer = 0;
-										int anzDispTreffer = 0;
-										int anzBreedTreffer = 0;
-										int anzGesamtTreffer = 0;
-										int anzRoadTreffer = 0;
-										double growthRate = 0;
-										int thisYear = 0;
-										int roadCount = 0;
-											
-										// Variablen, die für den DISPERSION Bereich benötigt werden
-										double disp_value = Math.round((dispF*0.005)* Math.sqrt(Math.pow(outputGrid.getWidth(), 2)+(Math.pow(outputGrid.getHeight(), 2))));
-										int dispRandX = 0;
-										int dispRandY = 0;
-										float slopeRandDisp = 0;
-		
-										// Variablen, die für den ROAD GRAVITY Bereich benötigt werden
-										double max_RG_value = 100.0;
-										double rg_value = Math.round((roadGravityF/max_RG_value)*((areaWidth + areaHeight)/16)); 
-										double max_search_index = Math.round(4*((int)rg_value*(1+(int)rg_value)));
-//										statusOut.println("RG-Value:"+rg_value);
-//										statusOut.println("Max-SearchIndex"+max_search_index);
-		
-										//Variablendefinitionen bzgl. Slope-Berechnungen
+										double disp_value = Math.round((dispF*0.005)* Math.sqrt(Math.pow(inputGrid.getWidth(), 2)+(Math.pow(inputGrid.getHeight(), 2))));
+										max_RG_value = 100.0;			//Maximum possible road gravity value
+										double rg_value = Math.round((roadGravityF/max_RG_value)*((areaWidth + areaHeight)/16));
+										//statusOut.println("RG"+roadGravityF+" / MaxRG:"+max_RG_value+" * (Width"+areaWidth+" + areaHeight"+areaHeight+") / 16");
 										
-										slopeLUT = new HashMap<Number,Number>();	//Definition eines Lookup-Tables (HashMap --> jeder Indexwert bekommt einen Wert zugewiesen)
-										int MaxSlopeResistance = 100;				//Hangneigung kann maximal 100% betragen	
-										double exp = 0.0;							
-										exp = (slopeF / (MaxSlopeResistance / 2));
-										double[] lookup = new double[slopeMax+1];	//ein Array, das slopeMax+1 Stellen lang ist (+1, da Arrays mit der Zahl 0 beginnen)
-										Number key = 0;								//die Zahl key nimmt den Wert des Index für den Lookup-Table an
-									
-										//Aufbau des Lookup-Tables
-										for (int i = 0;i <= slopeMax;i++){							//Für jede Hangneigung zwischen 0% und dem maximal im Bild vorhandenen Wert
-											if (i <= criticalSlope){								//der kleiner als criticalSlope ist
-												double val = (criticalSlope - i) / criticalSlope;	//berechne den Wert val
-												lookup[i] = 1 - Math.pow(val,exp);					//und füge den Wert val hoch exp an der Stelle i in das Array lookup ein
-												key = i;											//Index-Wert ist key
-											} else{													//Ist der Wert größer als criticalSlope
-												lookup[i] = 1;										//wird der Wert 1 in das Array eingefügt
-												key = i;										
-											}
-											slopeLUT.put(key,lookup[i]);							//put platziert die Werte key und den entsprechenden Wert aus dem Array lookup in die HashMap-Tabelle
-//											statusOut.println(slopeLUT.get(key));
-										}	
+										max_search_index = Math.round(4*((int)rg_value*(1+(int)rg_value)));	//area in which to look for a road cell
+										//statusOut.println("MaxSearchIndex: "+max_search_index);
 										
 										/*****************************************************************
-										 * DISPERSION and BREED
+										 * DISPERSION and BREED (Growth Phase 1 and 2)
 										 *****************************************************************/
+										boolean[][] tmpGridDisp = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+										tmpGridDisp = DispersionGrowth(disp_value,breedF);	//calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
+										int anzDispBreed = 0;	//number of cells urbanized by Dispersion and Breed
+										for (int x = 0; x < inputGrid.getWidth();x++)
+											for(int y = 0; y < inputGrid.getHeight();y++){
+												int X = inputGrid.getMinX() + x;
+												int Y = inputGrid.getMinY() + y;
+												if (tmpGridDisp[X][Y]==true){
+													anzDispBreed++;
+													tmpGrid[X][Y] = true;	//write the temporary Dispersion and Breed Cells to the overall temporary Cell array
+												}		
+											}
+										statusOut.println("Number of Spontaneous and New Spreading Center Cells: "+anzDispBreed);
+										writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
 										
-										//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
-										//-->Beginn einer do-while-Schleife
-										int p = 0;	
-										do{
-											dispRandX = Math.round((float) Math.random()*areaWidth);											//Zufallsposition in X-Richtung
-											dispRandY = Math.round((float) Math.random()*areaHeight);											//Zufallsposition in Y-Richtung
-											if ( dispRandX < areaMinX || dispRandY < areaMinY || dispRandX > areaMaxX || dispRandY > areaMaxY ||
-													Float.isNaN(outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY)) ) 						//wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-												continue;
-											if (areaRestr.getRasterSampleAsFloat(dispRandX,dispRandY) != 0 || outputGrid.getRasterSampleAsFloat(dispRandX,dispRandY) == 1)
-												continue;																						//wenn in Area Restriction oder wenn schon Siedlung da ist, mach weiter
-											slopeRandDisp = (float) Math.random();																//Zufallszahl zum Abgleich mit Slope-Koeffizient
-											int getSlope = (int) slopeGrid.getRasterSampleAsFloat(dispRandX,dispRandY);							//holt sich den Slope-Wert aus dem Slope-Raster
-											Double doubleObj = (Double)slopeLUT.get(getSlope);													//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-											double slopeDouble = doubleObj.doubleValue();														//konvertiert Double-Objekt in double-Wert
-	//	      								statusOut.println(getSlope+","+slopeDouble+"----Random: "+slopeRandDisp);
-											if(slopeDouble < slopeRandDisp){			//wenn der Slope-Wert kleiner als der Wert der Zufallszahl ist
-												tmpGrid[dispRandX][dispRandY] = true;	//wird "true" ins temporäre Raster geschrieben (neue Siedlung entsteht!!)
-												anzDispTreffer++;						//Anzahl der Disp-Treffer wird hochgezählt
-												
-												//
-												//hier beginnt der BREED Bereich
-												//
-												//Variablendefinitionen
-												float breedRnd = (float) Math.random()*100;
-												int nbBreedX  = 0;
-												int nbBreedY  = 0;
-												int breedNb	  = 0;
-												float NbValue = 0f;
-												if (tmpGrid[dispRandX][dispRandY] == true && breedRnd < breedF)	//wenn durch DISPERSION neue Zellen entstanden sind UND der Breed-Zufallswert kleiner als der Breed-Wert ist
-													breedNb = calculateNeighbors(dispRandX,dispRandY,NbValue);	//werden die Nachbarzellen dieser neuen Zellen gezählt, und zwar alle, die zur weiteren Besiedlung zur Verfügung stehen (--> Funktion calculateNeighbors)
-		        			       
-												int RNBreed1 = 0;
-												int RNBreed2 = 0;
-												float RNBreedSlope = 0f;
-		        
-												if (breedNb >= 2 && tmpGrid[dispRandX][dispRandY] == true){		//sind mehr als 2 Nachbarzellen verfügbar und die Koordinate X/Y true...
-													int anzBreedTemp = 0;
-													int[] nbPossibleBreedUrban = null;
-													RNBreed1 = 1 + Math.round((float)Math.random()*(breedNb-1));	//werden 2 Zufallszahlen zwischen 1 und breedNb erzeugt
-													RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));
-													if (RNBreed2 == RNBreed1)										//falls beide Zufallszahlen den gleichen Wert haben sollten, wird die zweite Zahl nochmal erzeugt
-														RNBreed2 = 1 + Math.round((float)Math.random()*(breedNb-1));	
-													for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){	//die Nachbarn jeder Zelle müssen nochmal durchgezählt werden, um zu bestimmen, welche per Zufallswert in Siedlung umgewandelt werden soll
-														nbBreedX = dispRandX+NEIGHBOR[cellBreed][0];
-														nbBreedY = dispRandY+NEIGHBOR[cellBreed][1];
-														if ( nbBreedX < areaMinX || nbBreedY < areaMinY || nbBreedX > areaMaxX || nbBreedY > areaMaxY ||
-																Float.isNaN(outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-															continue;
-														if (areaRestr.getRasterSampleAsFloat(nbBreedX,nbBreedY) != 0)
-															continue;
-														RNBreedSlope = (float)Math.random();	 										//Zufallszahl zum Abgleich mit Slope-Koeffizient
-														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt sich den Slope-Wert aus dem Slope-Raster
-														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);							//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-														double slopeDoubleNb = doubleObjNb.doubleValue();								//konvertiert Double-Objekt in double-Wert
-														float breedSample = outputGrid.getRasterSampleAsFloat(nbBreedX,nbBreedY);		//holt den Wert aus dem Output-Raster
-														if (breedSample == 0f){													//ist der Wert aus dem Output-Raster 0
-															anzBreedTemp++;														//wird die Zahl der zur Verfügung stehenden Zellen hochgezählt
-															nbPossibleBreedUrban = new int[] {nbBreedX,nbBreedY,anzBreedTemp};	//und die Nummer und Koordinaten der jeweiligen Zellen in ein Array geschrieben 
-															if (nbPossibleBreedUrban[2] == RNBreed1 || nbPossibleBreedUrban[2] == RNBreed2 && slopeDoubleNb < RNBreedSlope){	//entspricht die Nummer einer der zuvor erstellten Zufallswerte...
-																tmpGrid[nbBreedX][nbBreedY] = true;								//wird in das temporäre Raster "true" geschrieben (--> neue Siedlung durch BREED entstanden!!)
-																anzBreedTreffer++;												//die Anzahl der BREED-Treffer wird gezählt
-															}	
-														}
-													}
-												} 
-											} p++;		//der Wert p wird hochgezählt, bis der Disp-Wert erreicht ist
-		       
-										} while (p < disp_value);	//while, statt for-Schleife, da Überprüfung erst am Ende vorgenommen werden kann
-																	//am Anfang der Schleife ist noch nicht klar, ob alle Pixel verteilt werden können
-																	//da ein Teil in Ausschlussflächen etc. landen würde
-										//ENDE DISPERSION UND BREED WACHSTUM
-	
 										/*********************************************************************
 										 * EDGE
 										 *********************************************************************/
-		
-										//iterate over all cells
-										for (int x = 0; x < outputGrid.getWidth(); x++)
-											for (int y = 0; y < outputGrid.getHeight(); y++) {		//für jede Zelle in x/y-Richtung
-												
-												//Dimensionen des Rasters
-												int areaMinXadd = areaMinX + x;								
-												int areaMinYadd = areaMinY + y;
-												
-												//Variablendefinitionen
-												int anzNachbarn = 0;
-												int noNachbarn = 0;
-				
-												for (int nbCellIdx = 0; nbCellIdx < NEIGHBOR.length; nbCellIdx++) {	//zählt alle Nachbarn jeder Rasterzelle durch
-													checkBreakingCommands();
-													nbX = x+NEIGHBOR[nbCellIdx][0];		//Nachbarschaft der Zellen
-													nbY = y+NEIGHBOR[nbCellIdx][1];
-													nbCell = new int[] {nbX,nbY};		//jede Nachbarzelle
-													if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
-															Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-														continue;
-													if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
-														continue;
-													float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
-													if (rasterSample > 0f)		//ist Nachbarzelle urban (1), wird sie als anzNachbarn gezählt
-														anzNachbarn++;
-													if (rasterSample == 0f)		//ist sie nicht urban (0), wird sie als noNachbarn gezählt		
-														noNachbarn++;
-												}
-				
-												boolean lebt = outputGrid.getRasterSampleAsFloat(areaMinXadd , areaMinYadd ) > 0f;	//eine Zelle lebt, wenn sie 1 ist
-				
-												//hier ist die Abfrage wieviele Nachbarzellen am Leben sind
-												//daraus ergibt sich, ob im tmpGrid die entsprechende Zelle
-												//true oder false ist
-				
-												float SpR = (float) Math.random()*100;						//eine Zufallszahl zwischen 0 und 1
-												int RN = 0; 	//hier wird eine Integer-Zufallszahl reingeschrieben
-				
-												if (lebt && (anzNachbarn>=2) && (SpR < spreadF) && (noNachbarn >=1)) {	//wenn eine Zelle lebt, mindestens 2 lebende Nachbarzellen hat, der Spread-Koeffizient größer als die für die Zelle berechnete Zufallszahl und mindestens einen nicht lebenden Nachbarn hat
-													
-													//Variablendefinitionen
-													int anzTemp = 0;
-													int[] nbPossibleUrban = null;
-													RN = 1 + Math.round((float)Math.random()*(noNachbarn-1));
-													float RNEdgeSlope = 0;
-													int nbUrbanX = 0;
-													int nbUrbanY = 0;
-													
-													for (int nbCellChange = 0; nbCellChange < NEIGHBOR.length; nbCellChange++){	//dann starte eine Schleife
-														checkBreakingCommands();
-														nbX = x+NEIGHBOR[nbCellChange][0];
-														nbY = y+NEIGHBOR[nbCellChange][1];
-														if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
-																Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-															continue;
-														if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
-															continue;
-														RNEdgeSlope = (float)Math.random();									//Zufallszahl zum Abgleich mit Slope-Koeffizient
-														int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbX,nbY);	//holt sich den Slope-Wert aus dem Slope-Raster
-														Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);				//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-														double slopeDoubleNb = doubleObjNb.doubleValue();					//konvertiert Double-Objekt in double-Wert
-														float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);	//holt die Werte aus den jeweiligen Nachbarzellen
-														if (rasterSample == 0f){	//wenn der Wert 0 ist
-															anzTemp++;				//wird Anzahl der möglichen Zellen erhöht
-															nbPossibleUrban = new int[] {nbX,nbY,anzTemp};	//Koordinaten und Nummern dieser Zellen werden in Array geschrieben 
-															int urbanNbTemp = 0;
-															float NbValueEdge = 1f;
-															if (nbPossibleUrban[2] == RN){	//wenn Nummer im "PossibleUrban"-Array der Zufallszahl entspricht, die zwischen 1 und Anzahl der möglichen Zellen liegt...
-																							//damit die Städte nicht zu sehr "ausfransen" steht eine Zelle nur zur Umwandlung zur Verfügung, wenn auch sie mind. 2 urbane Nachbarn hat
-																urbanNbTemp = calculateNeighbors(nbX,nbY,NbValueEdge);
-																if (urbanNbTemp >= 2 && tmpGrid[nbX][nbY]==false && slopeDoubleNb < RNEdgeSlope){
-																	tmpGrid[nbX][nbY] = true;	//wird true ins temporäre Raster geschrieben
-																	anzSpreadTreffer++;			//und die Anzahl der Spread-Treffer gezählt
-																}
-															} 
-														}
-														nbCell = new int[] {nbX,nbY,(int) rasterSample};	//die Nummer und Koordinaten der jeweiligen Zellen wird in ein Array geschrieben
-													}
-												}
-												if (anzNachbarn>0) anyBodyAlive = true;		
-											}	//ENDE EDGE-WACHSTUM
-		
+										boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+										tmpGridSpread = EdgeGrowth(spread);	//calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
+										int anzSpread = 0;	//number of cells urbanized by Spread
+										for (int x = 0; x < inputGrid.getWidth();x++)
+											for(int y = 0; y < inputGrid.getHeight();y++){
+												int X = inputGrid.getMinX() + x;
+												int Y = inputGrid.getMinY() + y;
+												if (tmpGridSpread[X][Y]==true){
+													anzSpread++;
+													tmpGrid[X][Y] = true;	//write the temporary Spread cells to the overall temporary Cell array
+												}		
+											}
+										statusOut.println("Number of Edge Growth Cells: "+anzSpread);
+										writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
+									
 										/*********************************************************************
 										 * ROAD
 										 *********************************************************************/
-										
-										//Variablendefinitionen
-										int anzGesamt = 0;
-										int[] cellValue = null;
-										int RSearchRoad = 0;
-										int r = 1;	//Verteile soviel neue Pixel zufällig in geeigneten Bereichen, bis disp_value erreicht ist
-										//Rectangle gridBounds = new Rectangle(0, 0, outputGrid.getWidth(), outputGrid.getHeight()); //ein Rechteck wird definiert
-		
-										//For-Schleife zählt alle als true markierten Zellen im Temp-Raster
-										for (int x = 0; x < outputGrid.getWidth();x++)
-											for(int y = 0; y < outputGrid.getHeight();y++){
-												int X = outputGrid.getMinX() + x;
-												int Y = outputGrid.getMinY() + y;
-												if (tmpGrid[X][Y]==true){
-													anzGesamt++;
+										boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+										statusOut.println("Start Road Growth...");
+										tmpGridRoad = RoadGrowth(tmpGrid,rg_value,breed,disp);	//calls the method "RoadGrowth" to perform the Road weighted growth
+										statusOut.println("Road things returned...");
+										int anzRoad = 0;	//number of cells urbanized by Road Growth
+										for (int x = 0; x < inputGrid.getWidth();x++)
+											for(int y = 0; y < inputGrid.getHeight();y++){
+												int X = inputGrid.getMinX() + x;
+												int Y = inputGrid.getMinY() + y;
+												if (tmpGridRoad[X][Y]==true){
+													anzRoad++;
+													tmpGrid[X][Y] = true;	//write the temporary Road Growth cells to the overall temporary Cell array
 												}		
 											}
-		
-										//Beginn einer do-while-Schleife
-										do{
-											//Variablendefinitionen
-											RSearchRoad = Math.round((float)Math.random()*anzGesamt);	//Zufallszahl zwischen 1 und Anzahl aller bisher neu hinzugekommener Pixel
-											int anzTruePixels = 0;
-											int roadNeighborhoodRange = 0;
-											int RSearchNbRoad = 0;
-												for (int x = 0; x < outputGrid.getWidth();x++){		//gesamtes Raster wird durchsucht
-													for(int y = 0; y < outputGrid.getHeight();y++){
-														int X = outputGrid.getMinX() + x;
-														int Y = outputGrid.getMinY() + y;
-														if (tmpGrid[X][Y]==true){
-															anzTruePixels++;		//wird true-Pixel gefunden, wird anzTruePixels hochgezählt
-															cellValue = new int[] {X,Y,anzTruePixels};	//und Koordinaten in Array geschrieben
-															int tempRoadCell[] = null;
-															int tempNbRoadCell[] = null;
-															if (cellValue[2] == RSearchRoad){	//eins der neu entstandenen Pixel wird nach Zufallsprinzip ausgewählt
-																//statusOut.println(cellValue[0]+","+cellValue[1]+","+cellValue[2]);
-																//statusOut.println(r+","+RSearchRoad);
-																r++;							//Anzahl der so gefundenen Zellen wird hochgezählt, bis Road-Koeffizient erreicht wird
-																//JETZT NACH STRAßE SUCHEN!!
-																float roadValue = roadGrid.getRasterSampleAsFloat(X,Y);	//An Koordinate X/Y wird Wert aus roadGrid geholt
-																//		statusOut.println(roadValue);
-																if (roadValue > 0.0){					//wenn Wert > 0 ist...
-																	tempRoadCell = new int[] {X,Y};		//wird an Koordinate X/Y eine temporäre Straßenzelle platziert (bzw. Koordinaten in Array geschrieben
-					//												statusOut.println("Strasse in Entfernung 0: "+tempRoadCell[0]+","+tempRoadCell[1]);
-																	int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],dispF);	//von dieser Koordinate aus wird ein Road-Walk gestartete (siehe Funktion roadWalk!!)
-																	if(nbCellNew != null){									//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
-																		tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;			//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
-					//													statusOut.println(nbCellNew.length);
-					//													statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
-					//													statusOut.println("++++++++++++++++++++++++++++++++++++++++");
-																		
-																		//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
-																		//nochmals ein "Breed" aus.
-																		
-																		//Variablendefinitionen
-																		float nbRoadBreed = 0f;
-																		int nbRoadBreedNeighbors = 0;
-																		nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);	//Nachbarzellen der neuen Zelle werden gezählt
-																		int RNRoadBreed1 = 0;
-																		int RNRoadBreed2 = 0;
-																		int nbRoadBreedX = 0;
-																		int nbRoadBreedY = 0;
-																		int anzRoadBreedTreffer = 0;
-							        
-																		if (nbRoadBreedNeighbors >= 2){	//sind mehr als 2 potenzielle Nachbarzellen verfügbar
-																			int anzBreedTemp = 0;
-																			int[] nbPossibleBreedUrban = null;
-																			RNRoadBreed1 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																			RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																			float RNRoadBreedSlope = 0f;
-																			if (RNRoadBreed2 == RNRoadBreed1)
-																				RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));	
-																			for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){
-																				nbRoadBreedX = nbCellNew[0]+NEIGHBOR[cellBreed][0];
-																				nbRoadBreedY = nbCellNew[1]+NEIGHBOR[cellBreed][1];
-																				if ( nbRoadBreedX < areaMinX || nbRoadBreedY < areaMinY || nbRoadBreedX > areaMaxX || nbRoadBreedY > areaMaxY ||
-																						Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																					continue;
-																				if (areaRestr.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY) != 0)
-																					continue;
-																				RNRoadBreedSlope = (float)Math.random();											//Zufallszahl zum Abgleich mit Slope-Koeffizient
-																				int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt sich den Slope-Wert aus dem Slope-Raster
-																				Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);								//holt den Slope-Wert aus dem Lookup-Table (get) und konvertiert in Double
-																				double slopeDoubleNb = doubleObjNb.doubleValue();									//konvertiert Double-Objekt in double-Wert
-																				float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);	//holt die Werte aus den jeweiligen Nachbarzellen
-																				if (breedSample == 0f){			//hat die Nachbarzelle den Wert 0 wird anzBreedTemp hochgezählt
-																					anzBreedTemp++;
-																					nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};		//und Koordinaten dieser Zelle in Array geschrieben
-																					if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){	//stimmt der Wert mit einer der beiden Zufallszahlen überein und ist laut Slope-Wert Besiedlung erlaubt...
-																						tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;					//..wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle erstellt!)
-																						anzRoadBreedTreffer++;										//Anzahl der durch Breed nach RoadWalk erzeugten Zellen wird hochgezählt
-																						anzRoadTreffer++;
-						//																statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
-																					}
-																				}
-																			}
-																		}
-																	} else{		//kommt nach Road-Walk nichts zurück...
-																		//	statusOut.println("Keine neue Zelle gefunden");
-																	}
-																//ist an der Stelle, an der eine neue Zelle entstanden war keine Straße, wird im Folgenden in ihrer Nähe danach gesucht...
-																} else{	
-																	
-																	int anzRoadNb = 0;
-								
-																	//HIER MIT FOR SCHLEIFE RECHTECK WACHSEN LASSEN!!!
-																	for (int roadSearch = 0; roadSearch <= rg_value; roadSearch++){		//vergrößere die Nachbarschaft, bis rg_value erreicht ist
-																		if (anzRoadNb > 0)		//höre auf, sobald Straße in der Nachbarschaft gefunden wurde
-																			continue;
-																		for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++)
-																			for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){
-																				//if (gridBounds.contains(nbRoadCellsX, nbRoadCellsY))
-																				if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
-																						Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																					continue;
-																			//	if (areaRestr.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY) != 0)
-																			//		continue;
-																				float roadValueNb = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY);	//hole Wert aus Straßenraster
-																				if (roadValueNb > 0f)	//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNb hoch
-																					anzRoadNb++;
-																				
-																				//statusOut.println("Strasse in Entfernung 1: "+anzRoadNb+","+nbRoadCellsX+","+nbRoadCellsY);
-																			}
-																		roadNeighborhoodRange++;	
-																		RSearchNbRoad = Math.round((float)Math.random()*anzRoadNb);
-																		//statusOut.println("--> Zyklus "+roadNeighborhoodRange+"Nachbarn: "+anzRoadNb);
-																		//statusOut.println(RSearchNbRoad);
-																		int anzTempRoadNb = 0;
-																		for (int nbRoadCellsX = X - roadNeighborhoodRange; nbRoadCellsX <= X + roadNeighborhoodRange; nbRoadCellsX++){
-																			for (int nbRoadCellsY = Y - roadNeighborhoodRange; nbRoadCellsY <= Y + roadNeighborhoodRange; nbRoadCellsY++){
-						        	//											statusOut.println("TEST-ROAD: "+nbRoadCellsX+","+nbRoadCellsY);
-											//									if (gridBounds.contains(nbRoadCellsX, nbRoadCellsY))
-																				if ( nbRoadCellsX < areaMinX || nbRoadCellsY < areaMinY || nbRoadCellsX > areaMaxX || nbRoadCellsY > areaMaxY ||
-																						Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																					continue;
-																	//			if (areaRestr.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY) != 0)
-																	//				continue;
-																				float roadValueNbTemp = roadGrid.getRasterSampleAsFloat(nbRoadCellsX,nbRoadCellsY);	//hole Wert aus Straßenraster
-																				if (roadValueNbTemp > 0f){									//ist der Wert im Straßen-Raster > 0 zähle den Wert anzRoadNbTemp hoch
-																					anzTempRoadNb++;
-																					tempNbRoadCell = new int[] {nbRoadCellsX,nbRoadCellsY,anzTempRoadNb};	//schreibe die Koordinaten in ein Array
-																					if (tempNbRoadCell[2]==RSearchNbRoad){					//Wenn der Wert im Array dem vorher definierten Zufallswert entspricht...
-																						//statusOut.println("Treffer: "+tempNbRoadCell[0]+","+tempNbRoadCell[1]+","+tempNbRoadCell[2]);
-																						tempRoadCell = tempNbRoadCell;						//...wird die temporäre Straßenzelle an diese Position verschoben
-											//											statusOut.println("Strasse in Entfernung "+roadSearch+": "+tempRoadCell[0]+","+tempRoadCell[1]+","+tempRoadCell[2]);
-																						int nbCellNew[] = roadWalk(tempRoadCell[0],tempRoadCell[1],dispF);	//von dort aus wird ein Road-Walk durchgeführt (--> siehe Funktion roadWalk!)
-																						if(nbCellNew != null){												//kommt nach roadWalk ein Wert zurück (d.h. wurde potenziell zu besiedelndes Pixel gefunden)...
-																							tmpGrid[nbCellNew[0]][nbCellNew[1]] = true;						//wird "true" ins temporäre Raster geschrieben (neue Siedlungszelle gefunden!!)
-//																							statusOut.println(nbCellNew.length);
-//																							statusOut.println("Neue Zelle: "+nbCellNew[0]+","+nbCellNew[1]);
-//																							statusOut.println("++++++++++++++++++++++++++++++++++++++++");
-																							//Variablendefinitionen
-																							
-																							float nbRoadBreed = 0f;
-																							int nbRoadBreedNeighbors = 0;
-																							nbRoadBreedNeighbors = calculateNeighbors(nbCellNew[0],nbCellNew[1],nbRoadBreed);
-																							int RNRoadBreed1 = 0;
-																							int RNRoadBreed2 = 0;
-																							int nbRoadBreedX = 0;
-																							int nbRoadBreedY = 0;
-																							int anzRoadBreedTreffer = 0;
-																						
-																							//wenn per roadWalk eine neue Zelle gefunden wurde, kann sie auch noch als Ausbreitungszentrum fungieren. Daher geht von ihr 
-																							//nochmals ein "Breed" aus. (GLEICHE FUNKTION WIE OBEN!!)
-												        
-																							if (nbRoadBreedNeighbors >= 2){
-																								int anzBreedTemp = 0;
-																								int[] nbPossibleBreedUrban = null;
-																								RNRoadBreed1 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																								RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));
-																								float RNRoadBreedSlope = 0f;
-																								if (RNRoadBreed2 == RNRoadBreed1)
-																									RNRoadBreed2 = 1 + Math.round((float)Math.random()*(nbRoadBreedNeighbors-1));	
-																								for (int cellBreed = 0; cellBreed < NEIGHBOR.length; cellBreed++){
-																									nbRoadBreedX = nbCellNew[0]+NEIGHBOR[cellBreed][0];
-																									nbRoadBreedY = nbCellNew[1]+NEIGHBOR[cellBreed][1];
-																									if ( nbRoadBreedX < areaMinX || nbRoadBreedY < areaMinY || nbRoadBreedX > areaMaxX || nbRoadBreedY > areaMaxY ||
-																											Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-																										continue;
-																									if (areaRestr.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY) != 0)
-																										continue;
-																									RNRoadBreedSlope = (float)Math.random();
-																									int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
-																									Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
-																									double slopeDoubleNb = doubleObjNb.doubleValue();
-																									float breedSample = outputGrid.getRasterSampleAsFloat(nbRoadBreedX,nbRoadBreedY);
-																									if (breedSample == 0f){
-																										anzBreedTemp++;
-																										nbPossibleBreedUrban = new int[] {nbRoadBreedX,nbRoadBreedY,anzBreedTemp};
-																										if (nbPossibleBreedUrban[2] == RNRoadBreed1 || nbPossibleBreedUrban[2] == RNRoadBreed2 && slopeDoubleNb < RNRoadBreedSlope){
-																											tmpGrid[nbRoadBreedX][nbRoadBreedY] = true;
-																											anzRoadBreedTreffer++;
-																											anzRoadTreffer++;
-																											//statusOut.println("Road-Breed-Treffer: "+anzRoadBreedTreffer);
-																										}
-																									}
-																								}
-												        									}
-																						} else{			//sind nicht mind. 2 Nachbarzellen gefunden worden...
-																							//statusOut.println("Keine neue Zelle gefunden");
-																						}
-																					}
-																				}
-																			}
-																		}
-																	}
-																}
-															}
-														}	
-													}
-												}
-			
-										} while (r <= breedF);
-		
-										//		statusOut.println("Spread-Treffer: "+anzSpreadTreffer);
-										//		statusOut.println("Dispersion-Treffer: "+anzDispTreffer);
-										//		statusOut.println("Breed-Treffer: "+anzBreedTreffer);
-										//		statusOut.println("Treffer gesamt: "+anzGesamt);
-										anzGesamtTreffer = anzSpreadTreffer+anzDispTreffer+anzBreedTreffer+anzRoadTreffer;
-										//		outStep.addGrid();
-										
+										statusOut.println("Number of Road Growth Cells: "+anzRoad);
+										writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
 
-										/**
-										 * Hier endet der eigentliche Modellalgorithmus des Urban Growth Modells.
-										 * Als nächstes wird das was ins temporäre grid geschrieben wurde ins outputGrid geschrieben.
-										 * Mit dem outputGrid wird dann im nächsten Zeitschritt weitergerechnet, bis die maximale Anzahl
-										 * an Jahren erreicht ist. Danach wird die nächste Kombination an Koeffizienten gewählt.
-										 */
+										// Here the main modeling algorithm ends. Next the temporary raster is written in the output raster. 
+										//With the outputGrid the next time step is calculated until the maximum number of time steps
+										//is reached. After that the next Monte Carlo iteration is performed for the specific parameter combination. 									
 										
-										// TempGrid auf das echte Grid schreiben
-										for (int y = 1; y < outputGrid.getHeight()-1;y++ ) 
-											for (int x = 1; x < outputGrid.getWidth()-1; x++ ) {
-				
-												int X = outputGrid.getMinX() + x;
-												int Y = outputGrid.getMinY() + y;
-				
-												boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f;	//eine Zelle lebt, wenn sie 1 ist
+										// Write the temporary Grid to the Output Grid
+										int anzGesamt = 0;
+										for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+											for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
+												
+												int X = inputGrid.getMinX() + x;
+												int Y = inputGrid.getMinY() + y;
+											
+												if (tmpGrid[x][y] == true)
+													anzGesamt++;
+												
+												boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f;	//a cell is alive, when it is 1
 												boolean road = roadGrid.getRasterSampleAsFloat(X, Y) > 0f;	//eine Zelle beinhaltet eine Straße...
-												if (tmpGrid[x][y] == false)	//wenn im temporären Raster nichts drinsteht...
-													tmpGrid[x][y] = lebt;	//wird der Wert aus dem Ausgangsraster übernommen
+												if (tmpGrid[x][y] == false)	//if there is nothing in the temporary raster
+													tmpGrid[x][y] = lebt;	//take the values from the current output raster
 												if(lebt == true)
-													thisYear++;
+													thisYear++;		//all urban cells in this year
 												if(road == true)
-													roadCount++;
-
-												outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);	
-												actUrb  = (Float)outputGrid.getRasterSample(x,y);
-												// outStep.getGrid(stepNo-1).setRasterSample(actUrb,x,y);
+													roadCount++;	//road cells
+												
+												outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);	//write the results in the output raster
+												actUrb  = (Float)outputGrid.getRasterSample(x,y);	//the actual urban extent
 											}
+										}
+										statusOut.println("Urban pixels at step "+timeSteps+": "+anzGesamt);
 										
 										//SELF-MODIFICATION
-										growthRate = ((float)anzGesamtTreffer / (float)thisYear)*100;
-									//	statusOut.println("Wachstumsrate: "+growthRate+", Urban: "+anzGesamtTreffer);
+										growthRate = ((float)anzGesamt / (float)thisYear)*100;	//growth rate
+										statusOut.println("Wachstumsrate: "+growthRate+", Urban: "+anzGesamt);
 										double percent_urban = (100.0 *(thisYear+roadCount) / (totalPixels-roadCount-excldCount));
-									//	statusOut.println("1. Slope-Sensitivity: "+slopeF+", RoadGravity-Sensitivity: "+roadGravityF+", Diffusion-Sensitivity: "+dispF+", Breed-Sensitivity: "+breedF+", Spread-Sensitivity: "+spreadF);
+										
 										//Boom-Year
-										if(growthRate > criticalHigh){
-											slopeF -= (float)percent_urban * (float)slopeSens;
-											if(slopeF <= 0.01)
+										if(growthRate > criticalHigh){	//if the growth rate exceeds the critical high value
+											slopeF -= (float)percent_urban * (float)slopeSens;	//decrease the slope coefficient
+											if(slopeF <= 0.01)	//if it is already very low, make it 1
 												slopeF = 1.0;
-											roadGravityF += (float)percent_urban * roadGravSens;
+											roadGravityF += (float)percent_urban * roadGravSens;	//increase the road Gravity
 											if(roadGravityF > 100.0)
 												roadGravityF = 100.0;
-											if(dispF < 100.0){
+											if(dispF < 100.0){	//increase the other coefficients by multiplying with the boom parameter
 												dispF *= boom;
 												if(dispF > 100.0)
 													dispF = 100.0;
@@ -938,15 +336,16 @@
 													spreadF = 100.0;
 											}
 										}
+										
 										//Bust-Year
-										if(growthRate < criticalLow){
-											slopeF += (float)percent_urban * (float)slopeSens;
+										if(growthRate < criticalLow){	//if the growth rate falls below the critical low value
+											slopeF += (float)percent_urban * (float)slopeSens;	//increase the slope coefficient
 											if(slopeF > MaxSlopeResistance)
 												slopeF = MaxSlopeResistance;
-											roadGravityF -= (float)percent_urban * roadGravSens;
+											roadGravityF -= (float)percent_urban * roadGravSens;	//decrease the road Gravity
 											if(roadGravityF <= 0.01)
 												roadGravityF = 1.0;
-											if(growthRate < criticalLow && dispF > 0){
+											if(growthRate < criticalLow && dispF > 0){	//decrease the other coefficients by multiplying with the bust parameter
 												dispF *= bust;
 												if(dispF <= 0.01)
 													dispF = 1.0;
@@ -958,333 +357,72 @@
 													breedF = 1.0;
 											}
 										}
-										//statusOut.println("thisYear: "+thisYear+", roadCount: "+roadCount+", excldCount: "+excldCount+", percent_urban: "+percent_urban);
-										statusOut.println("Slope-Sensitivity: "+slopeF+", RoadGravity-Sensitivity: "+roadGravityF+", Diffusion-Sensitivity: "+dispF+", Breed-Sensitivity: "+breedF+", Spread-Sensitivity: "+spreadF);
 										
 										
-										if (!anyBodyAlive) {
-											stepCount = stepNo;
-											//statusOut.println("Lebt keiner mehr... höre hier auf!");
-										}
-		
-										//RasterUtil.copyInto(outputGrid, inputGrid);
-										//	System.out.println("Finished step " + (stepNo) + " in "
-										//			+ ((System.currentTimeMillis() - localStartTime)) + " ms\n");
-										localStartTime = System.currentTimeMillis();
-		
-									}	//HIER ENDET DER ZEITSCHRITT. DIE SCHLEIFE WIRD DURCHLAUFEN, BIS MAX JAHRE ERREICHT SIND.
-		
-									/**
-									 * +++++ MULTIPLE RESOLUTION VALIDATION ++++++
-									 * Sind alle Zeitschritte durchlaufen, wird das Endergebnis validiert.
-									 * Als Validierungsmethode wurde die Multiple Resolution Validation ausgewählt (siehe
-									 * Costanza(1989), Pontius (2002), Pontius et al. (2005), Lesschen et al. (2005),
-									 * Pontius et al. (2008a), Pontius et al. (2008b))
-									 * Für das SLEUTH-Modell werden eigentlich eine Reihe an Landschaftsmaßen zur Validierung
-									 * verwendet (siehe Clarke et al. (1997), Dietzel et al. (2007)), wie z.B. LeeSallee
-									 * oder OSM. Da für die spätere Validierung der Modellierungsergebnisse und zum Vergleich mit 
-									 * anderen Modelltypen die Multiple Resolution Validation verwendet wird, wird sie auch zur
-									 * Bewertung der Kalibrierungsschritte verwendet.
-									 */
-									
-									//Variablendefinitionen
-									int RoverallSum = 0;
-									int RnumClasses = 0;
-									int SoverallSum = 0;
-									int SnumClasses = 0;
-									int correct = 0;
-									double fractionCorrect = 0f;
-		
-
-									long localStartTime = System.currentTimeMillis();
-									neighborhoodRange = (int) Math.sqrt(referenceGrid.getWidth()*referenceGrid.getHeight()); //maximal mögliche Zellengröße
-									//statusOut.println(neighborhoodRange);
-									resultArray = new float[13];		//!!!!!!!!! Ergebnis-Array
-									resultArrayFinal = new float[MonteCarlo-1][13];	//?????????????
-									
-									//Für die Ausgangs-Auflösung wird berechnet, wieviel % der Pixel zwischen Modell und Referenz übereinstimmen
-									for (int x = 0; x < referenceGrid.getWidth(); x++)
-										for (int y = 0; y < referenceGrid.getHeight(); y++) {
-											float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
-											float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
-											if (!Float.isNaN(Rtmp) && !Float.isNaN(Stmp)){
-												RoverallSum ++;
-												SoverallSum ++;
-												if (Rtmp > RnumClasses)
-													RnumClasses = (int) Rtmp;
-												if (Stmp > SnumClasses)
-													SnumClasses = (int) Stmp;	
-												if (Rtmp == Stmp)
-													correct++;
+										if (timeSteps == years){
+											outStep.addGrid();	//add a raster to the GridList
+											
+											// Write the temporary Grid to the Output Grid
+											for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+												for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
+													actUrb  = (Float)outputGrid.getRasterSample(x,y);	//the actual urban extent
+													outStep.getGrid(MC-1).setRasterSample(actUrb,x,y);	//put the layer in the raster list containing the step results
+												}
 											}
-										}
-									fractionCorrect = (double) correct / (double) RoverallSum;
-		
-									//Anzahl der Pixel pro Klasse
-									for (int i = 1; i <= RnumClasses; i++){
-										int Rj = 0;
-										int Sj = 0;
-										for (int x = 0; x < referenceGrid.getWidth(); x++)
-											for (int y = 0; y < referenceGrid.getHeight(); y++){
-												float Rtmp = referenceGrid.getRasterSampleAsFloat(x, y);
-												float Stmp = outputGrid.getRasterSampleAsFloat(x, y);
-												if (!Float.isNaN(Rtmp))
-													if ((int) Rtmp == i)
-														Rj++;
-												if (!Float.isNaN(Stmp))
-													if ((int) Stmp == i)
-														Sj++;
+											WritableGrid simulationMap = outStep.getGrid(MC-1);		//write the final step result to the grid list
+											float[] mrv = MultipleResolutionComparison(simulationMap);	//perform the MRV
+											for(int i = 0;i < mrv.length;i++){
+												statusOut.println(mrv[i]);
+												mrvTempResultArray[i] += mrv[i];
 											}
-										//statusOut.println("Klasse "+i+": Referenz("+Rj+"), Simulation("+Sj+")");
-									}
-		
-									ngrids = 0;
+										}
+									}	//END OF THE TIME STEPS
 									
-									//Die eigentliche Validierung wird für alle Zellengrößen von 1 (Ausgangsauflösung) bis "neighborhoodRange" durchgeführt
-									for (int r1 = 1; r1 <= neighborhoodRange; r1 = r1+r1){	//für Zellengröße 1 bis zur max. möglichen Zellengröße wird Statistik durchgeführt
-										//statusOut.println(r1);	
-										ngrids++;
-										float SumWn = 0f;	//Summe der gewichteten Mittelwerte 
-										int SumCells = 0;	//Summe der Zellen
-										float totalAgreement = 0f;	//Endergebnis
-										for (int x = 0; x < referenceGrid.getWidth(); x = x+r1)	//für jeden größer werdenden Zellenbereich...
-											for (int y = 0; y < referenceGrid.getHeight(); y = y+r1){	//was folgt passiert innerhalb einer größeren Rasterzelle
-												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+r1; x2++)	//für jede kleinere Zelle innerhalb der größeren...
-													for(int y2 = y; y2 < y+r1; y2++){
-														if ( x2 < referenceGrid.getMinX() || y2 < referenceGrid.getMinY() || x2 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y2 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
-																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x2,y2)))
-															continue;
-														nCells++;	//zähle "positive" Zellen
-													}
-												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+r1; x3++)	//für jede kleinere Zelle pro größerer Zelle...
-														for(int y3 = y; y3 < y+r1; y3++){
-															if ( x3 < referenceGrid.getMinX() || y3 < referenceGrid.getMinY() || x3 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y3 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
-																	Float.isNaN(referenceGrid.getRasterSampleAsFloat(x3,y3)))
-																continue;
-															float Rtmp = referenceGrid.getRasterSampleAsFloat(x3, y3);	//hole Wert aus Referenz-Karte und
-															float Stmp = outputGrid.getRasterSampleAsFloat(x3, y3);	//Simulationskarte
-															if ((int) Rtmp == i)
-																Rn++;	//zähle in Referenzkarte Zellen, die zu Klasse i gehören 
-															if ((int) Stmp == i)
-																Sn++;	//und in Simulationskarte
-														}
-													if(nCells > 0){	//wenn positive Zellen vorhanden sind...
-														Rnj = (float)Rn / (float)nCells;	//berechne Anteile pro größerer Zelle
-														Snj = (float)Sn / (float)nCells;
-													}
-													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);	
-												}
-												
-												Wn = (float)nCells * SumMinRS;
-												//	statusOut.println(SumMinRS+", gewichtet: "+Wn);
-												//Erstelle Output-Karten
-												float WnCell = 0f;
-												for(int x4 = x; x4 < x+r1; x4++)	//für jede kleinere Zelle pro größerer Zelle...
-													for(int y4 = y; y4 < y+r1; y4++){
-														if ( x4 < referenceGrid.getMinX() || y4 < referenceGrid.getMinY() || x4 > referenceGrid.getMinX()+referenceGrid.getWidth()-1 || y4 > referenceGrid.getMinY()+referenceGrid.getHeight()-1 ||
-																Float.isNaN(referenceGrid.getRasterSampleAsFloat(x4,y4)))
-															continue;
-														WnCell = Wn / (float)nCells; //pro Zelle wird Mittelwert des Vergleichs genommen
-														//actualValidation.setRasterSample( WnCell ,x4 ,y4);	
-													}
-				
-												SumCells += (float)nCells;	//Summiere alle Zellen auf
-												SumWn += Wn;	//Summiere die gewichteten Anteile auf
-											}		//hier endet die Berechnung innerhalb einer größeren Rasterzelle
+									if (MC == MonteCarlo){
+										SumOutStep.addGrid();	//add a final raster to the GridList (contains the sum of all iterations)
 										
+										//statusOut.println("Step Grids: "+outStep.getGridCount());
 										
-										//Total Agreement:
-										//statusOut.println(SumWn+" / "+SumCells);
-										totalAgreement = SumWn / (float)SumCells;	//Ergebnisformel
-										//statusOut.println(totalAgreement);	
-
-										outResults.addValue(totalAgreement);
-										resultArray[ngrids] = totalAgreement;
-
-										//	statusOut.println("Gesamt-Pixel: "+RoverallSum);
-										//	statusOut.println("Anzahl Klassen: "+RnumClasses);
-										//	statusOut.println("Fraction Correct: "+fractionCorrect);
-										
-									}	//Hier endet die Berechnung pro Auflösung
-		
-								//	System.out.println("(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
-								//			resultArray[1]+","+resultArray[2]+","+resultArray[3]+","+resultArray[4]+","+resultArray[5]+","+resultArray[6]+
-								//			","+resultArray[7]+","+resultArray[8]+","+resultArray[9]);
-																		
-									pos1 += resultArray[1];
-									pos2 += resultArray[2];
-									pos3 += resultArray[3];
-									pos4 += resultArray[4];
-									pos5 += resultArray[5];
-									pos6 += resultArray[6];
-									pos7 += resultArray[7];
-									pos8 += resultArray[8];
-									pos9 += resultArray[9];
-									pos10 += resultArray[10];
-									pos11 += resultArray[11];
-									pos12 += resultArray[12];
-									//	System.out.print("Finished step " + (stepNo) + " in "
-									//			+ ((System.currentTimeMillis() - localStartTime)) + " ms");
-									localStartTime = System.currentTimeMillis();
-									//	System.out.println(" with sum (local calculated): " + RoverallSum);
-							}	//!!!!!!!!!! Hier endet ein Monte-Carlo-Schritt
-							
-							System.out.println("-->(Slope:"+slope+" Spread:"+spread+" Dispersion:"+disp+" Breed: "+breed+" RoadGravity: "+roadGravity+") "+
-									pos1/MonteCarlo+","+pos2/MonteCarlo+","+pos3/MonteCarlo+","+pos4/MonteCarlo+","+pos5/MonteCarlo+","+pos6/MonteCarlo+
-											","+pos7/MonteCarlo+","+pos8/MonteCarlo+","+pos9/MonteCarlo+","+pos10/MonteCarlo+","+pos11/MonteCarlo+","+pos12/MonteCarlo);
-						}	//Ende RoadGravity-Koeffizient
-					}	//Ende Breed-Koeffizient
-				}	//Ende Disp-Koeffizient
-			}	//Ende Spread-Koeffizient
-		}	//Ende Slope-Koeffizient
-	}	//Ende Model-Step
-	
-	private int[] roadWalk(int X,int Y,double dispF){
-//		statusOut.println(X+","+Y);
-		boolean end_of_road;
-		end_of_road = false;
-		int run = 0;
-		int run_value = 0;
-		int[] nbCellNew = null;
-		int[] nbCellTemp = null;
-		while(!end_of_road){
-			end_of_road = true;
-			int nbRoadX = 0;
-			int nbRoadY = 0;
-			int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
-			int areaMinY = outputGrid.getMinY();
-			int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
-			int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
-			int roadNb = 0;
-			int roadNbTemp = 0;
-			int RN = 0;
-						
-			int[] nbCell = null;
-			for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
-				nbRoadX = X+NEIGHBOR[nbRoadCells][0];
-				nbRoadY = Y+NEIGHBOR[nbRoadCells][1];
-				if ( nbRoadX < areaMinX || nbRoadY < areaMinY || nbRoadX > areaMaxX || nbRoadY > areaMaxY ||
-			               Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-			             continue;
-				//if (areaRestr.getRasterSampleAsFloat(nbRoadX,nbRoadY) != 0)
-		        //	continue;
-				float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY);
-				if (roadSample > 0f)
-					roadNb++;
-			}
-	//		statusOut.println("Nachbarn von temporaerer Strassenzelle: "+roadNb);
-			
-			if (roadNb > 0){
-				RN = 1 + Math.round((float)Math.random()*(roadNb-1));
-			
-				for (int nbRoadCells = 0; nbRoadCells < NEIGHBOR.length; nbRoadCells++){
-					nbRoadX = X+NEIGHBOR[nbRoadCells][0];
-					nbRoadY = Y+NEIGHBOR[nbRoadCells][1];
-					if ( nbRoadX < areaMinX || nbRoadY < areaMinY || nbRoadX > areaMaxX || nbRoadY > areaMaxY ||
-							Float.isNaN(outputGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-			             	continue;
-					float roadSample = roadGrid.getRasterSampleAsFloat(nbRoadX,nbRoadY);
-					if (roadSample > 0f){
-						roadNbTemp++;
-						nbCell = new int[] {nbRoadX,nbRoadY,roadNbTemp};
-						if (nbCell[2] == RN){
-//							statusOut.println("Nachbarzelle gefunden: "+nbCell[0]+","+nbCell[1]+","+nbCell[2]);
-							end_of_road = false;
-							run++;
-							X = nbRoadX;
-							Y = nbRoadY;
-							float roadSample2 = roadGrid.getRasterSampleAsFloat(X,Y);
-							run_value = (int) (roadSample2 / 100 * dispF);
-					//		statusOut.println("Run: "+run);
-					//		statusOut.println("Run_Value: "+run_value);
-					//		statusOut.println(X+","+Y+","+roadSample2);
-							if (run > run_value){
-								end_of_road = true;
-					//			statusOut.println("Endzelle erreicht!! Run:"+run+"RunValue: "+run_value);
-								float NbValue = 0f; 
-								int Nb = calculateNeighbors(X,Y,NbValue);
-					//			statusOut.println("moegliche Nachbarzellen nach RoadWalk: "+Nb);
-								RN = 1 + Math.round((float)Math.random()*(Nb-1));
-				//				statusOut.println("Random: "+RN);
-								if (Nb > 0){
-									int nbUrbanizeX = 0;
-									int nbUrbanizeY = 0;
-									int NbTemp = 0;
-									float RNRoadSlope = 0f;
-						//			statusOut.println(X+","+Y);
-									for (int urbanizeCells = 0; urbanizeCells < NEIGHBOR.length; urbanizeCells++){
-										nbUrbanizeX = X+NEIGHBOR[urbanizeCells][0];
-										nbUrbanizeY = Y+NEIGHBOR[urbanizeCells][1];
-										if ( nbUrbanizeX < areaMinX || nbUrbanizeY < areaMinY || nbUrbanizeX > areaMaxX || nbUrbanizeY > areaMaxY ||
-												Float.isNaN(outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-											continue;
-										if (areaRestr.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY) != 0)
-											continue;
-										float rasterSample = outputGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY);
-										RNRoadSlope = (float)Math.random();
-					        			int getSlopeNb = (int) slopeGrid.getRasterSampleAsFloat(nbUrbanizeX,nbUrbanizeY);
-					        			Double doubleObjNb = (Double)slopeLUT.get(getSlopeNb);
-					        			double slopeDoubleNb = doubleObjNb.doubleValue();
-										if (rasterSample == 0f){
-											NbTemp++;
-											nbCellTemp = new int[] {nbUrbanizeX,nbUrbanizeY,NbTemp};
-											if (nbCellTemp[2] == RN && slopeDoubleNb < RNRoadSlope){
-												nbCellNew = new int[] {nbCellTemp[0],nbCellTemp[1],nbCellTemp[2]};
+										for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+											for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {	//for every pixel...
+												float sumUrb = 0; 	//sum of pixel values
+												for (int gridNo = 0; gridNo < MC; gridNo++){	//look in every grid of the GridList
+													float tempUrb = (Float) outStep.getGrid(gridNo).getRasterSample(x,y);	//take the pixel value
+													sumUrb  += tempUrb;		//and add its value
+												}
+												SumOutStep.getGrid(runs-1).setRasterSample(sumUrb,x,y);	//put the layer in the raster list containing the step results
 											}
-										}	
-									}
+										}
+										
+										System.out.print("Slope: "+slope+" Spread: "+spread+" Disp: "+disp+" Breed: "+breed+" Road: "+roadGravity+" : ");
+										
+										for(int i = 0;i < mrvTempResultArray.length-2;i++){
+											//print every element of the result array comma separated in one line in the status output
+											finalArray[i] = mrvTempResultArray[i]/MonteCarlo;
+											System.out.print(finalArray[i]+",");
+										}
+										System.out.print("//Weighted Averages (FT, WA): ");
+										for(int j = 0;j < 2;j++){
+											//print every element of the result array comma separated in one line in the status output
+											finalArray[numSteps+j] = mrvTempResultArray[j]/MonteCarlo;
+											System.out.print(finalArray[j]+",");
+										}
+										for (int grids = MC-1; grids >= 0; grids--){
+											outStep.removeGrid(grids); 				//empty GridList
+										}
+										//statusOut.println("Step Grids nach leeren: "+outStep.getGridCount());
 								
-							} else{
-								nbCellNew = null;
-							}	break;
-						}
-						
-					}
-					
-				}
-			}
-			
-			}
-		}
-		return nbCellNew;
-		}
-	
-	private int calculateNeighbors(int X, int Y, float NbValue){
-		int nbX = 0;
-		int nbY = 0;
-		int areaMinX = outputGrid.getMinX();								//Dimensionen des Rasters
-		int areaMinY = outputGrid.getMinY();
-		int areaMaxX = outputGrid.getMinX() + outputGrid.getWidth() - 1;
-		int areaMaxY = outputGrid.getMinY() + outputGrid.getHeight() - 1;
-		int Nb = 0;
-		for (int nbCells = 0; nbCells < NEIGHBOR.length; nbCells++){
-			nbX = X+NEIGHBOR[nbCells][0];
-			nbY = Y+NEIGHBOR[nbCells][1];
-			if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
-		               Float.isNaN(outputGrid.getRasterSampleAsFloat(nbX,nbY)) ) //wenn Nachbarzelle außerhalb des Rasters (NaN) --> ignorieren
-		             continue;
-			if (areaRestr.getRasterSampleAsFloat(nbX,nbY) != 0)
-	        	continue;
-			float rasterSample = outputGrid.getRasterSampleAsFloat(nbX,nbY);
-			if (rasterSample == NbValue)
-				Nb++;
-		}
-	//	statusOut.println("..."+Nb+"...");
-		return Nb;
-	}
-	
-	protected static boolean checkNoData(int x, int y, WritableGrid grid) {
-	    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
-	  }
-}
+									} 
+									countSetIndividuals();
+									
+								}	System.out.println("");
+								
+								//END OF THE MONTE CARLO ITERATIONS
+							}	//END OF ROADGRAVITY COMBINATION
+						}	//END OF BREED COMBINATION
+					}	//END OF DISP COMBINATION
+				}	//END OF SPREAD COMBINATION
+			}	//END OF SLOPE COMBINATION
+			System.out.println("Finished "  + " in " + ((System.currentTimeMillis() - localStartTime)) + " ms\n");
+		}	//END OF MODEL STEP
+}
\ No newline at end of file

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelCalibrationSelfModificationContentManager.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -1,57 +1,30 @@
 package edu.bonn.xulu.plugin.model.sleuth;
 
-import schmitzm.data.WritableGrid;
-import schmitzm.data.property.ListProperty;
 import schmitzm.data.property.ScalarProperty;
 import edu.bonn.xulu.data.XuluDataException;
-import edu.bonn.xulu.model.AbstractModelContentManager;
-import edu.bonn.xulu.model.DefaultModelResource;
 import edu.bonn.xulu.model.ModelResource;
 import edu.bonn.xulu.model.ValuePropertyResource;
-import edu.bonn.xulu.plugin.data.grid.MultiGrid;
 
 
-public class UrbanGrowthModelCalibrationSelfModificationContentManager extends AbstractModelContentManager {
+public class UrbanGrowthModelCalibrationSelfModificationContentManager extends UrbanGrowthModelCalibrationContentManager {
 	
-	public UrbanGrowthModelCalibrationSelfModificationContentManager() {
-		super(31);
+	public UrbanGrowthModelCalibrationSelfModificationContentManager(int additionalRes) {
+		super(6+additionalRes);
 	    
-		resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
-		resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of MonteCarlo Iterations",ScalarProperty.class,Integer.class,false);
-		resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
-		resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
-	    resource[5] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[6] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Reference Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[8] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[9] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[10] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[12]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[13]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[14]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[15]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[16]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[17]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[18]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[19]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[20]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Start",ScalarProperty.class,Double.class,false);
-	    resource[21]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient Step",ScalarProperty.class,Double.class,false);
-	    resource[22]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient End",ScalarProperty.class,Double.class,false);
-	    resource[23]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
-	    resource[24]= new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Validation Results",ListProperty.class,Float.class,false);
-	    resource[25]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Gravity Sensitivity",ScalarProperty.class,Double.class,false);
-	    resource[26]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Sensitivity",ScalarProperty.class,Double.class,false);
-	    resource[27]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Low",ScalarProperty.class,Double.class,false);
-	    resource[28]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical High",ScalarProperty.class,Double.class,false);
-	    resource[29]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Boom",ScalarProperty.class,Double.class,false);
-	    resource[30]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Bust",ScalarProperty.class,Double.class,false);
+		resource[27]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Gravity Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[28]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[29]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Low",ScalarProperty.class,Double.class,false);
+	    resource[30]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical High",ScalarProperty.class,Double.class,false);
+	    resource[31]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Boom",ScalarProperty.class,Double.class,false);
+	    resource[32]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Bust",ScalarProperty.class,Double.class,false);
 
 	 	// ===== Ressourcen Bezeichnungen lokalisieren =====
 	    resetCaptions(null);
 	}
 	
+	public UrbanGrowthModelCalibrationSelfModificationContentManager(){
+		this(0);
+	}
 	
 	@Override
 	public void checkAndError() throws XuluDataException {

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelContentManager.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -14,18 +14,18 @@
 	public UrbanGrowthModelContentManager(int additionalRes) {
 		super(13+additionalRes);
 		
-		resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
-		resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
-	    resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
-	    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient",ScalarProperty.class,Double.class,false);
-	    resource[5]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient",ScalarProperty.class,Double.class,false);
-	    resource[6]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient",ScalarProperty.class,Double.class,false);
-	    resource[7] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient",ScalarProperty.class,Double.class,false);
-	    resource[8]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient",ScalarProperty.class,Double.class,false);
-	    resource[9]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
-	    resource[10]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
-	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
+		resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+		resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
+		resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
+		resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Area Restrictions",ScalarProperty.class,WritableGrid.class,false);
+		resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Grid",ScalarProperty.class,WritableGrid.class,false);
+		resource[5] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Grid",ScalarProperty.class,WritableGrid.class,false);
+	    resource[6] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Spread Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[7]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Dispersion Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[8]	= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Breed Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[9] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"RoadGravity Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[10]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Coefficient",ScalarProperty.class,Double.class,false);
+	    resource[11]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Slope",ScalarProperty.class,Double.class,false);
 	    resource[12]= new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,"Step Results",MultiGrid.class,false);
 	    
 	 	// ===== Ressourcen Bezeichnungen lokalisieren =====

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModification.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModification.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModification.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -0,0 +1,308 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import edu.bonn.xulu.model.XuluModel;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ *  <b>Urban Growth Model with Self Modification</b><br>
+ *  This model is based on the {@link UrbanGrowthModel Urban Growth Model}, developed by Keith Clarke at the UC Santa Barbara, CA, within the Gigalopolis Project, funded by the
+ *  USGS. It has exactly the same growth rules as its parent class, with Self Modification of several coefficients enabled.
+ *  For a detailed description refer to {@link UrbanGrowthModel Urban Growth Model}
+ *  
+ * <br>
+ * In addition to the UGM Coefficients, these parameters are needed:<br>
+ * <ul>
+ *  <li><b>Road Gravity Sensitivity</b>: Influences the roadGravity coefficient</li>
+ *  <li><b>Slope Sensitivity</b>: Influences the slope coefficient</li>
+ *  <li><b>Critical Low</b>: When growth rate falls below this value, the coefficients are altered</li>
+ *  <li><b>Critical High</b>: When growth rate exceeds this value, the coefficients are altered</li>
+ *  <li><b>Boom</b>: Boom Phase. The Coefficients are increased by this value.</li>
+ *  <li><b>Bust</b>: Bust Phase. The Coefficients are decreased by this value.</li>
+ * </ul>
+ * 
+ * @see UrbanGrowthModelSelfModificationContentManager
+ * @see UrbanGrowthModel
+ * @author <a href="mailto:goetzke at uni-bonn.de">Roland Goetzke</a>
+ * @version 1.0
+ */
+public class UrbanGrowthModelSelfModification extends UrbanGrowthModel {
+
+	//protected UrbanGrowthModelSelfModificationContentManager contManager;
+
+	// ********** Read/Write access, that has to be maintained ***
+	// ********** through the whole model run ********************
+	private PropertyReadAccess RA_roadGravSens = null;	//RoadGravity Sensitivity
+	private PropertyReadAccess RA_slopeSens = null;	//Slope Sensitivity
+	private PropertyReadAccess RA_criticalLow = null;	//Critical Low
+	private PropertyReadAccess RA_criticalHigh = null;	//Critical High
+	private PropertyReadAccess RA_Boom = null;	//Boom
+	private PropertyReadAccess RA_Bust = null;	//Bust
+
+	//**************** Variables to work with *******************
+	protected double roadGravSens = 0;	//RoadGravity Sensitivity
+	protected double slopeSens = 0;	//Slope Sensitivity
+	protected double criticalLow = 0;	//critical Low
+	protected double criticalHigh = 0;	//critical High
+	protected double boom = 0;	//Boom
+	protected double bust = 0;	//Bust
+		
+	private int slopeMax = 0;
+	private int totalPixels = 0;
+	private int excldCount = 0;
+	
+	/**
+	 * First Constructor
+	 * @param contManager
+	 */
+	public UrbanGrowthModelSelfModification(UrbanGrowthModelSelfModificationContentManager contManager) {
+		super(contManager);
+	//	this.contManager = (UrbanGrowthModelSelfModificationContentManager) super.contManager;
+	}
+	/**
+	 * Second Constructor. The Content Manager is the parent content manager as well as the child content manager
+	 */
+	public UrbanGrowthModelSelfModification(){
+		super(new UrbanGrowthModelSelfModificationContentManager());
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		super.performModelInit();
+		
+		RA_roadGravSens = null;
+		if (contManager.getResource(13).getData() != null)
+			RA_roadGravSens = ((ScalarProperty) contManager.getResource(13).getData())
+					.getReadAccess(this);
+		RA_slopeSens = null;
+		if (contManager.getResource(14).getData() != null)
+			RA_slopeSens = ((ScalarProperty) contManager.getResource(14).getData())
+					.getReadAccess(this);
+		RA_criticalLow = null;
+		if (contManager.getResource(15).getData() != null)
+			RA_criticalLow = ((ScalarProperty) contManager.getResource(15).getData())
+					.getReadAccess(this);
+		RA_criticalHigh = null;
+		if (contManager.getResource(16).getData() != null)
+			RA_criticalHigh = ((ScalarProperty) contManager.getResource(16).getData())
+					.getReadAccess(this);
+		RA_Boom = null;
+		if (contManager.getResource(17).getData() != null)
+			RA_Boom = ((ScalarProperty) contManager.getResource(17).getData())
+					.getReadAccess(this);
+		RA_Bust = null;
+		if (contManager.getResource(18).getData() != null)
+			RA_Bust = ((ScalarProperty) contManager.getResource(18).getData())
+					.getReadAccess(this);
+
+		// Variables to work with
+	    roadGravSens = RA_roadGravSens.getValueAsDouble();
+	    slopeSens = RA_slopeSens.getValueAsDouble();
+	    criticalLow = RA_criticalLow.getValueAsDouble();
+	    criticalHigh = RA_criticalHigh.getValueAsDouble();
+	    boom = RA_Boom.getValueAsDouble();
+	    bust = RA_Bust.getValueAsDouble();
+
+	  //Calculate total amount of pixels and number of excluded pixels
+		for (int x = 0; x < inputGrid.getWidth();x++ ) 
+			for (int y = 0; y < inputGrid.getHeight(); y++ ) {
+				if ( x < inputGrid.getMinX() || y < inputGrid.getMinY() || x > inputGrid.getMinX()+inputGrid.getWidth()-1 || y > inputGrid.getMinY()+inputGrid.getHeight()-1 ||
+			            Float.isNaN(outputGrid.getRasterSampleAsFloat(x,y)) ) //ignore neighbor, if outside the raster
+			             continue;
+				totalPixels++;
+				if (areaRestr.getRasterSampleAsFloat(x,y) != 0 && !Float.isNaN(areaRestr.getRasterSampleAsFloat(x,y)))
+					excldCount++;
+			}
+		
+		statusOut.println("Total: "+totalPixels+", Excluded: "+excldCount);
+		
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+		super.performModelDispose();
+		// free resources
+		releaseAccess(RA_roadGravSens);
+		releaseAccess(RA_slopeSens);
+		releaseAccess(RA_criticalLow);
+		releaseAccess(RA_criticalHigh);
+		releaseAccess(RA_Boom);
+		releaseAccess(RA_Bust);
+	}
+
+	/**
+	 * The main method of the Urban Growth Model. For a detailed description refer to the performModelStep in 
+	 * {@link UrbanGrowthModel UrbanGrowthModel}. The difference to the plain UGM Calibration model is the Self Modification 
+	 * of several coefficients at the end of each modelling step.
+	 */
+	public void performModelStep(int stepNo) {
+		
+		long localStartTime = System.currentTimeMillis();
+		statusOut.println("Starting step " + stepNo + "...");
+		
+		int MaxSlopeResistance = 100;
+		slopeMax = getSlopeMax();
+		double exp = getSlopeExp(slope,MaxSlopeResistance);	//calculate the exp value based on the actual slope
+		statusOut.println("EXP: "+exp);
+		slopeLUT = getSlopeLookup(slopeMax,exp,criticalSlope);	//generate the lookup-table based on the actual exp-value
+
+		boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];
+		Float actUrb = null;
+
+		double growthRate = 0;
+		int thisYear = 0;
+		int roadCount = 0;
+		
+		//DISPERSION
+		double disp_value = Math.round((disp*0.005)* Math.sqrt(Math.pow(inputGrid.getWidth(), 2)+(Math.pow(inputGrid.getHeight(), 2))));
+		
+		//ROAD GRAVITY
+		double max_RG_value = 100.0;
+		double rg_value = Math.round((roadGravity/max_RG_value)*((areaWidth + areaHeight)/16)); 
+		
+
+		/*****************************************************************
+		 * DISPERSION and BREED (Growth Phase 1 and 2)
+		 *****************************************************************/
+		boolean[][] tmpGridDisp = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+		tmpGridDisp = DispersionGrowth(disp_value,breed);	//calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
+		int anzDispBreed = 0;	//number of cells urbanized by Dispersion and Breed
+		for (int x = 0; x < inputGrid.getWidth();x++)
+			for(int y = 0; y < inputGrid.getHeight();y++){
+				int X = inputGrid.getMinX() + x;
+				int Y = inputGrid.getMinY() + y;
+				if (tmpGridDisp[X][Y]==true){
+					anzDispBreed++;
+					tmpGrid[X][Y] = true;	//write the temporary Dispersion and Breed Cells to the overall temporary Cell array
+				}		
+			}
+		statusOut.println("Number of Spontaneous and New Spreading Center Cells: "+anzDispBreed);
+		writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
+		
+				
+		/*********************************************************************
+		 * EDGE
+		 *********************************************************************/
+		boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+		tmpGridSpread = EdgeGrowth(spread);	//calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
+		int anzSpread = 0;	//number of cells urbanized by Spread
+		for (int x = 0; x < inputGrid.getWidth();x++)
+			for(int y = 0; y < inputGrid.getHeight();y++){
+				int X = inputGrid.getMinX() + x;
+				int Y = inputGrid.getMinY() + y;
+				if (tmpGridSpread[X][Y]==true){
+					anzSpread++;
+					tmpGrid[X][Y] = true;	//write the temporary Spread cells to the overall temporary Cell array
+				}		
+			}
+		statusOut.println("Number of Edge Growth Cells: "+anzSpread);
+		writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
+	
+		/*********************************************************************
+		 * ROAD
+		 *********************************************************************/
+		boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
+		tmpGridRoad = RoadGrowth(tmpGrid,rg_value,breed,disp);	//calls the method "RoadGrowth" to perform the Road weighted growth
+		int anzRoad = 0;	//number of cells urbanized by Road Growth
+		for (int x = 0; x < inputGrid.getWidth();x++)
+			for(int y = 0; y < inputGrid.getHeight();y++){
+				int X = inputGrid.getMinX() + x;
+				int Y = inputGrid.getMinY() + y;
+				if (tmpGridRoad[X][Y]==true){
+					anzRoad++;
+					tmpGrid[X][Y] = true;	//write the temporary Road Growth cells to the overall temporary Cell array
+				}		
+			}
+		statusOut.println("Number of Road Growth Cells: "+anzRoad);
+		writeToGrid(tmpGrid);	//calls the method "writeToGrid" to write the new urbanized cells to the output grid
+		
+		
+		outStep.addGrid();
+		int anzGesamt = 0;
+		
+		// Write the temporary Grid to the Output Grid
+		for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {
+			for (int x = 1; x < inputGrid.getWidth()-1; x++ ) {
+				
+				int X = inputGrid.getMinX() + x;
+				int Y = inputGrid.getMinY() + y;
+				
+				if (tmpGrid[x][y] == true)
+					anzGesamt++;
+				
+				boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f;	//a cell is alive, when it is 1
+				boolean road = roadGrid.getRasterSampleAsFloat(X, Y) > 0f;	//a cell contains a road...
+				if (tmpGrid[x][y] == false)	//if there is nothing in the temporary raster
+					tmpGrid[x][y] = lebt;	//take the values from the current output raster
+				if(lebt == true)
+					thisYear++;		//all urban cells in this year
+				if(road == true)
+					roadCount++;	//road cells
+
+				outputGrid.setRasterSample( tmpGrid[x][y] ? 1f : 0f ,X ,Y);	//write the results in the output raster
+				actUrb  = (Float)outputGrid.getRasterSample(x,y);	//the actual urban extent
+				outStep.getGrid(stepNo-1).setRasterSample(actUrb,x,y);	//put the layer in the raster list containing the step results
+			}
+		}
+		
+		
+		//SELF-MODIFICATION
+		growthRate = ((float)anzGesamt / (float)thisYear)*100;	//growth rate
+		statusOut.println("Wachstumsrate: "+growthRate+", Urban: "+anzGesamt);
+		double percent_urban = (100.0 *(thisYear+roadCount) / (totalPixels-roadCount-excldCount));
+		
+		//Boom-Year
+		if(growthRate > criticalHigh){		//if the growth rate exceeds the critical high value
+			slope -= (float)percent_urban * (float)slopeSens;	//decrease the slope coefficient
+			if(slope <= 0.01)		//if it is already very low, make it 1
+				slope = 1.0;
+			roadGravity += (float)percent_urban * roadGravSens;	//increase the road Gravity
+			if(roadGravity > 100.0)
+				roadGravity = 100.0;
+			if(disp < 100.0){		//increase the other coefficients by multiplying with the boom parameter
+				disp *= boom;
+				if(disp > 100.0)
+					disp = 100.0;
+				breed *= boom;
+				if(breed > 100.0)
+					breed = 100.0;
+				spread *= boom;
+				if(spread > 100.0)
+					spread = 100.0;
+			}
+		}
+		//Bust-Year
+		if(growthRate < criticalLow){		//if the growth rate falls below the critical low value
+			slope += (float)percent_urban * (float)slopeSens;	//increase the slope coefficient
+			if(slope > MaxSlopeResistance)
+				slope = MaxSlopeResistance;
+			roadGravity -= (float)percent_urban * roadGravSens;	//decrease the road Gravity
+			if(roadGravity <= 0.01)
+				roadGravity = 1.0;
+			if(growthRate < criticalLow && disp > 0){	//decrease the other coefficients by multiplying with the bust parameter
+				disp *= bust;
+				if(disp <= 0.01)
+					disp = 1.0;
+				spread *= bust;
+				if(spread <= 0.01)
+					spread = 1.0;
+				breed *= bust;
+				if(breed <= 0.01)
+					breed = 1.0;
+			}
+		}
+		System.out.println("thisYear: "+thisYear+", roadCount: "+roadCount+", excldCount: "+excldCount+", percent_urban: "+percent_urban);
+		System.out.println("Slope-Sensitivity: "+slope+", RoadGravity-Sensitivity: "+roadGravity+", Diffusion-Sensitivity: "+disp+", Breed-Sensitivity: "+breed+", Spread-Sensitivity: "+spread);
+		
+		System.out.println("Finished step " + (stepNo) + " in "
+				+ ((System.currentTimeMillis() - localStartTime)) + " ms\n");
+		localStartTime = System.currentTimeMillis();
+	}
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModificationContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModificationContentManager.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModelSelfModificationContentManager.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -0,0 +1,35 @@
+package edu.bonn.xulu.plugin.model.sleuth;
+
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+
+
+public class UrbanGrowthModelSelfModificationContentManager extends UrbanGrowthModelContentManager {
+	
+	public UrbanGrowthModelSelfModificationContentManager(int additionalRes) {
+		super(6+additionalRes);
+	
+	    resource[13]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Road Gravity Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[14]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Slope Sensitivity",ScalarProperty.class,Double.class,false);
+	    resource[15]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical Low",ScalarProperty.class,Double.class,false);
+	    resource[16]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Critical High",ScalarProperty.class,Double.class,false);
+	    resource[17]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Boom",ScalarProperty.class,Double.class,false);
+	    resource[18]= new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Bust",ScalarProperty.class,Double.class,false);
+	    
+	 	// ===== Ressourcen Bezeichnungen lokalisieren =====
+	    resetCaptions(null);
+	}
+	
+	public UrbanGrowthModelSelfModificationContentManager() {
+		this(0);
+		
+	}
+	
+	@Override
+	public void checkAndError() throws XuluDataException {
+		// TODO Auto-generated method stub
+		super.checkAndError();
+	}
+}

Modified: trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel_MC.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel_MC.java	2009-11-05 08:53:41 UTC (rev 64)
+++ trunk/src/edu/bonn/xulu/plugin/model/sleuth/UrbanGrowthModel_MC.java	2009-11-06 13:33:59 UTC (rev 65)
@@ -93,7 +93,7 @@
 			 * DISPERSION and BREED (Growth Phase 1 and 2)
 			 *****************************************************************/
 			boolean[][] tmpGridDisp = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
-			tmpGridDisp = DispersionGrowth();	//calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
+			tmpGridDisp = DispersionGrowth(disp_value,breed);	//calls the method "DispersionBreed" to perform the Dispersion and Breed Growth Phase
 			int anzDispBreed = 0;	//number of cells urbanized by Dispersion and Breed
 			for (int x = 0; x < inputGrid.getWidth();x++)
 				for(int y = 0; y < inputGrid.getHeight();y++){
@@ -111,7 +111,7 @@
 			 * EDGE
 			 *********************************************************************/
 			boolean[][] tmpGridSpread = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
-			tmpGridSpread = EdgeGrowth();	//calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
+			tmpGridSpread = EdgeGrowth(spread);	//calls the method "EdgeGrowth" to perform the Spread (Edge Growth) Phase
 			int anzSpread = 0;	//number of cells urbanized by Spread
 			for (int x = 0; x < inputGrid.getWidth();x++)
 				for(int y = 0; y < inputGrid.getHeight();y++){
@@ -130,7 +130,7 @@
 			 *********************************************************************/
 			
 			boolean[][] tmpGridRoad = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];	//a temporary raster
-			tmpGridRoad = RoadGrowth(tmpGrid);	//calls the method "RoadGrowth" to perform the Road weighted growth
+			tmpGridRoad = RoadGrowth(tmpGrid,rg_value,breed,disp);	//calls the method "RoadGrowth" to perform the Road weighted growth
 			int anzRoad = 0;	//number of cells urbanized by Road Growth
 			for (int x = 0; x < inputGrid.getWidth();x++)
 				for(int y = 0; y < inputGrid.getHeight();y++){
@@ -180,7 +180,7 @@
 		countSetIndividuals();	//sets the outputGrid to the initial inputGrid in order to start the next modelling step with the same initial map
 		System.out.println("Finished step " + (stepNo) + " in "
 				+ ((System.currentTimeMillis() - localStartTime)) + " ms\n");
-			if (stepNo == MonteCarlo){
+		if (stepNo == MonteCarlo){
 			outStep.addGrid();	//add a final raster to the GridList (contains the sum of all iterations)
 			
 			for (int y = 1; y < inputGrid.getHeight()-1;y++ ) {



More information about the Xulu-commits mailing list