vancauwe commited on
Commit
ec819d9
·
1 Parent(s): 8f0e835

refactor: homogenize config loading

Browse files
app/.env.dist ADDED
@@ -0,0 +1 @@
 
 
1
+ PATH_ASSETS="YOUR_PATH_HERE"
app/behavior_checkbox.py CHANGED
@@ -3,7 +3,7 @@ from utils_checkbox import create_checkbox
3
  from utils_visible import set_visible
4
 
5
  def retrieve_behavior_options_description():
6
- dropdown_config = get_custom_config_dropdowns("/assets/config/config_checkbox_behavior.json")
7
  options = list(dropdown_config.keys())
8
  options = [option.title() for option in options]
9
  descriptions =[]
 
3
  from utils_visible import set_visible
4
 
5
  def retrieve_behavior_options_description():
6
+ dropdown_config = get_custom_config_dropdowns("config_checkbox_behavior.json")
7
  options = list(dropdown_config.keys())
8
  options = [option.title() for option in options]
9
  descriptions =[]
app/circumstances.py CHANGED
@@ -1,10 +1,16 @@
1
  import gradio as gr
2
  import os
3
  from utils_visible import set_visible
 
 
 
 
 
 
4
 
5
- PATH = os.getcwd()
6
  CAUSE_COL_WIDTH = "50px"
7
 
 
8
  def show_causes(choice):
9
  visible = set_visible(choice)
10
  button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2 = create_causes(visible)
@@ -15,30 +21,29 @@ def create_causes(visible):
15
  dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2 = create_causes_dropdown(visible)
16
  return button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2
17
 
18
-
19
  def create_causes_buttons(visible):
20
  with gr.Row() as image_row:
21
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
22
  button_collision = gr.Button("Collision with a means of transport",
23
  visible=visible,
24
- icon=PATH + '/assets/logos/van.png',
25
  elem_id="buttons-conditions")
26
 
27
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
28
  button_deliberate_destruction = gr.Button("Destruction / Deliberatly removed",
29
- icon=PATH + '/assets/logos/destruction.png',
30
  visible=visible,
31
  elem_id="buttons-conditions")
32
 
33
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
34
  button_indirect_destruction = gr.Button("Indirect destruction",
35
- icon=PATH + '/assets/logos/indirect.png',
36
  visible=visible,
37
  elem_id="buttons-conditions")
38
 
39
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
40
  button_natural_cause = gr.Button("Natural cause",
41
- icon=PATH + '/assets/logos/natural.png',
42
  visible=visible,
43
  elem_id="buttons-conditions")
44
  return button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause
 
1
  import gradio as gr
2
  import os
3
  from utils_visible import set_visible
4
+ from dotenv import load_dotenv
5
+ import os
6
+ load_dotenv()
7
+ PATH = os.getcwd() + "/"
8
+ PATH_ASSETS = os.getenv('PATH_ASSETS')
9
+ LOGO_PATH = PATH + PATH_ASSETS + "logos"
10
 
 
11
  CAUSE_COL_WIDTH = "50px"
12
 
13
+
14
  def show_causes(choice):
15
  visible = set_visible(choice)
16
  button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2 = create_causes(visible)
 
21
  dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2 = create_causes_dropdown(visible)
22
  return button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2
23
 
 
24
  def create_causes_buttons(visible):
25
  with gr.Row() as image_row:
26
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
27
  button_collision = gr.Button("Collision with a means of transport",
28
  visible=visible,
29
+ icon=LOGO_PATH + '/van.png',
30
  elem_id="buttons-conditions")
31
 
32
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
33
  button_deliberate_destruction = gr.Button("Destruction / Deliberatly removed",
34
+ icon=LOGO_PATH + '/destruction.png',
35
  visible=visible,
36
  elem_id="buttons-conditions")
37
 
38
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
39
  button_indirect_destruction = gr.Button("Indirect destruction",
40
+ icon=LOGO_PATH + '/indirect.png',
41
  visible=visible,
42
  elem_id="buttons-conditions")
43
 
44
  with gr.Column(scale=1, min_width=CAUSE_COL_WIDTH):
45
  button_natural_cause = gr.Button("Natural cause",
46
+ icon=LOGO_PATH + '/natural.png',
47
  visible=visible,
48
  elem_id="buttons-conditions")
49
  return button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause
app/circumstances_dropdowns.py CHANGED
@@ -15,7 +15,7 @@ def reinitialise_level2():
15
  return dropdown_level2, openfield_level2, dropdown_extra_level2
16
 
17
  def create_dropdown_level1(label):
18
- dropdown_config = get_custom_config_dropdowns("/assets/config/config_dropdown_conditions.json")
19
  options = retrieve_config_options(label, dropdown_config)
20
  dropdown = gr.Dropdown(choices=options, label=label, interactive=True, visible=True)
21
  dropdown_level2, openfield_level2, dropdown_extra_level2 = reinitialise_level2()
@@ -45,7 +45,7 @@ def get_options(value):
45
  open_field = None
46
  extras = None
47
  extras_label = None
48
- dropdown_config = get_custom_config_dropdowns("/assets/config/config_dropdown_conditions.json")
49
  for _, sub_dict in dropdown_config.items():
50
  nested_dict = sub_dict.get(value)
51
  if nested_dict is not None:
 
15
  return dropdown_level2, openfield_level2, dropdown_extra_level2
16
 
17
  def create_dropdown_level1(label):
18
+ dropdown_config = get_custom_config_dropdowns("config_dropdown_conditions.json")
19
  options = retrieve_config_options(label, dropdown_config)
20
  dropdown = gr.Dropdown(choices=options, label=label, interactive=True, visible=True)
21
  dropdown_level2, openfield_level2, dropdown_extra_level2 = reinitialise_level2()
 
45
  open_field = None
46
  extras = None
47
  extras_label = None
48
+ dropdown_config = get_custom_config_dropdowns("config_dropdown_conditions.json")
49
  for _, sub_dict in dropdown_config.items():
50
  nested_dict = sub_dict.get(value)
51
  if nested_dict is not None:
app/followup_events.py CHANGED
@@ -2,7 +2,7 @@ import gradio as gr
2
  from utils_config import get_custom_config_dropdowns
3
 
4
  def create_followup_section():
5
- followup_config = get_custom_config_dropdowns("/assets/config/config_followup.json")
6
  followup_config = followup_config["Event follow-up"]
7
  gr.Markdown("Please tell us what you did with the animal.", label="description")
8
  with gr.Row():
 
2
  from utils_config import get_custom_config_dropdowns
3
 
4
  def create_followup_section():
5
+ followup_config = get_custom_config_dropdowns("config_followup.json")
6
  followup_config = followup_config["Event follow-up"]
7
  gr.Markdown("Please tell us what you did with the animal.", label="description")
8
  with gr.Row():
app/main_multianimal.py CHANGED
@@ -1,8 +1,16 @@
1
  import gradio as gr
2
  from gradio_modal import Modal
3
  import numpy as np
4
- from maps import get_location
5
  from utils_json import *
 
 
 
 
 
 
 
 
6
 
7
 
8
  def save_input(input, df):
@@ -24,7 +32,6 @@ with gr.Blocks() as demo:
24
  )
25
  show_markdown = gr.Markdown("This is a markdown")
26
  with Modal(visible=False) as modal:
27
- input = gr.Textbox(label="Input 1", interactive=True)
28
  # ---------------------------------------------------------
29
  # Intro Text
30
  with gr.Row():
@@ -56,11 +63,121 @@ with gr.Blocks() as demo:
56
  submit_location.click(get_location, inputs=[location], outputs=[identified_location])
57
 
58
  # ---------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  button = gr.Button("Click me")
61
- button.click(save_input,
62
- inputs=[input, df],
63
- outputs=[df])
64
  button.click(lambda: Modal(visible=False), None, modal)
65
  show_btn.click(lambda: Modal(visible=True), None, modal)
66
  show_btn.click(create_json)
 
1
  import gradio as gr
2
  from gradio_modal import Modal
3
  import numpy as np
4
+
5
  from utils_json import *
6
+ from functools import partial
7
+ from dead import show_section_dead
8
+ from wounded import show_section_wounded
9
+ from circumstances import show_causes
10
+ from circumstances_dropdowns import *
11
+ from physical_select_animal import show_physical, find_bounding_box
12
+ from behavior_checkbox import show_behavior
13
+ from maps import get_location
14
 
15
 
16
  def save_input(input, df):
 
32
  )
33
  show_markdown = gr.Markdown("This is a markdown")
34
  with Modal(visible=False) as modal:
 
35
  # ---------------------------------------------------------
36
  # Intro Text
37
  with gr.Row():
 
63
  submit_location.click(get_location, inputs=[location], outputs=[identified_location])
64
 
65
  # ---------------------------------------------------------
66
+ # ---------------------------------------------------------
67
+ # Dead and Wounded Buttons
68
+ gr.Markdown("## The State of the Animal", label="Title")
69
+ gr.Markdown("Please tell us if the animal was wounded or dead.", label="description")
70
+ with gr.Row() as block_form:
71
+ with gr.Column(scale=1):
72
+ butt_wounded = gr.Button("Wounded", elem_id="wounded")
73
+ with gr.Column(scale=1):
74
+ butt_dead = gr.Button("Dead", elem_id="dead")
75
+
76
+ # ---------------------------------------------------------
77
+ # Initiate sections
78
+ section_dead, \
79
+ button_collision_dead, button_deliberate_destruction_dead, button_indirect_destruction_dead, button_natural_cause_dead, \
80
+ dropdown_dead, dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead \
81
+ = show_section_dead(False)
82
+ section_wounded, radio_cause_wounded, radio_behavior_wounded, radio_physical_wounded, \
83
+ button_collision_wounded, button_deliberate_destruction_wounded, button_indirect_destruction_wounded, button_natural_cause_wounded, \
84
+ dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded, \
85
+ behavior_checkbox, behavior_text, \
86
+ physical_boxes_wounded, \
87
+ checkbox_beak, text_beak, checkbox_body, text_body, checkbox_feathers, text_feathers, checkbox_head, text_head, checkbox_legs, text_legs \
88
+ = show_section_wounded(False)
89
+
90
+ # ---------------------------------------------------------
91
+ # ---------------------------------------------------------
92
+ # ---------------------------------------------------------
93
+ # Dead Button Logic
94
+ partial_show_section_dead = partial(show_section_dead, True)
95
+ partial_hide_section_wounded = partial(show_section_wounded, False)
96
+ butt_dead.click(partial_show_section_dead,
97
+ inputs=None,
98
+ outputs=[section_dead,
99
+ button_collision_dead, button_deliberate_destruction_dead, button_indirect_destruction_dead, button_natural_cause_dead,
100
+ dropdown_dead, dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead
101
+ ])
102
+ butt_dead.click(partial_hide_section_wounded,
103
+ inputs=None,
104
+ outputs=[section_wounded,
105
+ radio_cause_wounded, radio_behavior_wounded, radio_physical_wounded,
106
+ button_collision_wounded, button_deliberate_destruction_wounded, button_indirect_destruction_wounded, button_natural_cause_wounded,
107
+ dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded,
108
+ behavior_checkbox, behavior_text,
109
+ physical_boxes_wounded,
110
+ checkbox_beak, text_beak, checkbox_body, text_body, checkbox_feathers, text_feathers, checkbox_head, text_head, checkbox_legs, text_legs
111
+ ])
112
+ # ---------------------------------------------------------
113
+ # Wounded Button Logic
114
+ partial_show_section_wounded = partial(show_section_wounded, True)
115
+ partial_hide_section_dead = partial(show_section_dead, False)
116
+
117
+ butt_wounded.click(partial_show_section_wounded,
118
+ inputs=None,
119
+ outputs=[section_wounded,
120
+ radio_cause_wounded, radio_behavior_wounded, radio_physical_wounded,
121
+ button_collision_wounded, button_deliberate_destruction_wounded, button_indirect_destruction_wounded, button_natural_cause_wounded,
122
+ dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded,
123
+ behavior_checkbox, behavior_text,
124
+ physical_boxes_wounded,
125
+ checkbox_beak, text_beak, checkbox_body, text_body, checkbox_feathers, text_feathers, checkbox_head, text_head, checkbox_legs, text_legs
126
+ ])
127
+ butt_wounded.click(partial_hide_section_dead, inputs=None, outputs=[section_dead,
128
+ button_collision_dead, button_deliberate_destruction_dead, button_indirect_destruction_dead, button_natural_cause_dead,
129
+ dropdown_dead, dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead
130
+ ])
131
+ # ---------------------------------------------------------
132
+ # Dropdowns Dead
133
+ button_collision_dead.click(dropdown_collision,
134
+ outputs=[dropdown_dead, dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead])
135
+ button_deliberate_destruction_dead.click(dropdown_deliberate_destruction, outputs=[dropdown_dead, dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead])
136
+ button_indirect_destruction_dead.click(dropdown_indirect_destruction, outputs=[dropdown_dead, dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead])
137
+ button_natural_cause_dead.click(dropdown_natural_cause, outputs=[dropdown_dead, dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead])
138
+
139
+ dropdown_dead.select(on_select, None, [dropdown_level2_dead, openfield_level2_dead, dropdown_extra_level2_dead])
140
+
141
+ # ---------------------------------------------------------
142
+ # Radio Cause Wounded
143
+ radio_cause_wounded.change(fn=show_causes,
144
+ inputs=[radio_cause_wounded],
145
+ outputs=[button_collision_wounded, button_deliberate_destruction_wounded, button_indirect_destruction_wounded, button_natural_cause_wounded,
146
+ dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded]
147
+ )
148
 
149
+ # Dropdowns Cause Wounded
150
+ button_collision_wounded.click(dropdown_collision,
151
+ outputs=[dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded])
152
+ button_deliberate_destruction_wounded.click(dropdown_deliberate_destruction, outputs=[dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded])
153
+ button_indirect_destruction_wounded.click(dropdown_indirect_destruction, outputs=[dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded])
154
+ button_natural_cause_wounded.click(dropdown_natural_cause, outputs=[dropdown_wounded, dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded])
155
+
156
+ dropdown_wounded.select(on_select, None, [dropdown_level2_wounded, openfield_level2_wounded, dropdown_extra_level2_wounded])
157
+
158
+ # ---------------------------------------------------------
159
+ # Radio Behavior Wounded
160
+ radio_behavior_wounded.change(fn=show_behavior,
161
+ inputs=[radio_behavior_wounded, gr.Text("wounded", visible=False)],
162
+ outputs=[behavior_checkbox, behavior_text])
163
+
164
+ # ---------------------------------------------------------
165
+ # Radio Physical Wounded
166
+ radio_physical_wounded.change(fn=show_physical,
167
+ inputs=[radio_physical_wounded, gr.Text("wounded", visible=False)],
168
+ outputs=[physical_boxes_wounded])
169
+
170
+ # Checkbox Physical Wounded
171
+ physical_boxes_wounded.select(find_bounding_box,
172
+ inputs=[physical_boxes_wounded, gr.Textbox(value="wounded", visible=False)],
173
+ outputs=[checkbox_beak, text_beak, checkbox_body, text_body, checkbox_feathers, text_feathers, checkbox_head, text_head, checkbox_legs, text_legs
174
+ ])
175
+
176
+
177
  button = gr.Button("Click me")
178
+ # button.click(save_input,
179
+ # inputs=[df],
180
+ # outputs=[df])
181
  button.click(lambda: Modal(visible=False), None, modal)
182
  show_btn.click(lambda: Modal(visible=True), None, modal)
183
  show_btn.click(create_json)
app/physical_boxes_map.py CHANGED
@@ -2,6 +2,11 @@ from PIL import Image, ImageDraw, ImageFont
2
 
3
  from physical_boxes_define import gdf
4
 
 
 
 
 
 
5
  # Function to draw the bounding boxes on the image
6
  def draw_bounding_boxes(image_path, gdf):
7
  image = Image.open(image_path+'bird.png').convert("RGB")
@@ -10,7 +15,7 @@ def draw_bounding_boxes(image_path, gdf):
10
 
11
  # Optional: Load a font (requires a TTF file)
12
  # try:
13
- font = ImageFont.truetype("assets/fonts/LiberationSans-Regular.ttf",
14
  20)
15
  # except IOError:
16
  # print("default")
@@ -25,4 +30,4 @@ def draw_bounding_boxes(image_path, gdf):
25
  image.save(image_path+'bird_boxed.png', "PNG")
26
 
27
  if __name__ == "__main__":
28
- draw_bounding_boxes('assets/images/', gdf)
 
2
 
3
  from physical_boxes_define import gdf
4
 
5
+ from dotenv import load_dotenv
6
+ import os
7
+ load_dotenv()
8
+ PATH_ASSETS = os.getenv('PATH_ASSETS')
9
+
10
  # Function to draw the bounding boxes on the image
11
  def draw_bounding_boxes(image_path, gdf):
12
  image = Image.open(image_path+'bird.png').convert("RGB")
 
15
 
16
  # Optional: Load a font (requires a TTF file)
17
  # try:
18
+ font = ImageFont.truetype(PATH_ASSETS + "fonts/LiberationSans-Regular.ttf",
19
  20)
20
  # except IOError:
21
  # print("default")
 
30
  image.save(image_path+'bird_boxed.png', "PNG")
31
 
32
  if __name__ == "__main__":
33
+ draw_bounding_boxes(PATH_ASSETS + 'images/', gdf)
app/physical_checkbox.py CHANGED
@@ -3,7 +3,7 @@ from utils_config import get_custom_config_dropdowns
3
  from utils_checkbox import create_checkbox
4
  #---------------------------------------------------------
5
  def get_body_parts():
6
- dropdown_config = get_custom_config_dropdowns("/assets/config/config_checkbox_physical.json")
7
  return list(dropdown_config.keys())
8
 
9
  def retrieve_config_options(label, dropdown_config):
@@ -12,7 +12,7 @@ def retrieve_config_options(label, dropdown_config):
12
  return options
13
 
14
  def get_options_description(value):
15
- dropdown_config = get_custom_config_dropdowns("/assets/config/config_checkbox_physical.json")
16
  # get options
17
  options_common = retrieve_config_options("Common", dropdown_config)
18
  options_for_value = retrieve_config_options(value, dropdown_config)
 
3
  from utils_checkbox import create_checkbox
4
  #---------------------------------------------------------
5
  def get_body_parts():
6
+ dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
7
  return list(dropdown_config.keys())
8
 
9
  def retrieve_config_options(label, dropdown_config):
 
12
  return options
13
 
14
  def get_options_description(value):
15
+ dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
16
  # get options
17
  options_common = retrieve_config_options("Common", dropdown_config)
18
  options_for_value = retrieve_config_options(value, dropdown_config)
app/physical_select_animal.py CHANGED
@@ -5,7 +5,10 @@ from shapely.geometry import Point
5
  from physical_checkbox import *
6
  from physical_boxes_define import gdf
7
  from utils_visible import set_visible
8
-
 
 
 
9
 
10
  # Function to find the matching bounding box for a given point and return the image with boxes
11
  def find_bounding_box(evt: gr.SelectData, img, section: str):
@@ -25,7 +28,8 @@ def find_bounding_box(evt: gr.SelectData, img, section: str):
25
  # Gradio app
26
  def create_bird_anatomy(visible, section: str):
27
  # Draw bounding boxes on the image
28
- img_with_boxes = gr.Image(value='assets/images/bird_boxed.png',
 
29
  show_label=False,
30
  height="600px",
31
  elem_id=section,
 
5
  from physical_checkbox import *
6
  from physical_boxes_define import gdf
7
  from utils_visible import set_visible
8
+ from dotenv import load_dotenv
9
+ import os
10
+ load_dotenv()
11
+ PATH_ASSETS = os.getenv('PATH_ASSETS')
12
 
13
  # Function to find the matching bounding box for a given point and return the image with boxes
14
  def find_bounding_box(evt: gr.SelectData, img, section: str):
 
28
  # Gradio app
29
  def create_bird_anatomy(visible, section: str):
30
  # Draw bounding boxes on the image
31
+ print
32
+ img_with_boxes = gr.Image(value=PATH_ASSETS+'images/bird_boxed.png',
33
  show_label=False,
34
  height="600px",
35
  elem_id=section,
app/utils_config.py CHANGED
@@ -1,5 +1,11 @@
1
  import json
2
  import os
 
 
 
 
 
 
3
 
4
  def load_config(file_path):
5
  with open(file_path) as f:
@@ -7,8 +13,7 @@ def load_config(file_path):
7
  return config
8
 
9
  def get_custom_config_dropdowns(config_path):
10
- path = os.getcwd()
11
- dropdown_config_path = path + config_path
12
  dropdown_config = load_config(dropdown_config_path)
13
  return dropdown_config
14
 
 
1
  import json
2
  import os
3
+ from dotenv import load_dotenv
4
+ import os
5
+ load_dotenv()
6
+ PATH = os.getcwd() + "/"
7
+ PATH_ASSETS = os.getenv('PATH_ASSETS')
8
+ PATH_CONFIG = PATH + PATH_ASSETS + "config/"
9
 
10
  def load_config(file_path):
11
  with open(file_path) as f:
 
13
  return config
14
 
15
  def get_custom_config_dropdowns(config_path):
16
+ dropdown_config_path = PATH_CONFIG + config_path
 
17
  dropdown_config = load_config(dropdown_config_path)
18
  return dropdown_config
19
 
requirements.txt CHANGED
@@ -2,4 +2,5 @@ gradio
2
  gradio_modal
3
  geopy
4
  geopandas
5
- pillow
 
 
2
  gradio_modal
3
  geopy
4
  geopandas
5
+ pillow
6
+ dotenv