Skip to content

Instantly share code, notes, and snippets.

@teufelweich
Created February 10, 2023 15:16
Show Gist options
  • Save teufelweich/3102a82d883811a331c8c288278456dc to your computer and use it in GitHub Desktop.
Save teufelweich/3102a82d883811a331c8c288278456dc to your computer and use it in GitHub Desktop.
ugly script to calculate body fat percentage with uncertainties
#MIT License
# Copyright (c) 2020 Marius Engelhardt
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import uncertainties
from datetime import date
import numpy as np
def calculate_bfp(fatness: list, age: float, male=True) -> float:
# Calculatebody fat percentage according to Jackson & Pollock https://doi.org/10.1079/BJN19780152
if male:
if len(fatness) == 3: # 3 skinfold thicknesses
k = [1.1093800, -0.0008267, 0.0000016, -0.0002574] # k0 to k2 and k_a for age
R = 0.905 # multiple correlation
standard_error = 0.0077
elif len(fatness) == 5: # 3 skinfold thicknesses, 2 circumferences
k = [1.0990750, -0.0008209, 0.0000026, -0.0002017, -0.005657,
0.018586] # k0 to k2 and k_a for age, k4 for waist circumference, k5 for forearm circumference
R = 0.918
standard_error = 0.0072
else:
raise ValueError(f"No formula for fatness values of length {len(fatness)}")
else:
raise NotImplementedError("Measurements for women not implemented yet.")
S = sum(fatness[:3]) # sum of skinfolds
body_density = k[0] + k[1] * S + k[2] * S ** 2 + k[3] * age
try:
body_density += k[4] * fatness[3] * k[5] * fatness[4]
except IndexError:
pass
body_density = uncertainties.ufloat(body_density, standard_error)
print(f"Body density: {body_density}")
# Brozek 1963
bfp = (4.57 / body_density - 4.142) * 100
print(f"BFP after Brozek: {bfp}")
# Siri 1961
bfp = (4.95 / body_density - 4.50) * 100
print(f"BFP after Siri: {bfp}")
return bfp
def calc_age(date_of_birth):
dob = date.fromisoformat(date_of_birth)
days_per_year = 365.24225 # according to https://pumas.nasa.gov/examples/index.php?id=46
age = date.today() - dob
return age.days / days_per_year
if __name__ == '__main__':
# enter birthday here
age = calc_age("1990-01-01")
print(age)
# enter skinfold thickness in mm into this list
f = [8, 17, 15]
f_u = [uncertainties.ufloat(v, 1) for v in f]
calculate_bfp(f, age)
calculate_bfp(f_u, age)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment