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

geo-engine / geoengine / 29338235936

14 Jul 2026 01:17PM UTC coverage: 87.769% (-0.005%) from 87.774%
29338235936

push

github

web-flow
fix: add resolution to python down/up sampling operators (#1199)

* fix: add resolution and outputOriginReference to python down/up sampling operators

- Added output_origin_reference support to Interpolation and Downsampling
- Fix duplicate 'fraction' branch bug in outputResolution parser
- Add Downsampling to RasterOperator dispatch
- Add websocket error logging in workflows.rs
- Add inspect_err on tile stream

* feat(backend): add Downsampling operator and Fraction type to API model

Also update www plugin to extract oneOf descriptions for operator parameter tables.

* chore(api-clients): regenerate OpenAPI spec, API clients, and docs

* remove commented-out assert

* fix: deduplicate Fraction1/Fraction2 in generated API clients

Remove variant-level doc comments from Fraction(Fraction) in both
InterpolationResolution and DownsamplingResolution enums. The
Fraction struct's own field docs already describe the data — the
context-specific descriptions ('Upscale factor' / 'Downscale factor')
caused the OpenAPI generator to create separate Fraction1 and Fraction2
classes for structurally identical allOf wrappers.

With identical allOf wrappers the generator now produces a single shared
Fraction1 (the tagged variant with the 'type: fraction' discriminator)
used by both enums.

* revert: remove non-essential changes from PR

- Revert websocket error logging (workflows.rs, websocket_stream.rs)
- Revert Jupyter notebook metadata changes (interpolation.ipynb)
- Revert unrelated TemporalRasterAggregation doc updates
- Revert auto-generated python types.md to_api_dict docs

These changes are not essential to the Downsampling feature.

* revert: non-essential docs improvements

Revert Interpolation.md description update and astro-openapi-plugin.ts
oneOf fallback — not essential to the Downsampling feature.

* revert: non-essential types.py changes

Revert SpatialResolution typed dict, assert deletion, and GeoTransform
docstring — not required for the Downsampli... (continued)

72 of 97 new or added lines in 5 files covered. (74.23%)

2 existing lines in 1 file now uncovered.

121729 of 138692 relevant lines covered (87.77%)

471993.26 hits per line

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

96.08
/geoengine/services/src/api/model/processing_graphs/mod.rs
1
#![allow(clippy::needless_for_each)] // TODO: remove when clippy is fixed for utoipa <https://github.com/juhaku/utoipa/issues/1420>
2

3
// use crate::api::model::processing_graphs::{
4
//     processing::{Expression, ExpressionParameters, RasterVectorJoin, RasterVectorJoinParameters},
5
//     source::{GdalSource, GdalSourceParameters, MockPointSource, MockPointSourceParameters},
6
// };
7
use geoengine_operators::{
8
    engine::{
9
        PlotOperator as OperatorsPlotOperator, RasterOperator as OperatorsRasterOperator,
10
        TypedOperator as OperatorsTypedOperator, VectorOperator as OperatorsVectorOperator,
11
    },
12
    mock::MockPointSource as OperatorsMockPointSource,
13
    plot::{Histogram as OperatorsHistogram, Statistics as OperatorsStatistics},
14
    processing::{
15
        BandFilter as OperatorsBandFilter, Downsampling as OperatorsDownsampling,
16
        Expression as OperatorsExpression, Interpolation as OperatorsInterpolation,
17
        RasterStacker as OperatorsRasterStacker,
18
        RasterTypeConversion as OperatorsRasterTypeConversion,
19
        RasterVectorJoin as OperatorsRasterVectorJoin, Reprojection as OperatorsReprojection,
20
        TemporalRasterAggregation as OperatorsTemporalRasterAggregation,
21
    },
22
    source::{
23
        GdalSource as OperatorsGdalSource, MultiBandGdalSource as OperatorsMultiBandGdalSource,
24
        OgrSource as OperatorsOgrSource,
25
    },
26
};
27
use serde::{Deserialize, Serialize};
28
use utoipa::{OpenApi, ToSchema};
29

30
mod macros;
31
mod parameters;
32
mod plots;
33
mod processing;
34
mod source;
35
mod source_parameters;
36

37
// TODO: avoid exporting them to outside of API module
38
#[cfg(test)]
39
pub(crate) use crate::api::model::processing_graphs::parameters::SpatialBoundsDerive;
40
pub(crate) use crate::api::model::processing_graphs::{
41
    plots::{Histogram, HistogramParameters, Statistics, StatisticsParameters},
42
    processing::{
43
        Aggregation, BandFilter, BandFilterParameters, BandsByNameOrIndex,
44
        DeriveOutRasterSpecsSource, Downsampling, DownsamplingMethod, DownsamplingParameters,
45
        DownsamplingResolution, Expression, ExpressionParameters, Interpolation,
46
        InterpolationMethod, InterpolationParameters, InterpolationResolution, RasterStacker,
47
        RasterStackerParameters, RasterTypeConversion, RasterTypeConversionParameters,
48
        RasterVectorJoin, RasterVectorJoinParameters, RenameBands, Reprojection,
49
        ReprojectionParameters, TemporalRasterAggregation, TemporalRasterAggregationParameters,
50
    },
51
    source::{
52
        GdalSource, GdalSourceParameters, MockPointSource, MockPointSourceParameters,
53
        MultiBandGdalSource, OgrSource, OgrSourceParameters,
54
    },
55
    source_parameters::{
56
        MultipleRasterOrSingleVectorOperator, MultipleRasterOrSingleVectorSource,
57
        MultipleRasterSources, SingleRasterOrVectorOperator, SingleRasterOrVectorSource,
58
        SingleRasterSource, SingleVectorMultipleRasterSources,
59
    },
60
};
61

62
/// Operator outputs are distinguished by their data type.
63
/// There are `raster`, `vector` and `plot` operators.
64
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
65
#[serde(tag = "type", content = "operator")]
66
pub enum TypedOperator {
67
    #[schema(title = "TypedVectorOperator")]
68
    Vector(VectorOperator),
69
    #[schema(title = "TypedRasterOperator")]
70
    Raster(RasterOperator),
71
    #[schema(title = "TypedPlotOperator")]
72
    Plot(PlotOperator),
73
}
74

75
/// An operator that produces raster data.
76
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
77
#[serde(rename_all = "camelCase", untagged)]
78
#[schema(discriminator = "type")]
79
pub enum RasterOperator {
80
    BandFilter(BandFilter),
81
    Downsampling(Downsampling),
82
    Expression(Expression),
83
    GdalSource(GdalSource),
84
    Interpolation(Interpolation),
85
    MultiBandGdalSource(MultiBandGdalSource),
86
    RasterStacker(RasterStacker),
87
    RasterTypeConversion(RasterTypeConversion),
88
    Reprojection(Reprojection),
89
    TemporalRasterAggregation(TemporalRasterAggregation),
90
}
91

92
/// An operator that produces vector data.
93
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
94
#[serde(rename_all = "camelCase", untagged)]
95
#[schema(discriminator = "type")]
96
pub enum VectorOperator {
97
    MockPointSource(MockPointSource),
98
    OgrSource(OgrSource),
99
    RasterVectorJoin(RasterVectorJoin),
100
    Reprojection(Reprojection),
101
}
102

103
/// An operator that produces plot data.
104
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
105
#[serde(rename_all = "camelCase", untagged)]
106
#[schema(discriminator = "type")]
107
pub enum PlotOperator {
108
    Histogram(Histogram),
109
    Statistics(Statistics),
110
}
111

112
impl TryFrom<RasterOperator> for Box<dyn OperatorsRasterOperator> {
113
    type Error = anyhow::Error;
114
    fn try_from(operator: RasterOperator) -> Result<Self, Self::Error> {
103✔
115
        // TODO: Missing raster operator mappings (operators crate -> OpenAPI model):
116
        // [ ] BandNeighborhoodAggregate
117
        // [ ] BandwiseExpression
118
        // [ ] NeighborhoodAggregate
119
        // [ ] Onnx
120
        // [ ] RasterScaling
121
        // [ ] Rasterization
122
        // [ ] Reflectance
123
        // [ ] Radiance
124
        // [ ] Temperature
125
        // [ ] TimeShift
126
        match operator {
103✔
127
            RasterOperator::BandFilter(band_filter) => {
2✔
128
                OperatorsBandFilter::try_from(band_filter).map(OperatorsRasterOperator::boxed)
2✔
129
            }
NEW
130
            RasterOperator::Downsampling(downsampling) => {
×
NEW
131
                OperatorsDownsampling::try_from(downsampling).map(OperatorsRasterOperator::boxed)
×
132
            }
133
            RasterOperator::Expression(expression) => {
1✔
134
                OperatorsExpression::try_from(expression).map(OperatorsRasterOperator::boxed)
1✔
135
            }
136
            RasterOperator::GdalSource(gdal_source) => {
77✔
137
                OperatorsGdalSource::try_from(gdal_source).map(OperatorsRasterOperator::boxed)
77✔
138
            }
139
            RasterOperator::Interpolation(interpolation) => {
1✔
140
                OperatorsInterpolation::try_from(interpolation).map(OperatorsRasterOperator::boxed)
1✔
141
            }
142
            RasterOperator::MultiBandGdalSource(gdal_source) => {
7✔
143
                OperatorsMultiBandGdalSource::try_from(gdal_source)
7✔
144
                    .map(OperatorsRasterOperator::boxed)
7✔
145
            }
146
            RasterOperator::RasterStacker(raster_stacker) => {
3✔
147
                OperatorsRasterStacker::try_from(raster_stacker).map(OperatorsRasterOperator::boxed)
3✔
148
            }
149
            RasterOperator::RasterTypeConversion(type_conversion) => {
1✔
150
                OperatorsRasterTypeConversion::try_from(type_conversion)
1✔
151
                    .map(OperatorsRasterOperator::boxed)
1✔
152
            }
153
            RasterOperator::Reprojection(reprojection) => {
10✔
154
                OperatorsReprojection::try_from(reprojection).map(OperatorsRasterOperator::boxed)
10✔
155
            }
156
            RasterOperator::TemporalRasterAggregation(aggregation) => {
1✔
157
                OperatorsTemporalRasterAggregation::try_from(aggregation)
1✔
158
                    .map(OperatorsRasterOperator::boxed)
1✔
159
            }
160
        }
161
    }
103✔
162
}
163

164
impl TryFrom<VectorOperator> for Box<dyn OperatorsVectorOperator> {
165
    type Error = anyhow::Error;
166
    fn try_from(operator: VectorOperator) -> Result<Self, Self::Error> {
15✔
167
        // TODO: Missing vector operator mappings (operators crate -> OpenAPI model):
168
        // [ ] ColumnRangeFilter
169
        // [ ] CsvSource
170
        // [ ] LineSimplification
171
        // [ ] MockDatasetDataSource
172
        // [ ] PointInPolygonFilter
173
        // [ ] TimeProjection
174
        // [ ] TimeShift
175
        // [ ] VectorExpression
176
        // [ ] VectorJoin
177
        // [ ] VisualPointClustering
178
        match operator {
15✔
179
            VectorOperator::MockPointSource(mock_point_source) => {
8✔
180
                OperatorsMockPointSource::try_from(mock_point_source)
8✔
181
                    .map(OperatorsVectorOperator::boxed)
8✔
182
            }
183
            VectorOperator::OgrSource(ogr_source) => {
5✔
184
                OperatorsOgrSource::try_from(ogr_source).map(OperatorsVectorOperator::boxed)
5✔
185
            }
186
            VectorOperator::RasterVectorJoin(rvj) => {
1✔
187
                OperatorsRasterVectorJoin::try_from(rvj).map(OperatorsVectorOperator::boxed)
1✔
188
            }
189
            VectorOperator::Reprojection(reprojection) => {
1✔
190
                OperatorsReprojection::try_from(reprojection).map(OperatorsVectorOperator::boxed)
1✔
191
            }
192
        }
193
    }
15✔
194
}
195

196
impl TryFrom<PlotOperator> for Box<dyn OperatorsPlotOperator> {
197
    type Error = anyhow::Error;
198
    fn try_from(operator: PlotOperator) -> Result<Self, Self::Error> {
4✔
199
        // TODO: Missing plot operator mappings (operators crate -> OpenAPI model):
200
        // [ ] BoxPlot
201
        // [ ] ClassHistogram
202
        // [ ] FeatureAttributeValuesOverTime
203
        // [ ] MeanRasterPixelValuesOverTime
204
        // [ ] PieChart
205
        // [ ] ScatterPlot
206
        match operator {
4✔
207
            PlotOperator::Histogram(histogram) => {
1✔
208
                OperatorsHistogram::try_from(histogram).map(OperatorsPlotOperator::boxed)
1✔
209
            }
210
            PlotOperator::Statistics(statistics) => {
3✔
211
                OperatorsStatistics::try_from(statistics).map(OperatorsPlotOperator::boxed)
3✔
212
            }
213
        }
214
    }
4✔
215
}
216

217
impl TryFrom<TypedOperator> for OperatorsTypedOperator {
218
    type Error = anyhow::Error;
219
    fn try_from(operator: TypedOperator) -> Result<Self, Self::Error> {
71✔
220
        match operator {
71✔
221
            TypedOperator::Raster(raster_operator) => Ok(Self::Raster(raster_operator.try_into()?)),
62✔
222
            TypedOperator::Vector(vector_operator) => Ok(Self::Vector(vector_operator.try_into()?)),
7✔
223
            TypedOperator::Plot(plot_operator) => Ok(Self::Plot(plot_operator.try_into()?)),
2✔
224
        }
225
    }
71✔
226
}
227

228
#[derive(OpenApi)]
229
#[openapi(components(schemas(
230
    // General
231
    PlotOperator,
232
    TypedOperator,
233
    VectorOperator,
234
    // Source
235
    GdalSource,
236
    GdalSourceParameters,
237
    MockPointSource,
238
    MockPointSourceParameters,
239
    MultiBandGdalSource,
240
    OgrSource,
241
    OgrSourceParameters,
242
    // Processing
243
    Aggregation,
244
    BandFilter,
245
    BandFilterParameters,
246
    BandsByNameOrIndex,
247
    DeriveOutRasterSpecsSource,
248
    Downsampling,
249
    DownsamplingMethod,
250
    DownsamplingParameters,
251
    DownsamplingResolution,
252
    Expression,
253
    ExpressionParameters,
254
    Interpolation,
255
    InterpolationMethod,
256
    InterpolationParameters,
257
    InterpolationResolution,
258
    RasterOperator,
259
    RasterStacker,
260
    RasterStackerParameters,
261
    RasterTypeConversion,
262
    RasterTypeConversionParameters,
263
    RasterVectorJoin,
264
    RasterVectorJoinParameters,
265
    RenameBands,
266
    Reprojection,
267
    ReprojectionParameters,
268
    TemporalRasterAggregation,
269
    TemporalRasterAggregationParameters,
270
    // Plots
271
    Histogram,
272
    HistogramParameters,
273
    Statistics,
274
    StatisticsParameters,
275
    // Source Parameters
276
    MultipleRasterOrSingleVectorOperator,
277
    MultipleRasterOrSingleVectorSource,
278
    MultipleRasterSources,
279
    SingleRasterOrVectorOperator,
280
    SingleRasterOrVectorSource,
281
    SingleRasterSource,
282
    SingleVectorMultipleRasterSources,
283

284
)))]
285
pub struct OperatorsApi;
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