Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for new feature #17

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# IDEs
.vscode/
.idea/
.venv/

# Intermediate Coverage file
.coverage
Expand Down
37 changes: 27 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
# Introduction
# Inflam
![Continuous Integration build in GitHub Actions](https://github.com/JBello1610/python-intermediate-inflammation/workflows/CI/badge.svg?branch=main)

This is a template software project repository used by the [Intermediate Research Software Development Skills In Python](https://github.com/carpentries-incubator/python-intermediate-development).
Inflam is a data management system written in Python that manages trial data used in clinical inflammation studies.

## Purpose
## Main Features
Here are some key features of Inflam:

This repository is intended to be used as a code template which is copied by learners at [Intermediate Research Software Development Skills In Python](https://github.com/carpentries-incubator/python-intermediate-development) course.
This can be done using the `Use this template` button towards the top right of this repo's GitHub page.
- Provide basic statistical analyses over clinical trial data
- Ability ti woek on trial data in Comma0-Seperated Value (CSV) format.
- Generate plots of trial data.
- Analytical functions and views can be easily extended based on its Model-View-Controller architecture

This software project is not finished, is currently failing to run and contains some code style issues. It is used as a starting point for the course - issues will be fixed and code will be added in a number of places during the course by learners in their own copies of the repository, as course topics are introduced.
## Prerequisites
Inflam requires the following Python packages:

## Tests
- [NumPy](https://www.numpy.org/) - makes use of NumPy's statistical functions.
- [Matplotlib](https://matplotlib.org/stable/index.html) - uses Matplotlib to generate statistical plots

Several tests have been implemented already, some of which are currently failing.
These failing tests set out the requirements for the additional code to be implemented during the workshop.
The following optional packages are required to run Inflam's unit tests:

The tests should be run using `pytest`, which will be introduced during the workshop.
- [pytest](https://docs.pytest.org/stable/) - Inflam's unit tests are written using pytest
- [pytest-cov](https://pypi.org/project/pytest-cov/) - Adds test coverage stats to unit testing

## Installation
Can be installed and run by cloning this git repository and running the below commands:

```bash
git clone [email protected]:JBello1610/python-intermediate-inflammation.git

cd python-intermediate-inflammation/

python inflammation-analysis.py
```
3 changes: 2 additions & 1 deletion inflammation-analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def main(args):
for filename in InFiles:
inflammation_data = models.load_csv(filename)

view_data = {'average': models.daily_mean(inflammation_data), 'max': models.daily_max(inflammation_data), 'min': models.daily_min(inflammation_data)}
view_data = {'average': models.daily_mean(inflammation_data), 'max': models.daily_max(inflammation_data), 'min': models.daily_min(inflammation_data), **(models.s_dev(inflammation_data))}


views.visualize(view_data)

Expand Down
22 changes: 16 additions & 6 deletions inflammation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

The Model layer is responsible for the 'business logic' part of the software.

Patients' data is held in an inflammation table (2D array) where each row contains
inflammation data for a single patient taken over a number of days
Patients' data is held in an inflammation table (2D array) where each row contains
inflammation data for a single patient taken over a number of days
and each column represents a single day across all patients.
"""

Expand All @@ -16,7 +16,8 @@ def load_csv(filename):

:param filename: Filename of CSV to load
"""
return np.loadtxt(fname=filename, delimiter=',')
return np.loadtxt(fname=filename, delimiter=",")


def load_json(filename):
"""Load a numpy array from a JSON document.
Expand All @@ -34,10 +35,9 @@ def load_json(filename):
:param filename: Filename of CSV to load

"""
with open(filename, 'r', encoding='utf-8') as file:
with open(filename, "r", encoding="utf-8") as file:
data_as_json = json.load(file)
return [np.array(entry['observations']) for entry in data_as_json]

return [np.array(entry["observations"]) for entry in data_as_json]


def daily_mean(data):
Expand All @@ -54,3 +54,13 @@ def daily_min(data):
"""Calculate the daily min of a 2d inflammation data array."""
return np.min(data, axis=0)


def s_dev(data):
"""Computes and returns standard deviation for data."""
mean_of_data = np.mean(data, axis=0)
devs = []
for entry in data:
devs.append((entry - mean_of_data) * (entry - mean_of_data))

standard_dev = sum(devs) / len(data)
return {"standard deviation": np.sqrt(standard_dev)}
30 changes: 22 additions & 8 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
import numpy as np
import numpy.testing as npt
import os
import pytest


def test_daily_mean_zeros():
"""Test that mean function works for an array of zeros."""
from inflammation.models import daily_mean

test_input = np.array([[0, 0],
[0, 0],
[0, 0]])
test_input = np.array([[0, 0], [0, 0], [0, 0]])
test_result = np.array([0, 0])

# Need to use Numpy testing functions to compare arrays
Expand All @@ -22,18 +21,33 @@ def test_daily_mean_integers():
"""Test that mean function works for an array of positive integers."""
from inflammation.models import daily_mean

test_input = np.array([[1, 2],
[3, 4],
[5, 6]])
test_input = np.array([[1, 2], [3, 4], [5, 6]])
test_result = np.array([3, 4])

# Need to use Numpy testing functions to compare arrays
npt.assert_array_equal(daily_mean(test_input), test_result)


def test_load_from_json(tmpdir):
from inflammation.models import load_json
example_path = os.path.join(tmpdir, 'example.json')
with open(example_path, 'w') as temp_json_file:

example_path = os.path.join(tmpdir, "example.json")
with open(example_path, "w") as temp_json_file:
temp_json_file.write('[{"observations":[1, 2, 3]},{"observations":[4, 5, 6]}]')
result = load_json(example_path)
npt.assert_array_equal(result, [[1, 2, 3], [4, 5, 6]])


@pytest.mark.parametrize(
"data, expected_standard_deviation",
[
([0, 0, 0], 0.0),
([1.0, 1.0, 1.0], 0),
([1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 10.0], 2.4088314876309775),
],
)
def test_daily_standard_deviation(data, expected_standard_deviation):
from inflammation.models import s_dev

result_data = s_dev(data)["standard deviation"]
npt.assert_approx_equal(result_data, expected_standard_deviation)