6
6
7
7
# This is the process dictionary that is used to store all processes of
8
8
# the Actinia wrapper
9
- from openeo_grass_gis_driver .actinia_processing .actinia_interface import \
10
- ActiniaInterface
9
+ from openeo_grass_gis_driver .actinia_processing .actinia_interface import (
10
+ ActiniaInterface ,
11
+ )
11
12
12
13
from openeo_grass_gis_driver .models .process_graph_schemas import ProcessGraph
13
14
@@ -62,7 +63,14 @@ class GrassDataType(Enum):
62
63
RASTER = "raster"
63
64
VECTOR = "vector"
64
65
STRDS = "strds"
65
- STAC = "rastercube"
66
+ EXTERN = "rastercube"
67
+
68
+
69
+ class DataSource (Enum ):
70
+
71
+ GRASS = "grass"
72
+ STAC = "stac"
73
+ LOCAL = "gdallocal"
66
74
67
75
68
76
class DataObject :
@@ -71,14 +79,17 @@ class DataObject:
71
79
"""
72
80
73
81
def __init__ (
74
- self ,
75
- name : str ,
76
- datatype : GrassDataType ,
77
- mapset : str = None ,
78
- location : str = None ):
82
+ self ,
83
+ name : str ,
84
+ datatype : GrassDataType ,
85
+ datasource : DataSource = DataSource .GRASS ,
86
+ mapset : str = None ,
87
+ location : str = None ,
88
+ ):
79
89
80
90
self .name = name
81
91
self .datatype = datatype
92
+ self .datasource = datasource
82
93
self .mapset = mapset
83
94
self .location = location
84
95
@@ -90,38 +101,67 @@ def __str__(self):
90
101
def from_string (name : str ):
91
102
92
103
AI = ActiniaInterface
93
- location , mapset , datatype , layer_name = AI .layer_def_to_components (
94
- name )
104
+ location , mapset , datatype , layer_name = AI .layer_def_to_components (name )
95
105
96
106
if datatype is None :
97
107
raise Exception (f"Invalid collection id <{ name } >" )
98
108
99
- if GrassDataType .RASTER .value == datatype :
109
+ datasource = DataSource .GRASS
110
+ if location == "stac" :
111
+ datasource = DataSource .STAC
112
+ elif location == "local" :
113
+ datasource = DataSource .LOCAL
114
+
115
+ if DataSource .GRASS == datasource and GrassDataType .RASTER .value == datatype :
100
116
return DataObject (
101
117
name = layer_name ,
102
118
datatype = GrassDataType .RASTER ,
119
+ datasource = datasource ,
103
120
mapset = mapset ,
104
- location = location )
105
- elif GrassDataType .VECTOR .value == datatype :
121
+ location = location ,
122
+ )
123
+ elif DataSource .GRASS == datasource and GrassDataType .VECTOR .value == datatype :
106
124
return DataObject (
107
125
name = layer_name ,
108
126
datatype = GrassDataType .VECTOR ,
127
+ datasource = datasource ,
109
128
mapset = mapset ,
110
- location = location )
111
- elif GrassDataType .STRDS .value == datatype :
129
+ location = location ,
130
+ )
131
+ elif DataSource .GRASS == datasource and GrassDataType .STRDS .value == datatype :
112
132
return DataObject (
113
133
name = layer_name ,
114
134
datatype = GrassDataType .STRDS ,
135
+ datasource = datasource ,
115
136
mapset = mapset ,
116
- location = location )
117
- elif GrassDataType .STAC .value == datatype :
137
+ location = location ,
138
+ )
139
+ elif DataSource .STAC == datasource and GrassDataType .EXTERN .value == datatype :
140
+ # location = "stac"
141
+ del AI .PROCESS_LOCATION [location ]
142
+ AI .PROCESS_LOCATION ["latlong_wgs84" ] = "latlong_wgs84"
118
143
return DataObject (
119
144
name = layer_name ,
120
- datatype = GrassDataType .STAC ,
145
+ datatype = GrassDataType .EXTERN ,
146
+ datasource = datasource ,
121
147
mapset = mapset ,
122
- location = "latlong_wgs84" )
148
+ location = "latlong_wgs84" ,
149
+ )
150
+ elif DataSource .LOCAL == datasource and GrassDataType .EXTERN .value == datatype :
151
+ # location = "local"
152
+ del AI .PROCESS_LOCATION [location ]
153
+ AI .PROCESS_LOCATION ["latlong_wgs84" ] = "latlong_wgs84"
154
+ return DataObject (
155
+ name = layer_name ,
156
+ datatype = GrassDataType .EXTERN ,
157
+ datasource = datasource ,
158
+ mapset = mapset ,
159
+ location = "latlong_wgs84" ,
160
+ )
123
161
124
- raise Exception (f"Unsupported object type <{ datatype } >" )
162
+ raise Exception (
163
+ f"Unsupported object type <{ datatype } > and data source <{ datasource .value } >"
164
+ )
125
165
126
166
def grass_name (self ):
127
167
@@ -134,24 +174,40 @@ def full_name(self):
134
174
135
175
def is_strds (self ):
136
176
137
- return self .datatype == GrassDataType .STRDS
177
+ return (
178
+ self .datasource == DataSource .GRASS and self .datatype == GrassDataType .STRDS
179
+ )
138
180
139
181
def is_raster (self ):
140
182
141
- return self .datatype == GrassDataType .RASTER
183
+ return (
184
+ self .datasource == DataSource .GRASS
185
+ and self .datatype == GrassDataType .RASTER
186
+ )
142
187
143
188
def is_vector (self ):
144
189
145
- return self .datatype == GrassDataType .VECTOR
190
+ return (
191
+ self .datasource == DataSource .GRASS
192
+ and self .datatype == GrassDataType .VECTOR
193
+ )
146
194
147
195
def is_stac (self ):
148
196
149
- return self .datatype == GrassDataType .STAC
197
+ return (
198
+ self .datasource == DataSource .STAC and self .datatype == GrassDataType .EXTERN
199
+ )
200
+
201
+ def is_local (self ):
202
+
203
+ return (
204
+ self .datasource == DataSource .LOCAL
205
+ and self .datatype == GrassDataType .EXTERN
206
+ )
150
207
151
208
152
209
class Node :
153
- """A single node in the process graph
154
- """
210
+ """A single node in the process graph"""
155
211
156
212
def __init__ (self , id , process_description : dict ):
157
213
@@ -171,7 +227,7 @@ def __init__(self, id, process_description: dict):
171
227
def add_output (self , output_object : DataObject ):
172
228
self .output_objects .add (output_object )
173
229
174
- def get_parent_by_name (self , parent_name : str ) -> Optional [' Node' ]:
230
+ def get_parent_by_name (self , parent_name : str ) -> Optional [" Node" ]:
175
231
if parent_name in self .parents_dict .keys ():
176
232
return self .parents_dict [parent_name ]
177
233
return None
@@ -198,8 +254,10 @@ def __str__(self):
198
254
if self .parents_dict :
199
255
parent_names = list (self .parents_dict .keys ())
200
256
201
- return (f"Node: { self .id } parent names: { parent_names } parent "
202
- f"ids: { parent_ids } child ids: { child_ids } " )
257
+ return (
258
+ f"Node: { self .id } parent names: { parent_names } parent "
259
+ f"ids: { parent_ids } child ids: { child_ids } "
260
+ )
203
261
204
262
def get_parents_dict (self ) -> dict :
205
263
@@ -220,9 +278,7 @@ def as_dict(self) -> dict:
220
278
221
279
222
280
class Graph :
223
- """This class represents a process graph
224
-
225
- """
281
+ """This class represents a process graph"""
226
282
227
283
def __init__ (self , graph_description : Union [Dict , ProcessGraph ]):
228
284
"""The constructor checks the validity of the provided dictionary
@@ -237,7 +293,8 @@ def __init__(self, graph_description: Union[Dict, ProcessGraph]):
237
293
self .title : str = graph_description .title
238
294
self .description : str = graph_description .description
239
295
self .build_process_graph_from_description (
240
- process_graph = graph_description .process_graph )
296
+ process_graph = graph_description .process_graph
297
+ )
241
298
else :
242
299
if "title" not in graph_description :
243
300
# raise Exception("Title is required in the process graph")
@@ -250,13 +307,16 @@ def __init__(self, graph_description: Union[Dict, ProcessGraph]):
250
307
251
308
# graph_description can be a process with process_graph or
252
309
# only a process_graph
253
- if "process" not in graph_description and \
254
- "process_graph" not in graph_description :
255
- raise Exception (
256
- "process_graph is required in the process graph" )
257
-
258
- if "process" in graph_description and \
259
- "process_graph" not in graph_description ["process" ]:
310
+ if (
311
+ "process" not in graph_description
312
+ and "process_graph" not in graph_description
313
+ ):
314
+ raise Exception ("process_graph is required in the process graph" )
315
+
316
+ if (
317
+ "process" in graph_description
318
+ and "process_graph" not in graph_description ["process" ]
319
+ ):
260
320
raise Exception ("process_graph is required in the process" )
261
321
262
322
if "process" in graph_description :
@@ -266,8 +326,7 @@ def __init__(self, graph_description: Union[Dict, ProcessGraph]):
266
326
self .title : str = graph_description ["title" ]
267
327
self .description : str = graph_description ["description" ]
268
328
269
- self .build_process_graph_from_description (
270
- process_graph = process_graph )
329
+ self .build_process_graph_from_description (process_graph = process_graph )
271
330
272
331
def build_process_graph_from_description (self , process_graph : dict ):
273
332
"""Build the directed process graph from the graph description
@@ -425,31 +484,30 @@ def openeo_to_actinia(node: Node) -> Tuple[list, list]:
425
484
# warning, error, exception?
426
485
continue
427
486
# check if it is an input object
428
- if isinstance (node .arguments [key ], dict ) and \
429
- "from_node" in node .arguments [key ]:
487
+ if isinstance (node .arguments [key ], dict ) and "from_node" in node .arguments [key ]:
430
488
# input option comes from another node in the process graph
431
489
# which output object in the set of output_objects?
432
- value = list (
433
- node .get_parent_by_name (
434
- parent_name = key ).output_objects )[0 ]
490
+ value = list (node .get_parent_by_name (parent_name = key ).output_objects )[0 ]
435
491
data_object = value
436
492
# check schema subtype of parameter and compare with
437
493
# datatype of data_object
438
- if ao ["schema" ]["subtype" ] == "cell" and \
439
- data_object .datatype != GrassDataType .RASTER :
440
- raise Exception (
441
- "Wrong input data type, expecting 'cell'" )
442
- elif ao ["schema" ]["subtype" ] == "strds" and \
443
- data_object .datatype != GrassDataType .STRDS :
444
- raise Exception (
445
- "Wrong input data type, expecting 'strds'" )
446
- elif ao ["schema" ]["subtype" ] == "vector" and \
447
- data_object .datatype != GrassDataType .VECTOR :
448
- raise Exception (
449
- "Wrong input data type, expecting 'vector'" )
450
-
451
- param = {"param" : key ,
452
- "value" : data_object .grass_name ()}
494
+ if (
495
+ ao ["schema" ]["subtype" ] == "cell"
496
+ and data_object .datatype != GrassDataType .RASTER
497
+ ):
498
+ raise Exception ("Wrong input data type, expecting 'cell'" )
499
+ elif (
500
+ ao ["schema" ]["subtype" ] == "strds"
501
+ and data_object .datatype != GrassDataType .STRDS
502
+ ):
503
+ raise Exception ("Wrong input data type, expecting 'strds'" )
504
+ elif (
505
+ ao ["schema" ]["subtype" ] == "vector"
506
+ and data_object .datatype != GrassDataType .VECTOR
507
+ ):
508
+ raise Exception ("Wrong input data type, expecting 'vector'" )
509
+
510
+ param = {"param" : key , "value" : data_object .grass_name ()}
453
511
pc ["inputs" ].append (param )
454
512
elif ao ["schema" ]["type" ] == "boolean" :
455
513
# flag
@@ -461,18 +519,15 @@ def openeo_to_actinia(node: Node) -> Tuple[list, list]:
461
519
else :
462
520
# option answer, treat as string
463
521
value = node .arguments [key ]
464
- param = {"param" : key ,
465
- "value" : str (value )}
522
+ param = {"param" : key , "value" : str (value )}
466
523
pc ["inputs" ].append (param )
467
524
468
525
if pc ["flags" ] is None :
469
526
del pc ["flags" ]
470
527
471
528
# TODO: support modules that do not have input maps
472
529
if data_object is None :
473
- raise Exception (
474
- "No input data object for actinia process '%s'" %
475
- module_name )
530
+ raise Exception ("No input data object for actinia process '%s'" % module_name )
476
531
477
532
# output parameters
478
533
if "returns" in module and openeo_returns is not None :
@@ -499,16 +554,14 @@ def openeo_to_actinia(node: Node) -> Tuple[list, list]:
499
554
# in order to distinguish between different outputs
500
555
# of the same module
501
556
output_object = DataObject (
502
- name = create_output_name (data_object .name , node ),
503
- datatype = datatype )
504
- param = {"param" : key ,
505
- "value" : output_object .grass_name ()}
557
+ name = create_output_name (data_object .name , node ), datatype = datatype
558
+ )
559
+ param = {"param" : key , "value" : output_object .grass_name ()}
506
560
pc ["inputs" ].append (param )
507
561
output_objects .append (output_object )
508
562
node .add_output (output_object = output_object )
509
563
if module_name in T_BASENAME_MODULES_LIST :
510
- param = {"param" : "basename" ,
511
- "value" : output_object .name }
564
+ param = {"param" : "basename" , "value" : output_object .name }
512
565
pc ["inputs" ].append (param )
513
566
514
567
process_list .append (pc )
@@ -532,7 +585,7 @@ def create_output_name(input: str, node: Node):
532
585
new_uuid = uuid .uuid4 ().hex
533
586
534
587
# shorter version: only uuid + node id
535
- node_id = node .id .lower ().replace (' ' , '_' )
588
+ node_id = node .id .lower ().replace (" " , "_" )
536
589
output = f"uuid{ new_uuid } _{ node_id } "
537
590
538
591
return output
0 commit comments