From 48609f7bcb2bbb4bb429fd2c608f2559821a0956 Mon Sep 17 00:00:00 2001 From: Peter Alexander <peter@blackhillock.co.uk> Date: Mon, 15 Dec 2014 16:51:02 +0000 Subject: [PATCH] 'cookie' cutter the yields for a particular country --- src/ac/ed/lurg/ModelConfig.java | 8 +- src/ac/ed/lurg/ModelContext.java | 9 +- src/ac/ed/lurg/ModelMain.java | 64 +++++++++++---- src/ac/ed/lurg/country/Country.java | 33 ++++---- src/ac/ed/lurg/country/CountryAgent.java | 82 ++++++------------- .../ed/lurg/country/CountryAgentCreator.java | 18 ++-- .../CountryBoundaryItem.java} | 30 ++----- .../lurg/country/CountryBoundaryReader.java | 30 +++++++ src/ac/ed/lurg/country/CountryManager.java | 70 ++++++++++++++++ ...{GamsInput.java => GamsLocationInput.java} | 4 +- ...imiser.java => GamsLocationOptimiser.java} | 12 +-- ...amsOutput.java => GamsLocationOutput.java} | 4 +- .../{GamsTest.java => GamsLocationTest.java} | 8 +- .../country/gams/GamsRasterOptimiser.java | 16 ++-- .../lurg/country/gams/GamsRasterOutput.java | 12 +-- .../ed/lurg/country/gams/GamsRasterTest.java | 4 +- src/ac/ed/lurg/demand/BaseConsumpManager.java | 3 +- src/ac/ed/lurg/demand/SspManager.java | 3 +- src/ac/ed/lurg/utils/CollectionHelper.java | 23 ++++++ src/ac/ed/lurg/yield/YieldManager.java | 76 ----------------- src/ac/ed/lurg/yield/YieldRaster.java | 16 +++- .../ed/lurg/yield/YieldResponseMapReader.java | 3 +- src/ac/ed/lurg/yield/YieldResponsesItem.java | 2 +- src/ac/sac/raster/AbstractRasterReader.java | 4 +- src/ac/sac/raster/RasterHeaderDetails.java | 19 +++-- src/ac/sac/raster/RasterSet.java | 6 +- 26 files changed, 300 insertions(+), 259 deletions(-) rename src/ac/ed/lurg/{yield/YieldKey.java => country/CountryBoundaryItem.java} (53%) create mode 100644 src/ac/ed/lurg/country/CountryBoundaryReader.java create mode 100644 src/ac/ed/lurg/country/CountryManager.java rename src/ac/ed/lurg/country/gams/{GamsInput.java => GamsLocationInput.java} (77%) rename src/ac/ed/lurg/country/gams/{GamsLandUseOptimiser.java => GamsLocationOptimiser.java} (96%) rename src/ac/ed/lurg/country/gams/{GamsOutput.java => GamsLocationOutput.java} (93%) rename src/ac/ed/lurg/country/gams/{GamsTest.java => GamsLocationTest.java} (94%) create mode 100644 src/ac/ed/lurg/utils/CollectionHelper.java delete mode 100644 src/ac/ed/lurg/yield/YieldManager.java diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index 8995025f..3f97841c 100644 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -91,14 +91,14 @@ public class ModelConfig { public static final String DEMAND_CURVES_FILE = DATA_DIR + File.separator + "com_curves.csv"; public static final String SSP_FILE = DATA_DIR + File.separator + "ssp.csv"; - public static final String COUNTRY_DATA_FILE = DATA_DIR + File.separator + "country_data.csv"; public static final String YIELD_DIR = DATA_DIR + File.separator + "yields"; - public static final String REF_YIELD_FILE = DATA_DIR + File.separator + "ref_yields.csv"; public static final String BASELINE_CONSUMP_FILE = DATA_DIR + File.separator + "base_consump.csv"; - + public static final String COUNTRY_BOUNDARY_FILE = DATA_DIR + File.separator + "country_boundaries.test.asc"; + public static final String COUNTRY_CODES_FILE = DATA_DIR + File.separator + "country_codes3.csv"; + + public static final String COUNTRY_DATA_FILE = DATA_DIR + File.separator + "country_data.csv"; - public static final int START_TIMESTEP = getIntProperty("START_TIMESTEP", 0); public static final int END_TIMESTEP = getIntProperty("END_TIMESTEP", 1); public static final int BASE_YEAR = getIntProperty("BASE_YEAR", 2010); diff --git a/src/ac/ed/lurg/ModelContext.java b/src/ac/ed/lurg/ModelContext.java index 703a4030..4acc81ef 100644 --- a/src/ac/ed/lurg/ModelContext.java +++ b/src/ac/ed/lurg/ModelContext.java @@ -1,23 +1,16 @@ package ac.ed.lurg; import ac.ed.lurg.demand.DemandManager; -import ac.ed.lurg.yield.YieldManager; public class ModelContext { private DemandManager demandManager; - private YieldManager yieldManager; - public ModelContext(DemandManager demandManager, YieldManager yieldManager) { + public ModelContext(DemandManager demandManager) { super(); this.demandManager = demandManager; - this.yieldManager = yieldManager; } public DemandManager getDemandManager() { return demandManager; } - - public YieldManager getYieldManager() { - return yieldManager; - } } diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index d13f0450..cb9ddf54 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -1,23 +1,32 @@ package ac.ed.lurg; import java.io.File; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import ac.ed.lurg.country.Country; import ac.ed.lurg.country.CountryAgent; import ac.ed.lurg.country.CountryAgentCreator; +import ac.ed.lurg.country.CountryBoundaryItem; +import ac.ed.lurg.country.CountryBoundaryReader; import ac.ed.lurg.demand.DemandManager; import ac.ed.lurg.types.CropType; import ac.ed.lurg.types.ModelFitType; import ac.ed.lurg.types.YieldType; -import ac.ed.lurg.yield.YieldManager; -import ac.ed.lurg.yield.YieldResponsesItem; +import ac.ed.lurg.utils.LogWriter; +import ac.ed.lurg.yield.YieldRaster; import ac.ed.lurg.yield.YieldResponseMapReader; +import ac.sac.raster.RasterKey; import ac.sac.raster.RasterSet; public class ModelMain { private Collection<CountryAgent> countryAgents; - ModelContext modelContext; + private ModelContext modelContext; + private Map<Country, List<RasterKey>> countryToKeysMap; public static void main(String[] args) { ModelMain theModel = new ModelMain(); @@ -28,13 +37,33 @@ public class ModelMain { /* setup models, reading inputs, etc. */ private void setup() { DemandManager demandManager = new DemandManager(ModelFitType.LOGISTIC, "SSP2_v9_130325"); + + modelContext = new ModelContext(demandManager); - YieldManager yieldManager = new YieldManager(); - - modelContext = new ModelContext(demandManager, yieldManager); - + countryToKeysMap = getCountryToKeysMap(); + countryAgents = new CountryAgentCreator().getAgents(modelContext); } + + private Map<Country, List<RasterKey>> getCountryToKeysMap() { + CountryBoundaryReader countryReader = new CountryBoundaryReader(); + RasterSet<CountryBoundaryItem> countryBoundaries = countryReader.getRasterDataFromFile(ModelConfig.COUNTRY_BOUNDARY_FILE); + + Map<Country, List<RasterKey>> countryToKeysMap = new HashMap<Country, List<RasterKey>>(); + + for (Map.Entry<RasterKey, CountryBoundaryItem> entry : countryBoundaries.entrySet()) { + List<RasterKey> keys = countryToKeysMap.get(entry.getValue().getCountry()); + + if (keys == null) { + keys = new ArrayList<RasterKey>(); + countryToKeysMap.put(entry.getValue().getCountry(), keys); + } + + keys.add(entry.getKey()); + } + + return countryToKeysMap; + } /* run the model */ private void run() { @@ -43,25 +72,32 @@ public class ModelMain { } private void doTimestep(int timestep) { - RasterSet<YieldResponsesItem> yieldSurfaces = getYieldSurfaces(timestep); - + YieldRaster yieldSurfaces = getYieldSurfaces(timestep); + LogWriter.println("Timestep " + timestep); + for (CountryAgent ca : countryAgents) { - ca.determineProduction(timestep); + LogWriter.println("Country " + ca.getCountry()); + Collection<RasterKey> countryKeys = countryToKeysMap.get(ca.getCountry()); + YieldRaster countryYieldSurfaces = yieldSurfaces.getSubsetRasterForKeys(countryKeys); + ca.determineProduction(timestep, countryYieldSurfaces); } // examine global trade balance } - private RasterSet<YieldResponsesItem> getYieldSurfaces(int timestep) { - String rootDir = ModelConfig.YIELD_DIR + File.separator + (timestep + ModelConfig.START_TIMESTEP) + File.separator; - RasterSet<YieldResponsesItem> yieldSurfaces = null; + private YieldRaster getYieldSurfaces(int timestep) { + String rootDir = ModelConfig.YIELD_DIR + File.separator + (timestep + ModelConfig.BASE_YEAR) + File.separator; + YieldRaster yieldSurfaces = null; for (CropType cropType : CropType.values()) { + String cropDir = rootDir + cropType.getGamsName() + File.separator; + for (YieldType yieldType : YieldType.values()) { YieldResponseMapReader yieldReader = new YieldResponseMapReader(yieldSurfaces, yieldType, cropType); - yieldSurfaces = yieldReader.getRasterDataFromFile(rootDir + yieldType.getFileName()); + yieldSurfaces = (YieldRaster)yieldReader.getRasterDataFromFile(cropDir + yieldType.getFileName()); } } + return yieldSurfaces; } } diff --git a/src/ac/ed/lurg/country/Country.java b/src/ac/ed/lurg/country/Country.java index 0337033e..36cddf64 100644 --- a/src/ac/ed/lurg/country/Country.java +++ b/src/ac/ed/lurg/country/Country.java @@ -1,33 +1,36 @@ package ac.ed.lurg.country; -import java.util.HashMap; -import java.util.Map; public class Country { private String countryName; - private static final Map<String, Country> cache = new HashMap<String, Country>(); + private String iso3CharCode; + private int iso3NumCode; - private Country(String countryName) { + + public Country(String countryName, String iso3CharCode, int iso3NumCode) { super(); this.countryName = countryName; + this.iso3CharCode = iso3CharCode; + this.iso3NumCode = iso3NumCode; } - - - public static Country get(String name) { - Country type = cache.get(name); - - if (type == null) { - type = new Country(name); - cache.put(name, type); - } - - return type; + + public String getIso3CharCode() { + return iso3CharCode; + } + + public int getIso3NumCode() { + return iso3NumCode; } public String getCountryName() { return countryName; } + + @Override + public String toString() { + return countryName; + } @Override public int hashCode() { diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java index 5291b92a..4c18334a 100644 --- a/src/ac/ed/lurg/country/CountryAgent.java +++ b/src/ac/ed/lurg/country/CountryAgent.java @@ -6,31 +6,29 @@ import java.util.Map; import ac.ed.lurg.ModelConfig; import ac.ed.lurg.ModelContext; import ac.ed.lurg.country.gams.GamsCountryInput; -import ac.ed.lurg.country.gams.GamsInput; -import ac.ed.lurg.country.gams.GamsLandUseOptimiser; -import ac.ed.lurg.country.gams.GamsOutput; +import ac.ed.lurg.country.gams.GamsRasterInput; +import ac.ed.lurg.country.gams.GamsRasterOptimiser; +import ac.ed.lurg.country.gams.GamsRasterOutput; import ac.ed.lurg.landuse.AreasItem; import ac.ed.lurg.types.CropType; -import ac.ed.lurg.types.LandDataType; import ac.ed.lurg.utils.LogWriter; -import ac.ed.lurg.yield.YieldResponsesItem; +import ac.ed.lurg.yield.YieldRaster; public class CountryAgent { private ModelContext modelContext; private Country country; - private Map<Integer, AreasItem> cropAreasTimeseries = new HashMap<Integer, AreasItem>(); -// private Map<Integer, LandCoverAreas> landUseAreasTimeseries = new HashMap<Integer, LandCoverAreas>(); + private Map<Integer, GamsRasterOutput> resultsTimeseries = new HashMap<Integer, GamsRasterOutput>(); private int currentTimestep; private Map<CropType, Double> currentProjectedDemand; - private Map<CropType, Double> currentRefYield; + private YieldRaster countryYieldSurfaces; public CountryAgent(ModelContext modelContext, Country country, AreasItem initialCropAreas) { this.modelContext = modelContext; this.country = country; - cropAreasTimeseries.put(0, initialCropAreas); +// cropAreasTimeseries.put(0, initialCropAreas); // landUseAreasTimeseries.put(0, initialLandCover); } @@ -38,70 +36,36 @@ public class CountryAgent { return country; } - public double getCropArea(int timestep, CropType item) { - AreasItem cd = cropAreasTimeseries.get(timestep); - if (cd == null) { - LogWriter.printlnError("Asked for timestep that we don't have " + timestep); - return Double.NaN; - } - - return cd.getCropArea(item); - } - - public void determineProduction(int timestep) { + public void determineProduction(int timestep, YieldRaster countryYieldSurfaces) { currentTimestep = timestep; - - int year = ModelConfig.BASE_YEAR + currentTimestep; + this.countryYieldSurfaces = countryYieldSurfaces; // get projected demand + int year = ModelConfig.BASE_YEAR + currentTimestep; currentProjectedDemand = modelContext.getDemandManager().getDemand(country, year); - // get ref yields - currentRefYield = modelContext.getYieldManager().getRefYield(country, year); - - // optimise areas and intensity - GamsCountryInput countryLevelInputs = new GamsCountryInput(getProjectedDemand(), getWorldInputEnergy(), getMaxNetImport(), getMinNetImport()); - GamsInput gamsInput = new GamsInput(getYields(), getPreviousAreas(), countryLevelInputs); - - GamsLandUseOptimiser opti = new GamsLandUseOptimiser(gamsInput); - LogWriter.println("Running " + country.getCountryName() + ", year " + year); + // optimize areas and intensity + GamsRasterInput input = getGamsRasterInput(); + GamsRasterOptimiser opti = new GamsRasterOptimiser(input); + LogWriter.println("Running " + country.getCountryName() + ", currentTimestep " + currentTimestep); - GamsOutput result = opti.run(); - // cropAreasTimeseries.put(timestep, result); + GamsRasterOutput result = opti.run(); + resultsTimeseries.put(timestep, result); } - public Map<CropType, Double> getProjectedDemand() { + private Map<CropType, Double> getProjectedDemand() { return currentProjectedDemand; } - public Map<Integer, YieldResponsesItem> getYields() { - // Map<Integer, Map<CropType, YieldResponse>> returnMap = new HashMap<Integer, Map<CropType, YieldResponse>>(); + public GamsRasterInput getGamsRasterInput() { - // for (int i= 1; i<=ModelConfig.NUM_LOCATIONS_PER_COUNTRY; i++) - // returnMap.put(i, currentRefYield); - - return null; // this should be from LPJ data - } - - public Map<Integer, AreasItem> getPreviousAreas() { - AreasItem previousCropAreas = new AreasItem(); int previousTimestep = currentTimestep==0 ? 0 : currentTimestep-1; - AreasItem cd = cropAreasTimeseries.get(previousTimestep); - - double totalCropArea = 0; - for (CropType crop : CropType.getAllItems()) { - previousCropAreas.setCropArea(crop, cd.getCropArea(crop)); - totalCropArea += cd.getCropArea(crop); - } - - previousCropAreas.setLandCoverArea(LandDataType.LAND, totalCropArea*2); - - Map<Integer, AreasItem> returnMap = new HashMap<Integer, AreasItem>(); - - for (int i= 1; i<=5; i++) - returnMap.put(i, previousCropAreas); + GamsRasterOutput prevOutput = resultsTimeseries.get(previousTimestep); + + GamsCountryInput countryLevelInputs = new GamsCountryInput(getProjectedDemand(), getWorldInputEnergy(), getMaxNetImport(), getMinNetImport()); + GamsRasterInput input = new GamsRasterInput(countryYieldSurfaces, prevOutput.getCropAreaRaster(), countryLevelInputs); - return returnMap; + return input; } public Map<CropType, Double> getWorldInputEnergy() { diff --git a/src/ac/ed/lurg/country/CountryAgentCreator.java b/src/ac/ed/lurg/country/CountryAgentCreator.java index 93a21f37..733fde29 100644 --- a/src/ac/ed/lurg/country/CountryAgentCreator.java +++ b/src/ac/ed/lurg/country/CountryAgentCreator.java @@ -9,21 +9,17 @@ import ac.ed.lurg.ModelConfig; import ac.ed.lurg.ModelContext; import ac.ed.lurg.landuse.AreasItem; import ac.ed.lurg.types.CropType; -import ac.ed.lurg.types.LandDataType; import ac.ed.lurg.utils.LogWriter; public class CountryAgentCreator { private static final int COUNTRY_COL = 0; private static final int YEAR_COL = 1; -// private static final int REGION_COL = 2; -// private static final int INCOME_GROUP_COL = 3; - private static final int LAND_COL = 4; - private static final int ARABLE_COL = 5; - private static final int FOREST_COL = 7; - private static final int PERM_CROP_COL = 8; - private static final int PASTURE_COL = 9; -// private static final int FERT_N_COL = 12; + private static final int LAND_COL = 2; + private static final int ARABLE_COL = 3; + private static final int FOREST_COL = 5; + private static final int PERM_CROP_COL = 6; + private static final int PASTURE_COL = 7; public Collection<CountryAgent> getAgents(ModelContext modelContext) { Collection<CountryAgent> countryAgents = new HashSet<CountryAgent>(); @@ -38,7 +34,7 @@ public class CountryAgentCreator { while ((line=fitReader.readLine()) != null) { String[] tokens = line.split(","); - if (tokens.length < 13) + if (tokens.length < 11) LogWriter.printlnError("Too few columns in " + filename + ", " + line); countryName = tokens[COUNTRY_COL]; @@ -66,7 +62,7 @@ public class CountryAgentCreator { initialCropData.setCropArea(CropType.CEREALS, arableArea); // at the moment can substitute freely between arable crops so this is ok-ish initialCropData.setCropArea(CropType.MEAT_OR_PASTURE, pastureArea); - CountryAgent ca = new CountryAgent(modelContext, Country.get(countryName), initialCropData); + CountryAgent ca = new CountryAgent(modelContext, CountryManager.getForName(countryName), initialCropData); countryAgents.add(ca); } diff --git a/src/ac/ed/lurg/yield/YieldKey.java b/src/ac/ed/lurg/country/CountryBoundaryItem.java similarity index 53% rename from src/ac/ed/lurg/yield/YieldKey.java rename to src/ac/ed/lurg/country/CountryBoundaryItem.java index c744e722..822a854e 100644 --- a/src/ac/ed/lurg/yield/YieldKey.java +++ b/src/ac/ed/lurg/country/CountryBoundaryItem.java @@ -1,23 +1,17 @@ -package ac.ed.lurg.yield; +package ac.ed.lurg.country; -import ac.ed.lurg.country.Country; -import ac.ed.lurg.types.CropType; +import ac.sac.raster.RasterItem; -class YieldKey { - private Country country; - private CropType item; - - YieldKey (Country country, CropType item) { - this.item = item; - this.country = country; - } +public class CountryBoundaryItem implements RasterItem { + Country country; + public Country getCountry() { return country; } - - public CropType getItem() { - return item; + + public void setCountry(Country country) { + this.country = country; } @Override @@ -25,7 +19,6 @@ class YieldKey { final int prime = 31; int result = 1; result = prime * result + ((country == null) ? 0 : country.hashCode()); - result = prime * result + ((item == null) ? 0 : item.hashCode()); return result; } @@ -37,17 +30,12 @@ class YieldKey { return false; if (getClass() != obj.getClass()) return false; - YieldKey other = (YieldKey) obj; + CountryBoundaryItem other = (CountryBoundaryItem) obj; if (country == null) { if (other.country != null) return false; } else if (!country.equals(other.country)) return false; - if (item == null) { - if (other.item != null) - return false; - } else if (!item.equals(other.item)) - return false; return true; } } diff --git a/src/ac/ed/lurg/country/CountryBoundaryReader.java b/src/ac/ed/lurg/country/CountryBoundaryReader.java new file mode 100644 index 00000000..747a6e68 --- /dev/null +++ b/src/ac/ed/lurg/country/CountryBoundaryReader.java @@ -0,0 +1,30 @@ +package ac.ed.lurg.country; + +import ac.ed.lurg.utils.LogWriter; +import ac.sac.raster.AbstractRasterReader; +import ac.sac.raster.RasterHeaderDetails; +import ac.sac.raster.RasterSet; + +public class CountryBoundaryReader extends AbstractRasterReader<CountryBoundaryItem> { + + protected void createDataSet(RasterHeaderDetails header) { + if (DEBUG) LogWriter.println("Creating RasterDataset col:"+header.getNcolumns() + ", rows:" + header.getNrows()); + + if (dataset == null) { + dataset = new RasterSet<CountryBoundaryItem>(header) { + private static final long serialVersionUID = 8813968413893792926L; + + protected CountryBoundaryItem createRasterData() { + return new CountryBoundaryItem(); + } + }; + } + } + + @Override + public void setData(CountryBoundaryItem item, String token) { + int isoCode = Integer.parseInt(token); + Country c = CountryManager.getForCode(isoCode); + item.setCountry(c); + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/country/CountryManager.java b/src/ac/ed/lurg/country/CountryManager.java new file mode 100644 index 00000000..7b75d35d --- /dev/null +++ b/src/ac/ed/lurg/country/CountryManager.java @@ -0,0 +1,70 @@ +package ac.ed.lurg.country; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.HashMap; +import java.util.Map; + +import ac.ed.lurg.ModelConfig; +import ac.ed.lurg.utils.LogWriter; + + +public class CountryManager { + private static final int NAME_COL = 0; + private static final int CHAR_CODE_COL = 1; + private static final int NUM_CODE_COL = 4; + + private final Map<String, Country> nameMap = new HashMap<String, Country>(); + private final Map<Integer, Country> numCodeMap = new HashMap<Integer, Country>(); + + private static CountryManager instance = null; + + private static CountryManager getInstance() { + if(instance == null) { + instance = new CountryManager(); + } + return instance; + } + + protected CountryManager() { + String filename = ModelConfig.COUNTRY_CODES_FILE; + try { + BufferedReader fitReader = new BufferedReader(new FileReader(filename)); + String line, name, charCode; + int numCode; + fitReader.readLine(); // read header + + while ((line=fitReader.readLine()) != null) { + String[] tokens = line.split(","); + + if (tokens.length < 4) + LogWriter.printlnError("Too few columns in " + filename + ", " + line); + + name = tokens[NAME_COL]; + charCode = tokens[CHAR_CODE_COL]; + numCode = Integer.parseInt(tokens[NUM_CODE_COL]); + + Country c = new Country(name, charCode, numCode); + nameMap.put(name, c); + numCodeMap.put(numCode, c); + } + fitReader.close(); + + } catch (Exception e) { + LogWriter.printlnError("Failed in reading commodity demand fits"); + e.printStackTrace(); + } + LogWriter.println("Processed " + filename + ", create " + nameMap.size() + " country codes"); + + } + + public static Country getForName(String name) { + Country c = getInstance().nameMap.get(name); + return c; + } + + public static Country getForCode(int isoCode) { + Country c = getInstance().numCodeMap.get(isoCode); + return c; + } +} diff --git a/src/ac/ed/lurg/country/gams/GamsInput.java b/src/ac/ed/lurg/country/gams/GamsLocationInput.java similarity index 77% rename from src/ac/ed/lurg/country/gams/GamsInput.java rename to src/ac/ed/lurg/country/gams/GamsLocationInput.java index 88d305cd..e3e5c95f 100644 --- a/src/ac/ed/lurg/country/gams/GamsInput.java +++ b/src/ac/ed/lurg/country/gams/GamsLocationInput.java @@ -5,13 +5,13 @@ import java.util.Map; import ac.ed.lurg.landuse.AreasItem; import ac.ed.lurg.yield.YieldResponsesItem; -public class GamsInput { +public class GamsLocationInput { private Map<Integer, ? extends YieldResponsesItem> yields; private Map<Integer, ? extends AreasItem> previousAreas; private GamsCountryInput countryInput; - public GamsInput(Map<Integer, ? extends YieldResponsesItem> yields, Map<Integer, ? extends AreasItem> previousAreas, GamsCountryInput countryInput) { + public GamsLocationInput(Map<Integer, ? extends YieldResponsesItem> yields, Map<Integer, ? extends AreasItem> previousAreas, GamsCountryInput countryInput) { super(); this.yields = yields; this.previousAreas = previousAreas; diff --git a/src/ac/ed/lurg/country/gams/GamsLandUseOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java similarity index 96% rename from src/ac/ed/lurg/country/gams/GamsLandUseOptimiser.java rename to src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java index d1801cf2..9e806dea 100644 --- a/src/ac/ed/lurg/country/gams/GamsLandUseOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java @@ -26,15 +26,15 @@ import com.gams.api.GAMSVariableRecord; import com.gams.api.GAMSWorkspace; import com.gams.api.GAMSWorkspaceInfo; -public class GamsLandUseOptimiser { +public class GamsLocationOptimiser { - private GamsInput inputData; + private GamsLocationInput inputData; - public GamsLandUseOptimiser(GamsInput inputData) { + public GamsLocationOptimiser(GamsLocationInput inputData) { this.inputData = inputData; } - public GamsOutput run() { + public GamsLocationOutput run() { File workingDirectory = new File(ModelConfig.TEMP_DIR, "GamsTest"); workingDirectory.mkdir(); @@ -122,7 +122,7 @@ public class GamsLandUseOptimiser { addScalar(inDB.addParameter("minFeedRate", 0, "minimum rate of feed for producing animal products"), inputData.getCountryInput().getMinFeedRate()); } - private GamsOutput handleResults(GAMSDatabase outDB) { + private GamsLocationOutput handleResults(GAMSDatabase outDB) { int modelStatus = (int) outDB.getParameter("ms").findRecord().getValue(); System.out.println( "\nModelstatus: " + GAMSGlobals.ModelStat.lookup( modelStatus ) + @@ -186,7 +186,7 @@ public class GamsLandUseOptimiser { LogWriter.println(String.format("\nTotal area= %.1f", totalArea)); //cleanup(ws.workingDirectory()); - GamsOutput results = new GamsOutput(modelStatus, intensities, cropAreas, feedAmounts, netImports); + GamsLocationOutput results = new GamsLocationOutput(modelStatus, intensities, cropAreas, feedAmounts, netImports); return results ; } diff --git a/src/ac/ed/lurg/country/gams/GamsOutput.java b/src/ac/ed/lurg/country/gams/GamsLocationOutput.java similarity index 93% rename from src/ac/ed/lurg/country/gams/GamsOutput.java rename to src/ac/ed/lurg/country/gams/GamsLocationOutput.java index 199b2ab8..2fb834a6 100644 --- a/src/ac/ed/lurg/country/gams/GamsOutput.java +++ b/src/ac/ed/lurg/country/gams/GamsLocationOutput.java @@ -6,7 +6,7 @@ import ac.ed.lurg.landuse.AreasItem; import ac.ed.lurg.landuse.IntensitiesItem; import ac.ed.lurg.types.CropType; -public class GamsOutput { +public class GamsLocationOutput { int status; Map<Integer, IntensitiesItem> intensities; // data mapped from id (not raster) @@ -14,7 +14,7 @@ public class GamsOutput { Map<CropType, Double> feedAmounts; Map<CropType, Double> netImports; - public GamsOutput(int status, + public GamsLocationOutput(int status, Map<Integer, IntensitiesItem> intensities, Map<Integer, AreasItem> cropAreas, Map<CropType, Double> feedAmounts, diff --git a/src/ac/ed/lurg/country/gams/GamsTest.java b/src/ac/ed/lurg/country/gams/GamsLocationTest.java similarity index 94% rename from src/ac/ed/lurg/country/gams/GamsTest.java rename to src/ac/ed/lurg/country/gams/GamsLocationTest.java index e0464fa8..f0942978 100644 --- a/src/ac/ed/lurg/country/gams/GamsTest.java +++ b/src/ac/ed/lurg/country/gams/GamsLocationTest.java @@ -9,19 +9,19 @@ import ac.ed.lurg.types.LandDataType; import ac.ed.lurg.types.YieldType; import ac.ed.lurg.yield.YieldResponsesItem; -public class GamsTest { +public class GamsLocationTest { public static final int NUM_LOCATIONS_PER_COUNTRY = 5; public static void main(String[] args) { - GamsTest aGamsTest = new GamsTest(); + GamsLocationTest aGamsTest = new GamsLocationTest(); aGamsTest.run(); } private void run() { GamsCountryInput countryLevelInputs = new GamsCountryInput(getProjectedDemand(), getWorldInputEnergy(), getMaxNetImport(), getMinNetImport()); - GamsInput gamsInput = new GamsInput(getYields(), getPreviousArea(), countryLevelInputs); + GamsLocationInput gamsInput = new GamsLocationInput(getYields(), getPreviousArea(), countryLevelInputs); - GamsLandUseOptimiser opti = new GamsLandUseOptimiser(gamsInput); + GamsLocationOptimiser opti = new GamsLocationOptimiser(gamsInput); opti.run(); } diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java index 8c5ff657..8afa96fb 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java @@ -34,24 +34,24 @@ public class GamsRasterOptimiser { public GamsRasterOutput run() { // workout similar areas - GamsInput gamsInput = convertFromRaster(rasterInputData); + GamsLocationInput gamsInput = convertFromRaster(rasterInputData); // run optimizer - GamsLandUseOptimiser opti = new GamsLandUseOptimiser(gamsInput); - GamsOutput gamsOutput = opti.run(); + GamsLocationOptimiser opti = new GamsLocationOptimiser(gamsInput); + GamsLocationOutput gamsOutput = opti.run(); // map results back to raster return convertToRaster(gamsInput, gamsOutput); } - private GamsRasterOutput convertToRaster(GamsInput gamsInput, GamsOutput gamsOutput) { + 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.getFeedAmounts(), gamsOutput.getNetImports()); } - private RasterSet<AreasItem> allocAreas(Map<Integer, ? extends AreasItem> prevAreasAgg, GamsOutput gamsOutput) { + private RasterSet<AreasItem> allocAreas(Map<Integer, ? extends AreasItem> prevAreasAgg, GamsLocationOutput gamsOutput) { RasterSet<AreasItem> newAreaRaster = new RasterSet<AreasItem>(); RasterSet<AreasItem> prevAreaRaster = rasterInputData.getPreviousAreas(); @@ -148,7 +148,7 @@ public class GamsRasterOptimiser { return netAddedCrop - prevForest - prevNatural; } - private RasterSet<IntensitiesItem> allocIntensities(GamsOutput gamsOutput) { + private RasterSet<IntensitiesItem> allocIntensities(GamsLocationOutput gamsOutput) { RasterSet<IntensitiesItem> newIntensityRaster = new RasterSet<IntensitiesItem>(); @@ -163,7 +163,7 @@ public class GamsRasterOptimiser { return newIntensityRaster; } - private GamsInput convertFromRaster(GamsRasterInput rasterInputData) { + private GamsLocationInput convertFromRaster(GamsRasterInput rasterInputData) { // as a first attempt only going to look at pasture and cereal yields, assuming other yields will be correlated to one or the other. YieldRaster yieldRaster = rasterInputData.getYields(); RasterSet<AreasItem> cropAreaRaster = rasterInputData.getPreviousAreas(); @@ -211,7 +211,7 @@ public class GamsRasterOptimiser { } } - return new GamsInput(aggregatedYield, aggregatedAreas, rasterInputData.getCountryInput()); + return new GamsLocationInput(aggregatedYield, aggregatedAreas, rasterInputData.getCountryInput()); } private Set<RasterKey> getMappingForLocation(Map<Integer, Set<RasterKey>> mapping, int id) { diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOutput.java b/src/ac/ed/lurg/country/gams/GamsRasterOutput.java index ba94d2d5..c986777a 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterOutput.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterOutput.java @@ -8,12 +8,13 @@ import ac.ed.lurg.types.CropType; import ac.sac.raster.RasterSet; public class GamsRasterOutput { - int status; - RasterSet<IntensitiesItem> intensityRaster; - RasterSet<AreasItem> cropAreaRaster; - Map<CropType, Double> feedAmounts; - Map<CropType, Double> netImports; + private int status; + + private RasterSet<IntensitiesItem> intensityRaster; + private RasterSet<AreasItem> cropAreaRaster; + private Map<CropType, Double> feedAmounts; + private Map<CropType, Double> netImports; public GamsRasterOutput(int status, RasterSet<IntensitiesItem> intensityRaster, RasterSet<AreasItem> cropAreaRaster, Map<CropType, Double> feedAmounts, Map<CropType, Double> netImports) { @@ -40,5 +41,4 @@ public class GamsRasterOutput { public Map<CropType, Double> getNetImports() { return netImports; } - } diff --git a/src/ac/ed/lurg/country/gams/GamsRasterTest.java b/src/ac/ed/lurg/country/gams/GamsRasterTest.java index 136a8be5..aceb1e2b 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterTest.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterTest.java @@ -1,12 +1,13 @@ package ac.ed.lurg.country.gams; import ac.ed.lurg.landuse.AreasItem; +import ac.ed.lurg.utils.LogWriter; import ac.ed.lurg.yield.YieldRaster; import ac.ed.lurg.yield.YieldResponsesItem; import ac.sac.raster.RasterKey; import ac.sac.raster.RasterSet; -public class GamsRasterTest extends GamsTest { +public class GamsRasterTest extends GamsLocationTest { public static void main(String[] args) { GamsRasterTest aGamsRasterTest = new GamsRasterTest(); @@ -19,6 +20,7 @@ public class GamsRasterTest extends GamsTest { GamsRasterOptimiser opti = new GamsRasterOptimiser(input); GamsRasterOutput output = opti.run(); + LogWriter.println(output.toString()); } private static final int X_RANGE = 3; diff --git a/src/ac/ed/lurg/demand/BaseConsumpManager.java b/src/ac/ed/lurg/demand/BaseConsumpManager.java index 91b8aa82..7931e013 100644 --- a/src/ac/ed/lurg/demand/BaseConsumpManager.java +++ b/src/ac/ed/lurg/demand/BaseConsumpManager.java @@ -7,6 +7,7 @@ import java.util.Map; import ac.ed.lurg.ModelConfig; import ac.ed.lurg.country.Country; +import ac.ed.lurg.country.CountryManager; import ac.ed.lurg.types.CountryCropKey; import ac.ed.lurg.types.CropType; import ac.ed.lurg.utils.LogWriter; @@ -41,7 +42,7 @@ public class BaseConsumpManager { cropName = tokens[CROP_COL]; cpc = Double.parseDouble(tokens[BASE_CPC_COL]); - baseConsumpMap.put(new CountryCropKey(Country.get(countryName), CropType.getForFaoName(cropName)), cpc); + baseConsumpMap.put(new CountryCropKey(CountryManager.getForName(countryName), CropType.getForFaoName(cropName)), cpc); } fitReader.close(); diff --git a/src/ac/ed/lurg/demand/SspManager.java b/src/ac/ed/lurg/demand/SspManager.java index 46bc8ee9..e82b7c3a 100644 --- a/src/ac/ed/lurg/demand/SspManager.java +++ b/src/ac/ed/lurg/demand/SspManager.java @@ -7,6 +7,7 @@ import java.util.Map; import ac.ed.lurg.ModelConfig; import ac.ed.lurg.country.Country; +import ac.ed.lurg.country.CountryManager; import ac.ed.lurg.utils.LogWriter; public class SspManager { @@ -47,7 +48,7 @@ public class SspManager { countryName = tokens[COUNTRY_COL]; gdp = Double.parseDouble(tokens[GDP_COL]); - SspKey sspKey = new SspKey(scenario, year, Country.get(countryName)); + SspKey sspKey = new SspKey(scenario, year, CountryManager.getForName(countryName)); SspData sspData = new SspData(population, gdp); sspMap.put(sspKey, sspData); } catch (Exception e) { diff --git a/src/ac/ed/lurg/utils/CollectionHelper.java b/src/ac/ed/lurg/utils/CollectionHelper.java new file mode 100644 index 00000000..44fd84ba --- /dev/null +++ b/src/ac/ed/lurg/utils/CollectionHelper.java @@ -0,0 +1,23 @@ +package ac.ed.lurg.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CollectionHelper { + + public static <K, V> Map<V, List<K>> invertMap(Map<K, V> map) { + + Map<V, List<K>> result = new HashMap<V, List<K>>(); + + for (Map.Entry<K, V> entry : map.entrySet()) { + if (!result.containsKey(entry.getValue())) { + result.put(entry.getValue(), new ArrayList<K>()); + } + result.get(entry.getValue()).add(entry.getKey()); + } + + return result; + } +} diff --git a/src/ac/ed/lurg/yield/YieldManager.java b/src/ac/ed/lurg/yield/YieldManager.java deleted file mode 100644 index 132e8e5f..00000000 --- a/src/ac/ed/lurg/yield/YieldManager.java +++ /dev/null @@ -1,76 +0,0 @@ -package ac.ed.lurg.yield; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.util.HashMap; -import java.util.Map; - -import ac.ed.lurg.ModelConfig; -import ac.ed.lurg.country.Country; -import ac.ed.lurg.types.CropType; -import ac.ed.lurg.utils.LogWriter; - -public class YieldManager { - - private Map<Country, Map<CropType, Double>> cache = new HashMap<Country, Map<CropType, Double>>(); - - private static final int COUNTRY_COL = 0; - private static final int ITEM_COL = 1; - private static final int REF_YIELD_COL = 2; - - public YieldManager () { - super(); - readRefYields(); - } - - private void readRefYields() { - String filename = ModelConfig.REF_YIELD_FILE; - try { - BufferedReader reader = new BufferedReader(new FileReader(filename)); - String line, itemName, countryName; - double refYield; - reader.readLine(); // read header - - while ((line=reader.readLine()) != null) { - String[] tokens = line.split(","); - - if (tokens.length < 3) - LogWriter.printlnError("Too few columns in " + filename + ", " + line); - - try { - countryName = tokens[COUNTRY_COL]; - itemName = tokens[ITEM_COL]; - refYield = Double.parseDouble(tokens[REF_YIELD_COL]); - - Map<CropType, Double> countryMap = cache.get(Country.get(countryName)); - - if (countryMap == null) { - countryMap = new HashMap<CropType, Double>(); - cache.put(Country.get(countryName), countryMap); - } - countryMap.put(CropType.getForFaoName(itemName), refYield); - - } catch (Exception e) { - LogWriter.printlnError("Failed in processing ssp line " + line); - e.printStackTrace(); - } - } - reader.close(); - - } catch (Exception e) { - LogWriter.printlnError("Failed in reading ssp data file"); - e.printStackTrace(); - } - LogWriter.println("Processed " + filename + ", create " + cache.size() + " ref yield entries"); - } - - public Map<CropType, Double> getRefYield(Country country, int year) { - return cache.get(country); - } - - public String getModelAndScenarioDescription() { - return "Estimated ref yields"; - } - - -} diff --git a/src/ac/ed/lurg/yield/YieldRaster.java b/src/ac/ed/lurg/yield/YieldRaster.java index 6876bbf8..d982611f 100644 --- a/src/ac/ed/lurg/yield/YieldRaster.java +++ b/src/ac/ed/lurg/yield/YieldRaster.java @@ -1,7 +1,9 @@ package ac.ed.lurg.yield; -import ac.ed.lurg.country.Country; +import java.util.Collection; + import ac.sac.raster.RasterHeaderDetails; +import ac.sac.raster.RasterKey; import ac.sac.raster.RasterSet; public class YieldRaster extends RasterSet<YieldResponsesItem> { @@ -16,8 +18,14 @@ public class YieldRaster extends RasterSet<YieldResponsesItem> { return new YieldResponsesItem(); } - public YieldRaster getRasterForCountry(Country c) { - // TODO - return null; + // not very efficient, we could keep the mapping of country to area somewhere. + public YieldRaster getSubsetRasterForKeys(Collection<RasterKey> keys) { + YieldRaster subsetYieldRaster = new YieldRaster(this.getHeaderDetails()); + + for (RasterKey key : keys) { + subsetYieldRaster.put(key, get(key)); + } + + return subsetYieldRaster; } } diff --git a/src/ac/ed/lurg/yield/YieldResponseMapReader.java b/src/ac/ed/lurg/yield/YieldResponseMapReader.java index 549975d9..94177331 100644 --- a/src/ac/ed/lurg/yield/YieldResponseMapReader.java +++ b/src/ac/ed/lurg/yield/YieldResponseMapReader.java @@ -5,14 +5,13 @@ import ac.ed.lurg.types.YieldType; import ac.ed.lurg.utils.LogWriter; import ac.sac.raster.AbstractRasterReader; import ac.sac.raster.RasterHeaderDetails; -import ac.sac.raster.RasterSet; public class YieldResponseMapReader extends AbstractRasterReader<YieldResponsesItem> { private YieldType yieldType; private CropType cropType; - public YieldResponseMapReader (RasterSet<YieldResponsesItem> dataset, YieldType yieldType, CropType cropType) { + public YieldResponseMapReader (YieldRaster dataset, YieldType yieldType, CropType cropType) { super(dataset); this.yieldType = yieldType; this.cropType = cropType; diff --git a/src/ac/ed/lurg/yield/YieldResponsesItem.java b/src/ac/ed/lurg/yield/YieldResponsesItem.java index db6a2776..216337bb 100644 --- a/src/ac/ed/lurg/yield/YieldResponsesItem.java +++ b/src/ac/ed/lurg/yield/YieldResponsesItem.java @@ -9,7 +9,7 @@ import ac.sac.raster.RasterItem; public class YieldResponsesItem implements RasterItem { Map<CropType, YieldResponse> yieldResponses = new HashMap<CropType, YieldResponse>(); - + public void setYield(YieldType type, CropType crop, double yield) { getYieldResponseForCrop(crop).setYield(type, yield); } diff --git a/src/ac/sac/raster/AbstractRasterReader.java b/src/ac/sac/raster/AbstractRasterReader.java index 284821a6..c9d5bea1 100755 --- a/src/ac/sac/raster/AbstractRasterReader.java +++ b/src/ac/sac/raster/AbstractRasterReader.java @@ -37,7 +37,7 @@ public abstract class AbstractRasterReader<D extends RasterItem> { int nrows=0; double xllCorner=0.0; double yllCorner = 0.0; - int cellSize = 1000; + double cellSize = 1000; String nodataString=null; for (int i=0; i<HEADER_LENGTH; i++) { @@ -65,7 +65,7 @@ public abstract class AbstractRasterReader<D extends RasterItem> { yllCorner = Double.parseDouble(tokens[HEADER_DATA_COL]); break; case CELL_SIZE: - cellSize = Integer.parseInt(tokens[HEADER_DATA_COL]); + cellSize = Double.parseDouble(tokens[HEADER_DATA_COL]); break; case NODATA_VALUE_ROW: nodataString = tokens[HEADER_DATA_COL]; diff --git a/src/ac/sac/raster/RasterHeaderDetails.java b/src/ac/sac/raster/RasterHeaderDetails.java index c45b0a52..31cd4c1a 100755 --- a/src/ac/sac/raster/RasterHeaderDetails.java +++ b/src/ac/sac/raster/RasterHeaderDetails.java @@ -5,10 +5,10 @@ public class RasterHeaderDetails { private int nrows; private double xllCorner; private double yllCorner; - private int cellSize; + private double cellSize; private String nodataString; - public RasterHeaderDetails(int ncolumns, int nrows, double xllCorner, double yllCorner, int cellSize, String nodataString) { + public RasterHeaderDetails(int ncolumns, int nrows, double xllCorner, double yllCorner, double cellSize, String nodataString) { super(); this.ncolumns = ncolumns; this.nrows = nrows; @@ -50,7 +50,7 @@ public class RasterHeaderDetails { return yllCorner; } - public int getCellSize() { + public double getCellSize() { return cellSize; } @@ -58,16 +58,18 @@ public class RasterHeaderDetails { return nodataString; } + @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + cellSize; + long temp; + temp = Double.doubleToLongBits(cellSize); + result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ncolumns; result = prime * result + ((nodataString == null) ? 0 : nodataString.hashCode()); result = prime * result + nrows; - long temp; temp = Double.doubleToLongBits(xllCorner); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(yllCorner); @@ -81,10 +83,11 @@ public class RasterHeaderDetails { return true; if (obj == null) return false; - if (!(obj instanceof RasterHeaderDetails)) + if (getClass() != obj.getClass()) return false; RasterHeaderDetails other = (RasterHeaderDetails) obj; - if (cellSize != other.cellSize) + if (Double.doubleToLongBits(cellSize) != Double + .doubleToLongBits(other.cellSize)) return false; if (ncolumns != other.ncolumns) return false; @@ -103,7 +106,7 @@ public class RasterHeaderDetails { return false; return true; } - + @Override public String toString() { return "ncolumns=" + ncolumns + diff --git a/src/ac/sac/raster/RasterSet.java b/src/ac/sac/raster/RasterSet.java index 0114de81..9c5d994f 100755 --- a/src/ac/sac/raster/RasterSet.java +++ b/src/ac/sac/raster/RasterSet.java @@ -34,12 +34,12 @@ public class RasterSet<D extends RasterItem> extends HashMap<RasterKey, D> { if (source.getCellSize() % header.getCellSize() != 0) throw new RuntimeException("Cell sizes must be the same or souce an integer multiple of destination"); - int cellRatio = source.getCellSize() / header.getCellSize(); + double cellRatio = source.getCellSize() / header.getCellSize(); for (int x = 0; x<cellRatio; x++) { for (int y = 0; y<cellRatio; y++) { - c = (col)*cellRatio + x + xOffset; - r = (row)*cellRatio + y + yOffset; + c = (int)(col*cellRatio) + x + xOffset; + r = (int)(row*cellRatio) + y + yOffset; D d = get(c, r); if (d != null) -- GitLab