britekit 0.1.2__tar.gz → 0.1.3__tar.gz

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.

Potentially problematic release.


This version of britekit might be problematic. Click here for more details.

Files changed (125) hide show
  1. {britekit-0.1.2 → britekit-0.1.3}/PKG-INFO +1 -1
  2. {britekit-0.1.2 → britekit-0.1.3}/britekit/__about__.py +1 -1
  3. {britekit-0.1.2 → britekit-0.1.3}/britekit/__init__.py +6 -2
  4. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_analyze.py +3 -1
  5. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_reports.py +21 -7
  6. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/base_model.py +1 -0
  7. britekit-0.1.2/src/britekit/testing/per_minute_tester.py → britekit-0.1.3/src/britekit/testing/per_block_tester.py +39 -36
  8. {britekit-0.1.2 → britekit-0.1.3}/.gitignore +0 -0
  9. {britekit-0.1.2 → britekit-0.1.3}/LICENSE.txt +0 -0
  10. {britekit-0.1.2 → britekit-0.1.3}/README.md +0 -0
  11. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/__init__.py +0 -0
  12. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_audioset.py +0 -0
  13. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_calibrate.py +0 -0
  14. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_ckpt_ops.py +0 -0
  15. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_db_add.py +0 -0
  16. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_db_delete.py +0 -0
  17. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_embed.py +0 -0
  18. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_ensemble.py +0 -0
  19. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_extract.py +0 -0
  20. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_find_dup.py +0 -0
  21. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_inat.py +0 -0
  22. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_init.py +0 -0
  23. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_pickle.py +0 -0
  24. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_plot.py +0 -0
  25. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_reextract.py +0 -0
  26. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_search.py +0 -0
  27. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_train.py +0 -0
  28. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_tune.py +0 -0
  29. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_wav2mp3.py +0 -0
  30. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_xeno.py +0 -0
  31. {britekit-0.1.2 → britekit-0.1.3}/britekit/commands/_youtube.py +0 -0
  32. {britekit-0.1.2 → britekit-0.1.3}/britekit/core/__init__.py +0 -0
  33. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/class_inclusion.csv +0 -0
  34. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/class_list.csv +0 -0
  35. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/aircraft.csv +0 -0
  36. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/car.csv +0 -0
  37. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/chainsaw.csv +0 -0
  38. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/cow.csv +0 -0
  39. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/cricket.csv +0 -0
  40. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/dog.csv +0 -0
  41. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/rain.csv +0 -0
  42. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/rooster.csv +0 -0
  43. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/sheep.csv +0 -0
  44. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/siren.csv +0 -0
  45. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/speech.csv +0 -0
  46. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/truck.csv +0 -0
  47. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/curated/wind.csv +0 -0
  48. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/audioset/unbalanced_train_segments.csv +0 -0
  49. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/classes.csv +0 -0
  50. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/data/ignore.txt +0 -0
  51. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/base_config.yaml +0 -0
  52. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/cfg_infer.yaml +0 -0
  53. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/train_dla.yaml +0 -0
  54. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/train_effnet.yaml +0 -0
  55. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/train_gernet.yaml +0 -0
  56. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/train_hgnet.yaml +0 -0
  57. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/train_timm.yaml +0 -0
  58. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/train_vovnet.yaml +0 -0
  59. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/tune_dropout.yaml +0 -0
  60. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/tune_learning_rate.yaml +0 -0
  61. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/tune_optimizer.yaml +0 -0
  62. {britekit-0.1.2 → britekit-0.1.3}/britekit/install/yaml/samples/tune_smooth.yaml +0 -0
  63. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/class_inclusion.csv +0 -0
  64. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/class_list.csv +0 -0
  65. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/aircraft.csv +0 -0
  66. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/car.csv +0 -0
  67. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/chainsaw.csv +0 -0
  68. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/cow.csv +0 -0
  69. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/cricket.csv +0 -0
  70. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/dog.csv +0 -0
  71. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/rain.csv +0 -0
  72. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/rooster.csv +0 -0
  73. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/sheep.csv +0 -0
  74. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/siren.csv +0 -0
  75. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/speech.csv +0 -0
  76. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/truck.csv +0 -0
  77. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/curated/wind.csv +0 -0
  78. {britekit-0.1.2 → britekit-0.1.3}/install/data/audioset/unbalanced_train_segments.csv +0 -0
  79. {britekit-0.1.2 → britekit-0.1.3}/install/data/classes.csv +0 -0
  80. {britekit-0.1.2 → britekit-0.1.3}/install/data/ignore.txt +0 -0
  81. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/base_config.yaml +0 -0
  82. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/cfg_infer.yaml +0 -0
  83. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/train_dla.yaml +0 -0
  84. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/train_effnet.yaml +0 -0
  85. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/train_gernet.yaml +0 -0
  86. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/train_hgnet.yaml +0 -0
  87. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/train_timm.yaml +0 -0
  88. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/train_vovnet.yaml +0 -0
  89. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/tune_dropout.yaml +0 -0
  90. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/tune_learning_rate.yaml +0 -0
  91. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/tune_optimizer.yaml +0 -0
  92. {britekit-0.1.2 → britekit-0.1.3}/install/yaml/samples/tune_smooth.yaml +0 -0
  93. {britekit-0.1.2 → britekit-0.1.3}/pyproject.toml +0 -0
  94. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/cli.py +0 -0
  95. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/analyzer.py +0 -0
  96. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/audio.py +0 -0
  97. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/augmentation.py +0 -0
  98. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/base_config.py +0 -0
  99. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/config_loader.py +0 -0
  100. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/data_module.py +0 -0
  101. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/dataset.py +0 -0
  102. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/exceptions.py +0 -0
  103. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/pickler.py +0 -0
  104. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/plot.py +0 -0
  105. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/predictor.py +0 -0
  106. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/reextractor.py +0 -0
  107. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/trainer.py +0 -0
  108. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/tuner.py +0 -0
  109. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/core/util.py +0 -0
  110. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/dla.py +0 -0
  111. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/effnet.py +0 -0
  112. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/gernet.py +0 -0
  113. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/head_factory.py +0 -0
  114. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/hgnet.py +0 -0
  115. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/model_loader.py +0 -0
  116. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/timm_model.py +0 -0
  117. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/models/vovnet.py +0 -0
  118. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/occurrence_db/occurrence_data_provider.py +0 -0
  119. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/occurrence_db/occurrence_db.py +0 -0
  120. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/testing/base_tester.py +0 -0
  121. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/testing/per_recording_tester.py +0 -0
  122. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/testing/per_segment_tester.py +0 -0
  123. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/training_db/extractor.py +0 -0
  124. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/training_db/training_data_provider.py +0 -0
  125. {britekit-0.1.2 → britekit-0.1.3}/src/britekit/training_db/training_db.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: britekit
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Core functions for bioacoustic recognizers.
5
5
  Project-URL: Documentation, https://github.com/jhuus/BriteKit#readme
6
6
  Project-URL: Issues, https://github.com/jhuus/BriteKit/issues
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2025-present Jan Huus <jhuus1@gmail.com>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "0.1.2"
4
+ __version__ = "0.1.3"
@@ -26,9 +26,11 @@ from britekit.core.pickler import Pickler
26
26
  from britekit.core.predictor import Predictor
27
27
  from britekit.core.trainer import Trainer
28
28
  from britekit.core.tuner import Tuner
29
+ from britekit.models.model_loader import load_new_model
30
+ from britekit.models.model_loader import load_from_checkpoint
29
31
  from britekit.occurrence_db.occurrence_db import OccurrenceDatabase
30
32
  from britekit.occurrence_db.occurrence_data_provider import OccurrenceDataProvider
31
- from britekit.testing.per_minute_tester import PerMinuteTester
33
+ from britekit.testing.per_block_tester import PerBlockTester
32
34
  from britekit.testing.per_recording_tester import PerRecordingTester
33
35
  from britekit.testing.per_segment_tester import PerSegmentTester
34
36
  from britekit.training_db.extractor import Extractor
@@ -39,6 +41,8 @@ __all__ = [
39
41
  "__version__",
40
42
  "commands",
41
43
  "get_config",
44
+ "load_new_model",
45
+ "load_from_checkpoint",
42
46
  "util",
43
47
  "Analyzer",
44
48
  "Audio",
@@ -47,7 +51,7 @@ __all__ = [
47
51
  "OccurrenceDatabase",
48
52
  "OccurrenceDataProvider",
49
53
  "Pickler",
50
- "PerMinuteTester",
54
+ "PerBlockTester",
51
55
  "PerRecordingTester",
52
56
  "PerSegmentTester",
53
57
  "Predictor",
@@ -46,7 +46,6 @@ def analyze(
46
46
  from britekit.core import util
47
47
  from britekit.core.analyzer import Analyzer
48
48
 
49
- util.set_logging()
50
49
  cfg = get_config(cfg_path)
51
50
  try:
52
51
  if rtype not in {"audacity", "csv", "both"}:
@@ -155,6 +154,9 @@ def _analyze_cmd(
155
154
  overlap: Optional[float] = None,
156
155
  segment_len: Optional[float] = None,
157
156
  ):
157
+ from britekit.core import util
158
+
159
+ util.set_logging()
158
160
  analyze(
159
161
  cfg_path,
160
162
  input_path,
@@ -528,6 +528,7 @@ def rpt_test(
528
528
  output_path: str = "",
529
529
  recordings_path: Optional[str] = None,
530
530
  min_score: Optional[float] = None,
531
+ block_size: int = 60,
531
532
  precision: float = 0.95,
532
533
  ):
533
534
  """
@@ -536,7 +537,7 @@ def rpt_test(
536
537
  This command evaluates model performance by comparing inference results against
537
538
  ground truth annotations. It supports three granularity levels:
538
539
  - "recording": Evaluate at the recording level (presence/absence)
539
- - "minute": Evaluate at the minute level (presence/absence per minute)
540
+ - "block": Evaluate at the block level (presence/absence per block)
540
541
  - "segment": Evaluate at the segment level (detailed temporal alignment)
541
542
 
542
543
  The command generates detailed performance metrics including precision, recall,
@@ -544,15 +545,16 @@ def rpt_test(
544
545
 
545
546
  Args:
546
547
  cfg_path (str, optional): Path to YAML file defining configuration overrides.
547
- granularity (str): Evaluation granularity ("recording", "minute", or "segment"). Default is "segment".
548
+ granularity (str): Evaluation granularity ("recording", "block", or "segment"). Default is "segment".
548
549
  annotations_path (str): Path to CSV file containing ground truth annotations.
549
550
  label_dir (str): Directory containing model prediction labels (Audacity format).
550
551
  output_path (str): Directory where test reports will be saved.
551
552
  recordings_path (str, optional): Directory containing audio recordings. Defaults to annotations directory.
552
553
  min_score (float, optional): Provide detailed reports for this confidence threshold.
554
+ block_size (int, optional): block_size in seconds (default=60).
553
555
  precision (float): For recording granularity, report true positive seconds at this precision. Default is 0.95.
554
556
  """
555
- from britekit.testing.per_minute_tester import PerMinuteTester
557
+ from britekit.testing.per_block_tester import PerBlockTester
556
558
  from britekit.testing.per_recording_tester import PerRecordingTester
557
559
  from britekit.testing.per_segment_tester import PerSegmentTester
558
560
 
@@ -582,13 +584,14 @@ def rpt_test(
582
584
  min_score,
583
585
  precision,
584
586
  ).run()
585
- elif granularity.startswith("min"):
586
- PerMinuteTester(
587
+ elif granularity.startswith("bl"):
588
+ PerBlockTester(
587
589
  annotations_path,
588
590
  recordings_path,
589
591
  labels_path,
590
592
  output_path,
591
593
  min_score,
594
+ block_size,
592
595
  ).run()
593
596
  elif granularity.startswith("seg"):
594
597
  PerSegmentTester(
@@ -600,7 +603,7 @@ def rpt_test(
600
603
  ).run()
601
604
  else:
602
605
  logging.error(
603
- 'Invalid granularity (expected "recording", "minute" or "segment").'
606
+ 'Invalid granularity (expected "recording", "block" or "segment").'
604
607
  )
605
608
 
606
609
  except InputError as e:
@@ -626,7 +629,7 @@ def rpt_test(
626
629
  "granularity",
627
630
  type=str,
628
631
  default="segment",
629
- help='Test annotation and reporting granularity ("recording", "minute" or "segment"). Default = "segment".',
632
+ help='Test annotation and reporting granularity ("recording", "block" or "segment"). Default = "segment".',
630
633
  )
631
634
  @click.option(
632
635
  "-a",
@@ -668,6 +671,15 @@ def rpt_test(
668
671
  required=False,
669
672
  help="Provide detailed reports for this threshold.",
670
673
  )
674
+ @click.option(
675
+ "-b",
676
+ "--block",
677
+ "block_size",
678
+ type=int,
679
+ required=False,
680
+ default=60,
681
+ help="Block size in seconds, when granularity=block (default=60).",
682
+ )
671
683
  @click.option(
672
684
  "--precision",
673
685
  required=False,
@@ -683,6 +695,7 @@ def _rpt_test_cmd(
683
695
  output_path: str,
684
696
  recordings_path: Optional[str],
685
697
  min_score: Optional[float],
698
+ block_size: int,
686
699
  precision: float,
687
700
  ):
688
701
  util.set_logging()
@@ -694,5 +707,6 @@ def _rpt_test_cmd(
694
707
  output_path,
695
708
  recordings_path,
696
709
  min_score,
710
+ block_size,
697
711
  precision,
698
712
  )
@@ -252,6 +252,7 @@ class BaseModel(pl.LightningModule):
252
252
  }
253
253
 
254
254
  def on_save_checkpoint(self, checkpoint):
255
+ print("on_save_checkpoint")
255
256
  """Save model metadata to checkpoint."""
256
257
  if not hasattr(self, "identifier"):
257
258
  self.identifier = str(uuid.uuid4()).upper()
@@ -17,16 +17,16 @@ class Annotation:
17
17
  return f"{self.class_code}: {self.start_time}-{self.end_time}"
18
18
 
19
19
 
20
- class PerMinuteTester(BaseTester):
20
+ class PerBlockTester(BaseTester):
21
21
  """
22
- Calculate test metrics when annotations are specified per minute. That is, for selected minutes of
23
- each recording, a list of classes known to be present is given, and we are to calculate metrics for
24
- those minutes only.
22
+ Calculate test metrics when annotations are specified per block, where a block is a fixed length, such
23
+ as a minute. That is, for selected blocks of each recording, a list of classes known to be present is given,
24
+ and we are to calculate metrics for those blocks only.
25
25
 
26
- Annotations are read as a CSV with three columns: "recording", "minute", and "classes".
26
+ Annotations are read as a CSV with three columns: "recording", "block", and "classes".
27
27
  The recording column is the file name without the path or type suffix, e.g. "recording1".
28
- The minute column contains 1 for the first minute, 2 for the second minute etc. and may
29
- exclude some minutes. The classes column contains a comma-separated list of codes for the classes found in the corresponding minute.
28
+ The block column contains 1 for the first block, 2 for the second block etc. and may exclude some blocks.
29
+ The classes column contains a comma-separated list of codes for the classes found in the corresponding block.
30
30
  If your annotations are in a different format, simply convert to this format to use this script.
31
31
 
32
32
  Classifiers should be run with a threshold of 0, and with label merging disabled so segment-specific scores are retained.
@@ -37,6 +37,7 @@ class PerMinuteTester(BaseTester):
37
37
  label_dir (str): Directory containing Audacity labels.
38
38
  output_dir (str): Output directory, where reports will be written.
39
39
  threshold (float): Score threshold for precision/recall reporting.
40
+ block_size (int, optional): block_size in seconds (default=60).
40
41
  gen_pr_table (bool, optional): If true, generate a PR table, which may be slow (default = False).
41
42
  """
42
43
 
@@ -47,10 +48,11 @@ class PerMinuteTester(BaseTester):
47
48
  label_dir: str,
48
49
  output_dir: str,
49
50
  threshold: float,
51
+ block_size: int = 60,
50
52
  gen_pr_table: bool = False,
51
53
  ):
52
54
  """
53
- Initialize the PerMinuteTester.
55
+ Initialize the PerBlockTester.
54
56
 
55
57
  See class docstring for detailed parameter descriptions and usage information.
56
58
  """
@@ -60,6 +62,7 @@ class PerMinuteTester(BaseTester):
60
62
  self.label_dir = label_dir
61
63
  self.output_dir = output_dir
62
64
  self.threshold = threshold
65
+ self.block_size = block_size
63
66
  self.gen_pr_table = gen_pr_table
64
67
 
65
68
  self.cfg = get_config()
@@ -119,8 +122,8 @@ class PerMinuteTester(BaseTester):
119
122
  Load annotation data from CSV file and process into internal format.
120
123
 
121
124
  This method reads a CSV file containing ground truth annotations where each row
122
- represents a recording, minute, and its associated classes. The CSV should have columns:
123
- "recording" (filename without path/extension), "minute" (minute number starting from 1),
125
+ represents a recording, block, and its associated classes. The CSV should have columns:
126
+ "recording" (filename without path/extension), "block" (block number starting from 1),
124
127
  and "classes" (comma-separated class codes).
125
128
 
126
129
  The method processes the annotations, handles class code mapping, filters out
@@ -151,10 +154,10 @@ class PerMinuteTester(BaseTester):
151
154
  self.annotations[recording] = {}
152
155
  self.segments_per_recording[recording] = []
153
156
 
154
- minute = row["minute"]
155
- if minute not in self.annotations[recording]:
156
- self.annotations[recording][minute] = []
157
- self.segments_per_recording[recording].append(minute - 1)
157
+ block = row["block"]
158
+ if block not in self.annotations[recording]:
159
+ self.annotations[recording][block] = []
160
+ self.segments_per_recording[recording].append(block - 1)
158
161
 
159
162
  input_class_list = []
160
163
  for code in row["classes"].split(","):
@@ -176,7 +179,7 @@ class PerMinuteTester(BaseTester):
176
179
  continue # exclude from saved annotations
177
180
 
178
181
  if class_code:
179
- self.annotations[recording][minute].append(class_code)
182
+ self.annotations[recording][block].append(class_code)
180
183
  self.annotated_class_set.add(class_code)
181
184
 
182
185
  self.annotated_classes = sorted(list(self.annotated_class_set))
@@ -192,12 +195,12 @@ class PerMinuteTester(BaseTester):
192
195
 
193
196
  This method evaluates precision and recall metrics at different threshold values
194
197
  (0.01 to 1.00 in 0.01 increments) to create comprehensive precision-recall curves.
195
- It calculates both per-minute granularity metrics and per-second granularity metrics.
198
+ It calculates both per-block granularity metrics and per-second granularity metrics.
196
199
 
197
200
  Returns:
198
201
  dict: Dictionary containing precision-recall data with keys:
199
202
  - annotated_thresholds: List of threshold values for annotated classes
200
- - annotated_precisions_minutes: List of precision values (minutes) for annotated classes
203
+ - annotated_precisions_blocks: List of precision values (blocks) for annotated classes
201
204
  - annotated_precisions_seconds: List of precision values (seconds) for annotated classes
202
205
  - annotated_recalls: List of recall values for annotated classes
203
206
  - trained_thresholds: List of threshold values for trained classes
@@ -219,20 +222,20 @@ class PerMinuteTester(BaseTester):
219
222
 
220
223
  # use the looping method so we get per_second precision
221
224
  thresholds = []
222
- recall_annotated, precision_annotated_minutes, precision_annotated_seconds = (
225
+ recall_annotated, precision_annotated_blocks, precision_annotated_seconds = (
223
226
  [],
224
227
  [],
225
228
  [],
226
229
  )
227
- recall_trained, precision_trained_minutes = [], []
230
+ recall_trained, precision_trained_blocks = [], []
228
231
  for threshold in np.arange(0.01, 1.01, 0.01):
229
232
  info = self.get_precision_recall(threshold)
230
233
  thresholds.append(threshold)
231
234
  recall_annotated.append(info["recall_annotated"])
232
- precision_annotated_minutes.append(info["precision_annotated"])
235
+ precision_annotated_blocks.append(info["precision_annotated"])
233
236
  precision_annotated_seconds.append(info["precision_secs"])
234
237
  recall_trained.append(info["recall_trained"])
235
- precision_trained_minutes.append(info["precision_trained"])
238
+ precision_trained_blocks.append(info["precision_trained"])
236
239
  logging.info(
237
240
  f"\rPercent complete: {int(threshold * 100)}%", end="", flush=True
238
241
  )
@@ -240,12 +243,12 @@ class PerMinuteTester(BaseTester):
240
243
  logging.info("")
241
244
  pr_table_dict = {}
242
245
  pr_table_dict["annotated_thresholds"] = thresholds
243
- pr_table_dict["annotated_precisions_minutes"] = precision_annotated_minutes
246
+ pr_table_dict["annotated_precisions_blocks"] = precision_annotated_blocks
244
247
  pr_table_dict["annotated_precisions_seconds"] = precision_annotated_seconds
245
248
  pr_table_dict["annotated_recalls"] = recall_annotated
246
249
 
247
250
  pr_table_dict["trained_thresholds"] = thresholds
248
- pr_table_dict["trained_precisions"] = precision_trained_minutes
251
+ pr_table_dict["trained_precisions"] = precision_trained_blocks
249
252
  pr_table_dict["trained_recalls"] = recall_trained
250
253
 
251
254
  # use this method for more granular results without per_second precision
@@ -303,7 +306,7 @@ class PerMinuteTester(BaseTester):
303
306
  if self.gen_pr_table:
304
307
  # calculate and output precision/recall per threshold
305
308
  threshold_annotated = self.pr_table_dict["annotated_thresholds"]
306
- precision_annotated = self.pr_table_dict["annotated_precisions_minutes"]
309
+ precision_annotated = self.pr_table_dict["annotated_precisions_blocks"]
307
310
  precision_annotated_secs = self.pr_table_dict[
308
311
  "annotated_precisions_seconds"
309
312
  ]
@@ -401,13 +404,13 @@ class PerMinuteTester(BaseTester):
401
404
  )
402
405
  rpt.append(f" For threshold = {self.threshold}:\n")
403
406
  rpt.append(
404
- f" Precision (minutes) = {100 * self.details_dict['precision_annotated']:.2f}%\n"
407
+ f" Precision (blocks) = {100 * self.details_dict['precision_annotated']:.2f}%\n"
405
408
  )
406
409
  rpt.append(
407
410
  f" Precision (seconds) = {100 * self.details_dict['precision_secs']:.2f}%\n"
408
411
  )
409
412
  rpt.append(
410
- f" Recall (minutes) = {100 * self.details_dict['recall_annotated']:.2f}%\n"
413
+ f" Recall (blocks) = {100 * self.details_dict['recall_annotated']:.2f}%\n"
411
414
  )
412
415
 
413
416
  rpt.append("\n")
@@ -420,10 +423,10 @@ class PerMinuteTester(BaseTester):
420
423
  )
421
424
  rpt.append(f" For threshold = {self.threshold}:\n")
422
425
  rpt.append(
423
- f" Precision (minutes) = {100 * self.details_dict['precision_trained']:.2f}%\n"
426
+ f" Precision (blocks) = {100 * self.details_dict['precision_trained']:.2f}%\n"
424
427
  )
425
428
  rpt.append(
426
- f" Recall (minutes) = {100 * self.details_dict['recall_trained']:.2f}%\n"
429
+ f" Recall (blocks) = {100 * self.details_dict['recall_trained']:.2f}%\n"
427
430
  )
428
431
  logging.info("")
429
432
  with open(os.path.join(self.output_dir, "summary_report.txt"), "w") as summary:
@@ -551,7 +554,7 @@ class PerMinuteTester(BaseTester):
551
554
 
552
555
  # initialize y_true and y_pred and save them as CSV files
553
556
  logging.info("Initializing")
554
- self.get_labels(self.label_dir, segment_len=60, overlap=0)
557
+ self.get_labels(self.label_dir, segment_len=self.block_size, overlap=0)
555
558
  self.get_annotations()
556
559
  self._init_y_true()
557
560
  self.init_y_pred(segments_per_recording=self.segments_per_recording)
@@ -573,7 +576,7 @@ class PerMinuteTester(BaseTester):
573
576
 
574
577
  def _init_y_true(self):
575
578
  """
576
- Create a dataframe representing the ground truth data, with recordings segmented into 1-minute segments
579
+ Create a dataframe representing the ground truth data, with recordings segmented into 1-block segments
577
580
  """
578
581
  import pandas as pd
579
582
 
@@ -582,11 +585,11 @@ class PerMinuteTester(BaseTester):
582
585
  self.recordings = [] # base class needs array with recording per row
583
586
  rows = []
584
587
  for recording in sorted(self.annotations.keys()):
585
- for minute in sorted(self.annotations[recording].keys()):
588
+ for block in sorted(self.annotations[recording].keys()):
586
589
  self.recordings.append(recording)
587
- row = [f"{recording}-{minute - 1}"]
590
+ row = [f"{recording}-{block - 1}"]
588
591
  row.extend([0 for class_code in self.trained_classes])
589
- for class_code in self.annotations[recording][minute]:
592
+ for class_code in self.annotations[recording][block]:
590
593
  if class_code in self.trained_class_indexes:
591
594
  row[self.trained_class_indexes[class_code] + 1] = 1
592
595
 
@@ -618,8 +621,8 @@ class PerMinuteTester(BaseTester):
618
621
 
619
622
  df = pd.DataFrame()
620
623
  df["threshold"] = pd.Series(threshold)
621
- df["recall (minutes)"] = pd.Series(recall)
622
- df["precision (minutes)"] = pd.Series(precision)
624
+ df["recall (blocks)"] = pd.Series(recall)
625
+ df["precision (blocks)"] = pd.Series(precision)
623
626
  if precision_secs is not None:
624
627
  df["precision (seconds)"] = pd.Series(precision_secs)
625
628
 
@@ -631,7 +634,7 @@ class PerMinuteTester(BaseTester):
631
634
 
632
635
  plt.clf()
633
636
  plt.plot(recall, label="Recall")
634
- plt.plot(precision, label="Precision (Minutes)")
637
+ plt.plot(precision, label="Precision (blocks)")
635
638
  if precision_secs is not None:
636
639
  plt.plot(precision_secs, label="Precision (Seconds)")
637
640
 
File without changes
File without changes
File without changes
File without changes
File without changes