@@ -15,7 +15,7 @@ def run_FLiES_ANN_inference(
15
15
elevation_km : np .ndarray ,
16
16
SZA : np .ndarray ,
17
17
ANN_model = None ,
18
- model_filename = DEFAULT_MODEL_FILENAME ,
18
+ model_filename = MODEL_FILENAME ,
19
19
split_atypes_ctypes = SPLIT_ATYPES_CTYPES ) -> dict :
20
20
"""
21
21
Runs inference for an artificial neural network (ANN) emulator of the Forest Light
@@ -52,76 +52,106 @@ def run_FLiES_ANN_inference(
52
52
- 'fdnir': Diffuse fraction of radiation in the near-infrared band (np.ndarray).
53
53
"""
54
54
55
- if ANN_model is None :
56
- # Load the ANN model if not provided
57
- ANN_model = load_FLiES_model (model_filename )
58
-
59
- # Prepare inputs for the ANN model
60
- inputs = prepare_FLiES_ANN_inputs (
61
- atype = atype ,
62
- ctype = ctype ,
63
- COT = COT ,
64
- AOT = AOT ,
65
- vapor_gccm = vapor_gccm ,
66
- ozone_cm = ozone_cm ,
67
- albedo = albedo ,
68
- elevation_km = elevation_km ,
69
- SZA = SZA ,
70
- split_atypes_ctypes = split_atypes_ctypes
71
- )
55
+ import os
56
+ import warnings
57
+ # Save current TF_CPP_MIN_LOG_LEVEL and TF logger level
58
+ old_tf_log_level = os .environ .get ('TF_CPP_MIN_LOG_LEVEL' , None )
59
+ try :
60
+ import tensorflow as tf
61
+ old_logger_level = tf .get_logger ().level
62
+ os .environ ['TF_CPP_MIN_LOG_LEVEL' ] = '3'
63
+ tf .get_logger ().setLevel ('ERROR' )
64
+ except Exception :
65
+ old_logger_level = None
72
66
73
- # Convert DataFrame to numpy array and reshape for the model
74
- inputs_array = inputs .values
75
-
76
- # Check what input shape the model expects and adapt accordingly
77
- # Different TensorFlow/Keras versions may have different input requirements
78
67
try :
79
- model_input_shape = ANN_model .input_shape
80
- if len (model_input_shape ) == 3 :
81
- # Model expects 3D input: (batch_size, sequence_length, features)
82
- # Reshape from (batch_size, features) to (batch_size, 1, features)
83
- inputs_array = inputs_array .reshape (inputs_array .shape [0 ], 1 , inputs_array .shape [1 ])
84
- expects_3d = True
85
- elif len (model_input_shape ) == 2 :
86
- # Model expects 2D input: (batch_size, features)
87
- # Keep the original 2D shape
88
- expects_3d = False
89
- else :
90
- # Fallback: try 2D first
68
+ if ANN_model is None :
69
+ # Load the ANN model if not provided
70
+ ANN_model = load_FLiES_model (model_filename )
71
+
72
+ # Prepare inputs for the ANN model
73
+ inputs = prepare_FLiES_ANN_inputs (
74
+ atype = atype ,
75
+ ctype = ctype ,
76
+ COT = COT ,
77
+ AOT = AOT ,
78
+ vapor_gccm = vapor_gccm ,
79
+ ozone_cm = ozone_cm ,
80
+ albedo = albedo ,
81
+ elevation_km = elevation_km ,
82
+ SZA = SZA ,
83
+ split_atypes_ctypes = split_atypes_ctypes
84
+ )
85
+
86
+ # Convert DataFrame to numpy array and reshape for the model
87
+ inputs_array = inputs .values
88
+
89
+ # Check what input shape the model expects and adapt accordingly
90
+ # Different TensorFlow/Keras versions may have different input requirements
91
+ try :
92
+ model_input_shape = ANN_model .input_shape
93
+ if len (model_input_shape ) == 3 :
94
+ # Model expects 3D input: (batch_size, sequence_length, features)
95
+ # Reshape from (batch_size, features) to (batch_size, 1, features)
96
+ inputs_array = inputs_array .reshape (inputs_array .shape [0 ], 1 , inputs_array .shape [1 ])
97
+ expects_3d = True
98
+ elif len (model_input_shape ) == 2 :
99
+ # Model expects 2D input: (batch_size, features)
100
+ # Keep the original 2D shape
101
+ expects_3d = False
102
+ else :
103
+ # Fallback: try 2D first
104
+ expects_3d = False
105
+ except (AttributeError , TypeError ):
106
+ # If input_shape is not available, try 2D first
91
107
expects_3d = False
92
- except (AttributeError , TypeError ):
93
- # If input_shape is not available, try 2D first
94
- expects_3d = False
95
-
96
- # Run inference using the ANN model
97
- try :
98
- outputs = ANN_model .predict (inputs_array )
99
- except ValueError as e :
100
- error_msg = str (e )
101
- if not expects_3d and ("expected shape" in error_msg or "incompatible" in error_msg ):
102
- # Try reshaping to 3D if 2D failed
103
- inputs_array = inputs .values # Reset to original 2D shape
104
- inputs_array = inputs_array .reshape (inputs_array .shape [0 ], 1 , inputs_array .shape [1 ])
105
- outputs = ANN_model .predict (inputs_array )
106
- expects_3d = True
107
- else :
108
- raise e
109
-
110
- # Handle output dimensions based on input dimensions used
111
- if expects_3d and len (outputs .shape ) == 3 :
112
- outputs = outputs .squeeze (axis = 1 )
113
-
114
- shape = COT .shape
115
-
116
- # Prepare the results dictionary
117
- results = {
118
- 'tm' : np .clip (outputs [:, 0 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Total transmittance
119
- 'puv' : np .clip (outputs [:, 1 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Proportion of UV radiation
120
- 'pvis' : np .clip (outputs [:, 2 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Proportion of visible radiation
121
- 'pnir' : np .clip (outputs [:, 3 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Proportion of NIR radiation
122
- 'fduv' : np .clip (outputs [:, 4 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Diffuse fraction of UV radiation
123
- 'fdvis' : np .clip (outputs [:, 5 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Diffuse fraction of visible radiation
124
- 'fdnir' : np .clip (outputs [:, 6 ].reshape (shape ), 0 , 1 ).astype (np .float32 ) # Diffuse fraction of NIR radiation
125
- }
126
108
127
- return results
109
+ # Run inference using the ANN model with warnings suppressed
110
+ try :
111
+ with warnings .catch_warnings ():
112
+ warnings .simplefilter ("ignore" )
113
+ outputs = ANN_model .predict (inputs_array )
114
+ except ValueError as e :
115
+ error_msg = str (e )
116
+ if not expects_3d and ("expected shape" in error_msg or "incompatible" in error_msg ):
117
+ # Try reshaping to 3D if 2D failed
118
+ inputs_array = inputs .values # Reset to original 2D shape
119
+ inputs_array = inputs_array .reshape (inputs_array .shape [0 ], 1 , inputs_array .shape [1 ])
120
+ with warnings .catch_warnings ():
121
+ warnings .simplefilter ("ignore" )
122
+ outputs = ANN_model .predict (inputs_array )
123
+ expects_3d = True
124
+ else :
125
+ raise e
126
+
127
+ # Handle output dimensions based on input dimensions used
128
+ if expects_3d and len (outputs .shape ) == 3 :
129
+ outputs = outputs .squeeze (axis = 1 )
130
+
131
+ shape = COT .shape
132
+
133
+ # Prepare the results dictionary
134
+ results = {
135
+ 'tm' : np .clip (outputs [:, 0 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Total transmittance
136
+ 'puv' : np .clip (outputs [:, 1 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Proportion of UV radiation
137
+ 'pvis' : np .clip (outputs [:, 2 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Proportion of visible radiation
138
+ 'pnir' : np .clip (outputs [:, 3 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Proportion of NIR radiation
139
+ 'fduv' : np .clip (outputs [:, 4 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Diffuse fraction of UV radiation
140
+ 'fdvis' : np .clip (outputs [:, 5 ].reshape (shape ), 0 , 1 ).astype (np .float32 ), # Diffuse fraction of visible radiation
141
+ 'fdnir' : np .clip (outputs [:, 6 ].reshape (shape ), 0 , 1 ).astype (np .float32 ) # Diffuse fraction of NIR radiation
142
+ }
143
+
144
+ return results
145
+ finally :
146
+ # Restore previous TF_CPP_MIN_LOG_LEVEL and logger level
147
+ if old_tf_log_level is not None :
148
+ os .environ ['TF_CPP_MIN_LOG_LEVEL' ] = old_tf_log_level
149
+ else :
150
+ if 'TF_CPP_MIN_LOG_LEVEL' in os .environ :
151
+ del os .environ ['TF_CPP_MIN_LOG_LEVEL' ]
152
+ try :
153
+ import tensorflow as tf
154
+ if old_logger_level is not None :
155
+ tf .get_logger ().setLevel (old_logger_level )
156
+ except Exception :
157
+ pass
0 commit comments