<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ariel Shadrac OUEDRAOGO</title>
    <description>The latest articles on DEV Community by Ariel Shadrac OUEDRAOGO (@iamshadrac).</description>
    <link>https://dev.to/iamshadrac</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3732680%2F4c4766ca-3cb6-4f70-8a42-cb68dddca111.png</url>
      <title>DEV Community: Ariel Shadrac OUEDRAOGO</title>
      <link>https://dev.to/iamshadrac</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iamshadrac"/>
    <language>en</language>
    <item>
      <title>Episia: Building an Open-Source Epidemiology Library in Python, Validated Against OpenEpi</title>
      <dc:creator>Ariel Shadrac OUEDRAOGO</dc:creator>
      <pubDate>Wed, 01 Jul 2026 19:22:05 +0000</pubDate>
      <link>https://dev.to/iamshadrac/episia-building-an-open-source-epidemiology-library-in-python-validated-against-openepi-4ap1</link>
      <guid>https://dev.to/iamshadrac/episia-building-an-open-source-epidemiology-library-in-python-validated-against-openepi-4ap1</guid>
      <description>&lt;h2&gt;
  
  
  Why Episia
&lt;/h2&gt;

&lt;p&gt;I am an MD candidate and a self-taught Python developer. Over the past year, working with epidemiological surveillance data in a resource-limited setting exposed a recurring gap: solid statistical epidemiology tooling exists (OpenEpi, R packages), but nothing brought compartmental modeling, biostatistics, surveillance data handling, and reporting together in a single, modern Python API with offline-first design.&lt;/p&gt;

&lt;p&gt;Episia is my attempt to close that gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Episia covers the full analytical workflow, from raw surveillance data to epidemic modeling and automated reporting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;episia&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;epi&lt;/span&gt;

&lt;span class="c1"&gt;# Compartmental model
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;epi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;I0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;E0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;beta&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;5.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gamma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# SEIR Model
#   R0            : 4.900
#   Peak infected : 331,751  at t=84.5
#   Final size    : 99.2%
&lt;/span&gt;
&lt;span class="c1"&gt;# Biostatistics
&lt;/span&gt;&lt;span class="n"&gt;rr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;epi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;risk_ratio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Risk Ratio: 2.667 (1.514-4.696)
&lt;/span&gt;
&lt;span class="c1"&gt;# Automated HTML report
&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;epi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SEIR Burkina Faso 2024&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save_html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;report.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Design decisions worth explaining
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Unified result objects.&lt;/strong&gt; Every function, whether it is a risk ratio or a full SEIR run, returns a rich, serializable result object. This keeps plotting, export, and reporting consistent across the entire library rather than each module inventing its own return shape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validated, not just tested.&lt;/strong&gt; Unit tests confirm the code does what I intended. They do not confirm the statistics are correct. So beyond the test suite (1490+ tests, 84% coverage), Episia's core statistical functions are systematically validated against OpenEpi, an established reference implementation in epidemiology. The full comparison notebook is in the repository, since a validation claim without a reproducible notebook is not worth much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offline by design.&lt;/strong&gt; Episia has zero runtime network dependencies outside an optional DHIS2 connector used to pull surveillance data. In many of the field settings this is built for, connectivity is not something you can assume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dual visualization backend.&lt;/strong&gt; Every plot function accepts &lt;code&gt;backend="plotly"&lt;/code&gt; for interactive exploration or &lt;code&gt;backend="matplotlib"&lt;/code&gt; for publication-quality figures, same code path either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current state
&lt;/h2&gt;

&lt;p&gt;Episia is at v0.1.3, on PyPI (&lt;code&gt;pip install episia&lt;/code&gt;), currently going through pyOpenSci peer review (issue #317), with a preprint on medRxiv. Source is on GitHub under MIT license.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repository: &lt;a href="https://github.com/Xcept-Health/episia" rel="noopener noreferrer"&gt;https://github.com/Xcept-Health/episia&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;a href="https://pypi.org/project/episia/" rel="noopener noreferrer"&gt;https://pypi.org/project/episia/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Preprint: &lt;a href="https://doi.org/10.64898/2026.04.17.26350337" rel="noopener noreferrer"&gt;https://doi.org/10.64898/2026.04.17.26350337&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I am looking for
&lt;/h2&gt;

&lt;p&gt;I would value input on the API design itself, particularly whether the result-object pattern and the module structure (&lt;code&gt;models&lt;/code&gt;, &lt;code&gt;stats&lt;/code&gt;, &lt;code&gt;viz&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;dhis2&lt;/code&gt;) hold up under real use. Testers running it against their own data are especially useful for surfacing edge cases I have not hit yet. Contributions, issues, and pull requests are welcome, and any general recommendations for what would strengthen the library ahead of a 1.0 release are appreciated.&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>datascience</category>
      <category>healthtech</category>
    </item>
  </channel>
</rss>
