diff --git a/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java b/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java index 33974c2..5c853dc 100644 --- a/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java +++ b/src/main/java/org/matsim/analysis/postAnalysis/NoiseAverageAnalysis.java @@ -40,7 +40,8 @@ @CommandLine.Command(name = "average-noise", description = "Calculates average noise stats based on several sim runs with different random seeds.") @CommandSpec( requires = {"runs"}, - produces = {"mean_emission_per_day.csv", "mean_immission_per_day.avro", "mean_immission_per_hour.avro"} + produces = {"mean_emission_per_day.csv", "mean_immission_per_day.avro", "mean_immission_per_hour.avro", "mean_noise_stats.csv", + "mean_damages_receiverPoint_per_day.avro", "mean_damages_receiverPoint_per_hour.avro"} ) public class NoiseAverageAnalysis implements MATSimAppCommand { private final Logger log = LogManager.getLogger(NoiseAverageAnalysis.class); @@ -58,6 +59,10 @@ public class NoiseAverageAnalysis implements MATSimAppCommand { private List imissionsPerHour = new ArrayList<>(); private Map> emissionsPerDay = new HashMap<>(); private Map meanEmissionsPerDay = new HashMap<>(); + private Map> totalStats = new HashMap<>(); + private Map meanTotalStatsPerDay = new HashMap<>(); + private List damagesPerDay = new ArrayList<>(); + private List damagesPerHour = new ArrayList<>(); public static void main(String[] args) { @@ -81,6 +86,9 @@ public Integer call() throws Exception { String emissionsCsv = globFile(analysisDir, "*emission_per_day.csv*").toString(); String imissionsPerDayAvro = globFile(analysisDir, "*immission_per_day.avro*").toString(); String imissionsPerHourAvro = globFile(analysisDir, "*immission_per_hour.avro*").toString(); + String totalStatsCsv = globFile(analysisDir, "*noise_stats.csv*").toString(); + String damagesPerDayAvro = globFile(analysisDir, "*damages_receiverPoint_per_day.avro*").toString(); + String damagesPerHourAvro = globFile(analysisDir, "*damages_receiverPoint_per_hour.avro*").toString(); // read Table emissions = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(emissionsCsv)) @@ -88,9 +96,17 @@ public Integer call() throws Exception { .sample(false) .separator(CsvOptions.detectDelimiter(emissionsCsv)).build()); -// read avro file + Table totalStatsTable = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(totalStatsCsv)) + .columnTypes(new ColumnType[]{ColumnType.STRING, ColumnType.DOUBLE}) + .header(false) + .sample(false) + .separator(CsvOptions.detectDelimiter(totalStatsCsv)).build()); + +// read avro files readAvroFile(imissionsPerDayAvro, imissionsPerDay); readAvroFile(imissionsPerHourAvro, imissionsPerHour); + readAvroFile(damagesPerDayAvro, damagesPerDay); + readAvroFile(damagesPerHourAvro, damagesPerHour); // get all emission stats for (int i = 0; i < emissions.rowCount(); i++) { @@ -101,20 +117,28 @@ public Integer call() throws Exception { } emissionsPerDay.get(row.getString(LINK_ID)).add(row.getDouble(VALUE)); } - } -// calc emission means and write to mean map - for (Map.Entry> e : emissionsPerDay.entrySet()) { - AtomicReference sum = new AtomicReference<>(0.); - e.getValue().forEach(d -> sum.set(sum.get() + d)); +// get all total stats + for (int i = 0; i < totalStatsTable.rowCount(); i++) { + Row row = totalStatsTable.row(i); - meanEmissionsPerDay.put(e.getKey(), sum.get() / e.getValue().size()); + if (!totalStats.containsKey(row.getString(0))) { + totalStats.put(row.getString(0), new ArrayList<>()); + } + totalStats.get(row.getString(0)).add(row.getDouble(1)); + } } -// calc avro means - XYTData imissionsPerDayMean = calcAvroMeans(imissionsPerDay); - XYTData imissionsPerHourMean = calcAvroMeans(imissionsPerHour); +// calc emission means and write to mean map + calcCsvMeans(emissionsPerDay, meanEmissionsPerDay); +// calc mean total stats and write to mean map + calcCsvMeans(totalStats, meanTotalStatsPerDay); +// calc avro means + XYTData imissionsPerDayMean = calcAvroMeans(imissionsPerDay, "imissions"); + XYTData imissionsPerHourMean = calcAvroMeans(imissionsPerHour, "imissions"); + XYTData damagesPerDayMean = calcAvroMeans(damagesPerDay, "damages_receiverPoint"); + XYTData damagesPerHourMean = calcAvroMeans(damagesPerHour, "damages_receiverPoint"); // write emission mean stats try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath("mean_emission_per_day.csv")), CSVFormat.DEFAULT)) { @@ -125,15 +149,33 @@ public Integer call() throws Exception { } } +// write total mean stats + try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath("mean_noise_stats.csv")), CSVFormat.DEFAULT)) { + for (Map.Entry e : meanTotalStatsPerDay.entrySet()) { + printer.printRecord(e.getKey(), e.getValue()); + } + } + // write avro mean files writeAvro(imissionsPerDayMean, new File(output.getPath("mean_immission_per_day.avro").toString())); writeAvro(imissionsPerHourMean, new File(output.getPath("mean_immission_per_hour.avro").toString())); + writeAvro(damagesPerDayMean, new File(output.getPath("mean_damages_receiverPoint_per_day.avro").toString())); + writeAvro(damagesPerHourMean, new File(output.getPath("mean_damages_receiverPoint_per_hour.avro").toString())); return 0; } + private void calcCsvMeans(Map> dataMap, Map meanMap) { + for (Map.Entry> e : dataMap.entrySet()) { + AtomicReference sum = new AtomicReference<>(0.); + e.getValue().forEach(d -> sum.set(sum.get() + d)); + + meanMap.put(e.getKey(), sum.get() / e.getValue().size()); + } + } + /** - * write an .avro file containing immission data. + * write an .avro file containing immission / damage data. */ public void writeAvro(XYTData xytData, File outputFile) { DatumWriter datumWriter = new SpecificDatumWriter<>(XYTData.class); @@ -146,7 +188,7 @@ public void writeAvro(XYTData xytData, File outputFile) { } } - private XYTData calcAvroMeans(List recordList) { + private XYTData calcAvroMeans(List recordList, String dataFieldName) { String crs = null; List xCoords = new ArrayList<>(); List yCoords = new ArrayList<>(); @@ -189,7 +231,7 @@ private XYTData calcAvroMeans(List recordList) { List values = new ArrayList<>(); for (Map.Entry entry : ((HashMap) object4).entrySet()) { - if (entry.getKey() instanceof Utf8 && entry.getKey().toString().equals("imissions") && entry.getValue() instanceof GenericData.Array) { + if (entry.getKey() instanceof Utf8 && entry.getKey().toString().equals(dataFieldName) && entry.getValue() instanceof GenericData.Array) { values.addAll((GenericData.Array) entry.getValue()); String entryString = ((Utf8) entry.getKey()).toString(); @@ -211,7 +253,7 @@ private XYTData calcAvroMeans(List recordList) { // calc mean values for each datapoint out of sums and number of records (1 record = 1 run seed) data.entrySet() .stream() - .filter(entry -> entry.getKey().equals("imissions")) + .filter(entry -> entry.getKey().equals(dataFieldName)) .forEach(entry -> entry.getValue() .forEach(value -> entry.getValue().set(entry.getValue().indexOf(value), value / recordList.size()))); @@ -234,7 +276,7 @@ private void getCoordData(Object object, List target) { } /** - * read an .avro file containing immissions. + * read an .avro file containing immissions / damages. */ public void readAvroFile(String input, List target) { try { diff --git a/src/main/java/org/matsim/dashboard/AverageKelheimEmissionsDashboard.java b/src/main/java/org/matsim/dashboard/AverageKelheimEmissionsDashboard.java index 526e24b..ba6201d 100644 --- a/src/main/java/org/matsim/dashboard/AverageKelheimEmissionsDashboard.java +++ b/src/main/java/org/matsim/dashboard/AverageKelheimEmissionsDashboard.java @@ -92,7 +92,7 @@ public void configure(Header header, Layout layout) { viz.height = 12.0; viz.datasets.csvFile = postProcess(data, "mean_emissions_per_link_per_m.csv"); viz.datasets.csvBase = Path.of(this.dirs.get(0)).getParent().relativize(Path.of(pathToCsvBase)).toString(); - viz.network = new CreateAverageDashboards().copyGeoJsonNetwork(dirs); + viz.network = new CreateAverageDashboards().copyVizNetwork(dirs, ".avro"); viz.display.color.columnName = "CO2_TOTAL [g/m]"; viz.display.color.dataset = "csvFile"; viz.display.width.scaleFactor = 100; diff --git a/src/main/java/org/matsim/dashboard/AverageKelheimNoiseDashboard.java b/src/main/java/org/matsim/dashboard/AverageKelheimNoiseDashboard.java index cb83ae7..333dc57 100644 --- a/src/main/java/org/matsim/dashboard/AverageKelheimNoiseDashboard.java +++ b/src/main/java/org/matsim/dashboard/AverageKelheimNoiseDashboard.java @@ -8,6 +8,7 @@ import org.matsim.simwrapper.viz.ColorScheme; import org.matsim.simwrapper.viz.GridMap; import org.matsim.simwrapper.viz.MapPlot; +import org.matsim.simwrapper.viz.Tile; import java.util.ArrayList; import java.util.List; @@ -26,6 +27,8 @@ public class AverageKelheimNoiseDashboard implements Dashboard { private static final String LIGHT_BLUE = "#95c7df"; private static final String ORANGE = "#f4a986"; private static final String RED = "#cc0c27"; + private static final String SAND = "#dfb095"; + private static final String YELLOW = "#dfdb95"; public AverageKelheimNoiseDashboard(List dirs, Integer noRuns) { this.dirs = dirs; @@ -45,51 +48,82 @@ public void configure(Header header, Layout layout) { header.title = "Average Noise"; header.description = "Shows the average noise footprint and spatial distribution for several simulation runs."; - layout.row("aggregate noise") - .el(GridMap.class, (viz, data) -> { - viz.title = "Noise Immissions (Grid)"; - viz.description = "Aggregate Noise Immissions per day"; - viz.height = 12.0; - viz.cellSize = 250; - viz.opacity = 0.2; - viz.maxHeight = 20; - viz.center = data.context().getCenter(); - viz.zoom = data.context().mapZoomLevel; - viz.setColorRamp(new double[]{40, 50, 60}, new String[]{DARK_BLUE, LIGHT_BLUE, ORANGE, RED}); - viz.file = postProcess(data, "mean_immission_per_day.avro"); - }) + layout.row("stats") + .el(Tile.class, (viz, data) -> { + viz.dataset = postProcess(data, "mean_noise_stats.csv"); + viz.height = 0.1; + }); + + layout.row("emissions") .el(MapPlot.class, (viz, data) -> { viz.title = "Noise Emissions (Link)"; - viz.description = "Aggregate Noise Emissions per day"; + viz.description = "Maximum Noise Level per day [dB]"; viz.height = 12.0; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; viz.minValue = minDb; viz.maxValue = maxDb; - viz.setShape(new CreateAverageDashboards().copyGeoJsonNetwork(dirs)); + viz.setShape(new CreateAverageDashboards().copyVizNetwork(dirs, ".avro")); viz.addDataset(NOISE, postProcess(data, "mean_emission_per_day.csv")); viz.display.lineColor.dataset = NOISE; viz.display.lineColor.columnName = "value"; viz.display.lineColor.join = "Link Id"; viz.display.lineColor.fixedColors = new String[]{DARK_BLUE, LIGHT_BLUE, ORANGE, RED}; - viz.display.lineColor.setColorRamp(ColorScheme.RdYlBu, 4, true, "45, 55, 65"); + viz.display.lineColor.setColorRamp(ColorScheme.Oranges, 8, false, "35, 45, 55, 65, 75, 85, 95"); viz.display.lineWidth.dataset = NOISE; viz.display.lineWidth.columnName = "value"; viz.display.lineWidth.scaleFactor = 8d; viz.display.lineWidth.join = "Link Id"; }); - layout.row("hourly noise") + layout.row("immissions") .el(GridMap.class, (viz, data) -> { - viz.title = "Hourly Noise Immissions (Grid)"; - viz.description = "Noise Immissions per hour"; + viz.title = "Noise Immissions (Grid)"; + viz.description = "Total Noise Immissions per day"; viz.height = 12.0; viz.cellSize = 250; viz.opacity = 0.2; viz.maxHeight = 20; viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; - viz.setColorRamp(new double[]{40, 50, 60}, new String[]{DARK_BLUE, LIGHT_BLUE, ORANGE, RED}); + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{DARK_BLUE, LIGHT_BLUE, YELLOW, SAND, ORANGE, RED}); + viz.file = postProcess(data, "mean_immission_per_day.avro"); + }) + .el(GridMap.class, (viz, data) -> { + viz.title = "Hourly Noise Immissions (Grid)"; + viz.description = "Noise Immissions per hour"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.1; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{DARK_BLUE, LIGHT_BLUE, YELLOW, SAND, ORANGE, RED}); viz.file = postProcess(data, "mean_immission_per_hour.avro"); }); + layout.row("damages") + .el(GridMap.class, (viz, data) -> { + viz.title = "Daily Noise Damages (Grid)"; + viz.description = "Total Noise Damages per day [€]"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.1; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{DARK_BLUE, LIGHT_BLUE, YELLOW, SAND, ORANGE, RED}); + viz.file = postProcess(data, "mean_damages_receiverPoint_per_day.avro"); + }) + .el(GridMap.class, (viz, data) -> { + viz.title = "Hourly Noise Damages (Grid)"; + viz.description = "Noise Damages per hour [€]"; + viz.height = 12.0; + viz.cellSize = 250; + viz.opacity = 0.2; + viz.maxHeight = 40; + viz.center = data.context().getCenter(); + viz.zoom = data.context().mapZoomLevel; + viz.setColorRamp(new double[]{30, 40, 50, 60, 70}, new String[]{DARK_BLUE, LIGHT_BLUE, YELLOW, SAND, ORANGE, RED}); + viz.file = postProcess(data, "mean_damages_receiverPoint_per_hour.avro"); + }); } } diff --git a/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java b/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java index cc0dd7f..b6dffb3 100644 --- a/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java +++ b/src/main/java/org/matsim/dashboard/CreateAverageDashboards.java @@ -82,23 +82,23 @@ public Integer call() throws Exception { } /** - * A helper method to copy an already existing Geojson network rather than creating it all over again. + * A helper method to copy an already existing Geojson / avro network rather than creating it all over again. */ - String copyGeoJsonNetwork(List dirs) { + String copyVizNetwork(List dirs, String fileType) { for (String dir : dirs) { - File networkFile = new File(dir + "/analysis/network/network.geojson"); + File networkFile = new File(dir + "/analysis/network/network" + fileType); Path target = Path.of(Path.of(dir).getParent() + "/analysis/network"); if (Files.notExists(target) && networkFile.exists() && networkFile.isFile()) { try { Files.createDirectories(target); - Files.copy(networkFile.toPath(), Path.of(target + "/network.geojson")); + Files.copy(networkFile.toPath(), Path.of(target + "/network" + fileType)); } catch (IOException e) { throw new UncheckedIOException(e); } } } - return "analysis/network/network.geojson"; + return "analysis/network/network" + fileType; } } diff --git a/src/test/java/org/matsim/run/MeanNoiseDashboardTest.java b/src/test/java/org/matsim/run/MeanNoiseDashboardTest.java index e53ed82..e3e0c50 100644 --- a/src/test/java/org/matsim/run/MeanNoiseDashboardTest.java +++ b/src/test/java/org/matsim/run/MeanNoiseDashboardTest.java @@ -11,7 +11,7 @@ import org.matsim.analysis.postAnalysis.NoiseAverageAnalysis; import org.matsim.application.avro.XYTData; import org.matsim.application.options.CsvOptions; -import org.matsim.application.prepare.network.CreateGeoJsonNetwork; +import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.core.utils.io.IOUtils; import org.matsim.dashboard.AverageKelheimNoiseDashboard; import org.matsim.simwrapper.Dashboard; @@ -35,6 +35,8 @@ class MeanNoiseDashboardTest { @RegisterExtension public final MatsimTestUtils utils = new MatsimTestUtils(); + private final NoiseAverageAnalysis analysis = new NoiseAverageAnalysis(); + /** * Test for building means over noise emission and immission values of several runs. The display of the values has to be done manually by looking at the resulting mean noise dashbaord. */ @@ -44,11 +46,10 @@ void runMeanNoiseDashboardTest() throws IOException { String networkPath = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/kelheim/kelheim-v3.0/input/kelheim-v3.0-network.xml.gz"; String crs = "EPSG:25832"; String path = utils.getInputDirectory(); - NoiseAverageAnalysis analysis = new NoiseAverageAnalysis(); List foldersSeeded = new ArrayList<>(); - new CreateGeoJsonNetwork().execute(List.of("--network", networkPath, "--with-properties", "--shp", "./input/shp/dilutionArea.shp", "--output-network", path + "1seed/analysis/network/network.geojson", + new CreateAvroNetwork().execute(List.of("--network", networkPath, "--with-properties", "--shp", "./input/shp/dilutionArea.shp", "--output-network", path + "1seed/analysis/network/network.avro", "--input-crs", "EPSG:25832").toArray(new String[0])); // write dummy data @@ -56,7 +57,8 @@ void runMeanNoiseDashboardTest() throws IOException { List xCoords = new ArrayList<>(); List yCoords = new ArrayList<>(); List timeStamps = new ArrayList<>(); - Map> data = new HashMap<>(); + Map> immissionData = new HashMap<>(); + Map> damageData = new HashMap<>(); xCoords.add(710419.08F); xCoords.add(710424.82F); @@ -65,21 +67,31 @@ void runMeanNoiseDashboardTest() throws IOException { timeStamps.add(28800); - data.put("imissions", List.of((float) i)); + immissionData.put("imissions", List.of((float) i)); + damageData.put("damages_receiverPoint", List.of((float) i)); String seedDir = path + i + "seed/"; foldersSeeded.add(seedDir); // write avro dummy files Files.createDirectories(Path.of(seedDir + "analysis/noise/")); - analysis.writeAvro(new XYTData(crs, xCoords, yCoords, List.of(0), data), new File(seedDir + "analysis/noise/immission_per_day.avro")); - analysis.writeAvro(new XYTData(crs, xCoords, yCoords, timeStamps, data), new File(seedDir + "analysis/noise/immission_per_hour.avro")); + analysis.writeAvro(new XYTData(crs, xCoords, yCoords, List.of(0), immissionData), new File(seedDir + "analysis/noise/immission_per_day.avro")); + analysis.writeAvro(new XYTData(crs, xCoords, yCoords, timeStamps, immissionData), new File(seedDir + "analysis/noise/immission_per_hour.avro")); + analysis.writeAvro(new XYTData(crs, xCoords, yCoords, List.of(0), damageData), new File(seedDir + "analysis/noise/damages_receiverPoint_per_day.avro")); + analysis.writeAvro(new XYTData(crs, xCoords, yCoords, timeStamps, damageData), new File(seedDir + "analysis/noise/damages_receiverPoint_per_hour.avro")); // write emissions csv dummy file try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Path.of(seedDir + "analysis/noise/emission_per_day.csv")), CSVFormat.DEFAULT)) { printer.printRecord("Link Id", "value"); printer.printRecord("-27443742#0", i); } + +// write total stats csv dummy file + try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Path.of(seedDir + "analysis/noise/noise_stats.csv")), CSVFormat.DEFAULT)) { + printer.printRecord("Annual cost rate per pop. unit [€]:", i); + printer.printRecord("Total damages at receiver points", i); + printer.printRecord("Total immission at receiver points", i); + } } SimWrapper sw = SimWrapper.create(); @@ -92,32 +104,25 @@ void runMeanNoiseDashboardTest() throws IOException { } sw.run(Path.of(path)); -// assert that: a) mean immission is 2.0 on daily and hourly data b) hourly data has timestamp 28800 c) mean emission is 2.0 - List daily = new ArrayList<>(); - List hourly = new ArrayList<>(); - analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_immission_per_day.avro", daily); - analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_immission_per_hour.avro", hourly); - - if (daily.getFirst().get(4) instanceof HashMap) { - Map.Entry entry = ((HashMap) daily.getFirst().get(4)).entrySet().stream().toList().getFirst(); - if (entry.getKey() instanceof Utf8 && entry.getValue() instanceof GenericData.Array) { - float dailyImmission = ((GenericData.Array) entry.getValue()).getFirst(); - Assertions.assertEquals(2.0, dailyImmission); - } - } - - if (hourly.getFirst().get(4) instanceof HashMap) { - Map.Entry entry = ((HashMap) hourly.getFirst().get(4)).entrySet().stream().toList().getFirst(); - if (entry.getKey() instanceof Utf8 && entry.getValue() instanceof GenericData.Array) { - float hourlyImmission = ((GenericData.Array) entry.getValue()).getFirst(); - Assertions.assertEquals(2.0, hourlyImmission); - } - } - - if (hourly.getFirst().get(3) instanceof GenericData.Array) { - int timeStamp = ((GenericData.Array) hourly.getFirst().get(3)).getFirst(); - Assertions.assertEquals(28800, timeStamp); - } +// assert that: +// a) mean immission is 2.0 on daily and hourly data +// b) hourly immission data has timestamp 28800 +// c) mean emission is 2.0 +// d) all mean total stats are 2.0 +// e) mean damage is 2.0 on daily and hourly data +// f) hourly damage data has timestamp + List dailyImmission = new ArrayList<>(); + List hourlyImmission = new ArrayList<>(); + List dailyDamage = new ArrayList<>(); + List hourlyDamage = new ArrayList<>(); + analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_immission_per_day.avro", dailyImmission); + analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_immission_per_hour.avro", hourlyImmission); + analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_damages_receiverPoint_per_day.avro", dailyDamage); + analysis.readAvroFile(path + "analysis/postAnalysis-noise/mean_damages_receiverPoint_per_hour.avro", hourlyDamage); + + assertValue(dailyImmission); + assertValue(hourlyImmission); + assertTimeStamp(hourlyImmission); Table emissions = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path + "analysis/postAnalysis-noise/mean_emission_per_day.csv")) .columnTypesPartial(Map.of("Link Id", ColumnType.STRING, "value", ColumnType.DOUBLE)) @@ -129,5 +134,46 @@ void runMeanNoiseDashboardTest() throws IOException { Assertions.assertEquals("-27443742#0", linkId); Assertions.assertEquals(2.0, emission); + + Table totalStats = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(path + "analysis/postAnalysis-noise/mean_noise_stats.csv")) + .columnTypes(new ColumnType[]{ColumnType.STRING, ColumnType.DOUBLE}) + .header(false) + .sample(false) + .separator(CsvOptions.detectDelimiter(path + "analysis/postAnalysis-noise/mean_noise_stats.csv")).build()); + + String row1ParamName = (String) totalStats.get(0, 0); + String row2ParamName = (String) totalStats.get(1, 0); + String row3ParamName = (String) totalStats.get(2, 0); + double row1Value = (Double) totalStats.get(0, 1); + double row2Value = (Double) totalStats.get(1, 1); + double row3Value = (Double) totalStats.get(2, 1); + + Assertions.assertEquals("Annual cost rate per pop. unit [€]:", row1ParamName); + Assertions.assertEquals("Total damages at receiver points", row2ParamName); + Assertions.assertEquals("Total immission at receiver points", row3ParamName); + Assertions.assertEquals(2.0, row1Value); + Assertions.assertEquals(2.0, row2Value); + Assertions.assertEquals(2.0, row3Value); + + assertValue(dailyDamage); + assertValue(hourlyDamage); + assertTimeStamp(hourlyDamage); + } + + private static void assertTimeStamp(List records) { + if (records.getFirst().get(3) instanceof GenericData.Array) { + int timeStamp = ((GenericData.Array) records.getFirst().get(3)).getFirst(); + Assertions.assertEquals(28800, timeStamp); + } + } + + private static void assertValue(List records) { + if (records.getFirst().get(4) instanceof HashMap) { + Map.Entry entry = ((HashMap) records.getFirst().get(4)).entrySet().stream().toList().getFirst(); + if (entry.getKey() instanceof Utf8 && entry.getValue() instanceof GenericData.Array) { + float value = ((GenericData.Array) entry.getValue()).getFirst(); + Assertions.assertEquals(2.0, value); + } + } } }