This is a WebApp of the Z-Score App available as standalone program for Mac and Windows on GitHub.
It is based on published DXA reference values for children and adults.
How to use:
- Wait about 20 sec until the page is loaded completely.
- Enter the data as described. Fields in the first cell (with *) need to be filled, others can be left empty if no data is available.
- Then click on "Compute".
- The computed Z-Scores and plots will be shown.
Loading ...
Measurement Data | Computed Values | LMS-Plots |
|
| |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
import asyncio
import numpy as np
import scipy.stats
import panel as pn
import pandas as pd
import openpyxl
from panel.io.pyodide import show
from io import StringIO, BytesIO
import os
import zscore_computation as zc
from js import fetch
# import datetime
import time
import math
import datetime
#### --- code to load and save data files from website ---
# import asyncio
# from js import fetch
# url = "https://raw.githubusercontent.com/FlorianKrach/scientific-LMS-zscore-app/master/data/adults_LMS_FMI_gender0.csv"
# response = await fetch(url)
# text = await response.text()
# filename = "text.csv"
# with open(filename, "w") as f:
# f.write(text)
# df = pd.read_csv(filename, index_col=0)
### ---------------------------------------------
#### --- code to load data files from local directory ---
# import asyncio
# from js import fetch
# from io import StringIO
# url = "data/adults_LMS_FMI_gender0.csv"
# response = await fetch(url)
# text = await response.text()
# df = pd.read_csv(StringIO(text), index_col=0)
### ---------------------------------------------
pyscript.write("output", "Loading data ...")
files = ['adults_LMS_appendicular_LMI_gender1.csv',
'adults_LMS_appendicular_LMI_gender0.csv',
'children_LMS_LMI_gender1.csv',
'children_LMS_LMI_gender0.csv',
'children_LMS_fitted_ALMI_gender0.csv',
'children_LMS_fitted_ALMI_gender1.csv',
'adults_LMS_VAT_mass_gender1.csv',
'adults_LMS_VAT_mass_gender0.csv',
'children_LMS_FMI_gender0.csv',
'children_LMS_BMI_gender1.csv',
'children_LMS_BMI_gender0.csv',
'children_LMS_FMI_gender1.csv',
'adults_LMS_LMI_gender1.csv',
'children_LMS_fitted_LMI_gender0.csv',
'children_LMS_fitted_LMI_gender1.csv',
'adults_LMS_LMI_gender0.csv',
'children_LMS_appendicular_LMI_gender0.csv',
'children_LMS_appendicular_LMI_gender1.csv',
'adults_LMS_FM_android_quotient_gynoid_gender1.csv',
'adults_LMS_FM_android_quotient_gynoid_gender0.csv',
'children_LMS_weight_gender1.csv',
'children_LMS_FM_trunk_quotient_limb_gender1.csv',
'adults_LMS_FM_trunk_quotient_limb_gender0.csv',
'adults_LMS_FM_trunk_quotient_limb_gender1.csv',
'children_LMS_FM_trunk_quotient_limb_gender0.csv',
'children_LMS_weight_gender0.csv',
'children_LMS_height_gender1.csv',
'children_LMS_height_gender0.csv',
'children_LMS_percent_FM_gender0.csv',
'children_LMS_percent_FM_gender1.csv',
'children_LMS_fitted_BMI_gender0.csv',
'adults_LMS_FMI_gender0.csv',
'children_LMS_fitted_FMI_gender1.csv',
'children_LMS_fitted_FMI_gender0.csv',
'adults_LMS_FMI_gender1.csv',
'children_LMS_fitted_BMI_gender1.csv']
if not os.path.exists("data1/"):
os.makedirs("data1/")
for filename in files:
url = "data/{}".format(filename)
response = await fetch(url)
text = await response.text()
savefile = "data1/{}".format(filename)
with open(savefile, "w") as f:
f.write(text)
pyscript.write("output", "")
uploadButton = pn.widgets.Button(name='Compute', button_type = 'primary')
textInput_dict = {}
params = ['Birthday', 'Measurement-day', 'Gender', 'LMI', 'FMI',
'FM_android_quotient_gynoid', 'FM_trunk_quotient_limb',
'appendicular_LMI',
'VAT_mass', 'BMI', 'height', 'weight', 'fitted_BMI', 'fitted_FMI',
'fitted_LMI', 'fitted_ALMI']
descs = ['Birthday *', 'Measurement Day *',
'Gender *', 'LMI (kg/m^2)',
'FMI (kg/m^2)', 'FM android / gynoid', 'FM trunk / limb',
'appendicular LMI', 'VAT mass (g)', 'BMI (kg/m^2)', 'height (cm)',
'weight (kg)', 'fitted BMI (kg/m^x)', 'fitted FMI (kg/m^x)',
'fitted LMI (kg/m^x)', 'fitted ALMI (kg/m^x)']
min_age = 6.0
child_adult_split = 18.0
max_age = 82.0
male = 0
female = 1
genders = {"male": 0, "female":1}
path = 'data1/'
filename_children = 'children_LMS_{}_gender{}.csv'
filename_adults = 'adults_LMS_{}_gender{}.csv'
params_only_children = [
'BMI', 'height', 'weight', 'fitted_BMI', 'fitted_FMI',
'fitted_LMI', 'fitted_ALMI']
params_only_adults = ['VAT_mass', 'FM_android_quotient_gynoid']
def zscore_to_perc(zscore):
return scipy.stats.norm.cdf(zscore)
def nice_name(string):
string = string.replace('_', ' ').replace('quotient', '/')
return string
# get all input fields
for p, desc in zip(params, descs):
if p in ['Birthday', 'Measurement-day']:
textInput_dict[p] = pn.widgets.DatePicker(name="{}".format(desc))
elif p in ["Gender"]:
textInput_dict[p] = pn.widgets.Select(name=desc, options=genders)
else:
textInput_dict[p] = pn.widgets.TextInput(
name="",
placeholder=desc)
def process_file(event):
pyscript.write("computing-info", 'computing...')
values_dict = {}
birthday = None
meas_day = None
for p in params:
val = textInput_dict[p].value
if p not in ['Gender', 'Birthday', 'Measurement-day']:
if val == '':
values_dict[p] = None
pyscript.write("output-{}".format(p), '')
else:
try:
val = float(val)
if val > 0:
values_dict[p] = val
pyscript.write("output-{}".format(p), '')
else:
values_dict[p] = None
pyscript.write(
"output-{}".format(p),
'invalid entry! entry > 0 is needed')
except Exception:
values_dict[p] = None
pyscript.write(
"output-{}".format(p),
'invalid entry! a number > 0 is needed (use . for comma)')
elif p == 'Birthday':
values_dict[p] = None
try:
birthday = datetime.datetime.strptime(str(val), "%Y-%m-%d")
pyscript.write("output-{}".format(p), '')
except Exception:
birthday = None
values_dict['Age'] = None
pyscript.write(
"output-{}".format(p),
'invalid Birthday!')
elif p == 'Measurement-day':
values_dict[p] = None
try:
meas_day = datetime.datetime.strptime(str(val), "%Y-%m-%d")
pyscript.write("output-{}".format(p), '')
except Exception:
meas_day = None
values_dict['Age'] = None
pyscript.write(
"output-{}".format(p),
'invalid Measurement-day!')
elif p == 'Gender':
values_dict[p] = val
# compute age
if birthday is not None and meas_day is not None:
age = (meas_day - birthday).days/365.25
pyscript.write("output-Age", 'age: {:.2f}'.format(age))
if min_age <= age <= max_age:
values_dict['Age'] = age
else:
values_dict['Age'] = None
pyscript.write(
"output-Age",
'invalid age ({:.2f}) -- needs age between {} - {}'.format(
age, min_age, max_age))
# compute z-scores
if (values_dict['Age'] is not None) and (values_dict['Gender'] is not None):
if values_dict['Age'] < child_adult_split:
filename = filename_children
params_avail = list(set(params) - set(params_only_adults))
params_unavail = params_only_adults
else:
filename = filename_adults
params_avail = list(set(params) - set(params_only_children))
params_unavail = params_only_children
gender = values_dict['Gender']
age = values_dict['Age']
values_dict_ = {key: values_dict[key] for key in params_avail}
out_values = zc.compute_zscores_all_params(
path=path, filename=filename, gender=gender,
age=age, value_dict=values_dict_)
for p in params_unavail:
if values_dict['Age'] < child_adult_split:
pyscript.write("output-{}".format(p),
'-> only available for adults')
else:
pyscript.write("output-{}".format(p),
'-> only available for children')
for p in params_avail:
if p not in ['Gender', 'Birthday', 'Measurement-day']:
# pyscript.write("output", "{} - {}".format(p, out_values[p]),
# append=True)
if out_values[p] is not None:
if type(out_values[p][0]) == str:
pyscript.write("output-{}".format(p),
'{}'.format(out_values[p][0]))
else:
if out_values[p][0] is not None:
pyscript.write(
"output-{}".format(p),
'{}:\nz-Score: {:.2f}, percentile: {:.2f}%'.format(
nice_name(p), out_values[p][0],
zscore_to_perc(out_values[p][0])*100))
# show plot
f = out_values[p][1]
ax = f.get_axes()[0]
g_str = 'male' if gender == male else 'female'
ca_str = 'children' if age < child_adult_split else 'adults'
ax.set_title('{} -- {} -- {}'.format(nice_name(p), ca_str, g_str))
if age < child_adult_split:
ax.set_xlim([None, child_adult_split+1])
else:
ax.set_xlim([child_adult_split-3, max_age+5])
ax.set_xlabel("age")
pyscript.write("plot-{}".format(p), f, append=False)
for p in params_unavail:
pyscript.write("plot-{}".format(p), "", append=False)
pyscript.write("computing-info", '')
uploadButton.on_click(process_file)
await show(uploadButton, 'upload')
# show all input fields
for p in params:
await show(textInput_dict[p], 'fileinput-{}'.format(p))