Skip to content

Commit 0f55b82

Browse files
committed
bug: concentration node does not update the concentration in peak_result
1 parent 8ddb62f commit 0f55b82

File tree

3 files changed

+127
-14
lines changed

3 files changed

+127
-14
lines changed

rust/config.example.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,11 @@ processing:
296296
# Array of 5 coefficients [a₀, a₁, a₂, a₃, a₄]
297297
# Polynomial coefficients for concentration calculation a₀, a₁, a₂, a₃, a₄
298298
# Concentration(ppm) = a₀ + a₁A + a₂A² + a₃A³ + a₄A⁴ where A is the peak amplitude
299-
- 0.0 # a₀ constant term
300-
- 25.0 # a₁ linear term
301-
- -0.3 # a₂ quadratic term
302-
- 0.0 # a₃ cubic term
303-
- 0.0 # a₄ quartic term
299+
- 0.0 # a₀ constant term
300+
- 0.5892 # a₁ linear term
301+
- -0.003 # a₂ quadratic term
302+
- 0.000001 # a₃ cubic term
303+
- 0.000000001 # a₄ quartic term
304304
temperature_compensation: false # Controle temperature compensation
305305
spectral_line_id: CO₂_4.26μm # Optional line identifier for concentration calculation
306306
min_amplitude_threshold: 0.001 # Minimum amplitude threshold for valid concentration calculation

rust/src/processing/computing_nodes/concentration.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,14 @@ impl ConcentrationNode {
289289
fn update_shared_state(&mut self, source_peak_result: &PeakResult, concentration: f64) {
290290
if self.processing_count % 100 == 0 {
291291
info!(
292-
"Concentration node '{}': Calculated {:.2} ppm from amplitude {:.4} (source: {})",
292+
"Concentration node '{}': Calculated {:.2} ppm = {:.1} + {:.1}A + {:.1}A² + {:.1}A³ + {:.1}A⁴ from amplitude {:.4} (source: {})",
293293
self.id,
294294
concentration,
295+
self.polynomial_coefficients[0],
296+
self.polynomial_coefficients[1],
297+
self.polynomial_coefficients[2],
298+
self.polynomial_coefficients[3],
299+
self.polynomial_coefficients[4],
295300
source_peak_result.amplitude,
296301
self.computing_peak_finder_id.as_deref().unwrap_or("latest")
297302
);
@@ -318,6 +323,14 @@ impl ConcentrationNode {
318323

319324
// Store concentration result under this node's ID
320325
state.update_concentration_result(self.id.clone(), concentration_result);
326+
327+
// Update the source PeakResult with the calculated concentration
328+
if let Some(source_id) = &self.computing_peak_finder_id {
329+
if let Some(mut peak_result) = state.get_peak_result(source_id).cloned() {
330+
peak_result.concentration_ppm = Some(concentration as f32);
331+
state.update_peak_result(source_id.clone(), peak_result);
332+
}
333+
}
321334
}
322335
Err(_) => {
323336
warn!(

rust/tests/real_world_peak_endpoint_test.rs

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! It tests the actual data flow from simulation → processing → shared state → API endpoints.
1010
1111
use anyhow::Result;
12+
use rand::rand_core::le;
1213
use rust_photoacoustic::{
1314
config::Config,
1415
daemon::launch_daemon::Daemon,
@@ -136,7 +137,7 @@ async fn test_real_world_peak_detection_endpoints() -> Result<()> {
136137
serde_json::to_string_pretty(&computing_data)?
137138
);
138139

139-
// Verify the structure exists
140+
// Verify the structure exists (legacy fields for compatibility)
140141
assert!(
141142
computing_data.get("peak_frequency").is_some(),
142143
"Should have peak_frequency field"
@@ -150,18 +151,109 @@ async fn test_real_world_peak_detection_endpoints() -> Result<()> {
150151
"Should have concentration_ppm field"
151152
);
152153

153-
// Check if we have real data (non-null values)
154-
let peak_frequency = computing_data["peak_frequency"].as_f64();
155-
let peak_amplitude = computing_data["peak_amplitude"].as_f64();
154+
// Verify new structure exists
155+
assert!(
156+
computing_data.get("active_node_ids").is_some(),
157+
"Should have active_node_ids field"
158+
);
159+
assert!(
160+
computing_data.get("peak_results").is_some(),
161+
"Should have peak_results field"
162+
);
163+
164+
// Get active node IDs
165+
let active_node_ids = computing_data["active_node_ids"]
166+
.as_array()
167+
.expect("active_node_ids should be an array");
168+
169+
println!("Active node IDs: {:?}", active_node_ids);
170+
171+
// Check if we have peak_detector in active nodes
172+
let peak_detector_id = active_node_ids
173+
.iter()
174+
.find(|id| id.as_str() == Some("peak_detector"))
175+
.expect("Should have peak_detector in active_node_ids");
176+
177+
println!("✓ Found active peak detector: {}", peak_detector_id);
156178

157-
println!("Peak frequency: {:?}", peak_frequency);
158-
println!("Peak amplitude: {:?}", peak_amplitude);
179+
// Get peak results for the active peak detector
180+
let peak_results = computing_data["peak_results"]
181+
.as_object()
182+
.expect("peak_results should be an object");
183+
184+
let peak_detector_result = peak_results
185+
.get("peak_detector")
186+
.expect("Should have peak_detector in peak_results");
187+
188+
println!(
189+
"Peak detector result: {}",
190+
serde_json::to_string_pretty(peak_detector_result)?
191+
);
192+
193+
// Extract data from the peak detector result
194+
let peak_frequency = peak_detector_result["frequency"].as_f64();
195+
let peak_amplitude = peak_detector_result["amplitude"].as_f64();
196+
let peak_concentration = peak_detector_result["concentration_ppm"].as_f64();
197+
198+
println!("Peak frequency from peak_detector: {:?}", peak_frequency);
199+
println!("Peak amplitude from peak_detector: {:?}", peak_amplitude);
200+
println!(
201+
"Peak concentration from peak_detector: {:?} ppm",
202+
peak_concentration
203+
);
204+
assert!(
205+
peak_frequency.is_some(),
206+
"Peak frequency should not be null"
207+
);
208+
// peak frequency should be between 1900 and 2200 Hz
209+
assert!(
210+
peak_frequency.unwrap() >= 1900.0 && peak_frequency.unwrap() <= 2200.0,
211+
"Peak frequency should be in the range [1900, 2200] Hz"
212+
);
213+
assert!(
214+
peak_amplitude.is_some(),
215+
"Peak amplitude should not be null"
216+
);
217+
// peak amplitude should be 45 and 55
218+
assert!(
219+
peak_amplitude.unwrap() >= 45.0 && peak_amplitude.unwrap() <= 55.0,
220+
"Peak amplitude should be in the range [45, 55]"
221+
);
222+
// peak concentration should be between 0 and 100 ppm
223+
assert!(
224+
peak_concentration.is_some(),
225+
"Peak concentration should not be null"
226+
);
227+
assert!(
228+
peak_concentration.unwrap() >= 0.0 && peak_concentration.unwrap() <= 100.0,
229+
"Peak concentration should be in the range [0, 100] ppm"
230+
);
231+
232+
// Check concentration calculation result
233+
let concentration_ppm = computing_data["concentration_ppm"].as_f64();
234+
println!("Calculated concentration: {:?} ppm", concentration_ppm);
235+
236+
// Check polynomial coefficients
237+
let polynomial_coefficients = computing_data["polynomial_coefficients"]
238+
.as_array()
239+
.expect("Should have polynomial_coefficients array");
240+
println!("Polynomial coefficients: {:?}", polynomial_coefficients);
159241

160242
// The main test: verify we get real data, not null values
161243
if peak_frequency.is_some() && peak_amplitude.is_some() {
162244
println!("✓ SUCCESS: Peak detection is working - got real values!");
163245
println!(" Peak frequency: {} Hz", peak_frequency.unwrap());
164246
println!(" Peak amplitude: {}", peak_amplitude.unwrap());
247+
248+
if concentration_ppm.is_some() {
249+
println!(
250+
" Calculated concentration: {} ppm",
251+
concentration_ppm.unwrap()
252+
);
253+
println!("✓ SUCCESS: Concentration calculation is also working!");
254+
} else {
255+
println!("⚠ WARNING: Concentration calculation returning null");
256+
}
165257
} else {
166258
println!("⚠ WARNING: Peak detection returning null values");
167259
println!(
@@ -184,8 +276,16 @@ async fn test_real_world_peak_detection_endpoints() -> Result<()> {
184276
serde_json::to_string_pretty(&retry_data)?
185277
);
186278

187-
let retry_peak_frequency = retry_data["peak_frequency"].as_f64();
188-
let retry_peak_amplitude = retry_data["peak_amplitude"].as_f64();
279+
let retry_peak_results = retry_data["peak_results"]
280+
.as_object()
281+
.expect("peak_results should be an object");
282+
283+
let retry_peak_detector_result = retry_peak_results
284+
.get("peak_detector")
285+
.expect("Should have peak_detector in peak_results");
286+
287+
let retry_peak_frequency = retry_peak_detector_result["frequency"].as_f64();
288+
let retry_peak_amplitude = retry_peak_detector_result["amplitude"].as_f64();
189289

190290
if retry_peak_frequency.is_some() && retry_peak_amplitude.is_some() {
191291
println!("✓ SUCCESS on retry: Peak detection working!");

0 commit comments

Comments
 (0)