edc-vitals 1.0.0__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edc_vitals/calculators/__init__.py +1 -0
- edc_vitals/calculators/bmi.py +69 -0
- edc_vitals/form_validators/__init__.py +4 -1
- edc_vitals/form_validators/bmi_form_validator_mixin.py +19 -0
- edc_vitals/form_validators/{weight_height_bmi_form_validator_mixin.py → weight_height_with_bmi_form_validator_mixin.py} +2 -1
- edc_vitals/model_mixins/weight_height_bmi_model_mixin.py +1 -1
- edc_vitals/tests/tests/test_calculators.py +77 -0
- {edc_vitals-1.0.0.dist-info → edc_vitals-1.1.1.dist-info}/METADATA +4 -3
- {edc_vitals-1.0.0.dist-info → edc_vitals-1.1.1.dist-info}/RECORD +13 -9
- {edc_vitals-1.0.0.dist-info → edc_vitals-1.1.1.dist-info}/WHEEL +1 -1
- edc_vitals-1.1.1.dist-info/licenses/AUTHORS +2 -0
- edc_vitals-1.0.0.dist-info/AUTHORS +0 -1
- {edc_vitals-1.0.0.dist-info → edc_vitals-1.1.1.dist-info/licenses}/LICENSE +0 -0
- {edc_vitals-1.0.0.dist-info → edc_vitals-1.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
from .bmi import BMI, CalculatorError, calculate_bmi
|
@@ -0,0 +1,69 @@
|
|
1
|
+
from dateutil.relativedelta import relativedelta
|
2
|
+
from edc_utils import age, get_utcnow
|
3
|
+
from edc_utils.round_up import round_half_away_from_zero
|
4
|
+
|
5
|
+
__all__ = ["calculate_bmi", "BMI", "CalculatorError"]
|
6
|
+
|
7
|
+
|
8
|
+
class CalculatorError(Exception):
|
9
|
+
pass
|
10
|
+
|
11
|
+
|
12
|
+
class BMI:
|
13
|
+
"""Calculate BMI, raise if not adult."""
|
14
|
+
|
15
|
+
def __init__(
|
16
|
+
self,
|
17
|
+
weight_kg=None,
|
18
|
+
height_cm=None,
|
19
|
+
lower_bmi_value=None,
|
20
|
+
upper_bmi_value=None,
|
21
|
+
dob=None,
|
22
|
+
report_datetime=None,
|
23
|
+
**kwargs,
|
24
|
+
):
|
25
|
+
if not weight_kg or not height_cm:
|
26
|
+
raise CalculatorError(f"Unable to calculate BMI. Got {weight_kg}kg, {height_cm}cm")
|
27
|
+
if age(dob, report_datetime).years < 18:
|
28
|
+
raise CalculatorError("Unable to calculate BMI. Got age<18")
|
29
|
+
self.lower = float(lower_bmi_value or 5.0)
|
30
|
+
self.upper = float(upper_bmi_value or 75.0)
|
31
|
+
self.weight = float(weight_kg)
|
32
|
+
self.height = float(height_cm) / 100.0
|
33
|
+
self.raw_bmi_value = self.weight / (self.height**2)
|
34
|
+
if not (self.lower <= self.raw_bmi_value <= self.upper):
|
35
|
+
raise CalculatorError(
|
36
|
+
"BMI value is absurd. "
|
37
|
+
f"Using {self.weight}kg, {self.height}m. Got {self.value}."
|
38
|
+
)
|
39
|
+
|
40
|
+
@property
|
41
|
+
def value(self):
|
42
|
+
return round_half_away_from_zero(self.raw_bmi_value, 4)
|
43
|
+
|
44
|
+
|
45
|
+
def calculate_bmi(
|
46
|
+
weight_kg=None,
|
47
|
+
height_cm=None,
|
48
|
+
lower_bmi_value=None,
|
49
|
+
upper_bmi_value=None,
|
50
|
+
dob=None,
|
51
|
+
report_datetime=None,
|
52
|
+
**kwargs,
|
53
|
+
):
|
54
|
+
"""Returns a BMI instance or None.
|
55
|
+
|
56
|
+
Assumes adult dob (18) if dob not provided."""
|
57
|
+
bmi = None
|
58
|
+
if height_cm and weight_kg:
|
59
|
+
report_datetime = report_datetime or get_utcnow()
|
60
|
+
bmi = BMI(
|
61
|
+
weight_kg=weight_kg,
|
62
|
+
height_cm=height_cm,
|
63
|
+
lower_bmi_value=lower_bmi_value,
|
64
|
+
upper_bmi_value=upper_bmi_value,
|
65
|
+
dob=dob or report_datetime - relativedelta(years=18),
|
66
|
+
report_datetime=report_datetime,
|
67
|
+
**kwargs,
|
68
|
+
)
|
69
|
+
return bmi
|
@@ -1,2 +1,5 @@
|
|
1
1
|
from .blood_pressure_form_validator_mixin import BloodPressureFormValidatorMixin
|
2
|
-
from .
|
2
|
+
from .bmi_form_validator_mixin import BmiFormValidatorMixin
|
3
|
+
from .weight_height_with_bmi_form_validator_mixin import (
|
4
|
+
WeightHeightBmiFormValidatorMixin,
|
5
|
+
)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from django import forms
|
2
|
+
|
3
|
+
from ..calculators import CalculatorError, calculate_bmi
|
4
|
+
|
5
|
+
__all__ = ["BmiFormValidatorMixin"]
|
6
|
+
|
7
|
+
|
8
|
+
class BmiFormValidatorMixin:
|
9
|
+
def validate_bmi(self, **kwargs):
|
10
|
+
try:
|
11
|
+
bmi = calculate_bmi(
|
12
|
+
height_cm=self.cleaned_data.get("height"),
|
13
|
+
weight_kg=self.cleaned_data.get("weight"),
|
14
|
+
**self.cleaned_data,
|
15
|
+
**kwargs,
|
16
|
+
)
|
17
|
+
except CalculatorError as e:
|
18
|
+
raise forms.ValidationError(e)
|
19
|
+
return bmi
|
@@ -0,0 +1,77 @@
|
|
1
|
+
from dateutil.relativedelta import relativedelta
|
2
|
+
from django import forms
|
3
|
+
from django.test import TestCase, tag
|
4
|
+
from edc_constants.constants import BLACK, MALE
|
5
|
+
from edc_form_validators import FormValidator
|
6
|
+
from edc_utils import get_utcnow
|
7
|
+
from edc_utils.round_up import round_half_away_from_zero
|
8
|
+
|
9
|
+
from edc_vitals.calculators import BMI, CalculatorError, calculate_bmi
|
10
|
+
from edc_vitals.form_validators import BmiFormValidatorMixin
|
11
|
+
|
12
|
+
|
13
|
+
class TestCalculators(TestCase):
|
14
|
+
@tag("1")
|
15
|
+
def test_bmi_calculator(self):
|
16
|
+
dob = get_utcnow() - relativedelta(years=25)
|
17
|
+
self.assertRaises(CalculatorError, BMI, weight_kg=56, height_cm=None)
|
18
|
+
try:
|
19
|
+
calculate_bmi(weight_kg=56, height_cm=None, dob=dob)
|
20
|
+
except CalculatorError:
|
21
|
+
self.fail("CalculatorError unexpectedly raised ")
|
22
|
+
|
23
|
+
for func in [BMI, calculate_bmi]:
|
24
|
+
with self.subTest(func=func):
|
25
|
+
self.assertRaises(
|
26
|
+
CalculatorError,
|
27
|
+
func,
|
28
|
+
weight_kg=56,
|
29
|
+
height_cm=1.50,
|
30
|
+
dob=dob,
|
31
|
+
report_datetime=get_utcnow(),
|
32
|
+
)
|
33
|
+
try:
|
34
|
+
bmi = func(
|
35
|
+
weight_kg=56, height_cm=150, dob=dob, report_datetime=get_utcnow()
|
36
|
+
)
|
37
|
+
except CalculatorError as e:
|
38
|
+
self.fail(f"CalculatorError unexpectedly raises. Got {e}")
|
39
|
+
else:
|
40
|
+
self.assertEqual(round_half_away_from_zero(bmi.value, 2), 24.89)
|
41
|
+
|
42
|
+
@tag("1")
|
43
|
+
def test_bmi_form_validator(self):
|
44
|
+
data = dict(
|
45
|
+
gender=MALE,
|
46
|
+
ethnicity=BLACK,
|
47
|
+
age_in_years=30,
|
48
|
+
)
|
49
|
+
|
50
|
+
class BmiFormValidator(BmiFormValidatorMixin, FormValidator):
|
51
|
+
pass
|
52
|
+
|
53
|
+
# not enough data
|
54
|
+
form_validator = BmiFormValidator(cleaned_data=data)
|
55
|
+
bmi = form_validator.validate_bmi()
|
56
|
+
self.assertIsNone(bmi)
|
57
|
+
|
58
|
+
# calculates
|
59
|
+
data.update(
|
60
|
+
weight=56,
|
61
|
+
height=150,
|
62
|
+
dob=get_utcnow() - relativedelta(years=30),
|
63
|
+
report_datetime=get_utcnow(),
|
64
|
+
)
|
65
|
+
form_validator = BmiFormValidator(cleaned_data=data)
|
66
|
+
bmi = form_validator.validate_bmi()
|
67
|
+
self.assertEqual(bmi.value, 24.8889)
|
68
|
+
|
69
|
+
# calculation error
|
70
|
+
data.update(
|
71
|
+
weight=56,
|
72
|
+
height=1.5,
|
73
|
+
dob=get_utcnow() - relativedelta(years=25),
|
74
|
+
report_datetime=get_utcnow(),
|
75
|
+
)
|
76
|
+
form_validator = BmiFormValidator(cleaned_data=data)
|
77
|
+
self.assertRaises(forms.ValidationError, form_validator.validate_bmi)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: edc-vitals
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.1.1
|
4
4
|
Summary: Classes for BP, weight, etc for clinicedc/edc projects
|
5
5
|
Home-page: https://github.com/clinicedc/edc-vitals
|
6
6
|
Author: Erik van Widenfelt
|
@@ -9,7 +9,7 @@ License: GPL license, see LICENSE
|
|
9
9
|
Keywords: django edc vitals,clinicedc,clinical trials
|
10
10
|
Classifier: Environment :: Web Environment
|
11
11
|
Classifier: Framework :: Django
|
12
|
-
Classifier: Framework :: Django :: 5.
|
12
|
+
Classifier: Framework :: Django :: 5.2
|
13
13
|
Classifier: Intended Audience :: Developers
|
14
14
|
Classifier: Intended Audience :: Science/Research
|
15
15
|
Classifier: Operating System :: OS Independent
|
@@ -19,6 +19,7 @@ Requires-Python: >=3.12
|
|
19
19
|
Description-Content-Type: text/x-rst
|
20
20
|
License-File: LICENSE
|
21
21
|
License-File: AUTHORS
|
22
|
+
Dynamic: license-file
|
22
23
|
|
23
24
|
|
24
25
|
|pypi| |actions| |codecov| |downloads|
|
@@ -2,13 +2,16 @@ edc_vitals/__init__.py,sha256=k7pm4XmS32dJU4XRYKHJrzEkA7CuQ75_Jj7nLkvUiDY,117
|
|
2
2
|
edc_vitals/apps.py,sha256=AvV-Dwgo6KRe5VhriAP8CYM6OJG6kGh2_1BwQ6Wmc8o,145
|
3
3
|
edc_vitals/utils.py,sha256=vXid44KUXxeaSyund_y5MNXc5DFJs052_PwUAjszE2k,1384
|
4
4
|
edc_vitals/validators.py,sha256=9bNs-txdfA-v9iPS8mzFy_HLlY12jFcUHoy_bDbEpH0,164
|
5
|
-
edc_vitals/
|
5
|
+
edc_vitals/calculators/__init__.py,sha256=H2gtS_5Aw7r4kELDmNy3AtNqTPbaNUDMM0OzSx3ZiU4,53
|
6
|
+
edc_vitals/calculators/bmi.py,sha256=DFJRChDR8zXL7WLNanJPUo6SE3Do44srFgIsb3TiLOQ,2055
|
7
|
+
edc_vitals/form_validators/__init__.py,sha256=Kd3uFE_Qe2MOWsyQG72gfG62HGNw-8GyqKmgA8uIjWA,241
|
6
8
|
edc_vitals/form_validators/blood_pressure_form_validator_mixin.py,sha256=RvIGvukC7RubqH7f6DUVArNUL__BVoTdRq1L4vPfX2A,1563
|
7
|
-
edc_vitals/form_validators/
|
9
|
+
edc_vitals/form_validators/bmi_form_validator_mixin.py,sha256=dQPb3CrvkRdSXJtDUbZ33Z1dMYrybWwrK9WvPbdjhZA,529
|
10
|
+
edc_vitals/form_validators/weight_height_with_bmi_form_validator_mixin.py,sha256=zJZJgyQ1KP5LZMPowf5Rs009Lq2sybm65UoHNP6pBxU,460
|
8
11
|
edc_vitals/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
12
|
edc_vitals/model_mixins/__init__.py,sha256=Nvu9-rNd0P5efB7KS74OHUE_AMJL_qtjUepEt0BuT8I,177
|
10
13
|
edc_vitals/model_mixins/blood_pressure_model_mixin.py,sha256=50J3xs3Po5IRaUodFs6qtPWzwOUckWhExVUEM25Ri4g,2052
|
11
|
-
edc_vitals/model_mixins/weight_height_bmi_model_mixin.py,sha256=
|
14
|
+
edc_vitals/model_mixins/weight_height_bmi_model_mixin.py,sha256=DjxSSlMLy2FCr1LvJ7ppCZFe4-HxWSs0ZuXta6VtvQc,1101
|
12
15
|
edc_vitals/models/__init__.py,sha256=kojBDnW6CZiBORa4hn7CtVl0D6pku3i7M1t8uVoVhWg,210
|
13
16
|
edc_vitals/models/fields/__init__.py,sha256=2mpaP8hoI0-4c5vlZZVoUFvGuy9rjfT7im3k8jykDyU,327
|
14
17
|
edc_vitals/models/fields/blood_pressure.py,sha256=5MLJcvNf6yOk5LJe1wmPCku4rpaA6JZrHrWoKX5EmiY,1369
|
@@ -32,13 +35,14 @@ edc_vitals/tests/etc/user-salt-local.key,sha256=8yXyuxh-EstHWMSkwqSNV7gakEQLnQLo
|
|
32
35
|
edc_vitals/tests/etc/user-salt-restricted.key,sha256=w835r6mLFeL4IIYoovEVU8JfXOw8VR1Moh15gaIJJww,256
|
33
36
|
edc_vitals/tests/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
34
37
|
edc_vitals/tests/tests/test_blood_pressure.py,sha256=dablDybatc_Z_4TxLdJoYzbe1ZVQ7dW3u6gAprAgB3w,7591
|
38
|
+
edc_vitals/tests/tests/test_calculators.py,sha256=op0P4WbP-OAAr-73Usaod-xHl3Ptikcf8n0AmoirnsQ,2674
|
35
39
|
edc_vitals/tests/tests/test_heart_rate.py,sha256=0-FpuWg1iDSRw6EmfFhH8u4OmvH9o1Ss_EKYwfOaVXI,1804
|
36
40
|
edc_vitals/tests/tests/test_respiratory_rate.py,sha256=-R7XIIw6gHd0u69AHdOcEgFjLQrjdYdsGbf7B3d_GwU,1906
|
37
41
|
edc_vitals/tests/tests/test_temperature.py,sha256=KYK-PrvCQIsNUPajUhl0R1FmuspwEYhxIZtc-TKgRjc,3518
|
38
42
|
edc_vitals/tests/tests/test_weight_height_bmi.py,sha256=aMlxxvdbeNAKX8IMp6x6zxRmjd3oL_mO8nCE06vyBV4,2322
|
39
|
-
edc_vitals-1.
|
40
|
-
edc_vitals-1.
|
41
|
-
edc_vitals-1.
|
42
|
-
edc_vitals-1.
|
43
|
-
edc_vitals-1.
|
44
|
-
edc_vitals-1.
|
43
|
+
edc_vitals-1.1.1.dist-info/licenses/AUTHORS,sha256=cRyIwmYX7rwmqBPh9_4EA9hZ_kw6RWjNSGOW4RpIoiM,102
|
44
|
+
edc_vitals-1.1.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
45
|
+
edc_vitals-1.1.1.dist-info/METADATA,sha256=oEG4Rboi936rDDYzyWyICTagF22x4CBpYnYcbx1jmmE,1779
|
46
|
+
edc_vitals-1.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
47
|
+
edc_vitals-1.1.1.dist-info/top_level.txt,sha256=hwo2JnqOF-wcBFoQz-fEhszjPca4sZ9a3QDF7BHGFhI,11
|
48
|
+
edc_vitals-1.1.1.dist-info/RECORD,,
|
@@ -1 +0,0 @@
|
|
1
|
-
Erik van Widenfelt <ew2789@gmail.com>
|
File without changes
|
File without changes
|