BilalSardar commited on
Commit
9d7f3c9
1 Parent(s): a28423c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1 -456
app.py CHANGED
@@ -84,54 +84,6 @@ def runSingleFileAnalysis(
84
  )
85
 
86
 
87
- def runBatchAnalysis(
88
- output_path,
89
- confidence,
90
- sensitivity,
91
- overlap,
92
- species_list_choice,
93
- species_list_file,
94
- lat,
95
- lon,
96
- week,
97
- use_yearlong,
98
- sf_thresh,
99
- custom_classifier_file,
100
- output_type,
101
- locale,
102
- batch_size,
103
- threads,
104
- input_dir,
105
- progress=gr.Progress(),
106
- ):
107
- validate(input_dir, "Please select a directory.")
108
- batch_size = int(batch_size)
109
- threads = int(threads)
110
-
111
- if species_list_choice == _CUSTOM_SPECIES:
112
- validate(species_list_file, "Please select a species list.")
113
-
114
- return runAnalysis(
115
- None,
116
- output_path,
117
- confidence,
118
- sensitivity,
119
- overlap,
120
- species_list_choice,
121
- species_list_file,
122
- lat,
123
- lon,
124
- week,
125
- use_yearlong,
126
- sf_thresh,
127
- custom_classifier_file,
128
- output_type,
129
- "en" if not locale else locale,
130
- batch_size if batch_size and batch_size > 0 else 1,
131
- threads if threads and threads > 0 else 4,
132
- input_dir,
133
- progress,
134
- )
135
 
136
 
137
  def runAnalysis(
@@ -431,147 +383,6 @@ def select_directory(collect_files=True):
431
  return dir_name[0] if dir_name else None
432
 
433
 
434
- def start_training(
435
- data_dir,
436
- crop_mode,
437
- crop_overlap,
438
- output_dir,
439
- classifier_name,
440
- epochs,
441
- batch_size,
442
- learning_rate,
443
- hidden_units,
444
- use_mixup,
445
- upsampling_ratio,
446
- upsampling_mode,
447
- model_format,
448
- progress=gr.Progress(),
449
- ):
450
- """Starts the training of a custom classifier.
451
-
452
- Args:
453
- data_dir: Directory containing the training data.
454
- output_dir: Directory for the new classifier.
455
- classifier_name: File name of the classifier.
456
- epochs: Number of epochs to train for.
457
- batch_size: Number of samples in one batch.
458
- learning_rate: Learning rate for training.
459
- hidden_units: If > 0 the classifier contains a further hidden layer.
460
- progress: The gradio progress bar.
461
-
462
- Returns:
463
- Returns a matplotlib.pyplot figure.
464
- """
465
- validate(data_dir, "Please select your Training data.")
466
- validate(output_dir, "Please select a directory for the classifier.")
467
- validate(classifier_name, "Please enter a valid name for the classifier.")
468
-
469
- if not epochs or epochs < 0:
470
- raise gr.Error("Please enter a valid number of epochs.")
471
-
472
- if not batch_size or batch_size < 0:
473
- raise gr.Error("Please enter a valid batch size.")
474
-
475
- if not learning_rate or learning_rate < 0:
476
- raise gr.Error("Please enter a valid learning rate.")
477
-
478
- if not hidden_units or hidden_units < 0:
479
- hidden_units = 0
480
-
481
- if progress is not None:
482
- progress((0, epochs), desc="Loading data & building classifier", unit="epoch")
483
-
484
- cfg.TRAIN_DATA_PATH = data_dir
485
- cfg.SAMPLE_CROP_MODE = crop_mode
486
- cfg.SIG_OVERLAP = crop_overlap
487
- cfg.CUSTOM_CLASSIFIER = str(Path(output_dir) / classifier_name)
488
- cfg.TRAIN_EPOCHS = int(epochs)
489
- cfg.TRAIN_BATCH_SIZE = int(batch_size)
490
- cfg.TRAIN_LEARNING_RATE = learning_rate
491
- cfg.TRAIN_HIDDEN_UNITS = int(hidden_units)
492
- cfg.TRAIN_WITH_MIXUP = use_mixup
493
- cfg.UPSAMPLING_RATIO = min(max(0, upsampling_ratio), 1)
494
- cfg.UPSAMPLING_MODE = upsampling_mode
495
- cfg.TRAINED_MODEL_OUTPUT_FORMAT = model_format
496
-
497
- def progression(epoch, logs=None):
498
- if progress is not None:
499
- if epoch + 1 == epochs:
500
- progress((epoch + 1, epochs), total=epochs, unit="epoch", desc=f"Saving at {cfg.CUSTOM_CLASSIFIER}")
501
- else:
502
- progress((epoch + 1, epochs), total=epochs, unit="epoch")
503
-
504
- history = trainModel(on_epoch_end=progression)
505
-
506
- if len(history.epoch) < epochs:
507
- gr.Info("Stopped early - validation metric not improving.")
508
-
509
- auprc = history.history["val_AUPRC"]
510
-
511
- import matplotlib.pyplot as plt
512
-
513
- fig = plt.figure()
514
- plt.plot(auprc)
515
- plt.ylabel("Area under precision-recall curve")
516
- plt.xlabel("Epoch")
517
-
518
- return fig
519
-
520
-
521
- def extract_segments(audio_dir, result_dir, output_dir, min_conf, num_seq, seq_length, threads, progress=gr.Progress()):
522
- validate(audio_dir, "No audio directory selected")
523
-
524
- if not result_dir:
525
- result_dir = audio_dir
526
-
527
- if not output_dir:
528
- output_dir = audio_dir
529
-
530
- if progress is not None:
531
- progress(0, desc="Searching files ...")
532
-
533
- # Parse audio and result folders
534
- cfg.FILE_LIST = segments.parseFolders(audio_dir, result_dir)
535
-
536
- # Set output folder
537
- cfg.OUTPUT_PATH = output_dir
538
-
539
- # Set number of threads
540
- cfg.CPU_THREADS = int(threads)
541
-
542
- # Set confidence threshold
543
- cfg.MIN_CONFIDENCE = max(0.01, min(0.99, min_conf))
544
-
545
- # Parse file list and make list of segments
546
- cfg.FILE_LIST = segments.parseFiles(cfg.FILE_LIST, max(1, int(num_seq)))
547
-
548
- # Add config items to each file list entry.
549
- # We have to do this for Windows which does not
550
- # support fork() and thus each process has to
551
- # have its own config. USE LINUX!
552
- flist = [(entry, max(cfg.SIG_LENGTH, float(seq_length)), cfg.getConfig()) for entry in cfg.FILE_LIST]
553
-
554
- result_list = []
555
-
556
- # Extract segments
557
- if cfg.CPU_THREADS < 2:
558
- for i, entry in enumerate(flist):
559
- result = extractSegments_wrapper(entry)
560
- result_list.append(result)
561
-
562
- if progress is not None:
563
- progress((i, len(flist)), total=len(flist), unit="files")
564
- else:
565
- with concurrent.futures.ProcessPoolExecutor(max_workers=cfg.CPU_THREADS) as executor:
566
- futures = (executor.submit(extractSegments_wrapper, arg) for arg in flist)
567
- for i, f in enumerate(concurrent.futures.as_completed(futures), start=1):
568
- if progress is not None:
569
- progress((i, len(flist)), total=len(flist), unit="files")
570
- result = f.result()
571
-
572
- result_list.append(result)
573
-
574
- return [[os.path.relpath(r[0], audio_dir), r[1]] for r in result_list]
575
 
576
 
577
  def sample_sliders(opened=True):
@@ -761,269 +572,6 @@ if __name__ == "__main__":
761
 
762
  single_file_analyze.click(runSingleFileAnalysis, inputs=inputs, outputs=output_dataframe)
763
 
764
- def build_multi_analysis_tab():
765
- with gr.Tab("Multiple files"):
766
- input_directory_state = gr.State()
767
- output_directory_predict_state = gr.State()
768
- with gr.Row():
769
- with gr.Column():
770
- select_directory_btn = gr.Button("Select directory (recursive)")
771
- directory_input = gr.Matrix(interactive=False, elem_classes="mh-200", headers=["Subpath", "Length"])
772
-
773
- def select_directory_on_empty():
774
- res = select_directory()
775
-
776
- return res if res[1] else [res[0], [["No files found"]]]
777
-
778
- select_directory_btn.click(
779
- select_directory_on_empty, outputs=[input_directory_state, directory_input], show_progress=True
780
- )
781
-
782
- with gr.Column():
783
- select_out_directory_btn = gr.Button("Select output directory.")
784
- selected_out_textbox = gr.Textbox(
785
- label="Output directory",
786
- interactive=False,
787
- placeholder="If not selected, the input directory will be used.",
788
- )
789
-
790
- def select_directory_wrapper():
791
- return (select_directory(collect_files=False),) * 2
792
-
793
- select_out_directory_btn.click(
794
- select_directory_wrapper,
795
- outputs=[output_directory_predict_state, selected_out_textbox],
796
- show_progress=False,
797
- )
798
-
799
- confidence_slider, sensitivity_slider, overlap_slider = sample_sliders()
800
-
801
- (
802
- species_list_radio,
803
- species_file_input,
804
- lat_number,
805
- lon_number,
806
- week_number,
807
- sf_thresh_number,
808
- yearlong_checkbox,
809
- selected_classifier_state,
810
- ) = species_lists()
811
-
812
- output_type_radio = gr.Radio(
813
- list(OUTPUT_TYPE_MAP.keys()),
814
- value="Raven selection table",
815
- label="Result type",
816
- info="Specifies output format.",
817
- )
818
-
819
- with gr.Row():
820
- batch_size_number = gr.Number(
821
- precision=1, label="Batch size", value=1, info="Number of samples to process at the same time."
822
- )
823
- threads_number = gr.Number(precision=1, label="Threads", value=4, info="Number of CPU threads.")
824
-
825
- locale_radio = locale()
826
-
827
- start_batch_analysis_btn = gr.Button("Analyze")
828
-
829
- result_grid = gr.Matrix(headers=["File", "Execution"], elem_classes="mh-200")
830
-
831
- inputs = [
832
- output_directory_predict_state,
833
- confidence_slider,
834
- sensitivity_slider,
835
- overlap_slider,
836
- species_list_radio,
837
- species_file_input,
838
- lat_number,
839
- lon_number,
840
- week_number,
841
- yearlong_checkbox,
842
- sf_thresh_number,
843
- selected_classifier_state,
844
- output_type_radio,
845
- locale_radio,
846
- batch_size_number,
847
- threads_number,
848
- input_directory_state,
849
- ]
850
-
851
- start_batch_analysis_btn.click(runBatchAnalysis, inputs=inputs, outputs=result_grid)
852
-
853
- def build_train_tab():
854
- with gr.Tab("Train"):
855
- input_directory_state = gr.State()
856
- output_directory_state = gr.State()
857
-
858
- with gr.Row():
859
- with gr.Column():
860
- select_directory_btn = gr.Button("Training data")
861
- directory_input = gr.List(headers=["Classes"], interactive=False, elem_classes="mh-200")
862
- select_directory_btn.click(
863
- select_subdirectories, outputs=[input_directory_state, directory_input], show_progress=False
864
- )
865
-
866
- with gr.Column():
867
- select_directory_btn = gr.Button("Classifier output")
868
-
869
- with gr.Column():
870
- classifier_name = gr.Textbox(
871
- "CustomClassifier",
872
- visible=False,
873
- info="The name of the new classifier.",
874
- )
875
- output_format = gr.Radio(
876
- ["tflite", "raven", "both"],
877
- value="tflite",
878
- label="Model output format",
879
- info="Format for the trained classifier.",
880
- visible=False,
881
- )
882
-
883
- def select_directory_and_update_tb():
884
- dir_name = _WINDOW.create_file_dialog(webview.FOLDER_DIALOG)
885
-
886
- if dir_name:
887
- return (
888
- dir_name[0],
889
- gr.Textbox.update(label=dir_name[0] + "\\", visible=True),
890
- gr.Radio.update(visible=True, interactive=True),
891
- )
892
-
893
- return None, None
894
-
895
- select_directory_btn.click(
896
- select_directory_and_update_tb,
897
- outputs=[output_directory_state, classifier_name, output_format],
898
- show_progress=False,
899
- )
900
-
901
- with gr.Row():
902
- epoch_number = gr.Number(100, label="Epochs", info="Number of training epochs.")
903
- batch_size_number = gr.Number(32, label="Batch size", info="Batch size.")
904
- learning_rate_number = gr.Number(0.01, label="Learning rate", info="Learning rate.")
905
-
906
- with gr.Row():
907
- crop_mode = gr.Radio(
908
- ["center", "first", "segments"],
909
- value="center",
910
- label="Crop mode",
911
- info="Crop mode for training data.",
912
- )
913
- crop_overlap = gr.Number(0.0, label="Crop overlap", info="Overlap of training data segments", visible=False)
914
-
915
- def on_crop_select(new_crop_mode):
916
- return gr.Number.update(visible=new_crop_mode == "segments", interactive=new_crop_mode == "segments")
917
-
918
- crop_mode.change(on_crop_select, inputs=crop_mode, outputs=crop_overlap)
919
-
920
- with gr.Row():
921
- upsampling_mode = gr.Radio(
922
- ["repeat", "mean", "smote"],
923
- value="repeat",
924
- label="Upsampling mode",
925
- info="Balance data through upsampling.",
926
- )
927
- upsampling_ratio = gr.Slider(
928
- 0.0, 1.0, 0.0, step=0.01, label="Upsampling ratio", info="Balance train data and upsample minority classes."
929
- )
930
-
931
- with gr.Row():
932
- hidden_units_number = gr.Number(
933
- 0, label="Hidden units", info="Number of hidden units. If set to >0, a two-layer classifier is used."
934
- )
935
- use_mixup = gr.Checkbox(False, label="Use mixup", info="Whether to use mixup for training.", show_label=True)
936
-
937
- train_history_plot = gr.Plot()
938
-
939
- start_training_button = gr.Button("Start training")
940
-
941
- start_training_button.click(
942
- start_training,
943
- inputs=[
944
- input_directory_state,
945
- crop_mode,
946
- crop_overlap,
947
- output_directory_state,
948
- classifier_name,
949
- epoch_number,
950
- batch_size_number,
951
- learning_rate_number,
952
- hidden_units_number,
953
- use_mixup,
954
- upsampling_ratio,
955
- upsampling_mode,
956
- output_format,
957
- ],
958
- outputs=[train_history_plot],
959
- )
960
-
961
- def build_segments_tab():
962
- with gr.Tab("Segments"):
963
- audio_directory_state = gr.State()
964
- result_directory_state = gr.State()
965
- output_directory_state = gr.State()
966
-
967
- def select_directory_to_state_and_tb():
968
- return (select_directory(collect_files=False),) * 2
969
-
970
- with gr.Row():
971
- select_audio_directory_btn = gr.Button("Select audio directory (recursive)")
972
- selected_audio_directory_tb = gr.Textbox(show_label=False, interactive=False)
973
- select_audio_directory_btn.click(
974
- select_directory_to_state_and_tb,
975
- outputs=[selected_audio_directory_tb, audio_directory_state],
976
- show_progress=False,
977
- )
978
-
979
- with gr.Row():
980
- select_result_directory_btn = gr.Button("Select result directory")
981
- selected_result_directory_tb = gr.Textbox(
982
- show_label=False, interactive=False, placeholder="Same as audio directory if not selected"
983
- )
984
- select_result_directory_btn.click(
985
- select_directory_to_state_and_tb,
986
- outputs=[result_directory_state, selected_result_directory_tb],
987
- show_progress=False,
988
- )
989
-
990
- with gr.Row():
991
- select_output_directory_btn = gr.Button("Select output directory")
992
- selected_output_directory_tb = gr.Textbox(
993
- show_label=False, interactive=False, placeholder="Same as audio directory if not selected"
994
- )
995
- select_output_directory_btn.click(
996
- select_directory_to_state_and_tb,
997
- outputs=[selected_output_directory_tb, output_directory_state],
998
- show_progress=False,
999
- )
1000
-
1001
- min_conf_slider = gr.Slider(
1002
- minimum=0.1, maximum=0.99, step=0.01, label="Minimum confidence", info="Minimum confidence threshold."
1003
- )
1004
- num_seq_number = gr.Number(
1005
- 100, label="Max number of segments", info="Maximum number of randomly extracted segments per species."
1006
- )
1007
- seq_length_number = gr.Number(3.0, label="Sequence length", info="Length of extracted segments in seconds.")
1008
- threads_number = gr.Number(4, label="Threads", info="Number of CPU threads.")
1009
-
1010
- extract_segments_btn = gr.Button("Extract segments")
1011
-
1012
- result_grid = gr.Matrix(headers=["File", "Execution"], elem_classes="mh-200")
1013
-
1014
- extract_segments_btn.click(
1015
- extract_segments,
1016
- inputs=[
1017
- audio_directory_state,
1018
- result_directory_state,
1019
- output_directory_state,
1020
- min_conf_slider,
1021
- num_seq_number,
1022
- seq_length_number,
1023
- threads_number,
1024
- ],
1025
- outputs=result_grid,
1026
- )
1027
 
1028
  with gr.Blocks(
1029
  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;}",
@@ -1031,11 +579,8 @@ if __name__ == "__main__":
1031
  analytics_enabled=False,
1032
  ) as demo:
1033
  build_single_analysis_tab()
1034
- #build_multi_analysis_tab()
1035
- #build_train_tab()
1036
- # build_segments_tab()
1037
 
1038
- demo.launch()
1039
  #url = demo.queue(api_open=False).launch(prevent_thread_lock=True, quiet=True)[1]
1040
  #_WINDOW = webview.create_window("BirdNET-Analyzer", url.rstrip("/") + "?__theme=light", min_size=(1024, 768))
1041
 
 
84
  )
85
 
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
 
89
  def runAnalysis(
 
383
  return dir_name[0] if dir_name else None
384
 
385
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
 
387
 
388
  def sample_sliders(opened=True):
 
572
 
573
  single_file_analyze.click(runSingleFileAnalysis, inputs=inputs, outputs=output_dataframe)
574
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
 
576
  with gr.Blocks(
577
  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;}",
 
579
  analytics_enabled=False,
580
  ) as demo:
581
  build_single_analysis_tab()
 
 
 
582
 
583
+ demo.launch(show_api=True)
584
  #url = demo.queue(api_open=False).launch(prevent_thread_lock=True, quiet=True)[1]
585
  #_WINDOW = webview.create_window("BirdNET-Analyzer", url.rstrip("/") + "?__theme=light", min_size=(1024, 768))
586