Spaces:
Sleeping
Sleeping
import numpy as np | |
import plotly.graph_objs as go | |
import plotly.io as pio | |
def calculate_fat_free_mass(weight_kg, body_fat_percentage): | |
""" | |
Calculate fat-free mass in kilograms. | |
:param weight_kg: Weight in kilograms [kg]. | |
:param body_fat_percentage: Body fat percentage [%]. | |
:return: Fat-free mass in kilograms [kg]. | |
""" | |
fat_free_mass = weight_kg * (1 - (body_fat_percentage / 100)) | |
return fat_free_mass | |
def calculate_ffmi(fat_free_mass_kg, height_m): | |
""" | |
Calculate FFMI (Fat-Free Mass Index). | |
:param fat_free_mass_kg: Fat-free mass in kilograms [kg]. | |
:param height_m: Height in meters [m]. | |
:return: FFMI in kg/m². | |
""" | |
ffmi = fat_free_mass_kg / (height_m ** 2) | |
return ffmi | |
def plot_ffmi_curves(height_m, gender): | |
""" | |
Generate a plot of FFMI (Fat-Free Mass Index) curves based on weight | |
and body fat percentage for a specified gender. | |
:param height_m: Height of the individual in meters [m]. | |
:param gender: Gender of the individual ('Male' or 'Female'), which determines | |
the FFMI ranges used for categorization. | |
:return: A Plotly Figure object containing the scatter plot of FFMI curves. | |
""" | |
weight_kg_range = np.linspace(45, 160, 100, endpoint=True) | |
body_fat_percentage_range = np.linspace(1, 50, 100, endpoint=True) | |
if gender == "Male": | |
ffmi_ranges = [ | |
{"min": 0, "max": 18, "description": "Below average", "color": "blue"}, | |
{"min": 18, "max": 20, "description": "Average", "color": "green"}, | |
{"min": 20, "max": 22, "description": "Above average", "color": "yellow"}, | |
{"min": 22, "max": 23, "description": "Excellent", "color": "orange"}, | |
{"min": 23, "max": 26, "description": "Superior", "color": "red"}, | |
{"min": 26, "max": 28, "description": "Suspicion of FAKEE", "color": "purple"}, | |
{"min": 28, "max": float("inf"), "description": "FAKEE", "color": "black"} | |
] | |
else: | |
ffmi_ranges = [ | |
{"min": 0, "max": 15, "description": "Below average", "color": "blue"}, | |
{"min": 15, "max": 17, "description": "Average", "color": "green"}, | |
{"min": 17, "max": 18, "description": "Above average", "color": "yellow"}, | |
{"min": 18, "max": 19, "description": "Excellent", "color": "orange"}, | |
{"min": 19, "max": 21.5, "description": "Superior", "color": "red"}, | |
{"min": 21.5, "max": 25, "description": "Suspicion of FAKEE", "color": "purple"}, | |
{"min": 25, "max": float("inf"), "description": "FAKEE", "color": "black"} | |
] | |
fig = go.Figure() | |
for ffmi_range in ffmi_ranges: | |
weight_kg_values = [] | |
body_fat_values = [] | |
ffmi_values = [] | |
for weight in weight_kg_range: | |
for body_fat_percentage in body_fat_percentage_range: | |
fat_free_mass = calculate_fat_free_mass(weight, body_fat_percentage) | |
ffmi = calculate_ffmi(fat_free_mass, height_m) | |
if ffmi_range["min"] <= ffmi < ffmi_range["max"]: | |
weight_kg_values.append(weight) | |
body_fat_values.append(body_fat_percentage) | |
ffmi_values.append(ffmi) | |
fig.add_trace(go.Scatter( | |
x=weight_kg_values, | |
y=body_fat_values, | |
mode='markers', | |
name=ffmi_range["description"], | |
marker=dict( | |
color=ffmi_range.get("marker_color", ffmi_range["color"]), | |
size=5, opacity=0.6, | |
line=dict(color=ffmi_range.get("line_color", ffmi_range["color"])) | |
), | |
hovertext=[ | |
f'FFMI: {ffmi:.2f}<br>Weight: {weight_kg:.2f}<br>BodyFat: {body_fat:.2f}<br>{ffmi_range["description"]}' for ffmi,weight_kg, body_fat in | |
zip(ffmi_values, weight_kg_values, body_fat_values)], | |
hoverinfo='text' | |
)) | |
fig.update_layout( | |
title='FFMI Curves for Different Body Fat Percentages and Weight', | |
xaxis_title='Weight (kg)', | |
yaxis_title='Body Fat Percentage (%)', | |
legend_title='FFMI Range', | |
hovermode='closest', | |
template='plotly_dark' | |
) | |
return fig | |