@@ -15,7 +15,7 @@ def run_FLiES_ANN_inference(
1515 elevation_km : np .ndarray ,
1616 SZA : np .ndarray ,
1717 ANN_model = None ,
18- model_filename = DEFAULT_MODEL_FILENAME ,
18+ model_filename = MODEL_FILENAME ,
1919 split_atypes_ctypes = SPLIT_ATYPES_CTYPES ) -> dict :
2020 """
2121 Runs inference for an artificial neural network (ANN) emulator of the Forest Light
@@ -52,76 +52,106 @@ def run_FLiES_ANN_inference(
5252 - 'fdnir': Diffuse fraction of radiation in the near-infrared band (np.ndarray).
5353 """
5454
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
7266
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
7867 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
91107 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- }
126108
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