From dd1a2063d6c1f207cecf091a2f91aec1a7ba235c Mon Sep 17 00:00:00 2001 From: Peter Alexander <peter@blackhillock.co.uk> Date: Tue, 7 Jul 2015 12:28:10 +0100 Subject: [PATCH] Changes to fix reading of LPJG file --- src/ac/ed/lurg/ModelMain.java | 4 + .../country/gams/GamsRasterOptimiser.java | 107 +++++++++++------- .../lurg/yield/LPJYieldResponseMapReader.java | 31 +++-- src/ac/ed/lurg/yield/YieldResponse.java | 4 +- src/ac/sac/raster/RasterKey.java | 2 +- src/ac/sac/raster/RasterSet.java | 5 +- src/ac/sac/raster/RasterSetTest.java | 19 ++++ 7 files changed, 118 insertions(+), 54 deletions(-) create mode 100644 src/ac/sac/raster/RasterSetTest.java diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index 6c28770b..c937c928 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -67,6 +67,10 @@ public class ModelMain { private void doTimestep(int timestep) { YieldRaster yieldSurfaces = getYieldSurfaces(timestep); + +// YieldResponsesItem yresp = yieldSurfaces.getFromCoordinates(-50.0, -4.0); +// LogWriter.printlnError("Test key: " + yresp.getYieldMax(CropType.CEREALS) + ", " + yresp.getYieldFertOnly(CropType.CEREALS) + ", " + yresp.getYieldIrrigOnly(CropType.CEREALS)); + LogWriter.println("Timestep " + timestep); CropToDoubleMap totalArea = new CropToDoubleMap(); diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java index 1113aa8f..55dce778 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java @@ -25,7 +25,7 @@ import ac.sac.raster.RasterKey; import ac.sac.raster.RasterSet; public class GamsRasterOptimiser { - public static final boolean DEBUG = false; + public static final boolean DEBUG = true; private GamsRasterInput rasterInputData; private LazyHashMap<Integer, Set<RasterKey>> mapping; @@ -49,28 +49,28 @@ public class GamsRasterOptimiser { private GamsRasterOutput convertToRaster(GamsLocationInput gamsInput, GamsLocationOutput gamsOutput) { RasterSet<AreasItem> newAreaRaster = allocAreas(gamsInput.getPreviousAreas(), gamsOutput); RasterSet<IntensitiesItem> newIntensityRaster = allocIntensities(gamsOutput); - + return new GamsRasterOutput(gamsOutput.getStatus(), newIntensityRaster, newAreaRaster, gamsOutput.getCommoditiesData()); } private RasterSet<AreasItem> allocAreas(Map<Integer, ? extends AreasItem> prevAreasAgg, GamsLocationOutput gamsOutput) { RasterSet<AreasItem> newAreaRaster = new RasterSet<AreasItem>(); RasterSet<AreasItem> prevAreaRaster = rasterInputData.getPreviousAreas(); - + for (Map.Entry<Integer, AreasItem> entry : gamsOutput.getCropAreas().entrySet()) { Integer locId = entry.getKey(); AreasItem newAreaAggItem = entry.getValue(); AreasItem prevAreaAggItem = prevAreasAgg.get(locId); Set<RasterKey> keys = mapping.get(locId); - + CropToDouble cropChangeTotals = newAreaAggItem.getCropChanges(prevAreaAggItem); - if (DEBUG) LogWriter.println("Processing location id " + locId); + // if (DEBUG) LogWriter.println("Processing location id " + locId); double shortfall = allocAllAreasForAgg(newAreaRaster, prevAreaRaster, keys, cropChangeTotals); if (shortfall > 0) LogWriter.printlnError("This should never happen, due to GAMS constraint. Not able to incorporate all changes, as not enough forest or natural areas left: " + shortfall); } - + return newAreaRaster; } @@ -79,9 +79,9 @@ public class GamsRasterOptimiser { double totalShortfall = 0; Set<RasterKey> keysWithSpace = new HashSet<RasterKey>(); CropToDouble avgCropChange = cropChange.scale(1.0/keys.size()); - + for (RasterKey key : keys) { - if (DEBUG) LogWriter.println(" Processing raster key " + key); + //if (DEBUG) LogWriter.println(" Processing raster key " + key); AreasItem prevAreasRasterItem = prevAreaRaster.get(key); AreasItem newAreasRasterItem = new AreasItem(); @@ -97,13 +97,13 @@ public class GamsRasterOptimiser { if (totalShortfall > 0 & keysWithSpace.size() > 0) { // more to allocate and some free areas to allocate into if (DEBUG) LogWriter.println("A total area of " + totalShortfall + " is unallocated, so trying again with areas with space"); double factor = totalShortfall / cropChange.getTotal(); - + allocAllAreasForAgg(newAreaRaster, newAreaRaster, keysWithSpace, cropChange.scale(factor)); } return totalShortfall; } - + /** returns the net area of crop change that not been able to be allocated */ private double allocRasterArea(AreasItem newAreasRasterItem, AreasItem prevAreasRasterItem, CropToDouble cropChange) { @@ -114,7 +114,7 @@ public class GamsRasterOptimiser { double prevNatural = prevAreasRasterItem.getLandCoverArea(LandDataType.OTHER_NATURAL); double ratioOfChanges = 1; - + if (netAddedCrop > prevForest + prevNatural) { ratioOfChanges = (prevForest + prevNatural) / netAddedCrop; forestRemoved = prevForest; @@ -139,9 +139,9 @@ public class GamsRasterOptimiser { for (CropType crop : CropType.values()) { double prevCropArea = prevAreasRasterItem.getCropArea(crop); Double d = cropChange.get(crop); - + double additionalArea = (d == null) ? 0 : d * ratioOfChanges; - // LogWriter.println(String.format("%s, %.1f", crop, additionalArea)); + // LogWriter.println(String.format("%s, %.1f", crop, additionalArea)); newAreasRasterItem.setCropArea(crop, prevCropArea + additionalArea); } @@ -171,11 +171,32 @@ public class GamsRasterOptimiser { RasterSet<AreasItem> cropAreaRaster = rasterInputData.getPreviousAreas(); RasterSet<IrrigationCostItem> irrigCostRaster = rasterInputData.getIrrigationCost(); - List<Double> cerealDivisions = getDivisions(yieldRaster, CropType.CEREALS, 2); - List<Double> pastureDivisions = getDivisions(yieldRaster, CropType.MEAT_OR_PASTURE, 2); + { + // YieldResponsesItem yresp = yieldRaster.getFromCoordinates(-118.0, -33.0); + // LogWriter.printlnError("Test key2: " + yresp.getYieldMax(CropType.CEREALS) + ", " + yresp.getYieldFertOnly(CropType.CEREALS) + ", " + yresp.getYieldIrrigOnly(CropType.CEREALS)); + } + + // look for inconsistencies + for (Entry<RasterKey, YieldResponsesItem> entry : yieldRaster.entrySet()) { + + YieldResponsesItem yresp = entry.getValue(); + RasterKey key = entry.getKey(); + + if (yresp != null && (yresp.getYieldMax(CropType.CEREALS) < yresp.getYieldFertOnly(CropType.CEREALS) || yresp.getYieldMax(CropType.CEREALS) < yresp.getYieldIrrigOnly(CropType.CEREALS))) { + LogWriter.printlnError(key.getCol() + ", " + key.getRow() + ": " + yieldRaster.getXCoordin(key) + ", " + yieldRaster.getYCoordin(key) + ": " + yresp.getYieldMax(CropType.CEREALS) + ", " + yresp.getYieldFertOnly(CropType.CEREALS) + ", " + yresp.getYieldIrrigOnly(CropType.CEREALS)); + } + // else if (yresp != null) + // LogWriter.println(key.getCol() + ", " + key.getRow() + ": " + yieldRaster.getXCoordin(key) + ", " + yieldRaster.getYCoordin(key) + ": " + yresp.getYieldMax(CropType.CEREALS) + ", " + yresp.getYieldFertOnly(CropType.CEREALS) + ", " + yresp.getYieldIrrigOnly(CropType.CEREALS)); + + } - int numCerealCats = (1+cerealDivisions.size()); - if (DEBUG) LogWriter.println("Making " + numCerealCats * (1+pastureDivisions.size()) + " categories"); + int numCerealCats = 4; + int numPastureCats = 4; + + List<Double> cerealDivisions = getDivisions(yieldRaster, CropType.CEREALS, numCerealCats); + List<Double> pastureDivisions = getDivisions(yieldRaster, CropType.MEAT_OR_PASTURE, numPastureCats); + + if (DEBUG) LogWriter.println("Making " + numCerealCats * numPastureCats + " categories"); LazyHashMap<Integer, AveragingYieldResponsesItem> aggregatedYields = new LazyHashMap<Integer, AveragingYieldResponsesItem>() { protected AveragingYieldResponsesItem createValue() { return new AveragingYieldResponsesItem(); } @@ -190,14 +211,18 @@ public class GamsRasterOptimiser { protected Set<RasterKey> createValue() { return new HashSet<RasterKey>(); } }; + int countFound = 0, countMissing = 0; + for (Entry<RasterKey, YieldResponsesItem> entry : yieldRaster.entrySet()) { YieldResponsesItem yresp = entry.getValue(); RasterKey key = entry.getKey(); - + if (yresp == null) { + countMissing++; LogWriter.printlnError("No YieldResponsesItem for " + key + ", x=" + yieldRaster.getXCoordin(key) + ", y=" + yieldRaster.getYCoordin(key)); } else { + countFound++; //LogWriter.println("YieldResponsesItem found for " + key + ", x=" + yieldRaster.getXCoordin(key) + ", y=" + yieldRaster.getYCoordin(key)); AreasItem cropAreas = cropAreaRaster.get(key); @@ -205,18 +230,18 @@ public class GamsRasterOptimiser { LogWriter.printlnError("GamsRasterOptimiser: Can't find cropAreas for " + key); continue; } - + IrrigationCostItem irrigCost = irrigCostRaster.get(key); - + int cerealCat = findCategory(cerealDivisions, yresp.getYieldMax(CropType.CEREALS)); int pastureCat = findCategory(pastureDivisions, yresp.getYieldMax(CropType.MEAT_OR_PASTURE)); Integer id = cerealCat + pastureCat * numCerealCats; - + AveragingYieldResponsesItem avgYResp = aggregatedYields.lazyGet(id); AreasItem aggAreas = aggregatedAreas.lazyGet(id); IrrigationCostItem avgIrigCost = aggregatedIrrigCosts.lazyGet(id); mapping.lazyGet(id).add(entry.getKey()); - + // Irrigation cost double suitableAreaThisTime = cropAreas.getSuitableLand(); if (irrigCost!= null && suitableAreaThisTime > 0) { @@ -230,12 +255,12 @@ public class GamsRasterOptimiser { for (YieldType yieldType : YieldType.values()) { avgYResp.setYield(yieldType, crop, yresp.getYield(yieldType, crop)); } - + double areaSoFar = aggAreas.getCropArea(crop); double areaThisTime = cropAreas.getCropArea(crop); aggAreas.setCropArea(crop, areaSoFar + areaThisTime); } - + // Land cover, we only need forest and other natural for (LandDataType landType : Arrays.asList(LandDataType.FOREST, LandDataType.OTHER_NATURAL)) { double areaThisTime = cropAreas.getLandCoverArea(landType); @@ -244,13 +269,14 @@ public class GamsRasterOptimiser { } } } - - if (DEBUG) { - for (Map.Entry<Integer, Set<RasterKey>> e : mapping.entrySet()) { - LogWriter.println(e.getKey() + " category has " + e.getValue().size() + " raster areas"); - for (RasterKey key : e.getValue()) { - LogWriter.println(String.format("\t%s: yields pasture=%.1f, cereal=%.1f", key, yieldRaster.get(key).getYieldMax(CropType.MEAT_OR_PASTURE), yieldRaster.get(key).getYieldMax(CropType.CEREALS))); - } + + LogWriter.println("YieldResponsesItem: " + rasterInputData.getCountryInput().getCountry() + ", countFound=" + countFound + ", countMissing=" + countMissing); + + + for (Map.Entry<Integer, Set<RasterKey>> e : mapping.entrySet()) { + LogWriter.println(e.getKey() + " category has " + e.getValue().size() + " raster areas"); + if (DEBUG) for (RasterKey key : e.getValue()) { + LogWriter.println(String.format("\t%s: yields pasture=%.1f, cereal=%.1f", key, yieldRaster.get(key).getYieldMax(CropType.MEAT_OR_PASTURE), yieldRaster.get(key).getYieldMax(CropType.CEREALS))); } } @@ -262,7 +288,7 @@ public class GamsRasterOptimiser { int numDivisions = divisions.size(); for (category = 0; category<numDivisions; category++) { - if (yield > divisions.get(category)) { + if (yield < divisions.get(category)) { break; } } @@ -274,28 +300,31 @@ public class GamsRasterOptimiser { for (YieldResponsesItem yresp : yieldRaster.values()) { if (yresp == null) { - //LogWriter.println("GamsRasterOptimiser: Can't get value for crop " + crop); + if (DEBUG) LogWriter.println("GamsRasterOptimiser: Can't get value for crop " + crop); } else { double d = yresp.getYieldMax(crop); - - if (Double.isNaN(d)) - LogWriter.println("GamsRasterOptimiser: Got NaN value for crop " + crop); - else + //LogWriter.println("GamsRasterOptimiser: Got value for crop " + crop + " of " + d); + + if (Double.isNaN(d) || d == 0.0) { + if (DEBUG) LogWriter.println("GamsRasterOptimiser: Got NaN or zero value for crop " + crop); + } + else { yieldValues.add(d); + } } } if (yieldValues.size() == 0) { throw new RuntimeException("No yield values for country, crop = " + crop); } - + Collections.sort(yieldValues); List<Double> divisions = new ArrayList<Double>(); for (int i=1; i < numCategories; i++) { - double d = yieldValues.get(yieldValues.size()/numCategories); + double d = yieldValues.get(yieldValues.size()/numCategories*i); divisions.add(d); } diff --git a/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java b/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java index 1f21ede6..343b7abe 100644 --- a/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java +++ b/src/ac/ed/lurg/yield/LPJYieldResponseMapReader.java @@ -55,21 +55,29 @@ public class LPJYieldResponseMapReader { record.y = d; break; case 2: - record.teWW = d; + record.teSW = d; break; case 3: - record.trRi = d; + record.teSWirr = d; break; case 4: - record.teCo = d; + record.teWW = d; break; case 5: - record.teSo = d; + record.teWWirr = d; break; case 6: - record.teWWirr = d; + record.teCo = d; + break; + case 7: + record.teCoirr = d; + break; + case 8: + record.trRi = d; + break; + case 9: + record.trRiirr = d; break; - } col++; @@ -99,18 +107,21 @@ public class LPJYieldResponseMapReader { //YieldRecord values in kg DM / m2, we want t/ha, so 10 times larger for (CropType crop : CropType.getAllItems()) { - item.setYield(noIrrigYieldType, crop, record.teWW * 10); - item.setYield(maxIrrigYieldType, crop, record.teWWirr * 10); + item.setYield(noIrrigYieldType, crop, record.teSW * 10); + item.setYield(maxIrrigYieldType, crop, record.teSWirr * 10); } } class YieldRecord { double x; double y; + double teSW; + double teSWirr; double teWW; double teWWirr; - double trRi; double teCo; - double teSo; + double teCoirr; + double trRi; + double trRiirr; } } \ No newline at end of file diff --git a/src/ac/ed/lurg/yield/YieldResponse.java b/src/ac/ed/lurg/yield/YieldResponse.java index 872cbbac..5aeb8d98 100644 --- a/src/ac/ed/lurg/yield/YieldResponse.java +++ b/src/ac/ed/lurg/yield/YieldResponse.java @@ -7,7 +7,7 @@ import ac.ed.lurg.types.YieldType; import ac.ed.lurg.utils.LogWriter; public class YieldResponse { - private Map<YieldType, Double> yields = new HashMap<YieldType, Double>(); + Map<YieldType, Double> yields = new HashMap<YieldType, Double>(); private double fertParm; private double irrigParm; @@ -37,7 +37,7 @@ public class YieldResponse { public double getIrrigParam() { if (irrigParm == 0) - irrigParm = calcParam (0, 0.6, 1); // we don't have a mide irrigation figure, so lets assume 60% at mid point + irrigParm = calcParam (0, 0.6, 1); // we don't have a mid irrigation figure, so lets assume 60% at mid point return irrigParm; } diff --git a/src/ac/sac/raster/RasterKey.java b/src/ac/sac/raster/RasterKey.java index 4b0def60..678e1a12 100755 --- a/src/ac/sac/raster/RasterKey.java +++ b/src/ac/sac/raster/RasterKey.java @@ -77,6 +77,6 @@ public class RasterKey implements Serializable { } public String toString() { - return "row:" + row + ", col:" + col; + return "col:" + col + ", row:" + row; } } diff --git a/src/ac/sac/raster/RasterSet.java b/src/ac/sac/raster/RasterSet.java index 9e2240aa..9a39a023 100755 --- a/src/ac/sac/raster/RasterSet.java +++ b/src/ac/sac/raster/RasterSet.java @@ -75,8 +75,8 @@ public class RasterSet<D extends RasterItem> extends HashMap<RasterKey, D> { } public double getYCoordin(RasterKey key) { - double x = header.getCellSize() * (key.getRow() + 1) + header.getYllCorner(); - return x; + double y = header.getCellSize() * (header.getNrows() - 1 - key.getRow()) + header.getYllCorner(); + return y; } /** Method to really get the data, or create it. Assumes the col and row are in the internal header format */ @@ -123,6 +123,7 @@ public class RasterSet<D extends RasterItem> extends HashMap<RasterKey, D> { public RasterSet<D> popSubsetForKeys(RasterSet<D> subset, Collection<RasterKey> keys) { for (RasterKey key : keys) { + //LogWriter.println("popSubsetForKeys: " + key.getCol() + ", " + key.getRow() + ": " + getXCoordin(key) + ", " + getYCoordin(key)); subset.put(key, get(key)); } return subset; diff --git a/src/ac/sac/raster/RasterSetTest.java b/src/ac/sac/raster/RasterSetTest.java new file mode 100644 index 00000000..55ba8547 --- /dev/null +++ b/src/ac/sac/raster/RasterSetTest.java @@ -0,0 +1,19 @@ +package ac.sac.raster; + +import org.junit.Test; + +import ac.ed.lurg.yield.YieldRaster; +import ac.ed.lurg.yield.YieldResponsesItem; + +public class RasterSetTest { + + @Test + public void test() { + YieldRaster dataset = new YieldRaster(new RasterHeaderDetails(720,360,-180,-90,0.5,"")); + double y = dataset.getYCoordin(new RasterKey(0,179)); + System.out.println("y=" +y); + + + } + +} -- GitLab