@@ -557,26 +557,54 @@ def _load_anipose_cfg(self):
557557
558558 return load_config (str (self .triangulation_path / "config.toml" ))
559559
560- def calibrate (self ):
561- from anipose .calibrate import calibrate_all
562- calibrate_all (self ._load_anipose_cfg ())
563-
564- def track (self ):
565- from anipose .pose_videos import pose_videos_all
566- pose_videos_all (self ._load_anipose_cfg ())
560+ def _resolve_anipose_session (self , session : str ) -> str :
561+ session_path = self .triangulation_path / session
562+ if not session_path .is_dir ():
563+ available = [p .name for p in self .triangulation_path .iterdir ()
564+ if p .is_dir ()] if self .triangulation_path .is_dir () else []
565+ raise ValueError (
566+ f"Session folder '{ session } ' not found in { self .triangulation_path } . "
567+ f"Available sessions: { available } " )
568+ return str (session_path .resolve ())
569+
570+ def calibrate (self , session : Optional [str ] = None ):
571+ if session is not None :
572+ from anipose .calibrate import process_session
573+ config = self ._load_anipose_cfg ()
574+ process_session (config , self ._resolve_anipose_session (session ))
575+ else :
576+ from anipose .calibrate import calibrate_all
577+ calibrate_all (self ._load_anipose_cfg ())
578+
579+ def track (self , session : Optional [str ] = None ):
580+ if session is not None :
581+ from anipose .pose_videos import process_session
582+ config = self ._load_anipose_cfg ()
583+ process_session (config , self ._resolve_anipose_session (session ))
584+ else :
585+ from anipose .pose_videos import pose_videos_all
586+ pose_videos_all (self ._load_anipose_cfg ())
567587
568- def triangulate (self ):
588+ def triangulate (self , session : Optional [ str ] = None ):
569589 # first triangulate points using Anipose
570- from anipose .triangulate import triangulate_all
571- triangulate_all (self ._load_anipose_cfg ())
590+ if session is not None :
591+ from anipose .triangulate import process_session
592+ config = self ._load_anipose_cfg ()
593+ process_session (config , self ._resolve_anipose_session (session ))
594+ sessions_to_process = [self .triangulation_path / session ]
595+ else :
596+ from anipose .triangulate import triangulate_all
597+ triangulate_all (self ._load_anipose_cfg ())
598+ sessions_to_process = [s for s in self .triangulation_path .iterdir ()
599+ if s .is_dir ()]
572600 # now compute cheese3d features
573601 exclude_kps = set (kp .label for kp in _DEFAULT_KEYPOINTS ) - set (kp .label for kp in self .keypoints )
574602 if len (exclude_kps ) > 0 :
575603 rprint ("[bold red]Keypoint configuration does not match default Cheese3D keypoints. "
576604 "Some Cheese3D features may not be computed![/bold red]" )
577- for session in self . triangulation_path . iterdir () :
578- if session .is_dir ():
579- landmarks = read_3d_data (session )
605+ for session_dir in sessions_to_process :
606+ if session_dir .is_dir ():
607+ landmarks = read_3d_data (session_dir )
580608 c3d_features = compute_anatomical_measurements (landmarks , exclude_kps )
581609 # write features to csv
582610 c3d_features_df = pd .DataFrame ({
@@ -585,9 +613,9 @@ def triangulate(self):
585613 for k , v in features .items ()
586614 })
587615 if len (c3d_features_df ) == 0 :
588- rprint (f"[bold red]No features constructed for { session .name } , skipping![/bold red]" )
616+ rprint (f"[bold red]No features constructed for { session_dir .name } , skipping![/bold red]" )
589617 continue
590- csv_output = (session / "cheese3d" )
618+ csv_output = (session_dir / "cheese3d" )
591619 csv_output .mkdir (exist_ok = True )
592620 csv_output = csv_output / "cheese3d_features.csv"
593621 if not csv_output .exists ():
0 commit comments