Dr. Richard Zinck commited on
Commit
4bf2fee
1 Parent(s): 5b6d5de
Files changed (2) hide show
  1. bat_gui.py +37 -209
  2. bat_ident.py +0 -1
bat_gui.py CHANGED
@@ -10,11 +10,11 @@ import segments
10
  import utils
11
  import logging
12
  import librosa
 
13
  logging.basicConfig(filename='bat_gui.log', encoding='utf-8', level=logging.DEBUG)
14
 
15
  _WINDOW: webview.Window
16
 
17
-
18
  _AREA_ONE = "EU"
19
  _AREA_TWO = "Bavaria"
20
  _AREA_THREE = "USA"
@@ -28,11 +28,14 @@ OUTPUT_TYPE_MAP = {"Raven selection table": "table", "Audacity": "audacity", "R"
28
  ORIGINAL_MODEL_PATH = cfg.MODEL_PATH
29
  ORIGINAL_MDATA_MODEL_PATH = cfg.MDATA_MODEL_PATH
30
  ORIGINAL_LABELS_FILE = cfg.LABELS_FILE
31
- ORIGINAL_TRANSLATED_LABELS_PATH = cfg.TRANSLATED_BAT_LABELS_PATH # cfg.TRANSLATED_LABELS_PATH
 
32
 
33
  def analyzeFile_wrapper(entry):
34
- #return (entry[0], analyze.analyzeFile(entry))
35
  return (entry[0], bat_ident.analyze_file(entry))
 
 
36
  def validate(value, msg):
37
  """Checks if the value ist not falsy.
38
  If the value is falsy, an error will be raised.
@@ -44,41 +47,6 @@ def validate(value, msg):
44
  raise gr.Error(msg)
45
 
46
 
47
- def runBatchAnalysis(
48
- output_path,
49
- confidence,
50
- sensitivity,
51
- overlap,
52
- species_list_choice,
53
- locale,
54
- batch_size,
55
- threads,
56
- input_dir,
57
- output_type_radio,
58
- progress=gr.Progress(),
59
- ):
60
- validate(input_dir, "Please select a directory.")
61
- batch_size = int(batch_size)
62
- threads = int(threads)
63
-
64
- return runAnalysis(
65
- species_list_choice,
66
- None,
67
- output_path,
68
- confidence,
69
- sensitivity,
70
- overlap,
71
- output_type_radio,
72
- "en" if not locale else locale,
73
- batch_size,
74
- threads,
75
- input_dir,
76
- progress,
77
- )
78
-
79
-
80
-
81
-
82
  def runSingleFileAnalysis(input_path,
83
  confidence,
84
  sensitivity,
@@ -97,24 +65,25 @@ def runSingleFileAnalysis(input_path,
97
  "csv",
98
  "en" if not locale else locale,
99
  1,
100
- 4,
101
  None,
102
  progress=None,
103
  )
104
 
 
105
  def runAnalysis(
106
- species_list_choice: str,
107
- input_path: str,
108
- output_path: str | None,
109
- confidence: float,
110
- sensitivity: float,
111
- overlap: float,
112
- output_type: str,
113
- locale: str,
114
- batch_size: int,
115
- threads: int,
116
- input_dir: str,
117
- progress: gr.Progress | None,
118
  ):
119
  """Starts the analysis.
120
  Args:
@@ -143,7 +112,7 @@ def runAnalysis(
143
  progress(0, desc="Preparing ...")
144
  # locale = locale.lower()
145
  # Load eBird codes, labels
146
- #cfg.CODES = analyze.loadCodes()
147
  # cfg.LABELS = utils.readLines(ORIGINAL_LABELS_FILE)
148
  cfg.LATITUDE, cfg.LONGITUDE, cfg.WEEK = -1, -1, -1
149
  cfg.LOCATION_FILTER_THRESHOLD = 0.03
@@ -282,10 +251,13 @@ def runAnalysis(
282
  progress((i, len(flist)), total=len(flist), unit="files")
283
  result = f.result()
284
  result_list.append(result)
285
- return [[os.path.relpath(r[0], input_dir), r[1]] for r in result_list] if input_dir else cfg.OUTPUT_PATH
 
286
 
287
  def extractSegments_wrapper(entry):
288
  return (entry[0][0], segments.extractSegments(entry))
 
 
289
  def extract_segments(audio_dir, result_dir, output_dir, min_conf, num_seq, seq_length, threads, progress=gr.Progress()):
290
  validate(audio_dir, "No audio directory selected")
291
 
@@ -298,7 +270,6 @@ def extract_segments(audio_dir, result_dir, output_dir, min_conf, num_seq, seq_l
298
  if progress is not None:
299
  progress(0, desc="Searching files ...")
300
 
301
-
302
  # Parse audio and result folders
303
  cfg.FILE_LIST = segments.parseFolders(audio_dir, result_dir)
304
 
@@ -353,6 +324,7 @@ def select_file(filetypes=()):
353
  files = _WINDOW.create_file_dialog(webview.OPEN_DIALOG, file_types=filetypes)
354
  return files[0] if files else None
355
 
 
356
  def format_seconds(secs: float):
357
  """Formats a number of seconds into a string.
358
 
@@ -369,6 +341,7 @@ def format_seconds(secs: float):
369
 
370
  return "{:2.0f}:{:02.0f}:{:06.3f}".format(hours, minutes, secs)
371
 
 
372
  def select_directory(collect_files=True):
373
  """Shows a directory selection system dialog.
374
 
@@ -417,10 +390,6 @@ def show_species_choice(choice: str):
417
  ]
418
 
419
 
420
-
421
-
422
-
423
-
424
  #
425
  # VIEW - This is where the UI elements are defined
426
  #
@@ -436,7 +405,8 @@ def sample_sliders(opened=True):
436
  with gr.Accordion("Inference settings", open=opened):
437
  with gr.Row():
438
  confidence_slider = gr.Slider(
439
- minimum=0, maximum=1, value=0.5, step=0.01, label="Minimum Confidence", info="Minimum confidence threshold."
 
440
  )
441
  sensitivity_slider = gr.Slider(
442
  minimum=0.5,
@@ -452,6 +422,7 @@ def sample_sliders(opened=True):
452
 
453
  return confidence_slider, sensitivity_slider, overlap_slider
454
 
 
455
  def locale():
456
  """Creates the gradio elements for locale selection
457
  Reads the translated labels inside the checkpoints directory.
@@ -461,7 +432,9 @@ def locale():
461
  label_files = os.listdir(os.path.join(os.path.dirname(sys.argv[0]), ORIGINAL_TRANSLATED_LABELS_PATH))
462
  options = ["EN"] + [label_file.rsplit("_", 1)[-1].split(".")[0].upper() for label_file in label_files]
463
 
464
- return gr.Dropdown(options, value="EN", label="Locale", info="Locale for the translated species common names.",visible=False)
 
 
465
 
466
  def species_lists(opened=True):
467
  """Creates the gradio accordion for species selection.
@@ -489,6 +462,7 @@ def species_lists(opened=True):
489
  #
490
  return species_list_radio
491
 
 
492
  #
493
  # Design main frame for analysis of a single file
494
  #
@@ -520,158 +494,12 @@ def build_single_analysis_tab():
520
  )
521
 
522
 
523
- def build_multi_analysis_tab():
524
- with gr.Tab("Multiple files"):
525
- input_directory_state = gr.State()
526
- output_directory_predict_state = gr.State()
527
- with gr.Row():
528
- with gr.Column():
529
- select_directory_btn = gr.Button("Select directory (recursive)")
530
- directory_input = gr.Matrix(interactive=False, elem_classes="mh-200", headers=["Subpath", "Length"])
531
-
532
- def select_directory_on_empty():
533
- res = select_directory()
534
-
535
- return res if res[1] else [res[0], [["No files found"]]]
536
-
537
- select_directory_btn.click(
538
- select_directory_on_empty, outputs=[input_directory_state, directory_input], show_progress=True
539
- )
540
-
541
- with gr.Column():
542
- select_out_directory_btn = gr.Button("Select output directory.")
543
- selected_out_textbox = gr.Textbox(
544
- label="Output directory",
545
- interactive=False,
546
- placeholder="If not selected, the input directory will be used.",
547
- )
548
-
549
- def select_directory_wrapper():
550
- return (select_directory(collect_files=False),) * 2
551
-
552
- select_out_directory_btn.click(
553
- select_directory_wrapper,
554
- outputs=[output_directory_predict_state, selected_out_textbox],
555
- show_progress=False,
556
- )
557
-
558
- confidence_slider, sensitivity_slider, overlap_slider = sample_sliders()
559
- species_list_radio = species_lists(False)
560
-
561
- output_type_radio = gr.Radio(
562
- list(OUTPUT_TYPE_MAP.keys()),
563
- value="Raven selection table",
564
- label="Result type",
565
- info="Specifies output format.",
566
- )
567
-
568
- with gr.Row():
569
- batch_size_number = gr.Number(
570
- precision=1, label="Batch size", value=1, info="Number of samples to process at the same time."
571
- )
572
- threads_number = gr.Number(precision=1, label="Threads", value=4, info="Number of CPU threads.")
573
-
574
- locale_radio = locale()
575
-
576
- start_batch_analysis_btn = gr.Button("Analyze")
577
-
578
- result_grid = gr.Matrix(headers=["File", "Execution"], elem_classes="mh-200")
579
-
580
- inputs = [
581
- output_directory_predict_state,
582
- confidence_slider,
583
- sensitivity_slider,
584
- overlap_slider,
585
- species_list_radio,
586
- locale_radio,
587
- batch_size_number,
588
- threads_number,
589
- input_directory_state,
590
- output_type_radio
591
- ]
592
-
593
- start_batch_analysis_btn.click(runBatchAnalysis, inputs=inputs, outputs=result_grid)
594
-
595
- def build_segments_tab():
596
- with gr.Tab("Segments"):
597
- audio_directory_state = gr.State()
598
- result_directory_state = gr.State()
599
- output_directory_state = gr.State()
600
-
601
- def select_directory_to_state_and_tb():
602
- return (select_directory(collect_files=False),) * 2
603
-
604
- with gr.Row():
605
- select_audio_directory_btn = gr.Button("Select audio directory (recursive)")
606
- selected_audio_directory_tb = gr.Textbox(show_label=False, interactive=False)
607
- select_audio_directory_btn.click(
608
- select_directory_to_state_and_tb,
609
- outputs=[selected_audio_directory_tb, audio_directory_state],
610
- show_progress=False,
611
- )
612
-
613
- with gr.Row():
614
- select_result_directory_btn = gr.Button("Select result directory")
615
- selected_result_directory_tb = gr.Textbox(
616
- show_label=False, interactive=False, placeholder="Same as audio directory if not selected"
617
- )
618
- select_result_directory_btn.click(
619
- select_directory_to_state_and_tb,
620
- outputs=[result_directory_state, selected_result_directory_tb],
621
- show_progress=False,
622
- )
623
-
624
- with gr.Row():
625
- select_output_directory_btn = gr.Button("Select output directory")
626
- selected_output_directory_tb = gr.Textbox(
627
- show_label=False, interactive=False, placeholder="Same as audio directory if not selected"
628
- )
629
- select_output_directory_btn.click(
630
- select_directory_to_state_and_tb,
631
- outputs=[selected_output_directory_tb, output_directory_state],
632
- show_progress=False,
633
- )
634
-
635
- min_conf_slider = gr.Slider(
636
- minimum=0.1, maximum=0.99, step=0.01, label="Minimum confidence", info="Minimum confidence threshold."
637
- )
638
- num_seq_number = gr.Number(
639
- 100, label="Max number of segments", info="Maximum number of randomly extracted segments per species."
640
- )
641
- seq_length_number = gr.Number(3.0, label="Sequence length", info="Length of extracted segments in seconds.")
642
- threads_number = gr.Number(4, label="Threads", info="Number of CPU threads.")
643
-
644
- extract_segments_btn = gr.Button("Extract segments")
645
-
646
- result_grid = gr.Matrix(headers=["File", "Execution"], elem_classes="mh-200")
647
-
648
- extract_segments_btn.click(
649
- extract_segments,
650
- inputs=[
651
- audio_directory_state,
652
- result_directory_state,
653
- output_directory_state,
654
- min_conf_slider,
655
- num_seq_number,
656
- seq_length_number,
657
- threads_number,
658
- ],
659
- outputs=result_grid,
660
- )
661
-
662
  if __name__ == "__main__":
663
  freeze_support()
664
  with gr.Blocks(
665
- css=r".d-block .wrap {display: block !important;} .mh-200 {max-height: 300px; overflow-y: auto !important;} footer {display: none !important;} #single_file_audio, #single_file_audio * {max-height: 81.6px; min-height: 0;}",
666
- theme=gr.themes.Default(),
667
- analytics_enabled=False,
668
  ) as demo:
669
  build_single_analysis_tab()
670
- # build_multi_analysis_tab()
671
- # build_segments_tab()
672
  demo.launch()
673
-
674
- #url = demo.queue(api_open=False).launch(prevent_thread_lock=True, quiet=True)[1]
675
- #_WINDOW = webview.create_window("BattyBirdNET-Analyzer", url.rstrip("/") +
676
- # "?__theme=light", min_size=(1024, 768))
677
- # webview.start(private_mode=False)
 
10
  import utils
11
  import logging
12
  import librosa
13
+
14
  logging.basicConfig(filename='bat_gui.log', encoding='utf-8', level=logging.DEBUG)
15
 
16
  _WINDOW: webview.Window
17
 
 
18
  _AREA_ONE = "EU"
19
  _AREA_TWO = "Bavaria"
20
  _AREA_THREE = "USA"
 
28
  ORIGINAL_MODEL_PATH = cfg.MODEL_PATH
29
  ORIGINAL_MDATA_MODEL_PATH = cfg.MDATA_MODEL_PATH
30
  ORIGINAL_LABELS_FILE = cfg.LABELS_FILE
31
+ ORIGINAL_TRANSLATED_LABELS_PATH = cfg.TRANSLATED_BAT_LABELS_PATH # cfg.TRANSLATED_LABELS_PATH
32
+
33
 
34
  def analyzeFile_wrapper(entry):
35
+ # return (entry[0], analyze.analyzeFile(entry))
36
  return (entry[0], bat_ident.analyze_file(entry))
37
+
38
+
39
  def validate(value, msg):
40
  """Checks if the value ist not falsy.
41
  If the value is falsy, an error will be raised.
 
47
  raise gr.Error(msg)
48
 
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  def runSingleFileAnalysis(input_path,
51
  confidence,
52
  sensitivity,
 
65
  "csv",
66
  "en" if not locale else locale,
67
  1,
68
+ 1,
69
  None,
70
  progress=None,
71
  )
72
 
73
+
74
  def runAnalysis(
75
+ species_list_choice: str,
76
+ input_path: str,
77
+ output_path: str or None,
78
+ confidence: float,
79
+ sensitivity: float,
80
+ overlap: float,
81
+ output_type: str,
82
+ locale: str,
83
+ batch_size: int,
84
+ threads: int,
85
+ input_dir: str,
86
+ progress: gr.Progress or None,
87
  ):
88
  """Starts the analysis.
89
  Args:
 
112
  progress(0, desc="Preparing ...")
113
  # locale = locale.lower()
114
  # Load eBird codes, labels
115
+ # cfg.CODES = analyze.loadCodes()
116
  # cfg.LABELS = utils.readLines(ORIGINAL_LABELS_FILE)
117
  cfg.LATITUDE, cfg.LONGITUDE, cfg.WEEK = -1, -1, -1
118
  cfg.LOCATION_FILTER_THRESHOLD = 0.03
 
251
  progress((i, len(flist)), total=len(flist), unit="files")
252
  result = f.result()
253
  result_list.append(result)
254
+ return [[os.path.relpath(r[0], input_dir), r[1]] for r in result_list] if input_dir else cfg.OUTPUT_PATH + "Results.csv"
255
+
256
 
257
  def extractSegments_wrapper(entry):
258
  return (entry[0][0], segments.extractSegments(entry))
259
+
260
+
261
  def extract_segments(audio_dir, result_dir, output_dir, min_conf, num_seq, seq_length, threads, progress=gr.Progress()):
262
  validate(audio_dir, "No audio directory selected")
263
 
 
270
  if progress is not None:
271
  progress(0, desc="Searching files ...")
272
 
 
273
  # Parse audio and result folders
274
  cfg.FILE_LIST = segments.parseFolders(audio_dir, result_dir)
275
 
 
324
  files = _WINDOW.create_file_dialog(webview.OPEN_DIALOG, file_types=filetypes)
325
  return files[0] if files else None
326
 
327
+
328
  def format_seconds(secs: float):
329
  """Formats a number of seconds into a string.
330
 
 
341
 
342
  return "{:2.0f}:{:02.0f}:{:06.3f}".format(hours, minutes, secs)
343
 
344
+
345
  def select_directory(collect_files=True):
346
  """Shows a directory selection system dialog.
347
 
 
390
  ]
391
 
392
 
 
 
 
 
393
  #
394
  # VIEW - This is where the UI elements are defined
395
  #
 
405
  with gr.Accordion("Inference settings", open=opened):
406
  with gr.Row():
407
  confidence_slider = gr.Slider(
408
+ minimum=0, maximum=1, value=0.5, step=0.01, label="Minimum Confidence",
409
+ info="Minimum confidence threshold."
410
  )
411
  sensitivity_slider = gr.Slider(
412
  minimum=0.5,
 
422
 
423
  return confidence_slider, sensitivity_slider, overlap_slider
424
 
425
+
426
  def locale():
427
  """Creates the gradio elements for locale selection
428
  Reads the translated labels inside the checkpoints directory.
 
432
  label_files = os.listdir(os.path.join(os.path.dirname(sys.argv[0]), ORIGINAL_TRANSLATED_LABELS_PATH))
433
  options = ["EN"] + [label_file.rsplit("_", 1)[-1].split(".")[0].upper() for label_file in label_files]
434
 
435
+ return gr.Dropdown(options, value="EN", label="Locale", info="Locale for the translated species common names.",
436
+ visible=False)
437
+
438
 
439
  def species_lists(opened=True):
440
  """Creates the gradio accordion for species selection.
 
462
  #
463
  return species_list_radio
464
 
465
+
466
  #
467
  # Design main frame for analysis of a single file
468
  #
 
494
  )
495
 
496
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
497
  if __name__ == "__main__":
498
  freeze_support()
499
  with gr.Blocks(
500
+ css=r".d-block .wrap {display: block !important;} .mh-200 {max-height: 300px; overflow-y: auto !important;} footer {display: none !important;} #single_file_audio, #single_file_audio * {max-height: 81.6px; min-height: 0;}",
501
+ theme=gr.themes.Default(),
502
+ analytics_enabled=False,
503
  ) as demo:
504
  build_single_analysis_tab()
 
 
505
  demo.launch()
 
 
 
 
 
bat_ident.py CHANGED
@@ -331,7 +331,6 @@ def analyze_file(item):
331
  with open(cfg.OUTPUT_PATH + "Results.csv", "a", encoding="utf-8") as rfile:
332
  postString = out_string.split("\n", 1)[1]
333
  # rfile.write(fpath.join(postString.splitlines(True)))
334
- rfile.write("\n"+fpath+"\n")
335
  rfile.write(postString)
336
 
337
  except Exception as ex:
 
331
  with open(cfg.OUTPUT_PATH + "Results.csv", "a", encoding="utf-8") as rfile:
332
  postString = out_string.split("\n", 1)[1]
333
  # rfile.write(fpath.join(postString.splitlines(True)))
 
334
  rfile.write(postString)
335
 
336
  except Exception as ex: