feat: behavior circumstance processing with pydantic
Browse files- app/assets/json_tmp/tmp_wounded_dead.json +1 -1
- app/behavior/behavior_checkbox.py +3 -2
- app/behavior/class_behavior.py +2 -1
- app/circumstances/circumstances.py +1 -1
- app/follow_up/followup_events.py +2 -2
- app/geolocalisation/maps.py +1 -1
- app/physical/class_physical.py +3 -2
- app/physical/physical_checkbox.py +3 -2
- app/physical/physical_select_animal.py +1 -0
- app/validation_submission/create_json.py +1 -1
- app/validation_submission/validation.py +74 -7
app/assets/json_tmp/tmp_wounded_dead.json
CHANGED
@@ -1 +1 @@
|
|
1 |
-
{}
|
|
|
1 |
+
{"circumstance_radio": true, "circumstance": "collision with a means of transport", "cirumstance_type": {"type": "boat", "option_dropdown_label": "NA", "open_field_label": "NA", "extra_label": "NA"}, "behavior_radio": "Yes", "behaviors_observed": ["Crash, Falling From The Sky", "Diarrhea"], "physical_radio": "Yes", "physical_type_head": "head", "physical_anomaly_type_head": ["Injury", "Parasites"], "physical_type_legs": "legs", "physical_anomaly_type_legs": ["Missing Limb"], "fe_fe_collection": "no", "fe_fe_recipient": "local museum", "fe_fe_name_recipient": "reserve", "fe_fe_radio": "unknown", "fe_fe_answer": "police call", "fe_fe_collection_ref": "ref"}
|
app/behavior/behavior_checkbox.py
CHANGED
@@ -2,10 +2,10 @@ import gradio as gr
|
|
2 |
from utils.utils_config import get_custom_config_dropdowns
|
3 |
from utils.utils_checkbox import create_checkbox
|
4 |
from utils.utils_visible import set_visible
|
5 |
-
from validation_submission.add_json import
|
6 |
|
7 |
def on_select_behavior(behavior_checkbox):
|
8 |
-
|
9 |
|
10 |
def retrieve_behavior_options_description():
|
11 |
dropdown_config = get_custom_config_dropdowns("config_checkbox_behavior.json")
|
@@ -25,4 +25,5 @@ def create_behavior_checkbox(section: str, visible):
|
|
25 |
def show_behavior(choice, section: str):
|
26 |
visible = set_visible(choice)
|
27 |
checkbox, text = create_behavior_checkbox(section, visible)
|
|
|
28 |
return checkbox, text
|
|
|
2 |
from utils.utils_config import get_custom_config_dropdowns
|
3 |
from utils.utils_checkbox import create_checkbox
|
4 |
from utils.utils_visible import set_visible
|
5 |
+
from validation_submission.add_json import add_data_tmp
|
6 |
|
7 |
def on_select_behavior(behavior_checkbox):
|
8 |
+
add_data_tmp("wounded_dead", "behaviors_type", behavior_checkbox)
|
9 |
|
10 |
def retrieve_behavior_options_description():
|
11 |
dropdown_config = get_custom_config_dropdowns("config_checkbox_behavior.json")
|
|
|
25 |
def show_behavior(choice, section: str):
|
26 |
visible = set_visible(choice)
|
27 |
checkbox, text = create_behavior_checkbox(section, visible)
|
28 |
+
add_data_tmp("wounded_dead", "behaviors_radio", choice)
|
29 |
return checkbox, text
|
app/behavior/class_behavior.py
CHANGED
@@ -63,4 +63,5 @@ BehaviorType = Union[
|
|
63 |
|
64 |
# Main class that logs multiple behaviors
|
65 |
class Behaviors(BaseModel):
|
66 |
-
|
|
|
|
63 |
|
64 |
# Main class that logs multiple behaviors
|
65 |
class Behaviors(BaseModel):
|
66 |
+
behaviors_radio: str # e.g., "Yes"
|
67 |
+
behaviors_type: List[BehaviorType] = Field(..., discriminator='type')
|
app/circumstances/circumstances.py
CHANGED
@@ -17,7 +17,7 @@ def show_circumstances(choice):
|
|
17 |
visible = set_visible(choice)
|
18 |
add_data_tmp("wounded_dead",
|
19 |
"circumstance_radio",
|
20 |
-
|
21 |
button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2 = create_circumstances(visible)
|
22 |
return button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2
|
23 |
|
|
|
17 |
visible = set_visible(choice)
|
18 |
add_data_tmp("wounded_dead",
|
19 |
"circumstance_radio",
|
20 |
+
choice)
|
21 |
button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2 = create_circumstances(visible)
|
22 |
return button_collision, button_deliberate_destruction, button_indirect_destruction, button_natural_cause, dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2
|
23 |
|
app/follow_up/followup_events.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import gradio as gr
|
2 |
from utils.utils_config import get_custom_config_dropdowns
|
3 |
-
from validation_submission.add_json import
|
4 |
|
5 |
def create_followup_dropdowns(visible, elem_id):
|
6 |
followup_config = get_custom_config_dropdowns("config_followup.json")
|
@@ -40,7 +40,7 @@ def create_fe_answer_dropdown(followup_config, visible, elem_id):
|
|
40 |
return fe_answer_dropdown
|
41 |
|
42 |
def save_fe(value, key):
|
43 |
-
|
44 |
|
45 |
|
46 |
|
|
|
1 |
import gradio as gr
|
2 |
from utils.utils_config import get_custom_config_dropdowns
|
3 |
+
from validation_submission.add_json import add_data_tmp
|
4 |
|
5 |
def create_followup_dropdowns(visible, elem_id):
|
6 |
followup_config = get_custom_config_dropdowns("config_followup.json")
|
|
|
40 |
return fe_answer_dropdown
|
41 |
|
42 |
def save_fe(value, key):
|
43 |
+
add_data_tmp("wounded_dead", key.lower(), value.lower())
|
44 |
|
45 |
|
46 |
|
app/geolocalisation/maps.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
from geopy.geocoders import Nominatim
|
2 |
import gradio as gr
|
3 |
-
from
|
4 |
from geolocalisation.class_geolocalisation import Geolocalisation
|
5 |
|
6 |
|
|
|
1 |
from geopy.geocoders import Nominatim
|
2 |
import gradio as gr
|
3 |
+
from validation_submission.add_json import add_data_to_individual
|
4 |
from geolocalisation.class_geolocalisation import Geolocalisation
|
5 |
|
6 |
|
app/physical/class_physical.py
CHANGED
@@ -74,5 +74,6 @@ AnomalyType = Union[
|
|
74 |
]
|
75 |
|
76 |
# Main PhysicalAnomaly class that logs anomalies across different body parts
|
77 |
-
class
|
78 |
-
|
|
|
|
74 |
]
|
75 |
|
76 |
# Main PhysicalAnomaly class that logs anomalies across different body parts
|
77 |
+
class PhysicalAnomalies(BaseModel):
|
78 |
+
physical_radio: str
|
79 |
+
physical_anomalies_type: List[AnomalyType] = Field(..., discriminator='type')
|
app/physical/physical_checkbox.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import gradio as gr
|
2 |
from utils.utils_config import get_custom_config_dropdowns
|
3 |
from utils.utils_checkbox import create_checkbox
|
4 |
-
from validation_submission.add_json import
|
5 |
#---------------------------------------------------------
|
6 |
def get_body_parts():
|
7 |
dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
|
@@ -72,7 +72,8 @@ def process_body_parts(section, matched_box):
|
|
72 |
#---------------------------------------------------------
|
73 |
|
74 |
def on_select_body_part(body_part_checkbox, body_part):
|
75 |
-
|
|
|
76 |
|
77 |
#---------------------------------------------------------
|
78 |
|
|
|
1 |
import gradio as gr
|
2 |
from utils.utils_config import get_custom_config_dropdowns
|
3 |
from utils.utils_checkbox import create_checkbox
|
4 |
+
from validation_submission.add_json import add_data_tmp
|
5 |
#---------------------------------------------------------
|
6 |
def get_body_parts():
|
7 |
dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
|
|
|
72 |
#---------------------------------------------------------
|
73 |
|
74 |
def on_select_body_part(body_part_checkbox, body_part):
|
75 |
+
add_data_tmp("wounded_dead", "physical_type_"+body_part, body_part)
|
76 |
+
add_data_tmp("wounded_dead", "physical_anomaly_type_"+body_part, body_part_checkbox)
|
77 |
|
78 |
#---------------------------------------------------------
|
79 |
|
app/physical/physical_select_animal.py
CHANGED
@@ -40,6 +40,7 @@ def create_bird_anatomy(visible, section: str):
|
|
40 |
def show_physical(choice, section: str):
|
41 |
visible = set_visible(choice)
|
42 |
physical_boxes = create_bird_anatomy(visible, section)
|
|
|
43 |
return physical_boxes
|
44 |
|
45 |
|
|
|
40 |
def show_physical(choice, section: str):
|
41 |
visible = set_visible(choice)
|
42 |
physical_boxes = create_bird_anatomy(visible, section)
|
43 |
+
add_data_tmp("wounded_dead", "physical_radio", choice)
|
44 |
return physical_boxes
|
45 |
|
46 |
|
app/validation_submission/create_json.py
CHANGED
@@ -10,7 +10,7 @@ def create_json_all_individuals(all_individuals={}):
|
|
10 |
with open("data/all_individuals.json", "w") as outfile:
|
11 |
outfile.write(all_individuals)
|
12 |
|
13 |
-
def create_tmp(tmp_name, tmp={}):
|
14 |
tmp = json.dumps(tmp)
|
15 |
with open(f"app/assets/json_tmp/tmp_{tmp_name}.json", "w") as outfile:
|
16 |
outfile.write(tmp)
|
|
|
10 |
with open("data/all_individuals.json", "w") as outfile:
|
11 |
outfile.write(all_individuals)
|
12 |
|
13 |
+
def create_tmp(tmp_name="wounded_dead", tmp={}):
|
14 |
tmp = json.dumps(tmp)
|
15 |
with open(f"app/assets/json_tmp/tmp_{tmp_name}.json", "w") as outfile:
|
16 |
outfile.write(tmp)
|
app/validation_submission/validation.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
from validation_submission.get_json import get_json_tmp, get_json_one_individual
|
2 |
from classes import Report
|
3 |
-
from circumstances.class_circumstance import
|
|
|
|
|
4 |
|
5 |
def get_fields(data_dict, keyword):
|
6 |
extract = {}
|
@@ -11,8 +13,8 @@ def get_fields(data_dict, keyword):
|
|
11 |
|
12 |
def validate_individual():
|
13 |
data = get_json_tmp("wounded_dead")
|
14 |
-
validate_circumstance(data)
|
15 |
-
validate_behavior(data)
|
16 |
validate_physical(data)
|
17 |
validate_follow_up(data)
|
18 |
validate_individual()
|
@@ -22,16 +24,81 @@ def validate_individual():
|
|
22 |
def validate_circumstance(data):
|
23 |
circumstance_raw = get_fields(data, "circumstance")
|
24 |
circumstance_formatted = process_circumstance(circumstance_raw)
|
25 |
-
if not
|
26 |
print("Validation failed for the circumstance.")
|
27 |
-
|
|
|
|
|
28 |
def process_circumstance(data):
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
def validate_behavior(data):
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
34 |
def validate_physical(data):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
pass
|
36 |
|
37 |
def validate_follow_up(data):
|
|
|
1 |
from validation_submission.get_json import get_json_tmp, get_json_one_individual
|
2 |
from classes import Report
|
3 |
+
from circumstances.class_circumstance import Circumstances
|
4 |
+
from behavior.class_behavior import Behaviors
|
5 |
+
from physical.class_physical import PhysicalAnomalies
|
6 |
|
7 |
def get_fields(data_dict, keyword):
|
8 |
extract = {}
|
|
|
13 |
|
14 |
def validate_individual():
|
15 |
data = get_json_tmp("wounded_dead")
|
16 |
+
circumstance = validate_circumstance(data)
|
17 |
+
behaviors = validate_behavior(data)
|
18 |
validate_physical(data)
|
19 |
validate_follow_up(data)
|
20 |
validate_individual()
|
|
|
24 |
def validate_circumstance(data):
|
25 |
circumstance_raw = get_fields(data, "circumstance")
|
26 |
circumstance_formatted = process_circumstance(circumstance_raw)
|
27 |
+
if not Circumstances(**circumstance_formatted).validate():
|
28 |
print("Validation failed for the circumstance.")
|
29 |
+
else:
|
30 |
+
return Circumstances(**circumstance_formatted)
|
31 |
+
|
32 |
def process_circumstance(data):
|
33 |
+
fields_to_check = ["option_dropdown", "open_field", "extra"]
|
34 |
+
for field in fields_to_check:
|
35 |
+
if data["circumstance_type"][field+"_label"] == "NA":
|
36 |
+
data["circumstance_type"].pop([field+"_label"])
|
37 |
+
else :
|
38 |
+
key = data[f"circumstance_{field}"]
|
39 |
+
val = data["circumstance_type"][field+"_label"]
|
40 |
+
data["circumstance_type"][key] = val
|
41 |
+
data["circumstance_type"].pop([field+"_label"])
|
42 |
+
# {"circumstance_radio": true,
|
43 |
+
# "circumstance": "destruction / deliberatly removed",
|
44 |
+
# "cirumstance_type": {"type": "removal or direct capture",
|
45 |
+
# "option_dropdown_label": "method",
|
46 |
+
# "open_field_label": "NA",
|
47 |
+
# "extra_label": "NA"},
|
48 |
+
# "circumstance_option_dropdown": "Traffic/Trade"}
|
49 |
+
return data
|
50 |
|
51 |
def validate_behavior(data):
|
52 |
+
behaviors_raw = get_fields(data, "behaviours")
|
53 |
+
behaviors_formatted = process_behaviors(behaviors_raw)
|
54 |
+
if not Behaviors(**behaviors_formatted).validate():
|
55 |
+
print("Validation failed for the behaviours.")
|
56 |
+
else:
|
57 |
+
return Behaviors(**behaviors_formatted)
|
58 |
+
|
59 |
+
def process_behaviors(data):
|
60 |
+
# INPUT :
|
61 |
+
#"behaviors_radio": true,
|
62 |
+
# "behaviors_type": ["Crash, Falling From The Sky", "Neurological"]
|
63 |
+
#OUTPUT:
|
64 |
+
# "behaviors_radio": "Yes",
|
65 |
+
# "behaviors_type": [
|
66 |
+
# {
|
67 |
+
# "type": "abnormal breathing",
|
68 |
+
# "description": "Problems breathing, breathing sounds"
|
69 |
+
# }
|
70 |
+
behaviors =[]
|
71 |
+
for type in data["behaviors_type"]:
|
72 |
+
new_behavior = {}
|
73 |
+
new_behavior["type"] = type
|
74 |
+
behaviors.append(new_behavior)
|
75 |
+
data["behaviors_type"] = behaviors
|
76 |
+
return data
|
77 |
|
78 |
def validate_physical(data):
|
79 |
+
physical_raw = get_fields(data, "physical")
|
80 |
+
physical_formatted = process_physical(physical_raw)
|
81 |
+
if not PhysicalAnomalies(**physical_formatted).validate():
|
82 |
+
print("Validation failed for the physical anomalies.")
|
83 |
+
else:
|
84 |
+
return PhysicalAnomalies(**physical_formatted)
|
85 |
+
|
86 |
+
def process_physical(data):
|
87 |
+
# INPUT
|
88 |
+
# "physical_type_feathers": "feathers",
|
89 |
+
# "physical_anomaly_type_feathers": ["Blood", "Swelling"]}
|
90 |
+
# OUTPUT
|
91 |
+
# "physical_radio": "Yes",
|
92 |
+
# "physical_anomalies_type": [
|
93 |
+
# {
|
94 |
+
# "type": "beak",
|
95 |
+
# "anomaly_type": "deformation"
|
96 |
+
# },
|
97 |
+
# {
|
98 |
+
# "type": "body",
|
99 |
+
# "anomaly_type": "fluffed up"
|
100 |
+
# },
|
101 |
+
|
102 |
pass
|
103 |
|
104 |
def validate_follow_up(data):
|