caviri commited on
Commit
f1a6252
·
1 Parent(s): 869adb6

bug: Expanded Pydantic class to make it compatible with simple and advance mode

Browse files
README.md CHANGED
@@ -13,7 +13,7 @@ short_description: Digiwild
13
  ## Docker
14
 
15
  ``` bash
16
- docker build -t ordes/digiwild .
17
  ```
18
 
19
 
@@ -29,18 +29,17 @@ python3 main.py
29
  ### How to develop on docker
30
 
31
  ``` bash
32
- docker run -it -p 7860:7860 -v $(pwd):/home/user/digiwild/ ordes/digiwild
33
  ```
34
 
35
  ## TODO
36
 
37
  - [x] Change `wounded` to `wounded / sick`
38
  - [x] Info formatting
39
- - [ ] Use in memory object instead of files to avoid writting / reading problems.
40
  - [ ] Connection to a database? Maybe an open MongoDB
41
  - [x] GPS Compatibility
42
  - [x] New fields suggested: Number individuals, Species, Comments
43
- - [ ] Save new fields values into the JSON. Perform validation too.
44
  - [ ] Add info and placeholder information to the different components.
45
 
46
  ## Needs
@@ -50,5 +49,3 @@ docker run -it -p 7860:7860 -v $(pwd):/home/user/digiwild/ ordes/digiwild
50
  - GPS location
51
  - Comments
52
  - Symptomps selection (Dropdown)
53
-
54
- ## PR Updates
 
13
  ## Docker
14
 
15
  ``` bash
16
+ docker build -t ordes/digiwild .
17
  ```
18
 
19
 
 
29
  ### How to develop on docker
30
 
31
  ``` bash
32
+ docker run -it -p 7860:7860 -v $(pwd):/home/user/digiwild/ --entrypoint bash ordes/digiwild
33
  ```
34
 
35
  ## TODO
36
 
37
  - [x] Change `wounded` to `wounded / sick`
38
  - [x] Info formatting
39
+ - [x] Use in memory object instead of files to avoid writting / reading problems.
40
  - [ ] Connection to a database? Maybe an open MongoDB
41
  - [x] GPS Compatibility
42
  - [x] New fields suggested: Number individuals, Species, Comments
 
43
  - [ ] Add info and placeholder information to the different components.
44
 
45
  ## Needs
 
49
  - GPS location
50
  - Comments
51
  - Symptomps selection (Dropdown)
 
 
app/behavior/behavior_checkbox.py CHANGED
@@ -4,33 +4,41 @@ from utils.utils_checkbox import create_checkbox
4
  from utils.utils_visible import set_visible
5
  from validation_submission.utils_individual import add_data_to_individual
6
 
7
- def on_select_behavior(behavior_checkbox, individual):
 
8
  behavior_checkbox = [behavior.lower() for behavior in behavior_checkbox]
9
  individual = add_data_to_individual("behaviors_type", behavior_checkbox, individual)
10
  return individual
11
 
12
- def retrieve_behavior_options_description(mode:str):
13
- print(mode)
14
- if mode =="simple":
15
- dropdown_config = get_custom_config_dropdowns("config_checkbox_behavior_simple.json")
16
- elif mode=="advanced":
 
 
 
17
  dropdown_config = get_custom_config_dropdowns("config_checkbox_behavior.json")
18
  options = list(dropdown_config.keys())
19
  options = [option.title() for option in options]
20
- descriptions =[]
21
- for _,subdict in dropdown_config.items():
22
  descriptions.append(subdict["Description"])
23
  return options, descriptions
24
 
 
25
  def create_behavior_checkbox(section: str, mode: str, visible):
26
  options, descriptions = retrieve_behavior_options_description(mode)
27
  label_checkbox = "Behavior changes observed"
28
- checkbox, text = create_checkbox("", section, label_checkbox, visible, options, descriptions)
 
 
29
  return checkbox, text
30
 
31
- def show_behavior(choice, section: str, mode: str, individual):
32
- print(mode)
 
33
  visible = set_visible(choice)
34
  checkbox, text = create_behavior_checkbox(section, mode, visible)
35
  individual = add_data_to_individual("behaviors_radio", choice, individual)
36
- return checkbox, text, individual
 
4
  from utils.utils_visible import set_visible
5
  from validation_submission.utils_individual import add_data_to_individual
6
 
7
+
8
+ def on_select_behavior(behavior_checkbox, individual):
9
  behavior_checkbox = [behavior.lower() for behavior in behavior_checkbox]
10
  individual = add_data_to_individual("behaviors_type", behavior_checkbox, individual)
11
  return individual
12
 
13
+
14
+ def retrieve_behavior_options_description(mode: str):
15
+ # print(f"Retrieve Behavior Option Description: {mode}")
16
+ if mode == "simple":
17
+ dropdown_config = get_custom_config_dropdowns(
18
+ "config_checkbox_behavior_simple.json"
19
+ )
20
+ elif mode == "advanced":
21
  dropdown_config = get_custom_config_dropdowns("config_checkbox_behavior.json")
22
  options = list(dropdown_config.keys())
23
  options = [option.title() for option in options]
24
+ descriptions = []
25
+ for _, subdict in dropdown_config.items():
26
  descriptions.append(subdict["Description"])
27
  return options, descriptions
28
 
29
+
30
  def create_behavior_checkbox(section: str, mode: str, visible):
31
  options, descriptions = retrieve_behavior_options_description(mode)
32
  label_checkbox = "Behavior changes observed"
33
+ checkbox, text = create_checkbox(
34
+ "", section, label_checkbox, visible, options, descriptions
35
+ )
36
  return checkbox, text
37
 
38
+
39
+ def show_behavior(choice, section: str, mode: str, individual):
40
+ # print(f"Show Behavior: {mode}")
41
  visible = set_visible(choice)
42
  checkbox, text = create_behavior_checkbox(section, mode, visible)
43
  individual = add_data_to_individual("behaviors_radio", choice, individual)
44
+ return checkbox, text, individual
app/behavior/class_behavior_simple.py CHANGED
@@ -1,34 +1,42 @@
1
  from pydantic import BaseModel, Field
2
  from typing import Literal, List, Union, Optional
3
 
 
4
  class BehaviorSimple(BaseModel):
5
  type: str
6
  description: Optional[str] = None # Making the description field optional
7
 
 
8
  # --- Specific BehaviorSimple classes ---
9
  class GeneralWeakness(BehaviorSimple):
10
- type: Literal['general weakness']
11
- description: Optional[Literal["Abnormal breathing (dyspnoea), sudden crash, apathy, lethargy, unable to fly but responsive"]] = None
 
 
 
 
 
12
 
13
  class Vomiting(BehaviorSimple):
14
- type: Literal['vomiting']
15
  description: Optional[Literal["Throwing up undigested food, regurgitating"]] = None
16
 
 
17
  class AtypicalBehavior(BehaviorSimple):
18
- type: Literal['atypical behavior']
19
- description: Optional[Literal["Circling, incoordination, tremors, convulsions"]] = None
 
 
 
20
 
21
  class NoChanges(BehaviorSimple):
22
- type: Literal['no changes']
23
  description: Optional[Literal["Animal is acting normally"]] = None
24
 
 
25
  # Union of all possible behaviors
26
- BehaviorSimpleType = Union[
27
- GeneralWeakness,
28
- Vomiting,
29
- AtypicalBehavior,
30
- NoChanges
31
- ]
32
 
33
  # Main class that logs multiple behaviors
34
  class BehaviorsSimple(BaseModel):
 
1
  from pydantic import BaseModel, Field
2
  from typing import Literal, List, Union, Optional
3
 
4
+
5
  class BehaviorSimple(BaseModel):
6
  type: str
7
  description: Optional[str] = None # Making the description field optional
8
 
9
+
10
  # --- Specific BehaviorSimple classes ---
11
  class GeneralWeakness(BehaviorSimple):
12
+ type: Literal["general weakness"]
13
+ description: Optional[
14
+ Literal[
15
+ "Abnormal breathing (dyspnoea), sudden crash, apathy, lethargy, unable to fly but responsive"
16
+ ]
17
+ ] = None
18
+
19
 
20
  class Vomiting(BehaviorSimple):
21
+ type: Literal["vomiting"]
22
  description: Optional[Literal["Throwing up undigested food, regurgitating"]] = None
23
 
24
+
25
  class AtypicalBehavior(BehaviorSimple):
26
+ type: Literal["atypical behavior"]
27
+ description: Optional[
28
+ Literal["Circling, incoordination, tremors, convulsions"]
29
+ ] = None
30
+
31
 
32
  class NoChanges(BehaviorSimple):
33
+ type: Literal["no changes"]
34
  description: Optional[Literal["Animal is acting normally"]] = None
35
 
36
+
37
  # Union of all possible behaviors
38
+ BehaviorSimpleType = Union[GeneralWeakness, Vomiting, AtypicalBehavior, NoChanges]
39
+
 
 
 
 
40
 
41
  # Main class that logs multiple behaviors
42
  class BehaviorsSimple(BaseModel):
app/circumstances/circumstances_dropdowns.py CHANGED
@@ -2,114 +2,141 @@ import gradio as gr
2
  from utils.utils_config import get_custom_config_dropdowns
3
  from validation_submission.utils_individual import add_data_to_individual
4
 
5
- #--------------------------------------------------------- LEVEL 1 DROPDOWNS
 
6
  def retrieve_config_options(label, dropdown_config):
7
  options = list(dropdown_config[label].keys())
8
  options = [option.title() for option in options]
9
  return options
10
 
11
- def reinitialise_level2():
 
12
  dropdown_level2 = gr.Dropdown(choices=[], visible=False)
13
  openfield_level2 = gr.Textbox(visible=False)
14
  dropdown_extra_level2 = gr.Dropdown(choices=[], visible=False)
15
  return dropdown_level2, openfield_level2, dropdown_extra_level2
16
 
17
- def create_dropdown_level1(label, individual):
 
18
  dropdown_config = get_custom_config_dropdowns("config_dropdown_circumstances.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()
22
- return dropdown, dropdown_level2, openfield_level2, dropdown_extra_level2, individual
23
-
 
 
 
 
 
 
 
24
  def dropdown_collision(individual):
25
  label = "Collision with a means of transport"
26
  individual = add_data_to_individual("circumstance", label.lower(), individual)
27
  return create_dropdown_level1(label, individual)
28
 
 
29
  def dropdown_deliberate_destruction(individual):
30
  label = "Destruction / Deliberatly removed"
31
  individual = add_data_to_individual("circumstance", label.lower(), individual)
32
- return create_dropdown_level1(label, individual)
 
33
 
34
- def dropdown_indirect_destruction(individual):
35
  label = "Indirect destruction"
36
  individual = add_data_to_individual("circumstance", label.lower(), individual)
37
- return create_dropdown_level1(label, individual)
38
 
39
- def dropdown_natural_cause(individual):
 
40
  label = "Natural cause"
41
- individual = add_data_to_individual( "circumstance", label.lower(), individual)
42
- return create_dropdown_level1(label, individual)
43
 
44
 
45
- #--------------------------------------------------------- LEVEL 2 DROPDOWNS
46
  def get_options(value):
47
- value = value.lower()
48
- options_label = None
49
- options_dropdown= None
50
- open_field = None
51
- extras = None
52
- extras_label = None
53
- dropdown_config = get_custom_config_dropdowns("config_dropdown_circumstances.json")
54
- for _, sub_dict in dropdown_config.items():
55
- nested_dict = sub_dict.get(value)
56
- if nested_dict is not None:
57
- if "Options" in nested_dict.keys():
58
- options_dict = nested_dict["Options"]
59
- options_label = list(options_dict.keys())[0]
60
- options_dropdown = list(options_dict.values())[0]
61
- options_dropdown = [option.title() for option in options_dropdown]
62
- if "Open" in nested_dict.keys():
63
- open_field = nested_dict["Open"]
64
- open_field = open_field.title()
65
- if "Extra" in nested_dict.keys():
66
- for key, val in nested_dict["Extra"].items():
67
- extras_label = key
68
- extras = val
69
- extras = [extra.title() for extra in extras]
70
- return options_label, options_dropdown, open_field, extras, extras_label
71
-
72
-
73
  def on_select(evt: gr.SelectData, individual): # SelectData is a subclass of EventData
74
- options_label, options_dropdown, open_field, extras, extras_label = get_options(evt.value)
 
 
75
  individual = add_data_to_individual(
76
- "circumstance_type",
77
- {"type": (evt.value).lower(),
78
- "option_dropdown_label" : options_label.lower() if options_label is not None else 'NA',
79
- "open_field_label" : open_field.lower() if open_field is not None else 'NA',
80
- "extra_label": extras_label.lower() if extras_label is not None else 'NA'
81
- }, individual)
 
 
 
 
 
82
  if options_dropdown is not None:
83
- dropdown_level2 = gr.Dropdown(choices=options_dropdown, label=evt.value, interactive=True, visible=True)
84
- else:
 
 
85
  dropdown_level2 = gr.Dropdown(choices=[], visible=False)
86
 
87
  if open_field is not None:
88
  openfield_level2 = gr.Textbox(label=open_field, interactive=True, visible=True)
89
- else:
90
  openfield_level2 = gr.Textbox(visible=False)
91
 
92
- if extras is not None:
93
- dropdown_extra_level2 = gr.Dropdown(choices=extras, label=extras_label, interactive=True, visible=True)
94
- else:
 
 
95
  dropdown_extra_level2 = gr.Dropdown(choices=[], visible=False)
96
  return dropdown_level2, openfield_level2, dropdown_extra_level2, individual
97
 
98
- def on_select_dropdown_level2(evt: gr.SelectData, individual):
99
- individual = add_data_to_individual(
100
- "circumstance_option_dropdown",
101
- evt.value.lower(), individual)
 
102
  return individual
103
 
104
- def on_select_dropdown_extra_level2(evt: gr.SelectData, individual):
105
- individual = add_data_to_individual(
106
- "circumstance_extra",
107
- evt.value.lower(), individual)
 
108
  return individual
109
-
110
- def on_change_openfield_level2(openfield_level2_dead, individual):
111
- print("Saving open field")
 
112
  individual = add_data_to_individual(
113
- "circumstance_open_field",
114
- str(openfield_level2_dead).lower(), individual)
115
- return individual
 
2
  from utils.utils_config import get_custom_config_dropdowns
3
  from validation_submission.utils_individual import add_data_to_individual
4
 
5
+
6
+ # --------------------------------------------------------- LEVEL 1 DROPDOWNS
7
  def retrieve_config_options(label, dropdown_config):
8
  options = list(dropdown_config[label].keys())
9
  options = [option.title() for option in options]
10
  return options
11
 
12
+
13
+ def reinitialise_level2():
14
  dropdown_level2 = gr.Dropdown(choices=[], visible=False)
15
  openfield_level2 = gr.Textbox(visible=False)
16
  dropdown_extra_level2 = gr.Dropdown(choices=[], visible=False)
17
  return dropdown_level2, openfield_level2, dropdown_extra_level2
18
 
19
+
20
+ def create_dropdown_level1(label, individual):
21
  dropdown_config = get_custom_config_dropdowns("config_dropdown_circumstances.json")
22
  options = retrieve_config_options(label, dropdown_config)
23
  dropdown = gr.Dropdown(choices=options, label=label, interactive=True, visible=True)
24
  dropdown_level2, openfield_level2, dropdown_extra_level2 = reinitialise_level2()
25
+ return (
26
+ dropdown,
27
+ dropdown_level2,
28
+ openfield_level2,
29
+ dropdown_extra_level2,
30
+ individual,
31
+ )
32
+
33
+
34
  def dropdown_collision(individual):
35
  label = "Collision with a means of transport"
36
  individual = add_data_to_individual("circumstance", label.lower(), individual)
37
  return create_dropdown_level1(label, individual)
38
 
39
+
40
  def dropdown_deliberate_destruction(individual):
41
  label = "Destruction / Deliberatly removed"
42
  individual = add_data_to_individual("circumstance", label.lower(), individual)
43
+ return create_dropdown_level1(label, individual)
44
+
45
 
46
+ def dropdown_indirect_destruction(individual):
47
  label = "Indirect destruction"
48
  individual = add_data_to_individual("circumstance", label.lower(), individual)
49
+ return create_dropdown_level1(label, individual)
50
 
51
+
52
+ def dropdown_natural_cause(individual):
53
  label = "Natural cause"
54
+ individual = add_data_to_individual("circumstance", label.lower(), individual)
55
+ return create_dropdown_level1(label, individual)
56
 
57
 
58
+ # --------------------------------------------------------- LEVEL 2 DROPDOWNS
59
  def get_options(value):
60
+ value = value.lower()
61
+ options_label = None
62
+ options_dropdown = None
63
+ open_field = None
64
+ extras = None
65
+ extras_label = None
66
+ dropdown_config = get_custom_config_dropdowns("config_dropdown_circumstances.json")
67
+ for _, sub_dict in dropdown_config.items():
68
+ nested_dict = sub_dict.get(value)
69
+ if nested_dict is not None:
70
+ if "Options" in nested_dict.keys():
71
+ options_dict = nested_dict["Options"]
72
+ options_label = list(options_dict.keys())[0]
73
+ options_dropdown = list(options_dict.values())[0]
74
+ options_dropdown = [option.title() for option in options_dropdown]
75
+ if "Open" in nested_dict.keys():
76
+ open_field = nested_dict["Open"]
77
+ open_field = open_field.title()
78
+ if "Extra" in nested_dict.keys():
79
+ for key, val in nested_dict["Extra"].items():
80
+ extras_label = key
81
+ extras = val
82
+ extras = [extra.title() for extra in extras]
83
+ return options_label, options_dropdown, open_field, extras, extras_label
84
+
85
+
86
  def on_select(evt: gr.SelectData, individual): # SelectData is a subclass of EventData
87
+ options_label, options_dropdown, open_field, extras, extras_label = get_options(
88
+ evt.value
89
+ )
90
  individual = add_data_to_individual(
91
+ "circumstance_type",
92
+ {
93
+ "type": (evt.value).lower(),
94
+ "option_dropdown_label": options_label.lower()
95
+ if options_label is not None
96
+ else "NA",
97
+ "open_field_label": open_field.lower() if open_field is not None else "NA",
98
+ "extra_label": extras_label.lower() if extras_label is not None else "NA",
99
+ },
100
+ individual,
101
+ )
102
  if options_dropdown is not None:
103
+ dropdown_level2 = gr.Dropdown(
104
+ choices=options_dropdown, label=evt.value, interactive=True, visible=True
105
+ )
106
+ else:
107
  dropdown_level2 = gr.Dropdown(choices=[], visible=False)
108
 
109
  if open_field is not None:
110
  openfield_level2 = gr.Textbox(label=open_field, interactive=True, visible=True)
111
+ else:
112
  openfield_level2 = gr.Textbox(visible=False)
113
 
114
+ if extras is not None:
115
+ dropdown_extra_level2 = gr.Dropdown(
116
+ choices=extras, label=extras_label, interactive=True, visible=True
117
+ )
118
+ else:
119
  dropdown_extra_level2 = gr.Dropdown(choices=[], visible=False)
120
  return dropdown_level2, openfield_level2, dropdown_extra_level2, individual
121
 
122
+
123
+ def on_select_dropdown_level2(evt: gr.SelectData, individual):
124
+ individual = add_data_to_individual(
125
+ "circumstance_option_dropdown", evt.value.lower(), individual
126
+ )
127
  return individual
128
 
129
+
130
+ def on_select_dropdown_extra_level2(evt: gr.SelectData, individual):
131
+ individual = add_data_to_individual(
132
+ "circumstance_extra", evt.value.lower(), individual
133
+ )
134
  return individual
135
+
136
+
137
+ def on_change_openfield_level2(openfield_level2_dead, individual):
138
+ # print("Saving open field")
139
  individual = add_data_to_individual(
140
+ "circumstance_open_field", str(openfield_level2_dead).lower(), individual
141
+ )
142
+ return individual
app/classes.py CHANGED
@@ -1,5 +1,5 @@
1
  from pydantic import BaseModel, Field
2
- from typing import Optional
3
  import numpy as np
4
  from PIL import Image
5
  import io
@@ -7,24 +7,30 @@ import base64
7
  import uuid
8
 
9
  from behavior.class_behavior import Behaviors
 
10
  from circumstances.class_circumstance import Circumstances
11
  from physical.class_physical import PhysicalAnomalies
 
12
  from follow_up.class_follow_up import FollowUpEvents
13
  from geolocalisation.class_geolocalisation import Geolocalisation
14
 
 
15
  class Wounded(BaseModel):
16
  circumstances: Circumstances
17
- behaviors: Behaviors
18
- physical_anomalies: PhysicalAnomalies
19
  follow_up_events: FollowUpEvents
20
 
 
21
  class Dead(BaseModel):
22
  circumstances: Circumstances
23
- physical_anomalies: PhysicalAnomalies
24
  follow_up_events: FollowUpEvents
25
 
 
26
  class ImageBase64(BaseModel):
27
- image: str
 
28
  @classmethod
29
  def to_base64(cls, pixel_data: list):
30
  img_array = np.array(pixel_data, dtype=np.uint8)
@@ -33,15 +39,16 @@ class ImageBase64(BaseModel):
33
  buffer = io.BytesIO()
34
  img.save(buffer, format="PNG")
35
  buffer.seek(0)
36
- base64_str = base64.b64encode(buffer.read()).decode('utf-8')
37
  return cls(image=base64_str)
38
-
 
39
  class Report(BaseModel):
40
  identifier: str
41
  image: ImageBase64
42
  image_md5: str
43
  geolocalisation: Geolocalisation
44
  wounded_state: str
45
- wounded: Optional[Wounded] = None
46
  dead_state: str
47
- dead: Optional[Dead] = None
 
1
  from pydantic import BaseModel, Field
2
+ from typing import Optional, Union
3
  import numpy as np
4
  from PIL import Image
5
  import io
 
7
  import uuid
8
 
9
  from behavior.class_behavior import Behaviors
10
+ from behavior.class_behavior_simple import BehaviorsSimple
11
  from circumstances.class_circumstance import Circumstances
12
  from physical.class_physical import PhysicalAnomalies
13
+ from physical.class_physical_simple import PhysicalAnomaliesSimple
14
  from follow_up.class_follow_up import FollowUpEvents
15
  from geolocalisation.class_geolocalisation import Geolocalisation
16
 
17
+
18
  class Wounded(BaseModel):
19
  circumstances: Circumstances
20
+ behaviors: Union[Behaviors, BehaviorsSimple]
21
+ physical_anomalies: Union[PhysicalAnomalies, PhysicalAnomaliesSimple]
22
  follow_up_events: FollowUpEvents
23
 
24
+
25
  class Dead(BaseModel):
26
  circumstances: Circumstances
27
+ physical_anomalies: Union[PhysicalAnomalies, PhysicalAnomaliesSimple]
28
  follow_up_events: FollowUpEvents
29
 
30
+
31
  class ImageBase64(BaseModel):
32
+ image: str
33
+
34
  @classmethod
35
  def to_base64(cls, pixel_data: list):
36
  img_array = np.array(pixel_data, dtype=np.uint8)
 
39
  buffer = io.BytesIO()
40
  img.save(buffer, format="PNG")
41
  buffer.seek(0)
42
+ base64_str = base64.b64encode(buffer.read()).decode("utf-8")
43
  return cls(image=base64_str)
44
+
45
+
46
  class Report(BaseModel):
47
  identifier: str
48
  image: ImageBase64
49
  image_md5: str
50
  geolocalisation: Geolocalisation
51
  wounded_state: str
52
+ wounded: Optional[Wounded] = None
53
  dead_state: str
54
+ dead: Optional[Dead] = None
app/physical/physical_checkbox.py CHANGED
@@ -1,92 +1,168 @@
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.utils_individual import add_data_to_individual
5
- #---------------------------------------------------------
 
 
6
  def get_body_parts(mode):
7
- if mode=="simple":
8
- dropdown_config = get_custom_config_dropdowns("config_checkbox_physical_simple.json")
 
 
9
  elif mode == "advanced":
10
  dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
11
  return list(dropdown_config.keys())
12
 
 
13
  def retrieve_config_options(label, dropdown_config):
14
  options = list(dropdown_config[label].keys())
15
  options = [option.title() for option in options]
16
  return options
17
 
 
18
  def get_options_description(value, mode):
19
- print(mode)
20
- if mode=="simple":
21
- dropdown_config = get_custom_config_dropdowns("config_checkbox_physical_simple.json")
22
- elif mode == "advanced":
23
- dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
24
- # get options
25
- options_common = retrieve_config_options("Common", dropdown_config)
26
- options_for_value = retrieve_config_options(value, dropdown_config)
27
- options_common.extend(options_for_value)
28
- options = options_common
29
- # get descriptions
30
- descriptions = []
31
- for key, sub_dict in dropdown_config.items():
32
- if key==value or key=="Common":
33
- for _, option_dict in sub_dict.items():
34
- for description_tag, description in option_dict.items():
35
- if "Description"==description_tag:
36
- descriptions.append(description)
37
- return options, descriptions
38
-
39
- #---------------------------------------------------------
 
 
 
40
  def create_checkbox_beak(section, mode, label_checkbox, visible):
41
- body_part="Beak"
42
  options, descriptions = get_options_description(body_part, mode)
43
- return create_checkbox(body_part, section, label_checkbox, visible, options, descriptions)
 
 
 
44
 
45
  def create_checkbox_body(section, mode, label_checkbox, visible):
46
- body_part="Body"
47
  options, descriptions = get_options_description(body_part, mode)
48
- return create_checkbox(body_part, section, label_checkbox, visible, options, descriptions)
 
 
 
49
 
50
  def create_checkbox_feathers(section, mode, label_checkbox, visible):
51
- body_part="Feathers/Wings/Tail"
52
  options, descriptions = get_options_description(body_part, mode)
53
- return create_checkbox(body_part, section, label_checkbox, visible, options, descriptions)
 
 
 
54
 
55
  def create_checkbox_head(section, mode, label_checkbox, visible):
56
- body_part="Head incl. eyes"
57
  options, descriptions = get_options_description(body_part, mode)
58
- return create_checkbox(body_part, section, label_checkbox, visible, options, descriptions)
 
 
 
59
 
60
  def create_checkbox_legs(section, mode, label_checkbox, visible):
61
- body_part="Legs"
62
  options, descriptions = get_options_description(body_part, mode)
63
- return create_checkbox(body_part, section, label_checkbox, visible, options, descriptions)
 
 
 
64
 
65
- #---------------------------------------------------------
66
  def process_body_parts(section, mode, matched_box):
67
- #take all except "Common"
68
  body_parts = get_body_parts(mode)
69
  body_parts = body_parts[1:]
70
  label_checkbox = "Physical changes to "
71
- visibles = [True if matched_box==body_part else False for body_part in body_parts ]
72
- checkbox_beak, text_beak = create_checkbox_beak(section, mode, label_checkbox, visibles[0])
73
- checkbox_body, text_body = create_checkbox_body(section, mode, label_checkbox, visibles[1])
74
- checkbox_feathers, text_feathers = create_checkbox_feathers(section, mode, label_checkbox, visibles[2])
75
- checkbox_head, text_head = create_checkbox_head(section, mode, label_checkbox, visibles[3])
76
- checkbox_legs, text_legs = create_checkbox_legs(section, mode, label_checkbox, visibles[4])
77
- return checkbox_beak, text_beak, checkbox_body, text_body, checkbox_feathers, text_feathers, checkbox_head, text_head, checkbox_legs, text_legs
78
-
79
- #---------------------------------------------------------
80
-
81
- def on_select_body_part(body_part_checkbox, body_part, individual):
82
- individual = add_data_to_individual("physical_type_"+body_part.lower(), body_part.lower(), individual)
83
- body_part_checkbox = [body_part_check.lower() for body_part_check in body_part_checkbox]
84
- individual = add_data_to_individual("physical_anomaly_"+body_part.lower(), body_part_checkbox, individual)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  return individual
86
 
87
- #---------------------------------------------------------
 
 
88
 
89
  def hide_physical(mode):
90
- checkbox_beak, text_beak, checkbox_body, text_body, checkbox_feathers, text_feathers, checkbox_head, text_head, checkbox_legs, text_legs = process_body_parts("wounded", mode, "None")
91
- return checkbox_beak, text_beak, checkbox_body, text_body, checkbox_feathers, text_feathers, checkbox_head, text_head, checkbox_legs, text_legs
92
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.utils_individual import add_data_to_individual
5
+
6
+
7
+ # ---------------------------------------------------------
8
  def get_body_parts(mode):
9
+ if mode == "simple":
10
+ dropdown_config = get_custom_config_dropdowns(
11
+ "config_checkbox_physical_simple.json"
12
+ )
13
  elif mode == "advanced":
14
  dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
15
  return list(dropdown_config.keys())
16
 
17
+
18
  def retrieve_config_options(label, dropdown_config):
19
  options = list(dropdown_config[label].keys())
20
  options = [option.title() for option in options]
21
  return options
22
 
23
+
24
  def get_options_description(value, mode):
25
+ # print(f"Get options description: {mode}")
26
+ if mode == "simple":
27
+ dropdown_config = get_custom_config_dropdowns(
28
+ "config_checkbox_physical_simple.json"
29
+ )
30
+ elif mode == "advanced":
31
+ dropdown_config = get_custom_config_dropdowns("config_checkbox_physical.json")
32
+ # get options
33
+ options_common = retrieve_config_options("Common", dropdown_config)
34
+ options_for_value = retrieve_config_options(value, dropdown_config)
35
+ options_common.extend(options_for_value)
36
+ options = options_common
37
+ # get descriptions
38
+ descriptions = []
39
+ for key, sub_dict in dropdown_config.items():
40
+ if key == value or key == "Common":
41
+ for _, option_dict in sub_dict.items():
42
+ for description_tag, description in option_dict.items():
43
+ if "Description" == description_tag:
44
+ descriptions.append(description)
45
+ return options, descriptions
46
+
47
+
48
+ # ---------------------------------------------------------
49
  def create_checkbox_beak(section, mode, label_checkbox, visible):
50
+ body_part = "Beak"
51
  options, descriptions = get_options_description(body_part, mode)
52
+ return create_checkbox(
53
+ body_part, section, label_checkbox, visible, options, descriptions
54
+ )
55
+
56
 
57
  def create_checkbox_body(section, mode, label_checkbox, visible):
58
+ body_part = "Body"
59
  options, descriptions = get_options_description(body_part, mode)
60
+ return create_checkbox(
61
+ body_part, section, label_checkbox, visible, options, descriptions
62
+ )
63
+
64
 
65
  def create_checkbox_feathers(section, mode, label_checkbox, visible):
66
+ body_part = "Feathers/Wings/Tail"
67
  options, descriptions = get_options_description(body_part, mode)
68
+ return create_checkbox(
69
+ body_part, section, label_checkbox, visible, options, descriptions
70
+ )
71
+
72
 
73
  def create_checkbox_head(section, mode, label_checkbox, visible):
74
+ body_part = "Head incl. eyes"
75
  options, descriptions = get_options_description(body_part, mode)
76
+ return create_checkbox(
77
+ body_part, section, label_checkbox, visible, options, descriptions
78
+ )
79
+
80
 
81
  def create_checkbox_legs(section, mode, label_checkbox, visible):
82
+ body_part = "Legs"
83
  options, descriptions = get_options_description(body_part, mode)
84
+ return create_checkbox(
85
+ body_part, section, label_checkbox, visible, options, descriptions
86
+ )
87
+
88
 
89
+ # ---------------------------------------------------------
90
  def process_body_parts(section, mode, matched_box):
91
+ # take all except "Common"
92
  body_parts = get_body_parts(mode)
93
  body_parts = body_parts[1:]
94
  label_checkbox = "Physical changes to "
95
+ visibles = [True if matched_box == body_part else False for body_part in body_parts]
96
+ checkbox_beak, text_beak = create_checkbox_beak(
97
+ section, mode, label_checkbox, visibles[0]
98
+ )
99
+ checkbox_body, text_body = create_checkbox_body(
100
+ section, mode, label_checkbox, visibles[1]
101
+ )
102
+ checkbox_feathers, text_feathers = create_checkbox_feathers(
103
+ section, mode, label_checkbox, visibles[2]
104
+ )
105
+ checkbox_head, text_head = create_checkbox_head(
106
+ section, mode, label_checkbox, visibles[3]
107
+ )
108
+ checkbox_legs, text_legs = create_checkbox_legs(
109
+ section, mode, label_checkbox, visibles[4]
110
+ )
111
+ return (
112
+ checkbox_beak,
113
+ text_beak,
114
+ checkbox_body,
115
+ text_body,
116
+ checkbox_feathers,
117
+ text_feathers,
118
+ checkbox_head,
119
+ text_head,
120
+ checkbox_legs,
121
+ text_legs,
122
+ )
123
+
124
+
125
+ # ---------------------------------------------------------
126
+
127
+
128
+ def on_select_body_part(body_part_checkbox, body_part, individual):
129
+ individual = add_data_to_individual(
130
+ "physical_type_" + body_part.lower(), body_part.lower(), individual
131
+ )
132
+ body_part_checkbox = [
133
+ body_part_check.lower() for body_part_check in body_part_checkbox
134
+ ]
135
+ individual = add_data_to_individual(
136
+ "physical_anomaly_" + body_part.lower(), body_part_checkbox, individual
137
+ )
138
  return individual
139
 
140
+
141
+ # ---------------------------------------------------------
142
+
143
 
144
  def hide_physical(mode):
145
+ (
146
+ checkbox_beak,
147
+ text_beak,
148
+ checkbox_body,
149
+ text_body,
150
+ checkbox_feathers,
151
+ text_feathers,
152
+ checkbox_head,
153
+ text_head,
154
+ checkbox_legs,
155
+ text_legs,
156
+ ) = process_body_parts("wounded", mode, "None")
157
+ return (
158
+ checkbox_beak,
159
+ text_beak,
160
+ checkbox_body,
161
+ text_body,
162
+ checkbox_feathers,
163
+ text_feathers,
164
+ checkbox_head,
165
+ text_head,
166
+ checkbox_legs,
167
+ text_legs,
168
+ )
app/validation_submission/submission.py CHANGED
@@ -1,28 +1,31 @@
1
- import json
2
  from validation_submission.validation import validate_individual
3
 
4
  from huggingface_hub import HfApi
5
  import os
6
 
 
7
  def validate_save_individual(data, error_box, mode):
8
  individual, error_box = validate_individual(data, error_box, mode)
9
  if individual:
10
  push_to_dataset_hf(individual.model_dump())
11
  return error_box
12
-
 
13
  def push_to_dataset_hf(individual):
14
  token = os.environ.get("HF_TOKEN", None)
15
  api = HfApi(token=token)
16
  import tempfile
 
17
  f = tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False)
18
  json.dump(individual, f)
19
  f.flush()
20
  f.close()
21
- path_in_repo= f"data/{individual['image_md5']}.json"
22
- print(path_in_repo)
23
  # api.upload_file(
24
  # path_or_fileobj=f.name,
25
  # path_in_repo=path_in_repo,
26
  # repo_id="SDSC/digiwild-dataset",
27
  # repo_type="dataset",
28
- # )
 
1
+ import json
2
  from validation_submission.validation import validate_individual
3
 
4
  from huggingface_hub import HfApi
5
  import os
6
 
7
+
8
  def validate_save_individual(data, error_box, mode):
9
  individual, error_box = validate_individual(data, error_box, mode)
10
  if individual:
11
  push_to_dataset_hf(individual.model_dump())
12
  return error_box
13
+
14
+
15
  def push_to_dataset_hf(individual):
16
  token = os.environ.get("HF_TOKEN", None)
17
  api = HfApi(token=token)
18
  import tempfile
19
+
20
  f = tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False)
21
  json.dump(individual, f)
22
  f.flush()
23
  f.close()
24
+ path_in_repo = f"data/{individual['image_md5']}.json"
25
+ # print(path_in_repo)
26
  # api.upload_file(
27
  # path_or_fileobj=f.name,
28
  # path_in_repo=path_in_repo,
29
  # repo_id="SDSC/digiwild-dataset",
30
  # repo_type="dataset",
31
+ # )
app/validation_submission/validation.py CHANGED
@@ -10,22 +10,29 @@ from physical.class_physical import PhysicalAnomalies
10
  from physical.class_physical_simple import PhysicalAnomaliesSimple
11
  from follow_up.class_follow_up import FollowUpEvents
12
  from classes import Report, Wounded, Dead, ImageBase64
13
- from validation_submission.processing import process_circumstance, process_behaviors, process_physical, process_followup
 
 
 
 
 
 
14
 
15
  def get_fields(data_dict, keyword):
16
- extract = {}
17
  for key, val in data_dict.items():
18
  if keyword in key:
19
  extract[key] = val
20
  return extract
21
 
22
- def validate_individual(data, error_box, mode:str):
 
23
  error_box = reset_error_box(error_box)
24
- #data = get_json_one_individual() # TODO: This should change
25
  data["identifier"] = str(uuid.uuid4())
26
  if "image" in data.keys():
27
  img = ImageBase64.to_base64(data["image"])
28
- else:
29
  img = None
30
  if "geolocalisation" in data.keys():
31
  geolocalisation = data["geolocalisation"]
@@ -33,72 +40,109 @@ def validate_individual(data, error_box, mode:str):
33
  geolocalisation = None
34
 
35
  error_behavior = None
36
- error_circumstance = None
37
- error_followup = None
38
- error_physical = None
39
  error_individual = None
40
  if "wounded_state" not in data or "dead_state" not in data:
41
  data["wounded_state"] = "No"
42
  data["dead_state"] = "No"
43
  if (data["wounded_state"] == "Yes") or (data["dead_state"] == "Yes"):
44
- data_wounded_dead = data #get_json_tmp("wounded_dead")
45
- print(data_wounded_dead)
46
  circumstance, error_circumstance = validate_circumstance(data_wounded_dead)
47
  physical, error_physical = validate_physical(data_wounded_dead, mode)
48
  followup, error_followup = validate_follow_up(data_wounded_dead)
49
 
50
- if data["wounded_state"]=="Yes":
51
- print(physical)
52
  behavior, error_behavior = validate_behavior(data_wounded_dead, mode)
53
- try :
54
- individual = Report(identifier = data["identifier"],
55
- image = img,
56
- image_md5 = data["image_md5"],
57
- geolocalisation = geolocalisation,
58
- wounded_state = data["wounded_state"],
59
- wounded = Wounded(circumstances = circumstance,
60
- behaviors = behavior,
61
- physical_anomalies = physical,
62
- follow_up_events = followup),
63
- dead_state = data["dead_state"])
 
 
 
 
64
  except ValidationError as e:
65
- print(e)
 
66
  error_individual = e
67
 
68
- elif data["dead_state"]=="Yes":
69
- try:
70
- individual = Report(identifier = data["identifier"],
71
- image = img,
72
- image_md5 = data["image_md5"],
73
- geolocalisation = geolocalisation,
74
- wounded_state = data["wounded_state"],
75
- dead_state = data["dead_state"],
76
- dead = Dead(circumstances = circumstance,
77
- physical_anomalies = physical,
78
- follow_up_events = followup)
79
- )
 
 
 
80
  except ValidationError as e:
81
- print(e)
 
82
  error_individual = e
83
  else:
84
- try:
85
- individual = Report(identifier = data["identifier"],
86
- image = img,
87
- image_md5 = data["image_md5"],
88
- geolocalisation = geolocalisation,
89
- wounded_state = data["wounded_state"],
90
- dead_state = data["dead_state"])
 
 
91
  except ValidationError as e:
92
- print(e)
93
  error_individual = e
94
- if error_behavior or error_circumstance or error_followup or error_physical or error_individual:
95
- error_box = show_error(error_box, error_behavior, error_circumstance, error_followup, error_physical, error_individual)
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  individual = None
97
- else:
98
- error_box= gr.Text(label="ALL VALID.", value="Record Registered. You can return to the Display.", visible=True, elem_id="valid")
 
 
 
 
 
99
  return individual, error_box
100
 
101
- def show_error(error_box, error_behavior, error_circumstance, error_followup, error_physical, error_individual):
 
 
 
 
 
 
 
 
102
  error_text = ""
103
  if error_circumstance:
104
  error_text += f"Error in circumstance: {error_circumstance}\n"
@@ -111,78 +155,78 @@ def show_error(error_box, error_behavior, error_circumstance, error_followup, er
111
  if error_individual:
112
  error_text += f"Error in individual: {error_individual}\n"
113
  error_text += "PLEASE CORRECT THESE ERRORS BEFORE SUBMITTING."
114
- error_box= gr.Text(label="ERROR DETECTED !", value=error_text, visible=True, elem_id="error")
 
 
115
  return error_box
116
 
 
117
  def reset_error_box(error_box):
118
  error_box = gr.Text(value=None, visible=False)
119
  return error_box
120
 
 
121
  #### VALIDATION FUNCTIONS
122
- def validate_circumstance(data):
123
  circumstance_raw = get_fields(data, "circumstance")
124
  circumstance_formatted = process_circumstance(circumstance_raw)
125
- try:
126
  Circumstances.model_validate(circumstance_formatted)
127
  circumstances = Circumstances(**circumstance_formatted)
128
  error = None
129
  except ValidationError as e:
130
  error = e
131
- print(e)
132
  circumstances = None
133
  return circumstances, error
134
-
135
 
136
- def validate_behavior(data, mode):
 
137
  behaviors_raw = get_fields(data, "behaviors")
138
  behaviors_formatted = process_behaviors(behaviors_raw)
139
  try:
140
- if mode=="simple":
141
  BehaviorsSimple.model_validate(behaviors_formatted)
142
  behavior = BehaviorsSimple(**behaviors_formatted)
143
- elif mode=="advanced":
144
  Behaviors.model_validate(behaviors_formatted)
145
  behavior = Behaviors(**behaviors_formatted)
146
  error = None
147
  except ValidationError as e:
148
- print(e)
149
- print("Validation failed for the behaviors.")
150
  behavior = None
151
  error = e
152
  return behavior, error
153
-
154
 
155
- def validate_physical(data, mode):
 
156
  physical_raw = get_fields(data, "physical")
157
  physical_formatted = process_physical(physical_raw)
158
- print(physical_formatted)
159
- try:
160
- if mode=="simple":
161
  PhysicalAnomaliesSimple.model_validate(physical_formatted)
162
  physical = PhysicalAnomaliesSimple(**physical_formatted)
163
- elif mode=="advanced":
164
  PhysicalAnomalies.model_validate(physical_formatted)
165
  physical = PhysicalAnomalies(**physical_formatted)
166
  error = None
167
  except ValidationError as e:
168
- print(e)
169
- print("Validation failed for the physical anomalies.")
170
  physical = None
171
  error = e
172
  return physical, error
173
-
 
174
  def validate_follow_up(data):
175
  followup_raw = get_fields(data, "followup")
176
  followup_formatted = process_followup(followup_raw)
177
- try:
178
  FollowUpEvents.model_validate(followup_formatted)
179
  followup = FollowUpEvents(**followup_formatted)
180
  error = None
181
  except ValidationError as e:
182
- print(e)
183
- print("Validation failed for the follow-up events.")
184
  followup = None
185
  return followup, error
186
-
187
-
188
-
 
10
  from physical.class_physical_simple import PhysicalAnomaliesSimple
11
  from follow_up.class_follow_up import FollowUpEvents
12
  from classes import Report, Wounded, Dead, ImageBase64
13
+ from validation_submission.processing import (
14
+ process_circumstance,
15
+ process_behaviors,
16
+ process_physical,
17
+ process_followup,
18
+ )
19
+
20
 
21
  def get_fields(data_dict, keyword):
22
+ extract = {}
23
  for key, val in data_dict.items():
24
  if keyword in key:
25
  extract[key] = val
26
  return extract
27
 
28
+
29
+ def validate_individual(data, error_box, mode: str):
30
  error_box = reset_error_box(error_box)
31
+ # data = get_json_one_individual() # TODO: This should change
32
  data["identifier"] = str(uuid.uuid4())
33
  if "image" in data.keys():
34
  img = ImageBase64.to_base64(data["image"])
35
+ else:
36
  img = None
37
  if "geolocalisation" in data.keys():
38
  geolocalisation = data["geolocalisation"]
 
40
  geolocalisation = None
41
 
42
  error_behavior = None
43
+ error_circumstance = None
44
+ error_followup = None
45
+ error_physical = None
46
  error_individual = None
47
  if "wounded_state" not in data or "dead_state" not in data:
48
  data["wounded_state"] = "No"
49
  data["dead_state"] = "No"
50
  if (data["wounded_state"] == "Yes") or (data["dead_state"] == "Yes"):
51
+ data_wounded_dead = data # get_json_tmp("wounded_dead")
52
+ # print(f"Data Wounded Dead: {data_wounded_dead}")
53
  circumstance, error_circumstance = validate_circumstance(data_wounded_dead)
54
  physical, error_physical = validate_physical(data_wounded_dead, mode)
55
  followup, error_followup = validate_follow_up(data_wounded_dead)
56
 
57
+ if data["wounded_state"] == "Yes":
58
+ # print(f"Physical: {physical}")
59
  behavior, error_behavior = validate_behavior(data_wounded_dead, mode)
60
+ try:
61
+ individual = Report(
62
+ identifier=data["identifier"],
63
+ image=img,
64
+ image_md5=data["image_md5"],
65
+ geolocalisation=geolocalisation,
66
+ wounded_state=data["wounded_state"],
67
+ wounded=Wounded(
68
+ circumstances=circumstance,
69
+ behaviors=behavior,
70
+ physical_anomalies=physical,
71
+ follow_up_events=followup,
72
+ ),
73
+ dead_state=data["dead_state"],
74
+ )
75
  except ValidationError as e:
76
+ print("Error in wounded_state:")
77
+ print(e.json())
78
  error_individual = e
79
 
80
+ elif data["dead_state"] == "Yes":
81
+ try:
82
+ individual = Report(
83
+ identifier=data["identifier"],
84
+ image=img,
85
+ image_md5=data["image_md5"],
86
+ geolocalisation=geolocalisation,
87
+ wounded_state=data["wounded_state"],
88
+ dead_state=data["dead_state"],
89
+ dead=Dead(
90
+ circumstances=circumstance,
91
+ physical_anomalies=physical,
92
+ follow_up_events=followup,
93
+ ),
94
+ )
95
  except ValidationError as e:
96
+ print("Error in dead_state:")
97
+ print(e.json())
98
  error_individual = e
99
  else:
100
+ try:
101
+ individual = Report(
102
+ identifier=data["identifier"],
103
+ image=img,
104
+ image_md5=data["image_md5"],
105
+ geolocalisation=geolocalisation,
106
+ wounded_state=data["wounded_state"],
107
+ dead_state=data["dead_state"],
108
+ )
109
  except ValidationError as e:
110
+ print(f"""Error in individual else: {e}""")
111
  error_individual = e
112
+ if (
113
+ error_behavior
114
+ or error_circumstance
115
+ or error_followup
116
+ or error_physical
117
+ or error_individual
118
+ ):
119
+ error_box = show_error(
120
+ error_box,
121
+ error_behavior,
122
+ error_circumstance,
123
+ error_followup,
124
+ error_physical,
125
+ error_individual,
126
+ )
127
  individual = None
128
+ else:
129
+ error_box = gr.Text(
130
+ label="ALL VALID.",
131
+ value="Record Registered. You can return to the Display.",
132
+ visible=True,
133
+ elem_id="valid",
134
+ )
135
  return individual, error_box
136
 
137
+
138
+ def show_error(
139
+ error_box,
140
+ error_behavior,
141
+ error_circumstance,
142
+ error_followup,
143
+ error_physical,
144
+ error_individual,
145
+ ):
146
  error_text = ""
147
  if error_circumstance:
148
  error_text += f"Error in circumstance: {error_circumstance}\n"
 
155
  if error_individual:
156
  error_text += f"Error in individual: {error_individual}\n"
157
  error_text += "PLEASE CORRECT THESE ERRORS BEFORE SUBMITTING."
158
+ error_box = gr.Text(
159
+ label="ERROR DETECTED !", value=error_text, visible=True, elem_id="error"
160
+ )
161
  return error_box
162
 
163
+
164
  def reset_error_box(error_box):
165
  error_box = gr.Text(value=None, visible=False)
166
  return error_box
167
 
168
+
169
  #### VALIDATION FUNCTIONS
170
+ def validate_circumstance(data):
171
  circumstance_raw = get_fields(data, "circumstance")
172
  circumstance_formatted = process_circumstance(circumstance_raw)
173
+ try:
174
  Circumstances.model_validate(circumstance_formatted)
175
  circumstances = Circumstances(**circumstance_formatted)
176
  error = None
177
  except ValidationError as e:
178
  error = e
179
+ print(f"""Error in Validate_circumstance: {e}""")
180
  circumstances = None
181
  return circumstances, error
 
182
 
183
+
184
+ def validate_behavior(data, mode):
185
  behaviors_raw = get_fields(data, "behaviors")
186
  behaviors_formatted = process_behaviors(behaviors_raw)
187
  try:
188
+ if mode == "simple":
189
  BehaviorsSimple.model_validate(behaviors_formatted)
190
  behavior = BehaviorsSimple(**behaviors_formatted)
191
+ elif mode == "advanced":
192
  Behaviors.model_validate(behaviors_formatted)
193
  behavior = Behaviors(**behaviors_formatted)
194
  error = None
195
  except ValidationError as e:
196
+ print(f"""Error in behaviors validation: {e}""")
 
197
  behavior = None
198
  error = e
199
  return behavior, error
 
200
 
201
+
202
+ def validate_physical(data, mode):
203
  physical_raw = get_fields(data, "physical")
204
  physical_formatted = process_physical(physical_raw)
205
+ # print(physical_formatted)
206
+ try:
207
+ if mode == "simple":
208
  PhysicalAnomaliesSimple.model_validate(physical_formatted)
209
  physical = PhysicalAnomaliesSimple(**physical_formatted)
210
+ elif mode == "advanced":
211
  PhysicalAnomalies.model_validate(physical_formatted)
212
  physical = PhysicalAnomalies(**physical_formatted)
213
  error = None
214
  except ValidationError as e:
215
+ print(f"""Error in physical_anomalies validation: {e}""")
 
216
  physical = None
217
  error = e
218
  return physical, error
219
+
220
+
221
  def validate_follow_up(data):
222
  followup_raw = get_fields(data, "followup")
223
  followup_formatted = process_followup(followup_raw)
224
+ try:
225
  FollowUpEvents.model_validate(followup_formatted)
226
  followup = FollowUpEvents(**followup_formatted)
227
  error = None
228
  except ValidationError as e:
229
+ print(f"""Error in follow-up events validation: {e}""")
230
+
231
  followup = None
232
  return followup, error