growthcharts 0.1.0__tar.gz

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.
@@ -0,0 +1,12 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dr Dehghani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ [... continues with full MIT license text ...]
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: growthcharts
3
+ Version: 0.1.0
4
+ Summary: Pediatric Growth Chart Analyzer
5
+ Home-page: https://drdehghani.ir/
6
+ Author: Javad Dehghani MD
7
+ Author-email: j.dehghani@gmail.com
8
+ Keywords: growth chart pediatric infant child BMI CDC
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Intended Audience :: Healthcare Industry
13
+ Classifier: Topic :: Scientific/Engineering :: Visualization
14
+ Requires-Python: >=3.7
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE.txt
17
+ Requires-Dist: pandas
18
+ Requires-Dist: matplotlib
19
+ Requires-Dist: scipy
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: keywords
27
+ Dynamic: license-file
28
+ Dynamic: requires-dist
29
+ Dynamic: requires-python
30
+ Dynamic: summary
31
+
32
+
33
+ **GrowthCharts** is a pediatric growth chart analyzer for infants (0–2 years) and children (2–20 years).
34
+ It provides Z-score calculation, percentiles, and growth chart visualization based on CDC growth standards.
35
+
36
+ ---
37
+
38
+ ## Installation
39
+
40
+ Install from PyPI (once uploaded):
41
+
42
+ ```bash
43
+ pip install growthcharts
44
+ Or install locally for development:
45
+
46
+ pip install -e .
47
+ Requirements:
48
+
49
+ pandas
50
+
51
+ matplotlib
52
+
53
+ scipy
54
+
55
+ Quickstart
56
+ Infant example (0–24 months)
57
+ from growthcharts import Infant
58
+
59
+ # Create an Infant object
60
+ baby = Infant(sex='m', age=6, wt=7.5, length=65.0, hc=42.0)
61
+
62
+ # Plot growth charts
63
+ baby.plot_wtage(title="Weight-for-Age")
64
+ baby.plot_lenageinf(title="Length-for-Age")
65
+ baby.plot_hcageinf(title="Head Circumference-for-Age")
66
+ baby.plot_wtleninf(title="Weight-for-Length")
67
+
68
+ # Calculate Z-scores and percentiles
69
+ print(baby.analyze_wtageinf()) # Example output: {'Z': -0.23, 'Percentile': 41.0}
70
+ print(baby.analyze_lenageinf()) # Example output: {'Z': 0.12, 'Percentile': 55.0}
71
+ print(baby.analyze_hcageinf()) # Example output: {'Z': 0.30, 'Percentile': 62.0}
72
+ print(baby.analyze_wtleninf()) # Example output: {'Z': -0.15, 'Percentile': 44.0}
73
+ Child example (2–20 years)
74
+ from growthcharts import Child
75
+
76
+ # Create a Child object
77
+ child = Child(sex='f', age=36, wt=15.5, length=95.0)
78
+
79
+ # Plot growth charts
80
+ child.plot_wtage(title="Weight-for-Age")
81
+ child.plot_lenage(title="Height-for-Age")
82
+ child.plot_bmiage(title="BMI-for-Age")
83
+
84
+ # Calculate Z-scores and percentiles
85
+ print(child.analyze_wtage()) # Example output: {'Z': 0.12, 'Percentile': 55.0}
86
+ print(child.analyze_lenage()) # Example output: {'Z': -0.08, 'Percentile': 47.0}
87
+ print(child.analyze_bmiage()) # Example output: {'Z': 0.05, 'Percentile': 52.0}
88
+ Classes
89
+ Patient
90
+ Base class storing sex, age, weight, and length.
91
+
92
+ Calculates BMI if both weight and length are provided.
93
+
94
+ Infant(Patient)
95
+ Handles infants 0–24 months:
96
+
97
+ Plotting methods: plot_wtage, plot_lenageinf, plot_hcageinf, plot_wtleninf
98
+
99
+ Analysis methods: analyze_wtageinf, analyze_lenageinf, analyze_hcageinf, analyze_wtleninf
100
+
101
+ Child(Patient)
102
+ Handles children 2–20 years:
103
+
104
+ Plotting methods: plot_wtage, plot_lenage, plot_bmiage
105
+
106
+ Analysis methods: analyze_wtage, analyze_lenage, analyze_bmiage
107
+
108
+ Data
109
+ CSV data files for growth standards are included with the package under the data/ folder.
110
+
111
+ Infant: wtageinf.csv, lenageinf.csv, hcageinf.csv, wtleninf.csv
112
+
113
+ Child: wtage.csv, lenage.csv, bmiage.csv
114
+
115
+ These are loaded automatically by the classes and do not need separate downloading.
116
+
117
+ ## License
118
+
119
+ This project is licensed under the MIT License.
@@ -0,0 +1,88 @@
1
+
2
+ **GrowthCharts** is a pediatric growth chart analyzer for infants (0–2 years) and children (2–20 years).
3
+ It provides Z-score calculation, percentiles, and growth chart visualization based on CDC growth standards.
4
+
5
+ ---
6
+
7
+ ## Installation
8
+
9
+ Install from PyPI (once uploaded):
10
+
11
+ ```bash
12
+ pip install growthcharts
13
+ Or install locally for development:
14
+
15
+ pip install -e .
16
+ Requirements:
17
+
18
+ pandas
19
+
20
+ matplotlib
21
+
22
+ scipy
23
+
24
+ Quickstart
25
+ Infant example (0–24 months)
26
+ from growthcharts import Infant
27
+
28
+ # Create an Infant object
29
+ baby = Infant(sex='m', age=6, wt=7.5, length=65.0, hc=42.0)
30
+
31
+ # Plot growth charts
32
+ baby.plot_wtage(title="Weight-for-Age")
33
+ baby.plot_lenageinf(title="Length-for-Age")
34
+ baby.plot_hcageinf(title="Head Circumference-for-Age")
35
+ baby.plot_wtleninf(title="Weight-for-Length")
36
+
37
+ # Calculate Z-scores and percentiles
38
+ print(baby.analyze_wtageinf()) # Example output: {'Z': -0.23, 'Percentile': 41.0}
39
+ print(baby.analyze_lenageinf()) # Example output: {'Z': 0.12, 'Percentile': 55.0}
40
+ print(baby.analyze_hcageinf()) # Example output: {'Z': 0.30, 'Percentile': 62.0}
41
+ print(baby.analyze_wtleninf()) # Example output: {'Z': -0.15, 'Percentile': 44.0}
42
+ Child example (2–20 years)
43
+ from growthcharts import Child
44
+
45
+ # Create a Child object
46
+ child = Child(sex='f', age=36, wt=15.5, length=95.0)
47
+
48
+ # Plot growth charts
49
+ child.plot_wtage(title="Weight-for-Age")
50
+ child.plot_lenage(title="Height-for-Age")
51
+ child.plot_bmiage(title="BMI-for-Age")
52
+
53
+ # Calculate Z-scores and percentiles
54
+ print(child.analyze_wtage()) # Example output: {'Z': 0.12, 'Percentile': 55.0}
55
+ print(child.analyze_lenage()) # Example output: {'Z': -0.08, 'Percentile': 47.0}
56
+ print(child.analyze_bmiage()) # Example output: {'Z': 0.05, 'Percentile': 52.0}
57
+ Classes
58
+ Patient
59
+ Base class storing sex, age, weight, and length.
60
+
61
+ Calculates BMI if both weight and length are provided.
62
+
63
+ Infant(Patient)
64
+ Handles infants 0–24 months:
65
+
66
+ Plotting methods: plot_wtage, plot_lenageinf, plot_hcageinf, plot_wtleninf
67
+
68
+ Analysis methods: analyze_wtageinf, analyze_lenageinf, analyze_hcageinf, analyze_wtleninf
69
+
70
+ Child(Patient)
71
+ Handles children 2–20 years:
72
+
73
+ Plotting methods: plot_wtage, plot_lenage, plot_bmiage
74
+
75
+ Analysis methods: analyze_wtage, analyze_lenage, analyze_bmiage
76
+
77
+ Data
78
+ CSV data files for growth standards are included with the package under the data/ folder.
79
+
80
+ Infant: wtageinf.csv, lenageinf.csv, hcageinf.csv, wtleninf.csv
81
+
82
+ Child: wtage.csv, lenage.csv, bmiage.csv
83
+
84
+ These are loaded automatically by the classes and do not need separate downloading.
85
+
86
+ ## License
87
+
88
+ This project is licensed under the MIT License.
@@ -0,0 +1,7 @@
1
+ # growthcharts/__init__.py
2
+
3
+ from .patient import Patient
4
+ from .infant import Infant
5
+ from .child import Child
6
+
7
+ __all__ = ["Patient", "Infant", "Child"]
@@ -0,0 +1,269 @@
1
+ import pandas as pd
2
+ import matplotlib.pyplot as plt
3
+ import math
4
+ from scipy.stats import norm
5
+
6
+ from .patient import Patient
7
+ from pathlib import Path
8
+
9
+
10
+ DATA_PATH = Path(__file__).parent / "data"
11
+
12
+
13
+ class Child(Patient):
14
+ """
15
+ Represents a child patient (2–20 years) and provides growth chart analysis
16
+ and visualization based on CDC growth standards.
17
+
18
+ This class extends the Patient class and adds functionality for:
19
+ - Weight-for-age
20
+ - Length-for-age
21
+ - BMI-for-age
22
+
23
+ Supports plotting percentile curves and calculating Z-scores and percentiles
24
+ using the LMS method.
25
+ """
26
+
27
+ # Child 2 to 20 database
28
+ df_wtage = pd.read_csv(DATA_PATH /'wtage.csv', dtype={'Sex': str})
29
+ df_lenage = pd.read_csv(DATA_PATH /'lenage.csv', dtype={'Sex': str})
30
+ df_bmiage = pd.read_csv(DATA_PATH /'bmiage.csv', dtype={'Sex': str})
31
+
32
+ def __init__(self, sex: str, age: int, wt: float = None, length: float = None):
33
+ """
34
+ Initialize a Child object.
35
+
36
+ At least one anthropometric measurement must be provided.
37
+
38
+ Args:
39
+ sex (str): Child sex.
40
+ age (int): Age in months.
41
+ wt (float, optional): Weight in kilograms.
42
+ length (float, optional): Length/height in centimeters.
43
+
44
+ Raises:
45
+ ValueError: If both wt and length are None.
46
+ """
47
+ if wt is None and length is None:
48
+ raise ValueError("At least wt or length must be provided")
49
+
50
+ super().__init__(sex, age, wt, length)
51
+
52
+ def plot_wtage(self, title=None):
53
+ """
54
+ Plot weight-for-age growth chart with patient's measurement.
55
+
56
+ Args:
57
+ title (str, optional): Plot title.
58
+ """
59
+ df = self.df_wtage
60
+
61
+ self.sex = str(self.sex).lower()
62
+ if self.sex in ['m', '1']:
63
+ self.sex = '1'
64
+ elif self.sex in ['f', '2']:
65
+ self.sex = '2'
66
+ else:
67
+ raise TypeError('define sex as m or f')
68
+
69
+ data = df[df['Sex'] == self.sex]
70
+
71
+ plt.figure(figsize=(12, 7))
72
+ for i, col in enumerate(self.agecolumns[1:]):
73
+ if i in self.highlight_indices:
74
+ plt.plot(data['Agemos'], data[col],
75
+ color='gray', linewidth=2, label=f'{title} {col}')
76
+ else:
77
+ plt.plot(data['Agemos'], data[col],
78
+ color='lightgray', linewidth=1)
79
+
80
+ if self.wt is not None:
81
+ plt.scatter(self.age, self.wt, color='red', s=100, zorder=5)
82
+
83
+ plt.title(title)
84
+ plt.xlabel("age(month)")
85
+ plt.ylabel("Weight(Kg)")
86
+ plt.grid(True)
87
+ plt.legend()
88
+ plt.show()
89
+
90
+ def plot_lenage(self, title=None):
91
+ """
92
+ Plot length-for-age growth chart with patient's measurement.
93
+
94
+ Args:
95
+ title (str, optional): Plot title.
96
+ """
97
+ df = self.df_lenage
98
+
99
+ self.sex = str(self.sex).lower()
100
+ if self.sex in ['m', '1']:
101
+ self.sex = '1'
102
+ elif self.sex in ['f', '2']:
103
+ self.sex = '2'
104
+ else:
105
+ raise TypeError('define sex as m or f')
106
+
107
+ data = df[df['Sex'] == self.sex]
108
+
109
+ plt.figure(figsize=(14, 10))
110
+ for i, col in enumerate(self.agecolumns[1:]):
111
+ if i in self.highlight_indices:
112
+ plt.plot(data['Agemos'], data[col],
113
+ color='gray', linewidth=2, label=f'{title} {col}')
114
+ else:
115
+ plt.plot(data['Agemos'], data[col],
116
+ color='lightgray', linewidth=1)
117
+
118
+ if self.length is not None:
119
+ plt.scatter(self.age, self.length, color='red', s=100, zorder=5)
120
+
121
+ plt.title(title)
122
+ plt.xlabel("age(month)")
123
+ plt.ylabel("Length(cm)")
124
+ plt.grid(True)
125
+ plt.legend()
126
+ plt.show()
127
+
128
+ def plot_bmiage(self, title=None):
129
+ """
130
+ Plot BMI-for-age growth chart with patient's measurement.
131
+
132
+ Args:
133
+ title (str, optional): Plot title.
134
+ """
135
+ df = self.df_bmiage
136
+
137
+ self.sex = str(self.sex).lower()
138
+ if self.sex in ['m', '1']:
139
+ self.sex = '1'
140
+ elif self.sex in ['f', '2']:
141
+ self.sex = '2'
142
+ else:
143
+ raise TypeError('define sex as m or f')
144
+
145
+ data = df[df['Sex'] == self.sex]
146
+
147
+ plt.figure(figsize=(12, 7))
148
+ for i, col in enumerate(self.agecolumns[1:]):
149
+ if i in self.highlight_indices:
150
+ plt.plot(data['Agemos'], data[col],
151
+ color='gray', linewidth=2, label=f'{title} {col}')
152
+ else:
153
+ plt.plot(data['Agemos'], data[col],
154
+ color='lightgray', linewidth=1)
155
+
156
+ if self.wt is not None and self.length is not None and self.length > 0:
157
+ plt.scatter(self.age, self.bmi, color='red', s=100, zorder=5)
158
+
159
+ plt.title(title)
160
+ plt.xlabel("age(month)")
161
+ plt.ylabel("BMI")
162
+ plt.grid(True)
163
+ plt.legend()
164
+ plt.show()
165
+
166
+ def analyze_wtage(self):
167
+ """
168
+ Analyze weight-for-age using LMS method.
169
+
170
+ Returns:
171
+ dict: Z-score and percentile.
172
+ """
173
+ df = self.df_wtage
174
+ self.sex = str(self.sex).lower()
175
+ if self.sex in ['m', '1']:
176
+ self.sex = '1'
177
+ elif self.sex in ['f', '2']:
178
+ self.sex = '2'
179
+ else:
180
+ raise TypeError('define sex as m or f')
181
+
182
+ df2 = df[df['Sex'] == self.sex]
183
+ row = df2.iloc[(df2['Agemos'] - self.age).abs().argsort()[:1]]
184
+
185
+ L = float(row['L'].values[0])
186
+ M = float(row['M'].values[0])
187
+ S = float(row['S'].values[0])
188
+
189
+ if L != 0:
190
+ z = ((self.wt / M) ** L - 1) / (L * S)
191
+ else:
192
+ z = math.log(self.wt / M) / S
193
+
194
+ percentile = norm.cdf(z) * 100
195
+
196
+ return {
197
+ "Z": round(z, 2),
198
+ "Percentile": round(percentile, 2)
199
+ }
200
+
201
+ def analyze_lenage(self):
202
+ """
203
+ Analyze length-for-age using LMS method.
204
+
205
+ Returns:
206
+ dict: Z-score and percentile.
207
+ """
208
+ df = self.df_lenage
209
+ self.sex = str(self.sex).lower()
210
+ if self.sex in ['m', '1']:
211
+ self.sex = '1'
212
+ elif self.sex in ['f', '2']:
213
+ self.sex = '2'
214
+ else:
215
+ raise TypeError('define sex as m or f')
216
+
217
+ df2 = df[df['Sex'] == self.sex]
218
+ row = df2.iloc[(df2['Agemos'] - self.age).abs().argsort()[:1]]
219
+
220
+ L = float(row['L'].values[0])
221
+ M = float(row['M'].values[0])
222
+ S = float(row['S'].values[0])
223
+
224
+ if L != 0:
225
+ z = ((self.length / M) ** L - 1) / (L * S)
226
+ else:
227
+ z = math.log(self.length / M) / S
228
+
229
+ percentile = norm.cdf(z) * 100
230
+
231
+ return {
232
+ "Z": round(z, 2),
233
+ "Percentile": round(percentile, 2)
234
+ }
235
+
236
+ def analyze_bmiage(self):
237
+ """
238
+ Analyze BMI-for-age using LMS method.
239
+
240
+ Returns:
241
+ dict: Z-score and percentile.
242
+ """
243
+ df = self.df_bmiage
244
+ self.sex = str(self.sex).lower()
245
+ if self.sex in ['m', '1']:
246
+ self.sex = '1'
247
+ elif self.sex in ['f', '2']:
248
+ self.sex = '2'
249
+ else:
250
+ raise TypeError('define sex as m or f')
251
+
252
+ df2 = df[df['Sex'] == self.sex]
253
+ row = df2.iloc[(df2['Agemos'] - self.age).abs().argsort()[:1]]
254
+
255
+ L = float(row['L'].values[0])
256
+ M = float(row['M'].values[0])
257
+ S = float(row['S'].values[0])
258
+
259
+ if L != 0:
260
+ z = ((self.bmi / M) ** L - 1) / (L * S)
261
+ else:
262
+ z = math.log(self.bmi / M) / S
263
+
264
+ percentile = norm.cdf(z) * 100
265
+
266
+ return {
267
+ "Z": round(z, 2),
268
+ "Percentile": round(percentile, 2)
269
+ }