Skip to content

Table of Contents

  1. Load Project
  2. Calculate Step Length and Turn Angle
    1. Visualize Step and Angle Distribution
  3. Run CoMPASS Level 1
    1. Check Results
  4. Export HMM results

Load Project

from pathlib import Path
import pandas as pd
from compass_labyrinth import load_project


project_path = Path(".").resolve() / "my_project_2"

# Import config and metadata
config, cohort_metadata = load_project(project_path=project_path)

# Import all sessions combined pose-estimation CSV
df_all_csv = pd.read_csv(project_path / "csvs" / "combined" / "Preprocessed_combined_file_exclusions.csv")

df_all_csv
x y Grid Number likelihood S_no Region Session Genotype Sex NodeType Velocity
0 275.057129 875.337219 47 0.983259 748 entry_zone 3 WT Female Entry Nodes 0.000000
1 271.037537 872.005432 47 0.989085 749 entry_zone 3 WT Female Entry Nodes 26.104563
2 267.526978 873.733704 47 0.986050 750 entry_zone 3 WT Female Entry Nodes 19.564603
3 265.571991 873.412659 47 0.953975 751 entry_zone 3 WT Female Entry Nodes 9.905860
4 266.325684 874.166748 47 0.958631 752 entry_zone 3 WT Female Entry Nodes 5.330815
... ... ... ... ... ... ... ... ... ... ... ...
265495 228.690262 814.897949 34 0.999385 225311 reward_path 7 KO Female Non-Decision (Reward) 293.221609
265496 292.517883 837.722717 46 0.999992 225312 entry_zone 7 KO Female Entry Nodes 338.929760
265497 295.305054 862.294739 47 0.999458 225313 entry_zone 7 KO Female Entry Nodes 123.647944
265498 295.361694 876.922546 47 0.999976 225314 entry_zone 7 KO Female Entry Nodes 73.139586
265499 294.444183 901.016602 47 0.962276 225315 entry_zone 7 KO Female Entry Nodes 120.557592

265500 rows × 11 columns

Calculate Step Length and Turn Angle

from compass_labyrinth.compass.level_1 import prep_data


# Run prep
final_df = prep_data(
    data=df_all_csv,
    type="UTM",                         # or "LL" if lon/lat in coordNames
    coordNames=("x", "y"),
    covNames=[],  # example covariates if present
    centers=None,                       # e.g., np.array([[0,0], [10,10]])
    centroids=None,                     # e.g., {"goal": goal_df_with_time}
    angleCovs=None,
    altCoordNames=None
)

print("\nSummary: Step")
print(final_df["step"].describe())

print("\nSummary: Angle (radians)")
print(final_df["angle"].describe())
/opt/miniconda3/envs/compass-labyrinth/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
/Users/luiztauffer/Github/CoMPASS-Labyrinth/src/compass_labyrinth/compass/level_1/prep_data.py:159: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
  for _id, g in df.groupby("ID", sort=False):



Summary: Step
count    265490.000000
mean         21.121542
std          23.254561
min           0.000281
25%           3.304319
50%          12.055826
75%          32.961413
max         285.400817
Name: step, dtype: float64

Summary: Angle (radians)
count    265490.000000
mean          0.001154
std           1.465752
min          -3.141549
25%          -0.723278
50%           0.002277
75%           0.723531
max           3.141575
Name: angle, dtype: float64

Visualize Step and Angle Distribution

from compass_labyrinth.compass.level_1 import plot_step_and_angle_distributions

plot_step_and_angle_distributions(
    config=config,
    df=final_df,
)
Figure saved at: /Users/luiztauffer/Github/CoMPASS-Labyrinth/notebooks/my_project_2/figures/step_and_angle_distribution.pdf

png

Run CoMPASS Level-1

Goal R (momentuHMM) Python (SciPy analogue)


Gradient-based optimization "BFGS", "L-BFGS-B" "BFGS", "L-BFGS-B" Derivative-free (simplex) "Nelder-Mead" "Nelder-Mead" Derivative-free (Newton-like) "nlm" "Powell

from compass_labyrinth.compass.level_1 import fit_best_hmm
import numpy as np


# final_df must have: 'Session', 'step' (>0), 'angle' (radians)
res = fit_best_hmm(
    preproc_df=final_df,
    n_states=2,
    n_repetitions=1,
    opt_methods=["L-BFGS-B"],
    max_iter=50,
    use_abs_angle=(False,),          # True => |angle|~Gamma ; False => angle~VM
    stationary_flag="auto",
    use_data_driven_ranges=True,
    angle_mean_biased=(np.pi/2, 0.0),     # used for VM branch
    session_col="Session",
    seed=123,
    enforce_behavioral_constraints=False,
    show_progress=True
)

Check results

  • State 1 = low step + high turn angle
  • State 2 = high step + low turn angle
from compass_labyrinth.compass.level_1 import print_hmm_summary


print_hmm_summary(res.summary, res.model)

res.data.head()          # original df + HMM_State + posteriors
 Best Model Characteristics:
• Angle type: von Mises
• Optimizer: L-BFGS-B
• AIC: 2836846.56 | logLik: -1418412.28
• Start probs: [1.0, 0.0]
• Transmat:
 [[0.8783 0.1217]
 [0.1102 0.8898]]
• Step Means: [4.7984, 35.9023]
• VM mu: [-3.057, 0.006]
• VM kappa: [0.009, 1.98]
• Met behavioral constraints: True
• Final state ordering: State 1 = low step + high turn; State 2 = high step + low turn
ID step angle x y Grid Number likelihood S_no Region Session Genotype Sex NodeType Velocity HMM_State Post_Prob_1 Post_Prob_2
0 3 3.912921 -1.149582 267.526978 873.733704 47 0.986050 750 entry_zone 3 WT Female Entry Nodes 19.564603 1.0 NaN NaN
1 3 1.981172 0.620240 265.571991 873.412659 47 0.953975 751 entry_zone 3 WT Female Entry Nodes 9.905860 1.0 NaN NaN
2 3 1.066163 -2.518697 266.325684 874.166748 47 0.958631 752 entry_zone 3 WT Female Entry Nodes 5.330815 1.0 NaN NaN
3 3 0.899351 2.238799 265.432495 874.271851 47 0.932229 753 entry_zone 3 WT Female Entry Nodes 4.496755 1.0 NaN NaN
4 3 0.519677 1.625876 265.400269 873.753174 47 0.909978 754 entry_zone 3 WT Female Entry Nodes 2.598385 1.0 NaN NaN
res.data.HMM_State.value_counts()
HMM_State
2.0    139108
1.0    126382
Name: count, dtype: int64

Export HMM results - model and data

res.save(config=config)
  ✓ Saved model summary: model_summary.json
  ✓ Saved data with states: data_with_states.csv
  ✓ Saved model selection records: model_selection_records.csv
  ✓ Saved fitted model: fitted_model.joblib

📁 All CoMPASS Level 1 results saved to: /Users/luiztauffer/Github/CoMPASS-Labyrinth/notebooks/my_project_2/results/compass_level_1