diff --git a/contribs/application/src/main/avro/network.avsc b/contribs/application/src/main/avro/network.avsc new file mode 100644 index 00000000000..fe257c6d8c6 --- /dev/null +++ b/contribs/application/src/main/avro/network.avsc @@ -0,0 +1,79 @@ +{ + "namespace": "org.matsim.application.avro", + "type": "record", + "name": "AvroNetwork", + "fields": [ + { + "name": "crs", + "type": "string", + "doc": "Coordinate reference system" + }, + { + "name": "nodeAttributes", + "type": { + "type": "array", + "items": "string" + } + }, + { + "name": "linkAttributes", + "type": { + "type": "array", + "items": "string" + } + }, + { + "type": { + "type": "array", + "items": "string" + }, + "name": "nodeId" + }, + { + "type": { + "type": "array", + "items": "float" + }, + "name": "nodeCoordinates" + }, + {"type": {"type": "array", "items": "string" }, "name": "linkId"}, + {"type": {"type": "array", "items": "int" }, "name": "from"}, + {"type": {"type": "array", "items": "int"}, "name": "to"}, + {"type": { "type": "array", "items": "string"}, "name": "modes"}, + { + "type": { + "type": "array", + "items": "float" + }, + "name": "length" + }, + { + "type": { + "type": "array", + "items": "float" + }, + "name": "freespeed" + }, + { + "type": { + "type": "array", + "items": "float" + }, + "name": "capacity" + }, + { + "type": { + "type": "array", + "items": "float" + }, + "name": "permlanes" + }, + { + "type": { + "type": "array", + "items": "int" + }, + "name": "allowedModes" + } + ] +} diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/emissions/AirPollutionAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/emissions/AirPollutionAnalysis.java index f8210c4aa15..dbf40292057 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/emissions/AirPollutionAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/emissions/AirPollutionAnalysis.java @@ -1,7 +1,18 @@ package org.matsim.application.analysis.emissions; +import it.unimi.dsi.fastutil.floats.FloatArrayList; +import it.unimi.dsi.fastutil.floats.FloatFloatPair; +import it.unimi.dsi.fastutil.floats.FloatList; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2DoubleLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2FloatMap; +import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; +import org.apache.avro.file.CodecFactory; +import org.apache.avro.file.DataFileWriter; +import org.apache.avro.io.DatumWriter; +import org.apache.avro.specific.SpecificDatumWriter; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.apache.logging.log4j.LogManager; @@ -14,6 +25,8 @@ import org.matsim.application.ApplicationUtils; import org.matsim.application.CommandSpec; import org.matsim.application.MATSimAppCommand; +import org.matsim.application.avro.AvroNetwork; +import org.matsim.application.avro.XYTData; import org.matsim.application.options.InputOptions; import org.matsim.application.options.OutputOptions; import org.matsim.application.options.SampleOptions; @@ -43,9 +56,7 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; @CommandLine.Command( name = "air-pollution", description = "General air pollution analysis.", @@ -53,10 +64,11 @@ ) @CommandSpec(requireRunDirectory = true, produces = { - "emissions_total.csv", "emissions_grid_per_day.csv", "emissions_per_link.csv", + "emissions_total.csv", "emissions_per_link.csv", "emissions_per_link_per_m.csv", - "emissions_grid_per_hour.csv", + "emissions_grid_per_hour.%s", "emissions_vehicle_info.csv", + "emissions_grid_per_day.%s" } ) public class AirPollutionAnalysis implements MATSimAppCommand { @@ -128,7 +140,9 @@ public void install() { writeTotal(filteredNetwork, emissionsEventHandler); writeRaster(filteredNetwork, config, emissionsEventHandler); + writeAvroRaster(filteredNetwork, config, emissionsEventHandler); + writeTimeDependentAvroRaster(filteredNetwork, config, emissionsEventHandler); writeTimeDependentRaster(filteredNetwork, config, emissionsEventHandler); return 0; @@ -241,6 +255,62 @@ private void writeTotal(Network network, EmissionsOnLinkEventHandler emissionsEv } } + /** + * Creates the data for the XY-Time plot. The time is fixed and the data is summarized over the run. + * Currently only the CO2_Total Values is printed because Simwrapper can handle only one value. + */ + private void writeAvroRaster(Network network, Config config, EmissionsOnLinkEventHandler emissionsEventHandler) { + + String crs = ProjectionUtils.getCRS(network); + if (crs == null) + crs = config.network().getInputCRS(); + if (crs == null) + crs = config.global().getCoordinateSystem(); + + XYTData avroData = new XYTData(); + avroData.setCrs(crs); + + Map rasterMap = FastEmissionGridAnalyzer.processHandlerEmissions(emissionsEventHandler.getLink2pollutants(), network, gridSize, 20); + List xLength = rasterMap.values().stream().map(Raster::getXLength).distinct().toList(); + List yLength = rasterMap.values().stream().map(Raster::getYLength).distinct().toList(); + Raster raster = rasterMap.values().stream().findFirst().orElseThrow(); + + List xCoords = new ArrayList<>(); + List yCoords = new ArrayList<>(); + Map> values = new HashMap<>(); + List valuesList = new ArrayList<>(); + List times = new ArrayList<>(); + + times.add(0); + + for (int xi = 0; xi < xLength.get(0); xi++) { + for (int yi = 0; yi < yLength.get(0); yi++) { + Coord coord = raster.getCoordForIndex(xi, yi); + double value = rasterMap.get(Pollutant.CO2_TOTAL).getValueByIndex(xi, yi); + if (xi == 0) yCoords.add((float) coord.getY()); + if (yi == 0) xCoords.add((float) coord.getX()); + valuesList.add((float) value); + } + } + + + values.put(String.valueOf(Pollutant.CO2_TOTAL), valuesList); + + avroData.setYCoords(yCoords); + avroData.setXCoords(xCoords); + avroData.setData(values); + avroData.setTimestamps(times); + + DatumWriter datumWriter = new SpecificDatumWriter<>(XYTData.class); + try (DataFileWriter dataFileWriter = new DataFileWriter<>(datumWriter)) { + dataFileWriter.setCodec(CodecFactory.deflateCodec(9)); + dataFileWriter.create(avroData.getSchema(), IOUtils.getOutputStream(IOUtils.getFileUrl(output.getPath("emissions_grid_per_day.%s", "avro").toString()), false)); + dataFileWriter.append(avroData); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + /** * Creates the data for the XY-Time plot. The time is fixed and the data is summarized over the run. * Currently only the CO2_Total Values is printed because Simwrapper can handle only one value. @@ -254,7 +324,7 @@ private void writeRaster(Network network, Config config, EmissionsOnLinkEventHan Raster raster = rasterMap.values().stream().findFirst().orElseThrow(); - try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath("emissions_grid_per_day.csv")), + try (CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(output.getPath("emissions_grid_per_day.%s", "csv")), CSVFormat.DEFAULT.builder().setCommentMarker('#').build())) { String crs = ProjectionUtils.getCRS(network); @@ -281,8 +351,8 @@ private void writeRaster(Network network, Config config, EmissionsOnLinkEventHan Coord coord = raster.getCoordForIndex(xi, yi); double value = rasterMap.get(Pollutant.CO2_TOTAL).getValueByIndex(xi, yi); -// if (value == 0) -// continue; + if (value == 0) + continue; printer.print(0.0); printer.print(coord.getX()); @@ -310,7 +380,7 @@ private void writeTimeDependentRaster(Network network, Config config, EmissionsO Raster raster = firstBin.values().stream().findFirst().orElseThrow(); - try (CSVPrinter printer = new CSVPrinter(IOUtils.getBufferedWriter(output.getPath("emissions_grid_per_hour.csv").toString()), + try (CSVPrinter printer = new CSVPrinter(IOUtils.getBufferedWriter(output.getPath("emissions_grid_per_hour.%s", "csv").toString()), CSVFormat.DEFAULT.builder().setCommentMarker('#').build())) { String crs = ProjectionUtils.getCRS(network); @@ -358,4 +428,65 @@ private void writeTimeDependentRaster(Network network, Config config, EmissionsO } + private void writeTimeDependentAvroRaster(Network network, Config config, EmissionsOnLinkEventHandler emissionsEventHandler) { + + TimeBinMap> timeBinMap = FastEmissionGridAnalyzer.processHandlerEmissionsPerTimeBin(emissionsEventHandler.getTimeBins(), network, gridSize, 20); + + String crs = ProjectionUtils.getCRS(network); + if (crs == null) + crs = config.network().getInputCRS(); + if (crs == null) + crs = config.global().getCoordinateSystem(); + + XYTData avroData = new XYTData(); + avroData.setCrs(crs); + + Map rasterMap = FastEmissionGridAnalyzer.processHandlerEmissions(emissionsEventHandler.getLink2pollutants(), network, gridSize, 20); + List xLength = rasterMap.values().stream().map(Raster::getXLength).distinct().toList(); + List yLength = rasterMap.values().stream().map(Raster::getYLength).distinct().toList(); + Raster raster = rasterMap.values().stream().findFirst().orElseThrow(); + + List xCoords = new ArrayList<>(); + List yCoords = new ArrayList<>(); + Map> values = new HashMap<>(); + List valuesList = new ArrayList<>(); + List times = new ArrayList<>(); + + for (TimeBinMap.TimeBin> timeBin : timeBinMap.getTimeBins()) { + + boolean isFirst = times.isEmpty(); + + times.add((int) timeBin.getStartTime()); + + for (int xi = 0; xi < xLength.get(0); xi++) { + for (int yi = 0; yi < yLength.get(0); yi++) { + Coord coord = raster.getCoordForIndex(xi, yi); + + if (xi == 0 && isFirst) + yCoords.add((float) coord.getY()); + if (yi == 0 && isFirst) + xCoords.add((float) coord.getX()); + + valuesList.add((float) timeBin.getValue().get(Pollutant.CO2_TOTAL).getValueByIndex(xi, yi)); + } + } + } + + values.put(String.valueOf(Pollutant.CO2_TOTAL), valuesList); + + avroData.setYCoords(yCoords); + avroData.setXCoords(xCoords); + avroData.setData(values); + avroData.setTimestamps(times); + + DatumWriter datumWriter = new SpecificDatumWriter<>(XYTData.class); + try (DataFileWriter dataFileWriter = new DataFileWriter<>(datumWriter)) { + dataFileWriter.setCodec(CodecFactory.deflateCodec(9)); + dataFileWriter.create(avroData.getSchema(), IOUtils.getOutputStream(IOUtils.getFileUrl(output.getPath("emissions_grid_per_hour.%s", "avro").toString()), false)); + dataFileWriter.append(avroData); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + } diff --git a/contribs/application/src/main/java/org/matsim/application/avro/AvroNetwork.java b/contribs/application/src/main/java/org/matsim/application/avro/AvroNetwork.java new file mode 100644 index 00000000000..7aaedf7bdec --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/avro/AvroNetwork.java @@ -0,0 +1,1847 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package org.matsim.application.avro; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class AvroNetwork extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = -6654515155450649691L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"AvroNetwork\",\"namespace\":\"org.matsim.application.avro\",\"fields\":[{\"name\":\"crs\",\"type\":\"string\",\"doc\":\"Coordinate reference system\"},{\"name\":\"nodeAttributes\",\"type\":{\"type\":\"array\",\"items\":\"string\"}},{\"name\":\"linkAttributes\",\"type\":{\"type\":\"array\",\"items\":\"string\"}},{\"name\":\"nodeId\",\"type\":{\"type\":\"array\",\"items\":\"string\"}},{\"name\":\"nodeCoordinates\",\"type\":{\"type\":\"array\",\"items\":\"float\"}},{\"name\":\"linkId\",\"type\":{\"type\":\"array\",\"items\":\"string\"}},{\"name\":\"from\",\"type\":{\"type\":\"array\",\"items\":\"int\"}},{\"name\":\"to\",\"type\":{\"type\":\"array\",\"items\":\"int\"}},{\"name\":\"modes\",\"type\":{\"type\":\"array\",\"items\":\"string\"}},{\"name\":\"length\",\"type\":{\"type\":\"array\",\"items\":\"float\"}},{\"name\":\"freespeed\",\"type\":{\"type\":\"array\",\"items\":\"float\"}},{\"name\":\"capacity\",\"type\":{\"type\":\"array\",\"items\":\"float\"}},{\"name\":\"permlanes\",\"type\":{\"type\":\"array\",\"items\":\"float\"}},{\"name\":\"allowedModes\",\"type\":{\"type\":\"array\",\"items\":\"int\"}}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder<>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder<>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this AvroNetwork to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a AvroNetwork from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a AvroNetwork instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static AvroNetwork fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + /** Coordinate reference system */ + private java.lang.CharSequence crs; + private java.util.List nodeAttributes; + private java.util.List linkAttributes; + private java.util.List nodeId; + private java.util.List nodeCoordinates; + private java.util.List linkId; + private java.util.List from; + private java.util.List to; + private java.util.List modes; + private java.util.List length; + private java.util.List freespeed; + private java.util.List capacity; + private java.util.List permlanes; + private java.util.List allowedModes; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public AvroNetwork() {} + + /** + * All-args constructor. + * @param crs Coordinate reference system + * @param nodeAttributes The new value for nodeAttributes + * @param linkAttributes The new value for linkAttributes + * @param nodeId The new value for nodeId + * @param nodeCoordinates The new value for nodeCoordinates + * @param linkId The new value for linkId + * @param from The new value for from + * @param to The new value for to + * @param modes The new value for modes + * @param length The new value for length + * @param freespeed The new value for freespeed + * @param capacity The new value for capacity + * @param permlanes The new value for permlanes + * @param allowedModes The new value for allowedModes + */ + public AvroNetwork(java.lang.CharSequence crs, java.util.List nodeAttributes, java.util.List linkAttributes, java.util.List nodeId, java.util.List nodeCoordinates, java.util.List linkId, java.util.List from, java.util.List to, java.util.List modes, java.util.List length, java.util.List freespeed, java.util.List capacity, java.util.List permlanes, java.util.List allowedModes) { + this.crs = crs; + this.nodeAttributes = nodeAttributes; + this.linkAttributes = linkAttributes; + this.nodeId = nodeId; + this.nodeCoordinates = nodeCoordinates; + this.linkId = linkId; + this.from = from; + this.to = to; + this.modes = modes; + this.length = length; + this.freespeed = freespeed; + this.capacity = capacity; + this.permlanes = permlanes; + this.allowedModes = allowedModes; + } + + @Override + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + + @Override + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + + // Used by DatumWriter. Applications should not call. + @Override + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return crs; + case 1: return nodeAttributes; + case 2: return linkAttributes; + case 3: return nodeId; + case 4: return nodeCoordinates; + case 5: return linkId; + case 6: return from; + case 7: return to; + case 8: return modes; + case 9: return length; + case 10: return freespeed; + case 11: return capacity; + case 12: return permlanes; + case 13: return allowedModes; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @Override + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: crs = (java.lang.CharSequence)value$; break; + case 1: nodeAttributes = (java.util.List)value$; break; + case 2: linkAttributes = (java.util.List)value$; break; + case 3: nodeId = (java.util.List)value$; break; + case 4: nodeCoordinates = (java.util.List)value$; break; + case 5: linkId = (java.util.List)value$; break; + case 6: from = (java.util.List)value$; break; + case 7: to = (java.util.List)value$; break; + case 8: modes = (java.util.List)value$; break; + case 9: length = (java.util.List)value$; break; + case 10: freespeed = (java.util.List)value$; break; + case 11: capacity = (java.util.List)value$; break; + case 12: permlanes = (java.util.List)value$; break; + case 13: allowedModes = (java.util.List)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'crs' field. + * @return Coordinate reference system + */ + public java.lang.CharSequence getCrs() { + return crs; + } + + + /** + * Sets the value of the 'crs' field. + * Coordinate reference system + * @param value the value to set. + */ + public void setCrs(java.lang.CharSequence value) { + this.crs = value; + } + + /** + * Gets the value of the 'nodeAttributes' field. + * @return The value of the 'nodeAttributes' field. + */ + public java.util.List getNodeAttributes() { + return nodeAttributes; + } + + + /** + * Sets the value of the 'nodeAttributes' field. + * @param value the value to set. + */ + public void setNodeAttributes(java.util.List value) { + this.nodeAttributes = value; + } + + /** + * Gets the value of the 'linkAttributes' field. + * @return The value of the 'linkAttributes' field. + */ + public java.util.List getLinkAttributes() { + return linkAttributes; + } + + + /** + * Sets the value of the 'linkAttributes' field. + * @param value the value to set. + */ + public void setLinkAttributes(java.util.List value) { + this.linkAttributes = value; + } + + /** + * Gets the value of the 'nodeId' field. + * @return The value of the 'nodeId' field. + */ + public java.util.List getNodeId() { + return nodeId; + } + + + /** + * Sets the value of the 'nodeId' field. + * @param value the value to set. + */ + public void setNodeId(java.util.List value) { + this.nodeId = value; + } + + /** + * Gets the value of the 'nodeCoordinates' field. + * @return The value of the 'nodeCoordinates' field. + */ + public java.util.List getNodeCoordinates() { + return nodeCoordinates; + } + + + /** + * Sets the value of the 'nodeCoordinates' field. + * @param value the value to set. + */ + public void setNodeCoordinates(java.util.List value) { + this.nodeCoordinates = value; + } + + /** + * Gets the value of the 'linkId' field. + * @return The value of the 'linkId' field. + */ + public java.util.List getLinkId() { + return linkId; + } + + + /** + * Sets the value of the 'linkId' field. + * @param value the value to set. + */ + public void setLinkId(java.util.List value) { + this.linkId = value; + } + + /** + * Gets the value of the 'from' field. + * @return The value of the 'from' field. + */ + public java.util.List getFrom() { + return from; + } + + + /** + * Sets the value of the 'from' field. + * @param value the value to set. + */ + public void setFrom(java.util.List value) { + this.from = value; + } + + /** + * Gets the value of the 'to' field. + * @return The value of the 'to' field. + */ + public java.util.List getTo() { + return to; + } + + + /** + * Sets the value of the 'to' field. + * @param value the value to set. + */ + public void setTo(java.util.List value) { + this.to = value; + } + + /** + * Gets the value of the 'modes' field. + * @return The value of the 'modes' field. + */ + public java.util.List getModes() { + return modes; + } + + + /** + * Sets the value of the 'modes' field. + * @param value the value to set. + */ + public void setModes(java.util.List value) { + this.modes = value; + } + + /** + * Gets the value of the 'length' field. + * @return The value of the 'length' field. + */ + public java.util.List getLength() { + return length; + } + + + /** + * Sets the value of the 'length' field. + * @param value the value to set. + */ + public void setLength(java.util.List value) { + this.length = value; + } + + /** + * Gets the value of the 'freespeed' field. + * @return The value of the 'freespeed' field. + */ + public java.util.List getFreespeed() { + return freespeed; + } + + + /** + * Sets the value of the 'freespeed' field. + * @param value the value to set. + */ + public void setFreespeed(java.util.List value) { + this.freespeed = value; + } + + /** + * Gets the value of the 'capacity' field. + * @return The value of the 'capacity' field. + */ + public java.util.List getCapacity() { + return capacity; + } + + + /** + * Sets the value of the 'capacity' field. + * @param value the value to set. + */ + public void setCapacity(java.util.List value) { + this.capacity = value; + } + + /** + * Gets the value of the 'permlanes' field. + * @return The value of the 'permlanes' field. + */ + public java.util.List getPermlanes() { + return permlanes; + } + + + /** + * Sets the value of the 'permlanes' field. + * @param value the value to set. + */ + public void setPermlanes(java.util.List value) { + this.permlanes = value; + } + + /** + * Gets the value of the 'allowedModes' field. + * @return The value of the 'allowedModes' field. + */ + public java.util.List getAllowedModes() { + return allowedModes; + } + + + /** + * Sets the value of the 'allowedModes' field. + * @param value the value to set. + */ + public void setAllowedModes(java.util.List value) { + this.allowedModes = value; + } + + /** + * Creates a new AvroNetwork RecordBuilder. + * @return A new AvroNetwork RecordBuilder + */ + public static org.matsim.application.avro.AvroNetwork.Builder newBuilder() { + return new org.matsim.application.avro.AvroNetwork.Builder(); + } + + /** + * Creates a new AvroNetwork RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new AvroNetwork RecordBuilder + */ + public static org.matsim.application.avro.AvroNetwork.Builder newBuilder(org.matsim.application.avro.AvroNetwork.Builder other) { + if (other == null) { + return new org.matsim.application.avro.AvroNetwork.Builder(); + } else { + return new org.matsim.application.avro.AvroNetwork.Builder(other); + } + } + + /** + * Creates a new AvroNetwork RecordBuilder by copying an existing AvroNetwork instance. + * @param other The existing instance to copy. + * @return A new AvroNetwork RecordBuilder + */ + public static org.matsim.application.avro.AvroNetwork.Builder newBuilder(org.matsim.application.avro.AvroNetwork other) { + if (other == null) { + return new org.matsim.application.avro.AvroNetwork.Builder(); + } else { + return new org.matsim.application.avro.AvroNetwork.Builder(other); + } + } + + /** + * RecordBuilder for AvroNetwork instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + /** Coordinate reference system */ + private java.lang.CharSequence crs; + private java.util.List nodeAttributes; + private java.util.List linkAttributes; + private java.util.List nodeId; + private java.util.List nodeCoordinates; + private java.util.List linkId; + private java.util.List from; + private java.util.List to; + private java.util.List modes; + private java.util.List length; + private java.util.List freespeed; + private java.util.List capacity; + private java.util.List permlanes; + private java.util.List allowedModes; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(org.matsim.application.avro.AvroNetwork.Builder other) { + super(other); + if (isValidValue(fields()[0], other.crs)) { + this.crs = data().deepCopy(fields()[0].schema(), other.crs); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.nodeAttributes)) { + this.nodeAttributes = data().deepCopy(fields()[1].schema(), other.nodeAttributes); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.linkAttributes)) { + this.linkAttributes = data().deepCopy(fields()[2].schema(), other.linkAttributes); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.nodeId)) { + this.nodeId = data().deepCopy(fields()[3].schema(), other.nodeId); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.nodeCoordinates)) { + this.nodeCoordinates = data().deepCopy(fields()[4].schema(), other.nodeCoordinates); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + if (isValidValue(fields()[5], other.linkId)) { + this.linkId = data().deepCopy(fields()[5].schema(), other.linkId); + fieldSetFlags()[5] = other.fieldSetFlags()[5]; + } + if (isValidValue(fields()[6], other.from)) { + this.from = data().deepCopy(fields()[6].schema(), other.from); + fieldSetFlags()[6] = other.fieldSetFlags()[6]; + } + if (isValidValue(fields()[7], other.to)) { + this.to = data().deepCopy(fields()[7].schema(), other.to); + fieldSetFlags()[7] = other.fieldSetFlags()[7]; + } + if (isValidValue(fields()[8], other.modes)) { + this.modes = data().deepCopy(fields()[8].schema(), other.modes); + fieldSetFlags()[8] = other.fieldSetFlags()[8]; + } + if (isValidValue(fields()[9], other.length)) { + this.length = data().deepCopy(fields()[9].schema(), other.length); + fieldSetFlags()[9] = other.fieldSetFlags()[9]; + } + if (isValidValue(fields()[10], other.freespeed)) { + this.freespeed = data().deepCopy(fields()[10].schema(), other.freespeed); + fieldSetFlags()[10] = other.fieldSetFlags()[10]; + } + if (isValidValue(fields()[11], other.capacity)) { + this.capacity = data().deepCopy(fields()[11].schema(), other.capacity); + fieldSetFlags()[11] = other.fieldSetFlags()[11]; + } + if (isValidValue(fields()[12], other.permlanes)) { + this.permlanes = data().deepCopy(fields()[12].schema(), other.permlanes); + fieldSetFlags()[12] = other.fieldSetFlags()[12]; + } + if (isValidValue(fields()[13], other.allowedModes)) { + this.allowedModes = data().deepCopy(fields()[13].schema(), other.allowedModes); + fieldSetFlags()[13] = other.fieldSetFlags()[13]; + } + } + + /** + * Creates a Builder by copying an existing AvroNetwork instance + * @param other The existing instance to copy. + */ + private Builder(org.matsim.application.avro.AvroNetwork other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.crs)) { + this.crs = data().deepCopy(fields()[0].schema(), other.crs); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.nodeAttributes)) { + this.nodeAttributes = data().deepCopy(fields()[1].schema(), other.nodeAttributes); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.linkAttributes)) { + this.linkAttributes = data().deepCopy(fields()[2].schema(), other.linkAttributes); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.nodeId)) { + this.nodeId = data().deepCopy(fields()[3].schema(), other.nodeId); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.nodeCoordinates)) { + this.nodeCoordinates = data().deepCopy(fields()[4].schema(), other.nodeCoordinates); + fieldSetFlags()[4] = true; + } + if (isValidValue(fields()[5], other.linkId)) { + this.linkId = data().deepCopy(fields()[5].schema(), other.linkId); + fieldSetFlags()[5] = true; + } + if (isValidValue(fields()[6], other.from)) { + this.from = data().deepCopy(fields()[6].schema(), other.from); + fieldSetFlags()[6] = true; + } + if (isValidValue(fields()[7], other.to)) { + this.to = data().deepCopy(fields()[7].schema(), other.to); + fieldSetFlags()[7] = true; + } + if (isValidValue(fields()[8], other.modes)) { + this.modes = data().deepCopy(fields()[8].schema(), other.modes); + fieldSetFlags()[8] = true; + } + if (isValidValue(fields()[9], other.length)) { + this.length = data().deepCopy(fields()[9].schema(), other.length); + fieldSetFlags()[9] = true; + } + if (isValidValue(fields()[10], other.freespeed)) { + this.freespeed = data().deepCopy(fields()[10].schema(), other.freespeed); + fieldSetFlags()[10] = true; + } + if (isValidValue(fields()[11], other.capacity)) { + this.capacity = data().deepCopy(fields()[11].schema(), other.capacity); + fieldSetFlags()[11] = true; + } + if (isValidValue(fields()[12], other.permlanes)) { + this.permlanes = data().deepCopy(fields()[12].schema(), other.permlanes); + fieldSetFlags()[12] = true; + } + if (isValidValue(fields()[13], other.allowedModes)) { + this.allowedModes = data().deepCopy(fields()[13].schema(), other.allowedModes); + fieldSetFlags()[13] = true; + } + } + + /** + * Gets the value of the 'crs' field. + * Coordinate reference system + * @return The value. + */ + public java.lang.CharSequence getCrs() { + return crs; + } + + + /** + * Sets the value of the 'crs' field. + * Coordinate reference system + * @param value The value of 'crs'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setCrs(java.lang.CharSequence value) { + validate(fields()[0], value); + this.crs = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'crs' field has been set. + * Coordinate reference system + * @return True if the 'crs' field has been set, false otherwise. + */ + public boolean hasCrs() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'crs' field. + * Coordinate reference system + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearCrs() { + crs = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'nodeAttributes' field. + * @return The value. + */ + public java.util.List getNodeAttributes() { + return nodeAttributes; + } + + + /** + * Sets the value of the 'nodeAttributes' field. + * @param value The value of 'nodeAttributes'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setNodeAttributes(java.util.List value) { + validate(fields()[1], value); + this.nodeAttributes = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'nodeAttributes' field has been set. + * @return True if the 'nodeAttributes' field has been set, false otherwise. + */ + public boolean hasNodeAttributes() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'nodeAttributes' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearNodeAttributes() { + nodeAttributes = null; + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'linkAttributes' field. + * @return The value. + */ + public java.util.List getLinkAttributes() { + return linkAttributes; + } + + + /** + * Sets the value of the 'linkAttributes' field. + * @param value The value of 'linkAttributes'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setLinkAttributes(java.util.List value) { + validate(fields()[2], value); + this.linkAttributes = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'linkAttributes' field has been set. + * @return True if the 'linkAttributes' field has been set, false otherwise. + */ + public boolean hasLinkAttributes() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'linkAttributes' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearLinkAttributes() { + linkAttributes = null; + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'nodeId' field. + * @return The value. + */ + public java.util.List getNodeId() { + return nodeId; + } + + + /** + * Sets the value of the 'nodeId' field. + * @param value The value of 'nodeId'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setNodeId(java.util.List value) { + validate(fields()[3], value); + this.nodeId = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'nodeId' field has been set. + * @return True if the 'nodeId' field has been set, false otherwise. + */ + public boolean hasNodeId() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'nodeId' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearNodeId() { + nodeId = null; + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'nodeCoordinates' field. + * @return The value. + */ + public java.util.List getNodeCoordinates() { + return nodeCoordinates; + } + + + /** + * Sets the value of the 'nodeCoordinates' field. + * @param value The value of 'nodeCoordinates'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setNodeCoordinates(java.util.List value) { + validate(fields()[4], value); + this.nodeCoordinates = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'nodeCoordinates' field has been set. + * @return True if the 'nodeCoordinates' field has been set, false otherwise. + */ + public boolean hasNodeCoordinates() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'nodeCoordinates' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearNodeCoordinates() { + nodeCoordinates = null; + fieldSetFlags()[4] = false; + return this; + } + + /** + * Gets the value of the 'linkId' field. + * @return The value. + */ + public java.util.List getLinkId() { + return linkId; + } + + + /** + * Sets the value of the 'linkId' field. + * @param value The value of 'linkId'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setLinkId(java.util.List value) { + validate(fields()[5], value); + this.linkId = value; + fieldSetFlags()[5] = true; + return this; + } + + /** + * Checks whether the 'linkId' field has been set. + * @return True if the 'linkId' field has been set, false otherwise. + */ + public boolean hasLinkId() { + return fieldSetFlags()[5]; + } + + + /** + * Clears the value of the 'linkId' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearLinkId() { + linkId = null; + fieldSetFlags()[5] = false; + return this; + } + + /** + * Gets the value of the 'from' field. + * @return The value. + */ + public java.util.List getFrom() { + return from; + } + + + /** + * Sets the value of the 'from' field. + * @param value The value of 'from'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setFrom(java.util.List value) { + validate(fields()[6], value); + this.from = value; + fieldSetFlags()[6] = true; + return this; + } + + /** + * Checks whether the 'from' field has been set. + * @return True if the 'from' field has been set, false otherwise. + */ + public boolean hasFrom() { + return fieldSetFlags()[6]; + } + + + /** + * Clears the value of the 'from' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearFrom() { + from = null; + fieldSetFlags()[6] = false; + return this; + } + + /** + * Gets the value of the 'to' field. + * @return The value. + */ + public java.util.List getTo() { + return to; + } + + + /** + * Sets the value of the 'to' field. + * @param value The value of 'to'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setTo(java.util.List value) { + validate(fields()[7], value); + this.to = value; + fieldSetFlags()[7] = true; + return this; + } + + /** + * Checks whether the 'to' field has been set. + * @return True if the 'to' field has been set, false otherwise. + */ + public boolean hasTo() { + return fieldSetFlags()[7]; + } + + + /** + * Clears the value of the 'to' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearTo() { + to = null; + fieldSetFlags()[7] = false; + return this; + } + + /** + * Gets the value of the 'modes' field. + * @return The value. + */ + public java.util.List getModes() { + return modes; + } + + + /** + * Sets the value of the 'modes' field. + * @param value The value of 'modes'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setModes(java.util.List value) { + validate(fields()[8], value); + this.modes = value; + fieldSetFlags()[8] = true; + return this; + } + + /** + * Checks whether the 'modes' field has been set. + * @return True if the 'modes' field has been set, false otherwise. + */ + public boolean hasModes() { + return fieldSetFlags()[8]; + } + + + /** + * Clears the value of the 'modes' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearModes() { + modes = null; + fieldSetFlags()[8] = false; + return this; + } + + /** + * Gets the value of the 'length' field. + * @return The value. + */ + public java.util.List getLength() { + return length; + } + + + /** + * Sets the value of the 'length' field. + * @param value The value of 'length'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setLength(java.util.List value) { + validate(fields()[9], value); + this.length = value; + fieldSetFlags()[9] = true; + return this; + } + + /** + * Checks whether the 'length' field has been set. + * @return True if the 'length' field has been set, false otherwise. + */ + public boolean hasLength() { + return fieldSetFlags()[9]; + } + + + /** + * Clears the value of the 'length' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearLength() { + length = null; + fieldSetFlags()[9] = false; + return this; + } + + /** + * Gets the value of the 'freespeed' field. + * @return The value. + */ + public java.util.List getFreespeed() { + return freespeed; + } + + + /** + * Sets the value of the 'freespeed' field. + * @param value The value of 'freespeed'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setFreespeed(java.util.List value) { + validate(fields()[10], value); + this.freespeed = value; + fieldSetFlags()[10] = true; + return this; + } + + /** + * Checks whether the 'freespeed' field has been set. + * @return True if the 'freespeed' field has been set, false otherwise. + */ + public boolean hasFreespeed() { + return fieldSetFlags()[10]; + } + + + /** + * Clears the value of the 'freespeed' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearFreespeed() { + freespeed = null; + fieldSetFlags()[10] = false; + return this; + } + + /** + * Gets the value of the 'capacity' field. + * @return The value. + */ + public java.util.List getCapacity() { + return capacity; + } + + + /** + * Sets the value of the 'capacity' field. + * @param value The value of 'capacity'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setCapacity(java.util.List value) { + validate(fields()[11], value); + this.capacity = value; + fieldSetFlags()[11] = true; + return this; + } + + /** + * Checks whether the 'capacity' field has been set. + * @return True if the 'capacity' field has been set, false otherwise. + */ + public boolean hasCapacity() { + return fieldSetFlags()[11]; + } + + + /** + * Clears the value of the 'capacity' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearCapacity() { + capacity = null; + fieldSetFlags()[11] = false; + return this; + } + + /** + * Gets the value of the 'permlanes' field. + * @return The value. + */ + public java.util.List getPermlanes() { + return permlanes; + } + + + /** + * Sets the value of the 'permlanes' field. + * @param value The value of 'permlanes'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setPermlanes(java.util.List value) { + validate(fields()[12], value); + this.permlanes = value; + fieldSetFlags()[12] = true; + return this; + } + + /** + * Checks whether the 'permlanes' field has been set. + * @return True if the 'permlanes' field has been set, false otherwise. + */ + public boolean hasPermlanes() { + return fieldSetFlags()[12]; + } + + + /** + * Clears the value of the 'permlanes' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearPermlanes() { + permlanes = null; + fieldSetFlags()[12] = false; + return this; + } + + /** + * Gets the value of the 'allowedModes' field. + * @return The value. + */ + public java.util.List getAllowedModes() { + return allowedModes; + } + + + /** + * Sets the value of the 'allowedModes' field. + * @param value The value of 'allowedModes'. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder setAllowedModes(java.util.List value) { + validate(fields()[13], value); + this.allowedModes = value; + fieldSetFlags()[13] = true; + return this; + } + + /** + * Checks whether the 'allowedModes' field has been set. + * @return True if the 'allowedModes' field has been set, false otherwise. + */ + public boolean hasAllowedModes() { + return fieldSetFlags()[13]; + } + + + /** + * Clears the value of the 'allowedModes' field. + * @return This builder. + */ + public org.matsim.application.avro.AvroNetwork.Builder clearAllowedModes() { + allowedModes = null; + fieldSetFlags()[13] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public AvroNetwork build() { + try { + AvroNetwork record = new AvroNetwork(); + record.crs = fieldSetFlags()[0] ? this.crs : (java.lang.CharSequence) defaultValue(fields()[0]); + record.nodeAttributes = fieldSetFlags()[1] ? this.nodeAttributes : (java.util.List) defaultValue(fields()[1]); + record.linkAttributes = fieldSetFlags()[2] ? this.linkAttributes : (java.util.List) defaultValue(fields()[2]); + record.nodeId = fieldSetFlags()[3] ? this.nodeId : (java.util.List) defaultValue(fields()[3]); + record.nodeCoordinates = fieldSetFlags()[4] ? this.nodeCoordinates : (java.util.List) defaultValue(fields()[4]); + record.linkId = fieldSetFlags()[5] ? this.linkId : (java.util.List) defaultValue(fields()[5]); + record.from = fieldSetFlags()[6] ? this.from : (java.util.List) defaultValue(fields()[6]); + record.to = fieldSetFlags()[7] ? this.to : (java.util.List) defaultValue(fields()[7]); + record.modes = fieldSetFlags()[8] ? this.modes : (java.util.List) defaultValue(fields()[8]); + record.length = fieldSetFlags()[9] ? this.length : (java.util.List) defaultValue(fields()[9]); + record.freespeed = fieldSetFlags()[10] ? this.freespeed : (java.util.List) defaultValue(fields()[10]); + record.capacity = fieldSetFlags()[11] ? this.capacity : (java.util.List) defaultValue(fields()[11]); + record.permlanes = fieldSetFlags()[12] ? this.permlanes : (java.util.List) defaultValue(fields()[12]); + record.allowedModes = fieldSetFlags()[13] ? this.allowedModes : (java.util.List) defaultValue(fields()[13]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.crs); + + long size0 = this.nodeAttributes.size(); + out.writeArrayStart(); + out.setItemCount(size0); + long actualSize0 = 0; + for (java.lang.CharSequence e0: this.nodeAttributes) { + actualSize0++; + out.startItem(); + out.writeString(e0); + } + out.writeArrayEnd(); + if (actualSize0 != size0) + throw new java.util.ConcurrentModificationException("Array-size written was " + size0 + ", but element count was " + actualSize0 + "."); + + long size1 = this.linkAttributes.size(); + out.writeArrayStart(); + out.setItemCount(size1); + long actualSize1 = 0; + for (java.lang.CharSequence e1: this.linkAttributes) { + actualSize1++; + out.startItem(); + out.writeString(e1); + } + out.writeArrayEnd(); + if (actualSize1 != size1) + throw new java.util.ConcurrentModificationException("Array-size written was " + size1 + ", but element count was " + actualSize1 + "."); + + long size2 = this.nodeId.size(); + out.writeArrayStart(); + out.setItemCount(size2); + long actualSize2 = 0; + for (java.lang.CharSequence e2: this.nodeId) { + actualSize2++; + out.startItem(); + out.writeString(e2); + } + out.writeArrayEnd(); + if (actualSize2 != size2) + throw new java.util.ConcurrentModificationException("Array-size written was " + size2 + ", but element count was " + actualSize2 + "."); + + long size3 = this.nodeCoordinates.size(); + out.writeArrayStart(); + out.setItemCount(size3); + long actualSize3 = 0; + for (java.lang.Float e3: this.nodeCoordinates) { + actualSize3++; + out.startItem(); + out.writeFloat(e3); + } + out.writeArrayEnd(); + if (actualSize3 != size3) + throw new java.util.ConcurrentModificationException("Array-size written was " + size3 + ", but element count was " + actualSize3 + "."); + + long size4 = this.linkId.size(); + out.writeArrayStart(); + out.setItemCount(size4); + long actualSize4 = 0; + for (java.lang.CharSequence e4: this.linkId) { + actualSize4++; + out.startItem(); + out.writeString(e4); + } + out.writeArrayEnd(); + if (actualSize4 != size4) + throw new java.util.ConcurrentModificationException("Array-size written was " + size4 + ", but element count was " + actualSize4 + "."); + + long size5 = this.from.size(); + out.writeArrayStart(); + out.setItemCount(size5); + long actualSize5 = 0; + for (java.lang.Integer e5: this.from) { + actualSize5++; + out.startItem(); + out.writeInt(e5); + } + out.writeArrayEnd(); + if (actualSize5 != size5) + throw new java.util.ConcurrentModificationException("Array-size written was " + size5 + ", but element count was " + actualSize5 + "."); + + long size6 = this.to.size(); + out.writeArrayStart(); + out.setItemCount(size6); + long actualSize6 = 0; + for (java.lang.Integer e6: this.to) { + actualSize6++; + out.startItem(); + out.writeInt(e6); + } + out.writeArrayEnd(); + if (actualSize6 != size6) + throw new java.util.ConcurrentModificationException("Array-size written was " + size6 + ", but element count was " + actualSize6 + "."); + + long size7 = this.modes.size(); + out.writeArrayStart(); + out.setItemCount(size7); + long actualSize7 = 0; + for (java.lang.CharSequence e7: this.modes) { + actualSize7++; + out.startItem(); + out.writeString(e7); + } + out.writeArrayEnd(); + if (actualSize7 != size7) + throw new java.util.ConcurrentModificationException("Array-size written was " + size7 + ", but element count was " + actualSize7 + "."); + + long size8 = this.length.size(); + out.writeArrayStart(); + out.setItemCount(size8); + long actualSize8 = 0; + for (java.lang.Float e8: this.length) { + actualSize8++; + out.startItem(); + out.writeFloat(e8); + } + out.writeArrayEnd(); + if (actualSize8 != size8) + throw new java.util.ConcurrentModificationException("Array-size written was " + size8 + ", but element count was " + actualSize8 + "."); + + long size9 = this.freespeed.size(); + out.writeArrayStart(); + out.setItemCount(size9); + long actualSize9 = 0; + for (java.lang.Float e9: this.freespeed) { + actualSize9++; + out.startItem(); + out.writeFloat(e9); + } + out.writeArrayEnd(); + if (actualSize9 != size9) + throw new java.util.ConcurrentModificationException("Array-size written was " + size9 + ", but element count was " + actualSize9 + "."); + + long size10 = this.capacity.size(); + out.writeArrayStart(); + out.setItemCount(size10); + long actualSize10 = 0; + for (java.lang.Float e10: this.capacity) { + actualSize10++; + out.startItem(); + out.writeFloat(e10); + } + out.writeArrayEnd(); + if (actualSize10 != size10) + throw new java.util.ConcurrentModificationException("Array-size written was " + size10 + ", but element count was " + actualSize10 + "."); + + long size11 = this.permlanes.size(); + out.writeArrayStart(); + out.setItemCount(size11); + long actualSize11 = 0; + for (java.lang.Float e11: this.permlanes) { + actualSize11++; + out.startItem(); + out.writeFloat(e11); + } + out.writeArrayEnd(); + if (actualSize11 != size11) + throw new java.util.ConcurrentModificationException("Array-size written was " + size11 + ", but element count was " + actualSize11 + "."); + + long size12 = this.allowedModes.size(); + out.writeArrayStart(); + out.setItemCount(size12); + long actualSize12 = 0; + for (java.lang.Integer e12: this.allowedModes) { + actualSize12++; + out.startItem(); + out.writeInt(e12); + } + out.writeArrayEnd(); + if (actualSize12 != size12) + throw new java.util.ConcurrentModificationException("Array-size written was " + size12 + ", but element count was " + actualSize12 + "."); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.crs = in.readString(this.crs instanceof Utf8 ? (Utf8)this.crs : null); + + long size0 = in.readArrayStart(); + java.util.List a0 = this.nodeAttributes; + if (a0 == null) { + a0 = new SpecificData.Array((int)size0, SCHEMA$.getField("nodeAttributes").schema()); + this.nodeAttributes = a0; + } else a0.clear(); + SpecificData.Array ga0 = (a0 instanceof SpecificData.Array ? (SpecificData.Array)a0 : null); + for ( ; 0 < size0; size0 = in.arrayNext()) { + for ( ; size0 != 0; size0--) { + java.lang.CharSequence e0 = (ga0 != null ? ga0.peek() : null); + e0 = in.readString(e0 instanceof Utf8 ? (Utf8)e0 : null); + a0.add(e0); + } + } + + long size1 = in.readArrayStart(); + java.util.List a1 = this.linkAttributes; + if (a1 == null) { + a1 = new SpecificData.Array((int)size1, SCHEMA$.getField("linkAttributes").schema()); + this.linkAttributes = a1; + } else a1.clear(); + SpecificData.Array ga1 = (a1 instanceof SpecificData.Array ? (SpecificData.Array)a1 : null); + for ( ; 0 < size1; size1 = in.arrayNext()) { + for ( ; size1 != 0; size1--) { + java.lang.CharSequence e1 = (ga1 != null ? ga1.peek() : null); + e1 = in.readString(e1 instanceof Utf8 ? (Utf8)e1 : null); + a1.add(e1); + } + } + + long size2 = in.readArrayStart(); + java.util.List a2 = this.nodeId; + if (a2 == null) { + a2 = new SpecificData.Array((int)size2, SCHEMA$.getField("nodeId").schema()); + this.nodeId = a2; + } else a2.clear(); + SpecificData.Array ga2 = (a2 instanceof SpecificData.Array ? (SpecificData.Array)a2 : null); + for ( ; 0 < size2; size2 = in.arrayNext()) { + for ( ; size2 != 0; size2--) { + java.lang.CharSequence e2 = (ga2 != null ? ga2.peek() : null); + e2 = in.readString(e2 instanceof Utf8 ? (Utf8)e2 : null); + a2.add(e2); + } + } + + long size3 = in.readArrayStart(); + java.util.List a3 = this.nodeCoordinates; + if (a3 == null) { + a3 = new SpecificData.Array((int)size3, SCHEMA$.getField("nodeCoordinates").schema()); + this.nodeCoordinates = a3; + } else a3.clear(); + SpecificData.Array ga3 = (a3 instanceof SpecificData.Array ? (SpecificData.Array)a3 : null); + for ( ; 0 < size3; size3 = in.arrayNext()) { + for ( ; size3 != 0; size3--) { + java.lang.Float e3 = (ga3 != null ? ga3.peek() : null); + e3 = in.readFloat(); + a3.add(e3); + } + } + + long size4 = in.readArrayStart(); + java.util.List a4 = this.linkId; + if (a4 == null) { + a4 = new SpecificData.Array((int)size4, SCHEMA$.getField("linkId").schema()); + this.linkId = a4; + } else a4.clear(); + SpecificData.Array ga4 = (a4 instanceof SpecificData.Array ? (SpecificData.Array)a4 : null); + for ( ; 0 < size4; size4 = in.arrayNext()) { + for ( ; size4 != 0; size4--) { + java.lang.CharSequence e4 = (ga4 != null ? ga4.peek() : null); + e4 = in.readString(e4 instanceof Utf8 ? (Utf8)e4 : null); + a4.add(e4); + } + } + + long size5 = in.readArrayStart(); + java.util.List a5 = this.from; + if (a5 == null) { + a5 = new SpecificData.Array((int)size5, SCHEMA$.getField("from").schema()); + this.from = a5; + } else a5.clear(); + SpecificData.Array ga5 = (a5 instanceof SpecificData.Array ? (SpecificData.Array)a5 : null); + for ( ; 0 < size5; size5 = in.arrayNext()) { + for ( ; size5 != 0; size5--) { + java.lang.Integer e5 = (ga5 != null ? ga5.peek() : null); + e5 = in.readInt(); + a5.add(e5); + } + } + + long size6 = in.readArrayStart(); + java.util.List a6 = this.to; + if (a6 == null) { + a6 = new SpecificData.Array((int)size6, SCHEMA$.getField("to").schema()); + this.to = a6; + } else a6.clear(); + SpecificData.Array ga6 = (a6 instanceof SpecificData.Array ? (SpecificData.Array)a6 : null); + for ( ; 0 < size6; size6 = in.arrayNext()) { + for ( ; size6 != 0; size6--) { + java.lang.Integer e6 = (ga6 != null ? ga6.peek() : null); + e6 = in.readInt(); + a6.add(e6); + } + } + + long size7 = in.readArrayStart(); + java.util.List a7 = this.modes; + if (a7 == null) { + a7 = new SpecificData.Array((int)size7, SCHEMA$.getField("modes").schema()); + this.modes = a7; + } else a7.clear(); + SpecificData.Array ga7 = (a7 instanceof SpecificData.Array ? (SpecificData.Array)a7 : null); + for ( ; 0 < size7; size7 = in.arrayNext()) { + for ( ; size7 != 0; size7--) { + java.lang.CharSequence e7 = (ga7 != null ? ga7.peek() : null); + e7 = in.readString(e7 instanceof Utf8 ? (Utf8)e7 : null); + a7.add(e7); + } + } + + long size8 = in.readArrayStart(); + java.util.List a8 = this.length; + if (a8 == null) { + a8 = new SpecificData.Array((int)size8, SCHEMA$.getField("length").schema()); + this.length = a8; + } else a8.clear(); + SpecificData.Array ga8 = (a8 instanceof SpecificData.Array ? (SpecificData.Array)a8 : null); + for ( ; 0 < size8; size8 = in.arrayNext()) { + for ( ; size8 != 0; size8--) { + java.lang.Float e8 = (ga8 != null ? ga8.peek() : null); + e8 = in.readFloat(); + a8.add(e8); + } + } + + long size9 = in.readArrayStart(); + java.util.List a9 = this.freespeed; + if (a9 == null) { + a9 = new SpecificData.Array((int)size9, SCHEMA$.getField("freespeed").schema()); + this.freespeed = a9; + } else a9.clear(); + SpecificData.Array ga9 = (a9 instanceof SpecificData.Array ? (SpecificData.Array)a9 : null); + for ( ; 0 < size9; size9 = in.arrayNext()) { + for ( ; size9 != 0; size9--) { + java.lang.Float e9 = (ga9 != null ? ga9.peek() : null); + e9 = in.readFloat(); + a9.add(e9); + } + } + + long size10 = in.readArrayStart(); + java.util.List a10 = this.capacity; + if (a10 == null) { + a10 = new SpecificData.Array((int)size10, SCHEMA$.getField("capacity").schema()); + this.capacity = a10; + } else a10.clear(); + SpecificData.Array ga10 = (a10 instanceof SpecificData.Array ? (SpecificData.Array)a10 : null); + for ( ; 0 < size10; size10 = in.arrayNext()) { + for ( ; size10 != 0; size10--) { + java.lang.Float e10 = (ga10 != null ? ga10.peek() : null); + e10 = in.readFloat(); + a10.add(e10); + } + } + + long size11 = in.readArrayStart(); + java.util.List a11 = this.permlanes; + if (a11 == null) { + a11 = new SpecificData.Array((int)size11, SCHEMA$.getField("permlanes").schema()); + this.permlanes = a11; + } else a11.clear(); + SpecificData.Array ga11 = (a11 instanceof SpecificData.Array ? (SpecificData.Array)a11 : null); + for ( ; 0 < size11; size11 = in.arrayNext()) { + for ( ; size11 != 0; size11--) { + java.lang.Float e11 = (ga11 != null ? ga11.peek() : null); + e11 = in.readFloat(); + a11.add(e11); + } + } + + long size12 = in.readArrayStart(); + java.util.List a12 = this.allowedModes; + if (a12 == null) { + a12 = new SpecificData.Array((int)size12, SCHEMA$.getField("allowedModes").schema()); + this.allowedModes = a12; + } else a12.clear(); + SpecificData.Array ga12 = (a12 instanceof SpecificData.Array ? (SpecificData.Array)a12 : null); + for ( ; 0 < size12; size12 = in.arrayNext()) { + for ( ; size12 != 0; size12--) { + java.lang.Integer e12 = (ga12 != null ? ga12.peek() : null); + e12 = in.readInt(); + a12.add(e12); + } + } + + } else { + for (int i = 0; i < 14; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.crs = in.readString(this.crs instanceof Utf8 ? (Utf8)this.crs : null); + break; + + case 1: + long size0 = in.readArrayStart(); + java.util.List a0 = this.nodeAttributes; + if (a0 == null) { + a0 = new SpecificData.Array((int)size0, SCHEMA$.getField("nodeAttributes").schema()); + this.nodeAttributes = a0; + } else a0.clear(); + SpecificData.Array ga0 = (a0 instanceof SpecificData.Array ? (SpecificData.Array)a0 : null); + for ( ; 0 < size0; size0 = in.arrayNext()) { + for ( ; size0 != 0; size0--) { + java.lang.CharSequence e0 = (ga0 != null ? ga0.peek() : null); + e0 = in.readString(e0 instanceof Utf8 ? (Utf8)e0 : null); + a0.add(e0); + } + } + break; + + case 2: + long size1 = in.readArrayStart(); + java.util.List a1 = this.linkAttributes; + if (a1 == null) { + a1 = new SpecificData.Array((int)size1, SCHEMA$.getField("linkAttributes").schema()); + this.linkAttributes = a1; + } else a1.clear(); + SpecificData.Array ga1 = (a1 instanceof SpecificData.Array ? (SpecificData.Array)a1 : null); + for ( ; 0 < size1; size1 = in.arrayNext()) { + for ( ; size1 != 0; size1--) { + java.lang.CharSequence e1 = (ga1 != null ? ga1.peek() : null); + e1 = in.readString(e1 instanceof Utf8 ? (Utf8)e1 : null); + a1.add(e1); + } + } + break; + + case 3: + long size2 = in.readArrayStart(); + java.util.List a2 = this.nodeId; + if (a2 == null) { + a2 = new SpecificData.Array((int)size2, SCHEMA$.getField("nodeId").schema()); + this.nodeId = a2; + } else a2.clear(); + SpecificData.Array ga2 = (a2 instanceof SpecificData.Array ? (SpecificData.Array)a2 : null); + for ( ; 0 < size2; size2 = in.arrayNext()) { + for ( ; size2 != 0; size2--) { + java.lang.CharSequence e2 = (ga2 != null ? ga2.peek() : null); + e2 = in.readString(e2 instanceof Utf8 ? (Utf8)e2 : null); + a2.add(e2); + } + } + break; + + case 4: + long size3 = in.readArrayStart(); + java.util.List a3 = this.nodeCoordinates; + if (a3 == null) { + a3 = new SpecificData.Array((int)size3, SCHEMA$.getField("nodeCoordinates").schema()); + this.nodeCoordinates = a3; + } else a3.clear(); + SpecificData.Array ga3 = (a3 instanceof SpecificData.Array ? (SpecificData.Array)a3 : null); + for ( ; 0 < size3; size3 = in.arrayNext()) { + for ( ; size3 != 0; size3--) { + java.lang.Float e3 = (ga3 != null ? ga3.peek() : null); + e3 = in.readFloat(); + a3.add(e3); + } + } + break; + + case 5: + long size4 = in.readArrayStart(); + java.util.List a4 = this.linkId; + if (a4 == null) { + a4 = new SpecificData.Array((int)size4, SCHEMA$.getField("linkId").schema()); + this.linkId = a4; + } else a4.clear(); + SpecificData.Array ga4 = (a4 instanceof SpecificData.Array ? (SpecificData.Array)a4 : null); + for ( ; 0 < size4; size4 = in.arrayNext()) { + for ( ; size4 != 0; size4--) { + java.lang.CharSequence e4 = (ga4 != null ? ga4.peek() : null); + e4 = in.readString(e4 instanceof Utf8 ? (Utf8)e4 : null); + a4.add(e4); + } + } + break; + + case 6: + long size5 = in.readArrayStart(); + java.util.List a5 = this.from; + if (a5 == null) { + a5 = new SpecificData.Array((int)size5, SCHEMA$.getField("from").schema()); + this.from = a5; + } else a5.clear(); + SpecificData.Array ga5 = (a5 instanceof SpecificData.Array ? (SpecificData.Array)a5 : null); + for ( ; 0 < size5; size5 = in.arrayNext()) { + for ( ; size5 != 0; size5--) { + java.lang.Integer e5 = (ga5 != null ? ga5.peek() : null); + e5 = in.readInt(); + a5.add(e5); + } + } + break; + + case 7: + long size6 = in.readArrayStart(); + java.util.List a6 = this.to; + if (a6 == null) { + a6 = new SpecificData.Array((int)size6, SCHEMA$.getField("to").schema()); + this.to = a6; + } else a6.clear(); + SpecificData.Array ga6 = (a6 instanceof SpecificData.Array ? (SpecificData.Array)a6 : null); + for ( ; 0 < size6; size6 = in.arrayNext()) { + for ( ; size6 != 0; size6--) { + java.lang.Integer e6 = (ga6 != null ? ga6.peek() : null); + e6 = in.readInt(); + a6.add(e6); + } + } + break; + + case 8: + long size7 = in.readArrayStart(); + java.util.List a7 = this.modes; + if (a7 == null) { + a7 = new SpecificData.Array((int)size7, SCHEMA$.getField("modes").schema()); + this.modes = a7; + } else a7.clear(); + SpecificData.Array ga7 = (a7 instanceof SpecificData.Array ? (SpecificData.Array)a7 : null); + for ( ; 0 < size7; size7 = in.arrayNext()) { + for ( ; size7 != 0; size7--) { + java.lang.CharSequence e7 = (ga7 != null ? ga7.peek() : null); + e7 = in.readString(e7 instanceof Utf8 ? (Utf8)e7 : null); + a7.add(e7); + } + } + break; + + case 9: + long size8 = in.readArrayStart(); + java.util.List a8 = this.length; + if (a8 == null) { + a8 = new SpecificData.Array((int)size8, SCHEMA$.getField("length").schema()); + this.length = a8; + } else a8.clear(); + SpecificData.Array ga8 = (a8 instanceof SpecificData.Array ? (SpecificData.Array)a8 : null); + for ( ; 0 < size8; size8 = in.arrayNext()) { + for ( ; size8 != 0; size8--) { + java.lang.Float e8 = (ga8 != null ? ga8.peek() : null); + e8 = in.readFloat(); + a8.add(e8); + } + } + break; + + case 10: + long size9 = in.readArrayStart(); + java.util.List a9 = this.freespeed; + if (a9 == null) { + a9 = new SpecificData.Array((int)size9, SCHEMA$.getField("freespeed").schema()); + this.freespeed = a9; + } else a9.clear(); + SpecificData.Array ga9 = (a9 instanceof SpecificData.Array ? (SpecificData.Array)a9 : null); + for ( ; 0 < size9; size9 = in.arrayNext()) { + for ( ; size9 != 0; size9--) { + java.lang.Float e9 = (ga9 != null ? ga9.peek() : null); + e9 = in.readFloat(); + a9.add(e9); + } + } + break; + + case 11: + long size10 = in.readArrayStart(); + java.util.List a10 = this.capacity; + if (a10 == null) { + a10 = new SpecificData.Array((int)size10, SCHEMA$.getField("capacity").schema()); + this.capacity = a10; + } else a10.clear(); + SpecificData.Array ga10 = (a10 instanceof SpecificData.Array ? (SpecificData.Array)a10 : null); + for ( ; 0 < size10; size10 = in.arrayNext()) { + for ( ; size10 != 0; size10--) { + java.lang.Float e10 = (ga10 != null ? ga10.peek() : null); + e10 = in.readFloat(); + a10.add(e10); + } + } + break; + + case 12: + long size11 = in.readArrayStart(); + java.util.List a11 = this.permlanes; + if (a11 == null) { + a11 = new SpecificData.Array((int)size11, SCHEMA$.getField("permlanes").schema()); + this.permlanes = a11; + } else a11.clear(); + SpecificData.Array ga11 = (a11 instanceof SpecificData.Array ? (SpecificData.Array)a11 : null); + for ( ; 0 < size11; size11 = in.arrayNext()) { + for ( ; size11 != 0; size11--) { + java.lang.Float e11 = (ga11 != null ? ga11.peek() : null); + e11 = in.readFloat(); + a11.add(e11); + } + } + break; + + case 13: + long size12 = in.readArrayStart(); + java.util.List a12 = this.allowedModes; + if (a12 == null) { + a12 = new SpecificData.Array((int)size12, SCHEMA$.getField("allowedModes").schema()); + this.allowedModes = a12; + } else a12.clear(); + SpecificData.Array ga12 = (a12 instanceof SpecificData.Array ? (SpecificData.Array)a12 : null); + for ( ; 0 < size12; size12 = in.arrayNext()) { + for ( ; size12 != 0; size12--) { + java.lang.Integer e12 = (ga12 != null ? ga12.peek() : null); + e12 = in.readInt(); + a12.add(e12); + } + } + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateAvroNetwork.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateAvroNetwork.java new file mode 100644 index 00000000000..c94b17f9335 --- /dev/null +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateAvroNetwork.java @@ -0,0 +1,351 @@ +package org.matsim.application.prepare.network; + +import com.google.common.collect.Iterables; +import it.unimi.dsi.fastutil.floats.FloatArrayList; +import it.unimi.dsi.fastutil.floats.FloatList; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import org.apache.avro.Schema; +import org.apache.avro.file.CodecFactory; +import org.apache.avro.file.DataFileWriter; +import org.apache.avro.generic.GenericData; +import org.apache.avro.generic.GenericDatumWriter; +import org.apache.commons.lang3.mutable.MutableObject; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.application.CommandSpec; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.avro.AvroNetwork; +import org.matsim.application.options.CrsOptions; +import org.matsim.application.options.InputOptions; +import org.matsim.application.options.OutputOptions; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.scenario.ProjectionUtils; +import org.matsim.core.utils.geometry.CoordinateTransformation; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.matsim.core.utils.geometry.transformations.TransformationFactory; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.utils.objectattributes.attributable.Attributable; +import org.matsim.utils.objectattributes.attributable.Attributes; +import picocli.CommandLine; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + + +@CommandLine.Command(name = "network-avro", description = "Create avro representation of a network.") +@CommandSpec(requireNetwork = true, produces = "network.avro") +public class CreateAvroNetwork implements MATSimAppCommand { + + private static final Set FIELD_RESERVED = Set.of("name", "type", "doc", "default", "aliases"); + + @CommandLine.Mixin + private InputOptions input = InputOptions.ofCommand(CreateAvroNetwork.class); + @CommandLine.Mixin + private OutputOptions output = OutputOptions.ofCommand(CreateAvroNetwork.class); + @CommandLine.Mixin + private ShpOptions shp; + @CommandLine.Mixin + private CrsOptions crs = new CrsOptions(null, "EPSG:4326"); + + @CommandLine.Option(names = "--match-id", description = "Pattern to filter links by id") + private String matchId; + + @CommandLine.Option(names = "--mode-filter", split = ",", defaultValue = "car,bike,truck,freight,drt", + description = "Only keep links if they have one of the specified modes. Specify 'none' to disable.") + private Set modes; + + @CommandLine.Option(names = "--precision", description = "Number of decimals places", defaultValue = "6") + private int precision; + + @CommandLine.Option(names = "--with-properties", description = "Convert custom node and link attributes as well.") + private boolean withProperties; + + @CommandLine.Option(names = "--filter-properties", description = "Only include listed properties in the output.") + private Set filterProperties; + + public static void main(String[] args) { + new CreateAvroNetwork().execute(args); + } + + @Override + public Integer call() throws Exception { + + Network network = input.getNetwork(); + + String networkCrs = ProjectionUtils.getCRS(input.getNetwork()); + if (crs.getInputCRS() != null) + networkCrs = crs.getInputCRS(); + + if (networkCrs == null) { + throw new IllegalArgumentException("Network coordinate system is neither in the xml nor given as option."); + } + + Predicate filter = link -> true; + + if (shp.isDefined()) { + Geometry geom = shp.getGeometry(); + CoordinateTransformation ct = shp.createTransformation(networkCrs); + + filter = link -> geom.contains(MGC.coord2Point(ct.transform(link.getFromNode().getCoord()))) || + geom.contains(MGC.coord2Point(ct.transform(link.getToNode().getCoord()))); + } + + if (matchId != null) { + Pattern p = Pattern.compile(matchId); + filter = filter.and(link -> p.matcher(link.getId().toString()).matches()); + } + + // At least one of the specified modes needs to be contained + if (!modes.isEmpty() && !modes.equals(Set.of("none"))) { + filter = filter.and(link -> modes.stream().anyMatch(m -> link.getAllowedModes().contains(m))); + } + + GenericData.Record avro = convert(network, TransformationFactory.getCoordinateTransformation(networkCrs, this.crs.getTargetCRS()), filter); + + avro.put("crs", crs.getTargetCRS()); + + write(avro.getSchema(), avro, output.getPath().toFile()); + + return 0; + } + + /** + * Converts the given network to a GeoJson representation. + * + * @param network the network to convert + * @param ct the coordinate transformation to use + * @param filter the filter to apply to the links + * @return created record + */ + private GenericData.Record convert(Network network, CoordinateTransformation ct, Predicate filter) { + + // Node attributes + List nodeCoords = new ArrayList<>(); + Object2IntMap nodeIds = new Object2IntLinkedOpenHashMap<>(); + + Map nodeAttributes = getAttributeColumns(network.getNodes().values()); + + for (Node node : network.getNodes().values()) { + + List relevant = new ArrayList<>(); + relevant.addAll(node.getInLinks().values()); + relevant.addAll(node.getOutLinks().values()); + + // Skip nodes without relevant links + if (relevant.stream().noneMatch(filter)) + continue; + + Coord from = ct.transform(node.getCoord()); + double xCoord = round(from.getX()); + double yCoord = round(from.getY()); + nodeCoords.add((float) xCoord); + nodeCoords.add((float) yCoord); + + String nodeId = node.getId().toString(); + nodeIds.put(nodeId, nodeIds.size()); + + collectAttributes(nodeAttributes, node); + } + + // Link attributes + FloatList lengths = new FloatArrayList(); + FloatList freeSpeeds = new FloatArrayList(); + FloatList capacities = new FloatArrayList(); + FloatList permLanes = new FloatArrayList(); + List ids = new ArrayList<>(); + IntList froms = new IntArrayList(); + IntList tos = new IntArrayList(); + IntList allowedModes = new IntArrayList(); + + Map linkAttributes = getAttributeColumns(network.getLinks().values()); + + Object2IntMap modeMapping = new Object2IntLinkedOpenHashMap<>(); + + for (Link link : network.getLinks().values()) { + if (!filter.test(link)) + continue; + + lengths.add((float) link.getLength()); + freeSpeeds.add((float) link.getFreespeed()); + capacities.add((float) link.getCapacity()); + permLanes.add((float) link.getNumberOfLanes()); + + String m = String.join(",", link.getAllowedModes()); + allowedModes.add(modeMapping.computeIfAbsent(m, k -> modeMapping.size())); + + ids.add(link.getId().toString()); + froms.add(nodeIds.getOrDefault(link.getFromNode().getId().toString(), -1)); + tos.add(nodeIds.getOrDefault(link.getToNode().getId().toString(), -1)); + + collectAttributes(linkAttributes, link); + } + + // Create the Avro record + Schema baseSchema = AvroNetwork.getClassSchema(); + + // Field objects needs to be copied + List fields = baseSchema.getFields() + .stream() + .map(f -> new Schema.Field(f.name(), f.schema(), f.doc(), f.defaultVal(), f.order())) + .collect(Collectors.toList()); + + createFields(fields, nodeAttributes, "node_"); + createFields(fields, linkAttributes, "link_"); + + // Copy of the original schema + Schema schema = Schema.createRecord(baseSchema.getName(), baseSchema.getDoc(), + baseSchema.getNamespace(), baseSchema.isError(), fields); + + GenericData.Record avro = new GenericData.Record(schema); + + // Set the node attributes + avro.put("nodeId", nodeIds.keySet().stream().toList()); + avro.put("nodeCoordinates", nodeCoords); + avro.put("nodeAttributes", createAttributeList(nodeAttributes, "nodeId")); + avro.put("linkAttributes", createAttributeList(linkAttributes, + "linkId", "length", "freespeed", "capacity", "permlanes", "allowedModes")); + + // Set the mapping which assigns an integer to each possible allowed mode entry + avro.put("modes", modeMapping.keySet().stream().toList()); + + // Set the link attributes + avro.put("linkId", ids); + avro.put("length", lengths); + avro.put("freespeed", freeSpeeds); + avro.put("capacity", capacities); + avro.put("permlanes", permLanes); + avro.put("allowedModes", allowedModes); + + avro.put("from", froms); + avro.put("to", tos); + + // Put the additional entry columns + for (Map.Entry e : Iterables.concat(nodeAttributes.entrySet(), linkAttributes.entrySet())) { + avro.put(e.getValue().name.getValue(), e.getValue().values); + } + + return avro; + } + + private List createAttributeList(Map attr, String... baseAttributes) { + List result = Arrays.stream(baseAttributes).collect(Collectors.toList()); + attr.values().stream().map(AttributeColumn::name).map(MutableObject::getValue) + .forEach(result::add); + + return result; + } + + private Map getAttributeColumns(Collection entities) { + + if (!withProperties) + return Collections.emptyMap(); + + Map map = new LinkedHashMap<>(); + + for (T entity : entities) { + Attributes attr = entity.getAttributes(); + for (Map.Entry e : attr.getAsMap().entrySet()) { + String key = e.getKey(); + if (filterProperties != null && !filterProperties.contains(key)) + continue; + + Object value = e.getValue(); + if (value instanceof Number) { + map.computeIfAbsent(key, k -> new AttributeColumn(new MutableObject<>(k), ColumnType.NUMBER, new ArrayList<>())); + } else if (value instanceof Boolean) { + map.computeIfAbsent(key, k -> new AttributeColumn(new MutableObject<>(k), ColumnType.BOOLEAN, new ArrayList<>())); + } else { + map.computeIfAbsent(key, k -> new AttributeColumn(new MutableObject<>(k), ColumnType.STRING, new ArrayList<>())); + } + } + } + + return map; + } + + private void collectAttributes(Map attributes, Attributable el) { + attributes.forEach((key, column) -> { + Object value = el.getAttributes().getAttribute(key); + if (column.type == ColumnType.NUMBER && value instanceof Number n) + value = n.floatValue(); + else if (column.type == ColumnType.BOOLEAN && value instanceof Boolean b) + value = b; + else if (column.type == ColumnType.STRING && value != null) + value = value.toString(); + else if (column.type == ColumnType.NUMBER) + value = Float.NaN; + else if (column.type == ColumnType.BOOLEAN) + value = false; + else if (column.type == ColumnType.STRING) + value = ""; + + + // Null is not allowed for any of these entries + column.values.add(value); + }); + } + + /** + * Add fields to the schema. + */ + private void createFields(List fields, Map attr, String prefix) { + for (Map.Entry e : attr.entrySet()) { + MutableObject name = e.getValue().name; + + while (fields.stream().anyMatch(f -> f.name().equals(name.getValue())) || FIELD_RESERVED.contains(name.getValue())) + name.setValue(prefix + name.getValue()); + + String key = name.getValue(); + Schema field = switch (e.getValue().type) { + case NUMBER -> Schema.createArray(Schema.create(Schema.Type.FLOAT)); + case BOOLEAN -> Schema.createArray(Schema.create(Schema.Type.BOOLEAN)); + case STRING -> Schema.createArray(Schema.create(Schema.Type.STRING)); + }; + + fields.add(new Schema.Field(key, field, e.getValue().name.getValue())); + } + } + + /** + * Write the avro network given as generic data to file output. + */ + private void write(Schema schema, GenericData.Record avroNetwork, File output) { + GenericDatumWriter datumWriter = new GenericDatumWriter<>(); + try (DataFileWriter dataFileWriter = new DataFileWriter<>(datumWriter)) { + dataFileWriter.setCodec(CodecFactory.deflateCodec(9)); + dataFileWriter.create(schema, IOUtils.getOutputStream(IOUtils.getFileUrl(output.toString()), false)); + dataFileWriter.append(avroNetwork); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Round to desired precision. + */ + private double round(double x) { + BigDecimal d = BigDecimal.valueOf(x).setScale(precision, RoundingMode.HALF_UP); + return d.doubleValue(); + } + + private enum ColumnType { + NUMBER, STRING, BOOLEAN + } + + private record AttributeColumn(MutableObject name, ColumnType type, List values) { + } + +} diff --git a/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateGeoJsonNetwork.java b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateGeoJsonNetwork.java index 42eb4408fe9..526cd8d36be 100644 --- a/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateGeoJsonNetwork.java +++ b/contribs/application/src/main/java/org/matsim/application/prepare/network/CreateGeoJsonNetwork.java @@ -29,6 +29,9 @@ import java.util.regex.Pattern; +/** + * Note that {@link CreateAvroNetwork} offers a more efficient way to store network data, which also loads much faster in the browser. + */ @CommandLine.Command(name = "network-geojson", description = "Create geojson representation of a network.") @CommandSpec(requireNetwork = true, produces = "network.geojson") public class CreateGeoJsonNetwork implements MATSimAppCommand { diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index fa6c86d2f52..a94a59e4058 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -10,7 +10,7 @@ hybridsim - 4.27.0 + 4.27.1 1.64.0 diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml index a824085d737..b93c87b1246 100644 --- a/contribs/protobuf/pom.xml +++ b/contribs/protobuf/pom.xml @@ -11,7 +11,7 @@ protobuf - 4.27.0 + 4.27.1 diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Data.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Data.java index 7010225d9d4..d13bbc48ae4 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Data.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/Data.java @@ -121,6 +121,9 @@ public String compute(Class command, String file, St currentContext.add(command, args); Path p = currentContext.getRequiredPath(command, file); + if (file.contains("%s")) + throw new IllegalArgumentException("Placeholder in file name not supported. Use computeWithPlaceholder instead."); + // Relative path from the simulation output return this.getUnixPath(this.path.getParent().relativize(p)); } diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/EmissionsDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/EmissionsDashboard.java index 9f167447922..b4c044fbe99 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/EmissionsDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/EmissionsDashboard.java @@ -1,12 +1,15 @@ package org.matsim.simwrapper.dashboard; import org.matsim.application.analysis.emissions.AirPollutionAnalysis; +import org.matsim.application.analysis.noise.NoiseAnalysis; +import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.application.prepare.network.CreateGeoJsonNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; import org.matsim.simwrapper.Layout; import org.matsim.simwrapper.viz.GridMap; import org.matsim.simwrapper.viz.Links; +import org.matsim.simwrapper.viz.MapPlot; import org.matsim.simwrapper.viz.Table; /** @@ -32,18 +35,19 @@ public void configure(Header header, Layout layout) { viz.width = 1d; }) - .el(Links.class, (viz, data) -> { + .el(MapPlot.class, (viz, data) -> { viz.title = "Emissions per Link per Meter"; viz.description = "Displays the emissions for each link per meter."; viz.height = 12.; - viz.datasets.csvFile = data.compute(AirPollutionAnalysis.class, "emissions_per_link_per_m.csv"); - viz.network = data.compute(CreateGeoJsonNetwork.class, "network.geojson"); - viz.display.color.columnName = "CO2_TOTAL [g/m]"; - viz.display.color.dataset = "csvFile"; - viz.display.width.scaleFactor = 1; - viz.display.width.columnName = "CO2_TOTAL [g/m]"; - viz.display.width.dataset = "csvFile"; - + viz.addDataset("emissions_per_link_per_m", data.compute(AirPollutionAnalysis.class, "emissions_per_link_per_m.csv")); + viz.setShape(data.compute(CreateAvroNetwork.class, "network.avro", "--with-properties"), "linkId"); + viz.display.lineColor.columnName = "CO2_TOTAL [g/m]"; + viz.display.lineColor.dataset = "emissions_per_link_per_m"; + viz.display.lineColor.setColorRamp("greenRed", 10, false); + viz.display.lineColor.join = "linkId"; + viz.display.lineWidth.columnName = "CO2_TOTAL [g/m]"; + viz.display.lineWidth.dataset = "emissions_per_link_per_m"; + viz.display.lineWidth.join = "linkId"; viz.center = data.context().getCenter(); viz.width = 3d; }); @@ -59,9 +63,8 @@ public void configure(Header header, Layout layout) { viz.projection = "EPSG:25832"; viz.zoom = data.context().mapZoomLevel; viz.center = data.context().getCenter(); - viz.setColorRamp("greenRed", 10, false); - viz.file = data.compute(AirPollutionAnalysis.class, "emissions_grid_per_day.csv"); + viz.file = data.computeWithPlaceholder(AirPollutionAnalysis.class, "emissions_grid_per_day.%s", "avro"); }); layout.row("third") @@ -77,7 +80,7 @@ public void configure(Header header, Layout layout) { viz.center = data.context().getCenter(); viz.setColorRamp("greenRed", 10, false); - viz.file = data.compute(AirPollutionAnalysis.class, "emissions_grid_per_hour.csv"); + viz.file = data.computeWithPlaceholder(AirPollutionAnalysis.class, "emissions_grid_per_hour.%s", "avro"); }); diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java index 2d2f3a5070b..dc934e6c2e2 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/NoiseDashboard.java @@ -1,7 +1,7 @@ package org.matsim.simwrapper.dashboard; import org.matsim.application.analysis.noise.NoiseAnalysis; -import org.matsim.application.prepare.network.CreateGeoJsonNetwork; +import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; import org.matsim.simwrapper.Layout; @@ -53,7 +53,7 @@ public void configure(Header header, Layout layout) { viz.zoom = data.context().mapZoomLevel; viz.minValue = minDb; viz.maxValue = maxDb; - viz.setShape(data.compute(CreateGeoJsonNetwork.class, "network.geojson", "--with-properties"), "id"); + viz.setShape(data.compute(CreateAvroNetwork.class, "network.avro", "--with-properties"), "id"); viz.addDataset("noise", data.compute(NoiseAnalysis.class, "emission_per_day.csv")); viz.display.lineColor.dataset = "noise"; viz.display.lineColor.columnName = "value"; diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java index 089ee4c8ce9..ef29484258b 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/OverviewDashboard.java @@ -2,6 +2,7 @@ import org.matsim.application.analysis.LogFileAnalysis; import org.matsim.application.analysis.traffic.TrafficAnalysis; +import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.application.prepare.network.CreateGeoJsonNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; @@ -35,7 +36,7 @@ public void configure(Header header, Layout layout) { viz.height = 7.5; viz.width = 2.0; - viz.setShape(data.compute(CreateGeoJsonNetwork.class, "network.geojson", "--with-properties"), "id"); + viz.setShape(data.compute(CreateAvroNetwork.class, "network.avro", "--with-properties"), "linkId"); viz.addDataset("traffic", data.compute(TrafficAnalysis.class, "traffic_stats_by_link_daily.csv")); viz.display.lineColor.dataset = "traffic"; @@ -48,8 +49,10 @@ public void configure(Header header, Layout layout) { viz.display.lineWidth.scaleFactor = 20000d; viz.display.lineWidth.join = "link_id"; + }); + // Info about the status of the run layout.row("warnings").el(TextBlock.class, (viz, data) -> { viz.file = data.compute(LogFileAnalysis.class, "status.md"); }); diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficCountsDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficCountsDashboard.java index 644f8fab8f4..2bd83f1baba 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficCountsDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficCountsDashboard.java @@ -2,7 +2,7 @@ import org.apache.commons.lang.StringUtils; import org.matsim.application.analysis.traffic.CountComparisonAnalysis; -import org.matsim.application.prepare.network.CreateGeoJsonNetwork; +import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; import org.matsim.simwrapper.Layout; @@ -212,7 +212,7 @@ private void createTab(Layout layout, List argList, String tabName, Set< viz.title = "Relative traffic volumes"; viz.height = 8.0; - viz.setShape(data.withDefaultContext().compute(CreateGeoJsonNetwork.class, "network.geojson", "--with-properties"), "id"); + viz.setShape(data.withDefaultContext().compute(CreateAvroNetwork.class, "network.avro", "--with-properties"), "id"); viz.addDataset("counts", data.compute(CountComparisonAnalysis.class, "count_comparison_daily.csv", args)); viz.center = data.withDefaultContext().context().getCenter(); diff --git a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficDashboard.java b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficDashboard.java index 746c3e033ed..1c56e998229 100644 --- a/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficDashboard.java +++ b/contribs/simwrapper/src/main/java/org/matsim/simwrapper/dashboard/TrafficDashboard.java @@ -2,7 +2,7 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.application.analysis.traffic.TrafficAnalysis; -import org.matsim.application.prepare.network.CreateGeoJsonNetwork; +import org.matsim.application.prepare.network.CreateAvroNetwork; import org.matsim.simwrapper.Dashboard; import org.matsim.simwrapper.Header; import org.matsim.simwrapper.Layout; @@ -76,7 +76,7 @@ public void configure(Header header, Layout layout) { viz.center = data.context().getCenter(); viz.zoom = data.context().mapZoomLevel; - viz.setShape(data.compute(CreateGeoJsonNetwork.class, "network.geojson"), "id"); + viz.setShape(data.compute(CreateAvroNetwork.class, "network.avro"), "id"); viz.addDataset("traffic", data.compute(TrafficAnalysis.class, "traffic_stats_by_link_daily.csv")); diff --git a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/EmissionsDashboardTest.java b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/EmissionsDashboardTest.java index c82e08870df..3eb8a85e3f4 100644 --- a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/EmissionsDashboardTest.java +++ b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/EmissionsDashboardTest.java @@ -70,7 +70,7 @@ void generate() { Assertions.assertThat(out) .isDirectoryContaining("glob:**emissions_total.csv") - .isDirectoryContaining("glob:**emissions_grid_per_day.csv"); + .isDirectoryContaining("glob:**emissions_grid_per_day.avro"); }