From a5d40c44fd81a4ec2fdb3222734e5be1bcc26aab Mon Sep 17 00:00:00 2001
From: Peter Alexander <peter@blackhillock.co.uk>
Date: Wed, 5 Aug 2015 15:00:03 +0100
Subject: [PATCH] Changes to read newer format LPJ yield file (one for all fert
 rates)

---
 config.properties                             |   2 +-
 src/ac/ed/lurg/ModelMain.java                 |  10 +-
 src/ac/ed/lurg/types/FertiliserRate.java      |  22 +-
 src/ac/ed/lurg/types/IrrigationRate.java      |  14 +-
 .../lurg/yield/LPJYieldResponseMapReader.java | 195 ++++++------------
 .../raster/AbstractTabularRasterReader.java   |   4 +-
 6 files changed, 86 insertions(+), 161 deletions(-)

diff --git a/config.properties b/config.properties
index c87e4957..95a36d5f 100644
--- a/config.properties
+++ b/config.properties
@@ -1,2 +1,2 @@
 BASE_DIR=/Users/peteralexander/Documents/R_Workspace/UNPLUM
-YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/
\ No newline at end of file
+YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ
\ No newline at end of file
diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index 2ce1ffb0..54c1b213 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -26,7 +26,6 @@ import ac.ed.lurg.landuse.LandCoverReader;
 import ac.ed.lurg.output.LpjgOutputer;
 import ac.ed.lurg.types.CropToDoubleMap;
 import ac.ed.lurg.types.CropType;
-import ac.ed.lurg.types.FertiliserRate;
 import ac.ed.lurg.types.ModelFitType;
 import ac.ed.lurg.utils.LogWriter;
 import ac.ed.lurg.yield.LPJYieldResponseMapReader;
@@ -280,13 +279,8 @@ public class ModelMain {
 	}
 
 	private YieldRaster getYieldSurfaces(int year) {
-		LPJYieldResponseMapReader yieldReader = new LPJYieldResponseMapReader(ModelConfig.YIELD_DIR + File.separator + year, desiredProjection);
-
-		for (FertiliserRate fr : FertiliserRate.values()) {
-			yieldReader.getRasterDataFromFile(fr); 
-		}
-
-		return yieldReader.getYieldRaster();
+		LPJYieldResponseMapReader yieldReader = new LPJYieldResponseMapReader(desiredProjection);
+		return yieldReader.getRasterData(ModelConfig.YIELD_DIR + File.separator + year); 
 	}
 
 	private RasterSet<IrrigationCostItem> getIrrigationCosts() {
diff --git a/src/ac/ed/lurg/types/FertiliserRate.java b/src/ac/ed/lurg/types/FertiliserRate.java
index ea1babc0..03a55555 100644
--- a/src/ac/ed/lurg/types/FertiliserRate.java
+++ b/src/ac/ed/lurg/types/FertiliserRate.java
@@ -1,23 +1,17 @@
 package ac.ed.lurg.types;
 
-import java.io.File;
-
 public enum FertiliserRate {
-	//	NO_FERT("yield_1996_2005_minfert_CRU.out"),
-	//	MID_FERT("yield_1996_2005_middlefert_CRU.out"),
-	//   MAX_FERT("yield_1996_2005_highfert_CRU.out");
-	
-	NO_FERT("minfert" + File.separator + "anpp_1996_2005"),
-	MID_FERT("middlefert" + File.separator + "anpp_1996_2005"),
-	MAX_FERT("highfert" + File.separator + "anpp_1996_2005");
+	NO_FERT("lo"),
+	MID_FERT("me"),
+	MAX_FERT("hi");
 
-	private String fileName;
+	private String fertId;
 	
-	FertiliserRate(String fileName) {
-		this.fileName = fileName;
+	FertiliserRate(String fertId) {
+		this.fertId = fertId;
 	}
 
-	public String getFileName() {
-		return fileName;
+	public String getId() {
+		return fertId;
 	}
 }
diff --git a/src/ac/ed/lurg/types/IrrigationRate.java b/src/ac/ed/lurg/types/IrrigationRate.java
index 40344843..b4ce1b35 100644
--- a/src/ac/ed/lurg/types/IrrigationRate.java
+++ b/src/ac/ed/lurg/types/IrrigationRate.java
@@ -1,6 +1,16 @@
 package ac.ed.lurg.types;
 
 public enum IrrigationRate {
-	NO_IRRIG(), 
-	MAX_IRRIG();
+	NO_IRRIG(""), 
+	MAX_IRRIG("i");
+	
+	private String irrigId;
+	
+	IrrigationRate(String irrigId) {
+		this.irrigId = irrigId;
+	}
+
+	public String getId() {
+		return irrigId;
+	}
 }
diff --git a/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java b/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java
index 5b69ec47..c34b8ec9 100644
--- a/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java
+++ b/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java
@@ -1,8 +1,7 @@
 package ac.ed.lurg.yield;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileReader;
+import java.util.Map;
 
 import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.types.CropType;
@@ -11,26 +10,22 @@ import ac.ed.lurg.types.IrrigationRate;
 import ac.ed.lurg.types.YieldType;
 import ac.ed.lurg.utils.LogWriter;
 import ac.ed.lurg.utils.WatchForFile;
+import ac.sac.raster.AbstractTabularRasterReader;
 import ac.sac.raster.RasterHeaderDetails;
+import ac.sac.raster.RasterKey;
 
-public class LPJYieldResponseMapReader {	
+public class LPJYieldResponseMapReader extends AbstractTabularRasterReader<YieldResponsesItem> {	
 
-	private YieldRaster dataset;
-	private String rootDir;
-
-	public LPJYieldResponseMapReader(String rootDir, RasterHeaderDetails rasterProj) {
-		this.rootDir = rootDir;
-		dataset = new YieldRaster(rasterProj);
-	}
+	private RasterHeaderDetails rasterProj;
 	
-	private String[] parseLine(String line) {
-		return line.split(" +");
+	public LPJYieldResponseMapReader(RasterHeaderDetails rasterProj) {
+		super(" +", 10);
+		this.rasterProj = rasterProj; 
 	}
 
-	public YieldRaster getRasterDataFromFile(FertiliserRate fr) {
+	public YieldRaster getRasterData(String rootDir) {
+		// wait for data to be available
 		long startTime = System.currentTimeMillis();
-
-		// wait
 		WatchForFile fileWatcher = new WatchForFile(new File(rootDir + File.separator + "done"));
 		boolean foundFile = fileWatcher.await(ModelConfig.LPJG_MONITOR_TIMEOUT_SEC);
 		if (!foundFile) {
@@ -39,128 +34,60 @@ public class LPJYieldResponseMapReader {
 		}
 		LogWriter.println("Found marker file in " + (System.currentTimeMillis() - startTime) + " ms");
 
-		String filename = rootDir + File.separator + fr.getFileName();
-
-		YieldType noIrrigYieldType = YieldType.getYieldType(fr, IrrigationRate.NO_IRRIG);  // just do this look up once per file
-		YieldType maxIrrigYieldType = YieldType.getYieldType(fr, IrrigationRate.MAX_IRRIG);
-
-		int col=0;
-				
-		try {
-			BufferedReader in = new BufferedReader(new FileReader(filename));
-			String line;
-			in.readLine(); // read header
-			YieldRecord record = null;
-
-			while ((line=in.readLine()) != null) {
-				String[] tokens = parseLine(line.trim());
-				record = new YieldRecord();
-
-				for (String token : tokens) {
-					double d = Double.parseDouble(token);
-
-					switch (col) {
-					case 0:
-						record.x = d;
-						break;
-					case 1:
-						record.y = d;
-						break;
-					case 2:
-						//YieldRecord values in kg DM / m2, we want t/ha, so 10 times larger
-						record.c3Pasture = d * 10;
-						break;
-					case 3:
-						record.c4Pasture = d * 10;
-						break;
-					case 4:
-						record.teWW = d * 10;
-						break;
-					case 5:
-						record.teSW = d * 10;
-						break;
-					case 6:
-						record.teCo = d * 10;
-						break;
-					case 7:
-						record.trRi = d * 10;
-						break;
-					case 8:
-						record.teWWirr = d * 10;
-						break;
-					case 9:
-						record.teSWirr = d * 10;
-						break;
-					case 10:
-						record.teCoirr = d * 10;
-						break;
-					case 11:
-						record.trRiirr = d * 10;
-						break;
-					}
-
-					col++;
-				}
-				YieldResponsesItem data = dataset.getFromCoordinates(record.x, record.y);
-				setData(noIrrigYieldType, maxIrrigYieldType, data, record);
-				col=0;
-			}
-			in.close();
-		}
-		catch (Exception e) {
-			LogWriter.printlnError("Problem reading regional yield data: col:" + col);
-			e.printStackTrace();
-		}
-
-		LogWriter.println("Reading " + filename + ", took " + (System.currentTimeMillis() - startTime) + " ms");
-
-		return dataset;
-	}
-	
-	
-	public YieldRaster getYieldRaster() {
-		return dataset;
-	}
-	
-	public void setData(YieldType noIrrigYieldType, YieldType maxIrrigYieldType, YieldResponsesItem item, YieldRecord record) {
+		YieldRaster yieldRaster = new YieldRaster(rasterProj);
+		dataset = yieldRaster;
 		
-		boolean isSpringWheat = (record.teSW > record.teWW);
-		item.setIsSpringWheat(isSpringWheat);
+		String nppFilename = rootDir + File.separator + "anpp.out";
+		getRasterDataFromFile(nppFilename);
+
+		String yieldFilename = rootDir + File.separator + "yield.out";
+		getRasterDataFromFile(yieldFilename);
 		
-		item.setYield(noIrrigYieldType, CropType.WHEAT, isSpringWheat ? record.teSW : record.teWW);
-		item.setYield(maxIrrigYieldType, CropType.WHEAT, isSpringWheat ? record.teSWirr : record.teWWirr);
-		item.setYield(noIrrigYieldType, CropType.MAIZE, record.teCo);
-		item.setYield(maxIrrigYieldType, CropType.MAIZE, record.teCoirr);
-		item.setYield(noIrrigYieldType, CropType.RICE, record.trRi);
-		item.setYield(maxIrrigYieldType, CropType.RICE, record.trRiirr);
+		return yieldRaster;
+	}
 		
-		item.setYield(noIrrigYieldType, CropType.TROPICAL_CEREALS, record.teCo);
-		item.setYield(maxIrrigYieldType, CropType.TROPICAL_CEREALS, record.teCoirr);
-		item.setYield(noIrrigYieldType, CropType.OILCROPS, record.teWW);
-		item.setYield(maxIrrigYieldType, CropType.OILCROPS, record.teWWirr);
-		item.setYield(noIrrigYieldType, CropType.SOYBEAN, record.teSW);
-		item.setYield(maxIrrigYieldType, CropType.SOYBEAN, record.teSWirr);
-		item.setYield(noIrrigYieldType, CropType.PULSES, record.teSW);
-		item.setYield(maxIrrigYieldType, CropType.PULSES, record.teSWirr);
-		item.setYield(noIrrigYieldType, CropType.STARCHY_ROOTS, record.teSW);
-		item.setYield(maxIrrigYieldType, CropType.STARCHY_ROOTS, record.teSWirr);
+	@Override
+	protected void setData(RasterKey key, YieldResponsesItem item, Map<String, Double> rowValues) {
 		
-		item.setYield(noIrrigYieldType, CropType.PASTURE, Math.max(record.c3Pasture + record.c4Pasture, 0));
-		item.setYield(maxIrrigYieldType, CropType.PASTURE,  Math.max(record.c3Pasture + record.c4Pasture, 0)*1.2);
-	}
-	
-	class YieldRecord {
-		double x;
-		double y;
-		double c3Pasture;
-		double c4Pasture;
-		double teSW;
-		double teSWirr;
-		double teWW;
-		double teWWirr;
-		double teCo;
-		double teCoirr;
-		double trRi;
-		double trRiirr;
+		if (rowValues.containsKey("C4G_pas".toLowerCase())) { // need to work out if it's the yield.out or the anpp.out file, this isn't very nice, but should work ok
+			
+			//  C3G_pas C4G_pas  TeWWhi  TeWWme  TeWWlo  TeSWhi  TeSWme  TeSWlo  TeCohi  TeCome  TeColo  TrRihi  TrRime  TrRilo   Total     Crop_sum  Pasture_sum
+			double adjFactor = 20;  // 2 for carbon units, and 10 for kg/m2 to t/ha
+			double pastureYield = Math.max(getValueForCol(rowValues, "C3G_pas") + getValueForCol(rowValues, "C4G_pas"), 0) * adjFactor;
+			
+			item.setYield(YieldType.NO_FERT_NO_IRRIG, CropType.PASTURE, pastureYield);
+			item.setYield(YieldType.NO_FERT_IRRIG_MAX, CropType.PASTURE,  pastureYield*1.2);
+			item.setYield(YieldType.FERT_MAX_NO_IRRIG, CropType.PASTURE,  pastureYield*1.2);
+			item.setYield(YieldType.FERT_MAX_IRRIG_MAX, CropType.PASTURE,  pastureYield*1.3);
+		}
+		else {
+			//	TeWWhi  TeWWme  TeWWlo  TeSWhi  TeSWme  TeSWlo  TeCohi  TeCome  TeColo  TrRihi  TrRime  TrRilo
+			double adjFactor = 10;  // 10 for kg/m2 to t/ha
+
+			boolean isSpringWheat = (getValueForCol(rowValues, "teSWhi") > getValueForCol(rowValues, "TeWWhi"));
+			item.setIsSpringWheat(isSpringWheat);
+						
+			for (FertiliserRate fert : FertiliserRate.values()) {
+				for (IrrigationRate irrig : IrrigationRate.values()) {
+					YieldType yieldType = YieldType.getYieldType(fert, irrig);
+					
+					String fertIrrigString = irrig.getId() + fert.getId();
+					double ww = getValueForCol(rowValues, "TeWW" + fertIrrigString) * adjFactor;
+					double sw = getValueForCol(rowValues, "TeSW" + fertIrrigString) * adjFactor;
+					double co = getValueForCol(rowValues, "TeCo" + fertIrrigString) * adjFactor;
+					double ri = getValueForCol(rowValues, "TeRi" + fertIrrigString) * adjFactor;
+					
+					item.setYield(yieldType, CropType.WHEAT, isSpringWheat ? sw : ww);
+					item.setYield(yieldType, CropType.MAIZE, co);
+					item.setYield(yieldType, CropType.RICE, ri);
+					
+					item.setYield(yieldType, CropType.TROPICAL_CEREALS, co);
+					item.setYield(yieldType, CropType.OILCROPS, ww);
+					item.setYield(yieldType, CropType.SOYBEAN, sw);
+					item.setYield(yieldType, CropType.PULSES, sw);
+					item.setYield(yieldType, CropType.STARCHY_ROOTS, sw);
+				}
+			}
+		}
 	}
 }
\ No newline at end of file
diff --git a/src/ac/sac/raster/AbstractTabularRasterReader.java b/src/ac/sac/raster/AbstractTabularRasterReader.java
index 927b562c..fe20b043 100644
--- a/src/ac/sac/raster/AbstractTabularRasterReader.java
+++ b/src/ac/sac/raster/AbstractTabularRasterReader.java
@@ -70,7 +70,7 @@ public abstract class AbstractTabularRasterReader<D extends RasterItem> {
 			in.close();
 		}
 		catch (Exception e) {
-			LogWriter.printlnError("Problem reading data file");
+			LogWriter.printlnError("Problem reading data file " + filename);
 			e.printStackTrace();
 			throw new RuntimeException(e);
 		}
@@ -89,7 +89,7 @@ public abstract class AbstractTabularRasterReader<D extends RasterItem> {
 	}
 	
 	protected double getValueForCol(Map<String, Double> rowValues, String colName) {
-		Double d = rowValues.get(colName);
+		Double d = rowValues.get(colName.toLowerCase());
 		if (d == null) {
 			LogWriter.printlnError("Can't find column name " + colName);
 			throw new RuntimeException("Can't find column name " + colName);
-- 
GitLab