use crate::core_types::RasterType;
use crate::gdal_utils::{open_for_update, raster_from_size, write_bands_to_file};
use crate::metadata::RasterMetadata;
use crate::types::{BlockSize, GeoTransform, Overlap, RasterDataShape, ReadWindow};
use gdal::raster::Buffer;
use log::debug;
use ndarray::{s, Array2, Array3, Array4, Axis};
use std::path::{Path, PathBuf};
impl<U> RasterBlock<U>
where
U: RasterType,
{
pub fn into_frc(&self, data: &Array2<U>) -> Array3<U> {
let n_features = data.shape()[1];
let n_rows = self.read_window.size.rows as usize - self.overlap.top - self.overlap.bottom;
let n_cols = self.read_window.size.cols as usize; let mut result: Array3<U> = Array3::zeros((n_features, n_rows, n_cols));
for n_feature in 0..n_features {
let feature = data.slice(s![.., n_feature]);
let feature = feature.to_shape((n_rows, n_cols)).unwrap();
feature.assign_to(result.slice_mut(s![n_feature, .., ..]))
}
result
}
pub fn write_samples_feature<T>(&self, data: &Array2<T>, file_name: &PathBuf, na: T)
where
T: RasterType,
{
let n_bands = data.shape()[1] as isize;
let block_geotransform = self.geo_transform;
let epsg_code = self.epsg_code;
let size_x = self.read_window.size.cols as usize - self.overlap.left - self.overlap.right;
let size_y = self.read_window.size.rows as usize - self.overlap.top - self.overlap.bottom;
let block_size: BlockSize = BlockSize {
rows: size_y,
cols: size_x,
};
let na = T::from(na).unwrap();
raster_from_size::<T>(
file_name,
block_geotransform,
epsg_code as u32,
block_size,
n_bands,
na,
);
let out_ds = open_for_update(Path::new(&file_name));
for feature in 1..n_bands + 1 {
let mut out_band = out_ds.rasterband(feature as usize).unwrap();
let out_data = data.slice(s![.., feature - 1]);
let out_data_u8: Vec<T> = out_data.into_iter().map(|v| *v as T).collect();
let mut data_buffer = Buffer::new((block_size.cols, block_size.rows), out_data_u8);
out_band
.write((0, 0), (size_x, size_y), &mut data_buffer)
.unwrap();
}
}
pub fn write3<T>(&self, data: Array3<T>, out_fn: &PathBuf)
where
T: RasterType,
{
debug!("Writing block {:?}", out_fn);
let block_geotransform = self.geo_transform;
let block_size: BlockSize = BlockSize {
rows: self.read_window.size.rows as usize,
cols: self.read_window.size.cols as usize,
};
let n_bands = data.shape()[0] as isize;
let epsg_code = self.epsg_code;
let na_value = T::zero();
raster_from_size::<T>(
out_fn,
block_geotransform,
epsg_code.try_into().unwrap(),
block_size,
n_bands,
na_value,
);
let out_ds = open_for_update(out_fn);
write_bands_to_file(&out_ds, data.view(), (0, 0), (block_size.cols, block_size.rows));
}
pub fn write_time_step_blocks<T>(
&self,
data: &Array4<T>,
tmp_file: &Path,
file_stem: &str,
bid: usize,
) -> Vec<PathBuf>
where
T: RasterType,
{
let mut block_fns: Vec<PathBuf> = Vec::new();
for (tid, result3) in data.axis_iter(Axis(0)).enumerate() {
let block_fn = tmp_file.with_file_name(format!("{}_{}_{}.tif", file_stem, tid, bid));
self.write3(result3.to_owned(), &block_fn);
block_fns.push(block_fn);
}
block_fns
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct RasterBlock<U>
where
U: RasterType,
{
pub block_index: usize,
pub read_window: ReadWindow,
pub overlap_size: usize,
pub geo_transform: GeoTransform,
pub overlap: Overlap,
pub shape: RasterDataShape,
pub epsg_code: usize,
pub raster_metadata: RasterMetadata<U>,
}