Skip to content

Commit 0783b4f

Browse files
sameeulVasu Jaganath
andauthored
Link order fix (PolusAI#299)
* Update logic for ordering steps * Update dir search logic * correctly pre-process node when single node --------- Co-authored-by: Vasu Jaganath <[email protected]>
1 parent 5e84d68 commit 0783b4f

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

src/sophios/api/utils/converter.py

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,53 @@ def raw_wfb_to_lean_wfb(inp: Json) -> Json:
100100
return inp_restrict
101101

102102

103+
def get_topological_order(links: list[dict[str, str]]) -> list[str]:
104+
"""Get topological order of the nodes from links"""
105+
# Create adjacency list representation
106+
graph: dict[str, list[str]] = {}
107+
in_degree: dict[str, int] = {}
108+
109+
# Initialize all nodes with 0 in-degree
110+
for link in links:
111+
source = link['sourceId']
112+
target = link['targetId']
113+
if source not in graph:
114+
graph[source] = []
115+
if target not in graph:
116+
graph[target] = []
117+
if source not in in_degree:
118+
in_degree[source] = 0
119+
if target not in in_degree:
120+
in_degree[target] = 0
121+
122+
# Build the graph and count in-degrees
123+
for link in links:
124+
source = link['sourceId']
125+
target = link['targetId']
126+
graph[source].append(target)
127+
in_degree[target] += 1
128+
129+
# Initialize queue with nodes that have 0 in-degree
130+
queue: list[str] = []
131+
for node in in_degree:
132+
if in_degree[node] == 0:
133+
queue.append(node)
134+
135+
# Process the queue
136+
result: list[str] = []
137+
while queue:
138+
node = queue.pop(0)
139+
result.append(node)
140+
141+
# Reduce in-degree of neighbors
142+
for neighbor in graph[node]:
143+
in_degree[neighbor] -= 1
144+
if in_degree[neighbor] == 0:
145+
queue.append(neighbor)
146+
147+
return result
148+
149+
103150
def wfb_to_wic(inp: Json) -> Cwl:
104151
"""Convert lean wfb json to compliant wic"""
105152
# non-schema preserving changes
@@ -155,18 +202,21 @@ def wfb_to_wic(inp: Json) -> Cwl:
155202
for dfk in diff_keys:
156203
tgt_node['in'][dfk] = yaml.load('!ii ' + str(tgt_node['in'][dfk]), Loader=wic_loader())
157204

158-
for node in inp_restrict['nodes']:
159-
# just reuse name as node's pluginId, wic id is same as wfb name
160-
node['id'] = node['pluginId'].split('@')[0].replace('/', '_')
161-
node.pop('pluginId', None)
162-
163205
workflow_temp: Cwl = {}
164206
if inp_restrict["links"] != []:
207+
node_order = get_topological_order(inp_restrict["links"])
165208
workflow_temp["steps"] = []
166-
for node in inp_restrict["nodes"]:
167-
workflow_temp["steps"].append(node) # node["cwlScript"] # Assume dict form
209+
for id in node_order:
210+
node = next((n for n in inp_restrict["nodes"] if n["id"] == id), None)
211+
if node:
212+
# just reuse name as node's pluginId, wic id is same as wfb name
213+
node['id'] = node['pluginId'].split('@')[0].replace('/', '_')
214+
node.pop('pluginId', None)
215+
workflow_temp["steps"].append(node)
168216
else: # A single node workflow
169217
node = inp_restrict["nodes"][0]
218+
node['id'] = node['pluginId'].split('@')[0].replace('/', '_')
219+
node.pop('pluginId', None)
170220
if node.get("cwlScript"):
171221
workflow_temp = node["cwlScript"]
172222
else:

src/sophios/post_compile.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ def find_output_dirs(data: Union[RoseTree, Dict, list]) -> list:
2121
results = []
2222
if isinstance(data, Dict):
2323
if "class" in data and data["class"] == "Directory" and "location" in data:
24-
results.append(data["location"])
24+
if isinstance(data["location"], dict) and "wic_inline_input" in data["location"]:
25+
results.append(data["location"]["wic_inline_input"])
26+
else:
27+
results.append(data["location"])
2528
for value in data.values():
2629
results.extend(find_output_dirs(value))
2730
elif isinstance(data, list):

0 commit comments

Comments
 (0)