Skip to content

Getting Started

BrianThomasRoss edited this page May 20, 2020 · 3 revisions

Getting Started

Thank you for taking the time to consider contributing to this project. The following documentation has been compiled in an attempt to assist you in getting up and running with the project as quickly and painlessly as possible.

Ways to Contribute

We are thankful for and welcome contributions from anyone who wishes to volunteer their time. Among the most valuable contributions to the project are those which improve documentation and testing. If you find errors or typo's in the documentation please submit a pull request.

Participating on the issue tracker also extremely valuable. Reproducing bugs, or giving a up or own to suggestions you agree or disagree with is a great way to let the voice of the community be heard.

Core changes to project structure or functionality must be submitted via an

Installation

This project supports and adheres to the recommendations set forth by PEP517. As such, poetry has been selected for dependency management and specifying build system requirements. Detailed instructions for installing poetry can be found here.

Once you have poetry install getting the dependencies installed is as simples as:

cd /path/to/CHIME-2

poetry install

By default poetry will install the project package to instruction poetry not to do so use the --no-root instruction with poetry install. If you have any extra developer dependencies not found in the pyproject.toml use the command poetry add [packages] --dev. To enter a shell with the configured environment use poetry shell. For more information on working with poetry seek out their detailed documentation here.

Project Structure

At a base level the project can be thought of consisting of 3 main components:

  1. The forecasting model itself

    This is the work of the Predictive Healthcare team at Penn Medicine and contributors to their repository which can be found at https://www.github.com/pennsignals/chime_sims

    • Changes to the model occur through this repository, and are up to the sole discretion of the Predictive Healthcare team.
  2. The model interface

    For ease of development we have created an interface which allows for interacting with the model produce by Penn Medicine in the context of object-oriented programming.

    • Enhancements to the interface can be proposed here via the appropriate channel
    • Changes to the interface should ensure that they do not in anyway change the results, or outcome of the model. In simple terms they should be aesthetic in nature.
  3. The web application

    This is the core scope of this project. Creating a web facing application which allows for interacting with the forecasting model.

    • Enhancements can be proposed and will be earnestly considered on a case-by-case basis

Design Principles

SOLID is an acronym for a set of five design principles which when combined epitomize OOP. When properly implemented these principles allow developers to create a code base which is easily maintainable and extensible.

The acronym stands for:

  • Single-responsiblity principle:
    • A class should have one and only one job
  • Open-closed principle:
    • Objects should be open for extension closed for modification
  • Liskov substitution principle:
    • A child class should be able to substitute for the parent
  • Interface segregation principle:
    • A client should not depend on methods it does not use
  • Dependency Inversion Principle:
    • High level modules rely on abstractions not lower level modules

DRY

  • Don't Repeat Yourself - Every piece of knowledge should have a single unambiguous representation within a system
  • Wikipedia

KISS

Keep it simple, stupid! - Keep your methods small, code simple, each method or function should solve a single problem

YAGNI

You aren't gonna need it - Write the code needed for the current situation

The Zen of Python

import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Model API

The model API exists to provide ease of access, and usability to developers while interfacing with the model produced by Penn Medicine. Any modifications to this interface should take care to ensure the validity of the model, and as such will be heavily scrutinized. Those unfamiliar with predictive modeling techniques should seek out any of the many resources available online.

Here are some excellent resources to that end:


The API is broken down into the following components:

  • parameter
  • validator
  • model
  • simulation

Parameters

These are the model parameters interpreted as class objects. The model parameters are handled globally by the ChimeParameters class, which attempts to preserve the validity of the model by treating each set of parameters as an immutable object.

Consider the following:

We have the parameters foo, bar, and baz with values as described below

ChimeParameters.foo.set(37.3)
ChimeParameters.bar.set("spam")
ChimeParameters.baz.set(42)

Each parameter has the following values

Attribute Description
key "name" assigned to the parameter
dtype parameter data type
default_value default value for the parameter
distribution probability distribution of the parameter
validators a list of callable functions which validate parameter values
description short string type description of the parameter

This metadata is accessible through -

ChimeParameters.<parameter>.get.<attribute>

ChimeParameters.foo.get.dtype
float

Current global parameter state can also be accessed with the same dot syntax. For example

ChimeParameters.foo.get.current

using

ChimeParameters.all

will return

Parameters(foo=foobar, bar="spam", baz=42)

Web Application

The chime2 web application can be broken down into two main components:

  • the front-end, which is a reactive dashboard built using Plotly's dash
  • the back-end, which is a flask server utilizing several

Both of these components fit swimmingly into the Model-View-Controller design pattern and it is enforced throughout.

File Structure Outline of the Application

(without initialization files)

├── app
│  ├── dashboard
│  │  │
│  │  ├── callback
│  │  ├── component
│  │  ├── page
│  │  ├── service
│  │  └── utils
│  ├── server
│  │  │
│  │  ├── dto
│  │  ├── model
│  │  ├── route
│  │  ├── service
│  │  └── extensions.py
│  ├── _config.py
│  └── _typing.py
├── assets
├── bin
│  └── install.sh
├── localization
│  └── en
├── var
│   └── chime.log
└── chime2.py

Dashboard


Dash instance and subcomponents defined here and downstream.

callback

Callbacks are controllers, they manage the flow of information from view to model. Callbacks should be associated with a component, and should reside under a top level class object the same name as the component to which they are associated. One callback per method.

component

components define the view portion of the application, a component may consist of subcomponents, but an entire page is never a component - it is a page.

page

Pages define the layout at app endpoints.

service

util