1010from sophios .wic_types import Json , Cwl
1111from sophios .api .utils .ict .ict_spec .model import ICT
1212from sophios .api .utils .ict .ict_spec .cast import cast_to_ict
13+ from sophios .api .utils .wfb_util import get_node_config
1314
1415SCHEMA_FILE = Path (__file__ ).parent / "input_object_schema.json"
1516SCHEMA : Json = {}
@@ -147,10 +148,16 @@ def get_topological_order(links: list[dict[str, str]]) -> list[str]:
147148 return result
148149
149150
150- def wfb_to_wic (inp : Json ) -> Cwl :
151+ def wfb_to_wic (inp : Json , plugins : List [ dict [ str , Any ]] ) -> Cwl :
151152 """Convert lean wfb json to compliant wic"""
152153 # non-schema preserving changes
153154 inp_restrict = copy .deepcopy (inp )
155+ plugin_config_map : dict [str , dict ] = {}
156+ for plugin in plugins :
157+ pid : str = plugin .get ("pid" , "" )
158+ if pid == "" :
159+ continue
160+ plugin_config_map [pid ] = get_node_config (plugin )
154161
155162 for node in inp_restrict ['nodes' ]:
156163 if node .get ('settings' ):
@@ -159,7 +166,6 @@ def wfb_to_wic(inp: Json) -> Cwl:
159166 node ['out' ] = list ({k : yaml .load ('!& ' + v , Loader = wic_loader ())} for k , v in node ['settings' ]
160167 ['outputs' ].items ()) # outputs always have to be list
161168 # remove these (now) superfluous keys
162- node .pop ('settings' , None )
163169 node .pop ('name' , None )
164170 node .pop ('internal' , None )
165171
@@ -168,39 +174,101 @@ def wfb_to_wic(inp: Json) -> Cwl:
168174 target_node_ids = []
169175 for edg in inp_restrict ['links' ]:
170176 target_node_ids .append (edg ['targetId' ])
177+ # keep track of all the args that processed
178+ node_arg_map : dict [int , set ] = {}
171179 # now set inputs on non-sink nodes as inline input '!ii '
172180 # if inputs exist
173181 non_sink_nodes = [node for node in inp_restrict ['nodes' ] if node ['id' ] not in target_node_ids ]
174182 for node in non_sink_nodes :
183+ if node ["id" ] not in node_arg_map :
184+ node_arg_map [node ['id' ]] = set ()
175185 if node .get ('in' ):
176186 for nkey in node ['in' ]:
177- node ['in' ][nkey ] = yaml .load ('!ii ' + str (node ['in' ][nkey ]), Loader = wic_loader ())
187+ if str (node ['in' ][nkey ]) != "" :
188+ node ['in' ][nkey ] = yaml .load ('!ii ' + str (node ['in' ][nkey ]), Loader = wic_loader ())
189+ node_arg_map [node ['id' ]].add (nkey )
190+
191+ if plugins != []: # use the look up logic similar to WFB
192+ for edg in inp_restrict ['links' ]:
193+ # links = edge. nodes and edges is the correct terminology!
194+ src_id = edg ['sourceId' ]
195+ tgt_id = edg ['targetId' ]
196+ src_node = next ((node for node in inp_restrict ['nodes' ] if node ['id' ] == src_id ), None )
197+ tgt_node = next ((node for node in inp_restrict ['nodes' ] if node ['id' ] == tgt_id ), None )
198+ assert src_node , f'output(s) of source node of edge{ edg } must exist!'
199+ assert tgt_node , f'input(s) of target node of edge{ edg } must exist!'
200+ if src_id not in node_arg_map :
201+ node_arg_map [src_id ] = set ()
202+
203+ if tgt_id not in node_arg_map :
204+ node_arg_map [tgt_id ] = set ()
205+
206+ src_node_ui_config = plugin_config_map .get (src_node ['pluginId' ], None )
207+ tgt_node_ui_config = plugin_config_map .get (tgt_node ['pluginId' ], None )
208+ if src_node_ui_config and tgt_node_ui_config :
209+ inlet_index = edg ['inletIndex' ]
210+ outlet_index = edg ['outletIndex' ]
211+
212+ src_node_out_arg = src_node_ui_config ['outputs' ][outlet_index ]["name" ]
213+ tgt_node_in_arg = tgt_node_ui_config ['inputs' ][inlet_index ]["name" ]
214+
215+ if tgt_node .get ('in' ):
216+ source_output = src_node ['out' ][0 ][src_node_out_arg ]
217+ if isinstance (source_output , dict ) and 'wic_anchor' in source_output :
218+ source_output = source_output ["wic_anchor" ]
219+ tgt_node ['in' ][tgt_node_in_arg ] = yaml .load ('!* ' + str (source_output ), Loader = wic_loader ())
220+ node_arg_map [tgt_id ].add (tgt_node_in_arg )
221+
222+ for node in inp_restrict ['nodes' ]:
223+ output_dict = node ['settings' ].get ('outputs' , {})
224+ for key in output_dict :
225+ if str (output_dict [key ]) != "" :
226+ node ['in' ][key ] = yaml .load ('!ii ' + str (output_dict [key ]), Loader = wic_loader ())
227+ node_arg_map [node ['id' ]].add (key )
228+ node .pop ('settings' , None )
178229
179- # After outs are set
180- for edg in inp_restrict ['links' ]:
181- # links = edge. nodes and edges is the correct terminology!
182- src_id = edg ['sourceId' ]
183- tgt_id = edg ['targetId' ]
184- src_node = next ((node for node in inp_restrict ['nodes' ] if node ['id' ] == src_id ), None )
185- tgt_node = next ((node for node in inp_restrict ['nodes' ] if node ['id' ] == tgt_id ), None )
186- assert src_node , f'output(s) of source node of edge{ edg } must exist!'
187- assert tgt_node , f'input(s) of target node of edge{ edg } must exist!'
188- # flattened list of keys
189- if src_node .get ('out' ) and tgt_node .get ('in' ):
190- src_out_keys = [sk for sout in src_node ['out' ] for sk in sout .keys ()]
191- tgt_in_keys = tgt_node ['in' ].keys ()
192- # we match the source output tag type to target input tag type
193- # and connect them through '!* ' for input, all outputs are '!& ' before this
194- for sk in src_out_keys :
195- # It maybe possible that (explicit) outputs of src nodes might not have corresponding
196- # (explicit) inputs in target node
197- if tgt_node ['in' ].get (sk ):
198- tgt_node ['in' ][sk ] = yaml .load ('!* ' + tgt_node ['in' ][sk ], Loader = wic_loader ())
199- # the inputs which aren't dependent on previous/other steps
200- # they are by default inline input
201- diff_keys = set (tgt_in_keys ) - set (src_out_keys )
202- for dfk in diff_keys :
203- tgt_node ['in' ][dfk ] = yaml .load ('!ii ' + str (tgt_node ['in' ][dfk ]), Loader = wic_loader ())
230+ if "in" in node :
231+ unprocessed_args = set (node ['in' ].keys ())
232+ if node ['id' ] in node_arg_map :
233+ unprocessed_args = unprocessed_args .difference (node_arg_map [node ['id' ]])
234+ for arg in unprocessed_args :
235+ node ['in' ][arg ] = yaml .load ('!ii ' + str (node ['in' ][arg ]), Loader = wic_loader ())
236+ else : # No plugins, use the old logic
237+ # this logic is most likely not correct and need to be scrubbed
238+ # along with updating the non_wfb dummy tests
239+ for node in inp_restrict ['nodes' ]:
240+ node .pop ('settings' , None )
241+
242+ for edg in inp_restrict ['links' ]:
243+ # links = edge. nodes and edges is the correct terminology!
244+ src_id = edg ['sourceId' ]
245+ tgt_id = edg ['targetId' ]
246+ src_node = next ((node for node in inp_restrict ['nodes' ] if node ['id' ] == src_id ), None )
247+ tgt_node = next ((node for node in inp_restrict ['nodes' ] if node ['id' ] == tgt_id ), None )
248+ assert src_node , f'output(s) of source node of edge{ edg } must exist!'
249+ assert tgt_node , f'input(s) of target node of edge{ edg } must exist!'
250+ # flattened list of keys
251+ if src_node .get ('out' ) and tgt_node .get ('in' ):
252+ src_out_keys = [sk for sout in src_node ['out' ] for sk in sout .keys ()]
253+ tgt_in_keys = tgt_node ['in' ].keys ()
254+ # we match the source output tag type to target input tag type
255+ # and connect them through '!* ' for input, all outputs are '!& ' before this
256+ for sk in src_out_keys :
257+ # It maybe possible that (explicit) outputs of src nodes might not have corresponding
258+ # (explicit) inputs in target node
259+ if tgt_node ['in' ].get (sk ):
260+ # if the output is a dict, it is a wic_anchor, so we need to get the anchor
261+ # and use that as the input
262+ src_node_out_arg = src_node ['out' ][0 ][sk ]
263+ source_output = src_node ['out' ][0 ][sk ]
264+ if isinstance (source_output , dict ) and 'wic_anchor' in source_output :
265+ source_output = source_output ["wic_anchor" ]
266+ tgt_node ['in' ][sk ] = yaml .load ('!* ' + str (source_output ), Loader = wic_loader ())
267+ # the inputs which aren't dependent on previous/other steps
268+ # they are by default inline input
269+ diff_keys = set (tgt_in_keys ) - set (src_out_keys )
270+ for dfk in diff_keys :
271+ tgt_node ['in' ][dfk ] = yaml .load ('!ii ' + str (tgt_node ['in' ][dfk ]), Loader = wic_loader ())
204272
205273 workflow_temp : Cwl = {}
206274 if inp_restrict ["links" ] != []:
0 commit comments