Skip to content

Commit

Permalink
improve count options file format
Browse files Browse the repository at this point in the history
  • Loading branch information
rakow committed Mar 26, 2024
1 parent eb29023 commit ef62a7c
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 131 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package org.matsim.application.options;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.core.utils.io.IOUtils;
import picocli.CommandLine;

import javax.annotation.Nullable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.*;

/**
* Common options when working with counts data.
*/
public final class CountsOptions {

@CommandLine.Option(names = "--counts-mapping", description = "Path to csv with count station ids to ignore")
private String input;

private Map<String, Id<Link>> manualMatchedCounts = null;
private Set<String> ignoredCounts = null;

public CountsOptions() {
}

public CountsOptions(@Nullable String input) {
this.input = input;
}

/**
* Get list of ignored count ids.
*/
public Set<String> getIgnored() {
readMapping();
return ignoredCounts;
}

/**
* Return mapping of count id to specified link id.
*/
public Map<String, Id<Link>> getManualMatched() {
readMapping();
return manualMatchedCounts;
}

private void readMapping() {

// Already read
if (manualMatchedCounts != null)
return;

manualMatchedCounts = new HashMap<>();
ignoredCounts = new HashSet<>();

try (var reader = IOUtils.getBufferedReader(input)) {
CSVFormat format = CSVFormat.Builder.create()
.setAllowMissingColumnNames(true)
.setDelimiter(CsvOptions.detectDelimiter(input))
.setHeader()
.setSkipHeaderRecord(true)
.build();

try (CSVParser csv = new CSVParser(reader, format)) {
Schema schema = parseSchema(csv.getHeaderNames());
for (CSVRecord row : csv) {

String stationId = row.get(schema.stationColumn);
manualMatchedCounts.put(stationId, Id.createLinkId(row.get(schema.linkColumn)));

if (schema.usingColumn != null) {

String value = row.get(schema.usingColumn).strip().toLowerCase();
boolean val = value.equals("y") || value.equals("x") || value.equals("true");

if (schema.isWhiteList && !val)
ignoredCounts.add(stationId);
else if (!schema.isWhiteList && val)
ignoredCounts.add(stationId);
}
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}

}

/**
* Check whether station id should be ignored.
*/
public boolean isIgnored(String stationId) {
readMapping();
return ignoredCounts.contains(stationId);
}

/**
* Return manually matched link id.
*
* @return null if not matched
*/
public Id<Link> isManuallyMatched(String stationId) {
readMapping();

if (manualMatchedCounts.isEmpty() || !manualMatchedCounts.containsKey(stationId))
return null;

return manualMatchedCounts.get(stationId);
}

private Schema parseSchema(List<String> header) {

List<String> names = header.stream()
.map(String::toLowerCase)
.map(String::strip)
.map(s -> s.replace("_", ""))
.toList();

int linkId = names.indexOf("linkid");

if (linkId < 0)
throw new IllegalArgumentException("Link id column not found in csv: " + header);

int using = names.indexOf("using");
int ignore = names.indexOf("ignore");

// first or second column for station id
int station = linkId == 0 ? 1 : 0;

if (using > 0)
return new Schema(header.get(station), header.get(linkId), header.get(using), true);

if (ignore > 0)
return new Schema(header.get(station), header.get(linkId), header.get(ignore), false);

return new Schema(header.get(station), header.get(linkId), null, false);
}

private record Schema(String stationColumn, String linkColumn, String usingColumn, boolean isWhiteList) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.application.MATSimAppCommand;
import org.matsim.application.options.CountsOption;
import org.matsim.application.options.CountsOptions;
import org.matsim.application.options.CrsOptions;
import org.matsim.application.options.ShpOptions;
import org.matsim.core.config.groups.NetworkConfigGroup;
Expand Down Expand Up @@ -63,7 +63,7 @@ public class CreateCountsFromBAStData implements MATSimAppCommand {
@CommandLine.Mixin
private final ShpOptions shp = new ShpOptions();
@CommandLine.Mixin
private final CountsOption counts = new CountsOption();
private final CountsOptions counts = new CountsOptions();
@CommandLine.Mixin
private final CrsOptions crs = new CrsOptions("EPSG:25832");
@CommandLine.Option(names = "--network", description = "path to MATSim network", required = true)
Expand Down Expand Up @@ -284,7 +284,7 @@ private void readHourlyTrafficVolume(Path pathToDisaggregatedData, Map<String, B
}
}

private void match(Network network, NetworkIndex<BAStCountStation> index, BAStCountStation station, CountsOption counts) {
private void match(Network network, NetworkIndex<BAStCountStation> index, BAStCountStation station, CountsOptions counts) {

Id<Link> manuallyMatched = counts.isManuallyMatched(station.getId());
Link matched;
Expand Down Expand Up @@ -330,7 +330,7 @@ private List<Predicate<Link>> createRoadTypeFilter(List<String> types) {
return filter;
}

private void matchBAStWithNetwork(String pathToNetwork, Map<String, BAStCountStation> stations, CountsOption countsOption, CrsOptions crs) {
private void matchBAStWithNetwork(String pathToNetwork, Map<String, BAStCountStation> stations, CountsOptions countsOption, CrsOptions crs) {

if (crs.getTargetCRS() != null)
throw new RuntimeException("Please don't specify --target-crs. Only use --input-crs to determinate the network crs!");
Expand Down Expand Up @@ -366,7 +366,7 @@ private void matchBAStWithNetwork(String pathToNetwork, Map<String, BAStCountSta
match(filteredNetwork, index, station, countsOption);
}

private Map<String, BAStCountStation> readBAStCountStations(Path pathToAggregatedData, ShpOptions shp, CountsOption counts) {
private Map<String, BAStCountStation> readBAStCountStations(Path pathToAggregatedData, ShpOptions shp, CountsOptions counts) {

List<BAStCountStation> stations = new ArrayList<>();

Expand Down

0 comments on commit ef62a7c

Please sign in to comment.