modewise_operations/
reconstruct.rs1use modewise_pipeline::{
2 Artifact, ArtifactKind, Inputs, Operation, OperationDescriptor, Outputs, Port, resolve_params,
3};
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8use crate::input;
9
10#[derive(Serialize, Deserialize, JsonSchema)]
11#[serde(deny_unknown_fields)]
12struct Params {
13 modes: Vec<usize>,
15}
16
17pub struct ReconstructOperation;
19
20impl Operation for ReconstructOperation {
21 fn summary(&self) -> &'static str {
22 "Sums chosen modes of a decomposition back into a series, for example to keep one band."
23 }
24
25 fn params_schema(&self) -> serde_json::Value {
26 modewise_pipeline::schema_of::<Params>()
27 }
28
29 fn descriptor(&self) -> OperationDescriptor {
30 OperationDescriptor {
31 name: "reconstruct",
32 version: env!("CARGO_PKG_VERSION"),
33 inputs: &[Port {
34 name: "modes",
35 kinds: &[ArtifactKind::Decomposition],
36 }],
37 outputs: &[Port {
38 name: "signal",
39 kinds: &[ArtifactKind::Series],
40 }],
41 }
42 }
43
44 fn resolve(&self, params: Value) -> Result<Value, String> {
45 resolve_params::<Params>(params).map(|(_, resolved)| resolved)
46 }
47
48 fn run(&self, params: &Value, inputs: &Inputs) -> Result<Outputs, String> {
49 let p: Params = serde_json::from_value(params.clone()).map_err(|e| e.to_string())?;
50 let Artifact::Decomposition(modes) = input(inputs, "modes")? else {
51 return Err("input \"modes\" must be a decomposition".into());
52 };
53 let signal = modes.reconstruct(&p.modes).map_err(|e| e.to_string())?;
54 Ok(Outputs::from([("signal".into(), Artifact::Series(signal))]))
55 }
56}