Skip to content

Commit 6c64c07

Browse files
authored
Make providers configurable, add config file for easier configuration (#15)
* Making providers configurable * Adding config file
1 parent 589f579 commit 6c64c07

File tree

10 files changed

+317
-297
lines changed

10 files changed

+317
-297
lines changed

README.md

Lines changed: 21 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -37,44 +37,26 @@ pip install traveltime-google-comparison
3737
```
3838

3939
## Setup
40-
Provide credentials for the APIs via environment variables.
41-
42-
For Google Maps API:
43-
44-
```bash
45-
export GOOGLE_API_KEY=[Your Google Maps API Key]
46-
```
47-
48-
For TomTom API:
49-
50-
```bash
51-
export TOMTOM_API_KEY=[Your TomTom API Key]
52-
```
53-
54-
For HERE API:
55-
56-
```bash
57-
export HERE_API_KEY=[Your HERE API Key]
58-
```
59-
60-
For Mapbox API:
61-
62-
```bash
63-
export MAPBOX_API_KEY=[Your Mapbox API Key]
64-
```
65-
66-
For OpenRoutes API:
67-
68-
```bash
69-
export OPENROUTES_API_KEY=[Your OpenRoutes API Key]
70-
```
71-
72-
For OSRM API: OSRM does not require a key.
73-
74-
For TravelTime API:
75-
```bash
76-
export TRAVELTIME_APP_ID=[Your TravelTime App ID]
77-
export TRAVELTIME_API_KEY=[Your TravelTime API Key]
40+
Provide credentials and desired max requests per minute for the APIs inside the `config.json` file.
41+
You can also disable unwanted APIs by changing the `enabled` value to `false`.
42+
43+
```json
44+
{
45+
"traveltime": {
46+
"app-id": "<your-app-id>",
47+
"api-key": "<your-api-key>",
48+
"max-rpm": "60"
49+
},
50+
"api-providers": [
51+
{
52+
"name": "google",
53+
"enabled": true,
54+
"api-key": "<your-api-key>",
55+
"max-rpm": "60"
56+
},
57+
...other providers
58+
]
59+
}
7860
```
7961

8062
## Usage
@@ -104,23 +86,8 @@ Required arguments:
10486
- `--time-zone-id [Time zone ID]`: non-abbreviated time zone identifier in which the time values are specified.
10587
For example: `Europe/London`. For more information, see [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
10688

107-
108-
10989
Optional arguments:
110-
- `--google-max-rpm [int]`: Set max number of parallel requests sent to Google API per minute. Default is 60.
111-
It is enforced on per-second basis, to avoid bursts.
112-
- `--tomtom-max-rpm [int]`: Set max number of parallel requests sent to TomTom API per minute. Default is 60.
113-
It is enforced on per-second basis, to avoid bursts.
114-
- `--mapbox-max-rpm [int]`: Set max number of parallel requests sent to Mapbox API per minute. Default is 60.
115-
It is enforced on per-second basis, to avoid bursts.
116-
- `--here-max-rpm [int]`: Set max number of parallel requests sent to HERE API per minute. Default is 60.
117-
It is enforced on per-second basis, to avoid bursts.
118-
- `--osrm-max-rpm [int]`: Set max number of parallel requests sent to OSRM API per minute. Default is 60.
119-
It is enforced on per-second basis, to avoid bursts.
120-
- `--openroutes-max-rpm [int]`: Set max number of parallel requests sent to OpenRoutes API per minute. Default is 60.
121-
It is enforced on per-second basis, to avoid bursts.
122-
- `--traveltime-max-rpm [int]`: Set max number of parallel requests sent to TravelTime API per minute. Default is 60.
123-
It is enforced on per-second basis, to avoid bursts.
90+
- `--config [Config file path]`: Path to the config file. Default - ./config.json
12491

12592
Example:
12693

config.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"traveltime": {
3+
"app-id": "<your-app-id>",
4+
"api-key": "<your-api-key>",
5+
"max-rpm": "60"
6+
},
7+
"api-providers": [
8+
{
9+
"name": "google",
10+
"enabled": true,
11+
"api-key": "<your-api-key>",
12+
"max-rpm": "60"
13+
},
14+
{
15+
"name": "tomtom",
16+
"enabled": true,
17+
"api-key": "<your-api-key>",
18+
"max-rpm": "60"
19+
},
20+
{
21+
"name": "here",
22+
"enabled": true,
23+
"api-key": "<your-api-key>",
24+
"max-rpm": "60"
25+
},
26+
{
27+
"name": "mapbox",
28+
"enabled": true,
29+
"api-key": "<your-api-key>",
30+
"max-rpm": "60"
31+
},
32+
{
33+
"name": "osrm",
34+
"enabled": true,
35+
"api-key": "not-needed!",
36+
"max-rpm": "60"
37+
},
38+
{
39+
"name": "openroutes",
40+
"enabled": true,
41+
"api-key": "<your-api-key>",
42+
"max-rpm": "20"
43+
}
44+
]
45+
}

src/traveltime_google_comparison/analysis.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import logging
22
from dataclasses import dataclass
3-
from typing import List
43

54
from pandas import DataFrame
65

@@ -9,6 +8,7 @@
98
TRAVELTIME_API,
109
get_capitalized_provider_name,
1110
)
11+
from traveltime_google_comparison.config import Providers
1212

1313

1414
def absolute_error(api_provider: str) -> str:
@@ -26,31 +26,31 @@ class QuantileErrorResult:
2626

2727

2828
def log_results(
29-
results_with_differences: DataFrame, quantile: float, api_providers: List[str]
29+
results_with_differences: DataFrame, quantile: float, api_providers: Providers
3030
):
31-
for provider in api_providers:
32-
capitalized_provider = get_capitalized_provider_name(provider)
31+
for provider in api_providers.competitors:
32+
name = provider.name
33+
capitalized_provider = get_capitalized_provider_name(name)
3334
logging.info(
3435
f"Mean relative error compared to {capitalized_provider} "
35-
f"API: {results_with_differences[relative_error(provider)].mean():.2f}%"
36-
)
37-
quantile_errors = calculate_quantiles(
38-
results_with_differences, quantile, provider
36+
f"API: {results_with_differences[relative_error(name)].mean():.2f}%"
3937
)
38+
quantile_errors = calculate_quantiles(results_with_differences, quantile, name)
4039
logging.info(
4140
f"{int(quantile * 100)}% of TravelTime results differ from {capitalized_provider} API "
4241
f"by less than {int(quantile_errors.relative_error)}%"
4342
)
4443

4544

4645
def format_results_for_csv(
47-
results_with_differences: DataFrame, api_providers: List[str]
46+
results_with_differences: DataFrame, api_providers: Providers
4847
) -> DataFrame:
4948
formatted_results = results_with_differences.copy()
5049

51-
for provider in api_providers:
52-
formatted_results = formatted_results.drop(columns=[absolute_error(provider)])
53-
relative_error_col = relative_error(provider)
50+
for provider in api_providers.competitors:
51+
name = provider.name
52+
formatted_results = formatted_results.drop(columns=[absolute_error(name)])
53+
relative_error_col = relative_error(name)
5454
formatted_results[relative_error_col] = formatted_results[
5555
relative_error_col
5656
].astype(int)
@@ -59,7 +59,7 @@ def format_results_for_csv(
5959

6060

6161
def run_analysis(
62-
results: DataFrame, output_file: str, quantile: float, api_providers: List[str]
62+
results: DataFrame, output_file: str, quantile: float, api_providers: Providers
6363
):
6464
results_with_differences = calculate_differences(results, api_providers)
6565
log_results(results_with_differences, quantile, api_providers)
@@ -71,21 +71,22 @@ def run_analysis(
7171
formatted_results.to_csv(output_file, index=False)
7272

7373

74-
def calculate_differences(results: DataFrame, api_providers: List[str]) -> DataFrame:
74+
def calculate_differences(results: DataFrame, api_providers: Providers) -> DataFrame:
7575
results_with_differences = results.copy()
7676

77-
for provider in api_providers:
78-
absolute_error_col = absolute_error(provider)
79-
relative_error_col = relative_error(provider)
77+
for provider in api_providers.competitors:
78+
name = provider.name
79+
absolute_error_col = absolute_error(name)
80+
relative_error_col = relative_error(name)
8081

8182
results_with_differences[absolute_error_col] = abs(
82-
results[Fields.TRAVEL_TIME[provider]]
83+
results[Fields.TRAVEL_TIME[name]]
8384
- results[Fields.TRAVEL_TIME[TRAVELTIME_API]]
8485
)
8586

8687
results_with_differences[relative_error_col] = (
8788
results_with_differences[absolute_error_col]
88-
/ results_with_differences[Fields.TRAVEL_TIME[provider]]
89+
/ results_with_differences[Fields.TRAVEL_TIME[name]]
8990
* 100
9091
)
9192

@@ -95,13 +96,13 @@ def calculate_differences(results: DataFrame, api_providers: List[str]) -> DataF
9596
def calculate_quantiles(
9697
results_with_differences: DataFrame,
9798
quantile: float,
98-
api_provider: str,
99+
api_provider_name: str,
99100
) -> QuantileErrorResult:
100101
quantile_absolute_error = results_with_differences[
101-
absolute_error(api_provider)
102+
absolute_error(api_provider_name)
102103
].quantile(quantile, "higher")
103104
quantile_relative_error = results_with_differences[
104-
relative_error(api_provider)
105+
relative_error(api_provider_name)
105106
].quantile(quantile, "higher")
106107
return QuantileErrorResult(
107108
int(quantile_absolute_error), int(quantile_relative_error)

src/traveltime_google_comparison/collect.py

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from traveltime_google_comparison.config import Mode
1414
from traveltime_google_comparison.requests.base_handler import BaseRequestHandler
1515

16+
1617
GOOGLE_API = "google"
1718
TOMTOM_API = "tomtom"
1819
HERE_API = "here"
@@ -132,7 +133,10 @@ def generate_tasks(
132133

133134

134135
async def collect_travel_times(
135-
args, data, request_handlers: Dict[str, BaseRequestHandler], providers: List[str]
136+
args,
137+
data,
138+
request_handlers: Dict[str, BaseRequestHandler],
139+
provider_names: List[str],
136140
) -> DataFrame:
137141
timezone = pytz.timezone(args.time_zone_id)
138142
localized_start_datetime = localize_datetime(args.date, args.start_time, timezone)
@@ -144,28 +148,16 @@ async def collect_travel_times(
144148
tasks = generate_tasks(data, time_instants, request_handlers, mode=Mode.DRIVING)
145149

146150
capitalized_providers_str = ", ".join(
147-
[get_capitalized_provider_name(provider) for provider in providers]
148-
)
149-
logger.info(
150-
f"Sending {len(tasks)} requests to {capitalized_providers_str} and TravelTime APIs"
151+
[get_capitalized_provider_name(provider) for provider in provider_names]
151152
)
153+
logger.info(f"Sending {len(tasks)} requests to {capitalized_providers_str} APIs")
152154

153155
results = await asyncio.gather(*tasks)
154156

155157
results_df = pd.DataFrame(results)
156158
deduplicated = results_df.groupby(
157159
[Fields.ORIGIN, Fields.DESTINATION, Fields.DEPARTURE_TIME], as_index=False
158-
).agg(
159-
{
160-
Fields.TRAVEL_TIME[GOOGLE_API]: "first",
161-
Fields.TRAVEL_TIME[TOMTOM_API]: "first",
162-
Fields.TRAVEL_TIME[HERE_API]: "first",
163-
Fields.TRAVEL_TIME[OSRM_API]: "first",
164-
Fields.TRAVEL_TIME[OPENROUTES_API]: "first",
165-
Fields.TRAVEL_TIME[MAPBOX_API]: "first",
166-
Fields.TRAVEL_TIME[TRAVELTIME_API]: "first",
167-
}
168-
)
160+
).agg({Fields.TRAVEL_TIME[provider]: "first" for provider in provider_names})
169161
deduplicated.to_csv(args.output, index=False)
170162
return deduplicated
171163

0 commit comments

Comments
 (0)