use scirs2_core::ndarray::{Array, ArrayBase, IxDyn, OwnedRepr};
use scirs2_core::random::{Rng, RngExt};
use scirs2_io::compression::ndarray::{
compare_compression_algorithms, compress_array, compress_array_chunked, decompress_array,
decompress_array_chunked,
};
use scirs2_io::compression::{
algorithm_info, compress_data, compress_file, decompress_data, decompress_file,
CompressionAlgorithm,
};
use std::fs::File;
use std::io::Write;
#[allow(dead_code)]
fn main() {
if let Err(e) = basic_compression_example() {
println!("Basic compression example failed: {}", e);
}
if let Err(e) = file_compression_example() {
println!("File compression example failed: {}", e);
}
if let Err(e) = array_compression_example() {
println!("Array compression example failed: {}", e);
}
if let Err(e) = chunked_array_compression_example() {
println!("Chunked array compression example failed: {}", e);
}
if let Err(e) = compare_algorithms() {
println!("Compression algorithm comparison failed: {}", e);
}
println!("Compression examples completed!");
}
#[allow(dead_code)]
fn basic_compression_example() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== Basic Compression Example ===");
let original_data =
b"This is a sample string that will be compressed using different algorithms.
Scientific data often contains patterns and redundancy that can be effectively compressed.
Let's see how well different compression algorithms perform on this text.";
for algorithm in &[
CompressionAlgorithm::Gzip,
CompressionAlgorithm::Zstd,
CompressionAlgorithm::Lz4,
CompressionAlgorithm::Bzip2,
] {
let info = algorithm_info(*algorithm);
println!("\nCompressing with {}", info.name);
let compressed = compress_data(original_data, *algorithm, None)?;
let ratio = original_data.len() as f64 / compressed.len() as f64;
println!(" Original size: {} bytes", original_data.len());
println!(" Compressed size: {} bytes", compressed.len());
println!(" Compression ratio: {:.2}x", ratio);
let decompressed = decompress_data(&compressed, *algorithm)?;
assert_eq!(decompressed, original_data);
println!(" Decompression verified successfully");
}
Ok(())
}
#[allow(dead_code)]
fn file_compression_example() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== File Compression Example ===");
let test_file_path = "test_data.txt";
let mut test_file = File::create(test_file_path)?;
for i in 0..1000 {
writeln!(
test_file,
"Line {} with some repeated content for compression testing",
i
)?;
}
test_file.flush()?;
for algorithm in &[
CompressionAlgorithm::Gzip,
CompressionAlgorithm::Zstd,
CompressionAlgorithm::Lz4,
CompressionAlgorithm::Bzip2,
] {
let output_path = compress_file(test_file_path, None, *algorithm, Some(6))?;
println!("Compressed with {}: {}", algorithm.extension(), output_path);
let decompressed_path = decompress_file(&output_path, None, Some(*algorithm))?;
println!("Decompressed to: {}", decompressed_path);
std::fs::remove_file(output_path)?;
std::fs::remove_file(decompressed_path)?;
}
std::fs::remove_file(test_file_path)?;
Ok(())
}
#[allow(dead_code)]
fn array_compression_example() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== Array Compression Example ===");
let shape = vec![100, 100, 10];
let mut data = Vec::with_capacity(shape.iter().product());
for i in 0..shape[0] {
for j in 0..shape[1] {
for k in 0..shape[2] {
data.push((i as f64).sin() + (j as f64).cos() + (k as f64 / 5.0).sin());
}
}
}
let array = Array::from_shape_vec(IxDyn(&shape), data)?;
println!("Created array with shape: {:?}", array.shape());
for algorithm in &[
CompressionAlgorithm::Gzip,
CompressionAlgorithm::Zstd,
CompressionAlgorithm::Lz4,
CompressionAlgorithm::Bzip2,
] {
let extension = algorithm.extension();
let output_path = format!("array_compressed.{extension}");
compress_array(&output_path, &array, *algorithm, Some(6), None)?;
let file_size = std::fs::metadata(&output_path)?.len();
let original_size = array.len() * std::mem::size_of::<f64>();
println!(
"Compressed with {}: {:.2}MB → {:.2}MB (ratio: {:.2}x)",
algorithm.extension(),
original_size as f64 / 1024.0 / 1024.0,
file_size as f64 / 1024.0 / 1024.0,
original_size as f64 / file_size as f64
);
let decompressed_array: ArrayBase<OwnedRepr<f64>, IxDyn> = decompress_array(&output_path)?;
assert_eq!(decompressed_array.shape(), array.shape());
let indices_to_check = [(0, 0, 0), (50, 50, 5), (99, 99, 9)];
for &(i, j, k) in &indices_to_check {
let original = array[[i, j, k]];
let decompressed = decompressed_array[[i, j, k]];
assert!((original - decompressed).abs() < 1e-10);
}
println!(" Decompression verified successfully");
std::fs::remove_file(output_path)?;
}
Ok(())
}
#[allow(dead_code)]
fn chunked_array_compression_example() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== Chunked Array Compression Example ===");
let shape = vec![200, 200, 20]; let mut data = Vec::with_capacity(shape.iter().product());
for i in 0..shape[0] {
for j in 0..shape[1] {
for k in 0..shape[2] {
data.push(
(i as f64 / 20.0).sin() + (j as f64 / 20.0).cos() + (k as f64 / 5.0).sin(),
);
}
}
}
let array = Array::from_shape_vec(IxDyn(&shape), data)?;
println!("Created large array with shape: {:?}", array.shape());
println!("Number of elements: {}", array.len());
println!(
"Memory size: {:.2} MB",
(array.len() * std::mem::size_of::<f64>()) as f64 / 1024.0 / 1024.0
);
let output_path = "array_compressed_chunked.zst";
let chunk_size = 100_000;
println!("Compressing in chunks of {} elements", chunk_size);
compress_array_chunked(
output_path,
&array,
CompressionAlgorithm::Zstd,
Some(6),
chunk_size,
)?;
let file_size = std::fs::metadata(output_path)?.len();
let original_size = array.len() * std::mem::size_of::<f64>();
println!(
"Compressed with chunked ZSTD: {:.2}MB → {:.2}MB (ratio: {:.2}x)",
original_size as f64 / 1024.0 / 1024.0,
file_size as f64 / 1024.0 / 1024.0,
original_size as f64 / file_size as f64
);
let (decompressed_array, metadata) = decompress_array_chunked::<_, f64>(output_path)?;
println!("Decompressed with metadata:");
println!(" Shape: {:?}", metadata.shape);
println!(" Element type: {}", metadata.dtype);
println!(" Compression ratio: {:.2}x", metadata.compression_ratio);
println!(" Additional info: {:?}", metadata.additional_metadata);
assert_eq!(decompressed_array.shape(), array.shape());
let indices_to_check = [(0, 0, 0), (100, 100, 10), (199, 199, 19)];
for &(i, j, k) in &indices_to_check {
let original = array[[i, j, k]];
let decompressed = decompressed_array[[i, j, k]];
assert!((original - decompressed).abs() < 1e-10);
}
println!(" Chunked decompression verified successfully");
std::fs::remove_file(output_path)?;
Ok(())
}
#[allow(dead_code)]
fn compare_algorithms() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== Compression Algorithm Comparison ===");
let shape = vec![100, 100];
let patterns = vec![
("Sine waves", create_sine_wave_array(&shape)),
("Random noise", create_random_array(&shape)),
("Mixed data", create_mixed_array(&shape)),
];
let algorithms = vec![
CompressionAlgorithm::Gzip,
CompressionAlgorithm::Zstd,
CompressionAlgorithm::Lz4,
CompressionAlgorithm::Bzip2,
];
for (pattern_name, array) in patterns {
println!("\nPattern: {}", pattern_name);
let results = compare_compression_algorithms(&array, &algorithms, Some(6))?;
println!(
" {:<10} | {:<12} | {:<12}",
"Algorithm", "Ratio", "Size (KB)"
);
println!(" {:-<10} | {:-<12} | {:-<12}", "", "", "");
for (algorithm, ratio, size) in results {
println!(
" {:<10} | {:<12.2} | {:<12.2}",
format!("{:?}", algorithm),
ratio,
size as f64 / 1024.0
);
}
}
Ok(())
}
#[allow(dead_code)]
fn create_sine_wave_array(shape: &[usize]) -> Array<f64, IxDyn> {
let mut data = Vec::with_capacity(shape.iter().product());
for i in 0..shape[0] {
for j in 0..shape[1] {
data.push((i as f64 / 10.0).sin() * (j as f64 / 15.0).cos());
}
}
Array::from_shape_vec(IxDyn(shape), data).expect("Operation failed")
}
#[allow(dead_code)]
fn create_random_array(shape: &[usize]) -> Array<f64, IxDyn> {
let mut data = Vec::with_capacity(shape.iter().product());
let mut rng = scirs2_core::random::rng();
for _ in 0..shape[0] {
for _ in 0..shape[1] {
data.push(rng.random_range(-1.0..1.0));
}
}
Array::from_shape_vec(IxDyn(shape), data).expect("Operation failed")
}
#[allow(dead_code)]
fn create_mixed_array(shape: &[usize]) -> Array<f64, IxDyn> {
let mut data = Vec::with_capacity(shape.iter().product());
let mut rng = scirs2_core::random::rng();
for i in 0..shape[0] {
for j in 0..shape[1] {
if i < shape[0] / 2 {
data.push((i as f64 / 20.0).sin() + (j as f64 / 20.0).cos());
} else {
data.push(rng.random_range(-1.0..1.0));
}
}
}
Array::from_shape_vec(IxDyn(shape), data).expect("Operation failed")
}