1pub mod comparative;
43pub mod config_types;
44pub mod core;
45pub mod feature_importance;
46pub mod interactive;
47pub mod interactive_framework;
48pub mod mobile;
49pub mod output;
50pub mod plots_3d;
51pub mod plotting_functions;
52pub mod shap;
53pub mod simd_operations;
54
55pub use config_types::{
57 Animation3D, AutoRotate3D, Camera3D, ColorScheme, ComparativePlot, ComparisonType,
58 ContourLines3D, EasingType, FeatureImportancePlot, FeatureImportanceType, MobileConfig,
59 PartialDependencePlot, Plot3D, Plot3DType, PlotConfig, PlotConfigBuilder,
60 PlotInteractionHandler, ProjectionType, ShapPlot, ShapPlotType, Surface3D,
61};
62
63pub use interactive_framework::InteractiveVisualizer;
65
66pub use simd_operations::{
68 simd_color_mapping, simd_find_min_max, simd_generate_grid_range, simd_normalize_data,
69 simd_smooth_data, simd_sum,
70};
71
72pub use plotting_functions::{
74 create_2d_partial_dependence_plot, create_comparative_plot, create_feature_importance_plot,
75 create_partial_dependence_plot, create_performance_comparison_plot,
76 create_ranked_feature_importance_plot, create_shap_summary_plot, create_shap_visualization,
77};
78
79pub use plots_3d::{create_3d_plot, create_3d_shap_plot, create_3d_surface_plot};
81
82use crate::Float;
84use crate::SklResult;
85use scirs2_core::ndarray::{Array1, ArrayView1, ArrayView2};
86
87pub struct VisualizationFactory {
89 default_config: PlotConfig,
90 interactive_visualizer: InteractiveVisualizer,
91}
92
93impl VisualizationFactory {
94 pub fn new() -> Self {
96 Self {
97 default_config: PlotConfig::default(),
98 interactive_visualizer: InteractiveVisualizer::new(),
99 }
100 }
101
102 pub fn with_config(config: PlotConfig) -> Self {
104 Self {
105 default_config: config,
106 interactive_visualizer: InteractiveVisualizer::new(),
107 }
108 }
109
110 pub fn interactive(&mut self) -> &mut InteractiveVisualizer {
112 &mut self.interactive_visualizer
113 }
114
115 pub fn feature_importance(
117 &self,
118 importance_values: &ArrayView1<Float>,
119 feature_names: Option<&[String]>,
120 plot_type: FeatureImportanceType,
121 ) -> SklResult<FeatureImportancePlot> {
122 create_feature_importance_plot(
123 importance_values,
124 feature_names,
125 None,
126 &self.default_config,
127 plot_type,
128 )
129 }
130
131 pub fn shap_summary(
133 &self,
134 shap_values: &ArrayView2<Float>,
135 feature_values: &ArrayView2<Float>,
136 feature_names: &[String],
137 ) -> SklResult<ShapPlot> {
138 create_shap_summary_plot(
139 shap_values,
140 feature_values,
141 Some(feature_names),
142 &self.default_config,
143 true,
144 )
145 }
146
147 pub fn partial_dependence(
149 &self,
150 feature_values: &ArrayView1<Float>,
151 pd_values: &ArrayView1<Float>,
152 feature_name: &str,
153 ice_curves: Option<&ArrayView2<Float>>,
154 ) -> SklResult<PartialDependencePlot> {
155 create_partial_dependence_plot(
156 feature_values,
157 pd_values,
158 ice_curves,
159 feature_name,
160 &self.default_config,
161 ice_curves.is_some(),
162 )
163 }
164
165 pub fn scatter_3d(
167 &self,
168 x_values: &ArrayView1<Float>,
169 y_values: &ArrayView1<Float>,
170 z_values: &ArrayView1<Float>,
171 axis_labels: (String, String, String),
172 ) -> SklResult<Plot3D> {
173 create_3d_plot(
174 x_values,
175 y_values,
176 z_values,
177 None, None, None, axis_labels,
181 &self.default_config,
182 Plot3DType::Scatter,
183 )
184 }
185
186 pub fn surface_3d(
188 &self,
189 x_grid: &ArrayView2<Float>,
190 y_grid: &ArrayView2<Float>,
191 z_surface: &ArrayView2<Float>,
192 axis_labels: (String, String, String),
193 ) -> SklResult<Surface3D> {
194 create_3d_surface_plot(
195 x_grid,
196 y_grid,
197 z_surface,
198 None, axis_labels,
200 &self.default_config,
201 1.0, )
203 }
204}
205
206impl Default for VisualizationFactory {
207 fn default() -> Self {
208 Self::new()
209 }
210}
211
212pub mod convenience {
214 use super::*;
215
216 pub fn quick_feature_importance(
218 importance_values: &ArrayView1<Float>,
219 feature_names: &[String],
220 ) -> SklResult<FeatureImportancePlot> {
221 let config = PlotConfigBuilder::new()
222 .title("Feature Importance")
223 .x_label("Features")
224 .y_label("Importance")
225 .build();
226
227 create_feature_importance_plot(
228 importance_values,
229 Some(feature_names),
230 None,
231 &config,
232 FeatureImportanceType::Bar,
233 )
234 }
235
236 pub fn quick_shap_summary(
238 shap_values: &ArrayView2<Float>,
239 feature_values: &ArrayView2<Float>,
240 feature_names: &[String],
241 ) -> SklResult<ShapPlot> {
242 let config = PlotConfigBuilder::new()
243 .title("SHAP Summary")
244 .x_label("SHAP Value")
245 .y_label("Features")
246 .build();
247
248 create_shap_summary_plot(
249 shap_values,
250 feature_values,
251 Some(feature_names),
252 &config,
253 true,
254 )
255 }
256
257 pub fn quick_scatter_3d(
259 x_values: Array1<Float>,
260 y_values: Array1<Float>,
261 z_values: Array1<Float>,
262 ) -> SklResult<Plot3D> {
263 create_3d_plot(
264 &x_values.view(),
265 &y_values.view(),
266 &z_values.view(),
267 None,
268 None,
269 None,
270 ("X".to_string(), "Y".to_string(), "Z".to_string()),
271 &PlotConfig::default(),
272 Plot3DType::Scatter,
273 )
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280 use approx::assert_relative_eq;
281 use scirs2_core::ndarray::array;
282 use sklears_core::prelude::Array2;
283
284 #[test]
285 fn test_visualization_factory() {
286 let factory = VisualizationFactory::new();
287 assert_eq!(factory.default_config.title, "Visualization");
288 assert_eq!(factory.default_config.width, 800);
289 assert_eq!(factory.default_config.height, 600);
290 }
291
292 #[test]
293 fn test_factory_feature_importance() {
294 let factory = VisualizationFactory::new();
295 let importance = array![0.8, 0.6, 0.4, 0.2];
296 let feature_names = vec![
297 "feature_1".to_string(),
298 "feature_2".to_string(),
299 "feature_3".to_string(),
300 "feature_4".to_string(),
301 ];
302
303 let plot = factory
304 .feature_importance(
305 &importance.view(),
306 Some(&feature_names),
307 FeatureImportanceType::Bar,
308 )
309 .expect("operation should succeed");
310
311 assert_eq!(plot.feature_names.len(), 4);
312 assert_eq!(plot.importance_values.len(), 4);
313 assert_relative_eq!(plot.importance_values[0], 0.8, epsilon = 1e-10);
314 }
315
316 #[test]
317 fn test_factory_3d_scatter() {
318 let factory = VisualizationFactory::new();
319 let x = array![1.0, 2.0, 3.0];
320 let y = array![1.0, 2.0, 3.0];
321 let z = array![1.0, 2.0, 3.0];
322
323 let plot = factory
324 .scatter_3d(
325 &x.view(),
326 &y.view(),
327 &z.view(),
328 ("X".to_string(), "Y".to_string(), "Z".to_string()),
329 )
330 .expect("operation should succeed");
331
332 assert_eq!(plot.x_values.len(), 3);
333 assert_eq!(plot.y_values.len(), 3);
334 assert_eq!(plot.z_values.len(), 3);
335 assert_eq!(plot.axis_labels.0, "X");
336 }
337
338 #[test]
339 fn test_convenience_functions() {
340 let importance = array![0.5, 0.3, 0.2];
341 let feature_names = vec!["A".to_string(), "B".to_string(), "C".to_string()];
342
343 let plot = convenience::quick_feature_importance(&importance.view(), &feature_names)
344 .expect("operation should succeed");
345 assert_eq!(plot.feature_names.len(), 3);
346 assert_eq!(plot.config.title, "Feature Importance");
347
348 let x = array![1.0, 2.0];
349 let y = array![1.0, 2.0];
350 let z = array![1.0, 2.0];
351 let plot_3d = convenience::quick_scatter_3d(x, y, z).expect("operation should succeed");
352 assert_eq!(plot_3d.x_values.len(), 2);
353 }
354
355 #[test]
356 fn test_module_integration() {
357 let mut visualizer = InteractiveVisualizer::new();
359 visualizer.enable_real_time_updates();
360
361 let config = PlotConfigBuilder::new()
362 .title("Integration Test")
363 .color_scheme(ColorScheme::Viridis)
364 .build();
365
366 visualizer.set_plot_config("test_plot".to_string(), config);
367
368 let data = Array2::<f64>::zeros((10, 2));
369 visualizer.update_plot_data("test_plot", &data);
370
371 assert!(visualizer.is_real_time_enabled());
372 assert_eq!(visualizer.plot_count(), 1);
373 }
374
375 #[test]
376 fn test_simd_integration() {
377 let data = array![1.0, 2.0, 3.0, 4.0, 5.0];
379 let normalized = simd_normalize_data(&data.to_vec(), 0.0, 1.0);
380
381 assert_eq!(normalized.len(), 5);
382 assert_relative_eq!(normalized[0], 0.0, epsilon = 1e-10);
383 assert_relative_eq!(normalized[4], 1.0, epsilon = 1e-10);
384
385 let grid = simd_generate_grid_range(0.0, 10.0, 11);
386 assert_eq!(grid.len(), 11);
387 assert_relative_eq!(grid[0], 0.0, epsilon = 1e-10);
388 assert_relative_eq!(grid[10], 10.0, epsilon = 1e-10);
389 }
390}