0% found this document useful (0 votes)
17 views15 pages

Using Python To Analyze Isometric Force Time.7

This article discusses the use of Python for analyzing isometric midthigh pull (IMTP) force-time curves, providing a cost-effective alternative to commercial software. It outlines the importance of accurately selecting and analyzing force-time curves to assess athletes' force-generating capacities and offers guidance on using Python for data analysis. Key metrics such as peak force, rate of force development, and force at specific time points are emphasized for their relevance in performance diagnostics.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views15 pages

Using Python To Analyze Isometric Force Time.7

This article discusses the use of Python for analyzing isometric midthigh pull (IMTP) force-time curves, providing a cost-effective alternative to commercial software. It outlines the importance of accurately selecting and analyzing force-time curves to assess athletes' force-generating capacities and offers guidance on using Python for data analysis. Key metrics such as peak force, rate of force development, and force at specific time points are emphasized for their relevance in performance diagnostics.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

Using Python to Analyze

Isometric Force-Time
Curves
Jason Chadwick Smith,1 Tsuyoshi Nagatani,2 Stuart N. Guppy,2 and Guy Gregory Haff2,3
1
Department of Kinesiology, Coastal Carolina University, Conway, South Carolina; 2Strength and Power Research
Group, School of Medical and Health Sciences, Edith Cowan University, Joondalup Western Australia; and 3Sport,
Exercise, and Physiotherapy, University of Salford, Greater Manchester, United Kingdom

Supplemental digital content is available for this article. Direct URL citations appear in the printed text and are provided
in the HTML and PDF versions of this article on the journal’s Web site (http://journals.lww.com/nsca-scj).

ABSTRACT vided can be used to analyze the IMTP midthigh pull (IMTP) and isometric
force-time curve data, it can be modi- squat, should be used in addition to
The isometric midthigh pull (IMTP) is
fied to examine other metrics as these tests to provide a greater diag-
a commonly used strength diagnostic
needed by the user (see, Supplemen- nostic picture of the athlete’s force-
tool that can give insight into an ath-
tal Digital Content 1, http://links.lww. generating capacities (19). Incorporat-
lete’s force-generating capacities. The
com/SCJ/A412). ing these types of tests into the moni-
resulting force-time curves generated
toring plan allows for the creation of
are commonly analyzed using com-
force-time curves that can be system-
mercial software packages that pro- INTRODUCTION
atically analyzed to provide detailed
vide a variety of metrics. Although t is well documented that maximal
these software packages are useful,
they are often costly and operate as
a “black box,” limiting the control over
I strength, which represents the abil-
ity to exert external force on an
object or resistance, is an important
information about various aspects of
the athlete’s force-generating capaci-
ties (5,6,30).

how these metrics are calculated. A factor underpinning the performance One of the most common multi-joint
template created in Excel can be used of many athletic tasks, enhances isometric tests is the IMTP, introduced
to analyze isometric data. However, fatigue resistance, and reduces injury in the scientific literature in 1997 as
creating a custom script to analyze risk (7,14,22,28,31). Because of its over- a method for quantifying the athlete’s
isometric trials can be more time- all importance, it is widely accepted maximal force-generating capacity and
that the maximization of muscular the rate at which force can be applied
efficient. To provide users with an
strength is a central training target during maximal contractions (16,17).
alternative analysis option, this article
when working with athletes. To facili- Over time, the force-time curves gen-
provides a guide for selecting IMTP
tate the development and monitoring erated from this test have been further
force-time curves and variables for
of maximal strength, various testing dissected to include analyses of the
analysis and how to use Python to
and monitoring methods have been forces at specific epochs, changes in
perform these analyses. Basic proce- proposed. The most common method force, and incorporating analyses of
dures are provided to ensure that for assessing maximal strength is to impulse (9,16). Although the original
accurate force-time curves are assess the athlete’s 1 repetition maxi- incarnation of the test used a single
selected and analyzed, followed by mum or repetition maximum during force plate, more recently, it has
strategies for using Python to read a specific resistance training exercise become commonplace to use 2 force
files, filter data, calculate force-time (4,14). Although these tests are useful plates so that individual limb force-
curve variables, graphically present for guiding the training process, they time characteristics can be evaluated
data, and write results to a report are do not provide detailed information
discussed. Although the script pro- about how the athlete generates force. KEY WORDS:
To address this shortcoming, research- Performance testing; kinetics; sports
Address correspondence to J. Chadwick ers have proposed that multi-joint iso- science; force platform
Smith, [email protected]. metric testing, such as the isometric

Copyright Ó National Strength and Conditioning Association 287


Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Python & Isometric Force-Time Curves

to identify lower limb force generation reported to have an increased potential strapped to the bar to determine if pre-
asymmetries. The inclusion of these for processing errors and disagree- tension is being applied to the bar
measures as part of the force-time ments across analyses depending on (Figure 4C), as this can interfere with
curve analysis likely increases the abil- the software package used (24). This the onset detection and influence the
ity of the test to be used as a diagnostic has led many sport scientists and reliability and accuracy of the collected
tool, especially when considering strength and conditioning professio- measures (5,6). The final check deter-
sporting tasks such as jumping, sprint- nals to seek alternative ways of creating mines if the current trial is within 250 N
ing, and change of direction are time- their bespoke force-time curve analysis of the last trial collected in the testing
constrained (6) and asymmetries are software with programs such as Excel session. If the trial is within 250 N of
often related to injury risk (2,18). (5), R (24), or Python (29). With the last trial, then the trial can be
Generally, the peak forces, maximal increasing interest in using open- accepted (21). Although this method
forces determined at specific time access computer languages, such as of quality control is commonly used,
points, and impulse measures have Python, to analyze force-time curves, it may not be ideal for smaller or weak-
been reported to be highly reliable Smith (29) recently presented a user- er individuals, such as children (25). As
friendly guide on using this program- such, it may be warranted to use a per-
within and between training sessions
ming language to batch analyze verti- centage difference-based threshold for
(11,12,16). Conversely, the rate of force
cal jump force-time curves. Given determining if additional trials are war-
development (RFD) has not consis-
force-time curve data are fundamen- ranted. Based on the limited available
tently been reported to be reliable
tally similar in structure regardless of research exploring percentage differ-
either within or between sessions,
the test performed, Python may pro- ence thresholds, if the current trial
regardless of whether peak RFD
vide an alternative solution for analyz- is ,15% different than the last trial,
(pRFD) or time point specific RFDs
ing IMTP force-time curves. the trial should be accepted (25). If
are analyzed (13,16). It is important
Therefore, the purpose of this article is the trial fails to meet these criteria, it
to note that the reliability of the mea-
to discuss the key metrics that need to should be discarded, and additional tri-
sure can be impacted by not only the
be considered when analyzing force- als should be conducted (Figure 2).
methodology of testing but the choices
made when analyzing the force-time time curves collected from IMTP trials, If the testing trials meet all these crite-
curve (10,13). Specifically, manual compare using Excel and Python to ria, they can be analyzed for the com-
force-onset identification methods analyze force-time curves, and demon- mon force-time curve variables.
result in different levels of reliability strate how to write Python code so that
when compared with the automated manual or automated force-time curve COMMON FORCE-TIME CURVE
(40 N, 5 SDs, and 3 SDs) onset selec- analyses can be performed. VARIABLES
tion methods used by some practi- After completing an IMTP test, the
tioners and researchers. Although CHOOSING ISOMETRIC MIDTHIGH force-time curve generated can be ana-
manual force-onset identification is PULL TRIALS FOR ANALYSIS lyzed to determine an athlete’s maxi-
considered the criterion method for as- A visual inspection of the IMTP force- mal and explosive strength levels (14).
sessing force-time curves, it requires time curve should be made in real time During this analysis, the most common
custom software, such as LabView to determine if the collected trial is force measurements calculated include
(National Instruments, Austin, TX), acceptable and if additional trials the peak force and forces determined at
that can be associated with a significant should be collected (5,6). A trial is predetermined time periods (Table 1).
financial cost (10). deemed unacceptable if there is not Generally, when the IMTP is performed
In addition, manual force-time curve a stable weighing period, there is a clear with standardized and systematic meth-
analyses can result in a significant time countermovement .50 N that occurs ods, the peak force is highly reliable (6,14)
burden delaying data reporting. An before the initiation of the pull, or there and reflects the athlete’s maximal force-
alternative approach is to use real- is obvious pretension (Figure 1A), as generating capacities. Generally, the peak
time automated analyses using com- this will interfere with the ability to force determined during the IMTP test
mercially available software packages. accurately identify the initiation of has been reported to be significantly cor-
These software packages have become the pull (5,6,27) or if the peak force related (r 5 0.740 to 0.980) with the max-
commonplace within the industry as occurs at the end of the trial imal weight lifted in competitive
they allow the practitioner to rapidly (Figure 1B). If the trial does not contain weightlifting movements (i.e., snatch
collect and analyze force-time curves any of these conditions, it is deemed and clean and jerk) and their derivatives
collected during the IMTP (24). acceptable (Figure 1C). (15,20,30) and other strength-based exer-
Although these software packages are In addition, it is important to carefully cises such as the back squat (36), deadlift
often easy to use, they come with a sig- inspect the forces applied during the (8), and bench press (23). In addition, the
nificant financial cost (1,000 to 3,000 standing quiet period where the ath- IMTP peak force has been significantly
USD per year) and have recently been lete is in the ready position and correlated to sprint performance

288 VOLUME 47 | NUMBER 3 | JUNE 2025


Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
(r 5 20.50 to 20.69), change of direction
performance (r 5 20.57 to 20.79), coun-
termovement jump performance (r 5
0.59 to 0.82), and squat jump performance
(r 5 0.51 to 0.87) (6,14). Because of its
high degree of reliability and its relation-
ships to various dynamic movements,
peak force is the most commonly quan-
tified force-time curve metric collected
during an IMTP.
Although the peak force is commonly
quantified from an IMTP test, it is also
important to examine the forces deter-
mined at specific time points (i.e., 50,
100, 150, 200, and 250 ms) as these met-
rics can give a more holistic depiction of
the athlete’s force production capacities
(14). If appropriate controls are used dur-
ing testing, the forces at predetermined
time points are very reliable and have
been reported to be significantly corre-
lated to weightlifting performance (force
at 100, 150, 200, and 250 ms: r 5 0.605 to
0.804) (1), back squat performance (force
at 150, 200, and 250 ms: r 5 0.782 to
0.816) (36), sprint performance (force at
100 ms: r 5 20.54) (37), and squat jump
(force 50 and 250 ms: r 5 0.33–0.39) and
countermovement jumps (force at 50
and 250 ms: r 5 0.27 to 0.34) (21).
Because of the diagnostic capacity of
forces at specific time points, these met-
rics are generally recommended when
analyzing force-time curves (6).
Although peak force and forces at spe-
cific time points are commonly ana-
lyzed, it is also important to quantify
the (pRFD) and the RFD between spe-
cific time increments starting from the
force onset relative to a specific time
point, for example, from 0 to 200 ms,
because of the significant relationships
between these metrics and various
markers of sports performance
(9,14,16) and their utility as fatigue
monitoring tools (26). When calculating
the pRFD, it is generally recommended
that a 20 ms moving average is used to
increase the reliability of the measure
(16). It is, however, preferable to use
time-dependent epochs, such as 0–200
or 0–250 ms, as these metrics result in
more reliable measures that exhibit bet-
ter relationships with dynamic perfor-
Figure 1. Examples of unacceptable (A and B) and acceptable (C) force-time curves. mance (6,14,16). However, it is

289
Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Python & Isometric Force-Time Curves

imbalances. To determine this metric,


an asymmetry index is generally calcu-
lated with the following formula (33):
This metric is significantly related (r 5
0.75, p 5 0.01) to the single-leg hop test
and may provide a time-efficient method
for evaluating asymmetries as part of
a single strength test (33). Although
using the IMTP to examine lower limb
strength imbalances is a promising met-
ric, much more research is needed to
verify its importance and utility.

USING PYTHON FOR FORCE-TIME


CURVE ANALYSES
Recently, Chavda et al. (5) created
a user-friendly guide for analyzing
IMTP data using an Excel template.
Users can copy and paste the force
and time data into the spreadsheet to
obtain the desired metrics (e.g., RFD,
impulse, etc). Although the template
was set up for the user to input the
desired time period of interest for ana-
lyzing impulse and RFD, it can be easily
modified to automatically calculate
impulse and RFD values for various
specific epochs. In addition, the tem-
plate can be modified to evaluate limb
asymmetry when using 2 force plates to
analyze IMTP data. However, analyz-
ing multiple trials using this template
may be less time-efficient with the user
having to copy and paste data for each
Figure 2. Isometric midthigh pull force-time curve prescreening decision tree. trial into the spreadsheet separately.
A computer script can be written to
automate much of this process. Select-
important to note that regardless of performance (i.e., 505) (32), peak force ing the programming platform and/or
which RFD metric is analyzed, there and power during various jumping tasks programming language to create such
is some evidence questioning the use (i.e., squat jump and countermovement a script will be largely based on the
of this metric because of issues related jump) (35). Although there is an emerging user’s interest in learning a specific plat-
to reliability (3,9). Regardless, the gen- body of evidence that the impulse pro- form and/or their previous knowledge
eral consensus is to quantify the RFD vides valuable information, there is still no of the program/platform. As previously
and use standardized data collection consensus on how to best use this metric mentioned, cost may also influence
and analysis methods to enhance the as part of a monitoring program (6). commercially available platforms, such
reliability of these measures (6). as MATLAB (Mathworks, Natick, MA),
Another metric that has begun to be that require the purchase of a license.
Another variable that can be quantified examined with the IMTP is the lower Although some businesses and univer-
from the force-time curves derived from limb peak force (33) and RFD sities may already have a MATLAB
the IMTP is the impulse across different
time epochs (16,35). Impulse values taken
across various epochs (0–100, 0–200, and
0–300 ms) have been reported to be asso- 
ciated with sprint (i.e., 5- and 20-m sprint Dominant Leg 2 Non 2 Dominant Leg
3 100
times) and change of direction Dominant Leg

290 VOLUME 47 | NUMBER 3 | JUNE 2025


Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Table 1
Common force-time curve variables analyzed during the isometric midthigh pull

Variable Abbreviation Unit Calculation methods

Absolute peak force PF N Gross PF 2 body weight

Absolute force at specific time epochs


Force at 50 ms F50 N Gross F at 50 ms 2 body weight
Force at 100 ms F100 N Gross F at 100 ms 2 body weight
Force at 150 ms F150 N Gross F at 150 ms 2 body weight
Force at 200 ms F200 N Gross F at 200 ms 2 body weight
Force at 250 ms F250 N Gross F at 250 ms 2 body weight
21
Relative peak force PFRel N$kg Gross PF O body weight (kg)
Relative force at specific time epochs
Force at 50 ms FRel50 N F50 O body weight (kg)
Force at 100 ms FRel100 N F100 O body weight (kg)
Force at 150 ms FRel150 N F150 O body weight (kg)
Force at 200 ms FRel200 N F200 O body weight (kg)
Force at 250 ms FRel250 N F250 O body weight (kg)
Rate of force development RFD N$s21 O force O O time
21
Average rate of force development RFDAVG N$s PF O time to PF from force on-set
21
Peak rate of force development pRFD N$s PF O sampling window
21
Rate of force development 0–50 ms RFD0–50 N$s F50 O 50 ms
Rate of force development 0–100 ms RFD0–100 N$s21 F100 O 100 ms
21
Rate of force development 0–150 ms RFD0–150 N$s F150 O 150 ms
21
Rate of force development 0–200 ms RFD0–200 N$s F200 O 200 ms
21
Rate of force development 0–250 ms RFD0–250 N$s F250 O 250 ms
From: Haff GG. Isometric and dynamic testing. In: Performance Assessments for Strength and Conditioning Coaches. Comfort P, Jones PA,
McMahon JJ, eds. Oxon, United Kingdom: Taylor Francis Books, 168–194, 2019. Reproduced by permission of Taylor & Francis Group.

license, additional toolboxes may need learning Python, we have used it to cre- exported as CSV files for further anal-
to be purchased if advanced computa- ate this guide for analyzing IMTP data ysis. During the first second of data
tions are required. Alternatively, R, from multiple trials. collection, the participant performed
a commonly used open-access statistical a quiet stance. Then, data collection
The script presented in Supplemental
analysis platform, can create a script to was paused to strap the participant to
Digital Content 1 (see, http://links.
analyze IMTP data without additional the bar. Finally, data collection was
lww.com/SCJ/A412) can be modified
cost. However, the syntax used by R resumed to allow the participant to
makes learning this programming plat- to suit the user’s needs and data. A complete the IMTP trial. All trials were
form more difficult than learning MAT- series of IMTP trials were collected saved to a single CSV file (see Supple-
LAB commands for a new user. Python with the use of an isometric rack (Vald, mental Digital Content 2, http://links.
is another open-source, general pro- Queensland, Australia) and a pair of lww.com/SCJ/A413). Each trial com-
gramming language for various applica- Pasco Force Plates (PS-2141, PASCO prised 4 columns of data (time, Fz for
tions, such as web development, data Scientific, CA) that sampled at left leg, Fz for right leg, and combined
visualization, and scientific computing. 1,000 Hz and Pasco Capstone Software Fz, with Fz representing vertical
Because of the lack of cost and ease of (V2.4.0) that allowed data to be ground reaction forces).

291
Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Python & Isometric Force-Time Curves

PYTHON AND INTEGRATED 13 of the script accomplish this task. To function to create a list of trial names
DEVELOPMENT ENVIRONMENT be more efficient, we referenced the based upon the number of trials (e.g.,
(IDE) INSTALLATION AND package or specific module using an Trial 1, Trial 2) and then assign it to
CONFIGURATION
abbreviation. For example, pandas a new variable called “trial_choices.”
Before creating a Python script or pro- was referenced as “pd.” Therefore, we
gram, the user must install Python Lines 32–38 were used to set up the
called the pandas library in our script user interface for trial selection using
(http://python.org) and an editor or using “pd” instead of typing “pandas.”
integrated development environment PySimpleGui, which includes a mes-
A summary of each of the packages, sage “Select a Trial,” a combo box to
(IDE) on their computer. To create the libraries, and modules imported into
script for this paper, we used one of the select a particular trial from dataframe
our script and a brief explanation for “df,” and a button labeled “Analyze.”
most popular IDEs, PyCharm (http:// each package is provided in Table 2.
jetbrains.com/pycharm). There are 2 Line 38 creates a popup window using
versions of PyCharm, 1 for research PySimpleGui with its title labeled
FILE AND TRIAL SELECTION “Select Trial” based upon layout
and 1 for the community. Because the After installing the necessary Python
community version was free, we used it defined earlier and assigns it to a new
packages, we determined a visual style variable called “window.” Lines 40–54
to create this guide. Smith (29) provided for a popup window by executing Line
a supplemental digital video (http:// use a while True loop function, which
16, as the popup window was used for continues to run until a “break” state-
links.lww.com/SCJ/A390) that shows the user to select a CSV file and a spe-
the user how to install Python and Py- ment is encountered. Line 41 reads an
cific trial from it. Line 17 in the script event and associated variables from the
Charm, and another supplemental digital creates a small window using PySim-
video showing the user how to properly popup window created earlier. Line 43
pleGui, where the title of the window checked if the event is the window
configure PyCharm (http://links.lww. is labeled “File Selector” and the mes-
com/SCJ/A391). being closed. If this was true, line 44
sage “Select a CSV file” appears inside then used the “break” statement to ter-
the window. After selecting the file, the minate the infinite loop. Line 45
IMPORT PYTHON PACKAGES user presses the “Ok” button, and the checked if the event is the “Analyze”
After the user has installed Python and window closes. button being clicked. If this was true,
properly configured their IDE, they We have stored the selected CSV file the script proceeded to lines 46–54.
can start writing their script. When path in the “csv_file” variable. To select Line 46 used the selected trial name
writing the script, it can be helpful to which trial to analyze from the selected to retrieve a particular trial from the
make comments within the script to CSV file, we must first convert it into combo box and find its index within
help the user understand different sec- a pandas dataframe. Lines 19–25 con- “trial_choices,” which is assigned to
tions. In Python, you can use the verted the selected CSV file into a pan- a variable called “selected_trial_index.”
pound or hashtag (#) symbol to make das dataframe “df.” If a CSV file was not This variable was used in combination
these comments. When running the selected or malformed (e.g., a text file with “num_columns_per_trial” to cal-
script, any line that begins with the was selected), the error message “Error culate the start and end columns in the
pound symbol is ignored by Python. reading CSV file” is displayed to inform dataframe “df” in lines 47–48. Line 49
We have used comments to break the user about the error. If there was no used pandas “.iloc” method to extract
our script into several sections to help error during the CSV file reading pro- the data for the selected trial from the
the reader understand each section of cess, we proceed to next lines of code, datafame “df.” This line of code
the Python script. where line 27 sets a new variable called selected all rows using “:” and a specific
Most Python scripts will start with “num_columns_per_trial” to 4. This range of columns determined by the
installing the necessary Python pack- suggests that 4 columns correspond start and end columns defined earlier
ages and importing them into the to each trial in the dataframe “df.” If to create a new dataframe “data.” Lines
script. This can be done directly from there are only 2 columns correspond- 50–51 were used to print information
PyCharm’s Python Packages window ing to each trial in the dataframe “df” about the selected trial and the corre-
(see Smith (29) Supplemental Digital (e.g., only using a single force plate), 2 sponding data for that trial, which pro-
Content 9, http://links.lww.com/ should be assigned to this variable vided feedback to the user about the
SCJ/A391). Several packages are instead of 4 to represent the time and analysis being performed. Line 52 used
needed for the Python script created force columns. Line 28 calculates the the “break” statement to break out of
based on this paper. For some of these number of trials in the dataframe “df” the while True loop after trial selection
packages, we will only be using specific by dividing the total number of col- was completed. Once the dataframe
modules. We did not need to import umns by the number of columns per “data” was created, line 56 was used
the entire package and have specified trial to create a new variable called to assign new column names to this
the modules to be imported. Lines 1– “num_trials.” Line 29 uses a for loop dataframe, specifically “Time,” “rFz,”

292 VOLUME 47 | NUMBER 3 | JUNE 2025


Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Table 2
Python packages, libraries, and modules used in the script

Python package Description


Pandas Python data analysis library: a data analysis and manipulation tool. It allows the
data to be displayed in a spreadsheet-like manner
numpy Numerical python: a fundamental package that can be used for scientific
computing
scipy Scientific python: this scientific computing library is built on top of numpy to
perform more advanced calculations. This script uses the “integrate” function
to perform mathematical integration
matplotlib.pyplot This is a graphing library. The pyplot module (matplotlib.pyplot) was used to
create a graph for the user to inspect the force-time curve and create
a subplot that contains 3 different graphs. FigureCanvasAgg was also used to
display the subplot in the report generated at the end of the script
matplotlib.backends.backend_tkagg This module of matplotlib is primarily used to provide a matplotlib figure as
a widget on a graphical user interface. We imported the FigureCanvasTkAgg
module to create a special canvas to place the subplot created by
matplotlib.pyplot on the graphical user interface when displaying the results
of the analyzed trial
matplotlib.backends.backend_agg This module of matplotlib is primarily used for noninteractive rendering of
matplotlib figures. In this script, we used the FigureCanvasAgg for placing the
subplot in our report
PySimpleGUI This a graphical user interface package. In this script, PySimpleGUI was used to
display popup windows for user input and display the subplot, results in
tabular format, and allow the user to save the report that is generated at the
end of the script
reportlab.lib.pagesizes This module defines a few common page sizes. We used the letter function of
this module to generate the report page size (8.5 inches wide, 11 inches in
length)
reportlab.lib.units This module allows the user to specify different units of measure as multiples of
a point. For our script, we used the “inch” function to specify the width of
each column in the tables displayed in the report
reportlab.platypus Page layout and typography using scripts. This library allows the user to make
decisions about the layout of complex documents. From this library, we used
the SimpleDocTemplate to create the outermost container for the document.
This allowed us to place the subplot and tables inside this container in the
report. We also used the “Table” and “TableStyle” functions to format and
create the tables to display our results in the report
reportlab.playpus.flowables This module allows a “floating element” in a document where its position is
determined by the elements that precede it. In our script, we used the object
class “Image” to embed subplot into the report PDF document
io This module is part of Python’s standard library and is used to handle input and
output operations. The class “BytesIO” can temporarily store binary data in
the computer’s memory. We used this class in our script to temporarily store
the subplot as an image file within the computer’s memory so that it can be
used later in the script

“lFz,” and “Fz.” If the user has a single “Fz.” To visually verify that raw data a graph for the user to inspect. The user
force plate, line 56 would be modified for IMTP data were successfully im- should be able to view a force-time
to name the 2 columns “Time” and ported, lines 59–60 were used to create curve on the graph (see Video 1).

293
Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Python & Isometric Force-Time Curves

INSPECTING THE FORCE-TIME start. Line 63 in the script creates of data collection. Line 72 uses the
CURVE AND WEIGHT a popup window for the user to enter “std” function to calculate the SD of
DETERMINATION the time to start the weight determina- the individual’s weight. We labeled this
After the appropriate trial has been tion. From PySimpleGui, we can use variable “stddev”. Line 73 creates a vari-
selected, we need to inspect the the “popup_get_text” method to dis- able called “SD3,” representing 3 SDs
force-time curve to ensure no counter- play a small window. The title of the of the “Weight” variable. Lines 74 and
movement (i.e., .50 N) was performed window was labeled “Weight Determi- 75 calculate the values associated with
at the beginning of the trial. In addition, nation” and the message “Enter time in 3 SDs above the mean (“WSD_pos3”)
we need to determine the participant’s ms to begin weight determination” was and 3 SDs below the mean
weight. This was done to determine placed inside the window. Although (“WSD_neg3”).
the net force, and our force variables this is a text window, the user should
could be expressed relative to body Lines 78–84 were used to notify the
only input an integer in the window. user if a countermovement was de-
mass later in the script. Graphing the After doing so, the user presses the
force-time curve allows the user to tected before the beginning of the trial.
“Ok” button, and the window closes. The script will look through the Fz
visually inspect the data to determine The value entered by the user is then
if a countermovement was performed data to see if any value is 50 N below
labeled as “trim.” Lines 64–67 use an the variable Weight. Because we do not
at the beginning of the trial and find the “if-else” statement to determine the
flattest portion of the force-time curve, want to include Fz data at the end of
value of “trim.” If the user does not the trial, we need to trim our Fz and
which is used for their weight. enter anything into the popup window, time data. Line 78 uses the “idxmax”
Lines 59 and 60 were used to create lines 64 and 65 tell the script to set the function to find the location of the peak
and display the graph. Line 59 uses trim value equal to zero. This means Fz value in our dataframe. Line 79 uses
“plt.plot” to generate a plot using time that the script will use the beginning the “truncate” method to create a copy
from the “data” dataframe for the x-axis of the data file as the starting point for of the dataframe, df, and remove all
and “Fz” from the “data” dataframe for the weight determination. If the user data after the peak Fz value. This
the y-axis. Line 60 uses the “plt.show” enters a value into the popup window, new dataframe is labeled “df1.” Line
function to display the graph in a sep- the script presented in lines 66 and 67 80 calculates the threshold for detect-
arate window. If needed, the user can converts that value to an integer and ing the countermovement by subtract-
click on the magnifying glass in the calls it “trim.” ing 50 N from the variable Weight.
upper right-hand portion of the win- Line 69 creates a new dataframe called This threshold is labeled as “a.” Lines
dow to zoom in by clicking and drag- “df,” which will be a copy of the “data” 81–84 use an if-else statement to deter-
ging the mouse over the portion of the dataframe that has removed all the mine if the threshold was achieved or
graph where they want to zoom in. data before the value labeled as “trim.” not. Line 81 uses the “any.()” method
The home button (the icon that looks Line 70 calculates the weight by taking to determine if any Fz value in the df1
like a house) can restore the graph to the mean of the first 1,000 data points dataframe is 50 N less than the variable
its original view. After inspecting the of the “Fz” data in the “df” dataframe. Weight. If an Fz value meets this crite-
graph, the user can close the graph This weight variable was labeled as rion, line 82 displays a popup window
by clicking on the “X” in the top “Weight.” Later in the script, this vari- to notify the user that a countermove-
right-hand corner. able is used to calculate net force. Line ment was detected. If no countermove-
For weight determination, 1 full sec- 71 calculates the participant’s mass by ment is detected, line 84 displays
ond of data must be collected while dividing the “Weight” by the absolute a popup window to provide the user
the participant stands quietly without value for gravity (9.81). This mass vari- with the message, “No countermove-
grasping or being strapped to the bar. able is then labeled as “Mass.” Later in ment detected.”
In our setup, we collected the first sec- the script, this variable was used to Lines 87–95 can be used if the user
ond of data while the participant was express the force variables relative to wishes to automate the process of se-
not grasping or strapped to the bar, body mass and allometrically scaling lecting the beginning of the trial
paused data collection to allow them these force variables. instead of using the previously
to secure their lifting straps and grasp Before determining the onset of IMTP, described manual selection method.
bar, and resumed data collection for we should ensure that no excessive Video 1 shows how to use the script
the trial. Because the data were col- movement was being performed with the manual trial start selection
lected at 1,000 Hz, we will need at before the start of the trial. To aid the method and with this automated
least 1,000 data points before the user in this task, we will have the script method. Because these lines begin with
beginning of the movement. After draw horizontal lines on the force- the pound symbol, Python will skip
visually inspecting the graph, the user time curve that correspond to 3 SDs over them to get to line 98, which be-
should be able to identify the time above and below the mean weight of gins the manual selection at the start of
point where this calculation should the first second (i.e., 1,000 data points) the trial. Therefore, if the user wishes to

294 VOLUME 47 | NUMBER 3 | JUNE 2025


Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
use the automated steps, they need to the onset of the IMTP. Lines 98–99 element of that tuple (x value [Time]
remove the pound symbol from lines were used to create a scatter plot using of the selected data point). Although
87–95 and insert the pound symbol at Matplotlib to visualize the force-time the user is now able to display the
the beginning of each line for lines 98– curve data, with “fig” and “ax” repre- onset time above the plot, it is difficult
140. If the user wishes to use the man- senting the figure and axes of the plot, to visually see exactly which data point
ual selection method, they can run the respectively. The “picker 5 True” has been selected on the plot.
script in its current format. The varia- statement allows the user to select data To overcome this, lines 117–121 were
bles “WSD_neg3” and “WSD-pos3” points on the scatter plot. Lines 100 used to draw a vertical line on a Mat-
were used to determine if excessive and 101 draw 2 horizontal black plotlib plot at the x-coordinate of the
movement was performed during the dashed lines corresponding to selected data point. When selecting
quiet standing period. The first step in WSD_pos3 and WSD_neg3. If the Fz a data point for drawing a vertical line,
this automated process is a visual goes above or below 3 SDs before the the user can magnify data points
inspection of the force-time curve. Line start of the trial, the user will be able to around the onset in the plot by activat-
87 uses the “plt.plot()” method to gen- easily identify this excessive movement ing a zoom function located on the
erate a graph with the variable “Time” and discard the trial. Line 104 created
Matplotlib window. When the zoom
from the “df1” dataframe plotted along a variable called “vertical_line” initially
function is active, the user can draw
the x-axis and the variable “Fz” from set to “None.” This was used to draw
a rectangle on the plot to magnify
the same dataframe plotted along the a vertical line on the plot later. Simi-
the selected portion of the force-
y-axis. Lines 88 and 89 add 2 horizontal larly, line 105 created a text that was
trace. During this analysis, the user
black dashed lines to this graph that used to display text on the plot later,
needs to identify the last peak or
correspond to “WSD_pos3” and with the text positioned at coordinates
trough before the signal deviates from
WSD_neg3. Line 90 uses the (0.675, 1.011) relative to the axes’ di-
baseline noise and define this point as
“plt.show()” method to display the mensions rather than data coordinates
the moment of force-onset based on
graph for visual inspection by the user. using “transform 5 ax.transAxes.”
previously published methods (34).
To determine the beginning of the trial, Lines 105–121 were used to create
By clicking on this data point, the script
lines 92–95 used an “if-else” statement. a function to manually identify the
identifies the force and time value that
Line 92 stated if any value within the onset of the IMTP by selecting a data
corresponds to the beginning of the
“Fz” column of the “df1” dataframe point on the plot. Line 108 defined
trial. Line 117 defined the “vertical_-
contained values that are less than or a function named “onpick,” which
line” variable as a global variable. This
equal to the value of “WSD_neg3,” was called when a data point was
is important if the user wishes to mod-
then excessive movement occurred picked on the plot. Line 109 used the
ify a variable within this function (e.g.,
during the quiet stance period, and line “if” statement to check if the “event”
select a different data point to draw
93 would be executed. This line used was associated with the scatter plot,
a new vertical line); this modification
the “sg.popup_error” function to dis- ensuring that this code line was only
can affect other variables outside of the
play a popup window displaying the executed if the selected data point be-
function. Because line 104 is outside of
error message “There was an error longed to the scatter plot. Now, we
this function, this allows the user to
with data collection.” If the “Fz” col- need to create a few lines of code that
check if the “vertical_line” already ex-
umn of the dataframe “df1” does not return the x (Time) and y values (Fz) of
ists (using if vertical_line is not “None”
contain any values that are less than or the selected data point. Line 110 ex-
in Line 118) to avoid creating multiple
equal to the value of “WSD_neg3,” line tracted the index of the selected data
vertical lines by removing the existing
95 used the “index” function to identify point on the plot and assigned it to
“vertical_line” (using “vertical_line.re-
the first value (the zero contained a new variable called “ind.” The “[0]”
move” in line 119) before creating
within the brackets denotes the first was used to only extract the first index
position) of the “Fz” column in the da- in the list of indices. Lines 111–112 a new 1. Line 120 used Matplotlib’s
taframe “df1” that is greater than or were used to find the Time (x-axis) “axvline” method to create a vertical
equal to the value “WSD_pos3.” The and Fz (y-axis) values of the selected line on the plot, with the vertical line
beginning of the trial was given the data point from the dataframe “data” positioned at the x-coordinate (Time)
label “start.” using the index defined earlier. Line of the selected data point. Line 121 was
113 was used to assign a tuple contain- used to add a legend to the plot, with
the created vertical line labeled as
MANUAL IDENTIFICATION FOR ing “x_value” and “y_value” to the first
THE LOCATION OF THE ONSET element of the “onset” list. Line 114 “Onset Time.”
Now that we have installed a CSV file was used to display the onset time (x Now that we have defined the “onpick”
and created a working dataframe, we value) of a selected data point using event function, line 124 connected this
must start trimming the force-time Matplotlib’s “set-text” method, with function to the scatter plot using the
curve to calculate various metrics. the text set to “onset[0][0],” which al- Matplotlib event handling method
The most important step is to identify lowed the user to access the first (“.mpl_connect”). The event type was

295
Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Python & Isometric Force-Time Curves

set to “pick_event,” which means that “df2” dataframe. Line 145 tells the calculated at 1,000 Hz, each row rep-
when the user interacts with a plot by script to subtract the “Time” associated resents the time of 1 ms. Therefore, we
clicking on a data point within the plot, with the start of the trial from each row used “df2.Fz.iloc[50]” to determine the
the “pick_event” is triggered. When in the “Time” column. The “iloc[0]” gross peak force at 50 ms. The same
this occurs, the “onpick” function refers to the first value associated with function was applied for each epoch,
defined earlier is executed. Line 126 the “Time” column of the “df2” thus creating the variables gF50,
was used to set the title of the plot, dataframe. gF100, gF150, gF200, and gF250,
and the text defined in line 127 (onset which represented the gross peak force
time) was displayed above the under- at 50, 100, 150, 200, and 250 ms,
line “______” in the plot. Lines 128– CALCULATING METRICS
respectively. Similarly, the “iloc[]”
129 were used to label the x-axis and Now that we have a working data-
function was applied to the “net_-
y-axis of the plot as “Time” and “Fz,” frame containing only the IMTP data,
Force” column of the “df2” dataframe
respectively. Line 131 was used to dis- we can calculate the various force-time
to calculate the net force at each epoch.
play the plot, where the user can click curve metrics. Line 148 used the
The net force at 50, 100, 150, 200, and
on a data point to execute line 124. In “apply” and “lambda” functions to cre-
250 ms were labeled “F50,” “F100,”
case the user wishes to know what the ate a new column, called “net_Force,”
“F150,” “F200,” and “F250,” respec-
force value (Fz) was at the onset time, within the dataframe called “df2.” This
tively. The relative net force at each
lines 128–129 were used to print infor- new variable was calculated by sub-
epoch was calculated by dividing
mation about this. tracting “Weight” from each row in
“F50,” “F100,” “F150,” “F200,” and
the “Fz” column. Line 149 determined
“F250” by the individual’s mass
the peak net force in this dataframe.
TRIMMING THE FORCE-TIME (“Mass”). These relative net forces
CURVE This variable is given the label “Peak_-
Force.” Because the data in this data- were labeled “relF50,” “relF100,”
After we have identified the beginning “relF150,” “relF200,” and “relF250.”
of the trial, we can trim the force-time frame proceeded from the beginning of
the IMTP trial until peak force was The allometrically scaled peak forces
curve to only include the data from the for each epoch were calculated by
start of the trial until peak Fz. Line 143 achieved, we used “iloc[-1]” to find
the last value in the “net_force” column dividing the net force for each epoch
creates another dataframe, called “df2.” by the value labeled “e” and were
This line of code uses the “truncate” of “df2.” Line 151 calculated the peak
net force relative to body mass. This is labeled according to each epoch
method to make a copy of “df1” and (“allF50,” “allF100,” “allF150,”
remove all data before the start of the accomplished by dividing “Peak_-
Force” by “Mass.” This variable was “allF200,” and “allF250”).
trial. Because this method maintains
the original index of df1, we need to labeled “relPeak_Force.” Line 152 cal- Now, we can put these force metrics
reset the index so that the first data culated the allometrically scaled peak into a separate dataframe, which will
point is associated with the index of net force (“allPeak_Force”). This vari- be used later to create a table for our
0. Line 144 uses the “reset_index” able was calculated by dividing the net report. Lines 178–184 created a list of
method to accomplish this task. Now, peak force by the individual’s body information to create the dataframe. This
we have a dataframe that reports the mass raised to the two-thirds power. list is labeled “dict.” The first row in the
first “Fz” value at the start of the trial in Line 150 calculated the body mass list will contain the information for the
the first row of the “Fz” column. How- raised to the two-thirds power and first column, which are “Variable,” “Gross
ever, the “Time” value is still relative to labeled this value as “e.” In Python, Force,” “Net Force,” “Relative Force,”
the start of data collection (i.e., at the using double asterisks (**) denotes and “Allometrically Scaled Force.” The
start of the system weight determina- using an exponent. Therefore, the allo- second row in the list will contain the
tion or earlier). To make the “Time” metrically scaled peak net force in line peak force variables, which will be dis-
values relative to the start of the trial, 152 is calculated by dividing the played in the second column. Each sub-
we need to create a function that will “Peak_Force” by “e.” sequent row in the list will contain the
subtract the time at which the trial Lines 155–175 calculated the gross force data for each epoch (50 ms data in
started from every row in the “Time” peak force, net peak force, relative column 3, 100 ms data in column 4, etc).
column of the “df2” dataframe. Line net force, and allometrically scaled Information contained within the apos-
145 creates a new variable column peak net forces for specific epochs trophes is a string of characters (i.e., text)
called “nTime” in the “df2” dataframe. (50, 100, 150, 200, and 250 ms). Line that will be displayed in the dataframe.
The values in this column were calcu- 155 calculated the gross peak force by Information contained within the brack-
lated by applying a function to each using the “max()” function on the “Fz” ets without apostrophes will be the val-
row in the dataframe. The “apply” column of the “df2” dataframe. The ues previously calculated. Line 185
and “lambda” functions were used to gross peak force for each epoch was converted this list into a dataframe using
create an equation and to apply it to determined by applying the “iloc[]” the method “pd.DataFrame.from_dict.”
each row in the “Time” column of the function. Because the data were This new dataframe was labeled “df3.”

296 VOLUME 47 | NUMBER 3 | JUNE 2025


Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Because of the high degree of precision the force at the appropriate epoch from corresponding to the last window
that Python can produce, these newly the force at the start of the trial and being on the last row. Line 214 created
calculated variables will be displayed to divide this difference by the epoch win- a new column for this “df6” dataframe,
a high number of decimal places. Line dow. Because we wanted to express called “movingRFD.” Data in this col-
186 allowed the user to round the calcu- RFD in newtons per second, we con- umn were calculated by dividing the
lated variables to a specific number of verted the time in milliseconds to sec- difference between the “lastFz” value
decimal places. From the NumPy pack- onds for these calculations. Lines 204– and the “firstFz” value for each row
age, we used the “round” function on 206 calculated the RFD for 50–100 ms, by 0.02 seconds (20 ms). Therefore,
“df3” and had Python round these vari- 100–200 ms, and 200–250 ms, respec- the “movingRFD” column contains
ables to 1 decimal place. tively, using a similar process. Instead the RFD for every 20 ms time interval
of subtracting the force at the end of over the entire trial. Line 215 used the
Lines 189–195 were used to calculate
each epoch from the force produced at “max()” function to find the maximum
the impulse for the entire trial and for
the start of the trial, we subtracted the value in the “movingRFD” column.
specific epochs. Impulse was calculated
force at the end of each epoch from the This value represented the pRFD and
by integrating force and time. Using
force at the beginning of each epoch. was labeled “pkRFD.”
the trapezoid rule for integration, line
189 applied the “integrate” function To find the pRFD, we need to create Lines 218–225 used our impulse data
from the SciPy package to the “Fz” a moving window that will scroll to create a dataframe as a table in our
and “ntime” columns of data within through the “Fz” column of the “df2” final report. Lines 218–223 created a list
the “df2” dataframe. This cumulative dataframe. Because each row repre- containing labels for column headings
integration was placed in a new col- sented 1 ms, we can set the size of this and variables in brackets correspond-
umn labeled “Impulse.” To determine window to 20, which represents ing to the appropriate column heading.
the impulse at specific time points, we a 20 ms moving window. We chose Line 224 converted this list to a data-
used the “iloc[]” function again to spec- a 20 ms window because of the pre- frame labeled “df4,” and line 225
ify each time point. Line 190 deter- vious research that has reported that rounded our calculated values to 1 dec-
mines the impulse for the entire trial this window has the best level of reli- imal place.
by finding the last value in the ability (ICC 5 0.90, 90% CI 5 0.73– Assessing muscle strength asymmetry
“Impulse” column. This value was 0.97; CV% 5 12.9%, 90% CI 5 0.5– may be useful in determining muscular
labeled “IMP.” Lines 191–195 deter- 20.7) (16). Line 209 created a variable strength imbalances between the
mined the impulse for each of the pre- called “window_size” equal to 20. limbs. From an athletic monitoring
viously mentioned epochs and were Lines 211 and 212 moved this 20 ms perspective, tracking changes in mus-
labeled correspondingly (“IMP50,” window through “Fz” column of the cle strength asymmetry can provide
“IMP100,” “IMP150,” “IMP200,” and “df2” dataframe. Line 211 applied the the practitioner with potentially useful
“IMP250”). lambda function to each window as it information regarding the athlete’s
To calculate RFD, we needed to know scrolled through the data to find the training progress. The asymmetry
the gross force (or net forces) values at last “Fz” value in each 20 ms window. index can be calculated as a percentage
2 specific time points and the corre- So, the first value it found was 20 ms by dividing the difference in gross peak
sponding time interval. Lines 198–206 after the start of the trial, the next value force between the limbs by the gross
calculated average RFD and the RFD found was 21 ms after the start of the peak force of the dominant leg. The
for specific epochs. To calculate the trial, and so on. These values were put dominant leg is identified as the limb
change in force, we must subtract into a list called “lastFz.” Similarly, line that produces the greatest gross peak
“gPeak_Force” from the first “Fz” value 212 scrolled through the “Fz” data of force. Lines 229–234 used an “if-else”
in the “df2” dataframe. Because the the “df2” dataframe to find the first “Fz” statement to identify the dominant and
“ntime” column starts with 0 seconds value in each 20 ms window. So, the nondominant limbs and to determine
at the start of the trial, we can find the first value found was at the start of the the gross peak force for each limb.
change in time by finding the last value trial, the second value found was 1 ms Lines 229–231 state that if the left limb
in the “ntime” column using the “iloc after the start of the trial, and so on. produced a larger gross peak force than
[-1]” function. Line 193 calculated the These values were put into a list called the right limb, the left limb will be des-
average RFD by dividing this differ- “firstFz.” These 2 lists, “lastFz” and ignated as the dominant limb and left
ence in force values by the time elapsed “firstFz,” were converted to a data- limb’s gross peak force is assigned to
from the start of the trial to the time Frame, called “df6,” in line 213 using the value “d.” The right limb’s gross
associated with peak force. The RFD the “pd.DataFrame” function. Each peak force would be assigned to the
for 50, 100, 150, 200, and 250 ms were row in this dataframe represented value “n.” If the left limb’s gross peak
calculated on lines 199–203, respec- 1 20 ms window, with data corre- force is not larger than the right limb’s
tively. The process for each of these sponding to the first window being gross peak force, lines 233 and 234
RFD epochs was the same: subtract on the first row and data designate the right limb as the

297
Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Python & Isometric Force-Time Curves

dominant limb (“d”) and the left limb as function. The title for this plot was and tables on the computer screen.
the nondominant limb (“n”). Line 237 “IMTP using Weight.” Line 259 cre- Line 273 used PySimpleGUI’s “Can-
calculated the asymmetry index and ated the second graph for the subplot vas” function to create a canvas for
labeled this value as “asymmetry_in- using the “ntime” and “Fz” data from the subplot. The “key” argument was
dex.” If the user has a single force plate, the “df2” dataframe.” Line 260 gener- used as an identifier for the canvas.
they would not be able to calculate ated the title for the second plot. Lines Later in the script, we embedded the
asymmetry index. Therefore, they can 216 and 262 created the final plot by subplot into this canvas. The “size”
skip lines 227–237. plotting the gross force values for each argument provided the dimensions
Lines 238–243 created a list, called limb (“lFz” and “rFz”) from the “df2” for how big the canvas should be.
“dict_RFD” for the RFD data for aver- dataframe along the y-axis and “ntime” The first value indicated the width,
age RFD, RFD at 50 ms, RFD at from the “df2” dataframe along the and the second value indicated the
100 ms, RFD at 150 ms, RFD at x-axis. The “label” arguments for lines height of the canvas in pixels.
200 ms, and RFD at 250 ms. Lines 261 and 262 were used to identify the Lines 274–281 were used to display the
244–248 created a list, called left and right legs on the graph. Line tabular data in 4 different tables on the
“dict_RFDs,” for the RFD for 50– 263 generated the title for this third
computer screen. Lines 274 and 275
100 ms, the RFD for 100–200 ms, the graph, “IMTP for Left and Right Legs.”
were used to display the data from
RFD for 200–250 ms, pRFD, and the Line 264 used the “legend” function to
the “df3” dataframe, which contained
asymmetry index. Again, if the user is display the legend for the third plot. If
our force data. The “values.tolist()”
collecting data from a single force the user collects data from a single
function was used to convert the pan-
plate, they can remove the reference force plate, they would not need lines
das dataframe to a list and used the
to asymmetry index on line 248 of 261–264. In addition, they would re-
values in the table. The “columns.to-
the script. These lists were converted move “ax3” from line 256 and change
list()” function was used to extract
to dataframes, called “df5” and “df6,” the “3” in parentheses on this line to
the column headings from the data-
respectively, on lines 249 and 252. “2,” which changes the number of col-
frame and use them as the first row
Lines 205 and 253 rounded the values umns from 3 to 2.
in the table. The “size” argument was
associated with each dataframe to 1 After creating the subplot, it was saved used to specify the width in characters
decimal place. These dataframes were in the computer’s memory buffer as an and height in rows for the table.
used later in the script to generate ta- image file to be used later in the script Because the text in the first column
bles in our report and display this data to create the report and display the can take up more space than the other
on the GUI. image within the GUI. Line 267 cre- columns, we set the “auto_size_col-
ated a new variable called “subplot_i- umns” argument to “True” to allow
mage_buffer” and assigned it to an Python to adjust the column width
CREATING GRAPHS
instance of the “BytesIO” class, a class based on the text in the column for
To create the 3 graphs that will be dis- within Python’s “io” module. This the first and last table in the layout.
played within the GUI and in the module allowed the user to work with To make the table visually appealing,
report, we used Matplotlib’s pyplot binary data like a file. In this case, we we set the “justification” for each table
library. To arrange the plots side-by- used “BytesIO” to create an in-memory to “center” and the “font” to “Helveti-
side with similar dimensions, we had buffer where the image data were ca” with a font size of “12.” The second
Python create a subplot containing all stored. Line 268 the “plt.savefig” to and third tables had fewer characters in
3 graphs. Line 256 in the script gener- save the subplot into the variable, “sub- the first column, so we did not need to
ated the subplot function to create 1 plot_image_buffer.” The “format” argu- allow Python to autosize the columns.
figure that contained all 3 graphs with ment was used to save the image as In addition, these tables consisted of 2
3 separate axes. Because we wanted the a “PNG” file. When the image is saved
plots to be displayed side-by-side, we rows for each table. So, the “size” argu-
into the buffer, the pointer scrolls ment was set to 40 characters and 2
specified the number of rows to be 1 through the data from the beginning
and the number of columns to be 3. rows. Each “sg.Table” function was
of the file to the end. Line 269 resets contained within its own brackets to
Therefore, Python placed the 3 graphs the position of the pointer to the begin-
within a single row, each taking up 1 have the GUI display the tables below
ning of the file by using the “seek(0)” each other rather than side-by-side.
column across the page. The “figsize” method. This prepared the buffer to be
argument determined the width and read from the start when we called the Line 282 used the “sg.Text” function to
height for the entire subplot. Line image later in the script. display the instructions “Save PDF
257 used the “plot” function to graph Report as:.” Line 283 had 3 elements
the “Time” and “Fz” columns from the CREATING GRAPHICAL DISPLAY displayed on the GUI below these in-
“df1” dataframe for the first plot within OF DATA structions. The first element was an
the subplot. Line 258 created the title Lines 272–285 created a layout that “sg.Input” that displays the file path
for this plot using the “set_title” tells Python how to display the subplot when the user saves the PDF report.

298 VOLUME 47 | NUMBER 3 | JUNE 2025


Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
This input was given the key “file_- can be placed on the GUI. Therefore, key “file_save,” line 302 extracted the
save,” which was used later in the this line of code tells Python to treat file path and labeled it “pdf_filename.”
script. The next element was the “sg.Fi- the subplot as a widget and place that Lines 303–306 were checked to ensure
leSaveAs,” which allowed the user to widget on a canvas. Line 293 uses the the file path was not empty and to see if
open a dialog box so that the user “get_tk_widget()” and “pack” functions the file name ended in “.pdf.” If the
could navigate to the location where to pack the widget containing the sub- filename doesn’t end in “.pdf,” line
they wanted to save the file. This ele- plot onto the “sg.Canvas” element of 306 appended “.pdf”” to the filename.
ment was displayed as a button with our layout. We wanted the subplot to Line 308 used the “SimpleDocTem-
the word “Browse” written on it. The be packed into the canvas space, start- plate” class from the reportlab library
last element displayed on this row used ing at the top and filling up the space to generate the PDF document. It spec-
the “sg.Button” element to create a but- allocated for the widget horizontally ified the file name (“pdf_filename”) and
ton on the GUI labeled “Exit.” Because and vertically. The argument “side” set the page size to “letter.” Line 310
all 3 elements were contained within was set to “top” to pack the widget created an empty list called “elements.”
a single pair of brackets, they were dis- starting at the top of the first row in Later in the script, this list will contain
played on a single row of the GUI. Line the canvas. The argument “fill” was set all the elements to be displayed in the
284 used the “sg.Button” element to to “both” to have the widget fill any report.
create another button at the bottom extra space allocated for the canvas, Line 312 created an image from “sub-
of the GUI and was labeled “Save.” horizontally and vertically. The argu- plot_image_buffer.” This image was
The layout described above was sim- ment “expand” was set to “1” or “True” saved as the variable “subplot.” The last
ply a plan for arranging the different to tell Python to fill up any extra space 2 arguments in parenthesis specified
elements on the GUI. Our next step in the window that was not used by the width and height of the image in
was to create a window that would other elements. points (1 point was equal to 1/72 inch).
contain this layout. Line 288 used the GENERATING THE REPORT The image was set to 700 points wide
“sg.Window” element to create a dis- Normally, pressing any button on the and 250 points tall. Line 312 appended
play window on the computer screen. GUI would close the window. To the image called “subplot” to the list
This window was labeled “window2” make a persistent window (i.e., keep labeled “elements.”
and contained the “layout” for the ele- the window open indefinitely unless Lines 315–369 were used to create the
ments mentioned above. The window the user clicks the “X” in the top right tables in the PDF document. Creating
was also given the title “Inspect Force- corner of the window or clicks the and placing the tables in the document
Time Curve.” The “finalize 5 True” “Exit” button), we created an infinite was the same for each table. Lines 315,
argument initializes the window. To loop on lines 296–372. Line 296 started 329, 343, and 357 created the data-
allow the window to be resized, the the infinite loop with the statement frames for generating each table. The
argument “resizable” was set equal to “while True:” This loop continued to “columns.tolist()” was used to extract
“True.” run until a “break” statement was the column names from the corre-
After this display window was created, encountered. Line 297 reads an event sponding dataframe and add them to
we instructed Python to place the dif- and associated values from the GUI a list. The “values.tolist()” extracted the
ferent elements in the window, using window labeled “window2.” Line 298 values from the corresponding data-
the layout as a guide. Lines 291–293 began an “if” statement. The code “if frame and converted them to a list of
created a canvas and placed it on the event 5 5 sg. WIN_CLOSED or lists. The inner list corresponded to
window. Because the canvas was the event 5 “Exit”:” on line 298, checked a row in the dataframe; the outer list
first element in our layout, it will be if the event is either the window is contained all the rows. The brackets
displayed at the top of the window. closed by clicking on the “X” in the surrounding the “.columns.tolist()”
The “sg.Canvas” element in line 273 upper right-hand corner of the window were used to create a list of columns.
was given the key “-CANVAS-.” Line or if the event was an “exit” event This was done to preserve the structure
291 created the variable “canvas_elem” (i.e., the user clicked “Exit”). If either of the lists because the list of column
that identified the key “-CANVAS-” to of these events took place, line 299 headings and list of values were con-
be displayed in “window2.” Essentially, used the “break” to break out of the catenated by using the “+.” Lines 316–
this line of code tells Python to put the infinite loop. Line 300 checked to see 317, 330–331, 344–345, and 358–359
variable “canvas_elem” at the top of if the user clicked the “Save” button. If were used to create the “force_table,”
“window2” where we had identified this event was true, the script pro- “impulse_table,” “RFD_table,” and
the canvas to be placed. Line 292 cre- ceeded to lines 302–372 to generate “RFDs_table” by using the “Table”
ated a variable called “canvas” that the PDF report. If the user clicks the class from the reportlab library. The
used the “FigureCanvasTkAgg” class “Save” button, the script extracts the first argument inside the parentheses
to embed our subplot, called “fig” in filepath from the “sg.Input” on line identified the appropriate dataframe
a widget, which is a class or object that 283. Because this line of code has the for each table. The second argument

299
Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
Python & Isometric Force-Time Curves

sets the column widths for each col- 362. The last line of the script closed
J. Chadwick
umn in inches. The first value in this the GUI window labeled “window2.”
Smith, PhD is
list corresponded to the first column,
a Professor in the
and the last value to the last column. CONCLUSIONS Department of
The “spaceAfter” argument added IMTP and isometric squat testing can Kinesiology at
extra space (10 points) after the table be a useful diagnostic tool for athlete Coastal Carolina
to create some separation between ta- monitoring as peak force, impulse, and University.
bles and improve the visual layout of RFD measures can be obtained from
the PDF document. the ground reaction forces collected
Lines 318–326, 332–340, 346–354, during these tests. In addition, when
and 360–368 configured the styling these tests are performed on 2 force
of each table in the PDF document. plates, limb asymmetries can also be Tsuyoshi
The “setStyle” method was used to evaluated. To ensure the accuracy of Nagatani, MS
instruct Python to use the parameters these tests, a standardized protocol is a PhD candi-
that follow to set the visual style of the that includes a thorough warm-up date in the area
dataframe. The “TableStyle” class in- must be followed to improve test- of Sports Science
structed Python to apply this style to retest reliability. Although these tests and a member of
the table. The first “BACKGROUND” are useful diagnostic tools, the manual the Strength and
line determined the background color calculation of each force-time curve Power Research
for the header of the table. The “(0, 0)” metric or identification of force-onset Group at Edith
refers to the first column and first row. can be time-consuming, especially Cowan
The (21, 0) refers to the last column when analyzing multiple trials for large University.
of the first row. The “(0.8, 0.8, 0.8)” groups of athletes. One strategy for this
specified the RGB color, which is issue is using commercially available
a light gray, to be applied to this first software programs to rapidly analyze Stuart N.
row in the table. Typically, RGB val- isometric trials. However, purchasing Guppy, PhD is
ues range from 0 to 255. In this case, these programs can be cost- a Lecturer of
Python used a floating-point scale, so prohibitive for some users, and often, Exercise and
values ranged between 0 and 1 to how the force-time is filtered and as- Sport Science
determine the RGB values. The sessed is proprietary information. To (Strength &
“TEXTCOLOR” line applied black allow greater control of the analysis Conditioning)
to the text in this first row for each procedures, users can create a template and member of
table. The “ALIGN” line applied cen- in Excel to analyze their isometric data. the Strength and
ter alignment to the entire table. The Analyzing multiple trials using spread- Power Research
“FONTNAME” applied the font type sheet software may be less time- group in the School of Medical and
“Helvetica-Bold” to the first row to efficient than creating a custom script Health Sciences at Edith Cowan
distinguish the column names from to analyze isometric force data. The University.
the rest of the table. The “FONT- focus of this paper was to assist the user
SIZE” line is applied to the table to with creating a custom script using the
make the font size “10.” The “BOT- programming language, Python. The G. Gregory
TOMPADDING” added 8 points of script created by this guide could be Haff, PhD is the
padding below the header column. used to completely automate the anal- Professor of
The last “BACKGROUND” line for ysis of isometric trials or allow for the Strength and
each section specified the background manual selection of the start of each Conditioning,
color, a lighter gray than the back- trial before automating the rest of the and the Director
ground color for the column headings, data analysis. Finally, this paper dis- of the Strength
for the rest of the table, excluding the cussed a method to generate a report and Power
header row. Lines 327, 341, 355, and that can be used to disseminate test Research Group
369 used the “append” method to add results. in the School of
each table to the list labeled “ele- Medical and Health Sciences at Edith
ments.” On line 366, the PDF docu- Cowan University.
ment was generated by calling the
“doc.build (elements).” Finally, the Conflicts of Interest and Source of Funding:
script broke out of the infinite loop The authors report no conflicts of interest REFERENCES
1. Beckham G, Mizuguchi S, Carter C, et al.
with the “break” statement on line and no source of funding. Relationships of isometric mid-thigh pull variables

300 VOLUME 47 | NUMBER 3 | JUNE 2025


Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.
to weightlifting performance. J Sports Med Phys both testing protocol and analysis choices. midthigh pull in young female athletes. J Strength
Fitness 53: 573–581, 2013. J Strength Cond Res 36: 1191–1199, 2022. Cond Res 32: 1892–1901, 2018.
2. Bishop C, Read P, Lake J, Chavda S, Turner A. 14. Haff GG. Isometric and dynamic testing. In: 26. Norris D, Joyce D, Siegler J, Clock J, Lovell R.
Interlimb asymmetries: Understanding how to Performance Assessments for Strength and Recovery of force–time characteristics after
calculate differences from bilateral and unilateral Conditioning Coaches. Comfort P, Jones PA, and Australian rules football matches: Examining the
tests. Strength Cond J 40: 1–6, 2018. McMahon JJ, eds. Oxon, United Kingdom: Taylor utility of the isometric midthigh pull. Int J Sports
3. Brady CJ, Harrison AJ, Flanagan EP, Haff GG, Francis Books, 2019. pp. 168–194. Physiol Perform 14: 765–770, 2019.
Comyns TM. A comparison of the isometric mid- 15. Haff GG, Carlock JM, Hartman MJ, et al. Force- 27. Pickett CW, Nosaka K, Zois J, Blazevich A.
thigh pull and isometric squat: Intraday reliability, time curve characteristics of dynamic and Relationships between midthigh pull force
usefulness and the magnitude of difference isometric muscle actions of elite women olympic development and 200-m race performance in
between tests. Int J Sports Physiol Perform 13: weightlifters. J Strength Cond Res 19: 741–748, highly trained kayakers. J Strength Cond Res 35:
844–852, 2018. 2005. 2853–2861, 2021.
4. Buckner SL, Jessee MB, Mattocks KT, et al. 16. Haff GG, Ruben RP, Lider J, Twine C, Cormie P. A 28. Seitz LB, Reyes A, Tran TT, Saez de Villarreal E,
Determining strength: A case for multiple methods comparison of methods for determining the rate of Haff GG. Increases in lower-body strength transfer
of measurement. Sports Med 47: 193–195, 2017. force development during isometric midthigh clean positively to sprint performance: A systematic
5. Chavda S, Turner AN, Comfort P, et al. A practical pulls. J Strength Cond Res 29: 386–395, 2015. review with meta-analysis. Sports Med 44: 1693–
guide to analyzing the force-time curve of isometric 17. Haff GG, Stone MH, O’Bryant HS, et al. Force- 1702, 2014.
tasks in Excel. Strength Cond J 42: 26–37, 2020. time dependent characteristics of dynamic and 29. Smith JC. Using Python to analyze multiple
6. Comfort P, Dos’Santos T, Beckham GK, Stone isometric muscle actions. J Strength Cond Res countermovement vertical jumps over time.
MH, Guppy SN, Haff GG. Standardization and 11: 269–272, 1997. Strength Cond J. 2024;46:369–377.
methodological considerations for the isometric 18. Helme M, Tee J, Emmonds S, Low C. Does lower- 30. Stone MH, O’Bryant HS, Hornsby G, et al. Using
mid-thigh pull. Strength Cond J 41: 57–79, 2019. limb asymmetry increase injury risk in sport? A the isometric mid-thigh pull in the monitoring of
7. Cormie P, McGuigan MR, Newton RU. Developing systematic review. Phys Ther Sport 49: 204–213, weighlifters: 25+ years of experience. Prof
maximal neuromuscular power: Part 1—biological 2021. Strength Cond 54: 19–26, 2019.
basis of maximal power production. Sports Med 19. James LP, Talpey SW, Young WB, Geneau MC, 31. Suchomel TJ, Nimphius S, Stone MH. The
41: 17–38, 2011. Newton RU, Gastin PB. Strength classification importance of muscular strength in athletic
8. De Witt JK, English KL, Crowell JB, et al. Isometric and diagnosis: Not all strength is created equal. performance. Sports Med 46: 1419–1449, 2016.
mid-thigh pull reliability and relationship to deadlift Strength Cond J 45: 333–341, 2023. 32. Thomas C, Comfort P, Chiang C, A Jones P.
1RM. J Strength Cond Res 32: 525–533, 2018. 20. Joffe SA, Tallent J. Neuromuscular predictors of Relationship between isometric mid-thigh pull variables
9. Guppy SN, Brady CJ, Comfort P, Haff GG. The competition performance in advanced and sprint and change of direction performance in
isometric mid-thigh pull: Review and methodology international female weightlifters: A cross- collegiate athletes. J Trainology 4: 6–10, 2015.
part II. Prof Strength Cond 51: 21–29, 2018. sectional and longitudinal analysis. J Sports Sci 33. Thomas C, Comfort P, Dos’Santos T, Jones PA.
10. Guppy SN, Brady CJ, Kotani Y, et al. A comparison 38: 985–993, 2020. Determining bilateral strength imbalances in youth
of manual and automatic force-onset identification 21. Kraska JM, Ramsey MW, Haff GG, et al. basketball athletes. Int J Sports Med 38: 683–
methodologies and their effect on force-time Relationship between strength characteristics and 690, 2017.
characteristics in the isometric midthigh pull. unweighted and weighted vertical jump height. Int 34. Tillin NA, Jimenez-Reyes P, Pain MT, Folland JP.
Sports Biomech: 23: 1–18, 2024. J Sports Physiol Perform 4: 461–473, 2009. Neuromuscular performance of explosive power
11. Guppy SN, Brady CJ, Kotani Y, Stone MH, Medic 22. Malone S, Hughes B, Doran DA, Collins K, athletes versus untrained individuals. Med Sci
N, Haff GG. The effect of altering body posture Gabbett TJ. Can the workload-injury relationship Sports Exerc 42: 781–790, 2010.
and barbell position on the between-session be moderated by improved strength, speed and 35. Tran TT, Lundgren L, Secomb J, et al. Comparison
reliability of force-time curve characteristics in the repeated-sprint qualities? J Sci Med Sport 22: of physical capacities between nonselected and
isometric mid-thigh pull. Sports 6: 162–177, 29–34, 2019. selected elite male competitive surfers for the
2018. 23. McGuigan MR, Newton MJ, Winchester JB, national junior team. Int J Sports Physiol Perform
12. Guppy SN, Brady CJ, Kotani Y, Stone MH, Medic Nelson AG. Relationship between isometric and 10: 178–182, 2015.
N, Haff GG. Effect of altering body posture and dynamic strength in recreationally trained men. 36. Wang R, Hoffman JR, Tanigawa S, et al. Isometric
barbell position on the within-session reliability and J Strength Cond Res 24: 2570–2573, 2010. mid-thigh pull correlates with strength, sprint, and
magnitude of force-time curve characteristics in 24. Merrigan JJ, Stone JD, Galster SM, Hagen JA. agility performance in collegiate rugby union players.
the isometric midthigh pull. J Strength Cond Res Analyzing force-time curves: Comparison of J Strength Cond Res 30: 3051–3056, 2016.
33: 3252–3262, 2019. commercially available automated software and 37. West DJ, Owen NJ, Jones MR, et al. Relationships
13. Guppy SN, Kotani Y, Brady CJ, Connolly S, custom MATLAB analyses. J Strength Cond Res between force-time characteristics of the isometric
Comfort P, Haff GG. The reliability and magnitude 36: 2387–2402, 2022. midthigh pull and dynamic performance in
of time-dependent force-time characteristics 25. Moeskops S, Oliver JL, Read PJ, et al. Within- and professional rugby league players. J Strength
during the isometric midthigh pull are affected by between-session reliability of the isometric Cond Res 25: 3070–3075, 2011.

301
Strength and Conditioning Journal | www.nsca-scj.com

Copyright © National Strength and Conditioning Association. Unauthorized reproduction of this article is prohibited.

You might also like