Source code for pyvisor.ethogram

from threading import RLock
from typing import Dict, List

from pyvisor.GUI.model.animal import Animal, AnimalNumber
from pyvisor.GUI.model.behaviour import BehaviourName, Behaviour
from pyvisor.animal_ethogram_2 import AnimalEthogram2


[docs] class Ethogram: """Container linking all per-animal ethograms with shared state. Manages the live toggle states (which behaviours the user is currently pressing) and delegates frame-level recording to :class:`AnimalEthogram2` instances. """ def __init__(self, animals: Dict[AnimalNumber, Animal], n_frames: int, lock: RLock = None): self._animals = animals self.animal_ethograms = { an: AnimalEthogram2(animals[an], n_frames) for an in animals.keys() } # type: Dict[AnimalNumber, AnimalEthogram2] self.current_states = { an: [] for an in animals.keys() } # type: Dict[AnimalNumber, List[BehaviourName]] self._lock = lock or RLock()
[docs] def toggle_state(self, label: str): with self._lock: animal_number, behaviour_name = Behaviour.parse_label(label) animal = self._animals[animal_number] states = self.current_states[animal_number] if label in states: states.pop(states.index(label)) print('states:', states) return behav = animal.behaviours[label] _to_pop = [] for other in states: _, other_name = Behaviour.parse_label(other) if other_name in behav.compatible_with: continue _to_pop.append(states.index(other)) _to_pop.reverse() for idx in _to_pop: states.pop(idx) states.append(label) print('states:', states)
[docs] def clear_states(self): with self._lock: for states in self.current_states.values(): states.clear()
[docs] def apply_states_at_frame(self, frame_number: int): with self._lock: for an in self.current_states: states = list(self.current_states[an]) animal = self._animals[an] animal_etho = self.animal_ethograms[an] if 'A{}_delete'.format(animal.number) in states: animal_etho.delete_behaviours(frame_number) continue animal_etho.assign_behaviours(frame_number, states)
@property def lock(self) -> RLock: return self._lock