5adac812 by Nathan Lighthart

Merge branch 'feature/co2reading' into develop

2 parents bc9d664f b8441ceb
......@@ -988,6 +988,7 @@ public class AgESModel {
last = now;
}
temporalContext.put("time", time);
readerCO2.readData();
readerCO2.setValue(temporalContext);
if (temporalReader != null) {
......
......@@ -27,7 +27,8 @@ import java.io.IOException;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAccessor;
import java.util.Arrays;
import java.util.Iterator;
......@@ -42,9 +43,12 @@ public class CO2ClimateReader implements ClimateReader {
private Iterator<String[]> rows;
private DateTimeFormatter dateFormatter;
private double co2;
private double missingDataValue;
private LocalDate time;
private double co2;
private RowData nextUpdate;
public CO2ClimateReader(Path dataFilePath, double defaultCO2, LocalDate startTime, LocalDate endTime) {
this.dataFilePath = dataFilePath;
this.defaultCO2 = defaultCO2;
......@@ -61,23 +65,33 @@ public class CO2ClimateReader implements ClimateReader {
if (alwaysDefault) {
return;
}
try {
readData0();
} catch (Exception ex) {
throw new IOException("Error reading co2 file: " + dataFilePath, ex);
}
}
private void readData0() throws Exception {
// Initialize if not intialized otherwise update the time to the next day
if (rows == null) {
init();
time = startTime;
} else {
time = time.plusDays(1L);
}
String[] row = rows.next();
if (row.length < 3) {
throw new IOException("Malformed data line: " + Arrays.toString(row));
} else {
try {
co2 = Double.parseDouble(row[2]);
} catch (NumberFormatException ex) {
throw new IOException("Malformed data line: " + Arrays.toString(row), ex);
}
// if nextUpdate is null then there is no more data to read
// when there is no more data to read co2 should stay as the last known value
if (nextUpdate == null) {
return; // no more data to read so keep using last known value
}
if (Double.compare(co2, missingDataValue) == 0) {
co2 = defaultCO2;
// If nextUpdate.time >= time then update co2 and read next value
if (!time.isBefore(nextUpdate.time)) {
updateCO2(nextUpdate.co2);
nextUpdate = readNextRow();
}
}
......@@ -117,7 +131,7 @@ public class CO2ClimateReader implements ClimateReader {
if (missingDataValueString == null) {
missingDataValueString = table.getInfo().get("missing_val");
if (missingDataValueString == null) {
throw new IOException("Missing data value cannot be found");
missingDataValueString = "NaN";
}
}
missingDataValue = Double.parseDouble(missingDataValueString);
......@@ -128,17 +142,88 @@ public class CO2ClimateReader implements ClimateReader {
throw new IOException("Missing start/end time in " + dataFilePath);
}
LocalDate tableStartTime = LocalDate.parse(tableStartTimeString, dateFormatter);
LocalDate tableEndTime = LocalDate.parse(tableEndTimeString, dateFormatter);
if (startTime.isBefore(tableStartTime) || endTime.isAfter(tableEndTime) || tableEndTime.isBefore(tableStartTime)) {
throw new IOException("Illegal start/end in " + dataFilePath + " "
+ dateFormatter.format(startTime) + " - " + dateFormatter.format(endTime));
// Parse table start and end time
LocalDate tableStartTime;
LocalDate tableEndTime;
try {
tableStartTime = parseDate(tableStartTimeString);
} catch (DateTimeParseException ex) {
throw new IOException("Error parsing table start time: " + tableStartTimeString, ex);
}
try {
tableEndTime = parseDate(tableEndTimeString);
} catch (DateTimeParseException ex) {
throw new IOException("Error parsing table end time: " + tableEndTimeString, ex);
}
// validate that table end time is not before the table start time
// It is valid for tableEndTime >= tableStartTime
if (tableEndTime.isBefore(tableStartTime)) {
throw new IOException("Invalid co2 table time range: "
+ formatDate(tableStartTime) + " - " + formatDate(tableEndTime));
}
// validate table times are within simulation times
if (startTime.isBefore(tableStartTime)) {
System.out.println("WARNING: Simulation start time is before the start time of the co2 file. The default CO2 value of " + defaultCO2 + " will be used.");
}
// read co2 values until end of dates or until start time is found
co2 = defaultCO2;
while (true) {
nextUpdate = readNextRow();
if (nextUpdate == null) {
break;
} else if (nextUpdate.time.isAfter(startTime)) {
break;
} else {
updateCO2(nextUpdate.co2);
}
}
}
private RowData readNextRow() throws IOException {
if (!rows.hasNext()) {
return null;
}
String[] row = rows.next();
try {
return readNextRow0(row);
} catch (Exception ex) {
throw new IOException("Malformed data line: " + Arrays.toString(row), ex);
}
}
private RowData readNextRow0(String[] row) {
LocalDate timeValue = parseDate(row[1]);
double co2Value = Double.parseDouble(row[2]);
return new RowData(timeValue, co2Value);
}
private LocalDate parseDate(String dateString) throws DateTimeParseException {
return dateFormatter.parse(dateString, LocalDate::from);
}
private String formatDate(TemporalAccessor temporal) {
return dateFormatter.format(temporal);
}
private void updateCO2(double co2Value) {
// if new co2 value is missing value then leave as the last know value
if (Double.compare(co2Value, missingDataValue) == 0) {
return;
}
co2 = co2Value;
}
private class RowData {
public final LocalDate time;
public final double co2;
long daysUntilStart = tableStartTime.until(startTime, ChronoUnit.DAYS);
while (daysUntilStart > 0) {
rows.next();
--daysUntilStart;
public RowData(LocalDate time, double co2) {
this.time = time;
this.co2 = co2;
}
}
}
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!