# 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
# 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)