-
Notifications
You must be signed in to change notification settings - Fork 4
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.
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
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.
At a base level the project can be thought of consisting of 3 main components:
-
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.
-
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.
-
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
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
- Don't Repeat Yourself - Every piece of knowledge should have a single unambiguous representation within a system
- Wikipedia
Keep it simple, stupid! - Keep your methods small, code simple, each method or function should solve a single problem
You aren't gonna need it - Write the code needed for the current situation
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!
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 Elements of Statistical Learning. Hastie, R. Tibshirani, and J. Friedman. (2001)
-
Stanford cs229, also taught by Andrew Ng
The API is broken down into the following components:
- parameter
- validator
- model
- simulation
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.foo.get.dtype
float
Current global parameter state can also be accessed with the same dot syntax. For example
ChimeParameters.foo.get.current
using
will return
Parameters(foo=foobar, bar="spam", baz=42)
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.
(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
Dash instance and subcomponents defined here and downstream.
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