|
1 | 1 | from typing import List, Optional, Union, Tuple, Dict, Any, Set
|
2 | 2 | from itertools import groupby
|
3 |
| -from datetime import date, datetime |
| 3 | +from datetime import date, datetime, timedelta |
4 | 4 | from flask import Blueprint, request
|
5 | 5 | from flask.json import loads, jsonify
|
6 | 6 | from bisect import bisect_right
|
|
34 | 34 | from .._db import sql_table_has_columns
|
35 | 35 | from .._pandas import as_pandas
|
36 | 36 | from .covidcast_utils import compute_trend, compute_trends, compute_correlations, compute_trend_value, CovidcastMetaEntry, AllSignalsMap
|
37 |
| -from ..utils import shift_time_value, date_to_time_value, time_value_to_iso |
| 37 | +from ..utils import shift_time_value, date_to_time_value, time_value_to_iso, time_value_to_date |
38 | 38 |
|
39 | 39 | # first argument is the endpoint name
|
40 | 40 | bp = Blueprint("covidcast", __name__)
|
@@ -150,7 +150,6 @@ def handle():
|
150 | 150 | q.set_order("source", "signal", "time_type", "time_value", "geo_type", "geo_value", "issue")
|
151 | 151 | q.set_fields(fields_string, fields_int, fields_float)
|
152 | 152 |
|
153 |
| - |
154 | 153 | # basic query info
|
155 | 154 | # data type of each field
|
156 | 155 | # build the source, signal, time, and location (type and id) filters
|
@@ -493,3 +492,45 @@ def handle_meta():
|
493 | 492 | entry.intergrate(row)
|
494 | 493 |
|
495 | 494 | return jsonify([r.asdict() for r in out.values()])
|
| 495 | + |
| 496 | + |
| 497 | +@bp.route("/coverage", methods=("GET", "POST")) |
| 498 | +def handle_coverage(): |
| 499 | + """ |
| 500 | + similar to /signal_dashboard_coverage for a specific signal returns the coverage (number of locations for a given geo_type) |
| 501 | + """ |
| 502 | + |
| 503 | + signal = parse_source_signal_arg("signal") |
| 504 | + geo_type = request.args.get("geo_type", "county") |
| 505 | + if "window" in request.values: |
| 506 | + time_window = parse_day_range_arg("window") |
| 507 | + else: |
| 508 | + now_time = extract_date("latest") |
| 509 | + now = date.today() if now_time is None else time_value_to_date(now_time) |
| 510 | + last = extract_integer("days") |
| 511 | + if last is None: |
| 512 | + last = 30 |
| 513 | + time_window = (date_to_time_value(now - timedelta(days=last)), date_to_time_value(now)) |
| 514 | + |
| 515 | + q = QueryBuilder("covidcast", "c") |
| 516 | + fields_string = ["source", "signal"] |
| 517 | + fields_int = ["time_value"] |
| 518 | + |
| 519 | + q.set_fields(fields_string, fields_int) |
| 520 | + |
| 521 | + # manually append the count column because of grouping |
| 522 | + fields_int.append("count") |
| 523 | + q.fields.append(f"count({q.alias}.geo_value) as count") |
| 524 | + |
| 525 | + if geo_type == "only-county": |
| 526 | + q.where(geo_type="county") |
| 527 | + q.conditions.append('geo_value not like "%000"') |
| 528 | + else: |
| 529 | + q.where(geo_type=geo_type) |
| 530 | + q.where_source_signal_pairs("source", "signal", signal) |
| 531 | + q.where_time_pairs("time_type", "time_value", [TimePair("day", [time_window])]) |
| 532 | + q.group_by = "c.source, c.signal, c.time_value" |
| 533 | + |
| 534 | + _handle_lag_issues_as_of(q, None, None, None) |
| 535 | + |
| 536 | + return execute_query(q.query, q.params, fields_string, fields_int, []) |
0 commit comments