read-vk6 0.1.0

Fast and simple reader for VK6/VK7 files from Keyence confocal laser scanning microscopes
Documentation
# read-vk6

A fast and simple Rust library for reading VK6/VK7 files from Keyence confocal laser scanning microscopes (VK-X series), such as the VK-X1000 and VK-X3000.

This library extracts:
- **Height maps** (surface topography in micrometers)
- **RGB optical images** (when available)
- **Comprehensive metadata** (75+ fields including timestamp, lens info, measurement settings, camera parameters, etc.)

Inspired by the excellent [Surfalize](https://github.com/fredericjs/surfalize) Python library.

## Features

- ✨ Simple API: read a VK6 file in one function call
- 🚀 Fast native Rust implementation
- 📊 Returns data as `ndarray` arrays ready for scientific computing
- 🎨 Optional RGB image extraction
- 📝 Comprehensive metadata extraction (75+ measurement and camera settings fields)
- 🔬 Preserves all measurement conditions from the original file

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
read-vk6 = "0.1.0"
```

## Usage

```rust
use read_vk6::{read_vk6, RawSurface};
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Read VK6 file with RGB image
    let surface = read_vk6(Path::new("sample.vk6"), true)?;
    
    // Access height map (µm)
    println!("Height map shape: {:?}", surface.height.dim());
    println!("Step X: {} µm/pixel", surface.step_x);
    println!("Step Y: {} µm/pixel", surface.step_y);
    
    // Access metadata
    if let Some(title) = &surface.metadata.title {
        println!("Title: {}", title);
    }
    if let Some(timestamp) = &surface.metadata.timestamp {
        println!("Timestamp: {}", timestamp);
    }
    
    // Access RGB image if available
    if let Some(rgb) = &surface.rgb_image {
        println!("RGB image shape: {:?}", rgb.dim());
    }
    
    Ok(())
}
```

### Read without RGB image

If you only need the height map and want to skip image processing:

```rust
let surface = read_vk6(Path::new("sample.vk6"), false)?;
```

## Data Structure

The `RawSurface` struct contains:

```rust
pub struct RawSurface {
    pub height: Array2<f64>,          // Height map in micrometers (rows, cols)
    pub step_x: f64,                  // µm per pixel in X direction
    pub step_y: f64,                  // µm per pixel in Y direction
    pub metadata: Metadata,           // Comprehensive file metadata
    pub rgb_image: Option<Array3<u8>>, // RGB image (rows, cols, 3) if available
}
```

### Metadata Fields

The `Metadata` struct contains 75+ fields extracted from the VK6 file, including:

**Basic Information:**
- `title`, `lens_name`, `timestamp`, `diff_from_utc`

**Optical Settings:**
- `optical_zoom`, `objective_magnification`, `lens_id`, `num_aperture`
- `nd_filter`, `light_filter_type`, `head_type`

**Measurement Settings:**
- `run_mode`, `peak_mode`, `speed`, `distance`, `pitch`
- `sharpening_level`, `plane_compensation`

**Camera & PMT Settings:**
- `pmt_gain_mode`, `pmt_gain`, `pmt_gain_2`, `pmt_offset`
- `camera_gain`, `shutter_speed_mode`, `shutter_speed`
- `white_balance_mode`, `white_balance_red`, `white_balance_blue`

**Resolution & Units:**
- `x_length_per_pixel`, `y_length_per_pixel`, `z_length_per_digit` (in picometers)
- `xy_length_unit`, `z_length_unit`, `xy_decimal_place`, `z_decimal_place`
- `height_effective_bit_depth`, `light_effective_bit_depth`

**Image Processing:**
- `gamma`, `gamma_reverse`, `gamma_correction_offset`
- `light_lut_mode` and LUT parameters (`light_lut_in0-4`, `light_lut_out0-4`)
- `img_attributes`, `color_composite_mode`, `img_layer_number`

**And many more...** See `src/types.rs` for the complete list.

Use the `summary()` method for a quick overview:
```rust
println!("{}", surface.metadata.summary());
```

**Example:** See `examples/show_metadata.rs` for a complete demonstration of all metadata fields:
```bash
cargo run --example show_metadata
```

## Example: Export to NumPy and PNG

See `tests/integration.rs` for a complete example that:
1. Reads a VK6 file
2. Exports the height map as a NumPy `.npy` file
3. Exports the RGB image as a PNG

Run the test:

```bash
# Place your VK6 file at tests/data/sample.vk6
cargo test --test integration -- --nocapture
```

This will create:
- `tests/out/height.npy` - Height map array
- `tests/out/rgb.png` - RGB optical image

## Visualizing Results with Streamlit

A simple Streamlit app is included to visualize the extracted data:

```bash
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Place your VK6 file at tests/data/sample.vk6
cargo test --test integration -- --nocapture

# Run the viewer
uv run streamlit run streamlit_app.py
```

The app will display:
- Height map with colorbar
- RGB optical image

## File Format Support

Currently supports:
- ✅ VK6 files (tested)
- 🔄 VK7 files (uses same internal format, should work)

The library reads the embedded `Vk4File` from the ZIP archive and parses:
- Measurement conditions
- Height layer (16-bit or 32-bit depth)
- Color/Light layer (RGB image)
- String data (title, lens)

## Dependencies

- `ndarray` - Multi-dimensional arrays
- `byteorder` - Binary data parsing
- `zip` - ZIP archive handling
- `chrono` - Timestamp parsing
- `thiserror` - Error handling

## Contributing

Contributions welcome! This library was created to provide a Rust alternative for reading Keyence microscope files. If you encounter issues with specific VK6/VK7 files or have suggestions, please open an issue.

## License

MIT License. See [LICENSE-MIT](LICENSE-MIT) for details.

## Acknowledgments

- Inspired by [Surfalize]https://github.com/fredericjs/surfalize by Frederic Schell
- Format information based on reverse engineering of VK6 file structure

## See Also

- [Keyence VK-X Series]https://www.keyence.com/products/microscope/laser-microscope/vk-x1000/
- [Surfalize Python library]https://github.com/fredericjs/surfalize