Skip to content

Commit dd287a2

Browse files
authored
Merge pull request #342 from dfarrow0/dfarrow/covid-hosp-facility3
add endpoint `covid_hosp_facility`
2 parents 34ee996 + a512d03 commit dd287a2

File tree

6 files changed

+405
-1
lines changed

6 files changed

+405
-1
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""Integration tests for acquisition of COVID hospitalization facility."""
2+
3+
# standard library
4+
import unittest
5+
from unittest.mock import MagicMock
6+
7+
# first party
8+
from delphi.epidata.acquisition.covid_hosp.common.database import Database
9+
from delphi.epidata.acquisition.covid_hosp.common.test_utils import TestUtils
10+
from delphi.epidata.client.delphi_epidata import Epidata
11+
import delphi.operations.secrets as secrets
12+
13+
# py3tester coverage target (equivalent to `import *`)
14+
__test_target__ = 'delphi.epidata.acquisition.covid_hosp.facility.update'
15+
16+
17+
class AcquisitionTests(unittest.TestCase):
18+
19+
def setUp(self):
20+
"""Perform per-test setup."""
21+
22+
# configure test data
23+
self.test_utils = TestUtils(__file__)
24+
25+
# use the local instance of the Epidata API
26+
Epidata.BASE_URL = 'http://delphi_web_epidata/epidata/api.php'
27+
28+
# use the local instance of the epidata database
29+
secrets.db.host = 'delphi_database_epidata'
30+
secrets.db.epi = ('user', 'pass')
31+
32+
# clear relevant tables
33+
with Database.connect() as db:
34+
with db.new_cursor() as cur:
35+
cur.execute('truncate table covid_hosp_facility')
36+
cur.execute('truncate table covid_hosp_meta')
37+
38+
def test_acquire_dataset(self):
39+
"""Acquire a new dataset."""
40+
41+
# only mock out network calls to external hosts
42+
mock_network = MagicMock()
43+
mock_network.fetch_metadata.return_value = \
44+
self.test_utils.load_sample_metadata()
45+
mock_network.fetch_dataset.return_value = \
46+
self.test_utils.load_sample_dataset()
47+
48+
# make sure the data does not yet exist
49+
with self.subTest(name='no data yet'):
50+
response = Epidata.covid_hosp_facility(
51+
'450822', Epidata.range(20200101, 20210101))
52+
self.assertEqual(response['result'], -2)
53+
54+
# acquire sample data into local database
55+
with self.subTest(name='first acquisition'):
56+
acquired = Update.run(network=mock_network)
57+
self.assertTrue(acquired)
58+
59+
# make sure the data now exists
60+
with self.subTest(name='initial data checks'):
61+
response = Epidata.covid_hosp_facility(
62+
'450822', Epidata.range(20200101, 20210101))
63+
self.assertEqual(response['result'], 1)
64+
self.assertEqual(len(response['epidata']), 1)
65+
row = response['epidata'][0]
66+
self.assertEqual(row['hospital_pk'], '450822')
67+
self.assertEqual(row['collection_week'], 20201030)
68+
self.assertEqual(row['publication_date'], 20201208)
69+
self.assertEqual(row['previous_day_total_ed_visits_7_day_sum'], 536)
70+
self.assertAlmostEqual(row['total_beds_7_day_avg'], 69.3)
71+
self.assertEqual(
72+
row['previous_day_admission_influenza_confirmed_7_day_sum'], -999999)
73+
74+
# expect 94 fields per row (95 database columns, except `id`)
75+
self.assertEqual(len(row), 94)
76+
77+
# re-acquisition of the same dataset should be a no-op
78+
with self.subTest(name='second acquisition'):
79+
acquired = Update.run(network=mock_network)
80+
self.assertFalse(acquired)
81+
82+
# make sure the data still exists
83+
with self.subTest(name='final data checks'):
84+
response = Epidata.covid_hosp_facility(
85+
'450822', Epidata.range(20200101, 20210101))
86+
self.assertEqual(response['result'], 1)
87+
self.assertEqual(len(response['epidata']), 1)

src/client/delphi_epidata.R

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,25 @@ Epidata <- (function() {
571571
return(.request(params))
572572
}
573573

574+
# Fetch COVID hospitalization data for specific facilities
575+
covid_hosp_facility <- function(hospital_pks, collection_weeks, publication_dates) {
576+
# Check parameters
577+
if(missing(hospital_pks) || missing(collection_weeks)) {
578+
stop('`hospital_pks` and `collection_weeks` are both required')
579+
}
580+
# Set up request
581+
params <- list(
582+
source = 'covid_hosp_facility',
583+
hospital_pks = .list(hospital_pks),
584+
collection_weeks = .list(collection_weeks)
585+
)
586+
if(!missing(publication_dates)) {
587+
params$publication_dates <- .list(publication_dates)
588+
}
589+
# Make the API call
590+
return(.request(params))
591+
}
592+
574593
# Export the public methods
575594
return(list(
576595
range = range,
@@ -598,6 +617,7 @@ Epidata <- (function() {
598617
meta = meta,
599618
covidcast = covidcast,
600619
covidcast_meta = covidcast_meta,
601-
covid_hosp = covid_hosp
620+
covid_hosp = covid_hosp,
621+
covid_hosp_facility = covid_hosp_facility
602622
))
603623
})()

src/client/delphi_epidata.coffee

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,5 +430,20 @@ class Epidata
430430
# Make the API call
431431
_request(callback, params)
432432

433+
# Fetch COVID hospitalization data for specific facilities
434+
@covid_hosp_facility: (callback, hospital_pks, collection_weeks, publication_dates) ->
435+
# Check parameters
436+
unless hospital_pks? and collection_weeks?
437+
throw { msg: '`hospital_pks` and `collection_weeks` are both required' }
438+
# Set up request
439+
params =
440+
'source': 'covid_hosp_facility'
441+
'hospital_pks': _list(hospital_pks)
442+
'collection_weeks': _list(collection_weeks)
443+
if publication_dates?
444+
params.publication_dates = _list(publication_dates)
445+
# Make the API call
446+
_request(callback, params)
447+
433448
# Export the API to the global environment
434449
(exports ? window).Epidata = Epidata

src/client/delphi_epidata.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,32 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
634634
} // Make the API call
635635

636636

637+
return _request(callback, params);
638+
} // Fetch COVID hospitalization data for specific facilities
639+
640+
}, {
641+
key: "covid_hosp_facility",
642+
value: function covid_hosp_facility(callback, hospital_pks, collection_weeks, publication_dates) {
643+
var params; // Check parameters
644+
645+
if (!(hospital_pks != null && collection_weeks != null)) {
646+
throw {
647+
msg: '`hospital_pks` and `collection_weeks` are both required'
648+
};
649+
} // Set up request
650+
651+
652+
params = {
653+
'source': 'covid_hosp_facility',
654+
'hospital_pks': _list(hospital_pks),
655+
'collection_weeks': _list(collection_weeks)
656+
};
657+
658+
if (publication_dates != null) {
659+
params.publication_dates = _list(publication_dates);
660+
} // Make the API call
661+
662+
637663
return _request(callback, params);
638664
}
639665
}]);

src/client/delphi_epidata.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,3 +624,22 @@ def covid_hosp(states, dates, issues=None):
624624
params['issues'] = Epidata._list(issues)
625625
# Make the API call
626626
return Epidata._request(params)
627+
628+
# Fetch COVID hospitalization data for specific facilities
629+
@staticmethod
630+
def covid_hosp_facility(
631+
hospital_pks, collection_weeks, publication_dates=None):
632+
"""Fetch COVID hospitalization data for specific facilities."""
633+
# Check parameters
634+
if hospital_pks is None or collection_weeks is None:
635+
raise Exception('`hospital_pks` and `collection_weeks` are both required')
636+
# Set up request
637+
params = {
638+
'source': 'covid_hosp_facility',
639+
'hospital_pks': Epidata._list(hospital_pks),
640+
'collection_weeks': Epidata._list(collection_weeks),
641+
}
642+
if publication_dates is not None:
643+
params['publication_dates'] = Epidata._list(publication_dates)
644+
# Make the API call
645+
return Epidata._request(params)

0 commit comments

Comments
 (0)