@@ -34,23 +34,26 @@ class MetisRecipeImpl(ABC):
34
34
by particular pipeline recipe implementations.
35
35
"""
36
36
InputSet : type [PipelineInputSet ] = None
37
- Product : type [PipelineProduct ] = None
38
37
39
38
# Available parameters are a class variable. This must be present, even if empty.
40
39
parameters = cpl .ui .ParameterList ([])
41
40
42
41
def __init__ (self , recipe : 'MetisRecipe' ) -> None :
42
+ """
43
+ Initializes the recipe implementation object with parameters from the recipe
44
+ and sets internal attributes to None / empty as needed.
45
+ """
43
46
super ().__init__ ()
44
47
self .name = recipe .name
45
48
self .version = recipe .version
46
49
self .parameters = recipe .parameters
47
50
48
- self .inputset : PipelineInputSet = None
51
+ self .inputset : PipelineInputSet | None = None
49
52
self .frameset : cpl .ui .FrameSet | None = None
50
53
self .header : cpl .core .PropertyList | None = None
51
- self .products : Dict [ str , PipelineProduct ] = {}
54
+ self .products : [ PipelineProduct ] = {}
52
55
self .product_frames = cpl .ui .FrameSet ()
53
-
56
+
54
57
def run (self , frameset : cpl .ui .FrameSet , settings : Dict [str , Any ]) -> cpl .ui .FrameSet :
55
58
"""
56
59
The main function of the recipe implementation. It mirrors the signature of `Recipe.run`
@@ -64,14 +67,14 @@ def run(self, frameset: cpl.ui.FrameSet, settings: Dict[str, Any]) -> cpl.ui.Fra
64
67
65
68
try :
66
69
self .frameset = frameset
67
- self .import_settings (settings ) # Import and process the provided settings dict
68
- self .inputset = self .InputSet (frameset ) # Create an appropriate InputSet object
70
+ self .import_settings (settings ) # Import and process the provided settings dict
71
+ self .inputset = self .InputSet (frameset ) # Create an appropriate InputSet object
69
72
self .inputset .print_debug ()
70
- self .inputset .validate () # Verify that they are valid (maybe with `schema` too?)
71
- products = self .process_images () # Do all the actual processing
72
- self .save_products ( products ) # Save the output products
73
+ self .inputset .validate () # Verify that they are valid (maybe with `schema` too?)
74
+ self . products = self .process_images () # Do all the actual processing
75
+ self ._save_products () # Save the output products
73
76
74
- return self .build_product_frameset (products ) # Return the output as a pycpl FrameSet
77
+ return self .build_product_frameset () # Return the output as a pycpl FrameSet
75
78
except cpl .core .DataNotFoundError as e :
76
79
Msg .error (self .__class__ .__qualname__ , f"Data not found error: { e .message } " )
77
80
raise e
@@ -84,20 +87,20 @@ def import_settings(self, settings: Dict[str, Any]) -> None:
84
87
self .parameters [key ].value = value
85
88
except KeyError :
86
89
Msg .warning (self .__class__ .__qualname__ ,
87
- f"Settings includes '{ key } ': { value } "
90
+ f"Settings include '{ key } ' = { value } "
88
91
f"but class { self .__class__ .__qualname__ } "
89
92
f"has no parameter named { key } ." )
90
93
91
94
@abstractmethod
92
- def process_images (self ) -> Dict [ str , PipelineProduct ]:
95
+ def process_images (self ) -> [ PipelineProduct ]:
93
96
"""
94
97
The core method of the recipe implementation. It should contain all the processing logic.
95
98
At its entry point the Input class must be already loaded and validated.
96
99
97
100
All pixel manipulation should happen inside this function (or something it calls from within).
98
101
Put explicitly,
99
- - no pixel manipulation before entering `process_images`,
100
- - and no pixel manipulation after exiting `process_images`.
102
+ - no pixel manipulation * before* entering `process_images`,
103
+ - and no pixel manipulation * after* exiting `process_images`.
101
104
102
105
The basic workflow inside this function should be as follows:
103
106
@@ -118,22 +121,24 @@ def process_images(self) -> Dict[str, PipelineProduct]:
118
121
"""
119
122
return {}
120
123
121
- def save_products (self , products : Dict [ str , PipelineProduct ] ) -> None :
124
+ def _save_products (self ) -> None :
122
125
"""
123
126
Save and register the created products.
124
127
"""
125
- for name , product in products .items ():
126
- Msg .debug (self .__class__ .__qualname__ ,
127
- f"Saving product { name } " )
128
+ assert self .products is not None , "Products have not been created yet!"
129
+
130
+ Msg .debug (self .__class__ .__qualname__ ,
131
+ f"Saving { len (self .products )} products: { self .products } " )
132
+ for product in self .products :
128
133
product .save ()
129
134
130
- def build_product_frameset (self , products : Dict [ str , PipelineProduct ] ) -> cpl .ui .FrameSet :
135
+ def build_product_frameset (self ) -> cpl .ui .FrameSet :
131
136
"""
132
137
Gather all the products and build a FrameSet from their frames so that it can be returned from `run`.
133
138
"""
134
139
Msg .debug (self .__class__ .__qualname__ ,
135
140
f"Building the product frameset" )
136
- return cpl .ui .FrameSet ([product .as_frame () for product in products . values () ])
141
+ return cpl .ui .FrameSet ([product .as_frame () for product in self . products ])
137
142
138
143
def as_dict (self ) -> dict [str , Any ]:
139
144
"""
@@ -147,7 +152,7 @@ def as_dict(self) -> dict[str, Any]:
147
152
'title' : self .name ,
148
153
'inputset' : self .inputset .as_dict (),
149
154
'products' : {
150
- product .tag : product .as_dict () for product in self .products . values ()
155
+ str ( product .category ) : product .as_dict () for product in self .products
151
156
}
152
157
}
153
158
0 commit comments