1+ from __future__ import annotations
2+
3+ import numpy as np
4+ import tempfile
5+
6+ from celery import shared_task
7+ from django .conf import settings
8+
9+ from uvdat .core .models import TaskResult
10+
11+ from .analysis_type import AnalysisType , AnalysisTask
12+ from .flood_simulation import FloodSimulation
13+
14+
15+ class UncertaintyQuantification (AnalysisType ):
16+ def __init__ (self ):
17+ super ().__init__ ()
18+ self .name = "Uncertainty Quantification"
19+ self .description = "Select simulated floods and calculate their standard error."
20+ self .db_value = "uncertainty_quant"
21+ self .input_types = {
22+ "flood_simulation_1" : "TaskResult" ,
23+ "flood_simulation_2" : "TaskResult" ,
24+ "flood_simulation_3" : "TaskResult" ,
25+ }
26+ self .output_types = {
27+ "mean_precipitation_level_mm" : "number" ,
28+ "standard_error_precipitation_level_mm" : "number" ,
29+ "min_precipitation_level_mm" : "number" ,
30+ "max_precipitation_level_mm" : "number" ,
31+ "range_precipitation_level_mm" : "number" ,
32+ "mean_discharge_ft3_per_second" : "number" ,
33+ "standard_error_discharge_ft3_per_second" : "number" ,
34+ "min_discharge_ft3_per_second" : "number" ,
35+ "max_discharge_ft3_per_second" : "number" ,
36+ "range_discharge_ft3_per_second" : "number" ,
37+ }
38+ self .attribution = "Northeastern University"
39+
40+ @classmethod
41+ def is_enabled (cls ):
42+ return settings .UVDAT_ENABLE_UNCERTAINTY_QUANTIFICATION
43+
44+ def get_input_options (self ):
45+ return {
46+ "flood_simulation_1" : TaskResult .objects .filter (task_type = FloodSimulation ().db_value ),
47+ "flood_simulation_2" : TaskResult .objects .filter (task_type = FloodSimulation ().db_value ),
48+ "flood_simulation_3" : TaskResult .objects .filter (task_type = FloodSimulation ().db_value ),
49+ }
50+
51+ def run_task (self , * , project , ** inputs ):
52+ result = TaskResult .objects .create (
53+ name = "Uncertainty Quantification" ,
54+ task_type = self .db_value ,
55+ inputs = inputs ,
56+ project = project ,
57+ status = "Initializing task..." ,
58+ )
59+ uncertainty_quantification .delay (result .id )
60+ return result
61+
62+ def finalize (self , result ):
63+ pass
64+
65+
66+
67+
68+ @shared_task (base = AnalysisTask )
69+ def uncertainty_quantification (result_id ):
70+ result = TaskResult .objects .get (id = result_id )
71+ flood_sim_1_id = result .inputs .get ("flood_simulation_1" )
72+ flood_sim_1 = TaskResult .objects .get (id = flood_sim_1_id )
73+ flood_sim_2_id = result .inputs .get ("flood_simulation_2" )
74+ flood_sim_2 = TaskResult .objects .get (id = flood_sim_2_id )
75+ flood_sim_3_id = result .inputs .get ("flood_simulation_3" )
76+ flood_sim_3 = TaskResult .objects .get (id = flood_sim_3_id )
77+
78+ # Update name
79+ result .name = (
80+ f"Uncertainty Quantification for Flood Results { flood_sim_1 .id } , { flood_sim_2 .id } , { flood_sim_3 .id } "
81+ )
82+ result .save ()
83+
84+
85+ precip1 = flood_sim_1 .outputs .get ("precipitation_level_mm" )
86+ discharge1 = flood_sim_1 .outputs .get ("discharge_ft3_per_second" )
87+ precip2 = flood_sim_2 .outputs .get ("precipitation_level_mm" )
88+ discharge2 = flood_sim_2 .outputs .get ("discharge_ft3_per_second" )
89+ precip3 = flood_sim_3 .outputs .get ("precipitation_level_mm" )
90+ discharge3 = flood_sim_3 .outputs .get ("discharge_ft3_per_second" )
91+
92+
93+ result .write_status (
94+ f"Calculating uncertainty..."
95+ )
96+
97+ precip_mean = np .mean ([precip1 , precip2 , precip3 ])
98+ precip_stde = np .std ([precip1 , precip2 , precip3 ])
99+ precip_max = np .max ([precip1 , precip2 , precip3 ])
100+ precip_min = np .min ([precip1 , precip2 , precip3 ])
101+ precip_range = precip_max - precip_min
102+ discharge_mean = np .mean ([discharge1 , discharge2 , discharge3 ])
103+ discharge_stde = np .std ([discharge1 , discharge2 , discharge3 ])
104+ discharge_max = np .max ([discharge1 , discharge2 , discharge3 ])
105+ discharge_min = np .min ([discharge1 , discharge2 , discharge3 ])
106+ discharge_range = discharge_max - discharge_min
107+
108+
109+ result .write_status ("Saving result to database" )
110+
111+ result .write_outputs = {
112+ "mean_precipitation_level_mm" : precip_mean ,
113+ "standard_error_precipitation_level_mm" : precip_stde ,
114+ "min_precipitation_level_mm" : precip_min ,
115+ "max_precipitation_level_mm" : precip_max ,
116+ "range_precipitation_level_mm" : precip_range ,
117+ "mean_discharge_ft3_per_second" : discharge_mean ,
118+ "standard_error_discharge_ft3_per_second" : discharge_stde ,
119+ "min_discharge_ft3_per_second" : discharge_min ,
120+ "max_discharge_ft3_per_second" : discharge_max ,
121+ "range_discharge_ft3_per_second" : discharge_range ,
122+ }
0 commit comments