• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 17043803691

18 Aug 2025 02:38PM UTC coverage: 88.339%. First build
17043803691

Pull #1059

github

web-flow
Merge 5d8c31cc7 into db8685e5e
Pull Request #1059: Multi_band_gdal_source

3198 of 3544 new or added lines in 21 files covered. (90.24%)

116507 of 131886 relevant lines covered (88.34%)

477654.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.17
/operators/src/util/test.rs
1
use std::path::Path;
2

3
use super::Result;
4
use crate::{
5
    engine::{ExecutionContext, QueryContext, RasterOperator, WorkflowOperatorPath},
6
    util::gdal::gdal_open_dataset,
7
};
8
use futures::StreamExt;
9
use gdal::raster::GdalType;
10
use geoengine_datatypes::{
11
    primitives::{CacheHint, RasterQueryRectangle, TimeInterval},
12
    raster::{
13
        GeoTransform, Grid, GridOrEmpty, GridShape2D, MapElements, MaskedGrid, Pixel, RasterTile2D,
14
        TilingSpatialGridDefinition,
15
    },
16
    util::test::assert_eq_two_list_of_tiles_u8,
17
};
18

19
pub async fn raster_operator_to_list_of_tiles_u8<E: ExecutionContext, Q: QueryContext>(
6✔
20
    exe_ctx: &E,
6✔
21
    query_ctx: &Q,
6✔
22
    operator: Box<dyn RasterOperator>,
6✔
23
    query_rectangle: RasterQueryRectangle,
6✔
24
) -> Result<Vec<RasterTile2D<u8>>> {
6✔
25
    let initialized_operator = operator
6✔
26
        .initialize(WorkflowOperatorPath::initialize_root(), exe_ctx)
6✔
27
        .await?;
6✔
28
    let query_processor = initialized_operator.query_processor()?.get_u8().ok_or(
6✔
29
        crate::error::Error::MustNotHappen {
6✔
30
            message: "Operator does not produce u8 while this function requires it".to_owned(),
6✔
31
        },
6✔
32
    )?;
×
33

34
    let res = query_processor
6✔
35
        .raster_query(query_rectangle, query_ctx)
6✔
36
        .await?
6✔
37
        .collect::<Vec<_>>()
6✔
38
        .await;
6✔
39

40
    let res = res.into_iter().collect::<Result<Vec<_>, _>>()?;
6✔
41

42
    Ok(res)
6✔
43
}
6✔
44

45
/// Compares the output of a raster operators and a list of tiles and panics with a message if they are not equal
46
///
47
/// # Panics
48
///
49
/// If there are tiles that are not equal
50
pub async fn assert_eq_raster_operator_res_and_list_of_tiles_u8<
3✔
51
    E: ExecutionContext,
3✔
52
    Q: QueryContext,
3✔
53
>(
3✔
54
    exe_ctx: &E,
3✔
55
    query_ctx: &Q,
3✔
56
    operator: Box<dyn RasterOperator>,
3✔
57
    query_rectangle: RasterQueryRectangle,
3✔
58
    compare_cache_hint: bool,
3✔
59
    list_of_tiles: &[RasterTile2D<u8>],
3✔
60
) {
3✔
61
    let res_a = raster_operator_to_list_of_tiles_u8(exe_ctx, query_ctx, operator, query_rectangle)
3✔
62
        .await
3✔
63
        .expect("raster operator to list failed!");
3✔
64

65
    assert_eq_two_list_of_tiles_u8(&res_a, list_of_tiles, compare_cache_hint);
3✔
66
}
3✔
67

68
/// Compares the output of two raster operators and panics with a message if they are not equal
69
///
70
/// # Panics
71
///
72
/// If there are tiles that are not equal
73
pub async fn assert_eq_two_raster_operator_res_u8<E: ExecutionContext, Q: QueryContext>(
3✔
74
    exe_ctx: &E,
3✔
75
    query_ctx: &Q,
3✔
76
    operator_a: Box<dyn RasterOperator>,
3✔
77
    operator_b: Box<dyn RasterOperator>,
3✔
78
    query_rectangle: RasterQueryRectangle,
3✔
79
    compare_cache_hint: bool,
3✔
80
) {
3✔
81
    let res_a = raster_operator_to_list_of_tiles_u8(
3✔
82
        exe_ctx,
3✔
83
        query_ctx,
3✔
84
        operator_a,
3✔
85
        query_rectangle.clone(),
3✔
86
    )
3✔
87
    .await
3✔
88
    .expect("raster operator to list failed for operator_a!");
3✔
89

90
    assert_eq_raster_operator_res_and_list_of_tiles_u8(
3✔
91
        exe_ctx,
3✔
92
        query_ctx,
3✔
93
        operator_b,
3✔
94
        query_rectangle,
3✔
95
        compare_cache_hint,
3✔
96
        &res_a,
3✔
97
    )
3✔
98
    .await;
3✔
99
}
3✔
100

101
/// Reads a single raster tile from a single file and returns it as a `RasterTile2D<u8>`.
102
/// This assumes that the file actually contains exactly one geoengine tile according to the spatial grid definition.
103
pub fn raster_tile_from_file<T: Pixel + GdalType>(
224✔
104
    file_path: &Path,
224✔
105
    tiling_spatial_grid: TilingSpatialGridDefinition,
224✔
106
    time: TimeInterval,
224✔
107
    band: u32,
224✔
108
) -> Result<RasterTile2D<T>> {
224✔
109
    let ds = gdal_open_dataset(file_path)?;
224✔
110

111
    let gf: GeoTransform = ds.geo_transform()?.into();
224✔
112

113
    let tiling_strategy = tiling_spatial_grid.generate_data_tiling_strategy();
224✔
114

115
    let tiling_geo_transform = tiling_spatial_grid.tiling_geo_transform();
224✔
116
    let tile_origin_pixel_idx =
224✔
117
        tiling_geo_transform.coordinate_to_grid_idx_2d(gf.origin_coordinate);
224✔
118
    let tile_position = tiling_strategy.pixel_idx_to_tile_idx(tile_origin_pixel_idx);
224✔
119

120
    let rasterband = ds.rasterband(1)?;
224✔
121

122
    let out_shape: GridShape2D = GridShape2D::new([ds.raster_size().0, ds.raster_size().1]);
224✔
123

124
    let buffer = rasterband.read_as::<T>(
224✔
125
        (0, 0),
224✔
126
        ds.raster_size(),
224✔
127
        ds.raster_size(), // or: tile_size_in_pixels
224✔
128
        None,
224✔
NEW
129
    )?;
×
130

131
    let (_, buffer_data) = buffer.into_shape_and_vec();
224✔
132
    let data_grid = Grid::new(out_shape, buffer_data)?;
224✔
133

134
    let mask_band = rasterband.open_mask_band()?;
224✔
135
    let mask_buffer = mask_band.read_as::<u8>(
224✔
136
        (0, 0),
224✔
137
        ds.raster_size(),
224✔
138
        ds.raster_size(), // or: tile_size_in_pixels
224✔
139
        None,
224✔
NEW
140
    )?;
×
141
    let (_, mask_buffer_data) = mask_buffer.into_shape_and_vec();
224✔
142
    let mask_grid = Grid::new(out_shape, mask_buffer_data)?.map_elements(|p: u8| p > 0);
58,720,256✔
143

144
    let masked_grid = MaskedGrid::new(data_grid, mask_grid)?;
224✔
145

146
    Ok(RasterTile2D::<T>::new(
224✔
147
        time,
224✔
148
        tile_position,
224✔
149
        band,
224✔
150
        tiling_geo_transform,
224✔
151
        GridOrEmpty::from(masked_grid),
224✔
152
        CacheHint::default(),
224✔
153
    ))
224✔
154
}
224✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc