diff --git a/LabGym/config.py b/LabGym/config.py index 2c68c5a..7d0e5f8 100644 --- a/LabGym/config.py +++ b/LabGym/config.py @@ -8,13 +8,14 @@ Notes * Environment variables and command-line options can be used to - override the location of the configuration file, so determine the - configuration file location before reading it. + override the location of the configuration file, so its location is + determined (from defaults, environment variables, and command-line + options) before reading it. * Typical LabGym configdir organization is ~/.labgym/config.toml (optional) logging.yaml (optional) - registration.done (created at registration) + registration.yaml (created at registration) To use a different configfile only (without changing the references to other configdir files), @@ -66,6 +67,9 @@ }, 'anonymous': False, + + 'detectors': str(Path(__file__).parent.joinpath('detectors')), + 'models': str(Path(__file__).parent.joinpath('models')), } logger = logging.getLogger(__name__) @@ -129,8 +133,25 @@ def get_config_from_configfile(configfile: Path) -> dict: return result -def get_config(): - """Return a cached config dict. Construct it if necessary. +def get_config(*args) -> dict: + """Return a copy of the cached config dict (or a subset of its pairs). + + If args are passed, then return a new dict of only those keys and + their values from the cached config dict. + """ + + fullconfig = get_fullconfig() + + if len(args) == 0: + result = fullconfig + else: + result = {key: fullconfig[key] for key in args} + + return copy.deepcopy(result) + + +def get_fullconfig() -> dict: + """Return a copy of the cached config dict. Construct it if necessary. Strengths * Instead of reconstructing the config dict each time this diff --git a/LabGym/gui_analyzer.py b/LabGym/gui_analyzer.py index c37d19f..9f44d14 100644 --- a/LabGym/gui_analyzer.py +++ b/LabGym/gui_analyzer.py @@ -18,8 +18,8 @@ # Standard library imports. -import logging import json +import logging import os from pathlib import Path @@ -38,11 +38,9 @@ # Local application/library specific imports. from .analyzebehavior import AnalyzeAnimal from .analyzebehavior_dt import AnalyzeAnimalDetector +from LabGym import config from .minedata import data_mining -from .tools import plot_events,parse_all_events_file,calculate_distances - - -the_absolute_current_path=str(Path(__file__).resolve().parent) +from .tools import plot_events, parse_all_events_file, calculate_distances class ColorPicker(wx.Dialog): @@ -85,6 +83,10 @@ def __init__(self, parent): super().__init__(parent) self.notebook = parent + + # Get all of the values needed from config.get_config(). + self.config = config.get_config('detectors', 'models') + self.behavior_mode=0 # 0--non-interactive, 1--interactive basic, 2--interactive advanced, 3--static images self.use_detector=False # whether the Detector is used self.detector_path=None # the 'LabGym/detectors' folder, which stores all the trained Detectors @@ -247,7 +249,8 @@ def display_window(self): def select_categorizer(self,event): if self.model_path is None: - self.model_path=os.path.join(the_absolute_current_path,'models') + self.model_path = self.config['models'] + logger.debug('%s: %r', 'self.model_path', self.model_path) categorizers=[i for i in os.listdir(self.model_path) if os.path.isdir(os.path.join(self.model_path,i))] if '__pycache__' in categorizers: @@ -557,7 +560,8 @@ def select_method(self,event): else: self.animal_number={} - self.detector_path=os.path.join(the_absolute_current_path,'detectors') + self.detector_path = self.config['detectors'] + logger.debug('%s: %r', 'self.detector_path', self.detector_path) self.text_animalnumber.SetLabel('Default: 1.') detectors=[i for i in os.listdir(self.detector_path) if os.path.isdir(os.path.join(self.detector_path,i))] diff --git a/LabGym/gui_categorizer.py b/LabGym/gui_categorizer.py index 4c3e0e0..4176307 100644 --- a/LabGym/gui_categorizer.py +++ b/LabGym/gui_categorizer.py @@ -43,13 +43,11 @@ from .analyzebehavior_dt import AnalyzeAnimalDetector logger.debug('importing %s done', '.analyzebehavior_dt') from .categorizer import Categorizers +from LabGym import config from .tools import sort_examples_from_csv from .gui_utils import add_or_select_notebook_page -the_absolute_current_path=str(Path(__file__).resolve().parent) - - class PanelLv2_GenerateExamples(wx.Panel): ''' @@ -60,6 +58,10 @@ def __init__(self, parent): super().__init__(parent) self.notebook = parent + + # Get all of the values needed from config.get_config(). + self.config = config.get_config('detectors', 'models') + self.behavior_mode=0 # 0: non-interactive behavior; 1: interact basic; 2: interact advanced; 3: static images self.use_detector=False # whether the Detector is used self.detector_path=None # the 'LabGym/detectors' folder, which stores all the trained Detectors @@ -376,7 +378,8 @@ def select_method(self,event): self.use_detector=True self.animal_number={} - self.detector_path=os.path.join(the_absolute_current_path,'detectors') + self.detector_path = self.config['detectors'] + logger.debug('%s: %r', 'self.detector_path', self.detector_path) detectors=[i for i in os.listdir(self.detector_path) if os.path.isdir(os.path.join(self.detector_path,i))] if '__pycache__' in detectors: @@ -1063,6 +1066,10 @@ def __init__(self, parent): super().__init__(parent) self.notebook = parent + + # Get all of the values needed from config.get_config(). + self.config = config.get_config('models') + self.file_path=None # the folder that stores sorted, unprepared behavior examples (each category is a subfolder) self.new_path=None # the folder that stores prepared behavior examples (contains all examples with a category tag in their names) self.behavior_mode=0 # 0--non-interactive, 1--interactive basic, 2--interactive advanced, 3--static images @@ -1076,8 +1083,10 @@ def __init__(self, parent): self.aug_methods=[] # the methods for augment training and validation examples self.augvalid=True # whether to perform augmentation for validation data as well self.data_path=None # the folder that stores prepared behavior examples - self.model_path=os.path.join(the_absolute_current_path,'models') # the 'LabGym/models' folder, which stores all the trained Categorizers - self.path_to_categorizer=os.path.join(the_absolute_current_path,'models','New_model') # path to the Categorizer + self.model_path = self.config['models'] # the 'LabGym/models' folder, which stores all the trained Categorizers + logger.debug('%s: %r', 'self.model_path', self.model_path) + self.path_to_categorizer = os.path.join(self.config['models'], 'New_model') # path to the Categorizer + logger.debug('%s: %r', 'self.path_to_categorizer', self.path_to_categorizer) self.out_path=None # the folder for storing the training reports self.include_bodyparts=False # whether to include body parts in the pattern images self.std=0 # a value between 0 and 255, higher value, less body parts will be included in the pattern images @@ -1576,8 +1585,13 @@ def __init__(self, parent): super().__init__(parent) self.notebook = parent + + # Get all of the values needed from config.get_config(). + self.config = config.get_config('models') + self.file_path=None # the folder that stores the ground-truth examples (each subfolder is a behavior category) - self.model_path=os.path.join(the_absolute_current_path,'models') # the 'LabGym/models' folder, which stores all the trained Categorizers + self.model_path = self.config['models'] # the 'LabGym/models' folder, which stores all the trained Categorizers + logger.debug('%s: %r', 'self.model_path', self.model_path) self.path_to_categorizer=None # path to the Categorizer self.out_path=None # for storing the testing reports diff --git a/LabGym/gui_detector.py b/LabGym/gui_detector.py index 49b2a3c..ce726d7 100644 --- a/LabGym/gui_detector.py +++ b/LabGym/gui_detector.py @@ -20,8 +20,8 @@ # Standard library imports. import json import logging -from pathlib import Path import os +from pathlib import Path import shutil # Log the load of this module (by the module loader, on first import). @@ -34,13 +34,11 @@ import wx # Local application/library specific imports. +from LabGym import config from .detector import Detector from .tools import extract_frames -the_absolute_current_path=str(Path(__file__).resolve().parent) - - class PanelLv2_GenerateImages(wx.Panel): ''' @@ -236,11 +234,16 @@ def __init__(self, parent): super().__init__(parent) self.notebook = parent + + # Get all of the values needed from config.get_config(). + self.config = config.get_config('detectors') + self.path_to_trainingimages=None # the folder that stores all the training images self.path_to_annotation=None # the path to the .json file that stores the annotations in coco format self.inference_size=480 # the Detector inferencing frame size self.iteration_num=200 # the number of training iterations - self.detector_path=os.path.join(the_absolute_current_path,'detectors') # the 'LabGym/detectors' folder, which stores all the trained Detectors + self.detector_path = self.config['detectors'] # the 'LabGym/detectors' folder, which stores all the trained Detectors + logger.debug('%s: %r', 'self.detector_path', self.detector_path) self.path_to_detector=None # path to the Detector self.display_window() @@ -390,9 +393,14 @@ def __init__(self, parent): super().__init__(parent) self.notebook = parent + + # Get all of the values needed from config.get_config(). + self.config = config.get_config('detectors') + self.path_to_testingimages=None # the folder that stores all the testing images self.path_to_annotation=None # the path to the .json file that stores the annotations in coco format - self.detector_path=os.path.join(the_absolute_current_path,'detectors') # the 'LabGym/detectors' folder, which stores all the trained Detectors + self.detector_path = self.config['detectors'] # the 'LabGym/detectors' folder, which stores all the trained Detectors + logger.debug('%s: %r', 'self.detector_path', self.detector_path) self.path_to_detector=None # path to the Detector self.output_path=None # the folder that stores the testing images with annotations