Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Authored by Souvik Mandal, Ph.D.

Project Leader & Instructor, Computational Behavioral Sciences, LS100, FAS, Harvard University | Linkedin ID: souvik-mandal-phd


Last updated: 2026-07-02

Open in Colab Open in GitHub Codespaces

1. Data Exploration: Counting total number of frames in each file

Loading...

2. Detecting the “inflection point” for each angle

2.1. Data Exploration with one file:

Loading...
(291, 10)
<Figure size 1400x1000 with 2 Axes>

3. Finding the Last “Inflection Point” - the local extremum.

3.1. Goal and working definition for the local extremum search on one file

Our goal is to find, for each angle column, the last meaningful turning point near the end of the movement.

In this notebook, we are not using the strict calculus idea of an inflection point. Instead, we are looking for a local extremum: a peak or a valley where the direction of motion changes. In practical terms, this is a point where the first derivative changes sign after smoothing.

Working definition

For each angle series, we will search only within the last part of the movement and identify the last stable turning point. A turning point is where the smoothed slope changes state, for example:

  • upward to downward

  • upward to flat

  • downward to upward

  • downward to flat

  • flat to upward

  • flat to downward

Search region

Instead of hard-coding a fixed number of frames, we will define the search window from the size of the file itself.

If a file has n total frames, then the turning-point search will be restricted to the last n / 4 frames. This makes the method scale naturally for shorter and longer files.

Process we will use

  1. Take one angle column at a time.

  2. Restrict the search to the last n / 4 frames.

  3. Smooth the signal with a Savitzky-Golay filter so small frame-to-frame noise does not create false direction changes.

  4. Compute the first derivative of the smoothed signal. This derivative represents the slope of the line at each frame.

  5. Classify each slope as up, down, or flat using a threshold.

  6. Scan backward from the end and return the row index of the last clear state change.

  7. If no clear change is found in that tail region, return None.

How we will define the threshold

The threshold will be derived from the last slope value after smoothing. The idea is to compare earlier slopes against the movement trend at the end of the action.

Because the final slope may sometimes be very small, we will likely pair this rule with a small minimum floor so that tiny fluctuations are not treated as meaningful direction changes.

This gives us a rule that is easy to explain to students:

  • smooth the signal first

  • estimate the slope near the end of the motion

  • use that end-of-motion slope to decide what counts as up, down, or flat

Outputs we want

We want two levels of output for each file:

  1. A separate row index for each of the 6 angle columns.

  2. One combined global event frame for the file as a whole.

Working definition for the global event frame

A practical first approach is to calculate the turning point for each column separately, keep only the valid row indices, and then combine them into one global event frame using the median of the detected row indices.

The median is a good starting choice because it is less sensitive to one unusual column than the mean. If too few columns produce a valid turning point, then the global event frame can also be set to None.

So the final result for one file will be:

  • 6 individual turning-point row indices, one per angle column

  • 1 global event frame based on the combined information from those columns

Loading...

3.2. Trimming the files properly using the global event frame

Our next goal is to create a new trimmed version of each file using the detected global_event_frame as the reference point.

The final output file should always contain 240 frames. To do that, we will first align the file around the global event frame and then adjust the file length according to a simple set of rules.

Goal

For each input file, we want to create a new output dataframe that:

  • keeps the movement up to the detected global_event_frame

  • removes frames that occur after that event frame

  • ends with exactly 240 rows in the saved output file

The output filename will be the same as the input filename, but with _trimed inserted before the .csv extension.

For example:

  • input: example.csv

  • output: example_trimed.csv

Step-by-step trimming logic

  1. Start with the original input file.

  2. Find the global_event_frame for that file.

  3. Remove every frame that comes after the global_event_frame.

After that first trimming step, we count the number of rows that remain and store that value in a variable called num_frames.

We then handle three possible cases:

Case 1: num_frames > 240

If more than 240 frames remain, trim the extra frames from the beginning of the file. In other words, remove num_frames - 240 rows from the start so that the output keeps the most recent 240 frames leading up to the event frame.

Case 2: num_frames == 240

If exactly 240 frames remain, no additional trimming is needed. Save the dataframe directly as the output file.

Case 3: num_frames < 240

If fewer than 240 frames remain after trimming at the event frame, we need to add more frames back into the output. These extra frames should be taken starting from the global_event_frame and extending forward from that point, rather than starting from the very end of the original file.

This means the event frame remains the anchor, and we extend the trimmed dataframe by adding the next available rows after the event frame until the final output reaches 240 frames.

Why this method is useful

This trimming strategy makes the files more comparable because every output file has the same length, while still keeping the detected global event as the key reference point.

So each output file will:

  • be centered around the event logic used in the earlier step

  • preserve the lead-up to the event

  • contain exactly 240 frames whenever enough data are available in the original file

  • be saved as a new file with _trimed added to its name

Loading...

The task ends here. However, we can do some additional data investigations, as shown below.


4. Check Data Structure: Data Distribution


File: LS100_FInalData_10_final_kinematics_healed_id__angles_training_sheet.csv
<Figure size 1600x800 with 6 Axes>

File: LS100_FInalData_11_final_kinematics_healed_id__angles_training_sheet.csv
<Figure size 1600x800 with 6 Axes>

5. Understanding the statistics of each angle:

Loading...