pumaguard 20.post192__py3-none-any.whl → 20.post229__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pumaguard/main.py CHANGED
@@ -50,6 +50,12 @@ def create_global_parser() -> argparse.ArgumentParser:
50
50
  choices=["bash"],
51
51
  help="Print out bash completion script",
52
52
  )
53
+ global_parser.add_argument(
54
+ "--log-file",
55
+ help="Path to log file (default: ~/.cache/pumaguard/pumaguard.log)",
56
+ type=str,
57
+ default=None,
58
+ )
53
59
  global_parser.add_argument(
54
60
  "--model-path",
55
61
  help="Where the models are stored (default = %(default)s)",
@@ -183,19 +189,7 @@ def main():
183
189
  logging.basicConfig(level=logging.INFO)
184
190
  logger = logging.getLogger("PumaGuard")
185
191
 
186
- # Store logs in XDG cache directory
187
- log_dir = get_xdg_cache_home() / "pumaguard"
188
- log_dir.mkdir(parents=True, exist_ok=True)
189
- log_file = log_dir / "pumaguard.log"
190
-
191
- file_handler = logging.FileHandler(str(log_file))
192
- file_handler.setLevel(logging.DEBUG)
193
- formatter = logging.Formatter(
194
- "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
195
- )
196
- file_handler.setFormatter(formatter)
197
- logger.addHandler(file_handler)
198
-
192
+ # Parse args early to get log file location
199
193
  global_args_parser = create_global_parser()
200
194
  parser = argparse.ArgumentParser(
201
195
  description="""The goal of this project is to accurately classify
@@ -205,11 +199,31 @@ def main():
205
199
  dataset and validated using a separate set of images.""",
206
200
  parents=[global_args_parser],
207
201
  )
208
-
209
202
  configure_subparsers(parser, global_args_parser)
210
-
211
203
  args = parser.parse_args()
212
204
 
205
+ # Determine log file location
206
+ if args.log_file:
207
+ log_file = args.log_file
208
+ # Ensure parent directory exists
209
+ log_dir = os.path.dirname(log_file)
210
+ if log_dir:
211
+ os.makedirs(log_dir, exist_ok=True)
212
+ else:
213
+ # Store logs in XDG cache directory (default)
214
+ log_dir = get_xdg_cache_home() / "pumaguard"
215
+ log_dir.mkdir(parents=True, exist_ok=True)
216
+ log_file = str(log_dir / "pumaguard.log")
217
+
218
+ file_handler = logging.FileHandler(log_file)
219
+ file_handler.setLevel(logging.DEBUG)
220
+ formatter = logging.Formatter(
221
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
222
+ )
223
+ file_handler.setFormatter(formatter)
224
+ logger.addHandler(file_handler)
225
+ logger.info("Logging to: %s", log_file)
226
+
213
227
  if args.debug:
214
228
  logger.setLevel(logging.DEBUG)
215
229
 
@@ -23,7 +23,7 @@ import yaml
23
23
 
24
24
  logger = logging.getLogger("PumaGuard")
25
25
 
26
- MODEL_TAG = "e053533cdcb35d681972cb3a1b96d4c023c84516"
26
+ MODEL_TAG = "82ec09d65cabd06d46aeefed3a0317200888367d"
27
27
  MODEL_BASE_URI = (
28
28
  "https://github.com/PEEC-Nature-Youth-Group/pumaguard-models/raw"
29
29
  )
pumaguard/presets.py CHANGED
@@ -120,7 +120,7 @@ class Preset:
120
120
  self.settings_file = get_default_settings_file()
121
121
  self.yolo_min_size = 0.02
122
122
  self.yolo_conf_thresh = 0.25
123
- self.yolo_max_dets = 12
123
+ self.yolo_max_dets = 2
124
124
  self.yolo_model_filename = "yolov8s_101425.pt"
125
125
  self.classifier_model_filename = "colorbw_111325.h5"
126
126
  self.alpha = 1e-5
@@ -130,7 +130,7 @@ class Preset:
130
130
  self.sound_path = os.path.join(
131
131
  os.path.dirname(__file__), "../pumaguard-sounds"
132
132
  )
133
- self.deterrent_sound_file = "cougar_call.mp3"
133
+ self.deterrent_sound_file = "deterrent_puma.mp3"
134
134
  self.verification_path = "data/stable/stable_test"
135
135
  self.batch_size = 16
136
136
  self.notebook_number = 1
@@ -196,7 +196,22 @@ class Preset:
196
196
  )
197
197
  return
198
198
  except yaml.constructor.ConstructorError as e:
199
- raise PresetError(str(e)) from e
199
+ error_msg = str(e)
200
+ if "python/tuple" in error_msg:
201
+ raise PresetError(
202
+ f"{error_msg}\n\n"
203
+ "Your settings file contains Python-specific tuple "
204
+ "formatting that is no longer supported.\n"
205
+ f"Please update {filename} to use YAML list syntax.\n"
206
+ "For example, change:\n"
207
+ " image-dimensions: !!python/tuple [512, 512]\n"
208
+ "to:\n"
209
+ " image-dimensions:\n"
210
+ " - 512\n"
211
+ " - 512\n"
212
+ "Or delete the file to use defaults."
213
+ ) from e
214
+ raise PresetError(error_msg) from e
200
215
 
201
216
  self.yolo_min_size = settings.get("YOLO-min-size", 0.02)
202
217
  self.yolo_conf_thresh = settings.get("YOLO-conf-thresh", 0.25)
@@ -308,7 +323,7 @@ class Preset:
308
323
  "color-mode": self.color_mode,
309
324
  "file-stabilization-extra-wait": self.file_stabilization_extra_wait,
310
325
  "epochs": self.epochs,
311
- "image-dimensions": self.image_dimensions,
326
+ "image-dimensions": list(self.image_dimensions),
312
327
  "lion-directories": self.lion_directories,
313
328
  "validation-lion-directories": self.validation_lion_directories,
314
329
  "model-function": self.model_function_name,