Skip to main content

scirs2_ndimage/documentation/
modules.rs

1//! Module Documentation Builders
2//!
3//! This module contains functions to build comprehensive documentation
4//! for all the different modules in the SciRS2 NDImage library.
5
6use crate::documentation::types::{DocumentationSite, FunctionDoc, ModuleDoc, Parameter, Result};
7
8impl DocumentationSite {
9    /// Build comprehensive module documentation for all library modules
10    pub fn build_module_documentation(&mut self) -> Result<()> {
11        self.modules = vec![
12            build_filters_documentation(),
13            build_morphology_documentation(),
14            build_interpolation_documentation(),
15            build_measurements_documentation(),
16        ];
17        Ok(())
18    }
19}
20
21/// Build documentation for the Filters module
22pub fn build_filters_documentation() -> ModuleDoc {
23    let mut module = ModuleDoc::new(
24        "Filters",
25        "Image filtering operations including Gaussian, median, rank, and edge detection filters",
26    );
27
28    // Gaussian filter documentation
29    let mut gaussian_filter = FunctionDoc::new(
30        "gaussian_filter",
31        "pub fn gaussian_filter<T>(input: &ArrayD<T>, sigma: f64) -> ArrayD<T>",
32        "Apply Gaussian filter to n-dimensional array",
33        "ArrayD<T> - Filtered array",
34    );
35
36    gaussian_filter.add_parameter(Parameter::required(
37        "_input",
38        "&ArrayD<T>",
39        "Input n-dimensional array",
40    ));
41    gaussian_filter.add_parameter(Parameter::required(
42        "sigma",
43        "f64",
44        "Standard deviation for Gaussian kernel",
45    ));
46
47    gaussian_filter.add_example(
48        r#"use scirs2_ndimage::filters::gaussian_filter;
49use scirs2_core::ndarray::Array2;
50
51let image = Array2::from_elem((100, 100), 1.0f64);
52let filtered = gaussian_filter(&image, 2.0);
53assert_eq!(filtered.shape(), image.shape());"#,
54    );
55
56    gaussian_filter.add_note("Uses separable convolution for efficiency");
57    gaussian_filter.add_note("Supports all numeric types");
58
59    module.add_function(gaussian_filter);
60
61    // Median filter documentation
62    let mut median_filter = FunctionDoc::new(
63        "median_filter",
64        "pub fn median_filter<T>(input: &ArrayD<T>, size: usize) -> ArrayD<T>",
65        "Apply median filter to remove noise while preserving edges",
66        "ArrayD<T> - Filtered array",
67    );
68
69    median_filter.add_parameter(Parameter::required(
70        "_input",
71        "&ArrayD<T>",
72        "Input n-dimensional array",
73    ));
74    median_filter.add_parameter(Parameter::required(
75        "size",
76        "usize",
77        "Size of the median filter window",
78    ));
79
80    median_filter.add_example(
81        r#"use scirs2_ndimage::filters::median_filter;
82use scirs2_core::ndarray::Array2;
83
84let noisyimage = Array2::from_elem((50, 50), 128.0f64);
85let filtered = median_filter(&noisyimage, 3);
86// Median filter removes salt-and-pepper noise"#,
87    );
88
89    median_filter.add_note("Excellent for removing salt-and-pepper noise");
90    median_filter.add_note("Preserves edges better than linear filters");
91
92    module.add_function(median_filter);
93
94    // Module examples
95    module.add_example("Basic filtering operations");
96    module.add_example("Edge detection pipeline");
97    module.add_example("Noise reduction techniques");
98
99    module
100}
101
102/// Build documentation for the Morphology module
103pub fn build_morphology_documentation() -> ModuleDoc {
104    let mut module = ModuleDoc::new(
105        "Morphology",
106        "Mathematical morphology operations for binary and grayscale images",
107    );
108
109    // Binary erosion documentation
110    let mut binary_erosion = FunctionDoc::new(
111        "binary_erosion",
112        "pub fn binary_erosion(input: &ArrayD<bool>, structure: &ArrayD<bool>) -> ArrayD<bool>",
113        "Perform binary erosion operation",
114        "ArrayD<bool> - Eroded binary array",
115    );
116
117    binary_erosion.add_parameter(Parameter::required(
118        "_input",
119        "&ArrayD<bool>",
120        "Input binary array",
121    ));
122    binary_erosion.add_parameter(Parameter::required(
123        "structure",
124        "&ArrayD<bool>",
125        "Structuring element",
126    ));
127
128    binary_erosion.add_example(
129        r#"use scirs2_ndimage::morphology::binary_erosion;
130use scirs2_core::ndarray::Array2;
131
132let binary_image = Array2::from_elem((10, 10), true);
133let structure = Array2::from_elem((3, 3), true);
134let eroded = binary_erosion(&binary_image, &structure);"#,
135    );
136
137    binary_erosion.add_note("Shrinks white regions in binary images");
138    binary_erosion.add_note("Useful for separating connected objects");
139
140    module.add_function(binary_erosion);
141
142    // Distance transform documentation
143    let mut distance_transform = FunctionDoc::new(
144        "distance_transform_edt",
145        "pub fn distance_transform_edt(input: &ArrayD<bool>) -> ArrayD<f64>",
146        "Compute Euclidean distance transform using optimized algorithm",
147        "ArrayD<f64> - Distance transform",
148    );
149
150    distance_transform.add_parameter(Parameter::required(
151        "_input",
152        "&ArrayD<bool>",
153        "Input binary array",
154    ));
155
156    distance_transform.add_example(
157        r#"use scirs2_ndimage::morphology::distance_transform_edt;
158use scirs2_core::ndarray::Array2;
159
160let binary_image = Array2::from_elem((100, 100), false);
161let distances = distance_transform_edt(&binary_image);
162// Each pixel contains distance to nearest background pixel"#,
163    );
164
165    distance_transform
166        .add_note("Uses Felzenszwalb & Huttenlocher separable algorithm for O(n) performance");
167    distance_transform.add_note("Supports arbitrary dimensions");
168
169    module.add_function(distance_transform);
170
171    // Module examples
172    module.add_example("Object size analysis");
173    module.add_example("Shape decomposition");
174    module.add_example("Skeletonization");
175
176    module
177}
178
179/// Build documentation for the Interpolation module
180pub fn build_interpolation_documentation() -> ModuleDoc {
181    let mut module = ModuleDoc::new(
182        "Interpolation",
183        "Geometric transformations and interpolation operations",
184    );
185
186    // Affine transform documentation
187    let mut affine_transform = FunctionDoc::new(
188        "affine_transform",
189        "pub fn affine_transform<T>(input: &ArrayD<T>, matrix: &Array2<f64>) -> ArrayD<T>",
190        "Apply affine transformation to n-dimensional array",
191        "ArrayD<T> - Transformed array",
192    );
193
194    affine_transform.add_parameter(Parameter::required(
195        "_input",
196        "&ArrayD<T>",
197        "Input array to transform",
198    ));
199    affine_transform.add_parameter(Parameter::required(
200        "matrix",
201        "&Array2<f64>",
202        "Affine transformation matrix",
203    ));
204
205    affine_transform.add_example(
206        r#"use scirs2_ndimage::interpolation::affine_transform;
207use scirs2_core::ndarray::{Array2, array};
208
209let image = Array2::from_elem((50, 50), 1.0f64);
210let rotation_matrix = array![[0.866, -0.5], [0.5, 0.866]]; // 30 degree rotation
211let rotated = affine_transform(&image, &rotation_matrix);"#,
212    );
213
214    affine_transform.add_note("Supports rotation, scaling, shearing, and translation");
215    affine_transform.add_note("Uses spline interpolation for high quality results");
216
217    module.add_function(affine_transform);
218
219    // Module examples
220    module.add_example("Image registration");
221    module.add_example("Geometric correction");
222    module.add_example("Multi-resolution analysis");
223
224    module
225}
226
227/// Build documentation for the Measurements module
228pub fn build_measurements_documentation() -> ModuleDoc {
229    let mut module = ModuleDoc::new(
230        "Measurements",
231        "Statistical measurements and region analysis",
232    );
233
234    // Center of mass documentation
235    let mut center_of_mass = FunctionDoc::new(
236        "center_of_mass",
237        "pub fn center_of_mass<T>(input: &ArrayD<T>) -> Vec<f64>",
238        "Calculate center of mass of n-dimensional array",
239        "Vec<f64> - Center of mass coordinates",
240    );
241
242    center_of_mass.add_parameter(Parameter::required("_input", "&ArrayD<T>", "Input array"));
243
244    center_of_mass.add_example(
245        r#"use scirs2_ndimage::measurements::center_of_mass;
246use scirs2_core::ndarray::Array2;
247
248let image = Array2::from_elem((100, 100), 1.0f64);
249let com = center_of_mass(&image);
250println!("Center of mass: {:?}", com);"#,
251    );
252
253    center_of_mass.add_note("Works with any numeric type");
254    center_of_mass.add_note("Returns coordinates in array index order");
255
256    module.add_function(center_of_mass);
257
258    // Module examples
259    module.add_example("Object property analysis");
260    module.add_example("Region statistics");
261    module.add_example("Feature extraction");
262
263    module
264}
265
266/// Helper function to add common filter functions to a module
267pub fn add_common_filter_functions(module: &mut ModuleDoc) {
268    // Add sobel filter
269    let mut sobel_filter = FunctionDoc::new(
270        "sobel_filter",
271        "pub fn sobel_filter<T>(input: &ArrayD<T>) -> ArrayD<T>",
272        "Apply Sobel edge detection filter",
273        "ArrayD<T> - Edge-detected array",
274    );
275
276    sobel_filter.add_parameter(Parameter::required(
277        "_input",
278        "&ArrayD<T>",
279        "Input n-dimensional array",
280    ));
281
282    sobel_filter.add_example(
283        r#"use scirs2_ndimage::filters::sobel_filter;
284use scirs2_core::ndarray::Array2;
285
286let image = Array2::from_elem((100, 100), 1.0f64);
287let edges = sobel_filter(&image);"#,
288    );
289
290    sobel_filter.add_note("Detects edges using Sobel operators");
291    sobel_filter.add_note("Returns magnitude of gradient");
292
293    module.add_function(sobel_filter);
294
295    // Add laplacian filter
296    let mut laplacian_filter = FunctionDoc::new(
297        "laplacian_filter",
298        "pub fn laplacian_filter<T>(input: &ArrayD<T>) -> ArrayD<T>",
299        "Apply Laplacian edge detection filter",
300        "ArrayD<T> - Edge-detected array",
301    );
302
303    laplacian_filter.add_parameter(Parameter::required(
304        "_input",
305        "&ArrayD<T>",
306        "Input n-dimensional array",
307    ));
308
309    laplacian_filter.add_example(
310        r#"use scirs2_ndimage::filters::laplacian_filter;
311use scirs2_core::ndarray::Array2;
312
313let image = Array2::from_elem((100, 100), 1.0f64);
314let edges = laplacian_filter(&image);"#,
315    );
316
317    laplacian_filter.add_note("Uses second derivative for edge detection");
318    laplacian_filter.add_note("More sensitive to noise than Sobel");
319
320    module.add_function(laplacian_filter);
321}
322
323/// Helper function to add common morphology functions to a module
324pub fn add_common_morphology_functions(module: &mut ModuleDoc) {
325    // Add binary dilation
326    let mut binary_dilation = FunctionDoc::new(
327        "binary_dilation",
328        "pub fn binary_dilation(input: &ArrayD<bool>, structure: &ArrayD<bool>) -> ArrayD<bool>",
329        "Perform binary dilation operation",
330        "ArrayD<bool> - Dilated binary array",
331    );
332
333    binary_dilation.add_parameter(Parameter::required(
334        "_input",
335        "&ArrayD<bool>",
336        "Input binary array",
337    ));
338    binary_dilation.add_parameter(Parameter::required(
339        "structure",
340        "&ArrayD<bool>",
341        "Structuring element",
342    ));
343
344    binary_dilation.add_example(
345        r#"use scirs2_ndimage::morphology::binary_dilation;
346use scirs2_core::ndarray::Array2;
347
348let binary_image = Array2::from_elem((10, 10), true);
349let structure = Array2::from_elem((3, 3), true);
350let dilated = binary_dilation(&binary_image, &structure);"#,
351    );
352
353    binary_dilation.add_note("Expands white regions in binary images");
354    binary_dilation.add_note("Useful for connecting nearby objects");
355
356    module.add_function(binary_dilation);
357}
358
359#[cfg(test)]
360mod tests {
361    use super::*;
362
363    #[test]
364    fn test_filters_documentation() {
365        let filters_doc = build_filters_documentation();
366        assert_eq!(filters_doc.name, "Filters");
367        assert!(!filters_doc.functions.is_empty());
368        assert!(!filters_doc.examples.is_empty());
369
370        // Check that Gaussian filter is documented
371        let gaussian = filters_doc
372            .functions
373            .iter()
374            .find(|f| f.name == "gaussian_filter");
375        assert!(gaussian.is_some());
376
377        let gaussian = gaussian.expect("Operation failed");
378        assert_eq!(gaussian.parameters.len(), 2);
379        assert!(!gaussian.examples.is_empty());
380        assert!(!gaussian.notes.is_empty());
381    }
382
383    #[test]
384    fn test_morphology_documentation() {
385        let morphology_doc = build_morphology_documentation();
386        assert_eq!(morphology_doc.name, "Morphology");
387        assert!(!morphology_doc.functions.is_empty());
388
389        // Check that binary erosion is documented
390        let erosion = morphology_doc
391            .functions
392            .iter()
393            .find(|f| f.name == "binary_erosion");
394        assert!(erosion.is_some());
395
396        let erosion = erosion.expect("Operation failed");
397        assert_eq!(erosion.parameters.len(), 2);
398    }
399
400    #[test]
401    fn test_interpolation_documentation() {
402        let interpolation_doc = build_interpolation_documentation();
403        assert_eq!(interpolation_doc.name, "Interpolation");
404        assert!(!interpolation_doc.functions.is_empty());
405
406        // Check that affine transform is documented
407        let affine = interpolation_doc
408            .functions
409            .iter()
410            .find(|f| f.name == "affine_transform");
411        assert!(affine.is_some());
412    }
413
414    #[test]
415    fn test_measurements_documentation() {
416        let measurements_doc = build_measurements_documentation();
417        assert_eq!(measurements_doc.name, "Measurements");
418        assert!(!measurements_doc.functions.is_empty());
419
420        // Check that center of mass is documented
421        let com = measurements_doc
422            .functions
423            .iter()
424            .find(|f| f.name == "center_of_mass");
425        assert!(com.is_some());
426    }
427
428    #[test]
429    fn test_module_documentation_builder() {
430        let mut site = DocumentationSite::new();
431        let result = site.build_module_documentation();
432
433        assert!(result.is_ok());
434        assert_eq!(site.modules.len(), 4);
435
436        // Check all expected modules are present
437        let module_names: Vec<_> = site.modules.iter().map(|m| &m.name).collect();
438        assert!(module_names.contains(&&"Filters".to_string()));
439        assert!(module_names.contains(&&"Morphology".to_string()));
440        assert!(module_names.contains(&&"Interpolation".to_string()));
441        assert!(module_names.contains(&&"Measurements".to_string()));
442    }
443}