Repository: CodeForPhilly/chime (python)

Issue:
[bug] Incorrect doubling time for social distancing values above 63%
### STR
1. Load CHIME (https://penn-chime.phl.io/)
2. Set `Social distancing (% reduction in social contact)` to a value below 64 while leaving other values at the default.
2. Repeat step 2 with a value above 63

### Observed
Doubling times are negative when the social distancing value is greater than 63%

Social Distancing (%) | Doubling Time (days) | Rt
-- | -- | --
0 | 6 | 2.71
25 | 9.7 | 2.04
50 | 27.5 | 1.36
60 | 113.5 | 1.09
63 | 2229.4 | 1
64 | -425.4 | 0.98

### Expected
Doubling times are always positive. When `Rt < 1`, unit of time should still be positive and the summary text should indicate that infections will halve over the period of time, not double.

Pull request:
Update to mitigation summary text for `Rt < 1` (issue 155)
- Changed `display_header` in `src/penn_chime/presentation.py` so mitigation text for values of `Rt < 1` mention halving (vs doubling) and report a positive unit of time.
- Changed `tests/test_app.py` to add `test_mitigation_statement` to test `Rt` values `>= 1` are described as doubling and `< 1` is described as halving.
    
Fixes #155


Patch:
diff --git a/src/penn_chime/presentation.py b/src/penn_chime/presentation.py
index 3547b3b..aea0e74 100644
--- a/src/penn_chime/presentation.py
+++ b/src/penn_chime/presentation.py
@@ -63,7 +63,7 @@ An initial doubling time of **{doubling_time}** days and a recovery time of **{r
 **{r_naught:.2f}**.
 
 **Mitigation**: A **{relative_contact_rate:.0%}** reduction in social contact after the onset of the
-outbreak reduces the doubling time to **{doubling_time_t:.1f}** days, implying an effective $R_t$ of **${r_t:.2f}$**.
+outbreak **{impact_statement:s} {doubling_time_t:.1f}** days, implying an effective $R_t$ of **${r_t:.2f}$**.
 """.format(
             total_infections=m.infected,
             initial_infections=p.known_infected,
@@ -77,7 +77,8 @@ outbreak reduces the doubling time to **{doubling_time_t:.1f}** days, implying a
             doubling_time=p.doubling_time,
             relative_contact_rate=p.relative_contact_rate,
             r_t=m.r_t,
-            doubling_time_t=m.doubling_time_t,
+            doubling_time_t=abs(m.doubling_time_t),
+            impact_statement=("halves the infections every" if m.r_t < 1 else "reduces the doubling time to")
         )
     )
 


Test patch:
diff --git a/tests/test_app.py b/tests/test_app.py
index 0d4c7b8..2281edb 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -73,6 +73,33 @@ def test_the_rest_of_header_shows_up():
     ), "The whole header should render"
 
 
+def test_mitigation_statement():
+    st.cleanup()
+    expected_doubling = "outbreak **reduces the doubling time to 7.8** days"
+    display_header(st, MODEL, PARAM)
+    assert [s for s in st.render_store if expected_doubling in s]
+    # assert len((list(filter(lambda s: expected_doubling in s, st.render_store))))
+    st.cleanup()
+    expected_halving = "outbreak **halves the infections every 51.9** days"
+    halving_params = Parameters(
+        current_hospitalized=100,
+        doubling_time=6.0,
+        known_infected=5000,
+        market_share=0.05,
+        relative_contact_rate=0.7,
+        susceptible=500000,
+        hospitalized=RateLos(0.05, 7),
+        icu=RateLos(0.02, 9),
+        ventilated=RateLos(0.01, 10),
+        n_days=60,
+    )
+    halving_model = SimSirModel(halving_params)
+    display_header(st, halving_model, halving_params)
+    assert [s for s in st.render_store if expected_halving in s]
+    #assert len((list(filter(lambda s: expected_halving in s, st.render_store))))
+    st.cleanup()
+
+
 st.cleanup()