Table of Contents¶
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

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 |
HMM_State
2.0 139108
1.0 126382
Name: count, dtype: int64
Export HMM results - model and data¶
✓ 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