1 | 0 | |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
package au.csiro.netcdf.wron; |
18 | |
|
19 | |
import java.io.BufferedReader; |
20 | |
import java.io.ByteArrayInputStream; |
21 | |
import java.io.File; |
22 | |
import java.io.FileInputStream; |
23 | |
import java.io.FileNotFoundException; |
24 | |
import java.io.FileReader; |
25 | |
import java.io.IOException; |
26 | |
import java.io.PrintWriter; |
27 | |
import java.io.RandomAccessFile; |
28 | |
import java.io.StringWriter; |
29 | |
import java.io.UnsupportedEncodingException; |
30 | |
import java.text.DateFormat; |
31 | |
import java.text.NumberFormat; |
32 | |
import java.text.SimpleDateFormat; |
33 | |
import java.util.ArrayList; |
34 | |
import java.util.Arrays; |
35 | |
import java.util.Calendar; |
36 | |
import java.util.Collections; |
37 | |
import java.util.Comparator; |
38 | |
import java.util.Date; |
39 | |
import java.util.HashMap; |
40 | |
import java.util.Iterator; |
41 | |
import java.util.List; |
42 | |
import java.util.Map; |
43 | |
import java.util.Scanner; |
44 | |
import java.util.Set; |
45 | |
import java.util.TreeSet; |
46 | |
import java.util.regex.Pattern; |
47 | |
|
48 | |
import org.apache.commons.cli.BasicParser; |
49 | |
import org.apache.commons.cli.CommandLine; |
50 | |
import org.apache.commons.cli.HelpFormatter; |
51 | |
import org.apache.commons.cli.MissingOptionException; |
52 | |
import org.apache.commons.cli.Option; |
53 | |
import org.apache.commons.cli.OptionBuilder; |
54 | |
import org.apache.commons.cli.Options; |
55 | |
import org.apache.commons.cli.ParseException; |
56 | |
import org.apache.log4j.Logger; |
57 | |
|
58 | |
import ucar.ma2.DataType; |
59 | |
import ucar.nc2.Attribute; |
60 | |
import ucar.nc2.units.DateFormatter; |
61 | |
import au.csiro.netcdf.NcDefineAttributes; |
62 | |
import au.csiro.netcdf.NcDefineDimension; |
63 | |
import au.csiro.netcdf.NcDefineVariable; |
64 | |
import au.csiro.netcdf.NcWriteVariable; |
65 | |
import au.csiro.netcdf.cli.CommandLineOptionsComparator; |
66 | |
import au.csiro.netcdf.util.CSVTokenizer; |
67 | |
import au.csiro.netcdf.util.NetCDFUtils; |
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
|
79 | |
|
80 | 0 | public class MdbsyScenarioCConverter |
81 | |
{ |
82 | |
|
83 | 0 | private static String COLLECTION = "Collection-MDBSY_Climate"; |
84 | 0 | private static String SCENARIO = ""; |
85 | |
private static String[] MODEL_NAMES; |
86 | 0 | private static String CASE = ""; |
87 | |
|
88 | |
|
89 | |
|
90 | |
|
91 | 0 | private static String LOCATION_LOOKUP_FILE = ""; |
92 | |
|
93 | |
|
94 | |
|
95 | |
|
96 | 0 | private static String METADATA_FILE = ""; |
97 | |
|
98 | |
|
99 | |
|
100 | |
|
101 | 0 | private static String INPUT_CSV_DIRECTORY = ""; |
102 | |
|
103 | |
|
104 | |
|
105 | |
|
106 | 0 | private static String OUTPUT_NETCDF_DIRECTORY = ""; |
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
private static final String NETCDF_FILE_EXTENSION = ".nc"; |
112 | |
|
113 | |
|
114 | |
|
115 | |
|
116 | |
private static final String ENCODING = "UTF-8"; |
117 | |
|
118 | |
|
119 | |
|
120 | |
|
121 | 0 | private static Map<String, String> CLIMATE_MODELS = new HashMap<String, String>(); |
122 | |
static |
123 | |
{ |
124 | 0 | CLIMATE_MODELS.put("cccma_t47", "CCCMA T47"); |
125 | 0 | CLIMATE_MODELS.put("cccma_t63", "CCCMA T63"); |
126 | 0 | CLIMATE_MODELS.put("cnrm", "CNRM"); |
127 | 0 | CLIMATE_MODELS.put("csiro", "CSIRO-MK3.0"); |
128 | 0 | CLIMATE_MODELS.put("gfdl", "GFDL 2.0"); |
129 | 0 | CLIMATE_MODELS.put("giss_aom", "GISS-AOM"); |
130 | 0 | CLIMATE_MODELS.put("iap", "IAP"); |
131 | 0 | CLIMATE_MODELS.put("inmcm", "INMCM"); |
132 | 0 | CLIMATE_MODELS.put("ipsl", "IPSL"); |
133 | 0 | CLIMATE_MODELS.put("miroc", "MIROC-M"); |
134 | 0 | CLIMATE_MODELS.put("miub", "MIUB"); |
135 | 0 | CLIMATE_MODELS.put("mpi", "MPI-ECHAM5"); |
136 | 0 | CLIMATE_MODELS.put("mri", "MRI"); |
137 | 0 | CLIMATE_MODELS.put("ncar_ccsm", "NCAR-CCSM"); |
138 | 0 | CLIMATE_MODELS.put("ncar_pcm", "NCAR-PCM1"); |
139 | |
} |
140 | |
|
141 | |
|
142 | |
|
143 | |
private static final int FILE_NAME_MODEL_NAME = 0; |
144 | |
private static final int IPCC_MODEL_NAME = 1; |
145 | |
|
146 | |
|
147 | 0 | private static final String[] variableNames = new String[] { "rainfall", "APET" }; |
148 | 0 | private static final String[] variableUnits = new String[] { "mm", "mm" }; |
149 | 0 | private static final String[] variableLongNames = new String[] { "rainfall", "APET" }; |
150 | 0 | private static final String[] variableFillValues = new String[] { "-9999.0f", "-9999.0f" }; |
151 | 0 | private static final String[] variableMissingValues = variableFillValues; |
152 | 0 | private static final DataType[] variableDataTypes = new DataType[] { DataType.FLOAT, DataType.FLOAT }; |
153 | 0 | static final int numVariables = variableNames.length; |
154 | |
private static final String GRID_MAPPING = "crs"; |
155 | |
|
156 | |
|
157 | |
private static final String TIME = "time"; |
158 | 0 | private static String TIME_RANGE = "0-40906"; |
159 | |
private static final int TIME_SIZE = 40907; |
160 | |
private static final String TIME_LONG_NAME = "reference time"; |
161 | |
private static final String TIME_STANDARD_NAME = "time"; |
162 | |
private static final String TIME_UNITS = "days since 1895-01-01 0:0:0"; |
163 | |
private static final String TIME_CALENDAR = "Gregorian"; |
164 | |
private static final String TIME_AXIS = "T"; |
165 | |
private static final String TIME_BOUNDS = "time_bnds"; |
166 | |
|
167 | |
|
168 | |
private static final String LONG = "longitude"; |
169 | |
private static final int LONG_COLUMN_INDEX = 1; |
170 | |
private static final String LONG_RANGE = "0-296"; |
171 | |
private static final int LONG_SIZE = 297; |
172 | |
private static final String LONG_UNITS = "degrees_east"; |
173 | |
private static final String LONG_STANDARD_NAME = "longitude"; |
174 | |
private static final String LONG_AXIS = "X"; |
175 | |
private static final String LONG_LONG_NAME = "longitude"; |
176 | |
|
177 | |
|
178 | |
private static final String LAT = "latitude"; |
179 | |
private static final int LAT_COLUMN_INDEX = 2; |
180 | |
private static final String LAT_RANGE = "0-278"; |
181 | |
private static final int LAT_SIZE = 279; |
182 | |
private static final String LAT_UNITS = "degrees_north"; |
183 | |
private static final String LAT_STANDARD_NAME = "latitude"; |
184 | |
private static final String LAT_AXIS = "Y"; |
185 | |
private static final String LAT_LONG_NAME = "latitude"; |
186 | |
|
187 | |
|
188 | |
private static final String NV = "nv"; |
189 | |
private static final String NV_RANGE = "0-1"; |
190 | |
private static final int NV_SIZE = 2; |
191 | |
|
192 | |
|
193 | 0 | private static String ELEVATION = "elev"; |
194 | 0 | private static int ELEVATION_COLUMN_INDEX = 3; |
195 | |
private static final String ELEVATION_UNITS = "m"; |
196 | |
private static final String ELEVATION_STANDARD_NAME = "altitude"; |
197 | |
private static final String ELEVATION_LONG_NAME = "Elevation above sea level"; |
198 | |
private static final float ELEVATION_MISSING_VALUE = -999.99f; |
199 | |
|
200 | |
|
201 | 0 | private static String CATCHMENT_ID = "catchmentId"; |
202 | 0 | private static int CATCHMENT_ID_COLUMN_INDEX = 4; |
203 | |
private static final String CATCHMENT_ID_LONG_NAME = "MDB Catchment Id"; |
204 | |
private static final float CATCHMENT_ID_MISSING_VALUE = 0f; |
205 | |
|
206 | |
|
207 | 0 | private static String REPORTING_REGION = "repRegionId"; |
208 | 0 | private static int REPORTING_REGION_ID_COLUMN_INDEX = 5; |
209 | 0 | private static String REPORTING_REGION_LONG_NAME = "MDB Reporting Region Id"; |
210 | |
private static final float REPORTING_REGION_MISSING_VALUE = 0f; |
211 | |
|
212 | |
|
213 | 0 | private static String CRS_GRID_MAPPING_NAME = "latitude_longitude"; |
214 | 0 | private static float CRS_LONGITUDE_OF_PRIME_MERIDIAN = 0.0f; |
215 | 0 | private static float CRS_SEMI_MAJOR_AXIS = 6378137.0f; |
216 | 0 | private static float CRS_INVERSE_FLATTENING = 298.257222101f; |
217 | |
|
218 | |
|
219 | |
private static final int CELL_ID_COLUMN_INDEX = 0; |
220 | |
|
221 | |
|
222 | |
|
223 | |
|
224 | |
private static final String EPOC_DATE_STRING = "1895-01-01"; |
225 | 0 | private static final DateFormatter isoDateTimeFormat = new DateFormatter(); |
226 | |
private static final int DATE_COLUMN_INDEX = 0; |
227 | |
|
228 | |
|
229 | 0 | private static int ROW_CHUNK_SIZE = 1000; |
230 | |
|
231 | |
|
232 | 0 | private static final int NUM_CSV_COLUMNS = 1 + numVariables; |
233 | |
|
234 | |
|
235 | |
|
236 | |
|
237 | 0 | private static final Logger LOG = Logger.getLogger(MdbsyScenarioCConverter.class.getName()); |
238 | |
|
239 | |
|
240 | 0 | private ConversionUtils convUtils = new ConversionUtils(); |
241 | |
|
242 | |
|
243 | |
|
244 | |
|
245 | |
@SuppressWarnings("static-access") |
246 | |
public static void main(String[] args) throws Exception |
247 | |
{ |
248 | 0 | Options options = new Options(); |
249 | |
try |
250 | |
{ |
251 | 0 | Option inputDirectory = OptionBuilder.withArgName("dir").hasArg().withDescription( |
252 | 0 | " 1: the directory containing the csv files for the scenario.").isRequired(true).withLongOpt( |
253 | 0 | "inputDirectory").create("i"); |
254 | |
|
255 | 0 | Option lookupFile = OptionBuilder.withArgName("file").hasArg() |
256 | 0 | .withDescription(" 2: the cellId lookup file.").isRequired(true).withLongOpt("lookupFile").create( |
257 | 0 | "f"); |
258 | |
|
259 | 0 | Option outputDirectory = OptionBuilder.withArgName("dir").hasArg().withDescription( |
260 | 0 | " 3: the output directory.").isRequired(true).withLongOpt("outputDirectory").create("o"); |
261 | |
|
262 | 0 | Option scenario = OptionBuilder.withArgName("text").hasArg().withDescription( |
263 | 0 | " 4: the modelling scenario used to name the netCDF file.").isRequired(true).withLongOpt("scenario") |
264 | 0 | .create("s"); |
265 | |
|
266 | 0 | Option model = OptionBuilder.withArgName("text").hasArg().withDescription( |
267 | 0 | " 5: the global climate change model used to name the netCDF file.").isRequired(true).withLongOpt( |
268 | 0 | "model").create("e"); |
269 | |
|
270 | 0 | Option modelCase = OptionBuilder.withArgName("text").hasArg().withDescription( |
271 | 0 | " 6: the model case or sensitivity used to name the netCDF file.").isRequired(true).withLongOpt( |
272 | 0 | "case").create("c"); |
273 | |
|
274 | 0 | Option metadataFile = OptionBuilder.withArgName("file").hasArg().withDescription( |
275 | 0 | " 7: a file of global metadata attributes to be added to the netCDF file.").isRequired(true) |
276 | 0 | .withLongOpt("metadataFile").create("m"); |
277 | |
|
278 | 0 | Option numRows = OptionBuilder.withArgName("int").hasArg().withDescription( |
279 | 0 | " 8: the number of rows to read at a time.").isRequired(true).withLongOpt("rows").create("r"); |
280 | |
|
281 | 0 | Option byDecade = OptionBuilder.withDescription( |
282 | 0 | " 9: OPTIONAL, set if we want to convert into netCDF files by decade.").isRequired(false) |
283 | 0 | .withLongOpt("decade").create("d"); |
284 | |
|
285 | 0 | Option byLatitude = OptionBuilder.withDescription( |
286 | 0 | " 10: OPTIONAL, set if we want to convert into netCDF files by degrees of latitude.").isRequired( |
287 | 0 | false).withLongOpt("latitude").create("l"); |
288 | |
|
289 | 0 | Option startLat = OptionBuilder.withArgName("latitude").hasArg().withDescription( |
290 | 0 | " 11: OPTIONAL, The latitude at which to start processing. For byDecade, this option will " |
291 | 0 | + "assume already existing netCDF files.").isRequired(false).create("startLat"); |
292 | |
|
293 | 0 | Option endLat = OptionBuilder.withArgName("latitude").hasArg().withDescription( |
294 | 0 | " 12: OPTIONAL, The latitude at which to end processing (inclusive).").isRequired(false).create( |
295 | 0 | "endLat"); |
296 | |
|
297 | 0 | options.addOption(inputDirectory); |
298 | 0 | options.addOption(lookupFile); |
299 | 0 | options.addOption(outputDirectory); |
300 | 0 | options.addOption(scenario); |
301 | 0 | options.addOption(model); |
302 | 0 | options.addOption(modelCase); |
303 | 0 | options.addOption(metadataFile); |
304 | 0 | options.addOption(numRows); |
305 | 0 | options.addOption(byDecade); |
306 | 0 | options.addOption(byLatitude); |
307 | 0 | options.addOption(startLat); |
308 | 0 | options.addOption(endLat); |
309 | |
|
310 | |
|
311 | 0 | CommandLine parsedCommandLine = new BasicParser().parse(options, args); |
312 | |
|
313 | 0 | INPUT_CSV_DIRECTORY = (parsedCommandLine.hasOption("inputDirectory")) ? parsedCommandLine |
314 | 0 | .getOptionValue("inputDirectory") : ""; |
315 | 0 | LOCATION_LOOKUP_FILE = (parsedCommandLine.hasOption("lookupFile")) ? parsedCommandLine |
316 | 0 | .getOptionValue("lookupFile") : ""; |
317 | 0 | OUTPUT_NETCDF_DIRECTORY = (parsedCommandLine.hasOption("outputDirectory")) ? parsedCommandLine |
318 | 0 | .getOptionValue("outputDirectory") : ""; |
319 | 0 | SCENARIO = (parsedCommandLine.hasOption("scenario")) ? parsedCommandLine.getOptionValue("scenario") : ""; |
320 | 0 | METADATA_FILE = (parsedCommandLine.hasOption("metadataFile")) ? parsedCommandLine |
321 | 0 | .getOptionValue("metadataFile") : ""; |
322 | 0 | MODEL_NAMES = getModelMapping((parsedCommandLine.hasOption("model")) ? parsedCommandLine.getOptionValue("model") : ""); |
323 | 0 | CASE = (parsedCommandLine.hasOption("case")) ? parsedCommandLine.getOptionValue("case") : ""; |
324 | 0 | ROW_CHUNK_SIZE = (parsedCommandLine.hasOption("rows")) ? Integer.valueOf(parsedCommandLine |
325 | 0 | .getOptionValue("rows")) : ROW_CHUNK_SIZE; |
326 | 0 | String startingLatitude = (parsedCommandLine.hasOption("startLat")) ? parsedCommandLine |
327 | 0 | .getOptionValue("startLat") : ""; |
328 | 0 | String endingLatitude = (parsedCommandLine.hasOption("endLat")) ? parsedCommandLine |
329 | 0 | .getOptionValue("endLat") : ""; |
330 | |
|
331 | 0 | boolean doSplitByDecade = parsedCommandLine.hasOption("decade"); |
332 | 0 | boolean doSplitByLatitude = parsedCommandLine.hasOption("latitude"); |
333 | |
|
334 | 0 | MdbsyScenarioCConverter converter = new MdbsyScenarioCConverter(); |
335 | |
|
336 | 0 | if (doSplitByDecade) |
337 | |
{ |
338 | 0 | long start = System.currentTimeMillis(); |
339 | 0 | converter.splitByDecade(startingLatitude, endingLatitude); |
340 | 0 | long end = System.currentTimeMillis() - start; |
341 | 0 | LOG.warn("Split by decade in: " + end + " ms."); |
342 | |
} |
343 | |
|
344 | 0 | if (doSplitByLatitude) |
345 | |
{ |
346 | 0 | long start = System.currentTimeMillis(); |
347 | 0 | converter.splitByLatitude(startingLatitude, endingLatitude); |
348 | 0 | long end = System.currentTimeMillis() - start; |
349 | 0 | LOG.warn("Split by latitude in: " + end + " ms."); |
350 | |
} |
351 | |
} |
352 | 0 | catch (MissingOptionException moe) |
353 | |
{ |
354 | 0 | LOG.error(moe.getMessage()); |
355 | |
|
356 | 0 | StringWriter sw = new StringWriter(); |
357 | 0 | HelpFormatter formatter = new HelpFormatter(); |
358 | 0 | formatter.setOptionComparator(new CommandLineOptionsComparator()); |
359 | 0 | formatter.printHelp(new PrintWriter(sw), 80, "-", "header", options, 0, 1, "footer"); |
360 | 0 | System.out.println(sw.toString()); |
361 | |
} |
362 | 0 | } |
363 | |
|
364 | |
|
365 | |
|
366 | |
|
367 | |
|
368 | |
|
369 | |
public void splitByLatitude(String startingLatitude, String endingLatitude) throws Exception |
370 | |
{ |
371 | |
|
372 | 0 | Map<String, List<CellData>> triplesGroupedByLatitude = this.getTriplesGroupedByLatitude(this.readLookupFile()); |
373 | |
|
374 | |
|
375 | 0 | Set<String> latitudeKeySet = triplesGroupedByLatitude.keySet(); |
376 | 0 | Set<String> limitedLatitudes = convUtils.getLimitedLatitudes(latitudeKeySet, startingLatitude, endingLatitude); |
377 | 0 | List<String> latitudeKeyList = new ArrayList<String>(limitedLatitudes); |
378 | 0 | Collections.sort(latitudeKeyList, new Comparator<String>() |
379 | |
{ |
380 | |
@Override |
381 | |
public int compare(String o1, String o2) |
382 | |
{ |
383 | 0 | return Integer.valueOf(o2).compareTo(Integer.valueOf(o1)); |
384 | |
} |
385 | |
}); |
386 | |
|
387 | |
|
388 | 0 | for (String latitudeKey : latitudeKeyList) |
389 | |
{ |
390 | 0 | LOG.warn("Started work on latitude: " + latitudeKey + "."); |
391 | 0 | String latitudeDegree = latitudeKey; |
392 | 0 | List<CellData> triples = triplesGroupedByLatitude.get(latitudeDegree); |
393 | |
|
394 | |
|
395 | 0 | Set<String> sortedLatitudes = this.getSortedLatitudes(triples); |
396 | 0 | int blockLatSize = sortedLatitudes.size(); |
397 | 0 | String blockLatRange = "0-" + String.valueOf(sortedLatitudes.size() - 1); |
398 | |
|
399 | 0 | Set<String> sortedLongitudes = this.getSortedLongitudes(triples); |
400 | 0 | int blockLongSize = sortedLongitudes.size(); |
401 | 0 | String blockLongRange = "0-" + String.valueOf(sortedLongitudes.size() - 1); |
402 | |
|
403 | |
|
404 | 0 | String filenames[] = new String[numVariables]; |
405 | 0 | List<String> dates = this.getDatesAsDaysSinceEpoc(this.getDates()); |
406 | 0 | for (int i = 0; i < filenames.length; i++) |
407 | |
{ |
408 | 0 | filenames[i] = this.generateLatitudeFilename(latitudeDegree, variableNames[i]); |
409 | 0 | this.createVariableFile(filenames[i], Arrays.asList(LAT, LONG, TIME), i, TIME_SIZE, blockLatSize, blockLongSize); |
410 | 0 | this.fillCoordinateVariables(filenames[i], sortedLongitudes, sortedLatitudes, dates, blockLatRange, |
411 | 0 | blockLongRange, TIME_RANGE); |
412 | 0 | this.fillSpatialVariables(filenames[i], triples); |
413 | 0 | this.fillDataForLatitude(filenames[i], i, sortedLongitudes, sortedLatitudes, dates, Arrays.asList(LAT, |
414 | 0 | LONG, TIME)); |
415 | |
} |
416 | |
|
417 | |
|
418 | |
|
419 | 0 | this.fillDataByLatitudeVariables(filenames, triples, Arrays.asList(LAT, LONG, TIME)); |
420 | |
} |
421 | 0 | } |
422 | |
|
423 | |
|
424 | |
|
425 | |
|
426 | |
|
427 | |
|
428 | |
|
429 | |
|
430 | |
public void splitByDecade(String startingLatitude, String endingLatitude) throws Exception |
431 | |
{ |
432 | |
|
433 | 0 | List<CellData> triples = this.getAllTriples(this.readLookupFile()); |
434 | |
|
435 | |
|
436 | 0 | Set<String> sortedLatitudes = this.getSortedLatitudes(triples); |
437 | 0 | String blockLatRange = "0-" + String.valueOf(sortedLatitudes.size() - 1); |
438 | |
|
439 | 0 | Set<String> sortedLongitudes = this.getSortedLongitudes(triples); |
440 | 0 | String blockLongRange = "0-" + String.valueOf(sortedLongitudes.size() - 1); |
441 | 0 | String startingLongitude = new ArrayList<String>(sortedLongitudes).get(0); |
442 | |
|
443 | |
|
444 | 0 | Map<Integer, List<String>> datesByDecade = this.getDatesByDecade(this.getDates()); |
445 | |
|
446 | |
|
447 | 0 | Set<Integer> decadeKeySet = datesByDecade.keySet(); |
448 | 0 | List<Integer> decadeKeyList = new ArrayList<Integer>(decadeKeySet); |
449 | 0 | Collections.sort(decadeKeyList); |
450 | 0 | Map<Integer, String[]> allFilenames = new HashMap<Integer, String[]>(); |
451 | |
|
452 | |
|
453 | 0 | int start = 0; |
454 | 0 | int end = start; |
455 | 0 | int filenameStart = 0; |
456 | 0 | for (Integer decadeKey : decadeKeyList) |
457 | |
{ |
458 | 0 | LOG.warn("Started work on decade: " + decadeKey + "0s."); |
459 | 0 | System.gc(); |
460 | 0 | LOG.warn(" Mem: " + getMemDisplay()); |
461 | 0 | List<String> dates = datesByDecade.get(decadeKey); |
462 | 0 | end = end + dates.size(); |
463 | |
|
464 | 0 | int blockTimeSize = dates.size(); |
465 | 0 | String blockTimeRange = "0-" + String.valueOf(dates.size() - 1); |
466 | |
|
467 | |
|
468 | 0 | String decadeStr = String.valueOf(decadeKey + "0"); |
469 | |
|
470 | 0 | String filenames[] = new String[numVariables]; |
471 | 0 | dates = this.getDatesAsDaysSinceEpoc(dates); |
472 | 0 | for (int i = 0; i < filenames.length; i++) |
473 | |
{ |
474 | 0 | filenames[i] = this.generateDecadeFilename(decadeStr, variableNames[i]); |
475 | 0 | if ("".equals(startingLatitude)) |
476 | |
{ |
477 | 0 | this.createVariableFile(filenames[i], Arrays.asList(TIME, LAT, LONG), i, blockTimeSize, LAT_SIZE, LONG_SIZE); |
478 | 0 | this.fillCoordinateVariables(filenames[i], sortedLongitudes, sortedLatitudes, dates, blockLatRange, |
479 | 0 | blockLongRange, blockTimeRange); |
480 | 0 | this.fillSpatialVariables(filenames[i], triples); |
481 | |
} |
482 | |
} |
483 | |
|
484 | 0 | allFilenames.put(decadeKey, filenames); |
485 | 0 | filenameStart += numVariables; |
486 | |
} |
487 | |
|
488 | 0 | LOG.warn(" Latitude limits : " + startingLatitude + " to " + endingLatitude + "."); |
489 | |
|
490 | 0 | int numBlocks = LAT_SIZE / ROW_CHUNK_SIZE + (LAT_SIZE % ROW_CHUNK_SIZE > 0 ? 1 : 0); |
491 | 0 | Calendar baseCal = convUtils.getCalendar(new Date()); |
492 | 0 | baseCal.clear(); |
493 | 0 | baseCal.set(1895, 0, 1); |
494 | |
|
495 | 0 | Set<String> limitedLatitudes = convUtils.getLimitedLatitudes(sortedLatitudes, startingLatitude, endingLatitude); |
496 | 0 | for (int blockNum = 0; blockNum < numBlocks; blockNum++) |
497 | |
{ |
498 | 0 | LOG.warn(" Processing block : " + blockNum + "."); |
499 | 0 | LOG.warn(" Mem: " + getMemDisplay()); |
500 | |
|
501 | 0 | List<String> lats = convUtils.getLatitudeBlock(limitedLatitudes, blockNum, ROW_CHUNK_SIZE); |
502 | 0 | if (lats.isEmpty()) |
503 | |
{ |
504 | 0 | LOG.warn(" Skipping block as it is outside the latitude range."); |
505 | |
} |
506 | |
else |
507 | |
{ |
508 | 0 | LOG.warn(" Processing latitudes : " + lats + "."); |
509 | |
|
510 | |
|
511 | 0 | List<CellData> targetCells = convUtils.buildCsvFilenamesForLatitudes(lats, triples, INPUT_CSV_DIRECTORY, ".csv"); |
512 | |
|
513 | |
|
514 | 0 | LOG.warn(" Reading data from CSVs..."); |
515 | 0 | Map<Integer, Map<String, LongitudeRange>> latData = convUtils.readDataByLatitudes(targetCells, lats, |
516 | 0 | numVariables, TIME_SIZE, LONG_SIZE, variableFillValues, startingLongitude); |
517 | |
|
518 | |
|
519 | 0 | LOG.warn(" Writing data to netCDF..."); |
520 | 0 | LOG.warn(" Mem: " + getMemDisplay()); |
521 | 0 | convUtils.writeLatDataByDecade(latData, allFilenames, variableNames, baseCal.getTime()); |
522 | |
|
523 | 0 | LOG.warn(" Writing finished."); |
524 | |
} |
525 | |
} |
526 | 0 | } |
527 | |
|
528 | |
public String getMemDisplay() |
529 | |
{ |
530 | 0 | Runtime rt = Runtime.getRuntime(); |
531 | 0 | NumberFormat numFmt = NumberFormat.getNumberInstance(); |
532 | 0 | numFmt.setMaximumFractionDigits(0); |
533 | 0 | StringBuffer sb = new StringBuffer(); |
534 | 0 | sb.append(numFmt.format(rt.totalMemory() / 1024.0)); |
535 | 0 | sb.append(" Kb total, "); |
536 | 0 | sb.append(numFmt.format(rt.freeMemory() / 1024.0)); |
537 | 0 | sb.append(" Kb free, "); |
538 | 0 | sb.append(numFmt.format(rt.maxMemory() / 1024.0)); |
539 | 0 | sb.append(" Kb max."); |
540 | 0 | return sb.toString(); |
541 | |
} |
542 | |
|
543 | |
|
544 | |
|
545 | |
|
546 | |
|
547 | |
|
548 | |
|
549 | |
private void createVariableFile(String outputFileName, List<String> dimensionOrdering, int variableIndex, int blockTimeSize, int blockLatSize, int blockLongSize) |
550 | |
throws Exception |
551 | |
{ |
552 | 0 | this.defineDimensions(outputFileName, dimensionOrdering, blockTimeSize, blockLatSize, blockLongSize); |
553 | 0 | this.defineCoordinateVariables(outputFileName); |
554 | 0 | this.defineSpatialVariables(outputFileName); |
555 | |
|
556 | |
|
557 | 0 | DateFormat utcDateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); |
558 | 0 | Attribute converter = new Attribute("History", utcDateTime.format(new Date()) + " Converted to netCDF by " |
559 | 0 | + "$Id: MdbsyScenarioCConverter.java 84 2010-08-25 05:56:46Z robertbridle $"); |
560 | 0 | Attribute ipccClimateModel = new Attribute("IPCC Climate Model Name", MODEL_NAMES[IPCC_MODEL_NAME]); |
561 | 0 | List<Attribute> globalAttrs = new ArrayList<Attribute>(); |
562 | 0 | globalAttrs.add(converter); |
563 | 0 | globalAttrs.add(ipccClimateModel); |
564 | 0 | if (METADATA_FILE.length() > 0) |
565 | |
{ |
566 | 0 | globalAttrs.addAll(NetCDFUtils.readAttributesFromStream(new FileInputStream(METADATA_FILE))); |
567 | |
} |
568 | 0 | NcDefineAttributes ncDefineAttr = new NcDefineAttributes(); |
569 | 0 | ncDefineAttr.execute(outputFileName, globalAttrs, false ); |
570 | |
|
571 | 0 | String dimensions = ""; |
572 | 0 | for (String dimension : dimensionOrdering) |
573 | |
{ |
574 | 0 | dimensions += dimension + " "; |
575 | |
} |
576 | 0 | this.defineVariable(outputFileName, dimensions, variableIndex); |
577 | 0 | } |
578 | |
|
579 | |
|
580 | |
|
581 | |
|
582 | |
|
583 | |
|
584 | |
|
585 | |
|
586 | |
|
587 | |
private void defineDimensions(String outputFileName, List<String> dimensionOrdering, int blockTimeSize, int blockLatSize, int blockLongSize) |
588 | |
throws IllegalArgumentException, ParseException, IOException |
589 | |
{ |
590 | 0 | NcDefineDimension command = new NcDefineDimension(); |
591 | |
|
592 | 0 | for (String dimName : dimensionOrdering) |
593 | |
{ |
594 | 0 | if (dimName.equals(TIME)) |
595 | |
{ |
596 | 0 | command.execute(outputFileName, TIME, blockTimeSize, false , false); |
597 | |
} |
598 | 0 | else if (dimName.equals(LAT)) |
599 | |
{ |
600 | 0 | command.execute(outputFileName, LAT, blockLatSize, false , false); |
601 | |
} |
602 | 0 | else if (dimName.equals(LONG)) |
603 | |
{ |
604 | 0 | command.execute(outputFileName, LONG, blockLongSize, false , false); |
605 | |
} |
606 | |
} |
607 | |
|
608 | |
|
609 | 0 | command.execute(outputFileName, NV, NV_SIZE, false , false); |
610 | 0 | } |
611 | |
|
612 | |
|
613 | |
|
614 | |
|
615 | |
|
616 | |
|
617 | |
|
618 | |
|
619 | |
|
620 | |
private void defineCoordinateVariables(String outputFileName) throws IllegalArgumentException, ParseException, |
621 | |
IOException |
622 | |
{ |
623 | 0 | NcDefineVariable command = new NcDefineVariable(); |
624 | |
|
625 | 0 | command.execute(new File(outputFileName), LAT, DataType.FLOAT, Arrays.asList(new Attribute("units", LAT_UNITS), |
626 | 0 | new Attribute("long_name", LAT_LONG_NAME), new Attribute("standard_name", LAT_STANDARD_NAME), new Attribute("axis", LAT_AXIS)), LAT, |
627 | 0 | false , false); |
628 | 0 | command.execute(new File(outputFileName), LONG, DataType.FLOAT, Arrays.asList( |
629 | 0 | new Attribute("long_name", LONG_LONG_NAME), new Attribute("units", LONG_UNITS), new Attribute("standard_name", LONG_STANDARD_NAME), new Attribute( |
630 | 0 | "axis", LONG_AXIS)), LONG, false , false); |
631 | 0 | command.execute(new File(outputFileName), TIME, DataType.INT, Arrays.asList(new Attribute("units", TIME_UNITS), |
632 | 0 | new Attribute("long_name", TIME_LONG_NAME), new Attribute("standard_name", TIME_STANDARD_NAME), |
633 | 0 | new Attribute("axis", TIME_AXIS), new Attribute("calendar", TIME_CALENDAR), new Attribute("bounds", |
634 | 0 | TIME_BOUNDS)), TIME, false , false); |
635 | 0 | command.execute(new File(outputFileName), TIME_BOUNDS, DataType.INT, new ArrayList<Attribute>(), TIME + " " |
636 | 0 | + NV, false , false); |
637 | 0 | command.execute(new File(outputFileName), GRID_MAPPING, DataType.INT, Arrays.asList(new Attribute( |
638 | 0 | "grid_mapping_name", CRS_GRID_MAPPING_NAME), new Attribute("longitude_of_prime_meridian", |
639 | 0 | CRS_LONGITUDE_OF_PRIME_MERIDIAN), new Attribute("semi_major_axis", CRS_SEMI_MAJOR_AXIS), |
640 | 0 | new Attribute("inverse_flattening", CRS_INVERSE_FLATTENING)), "", |
641 | 0 | false , true); |
642 | 0 | } |
643 | |
|
644 | |
|
645 | |
|
646 | |
|
647 | |
|
648 | |
|
649 | |
|
650 | |
|
651 | |
|
652 | |
private void defineSpatialVariables(String outputFileName) throws IOException |
653 | |
{ |
654 | 0 | NcDefineVariable command = new NcDefineVariable(); |
655 | |
|
656 | 0 | String spatialDim = LAT + " " + LONG; |
657 | 0 | command.execute(new File(outputFileName), ELEVATION, DataType.FLOAT, Arrays.asList(new Attribute("units", |
658 | 0 | ELEVATION_UNITS), new Attribute("standard_name", ELEVATION_STANDARD_NAME), new Attribute("long_name", |
659 | 0 | ELEVATION_LONG_NAME), new Attribute("_FillValue", ELEVATION_MISSING_VALUE), new Attribute( |
660 | 0 | "grid_mapping", GRID_MAPPING)), spatialDim, false , false); |
661 | 0 | command |
662 | 0 | .execute(new File(outputFileName), CATCHMENT_ID, DataType.FLOAT, Arrays.asList(new Attribute( |
663 | 0 | "long_name", CATCHMENT_ID_LONG_NAME), new Attribute("_FillValue", CATCHMENT_ID_MISSING_VALUE), new Attribute( |
664 | 0 | "grid_mapping", GRID_MAPPING)), spatialDim, false , false); |
665 | 0 | command |
666 | 0 | .execute(new File(outputFileName), REPORTING_REGION, DataType.FLOAT, Arrays.asList(new Attribute( |
667 | 0 | "long_name", REPORTING_REGION_LONG_NAME), new Attribute("_FillValue", REPORTING_REGION_MISSING_VALUE), new Attribute( |
668 | 0 | "grid_mapping", GRID_MAPPING)), spatialDim, false , |
669 | 0 | false); |
670 | 0 | } |
671 | |
|
672 | |
|
673 | |
|
674 | |
|
675 | |
|
676 | |
|
677 | |
|
678 | |
|
679 | |
|
680 | |
private void defineVariable(String outputFileName, String dimensions, int variableIndex) |
681 | |
throws IllegalArgumentException, IOException, ParseException |
682 | |
{ |
683 | 0 | NcDefineVariable command = new NcDefineVariable(); |
684 | 0 | command.execute(new File(outputFileName), variableNames[variableIndex], variableDataTypes[variableIndex], |
685 | 0 | Arrays.asList(new Attribute("units", variableUnits[variableIndex]), new Attribute("long_name", |
686 | 0 | variableLongNames[variableIndex]), new Attribute("missing_value", Float |
687 | 0 | .valueOf(variableMissingValues[variableIndex])), new Attribute("_FillValue", Float |
688 | 0 | .valueOf(variableFillValues[variableIndex])), new Attribute("grid_mapping", |
689 | 0 | GRID_MAPPING)), dimensions, false , |
690 | 0 | false); |
691 | 0 | } |
692 | |
|
693 | |
|
694 | |
|
695 | |
|
696 | |
|
697 | |
|
698 | |
|
699 | |
|
700 | |
|
701 | |
|
702 | |
|
703 | |
|
704 | |
|
705 | |
|
706 | |
|
707 | |
|
708 | |
|
709 | |
|
710 | |
private void fillCoordinateVariables(String outputFileName, Set<String> sortedLongitudes, |
711 | |
Set<String> sortedLatitudes, List<String> dates, String blockLatRange, String blockLongRange, String timeRange) throws UnsupportedEncodingException, IOException, |
712 | |
java.text.ParseException |
713 | |
{ |
714 | 0 | NcWriteVariable command = new NcWriteVariable(); |
715 | |
|
716 | |
|
717 | |
|
718 | |
|
719 | 0 | StringBuffer longitudeStringBuffer = new StringBuffer(); |
720 | 0 | for (Iterator<String> iter = sortedLongitudes.iterator(); iter.hasNext();) |
721 | |
{ |
722 | 0 | longitudeStringBuffer.append(iter.next()).append(System.getProperty("line.separator")); |
723 | |
} |
724 | |
|
725 | |
|
726 | 0 | command.execute(new File(outputFileName), LONG, blockLongRange, new ByteArrayInputStream(longitudeStringBuffer |
727 | 0 | .toString().getBytes(ENCODING)), false); |
728 | |
|
729 | |
|
730 | |
|
731 | |
|
732 | 0 | StringBuffer latitudeStringBuffer = new StringBuffer(); |
733 | 0 | for (Iterator<String> iter = sortedLatitudes.iterator(); iter.hasNext();) |
734 | |
{ |
735 | 0 | latitudeStringBuffer.append(iter.next()).append(System.getProperty("line.separator")); |
736 | |
} |
737 | |
|
738 | |
|
739 | 0 | command.execute(new File(outputFileName), LAT, blockLatRange, new ByteArrayInputStream(latitudeStringBuffer |
740 | 0 | .toString().getBytes(ENCODING)), false); |
741 | |
|
742 | |
|
743 | |
|
744 | 0 | StringBuffer timeBoundsStringBuffer = new StringBuffer(); |
745 | 0 | StringBuffer dateStringBuffer = new StringBuffer(); |
746 | 0 | boolean first = true; |
747 | 0 | for (String date : dates) |
748 | |
{ |
749 | 0 | dateStringBuffer.append(date).append(System.getProperty("line.separator")); |
750 | 0 | if (!first) |
751 | |
{ |
752 | 0 | timeBoundsStringBuffer.append(date).append(System.getProperty("line.separator")); |
753 | |
} |
754 | 0 | timeBoundsStringBuffer.append(date).append(System.getProperty("line.separator")); |
755 | 0 | first = false; |
756 | |
} |
757 | 0 | int dayAfterLastDay = Integer.parseInt(dates.get(dates.size()-1)) +1; |
758 | 0 | String finalString = String.valueOf(dayAfterLastDay); |
759 | 0 | timeBoundsStringBuffer.append(finalString).append(System.getProperty("line.separator")); |
760 | |
|
761 | |
|
762 | 0 | command.execute(new File(outputFileName), TIME, timeRange, new ByteArrayInputStream(dateStringBuffer |
763 | 0 | .toString().getBytes(ENCODING)), false); |
764 | |
|
765 | |
|
766 | 0 | command.execute(new File(outputFileName), TIME_BOUNDS, timeRange+","+NV_RANGE, new ByteArrayInputStream( |
767 | 0 | timeBoundsStringBuffer.toString().getBytes(ENCODING)), false); |
768 | |
|
769 | 0 | } |
770 | |
|
771 | |
|
772 | |
|
773 | |
|
774 | |
|
775 | |
|
776 | |
|
777 | |
|
778 | |
|
779 | |
|
780 | |
|
781 | |
private void fillSpatialVariables(String outputFileName, List<CellData> sortedCellData) throws IOException |
782 | |
{ |
783 | 0 | NcWriteVariable command = new NcWriteVariable(); |
784 | |
|
785 | 0 | Set<String> latitudes = getSortedLatitudes(sortedCellData); |
786 | 0 | Set<String> longitudes = getSortedLongitudes(sortedCellData); |
787 | 0 | String spatialRange = "0-" + (latitudes.size() - 1) + ",0-" + (longitudes.size() - 1); |
788 | |
|
789 | |
|
790 | |
|
791 | |
|
792 | 0 | StringBuffer dataBuffer = fillSpatialDataBuffer(sortedCellData, latitudes, longitudes, |
793 | 0 | CellDataVariable.ELEVATION, "-999.99"); |
794 | |
|
795 | |
|
796 | 0 | command.execute(new File(outputFileName), ELEVATION, spatialRange, new ByteArrayInputStream(dataBuffer |
797 | 0 | .toString().getBytes(ENCODING)), false); |
798 | |
|
799 | |
|
800 | |
|
801 | |
|
802 | 0 | dataBuffer = fillSpatialDataBuffer(sortedCellData, latitudes, longitudes, CellDataVariable.CATCHMENTID, "0"); |
803 | |
|
804 | |
|
805 | 0 | command.execute(new File(outputFileName), CATCHMENT_ID, spatialRange, new ByteArrayInputStream(dataBuffer |
806 | 0 | .toString().getBytes(ENCODING)), false); |
807 | |
|
808 | |
|
809 | |
|
810 | |
|
811 | 0 | dataBuffer = fillSpatialDataBuffer(sortedCellData, latitudes, longitudes, CellDataVariable.REPORTINGREGIONID, |
812 | 0 | "0"); |
813 | |
|
814 | |
|
815 | 0 | command.execute(new File(outputFileName), REPORTING_REGION, spatialRange, new ByteArrayInputStream(dataBuffer |
816 | 0 | .toString().getBytes(ENCODING)), false); |
817 | 0 | } |
818 | |
|
819 | |
|
820 | |
|
821 | |
|
822 | |
|
823 | |
|
824 | |
|
825 | |
|
826 | |
|
827 | |
private StringBuffer fillSpatialDataBuffer(List<CellData> sortedCellData, Set<String> latitudes, |
828 | |
Set<String> longitudes, CellDataVariable varNum, String fillValue) |
829 | |
{ |
830 | 0 | StringBuffer dataBuffer = new StringBuffer(); |
831 | 0 | int cellNum = 0; |
832 | 0 | for (String latVal : latitudes) |
833 | |
{ |
834 | 0 | for (String longVal : longitudes) |
835 | |
{ |
836 | 0 | if (cellNum < sortedCellData.size()) |
837 | |
{ |
838 | 0 | CellData cellData = sortedCellData.get(cellNum); |
839 | 0 | if (cellData.latitude.equals(latVal) && cellData.longitude.equals(longVal)) |
840 | |
{ |
841 | 0 | switch (varNum) |
842 | |
{ |
843 | |
case ELEVATION: |
844 | 0 | dataBuffer.append(cellData.elevation); |
845 | 0 | break; |
846 | |
case CATCHMENTID: |
847 | 0 | dataBuffer.append(cellData.catchmentId); |
848 | 0 | break; |
849 | |
case REPORTINGREGIONID: |
850 | 0 | dataBuffer.append(cellData.reportingRegionId); |
851 | |
break; |
852 | |
} |
853 | 0 | cellNum++; |
854 | |
} |
855 | |
else |
856 | |
{ |
857 | 0 | dataBuffer.append(fillValue); |
858 | |
} |
859 | |
} |
860 | |
else |
861 | |
{ |
862 | 0 | dataBuffer.append(fillValue); |
863 | |
} |
864 | |
|
865 | 0 | dataBuffer.append(System.getProperty("line.separator")); |
866 | |
} |
867 | |
|
868 | |
} |
869 | 0 | return dataBuffer; |
870 | |
} |
871 | |
|
872 | |
|
873 | |
|
874 | |
|
875 | |
|
876 | |
|
877 | |
|
878 | |
|
879 | |
|
880 | |
|
881 | |
|
882 | |
|
883 | |
private void fillDataForLatitude(String filename, int varIndex, Set<String> sortedLongitudes, Set<String> sortedLatitudes, |
884 | |
List<String> dates, List<String> dimensionOrdering) throws IOException |
885 | |
{ |
886 | 0 | StringBuffer fillBlock = new StringBuffer(); |
887 | 0 | String fillLine = variableFillValues[varIndex] + "\n"; |
888 | 0 | for (int i = 0; i < dates.size(); i++) |
889 | |
{ |
890 | 0 | fillBlock.append(fillLine); |
891 | |
} |
892 | |
|
893 | 0 | NcWriteVariable writeVarCmd = new NcWriteVariable(); |
894 | 0 | for (String latitude : sortedLatitudes) |
895 | |
{ |
896 | 0 | for (String longitude : sortedLongitudes) |
897 | |
{ |
898 | 0 | String fillRange = this.constructFillRange(dimensionOrdering, latitude, longitude, dates.size()); |
899 | 0 | writeVarCmd.execute(new File(filename), variableNames[varIndex], fillRange, |
900 | 0 | new ByteArrayInputStream(fillBlock.toString().getBytes(ENCODING)), false); |
901 | |
} |
902 | |
} |
903 | 0 | } |
904 | |
|
905 | |
|
906 | |
|
907 | |
|
908 | |
|
909 | |
|
910 | |
|
911 | |
|
912 | |
|
913 | |
private void fillDataByLatitudeVariables(String[] variableFileNames, List<CellData> triples, List<String> dimensionOrdering) |
914 | |
throws IOException |
915 | |
{ |
916 | 0 | NcWriteVariable command = new NcWriteVariable(); |
917 | |
|
918 | 0 | int counter = 0; |
919 | 0 | for (CellData triple : triples) |
920 | |
{ |
921 | 0 | if (++counter % 1000 == 0) |
922 | |
{ |
923 | 0 | LOG.warn(" Num files processed: " + counter); |
924 | |
} |
925 | |
|
926 | 0 | String csvFileName = triple.getCellId(); |
927 | 0 | String latitude = triple.getLatitude(); |
928 | 0 | String longitude = triple.getLongitude(); |
929 | |
|
930 | 0 | String fillRange = this.constructFillRange(dimensionOrdering, latitude, longitude, TIME_SIZE); |
931 | |
|
932 | |
try |
933 | |
{ |
934 | 0 | StringBuffer[] valuesStringBuffer = new StringBuffer[numVariables]; |
935 | 0 | for (int i = 0; i < valuesStringBuffer.length; i++) |
936 | |
{ |
937 | 0 | valuesStringBuffer[i] = new StringBuffer(); |
938 | |
} |
939 | |
|
940 | 0 | Scanner s = null; |
941 | |
try |
942 | |
{ |
943 | 0 | s = new Scanner(new BufferedReader(new FileReader(INPUT_CSV_DIRECTORY + csvFileName + ".csv"))) |
944 | 0 | .useDelimiter(Pattern.compile("[\n,]")); |
945 | |
|
946 | |
|
947 | 0 | for (int i = 0; i < NUM_CSV_COLUMNS; i++) |
948 | |
{ |
949 | 0 | s.next(); |
950 | |
} |
951 | |
|
952 | 0 | while (s.hasNext()) |
953 | |
{ |
954 | 0 | s.next(); |
955 | |
|
956 | 0 | for (int i = 0; i < numVariables; i++) |
957 | |
{ |
958 | 0 | valuesStringBuffer[i].append(s.next()); |
959 | |
|
960 | 0 | if (i < numVariables - 1) |
961 | |
{ |
962 | 0 | valuesStringBuffer[i].append(System.getProperty("line.separator")); |
963 | |
} |
964 | |
} |
965 | |
} |
966 | |
} |
967 | |
finally |
968 | 0 | { |
969 | 0 | if (s != null) |
970 | |
{ |
971 | 0 | s.close(); |
972 | |
} |
973 | 0 | } |
974 | |
|
975 | |
try |
976 | |
{ |
977 | 0 | for (int i = 0; i < numVariables; i++) |
978 | |
{ |
979 | 0 | command.execute(new File(variableFileNames[i]), variableNames[i], fillRange, |
980 | 0 | new ByteArrayInputStream(valuesStringBuffer[i].toString().getBytes(ENCODING)), false); |
981 | |
} |
982 | |
} |
983 | 0 | catch (IllegalArgumentException iae) |
984 | |
{ |
985 | 0 | LOG.error(iae); |
986 | 0 | LOG.error("fillRange (date, lat, long): " + fillRange); |
987 | |
} |
988 | |
|
989 | |
} |
990 | 0 | catch (FileNotFoundException fnfe) |
991 | |
{ |
992 | 0 | LOG.info(fnfe.getMessage()); |
993 | |
|
994 | |
} |
995 | |
} |
996 | 0 | } |
997 | |
|
998 | |
|
999 | |
|
1000 | |
|
1001 | |
|
1002 | |
|
1003 | |
|
1004 | |
|
1005 | |
private String constructFillRange(List<String> dimensionOrdering, String latitude, String longitude, int dateSize) |
1006 | |
{ |
1007 | 0 | String time_range = "0-" + String.valueOf(dateSize - 1); |
1008 | 0 | String latitude_range = "lookup(" + latitude + ")-lookup(" + latitude + ")"; |
1009 | 0 | String longitude_range = "lookup(" + longitude + ")-lookup(" + longitude + ")"; |
1010 | |
|
1011 | 0 | String fillRange = new String(); |
1012 | 0 | for (Iterator<String> iter = dimensionOrdering.iterator(); iter.hasNext();) |
1013 | |
{ |
1014 | 0 | String dimension = iter.next(); |
1015 | 0 | if (dimension.equals(TIME)) |
1016 | |
{ |
1017 | 0 | fillRange += time_range; |
1018 | |
} |
1019 | 0 | else if (dimension.equals(LAT)) |
1020 | |
{ |
1021 | 0 | fillRange += latitude_range; |
1022 | |
} |
1023 | 0 | else if (dimension.equals(LONG)) |
1024 | |
{ |
1025 | 0 | fillRange += longitude_range; |
1026 | |
} |
1027 | 0 | if (iter.hasNext()) |
1028 | 0 | fillRange += ","; |
1029 | |
} |
1030 | 0 | return fillRange; |
1031 | |
} |
1032 | |
|
1033 | |
|
1034 | |
|
1035 | |
|
1036 | |
|
1037 | |
|
1038 | |
|
1039 | |
private Map<String, List<CellData>> getTriplesGroupedByLatitude(String[][] locationLookupValues) |
1040 | |
{ |
1041 | 0 | Map<String, List<CellData>> triplesGroupedByLatitude = new HashMap<String, List<CellData>>(); |
1042 | 0 | for (int i = 0; i < locationLookupValues.length; i++) |
1043 | |
{ |
1044 | 0 | String cellId = locationLookupValues[i][CELL_ID_COLUMN_INDEX]; |
1045 | 0 | String longitude = locationLookupValues[i][LONG_COLUMN_INDEX]; |
1046 | 0 | String latitude = locationLookupValues[i][LAT_COLUMN_INDEX]; |
1047 | 0 | String elevation = locationLookupValues[i][ELEVATION_COLUMN_INDEX]; |
1048 | 0 | String catchmentId = locationLookupValues[i][CATCHMENT_ID_COLUMN_INDEX]; |
1049 | 0 | String reportingRegionId = locationLookupValues[i][REPORTING_REGION_ID_COLUMN_INDEX]; |
1050 | |
|
1051 | 0 | String latitudeDegree = String.valueOf(Float.valueOf(latitude).intValue()); |
1052 | |
|
1053 | 0 | List<CellData> triplesInLatitude = triplesGroupedByLatitude.get(latitudeDegree); |
1054 | 0 | if (triplesInLatitude == null) |
1055 | |
{ |
1056 | 0 | triplesInLatitude = new ArrayList<CellData>(); |
1057 | 0 | triplesGroupedByLatitude.put(latitudeDegree, triplesInLatitude); |
1058 | |
} |
1059 | 0 | final CellData cellData = new CellData(cellId, longitude, latitude); |
1060 | 0 | cellData.elevation = elevation; |
1061 | 0 | cellData.catchmentId = catchmentId; |
1062 | 0 | cellData.reportingRegionId = reportingRegionId; |
1063 | 0 | triplesInLatitude.add(cellData); |
1064 | |
} |
1065 | |
|
1066 | |
|
1067 | 0 | int count = 0; |
1068 | 0 | for (Iterator<String> iter = triplesGroupedByLatitude.keySet().iterator(); iter.hasNext();) |
1069 | |
{ |
1070 | 0 | count += triplesGroupedByLatitude.get(iter.next()).size(); |
1071 | |
} |
1072 | 0 | if (count != locationLookupValues.length) |
1073 | |
{ |
1074 | 0 | LOG.error("latitudes where not grouped by latitude correctly"); |
1075 | 0 | System.exit(-1); |
1076 | |
} |
1077 | |
|
1078 | 0 | return triplesGroupedByLatitude; |
1079 | |
} |
1080 | |
|
1081 | |
|
1082 | |
|
1083 | |
|
1084 | |
|
1085 | |
|
1086 | |
|
1087 | |
public Map<Integer, List<String>> getDatesByDecade(List<String> dates) |
1088 | |
{ |
1089 | 0 | Map<Integer, List<String>> datesGroupedByDecade = new HashMap<Integer, List<String>>(); |
1090 | |
|
1091 | 0 | for (String date : dates) |
1092 | |
{ |
1093 | 0 | int year = Integer.valueOf(date.substring(0, 4)); |
1094 | 0 | int decade = year / 10; |
1095 | |
|
1096 | 0 | List<String> datesInDecade = datesGroupedByDecade.get(decade); |
1097 | 0 | if (datesInDecade == null) |
1098 | |
{ |
1099 | 0 | datesInDecade = new ArrayList<String>(); |
1100 | 0 | datesGroupedByDecade.put(decade, datesInDecade); |
1101 | |
} |
1102 | 0 | datesInDecade.add(date); |
1103 | |
} |
1104 | |
|
1105 | |
|
1106 | 0 | int count = 0; |
1107 | 0 | for (Iterator<Integer> iter = datesGroupedByDecade.keySet().iterator(); iter.hasNext();) |
1108 | |
{ |
1109 | 0 | count += datesGroupedByDecade.get(iter.next()).size(); |
1110 | |
} |
1111 | 0 | if (count != dates.size()) |
1112 | |
{ |
1113 | 0 | LOG.error("dates where not grouped decade correctly"); |
1114 | 0 | System.exit(-1); |
1115 | |
} |
1116 | |
|
1117 | 0 | return datesGroupedByDecade; |
1118 | |
} |
1119 | |
|
1120 | |
|
1121 | |
|
1122 | |
|
1123 | |
|
1124 | |
|
1125 | |
|
1126 | |
private List<CellData> getAllTriples(String[][] locationLookupValues) |
1127 | |
{ |
1128 | 0 | List<CellData> allTriples = new ArrayList<CellData>(); |
1129 | 0 | for (int i = 0; i < locationLookupValues.length; i++) |
1130 | |
{ |
1131 | 0 | String cellId = locationLookupValues[i][CELL_ID_COLUMN_INDEX]; |
1132 | 0 | String longitude = locationLookupValues[i][LONG_COLUMN_INDEX]; |
1133 | 0 | String latitude = locationLookupValues[i][LAT_COLUMN_INDEX]; |
1134 | 0 | String elevation = locationLookupValues[i][ELEVATION_COLUMN_INDEX]; |
1135 | 0 | String catchmentId = locationLookupValues[i][CATCHMENT_ID_COLUMN_INDEX]; |
1136 | 0 | String reportingRegionId = locationLookupValues[i][REPORTING_REGION_ID_COLUMN_INDEX]; |
1137 | |
|
1138 | 0 | CellData cellData = new CellData(cellId, longitude, latitude); |
1139 | 0 | cellData.elevation = elevation; |
1140 | 0 | cellData.catchmentId = catchmentId; |
1141 | 0 | cellData.reportingRegionId = reportingRegionId; |
1142 | 0 | allTriples.add(cellData); |
1143 | |
} |
1144 | |
|
1145 | |
|
1146 | 0 | if (allTriples.size() != locationLookupValues.length) |
1147 | |
{ |
1148 | 0 | LOG.error("lookup values where not read correctly"); |
1149 | 0 | System.exit(-1); |
1150 | |
} |
1151 | |
|
1152 | 0 | return allTriples; |
1153 | |
} |
1154 | |
|
1155 | |
|
1156 | |
|
1157 | |
|
1158 | |
|
1159 | |
|
1160 | |
private String[][] readLookupFile() throws IOException |
1161 | |
{ |
1162 | 0 | RandomAccessFile raf = new RandomAccessFile(new File(LOCATION_LOOKUP_FILE), "r"); |
1163 | 0 | raf.readLine(); |
1164 | |
|
1165 | 0 | List<String[]> lineList = new ArrayList<String[]>(); |
1166 | 0 | String line = raf.readLine(); |
1167 | 0 | while (line != null) |
1168 | |
{ |
1169 | 0 | String[] cols = new CSVTokenizer(line).getAllColumns(); |
1170 | 0 | lineList.add(cols); |
1171 | 0 | line = raf.readLine(); |
1172 | |
} |
1173 | |
|
1174 | 0 | raf.close(); |
1175 | |
|
1176 | 0 | String[][] lineCols = lineList.toArray(new String[][]{}); |
1177 | 0 | return lineCols; |
1178 | |
} |
1179 | |
|
1180 | |
|
1181 | |
|
1182 | |
|
1183 | |
|
1184 | |
|
1185 | |
|
1186 | |
private String[][] transpose(String[][] gridValues) |
1187 | |
{ |
1188 | 0 | String[][] transposed = new String[gridValues[0].length][gridValues.length]; |
1189 | 0 | for (int rows = 0; rows < gridValues.length; rows++) |
1190 | |
{ |
1191 | 0 | for (int cols = 0; cols < gridValues[0].length; cols++) |
1192 | |
{ |
1193 | 0 | transposed[cols][rows] = gridValues[rows][cols]; |
1194 | |
} |
1195 | |
} |
1196 | 0 | return transposed; |
1197 | |
} |
1198 | |
|
1199 | |
|
1200 | |
|
1201 | |
|
1202 | |
|
1203 | |
|
1204 | |
|
1205 | |
private Set<String> getSortedLatitudes(List<CellData> triples) |
1206 | |
{ |
1207 | 0 | Set<String> latitudes = new TreeSet<String>(); |
1208 | 0 | for (CellData triple : triples) |
1209 | |
{ |
1210 | 0 | latitudes.add(triple.getLatitude()); |
1211 | |
|
1212 | |
|
1213 | |
|
1214 | |
|
1215 | |
} |
1216 | 0 | return latitudes; |
1217 | |
} |
1218 | |
|
1219 | |
|
1220 | |
|
1221 | |
|
1222 | |
|
1223 | |
|
1224 | |
|
1225 | |
private Set<String> getSortedLongitudes(List<CellData> triples) |
1226 | |
{ |
1227 | 0 | Set<String> longitudes = new TreeSet<String>(); |
1228 | 0 | for (CellData triple : triples) |
1229 | |
{ |
1230 | 0 | longitudes.add(triple.getLongitude()); |
1231 | |
|
1232 | |
|
1233 | |
|
1234 | |
|
1235 | |
} |
1236 | 0 | return longitudes; |
1237 | |
} |
1238 | |
|
1239 | |
|
1240 | |
|
1241 | |
|
1242 | |
|
1243 | |
private List<String> getDates() throws IOException |
1244 | |
{ |
1245 | 0 | List<String> dates = new ArrayList<String>(); |
1246 | |
|
1247 | 0 | RandomAccessFile raf = null; |
1248 | |
try |
1249 | |
{ |
1250 | |
|
1251 | 0 | File dir = new File(INPUT_CSV_DIRECTORY); |
1252 | 0 | String[] children = dir.list(); |
1253 | 0 | if (children != null && children.length > 0) |
1254 | |
{ |
1255 | 0 | raf = new RandomAccessFile(new File(INPUT_CSV_DIRECTORY + children[0]), "r"); |
1256 | 0 | raf.readLine(); |
1257 | |
|
1258 | 0 | List<String[]> lineList = new ArrayList<String[]>(); |
1259 | 0 | String line = raf.readLine(); |
1260 | 0 | while (line != null) |
1261 | |
{ |
1262 | 0 | String[] cols = new CSVTokenizer(line).getAllColumns(); |
1263 | 0 | lineList.add(cols); |
1264 | 0 | line = raf.readLine(); |
1265 | |
} |
1266 | 0 | String[][] lineCols = lineList.toArray(new String[][]{}); |
1267 | 0 | dates = Arrays.asList(transpose(lineCols)[DATE_COLUMN_INDEX]); |
1268 | |
} |
1269 | |
} |
1270 | |
finally |
1271 | 0 | { |
1272 | 0 | if (raf != null) |
1273 | 0 | raf.close(); |
1274 | 0 | } |
1275 | |
|
1276 | 0 | return dates; |
1277 | |
} |
1278 | |
|
1279 | |
|
1280 | |
|
1281 | |
|
1282 | |
|
1283 | |
|
1284 | |
|
1285 | |
|
1286 | |
|
1287 | |
private List<String> getDatesAsDaysSinceEpoc(List<String> dates) throws IOException, java.text.ParseException |
1288 | |
{ |
1289 | 0 | return daysSinceSinceEpocAsString(dates, isoDateTimeFormat.dateOnlyFormat(EPOC_DATE_STRING)); |
1290 | |
} |
1291 | |
|
1292 | |
|
1293 | |
|
1294 | |
|
1295 | |
|
1296 | |
|
1297 | |
|
1298 | |
|
1299 | |
|
1300 | |
|
1301 | |
private List<String> daysSinceSinceEpocAsString(List<String> dates, Date epoc) throws java.text.ParseException |
1302 | |
{ |
1303 | 0 | List<String> convertedDates = new ArrayList<String>(); |
1304 | 0 | for (String date : dates) |
1305 | |
{ |
1306 | 0 | Date currentDate = isoDateTimeFormat.dateOnlyFormat(date); |
1307 | 0 | convertedDates.add(String.valueOf(daysBetween(epoc, currentDate))); |
1308 | |
} |
1309 | 0 | return convertedDates; |
1310 | |
} |
1311 | |
|
1312 | |
|
1313 | |
|
1314 | |
|
1315 | |
|
1316 | |
|
1317 | |
|
1318 | |
|
1319 | |
public int daysBetween(Date d1, Date d2) |
1320 | |
{ |
1321 | 0 | return (int) ((d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24)); |
1322 | |
} |
1323 | |
|
1324 | |
private String generateLatitudeFilename(String latitudeDegree, String variable) |
1325 | |
{ |
1326 | 0 | String filename = OUTPUT_NETCDF_DIRECTORY + COLLECTION + "." + SCENARIO + "."; |
1327 | 0 | if (MODEL_NAMES[FILE_NAME_MODEL_NAME].length() > 0) |
1328 | |
{ |
1329 | 0 | filename += MODEL_NAMES[FILE_NAME_MODEL_NAME] + "."; |
1330 | |
} |
1331 | 0 | if (CASE.length() > 0) |
1332 | |
{ |
1333 | 0 | filename += CASE + "."; |
1334 | |
} |
1335 | 0 | filename += "Latitude-"; |
1336 | 0 | if (latitudeDegree.startsWith("-")) |
1337 | |
{ |
1338 | 0 | filename += latitudeDegree.substring(1) + "S."; |
1339 | |
} |
1340 | |
else |
1341 | |
{ |
1342 | 0 | filename += latitudeDegree + "N."; |
1343 | |
} |
1344 | 0 | filename += "Var-" + variable + NETCDF_FILE_EXTENSION; |
1345 | 0 | return filename; |
1346 | |
} |
1347 | |
|
1348 | |
private String generateDecadeFilename(String decadeStr, String variable) |
1349 | |
{ |
1350 | 0 | String filename = OUTPUT_NETCDF_DIRECTORY + COLLECTION + "." + SCENARIO + "."; |
1351 | 0 | if (MODEL_NAMES[FILE_NAME_MODEL_NAME].length() > 0) |
1352 | |
{ |
1353 | 0 | filename += MODEL_NAMES[FILE_NAME_MODEL_NAME] + "."; |
1354 | |
} |
1355 | 0 | if (CASE.length() > 0) |
1356 | |
{ |
1357 | 0 | filename += CASE + "."; |
1358 | |
} |
1359 | 0 | filename += "Decade-" + decadeStr + ".Var-" + variable + NETCDF_FILE_EXTENSION; |
1360 | 0 | return filename; |
1361 | |
} |
1362 | |
|
1363 | |
|
1364 | |
|
1365 | |
|
1366 | |
|
1367 | |
|
1368 | |
@SuppressWarnings("unused") |
1369 | |
private void printLookupInMemory(Map<Integer, Map<String, LongitudeRange>> lookup) |
1370 | |
{ |
1371 | 0 | for (Iterator<Integer> dateIter = lookup.keySet().iterator(); dateIter.hasNext();) |
1372 | |
{ |
1373 | 0 | Integer dateKey = dateIter.next(); |
1374 | 0 | System.out.println(dateKey); |
1375 | |
|
1376 | 0 | for (Iterator<String> latIter = lookup.get(dateKey).keySet().iterator(); latIter.hasNext();) |
1377 | |
{ |
1378 | 0 | String latitude = latIter.next(); |
1379 | 0 | System.out.println("\t" + latitude); |
1380 | |
|
1381 | 0 | LongitudeRange longitudeRange = lookup.get(dateKey).get(latitude); |
1382 | 0 | System.out.println("\t\t" + longitudeRange.getStartLongitudeRange() + "-" |
1383 | 0 | + longitudeRange.getEndLongitudeRange()); |
1384 | |
} |
1385 | |
} |
1386 | 0 | } |
1387 | |
|
1388 | 0 | public enum CellDataVariable |
1389 | |
{ |
1390 | 0 | CELLID, LONGITUDE, LATITUDE, ELEVATION, CATCHMENTID, REPORTINGREGIONID |
1391 | |
} |
1392 | |
|
1393 | |
|
1394 | |
|
1395 | |
|
1396 | |
|
1397 | |
|
1398 | |
|
1399 | |
|
1400 | |
|
1401 | |
private static String[] getModelMapping(String directoryModelName) |
1402 | |
{ |
1403 | |
|
1404 | 0 | final String MODEL_NAME_PREFIX = "Model-"; |
1405 | 0 | int beginIndex = directoryModelName.indexOf(MODEL_NAME_PREFIX); |
1406 | 0 | if (beginIndex != -1) |
1407 | |
{ |
1408 | 0 | directoryModelName = directoryModelName.substring(beginIndex + (MODEL_NAME_PREFIX.length())); |
1409 | |
} |
1410 | |
|
1411 | |
|
1412 | |
|
1413 | 0 | if (CLIMATE_MODELS.containsKey(directoryModelName)) |
1414 | |
{ |
1415 | 0 | String[] modelNameMapping = new String[2]; |
1416 | 0 | modelNameMapping[FILE_NAME_MODEL_NAME] = MODEL_NAME_PREFIX + directoryModelName; |
1417 | 0 | modelNameMapping[IPCC_MODEL_NAME] = CLIMATE_MODELS.get(directoryModelName); |
1418 | 0 | return modelNameMapping; |
1419 | |
} |
1420 | 0 | throw new IllegalArgumentException("Unknown model: " + directoryModelName + ". Valid models are: " |
1421 | 0 | + CLIMATE_MODELS.keySet()); |
1422 | |
} |
1423 | |
} |