use std::env;
use std::path::PathBuf;
use polars::prelude::*;
use std::error::Error as StdError;
use variogram::*;
use kriging::*;
use raster::*;
mod variogram;
mod kriging;
mod raster;
fn main() -> Result<(), Box<dyn StdError>> {
let root_dir = env::var("CARGO_MANIFEST_DIR")?;
let mut csv_file_path = PathBuf::from(&root_dir);
csv_file_path.push("data/data_netatmo.csv");
let df = CsvReadOptions::default()
.with_infer_schema_length(None)
.with_has_header(true)
.try_into_reader_with_file_path(Some(csv_file_path.into()))?
.finish()?;
println!("{:?}", df);
let longitudes = df.column("lon")?.f64()?;
let latitudes = df.column("lat")?.f64()?;
let temps = df.column("temp_diff")?.f64()?;
let longitudes = longitudes.to_vec().into_iter().filter_map(|x| x).collect();
let latitudes = latitudes.to_vec().into_iter().filter_map(|x| x).collect();
let temps = temps.to_vec().into_iter().filter_map(|x| x).collect();
let empirical_variogram = EmpiricalVariogram::new(
&longitudes, &latitudes, &temps);
let max_x_data = empirical_variogram.get_max_distance();
let max_y_data = empirical_variogram.get_max_semivariance();
let mut variogram = Variogram::new(
0.0,
max_y_data,
max_x_data / 3.0,
VariogramModel::Spherical
);
println!("\nRunning gradient descent...");
variogram.fit(
&empirical_variogram,
1e-2,
1000,
1e-6
);
println!("\nFitted Parameters:");
println!("Nugget: {:.4}", variogram.nugget);
println!("Sill: {:.4}", variogram.sill);
println!("Range: {:.2}", variogram.range);
let mut semivariogram_file_path = PathBuf::from(&root_dir);
semivariogram_file_path.push("data/semivariogram.png");
plot(&variogram, &empirical_variogram, &semivariogram_file_path);
let known_coords: Vec<(f64, f64)> = longitudes
.into_iter()
.zip(latitudes)
.collect();
let known_values: Vec<f64> = temps;
let mut template_raster_file_path = PathBuf::from(&root_dir);
template_raster_file_path.push("data/svf.tif");
let prediction_points = read_raster_coords(&template_raster_file_path)?;
let initial_estimation_variogram = Variogram::new(
0.0, max_y_data, max_x_data / 3.0, VariogramModel::Spherical,
);
let gli_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("data/gli.tif");
let svf_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("data/svf.tif");
let drift = RasterDrift::new(&[gli_path.to_str().unwrap(), svf_path.to_str().unwrap()]);
let (predictions, variances) = universal_kriging(&known_coords, &known_values, &prediction_points, drift, initial_estimation_variogram);
let mut output_raster_file_path = PathBuf::from(&root_dir);
output_raster_file_path.push("data/interpolation.tif");
export_predictions_to_raster(
&template_raster_file_path,
&output_raster_file_path,
&predictions
)?;
let mut output_raster_file_path = PathBuf::from(&root_dir);
output_raster_file_path.push("data/variances.tif");
export_predictions_to_raster(
&template_raster_file_path,
&output_raster_file_path,
&variances
)?;
Ok(())
}