Demo 7 (PE): Analyzing Keypoint Movement and Kinematics in Pose Estimation Data
Written and last updated September 18, 2025 by Sedona Ewbank, snewbank@stanford.edu
The purpose of this demo is to demonstrate how to measure and plot keypoint travel and ego-centered kinematics in pose estimation data types typically associated with animal experiments (DLC, SLEAP) in MARIPoSA.
import os
import sys
import numpy as np
import pandas as pd
import importlib
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, FFMpegWriter
from IPython.display import HTML
#This block only important for running as script
#script_dir = os.path.dirname(os.path.abspath(__file__))
mariposa_dir = "/Users/snewbank/PycharmProjects/MARIPoSA"
utils_dir = os.path.join(mariposa_dir, 'utils')
sys.path.append(utils_dir)
sys.path.append(mariposa_dir)
#import utils
from utils import metadata, analyze, plot, simulate
importlib.reload(metadata)
importlib.reload(analyze)
importlib.reload(plot)
importlib.reload(simulate)
<module 'utils.simulate' from '/Users/snewbank/PycharmProjects/MARIPoSA/utils/simulate.py'>
demo_dir="/Users/snewbank/Behavior/MARIPoSA_demo_data/"
config=metadata.load_project(demo_dir+"250910_test_PE/config_PE.yaml")
save=True
save_path = demo_dir+"demo_figures/"
if not os.path.exists(save_path):
os.makedirs(save_path)
7.1: Measuring and plotting keypoint travel in animals
The purpose of this mode of analysis is to measure how much a keypoint has travelled during a recording, with or without time binning. This could reflect locomotion (e.g., in an open field recording approach) or overall movement of a keypoint in a confined assay (e.g., a reaching task). We obtain this with analyze.get_keypoint_travel, which will return a KeypointTravel object that we can then use for further analysis. Note the threshold parameter of this function, which optionally “cleans” the data; it can be disabled by setting it to None.
help(analyze.get_keypoint_travel)
Help on function get_keypoint_travel in module utils.analyze:
get_keypoint_travel(PE_config, keypoint, start, end, binsize=None, thresh=70, selected_subgroups='all', return_as_df=True)
Measure keypodint distance travelled across group of subjects
:param PE_config: pose estimation config - used for FPS only
:param keypoint: name of keypoint
:param start: start time in seconds
:param end: end time in seconds
:param binsize: if binned output is desired, size of timebins (default is None for no binning)
:param thresh: threshold for when distance 'jump' is too large and should be excluded; default 70
:param selected_subgroups: subgroups to analyze as defined in config; default "all"
:param return_as_df: return as a dataframe or return as KeypointTravel class (for embedding, classification)
:return:
kp_travel = analyze.get_keypoint_travel(config,
"tailbase",
0,1200,
selected_subgroups=["sal","k1","k5","k10"],
return_as_df=False)
kp_travel_df = kp_travel.to_df()
display(kp_travel_df)
plot.plot_keypoint_travel(kp_travel,cmap="viridis_r",plottype="bar")
kp_travel = analyze.get_keypoint_travel(config,
"tailbase",
0,1200,
binsize=60,
selected_subgroups=["sal","k1","k5","k10"],
return_as_df=False)
kp_travel_df = kp_travel.to_df()
display(kp_travel_df)
plot.plot_keypoint_travel(kp_travel,cmap="viridis_r")
0.0 | group | |
---|---|---|
2023-06-15_21-28-12_bf04_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 76585.673549 | sal |
2023-06-15_22-01-50_bf03_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 77601.985038 | sal |
2023-06-20_15-41-01_bm03_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 21844.904953 | sal |
2023-06-20_16-13-48_bm04_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 46279.020517 | sal |
2023-06-20_17-21-51_bf02_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 69155.547166 | sal |
2023-07-03_16-15-21_bm02_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 60179.625151 | sal |
2023-07-03_19-20-49_bf01_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 74034.204420 | sal |
2023-06-20_19-10-38_bf04_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 88946.845156 | k1 |
2023-06-26_15-35-45_bf01_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 85649.979937 | k1 |
2023-06-26_19-00-05_bm02_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 92955.598550 | k1 |
2023-06-27_10-47-10_bm04_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 22429.103784 | k1 |
2023-07-08_14-42-24_bf02_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 101134.822510 | k1 |
2023-07-08_15-47-29_bm01_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 70294.549563 | k1 |
2023-06-15_17-16-18_bm01_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 99097.355864 | k5 |
2023-06-26_16-15-58_bf02_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 117117.595734 | k5 |
2023-07-03_20-27-25_bf03_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 174943.106781 | k5 |
2023-07-08_16-19-27_bm02_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 154678.418900 | k5 |
2023-07-14_16-25-47_bf01_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 147305.238791 | k5 |
2023-07-18_19-35-14_bm03_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 121408.153258 | k5 |
2023-05-15_16-47-52_bf03_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 178874.593599 | k10 |
2023-05-15_18-18-22_bf04_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 163772.740151 | k10 |
2023-05-25_14-30-54_bm02_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 146356.555059 | k10 |
2023-05-31_17-08-06_bf01_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 256202.052488 | k10 |
2023-07-13_15-45-26_bm03_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 162133.395129 | k10 |
2023-07-14_13-56-09_bm01_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 140856.419448 | k10 |
2023-07-18_18-19-50_bm04_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 156764.561502 | k10 |
0.0 | 1.0 | 2.0 | 3.0 | 4.0 | 5.0 | 6.0 | 7.0 | 8.0 | 9.0 | ... | 11.0 | 12.0 | 13.0 | 14.0 | 15.0 | 16.0 | 17.0 | 18.0 | 19.0 | group | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2023-06-15_21-28-12_bf04_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 8880.331395 | 3351.100258 | 1587.052168 | 2750.742715 | 6399.252095 | 3460.315582 | 1016.990993 | 2570.881432 | 5468.918087 | 6059.387430 | ... | 1104.964260 | 1500.049482 | 3898.298124 | 6544.453556 | 4779.386395 | 3759.273735 | 2990.124814 | 1878.317699 | 6675.841174 | sal |
2023-06-15_22-01-50_bf03_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 8071.237357 | 6181.385243 | 7522.841487 | 3543.876735 | 3620.211232 | 5351.320313 | 6009.554638 | 3952.848740 | 5135.739960 | 2218.138347 | ... | 2122.939566 | 2672.667907 | 4010.858900 | 3015.353875 | 1996.782716 | 2114.914108 | 2257.268367 | 2296.118505 | 2669.904618 | sal |
2023-06-20_15-41-01_bm03_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 2660.048643 | 1383.006506 | 1059.346533 | 1503.847833 | 1535.395087 | 1002.214252 | 1054.906797 | 1108.866013 | 998.275640 | 1074.835503 | ... | 929.709634 | 910.307825 | 925.516701 | 768.447314 | 859.197324 | 803.552190 | 912.919929 | 705.072034 | 681.108369 | sal |
2023-06-20_16-13-48_bm04_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 5485.073029 | 1319.469199 | 3407.583833 | 3389.185426 | 2014.415106 | 2541.982760 | 2881.827623 | 2246.780758 | 3373.222174 | 1624.433605 | ... | 2263.354499 | 2712.941823 | 1787.785253 | 2965.370830 | 1906.642921 | 792.458697 | 1058.076463 | 1420.924233 | 1579.055731 | sal |
2023-06-20_17-21-51_bf02_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 7938.195203 | 6110.713672 | 5439.324565 | 4607.947223 | 3910.104986 | 3904.234479 | 3953.831284 | 4420.781394 | 2795.601820 | 2183.251945 | ... | 1217.639745 | 1699.270851 | 1403.652257 | 5089.822149 | 4489.189921 | 1268.897918 | 1459.432966 | 1557.146247 | 3414.117895 | sal |
2023-07-03_16-15-21_bm02_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 7048.375661 | 5818.277145 | 5278.729134 | 6021.514273 | 4386.361838 | 4524.004535 | 2291.139233 | 1999.318602 | 4098.064644 | 1537.187124 | ... | 3163.314795 | 1602.690430 | 1330.173334 | 1244.696870 | 1295.699150 | 1398.134903 | 1399.431639 | 1282.853249 | 1105.019397 | sal |
2023-07-03_19-20-49_bf01_salivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 8241.668408 | 4963.881674 | 5521.215270 | 3499.214739 | 3161.170596 | 5903.910838 | 3711.337363 | 2840.721863 | 4470.272583 | 4842.918753 | ... | 2164.682111 | 2000.644887 | 1889.692155 | 3446.230399 | 3064.598552 | 2689.005167 | 2111.795295 | 2750.955661 | 1497.574769 | sal |
2023-06-20_19-10-38_bf04_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 8845.988403 | 7188.888682 | 8933.440687 | 7737.247830 | 7132.427277 | 5154.259105 | 6499.133309 | 4838.891810 | 4362.034290 | 7835.191761 | ... | 1406.535741 | 1084.069936 | 1088.998064 | 1959.846857 | 1817.340613 | 1521.430826 | 1497.603369 | 3469.641220 | 2591.058581 | k1 |
2023-06-26_15-35-45_bf01_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 11838.689804 | 8031.028128 | 8091.465003 | 4083.950757 | 6227.053949 | 8353.814333 | 6247.864234 | 4675.471830 | 1606.425168 | 3986.807139 | ... | 1737.062475 | 2822.933304 | 2976.058980 | 3062.887893 | 2957.368912 | 1436.065023 | 1788.045139 | 1733.746204 | 1242.606624 | k1 |
2023-06-26_19-00-05_bm02_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 20724.839634 | 10159.438676 | 6694.307894 | 5773.045308 | 5343.981806 | 3339.687841 | 2991.561963 | 4323.656226 | 4578.547308 | 1474.808605 | ... | 1333.393782 | 2728.749019 | 1169.581962 | 2477.143336 | 4004.994848 | 2404.780803 | 3424.785899 | 4033.969786 | 4708.006492 | k1 |
2023-06-27_10-47-10_bm04_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 766.578810 | 5014.383998 | 2207.256298 | 1714.152071 | 574.814660 | 541.741661 | 554.249522 | 614.487656 | 553.554121 | 541.568858 | ... | 528.902945 | 550.459444 | 640.761410 | 1896.750790 | 1001.235900 | 1147.860654 | 1184.954039 | 1046.978826 | 828.924569 | k1 |
2023-07-08_14-42-24_bf02_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 9507.050556 | 7019.303165 | 5778.522216 | 5275.720184 | 4803.188901 | 5795.852212 | 5318.264303 | 5055.511504 | 5197.850531 | 6794.038094 | ... | 4213.263493 | 3866.977180 | 5637.361996 | 3318.199933 | 2946.646448 | 5080.904185 | 2982.917208 | 4375.070269 | 3004.641604 | k1 |
2023-07-08_15-47-29_bm01_k1ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 11255.983932 | 9795.427056 | 6615.669842 | 5953.572622 | 3314.193903 | 1333.949901 | 3547.871827 | 1639.513297 | 3787.331547 | 3724.773400 | ... | 4079.358745 | 2304.345840 | 1021.318289 | 987.000722 | 818.526623 | 749.524446 | 924.008889 | 3083.640126 | 2089.798243 | k1 |
2023-06-15_17-16-18_bm01_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 1016.139535 | 5548.329124 | 11221.154090 | 15577.294241 | 15856.303259 | 10550.382890 | 9436.532736 | 5250.601216 | 3021.957967 | 2782.403189 | ... | 1332.521919 | 5352.297650 | 1572.111102 | 982.383516 | 938.435036 | 1005.328986 | 1043.020094 | 1489.830168 | 3975.452915 | k5 |
2023-06-26_16-15-58_bf02_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 14258.394307 | 12114.657011 | 9102.119472 | 11990.647150 | 9855.363540 | 7376.524999 | 7655.121246 | 7192.705189 | 5686.557703 | 4683.214772 | ... | 2190.526606 | 3091.146136 | 1633.545223 | 1219.133549 | 2513.966949 | 3797.668741 | 5044.993972 | 822.887972 | 1084.662132 | k5 |
2023-07-03_20-27-25_bf03_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 18483.803942 | 19748.594069 | 13540.708424 | 13838.397015 | 13980.386907 | 12579.660954 | 11937.358990 | 10741.868081 | 10516.169960 | 6999.421026 | ... | 4401.776608 | 6663.845579 | 4579.081683 | 6278.084118 | 4725.643728 | 2439.890701 | 2259.074760 | 1876.957914 | 1750.146493 | k5 |
2023-07-08_16-19-27_bm02_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 16611.210569 | 19548.541040 | 19658.044198 | 17814.095713 | 15492.194395 | 10945.722452 | 7707.970097 | 6223.306978 | 4704.248748 | 1756.926066 | ... | 2511.241484 | 4233.279650 | 4207.197429 | 2686.937615 | 3080.327208 | 2562.255531 | 2879.748576 | 4858.737555 | 3996.036978 | k5 |
2023-07-14_16-25-47_bf01_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 16263.232968 | 17443.119375 | 22803.236161 | 12280.329026 | 11375.300372 | 9175.033094 | 7663.504950 | 6023.044032 | 3156.044494 | 5384.563438 | ... | 4284.413765 | 4759.089020 | 3107.118211 | 2045.449778 | 1671.686457 | 3081.160518 | 2499.152466 | 4010.878733 | 3482.302331 | k5 |
2023-07-18_19-35-14_bm03_k5ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 3141.386064 | 8431.135309 | 11445.512440 | 15631.544467 | 13700.836614 | 11320.928608 | 10849.105647 | 9040.392641 | 6958.009582 | 9139.713930 | ... | 1920.523942 | 2250.660670 | 3657.893139 | 1732.058743 | 1268.457942 | 1951.751149 | 979.272468 | 891.367322 | 1445.491110 | k5 |
2023-05-15_16-47-52_bf03_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 4540.862776 | 5761.342404 | 5972.096308 | 9212.996149 | 11265.014433 | 12343.530581 | 13109.885729 | 14265.232545 | 12622.386646 | 14532.162772 | ... | 9880.460142 | 9848.548262 | 8212.565308 | 6903.801921 | 5536.163377 | 4185.685251 | 5688.052096 | 6323.492953 | 4504.421440 | k10 |
2023-05-15_18-18-22_bf04_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 1384.384759 | 1561.798339 | 5305.881105 | 6953.295808 | 11953.262476 | 15763.644870 | 17379.785409 | 16629.811314 | 16709.346509 | 15048.740676 | ... | 7703.680453 | 5275.320585 | 7444.790561 | 5507.504817 | 1817.069497 | 1802.525010 | 2997.591737 | 5776.201930 | 2934.882903 | k10 |
2023-05-25_14-30-54_bm02_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 1667.979021 | 1379.497290 | 1663.627196 | 3107.784112 | 4318.061746 | 7187.792082 | 9062.464735 | 10455.246228 | 14283.478704 | 11130.539709 | ... | 13852.193039 | 14019.179637 | 11930.154609 | 6806.428533 | 3768.340484 | 6354.961249 | 5443.839714 | 2999.410224 | 1938.707364 | k10 |
2023-05-31_17-08-06_bf01_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 11082.830746 | 15343.322621 | 18279.907887 | 17224.223559 | 23570.051169 | 18951.071018 | 16536.410407 | 14840.127977 | 15261.406690 | 16009.304633 | ... | 11787.589473 | 10134.122145 | 8567.505371 | 10117.137028 | 8937.780320 | 6922.975225 | 5773.762636 | 5015.415782 | 7104.784164 | k10 |
2023-07-13_15-45-26_bm03_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 3318.773423 | 4584.927267 | 6942.028511 | 10606.361780 | 13405.089466 | 14297.165685 | 19119.371373 | 18978.367552 | 17304.071745 | 11322.589042 | ... | 8377.923276 | 4126.843001 | 7022.605035 | 3799.446167 | 6055.594219 | 3491.997983 | 1980.469115 | 1970.568348 | 1237.739002 | k10 |
2023-07-14_13-56-09_bm01_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 1094.347692 | 821.769350 | 947.428873 | 995.894179 | 878.307377 | 850.194499 | 800.261095 | 2530.965888 | 3584.427386 | 6113.109571 | ... | 13742.433401 | 9811.396039 | 15422.909725 | 16949.204517 | 9715.071936 | 8837.586482 | 8954.368748 | 12788.630333 | 10803.153588 | k10 |
2023-07-18_18-19-50_bm04_k10ivDLC_resnet101_DevRats2Jul21shuffle1_500000.csv | 977.064278 | 792.373003 | 2147.504600 | 4129.242798 | 5808.968030 | 7137.626090 | 11072.575732 | 9573.996864 | 10198.357200 | 11214.199924 | ... | 15963.185520 | 12328.413572 | 11840.693869 | 10454.337927 | 9633.147720 | 8050.751995 | 3756.558807 | 3974.695994 | 4693.074698 | k10 |
26 rows × 21 columns



7.2 Using keypoint travel in animals for embedding and classification
The KeypointTravel class has many of the same attributes and use cases as pose segmentation data object classes (ModuleUsage and ModuleTransitions), and thus we can use the same embedding, classification, and regression functions as we do for pose segmentation data. It is worth noting that travel of a single keypoint only has sufficient dimensionality for some methods (e.g., PCA) if time binning is applied, otherwise it is a point value rather than a time series. We can start by looking at embedding the data with PCA or LDA.
pca_emb = analyze.embed(kp_travel,method="pca")
plot.plot_embeddings(kp_travel,pca_emb)
lda_emb = analyze.embed(kp_travel,method="lda")
plot.plot_embeddings(kp_travel,lda_emb)
Ellipse only drawn for embeddings_object of class LDA, not <class 'sklearn.decomposition._pca.PCA'>



Next, we can look at classification with logistic regression - here shown with training a classifier on the full dataset and leave-one-out cross-validation to test performance on a subset of samples.
clf = analyze.classify(kp_travel,method="LogisticRegression")
accuracy, conf_mat = analyze.loocv(kp_travel,method="LogisticRegression")
plt.figure(figsize=(3,3),dpi=300)
plt.imshow(conf_mat,cmap="Greens")
plt.xticks([0,1,2,3],labels=kp_travel.group_dict.keys())
plt.yticks([0,1,2,3],labels=kp_travel.group_dict.keys())
plt.title("Confusion Matrix")
plt.colorbar()
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
/opt/anaconda3/envs/mariposa/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:460: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
<matplotlib.colorbar.Colorbar at 0x7fc448b17490>

And now we can take a look at using regression on a KeypointTravel class object.
# Training regression model and doing LOOCV
dose_dict={"sal":0,"k1":1,"k5":5,"k10":10}
reg, dose_labels = analyze.regress(kp_travel,dose_dict)
y_preds, sq_err = analyze.loocv_regression(kp_travel,dose_dict)
# Plotting results for held-out samples
plt.figure(figsize=(3,3),dpi=300)
cmap = "viridis_r"
cmap = plt.get_cmap(cmap)
colors = [cmap([i/4]) for i in range(4)]
for d,dose in enumerate(dose_dict.keys()):
x = dose_dict[dose]
mask = np.array(kp_travel.group_labels)==kp_travel.group_dict[dose]
m = np.mean(y_preds[mask])
sd = np.std(y_preds[mask])
plt.errorbar(x,m,yerr=sd,linestyle="none",marker="o",color=colors[d],capsize=2)
plt.xlabel("Real dose (mg/kg)")
plt.ylabel("Predicted dose (mg/kg)")
Text(0, 0.5, 'Predicted dose (mg/kg)')

7.3: Measuring and using ego-centered kinematics from pose estimation data
Travel of a single keypoint of interest can be useful for measuring overall movement of the animal or limb, depending on the experimental setup; however, additional insight can be gained by ego-centering the data (i.e., using two keypoints to establish the origin and axis along which to reorient all points to) and evaluating the angle, location, and movement of keypoints relative to the new orientation. Ego-centering is acheived in MARIPoSA with analyze.ego_center(), which may be useful to know if you want to save the ego-centered data for some reason. Below is the documentation for analyze.ego_center and a movie plotting the original and ego-centered data.
help(analyze.ego_center)
Help on function ego_center in module utils.analyze:
ego_center(config, data, keypoint_ego1, keypoint_ego2)
Ego centering a single pose estimation dataframe
:param config: config
:param data: pose estimation pandas dataframe in DLC format
:param keypoint_ego1: first keypoint to use for establishing egocentric alignment axis
:param keypoint_ego2: second keypoint to use for establishing egocentric alignment axis
:return: ego_centered pandas dataframe
data = pd.read_csv(config["data_directory"]+config["project_files"][0],header=[1,2])
data_reoriented = analyze.ego_center(config, data, "tailbase", "nose")
fig, ax = plt.subplots(figsize=(5, 5))
def update(fr):
ax.clear()
x = data.xs("x", level=1, axis=1).loc[fr]
y = data.xs("y", level=1, axis=1).loc[fr]
x_ego = data_reoriented.xs("x", level=1, axis=1).loc[fr]
y_ego = data_reoriented.xs("y", level=1, axis=1).loc[fr]
ax.scatter(x, y, color="gray", s=4, label="Original")
ax.scatter(x_ego, y_ego, color="C0", s=4, label="Ego-centered")
ax.set_xlim([-200, 1080])
ax.set_ylim([-200, 1080])
ax.set_title(f"Frame {fr}")
ax.legend(loc="upper right")
nframes=300
ani = FuncAnimation(fig, update, frames=nframes, interval=50)
HTML(ani.to_jshtml())

Ego-centering is incorporated into the function analyze.get_keypoint_kinematics, which can get the angle, distance, or travel/movement of keypoints relative to the ego-center.
help(analyze.get_keypoint_kinematics)
Help on function get_keypoint_kinematics in module utils.analyze:
get_keypoint_kinematics(PE_config, keypoint_ego1, keypoint_ego2, start, end, binsize=None, metric='angle', thresh=70, selected_subgroups='all', return_as_df=True, verbose=False)
Measure keypoint kinematics (egocentrically aligned angle, distance, and travel of keypoints) across group of subjects
:param PE_config: pose estimation config - used for FPS only
:param keypoint1: first keypoint to use for establishing egocentric alignment axis
:param keypoint2: second keypoint to use for establishing egocentric alignment axis
:param start: start time in seconds
:param end: end time in seconds
:param binsize: if binned output is desired, size of timebins (default is None for no binning)
:param metric: metric to assess for all non-keypoint1/2 keypoints; options are "angle_m" (for mean angle), "angle_sd" (for std deviation of angle), "distance_m" (for mean distance of keypoints to ego-center), "distance_sd" (for std deviation of distance of keypoints to ego-center), or "travel" (for movement of keypoints relative to ego-center)
:param thresh: threshold for when distance 'jump' is too large and should be excluded; default 70
:param selected_subgroups: subgroups to analyze as defined in config; default "all"
:param return_as_df: return as a dataframe or return as KeypointTravel class (for embedding, classification)
:return:
# Get the kinematic data - travel of keypoints relative to egocentric axis
travel_kin = analyze.get_keypoint_kinematics(config,
"tailbase",
"nose",
0, 1200,
metric='travel',
selected_subgroups=['sal', 'k1', 'k5', 'k10'],
return_as_df=False)
# plot the ego-centered travel data
plot.plot_keypoint_kinematics(config,travel_kin, figH=5,figW=8,style="bar_error",cmap="viridis_r")
plt.title("Ego-centered Keypoint Travel")
# use the data for embedding and classification
emb = analyze.embed(travel_kin)
plot.plot_embeddings(travel_kin,emb)
plt.title("LDA of Ego-centered Keypoint Travel")
plt.figure(figsize=(2.5,2.5),dpi=300)
plt.title("Ego-centered Keypoint Travel\nConfusion Matrix")
acc, cm = analyze.loocv(travel_kin)
plt.imshow(cm,cmap="Greens")
ticklabels=['sal','k1','k5','k10']
plt.xticks(range(len(ticklabels)),labels=ticklabels,rotation=90)
plt.yticks(range(len(ticklabels)),labels=ticklabels)
print(f"Accuracy: {acc}")
Accuracy: 0.23076923076923078



# Get the kinematic data - angle of keypoints relative to egocentric axis
angle_kin = analyze.get_keypoint_kinematics(config,
"tailbase",
"nose",
0, 1200,
metric='angle_sd',
selected_subgroups=['sal', 'k1', 'k5', 'k10'],
return_as_df=False)
# plot the kinematic data
plot.plot_keypoint_kinematics(config,angle_kin, figH=5,figW=8,style="bar_error",cmap="viridis_r")
plt.title("Ego-centered Keypoint Angle")
# use the data for embedding and classification
emb = analyze.embed(angle_kin)
plot.plot_embeddings(angle_kin,emb)
plt.title("LDA of Ego-centered Keypoint Angle")
plt.figure(figsize=(2.5,2.5),dpi=300)
plt.title("Ego-centered Keypoint Angle\nConfusion Matrix")
acc, cm = analyze.loocv(angle_kin)
plt.imshow(cm,cmap="Greens")
ticklabels=['sal','k1','k5','k10']
plt.xticks(range(len(ticklabels)),labels=ticklabels,rotation=90)
plt.yticks(range(len(ticklabels)),labels=ticklabels)
print(f"Accuracy: {acc}")
Accuracy: 0.2692307692307692


