Skip to content

Commit

Permalink
add docs on validating networks
Browse files Browse the repository at this point in the history
  • Loading branch information
e-lo committed Aug 27, 2024
1 parent fc35831 commit 6f82ec2
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 75 deletions.
69 changes: 69 additions & 0 deletions docs/networks.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,40 @@ RoadwayNetworks must be defined in the following format, which leverages [Open S

A network is defined by a set of nodes and links which connect them. Shapes may be optionally specified for each link in a separate file.

### Roadway Validation

RoadwayNetworks can be validated using the following tools:

=== "CLI"

```bash
python validate_roadway.py <network_directory> <network_suffix> [-s] [--output_dir <output_dir>]
```
Where:

- `network_directory`: The roadway network file directory.
- `network_suffix`: The suffices of roadway network file name.
- `-s`, `--strict`: Validate the roadway network strictly without parsing and filling in data.
- `--output_dir`: The output directory for the validation report.

=== "Python API"

```python
from network_wrangler.roadway.validate import validate_roadway_in_dir
validate_roadway_in_dir(
directory=<network_directory>,
suffix=<network_suffix>,
strict=<strict_bool>>,
output_dir=<output_dir>
)
```
Where:

- `network_directory`: The roadway network file directory.
- `network_suffix`: The suffices of roadway network file name.
- `strict`: Validate the roadway network strictly without parsing and filling in data.
- `output_dir`: The output directory for the validation report.

### Examples

Network Wrangler is packaged with two examples located in the `/examples` directory:
Expand Down Expand Up @@ -197,6 +231,41 @@ Transit Networks must use the the [GTFS](https://www.gtfs.org) Schedule format w
2. Each `stop_id` must be a node in the RoadwayNetwork.
3. `shapes.txt` is *required* (it is optional in GTFS) and must have the added field `model_node_id` associating a specific location with a node on the `RoadwayNetwork`.

### Transit Validation

TransitNetworks can be validated using the following tools:

=== "CLI"

```bash
python validate_transit.py <network_directory> <network_suffix> [-s] [--output_dir <output_dir>] [--road_dir <road_dir>] [--road_suffix <road_suffix>]
```
Where:

- `network_directory`: The roadway network file directory.
- `network_suffix`: The suffices of roadway network file name.
- `--output_dir`: The output directory for the validation report.
- `--road_dir`: The directory roadway network. if want to validate the transit network to it.
- `--road_suffix`: The suffix for roadway network. Defaults to 'geojson'.

=== "Python API"

```python
from network_wrangler.transit.validate import validate_transit_in_dir
validate_transit_in_dir(
directory=<network_directory>,
suffix=<network_suffix>,
road_dir=<road_dir>,
road_suffix=<road_suffix>,
)
```
Where:

- `network_directory`: The roadway network file directory.
- `network_suffix`: The suffices of roadway network file name.
- `road_dir`: The directory roadway network. if want to validate the transit network to it.
- `road_suffix`: The suffix for roadway network. Defaults to 'geojson'.

## Project Cards

Project Cards, which define changes to the roadway and transit networks must use the [ProjectCard](https://github.com/networkwrangler/projectcard) standard.
Expand Down
5 changes: 2 additions & 3 deletions network_wrangler/bin/build_scenario_from_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
information, and then creates a scenario by applying projects from the project card file to
the base scenario. The modified network can be written out to files if specified.
"""

import argparse

from pathlib import Path
Expand All @@ -33,9 +34,7 @@


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Build a scenario from a configuration file."
)
parser = argparse.ArgumentParser(description="Build a scenario from a configuration file.")
parser.add_argument(
"config_file",
type=Path,
Expand Down
21 changes: 9 additions & 12 deletions network_wrangler/bin/validate_roadway.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
-s, --strict: Validate the roadway network strictly without parsing and filling in data.
--output_dir: The output directory for the validation report.
"""

import argparse
import datetime

Expand All @@ -19,27 +20,23 @@

if __name__ == "__main__":
# ----- Setup Arguments ------
parser = argparse.ArgumentParser("Validate a roadway network to the wrangler data model specifications.")
parser = argparse.ArgumentParser(
"Validate a roadway network to the wrangler data model specifications."
)
parser.add_argument(
"network_directory",
help="The roadway network file directory.",
default="."
"network_directory", help="The roadway network file directory.", default="."
)
parser.add_argument(
"network_suffix",
help="The suffices of roadway network file name.",
default="geojson"
"network_suffix", help="The suffices of roadway network file name.", default="geojson"
)
parser.add_argument(
"-s",
"--strict",
action="store_true",
help="Validate the roadway network strictly without parsing and filling in data."
help="Validate the roadway network strictly without parsing and filling in data.",
)
parser.add_argument(
"--output_dir",
help="The output directory for the validation report.",
default="."
"--output_dir", help="The output directory for the validation report.", default="."
)

args = parser.parse_args()
Expand All @@ -62,5 +59,5 @@
directory=args.network_directory,
suffix=args.network_suffix,
strict=argparse.strict,
output_dir=args.output_dir
output_dir=args.output_dir,
)
25 changes: 10 additions & 15 deletions network_wrangler/bin/validate_transit.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
--road_dir: The directory roadway network if want to validate the transit network to it.
--road_suffix: The suffix for roadway network. Defaults to 'geojson'.
"""

import argparse
import datetime

Expand All @@ -22,23 +23,21 @@

if __name__ == "__main__":
# ----- Setup Arguments ------
parser = argparse.ArgumentParser("Validate a transit network to the wrangler data \
model specifications.")
parser = argparse.ArgumentParser(
"Validate a transit network to the wrangler data \
model specifications."
)
parser.add_argument(
"network_directory",
help="The transit network file directory.",
default="."
"network_directory", help="The transit network file directory.", default="."
)
parser.add_argument(
"network_suffix",
help="The suffices of transit network file name.",
default="geojson"
"network_suffix", help="The suffices of transit network file name.", default="geojson"
)
parser.add_argument(
"-s",
"--strict",
action="store_true",
help="Validate the transit network strictly without parsing and filling in data."
help="Validate the transit network strictly without parsing and filling in data.",
)
parser.add_argument(
"--road_dir",
Expand All @@ -51,14 +50,10 @@
default="geojson",
)
parser.add_argument(
"--output_dir",
help="The output directory for the validation report.",
default="."
"--output_dir", help="The output directory for the validation report.", default="."
)
parser.add_argument(
"--output_dir",
help="The output directory for the validation report.",
default="."
"--output_dir", help="The output directory for the validation report.", default="."
)

args = parser.parse_args()
Expand Down
18 changes: 6 additions & 12 deletions network_wrangler/roadway/nodes/validate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Validation for roadway nodes dataframes and files."""

from __future__ import annotations

from pathlib import Path
Expand All @@ -11,33 +12,25 @@


def validate_nodes_file(
nodes_filename: Path,
strict: bool = False,
errors_filename: Path = "node_errors.csv"
nodes_filename: Path, strict: bool = False, errors_filename: Path = "node_errors.csv"
) -> bool:
"""Validates a nodes file to RoadNodesTable.
Args:
nodes_filename (Path): The nodes file.
strict (bool): If True, will validate to nodes_df without trying to parse it first.
errors_filename (Path): The output file for the validation errors. Defaults
errors_filename (Path): The output file for the validation errors. Defaults
to "node_errors.csv".
Returns:
bool: True if the nodes file is valid.
"""
nodes_df = pd.read_csv(nodes_filename)
return validate_nodes_df(
nodes_df,
strict=strict,
errors_filename=errors_filename
)
return validate_nodes_df(nodes_df, strict=strict, errors_filename=errors_filename)


def validate_nodes_df(
nodes_df: pd.DataFrame,
strict: bool = False,
errors_filename: Path = "node_errors.csv"
nodes_df: pd.DataFrame, strict: bool = False, errors_filename: Path = "node_errors.csv"
) -> bool:
"""Validates a shapes df to RoadNodessTables.
Expand All @@ -54,6 +47,7 @@ def validate_nodes_df(

if not strict:
from .create import data_to_nodes_df

try:
nodes_df = data_to_nodes_df(nodes_df)
except Exception as e:
Expand Down
18 changes: 6 additions & 12 deletions network_wrangler/roadway/shapes/validate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Validation for roadway nodes dataframes and files."""

from __future__ import annotations

from pathlib import Path
Expand All @@ -11,33 +12,25 @@


def validate_shapes_file(
shapes_filename: Path,
strict: bool = False,
errors_filename: Path = "shape_errors.csv"
shapes_filename: Path, strict: bool = False, errors_filename: Path = "shape_errors.csv"
) -> bool:
"""Validates a shapes file to RoadShapesTable.
Args:
shapes_filename (Path): The shapes file.
strict (bool): If True, will validate to shapes_df without trying to parse it first.
errors_filename (Path): The output file for the validation errors. Defaults
errors_filename (Path): The output file for the validation errors. Defaults
to "shape_errors.csv".
Returns:
bool: True if the nodes file is valid.
"""
shapes_df = pd.read_csv(shapes_filename)
return validate_shapes_df(
shapes_df,
strict=strict,
errors_filename=errors_filename
)
return validate_shapes_df(shapes_df, strict=strict, errors_filename=errors_filename)


def validate_shapes_df(
shapes_df: pd.DataFrame,
strict: bool = False,
errors_filename: Path = "shape_errors.csv"
shapes_df: pd.DataFrame, strict: bool = False, errors_filename: Path = "shape_errors.csv"
) -> bool:
"""Validates a Shapes df to RoadShapesTables.
Expand All @@ -54,6 +47,7 @@ def validate_shapes_df(

if not strict:
from .create import data_to_shapes_df

try:
shapes_df = data_to_shapes_df(shapes_df)
except Exception as e:
Expand Down
33 changes: 12 additions & 21 deletions network_wrangler/roadway/validate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Validates a roadway network to the wrangler data model specifications."""

from pathlib import Path
from typing import Optional

Expand All @@ -11,23 +12,21 @@
from network_wrangler.roadway.shapes.validate import validate_shapes_df


def validate_roadway_in_dir(directory: Path, suffix: str, strict: bool = False, output_dir: Path = "."):
def validate_roadway_in_dir(
directory: Path, suffix: str, strict: bool = False, output_dir: Path = "."
):
"""Validates a roadway network in a directory to the wrangler data model specifications.
Args:
directory (str): The roadway network file directory.
suffix (str): The suffices of roadway network file name.
strict (bool): If True, will validate the roadway network strictly without
strict (bool): If True, will validate the roadway network strictly without
parsing and filling in data.
output_dir (str): The output directory for the validation report. Defaults to ".".
"""
links_file, nodes_file, shapes_file = id_roadway_file_paths_in_dir(directory, suffix)
validate_roadway_files(
links_file,
nodes_file,
shapes_file,
strict=strict,
output_dir=output_dir
links_file, nodes_file, shapes_file, strict=strict, output_dir=output_dir
)


Expand All @@ -36,46 +35,38 @@ def validate_roadway_files(
nodes_file: Path,
shapes_file: Optional[Path] = None,
strict: bool = False,
output_dir: Path = "."
output_dir: Path = ".",
):
"""Validates the roadway network files strictly to the wrangler data model specifications.
Args:
links_file (str): The path to the links file.
nodes_file (str): The path to the nodes file.
shapes_file (str): The path to the shapes file.
strict (bool): If True, will validate the roadway network strictly without
strict (bool): If True, will validate the roadway network strictly without
parsing and filling in data.
output_dir (str): The output directory for the validation report. Defaults to ".".
"""
valid = {
"net": True,
"links": True,
"nodes": True
}
valid = {"net": True, "links": True, "nodes": True}

nodes_df = read_table(nodes_file)
valid["links"] = validate_nodes_df(
nodes_df,
strict=strict,
output_file=Path(output_dir) / "node_errors.csv"
nodes_df, strict=strict, output_file=Path(output_dir) / "node_errors.csv"
)

links_df = read_table(links_file)
valid["links"] = validate_links_df(
links_df,
nodes_df=nodes_df,
strict=strict,
output_file=Path(output_dir) / "link_errors.csv"
output_file=Path(output_dir) / "link_errors.csv",
)

if shapes_file:
valid["shapes"] = True
shapes_df = read_table(shapes_file)
valid["shapes"] = validate_shapes_df(
shapes_df,
strict=strict,
output_file=Path(output_dir) / "shape_errors.csv"
shapes_df, strict=strict, output_file=Path(output_dir) / "shape_errors.csv"
)

try:
Expand Down

0 comments on commit 6f82ec2

Please sign in to comment.