Simple Example¶
Let's have a look at the different PlantUML diagrams that the cwl2puml APIs are able to generate, given, for example, the conditional-workflows Workflow.
1. Parsing¶
It is needed to read first a CWL document from a remote public URL:
In [1]:
Copied!
import cwl_loader
cwl_document = cwl_loader.load_cwl_from_location('https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl')
import cwl_loader
cwl_document = cwl_loader.load_cwl_from_location('https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl')
2025-11-06 22:17:52.625 | DEBUG | cwl_loader:load_cwl_from_location:228 - Loading CWL document from https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl...
2025-11-06 22:17:52.794 | DEBUG | cwl_loader:_load_cwl_from_stream:231 - Reading stream from https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl...
2025-11-06 22:17:52.817 | DEBUG | cwl_loader:load_cwl_from_stream:203 - CWL data of type <class 'ruamel.yaml.comments.CommentedMap'> successfully loaded from stream
2025-11-06 22:17:52.817 | DEBUG | cwl_loader:load_cwl_from_yaml:143 - No needs to update the Raw CWL document since it targets already the v1.2
2025-11-06 22:17:52.818 | DEBUG | cwl_loader:load_cwl_from_yaml:145 - Parsing the raw CWL document to the CWL Utils DOM...
2025-11-06 22:17:53.194 | DEBUG | cwl_loader:load_cwl_from_yaml:158 - Raw CWL document successfully parsed to the CWL Utils DOM!
2025-11-06 22:17:53.195 | DEBUG | cwl_loader:load_cwl_from_yaml:160 - Dereferencing the steps[].run...
2025-11-06 22:17:53.196 | DEBUG | cwl_loader:_on_process:78 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#stac must be externally imported...
2025-11-06 22:17:53.197 | DEBUG | cwl_loader:_on_process:82 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-11-06 22:17:53.197 | DEBUG | cwl_loader:_on_process:78 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#rio_stack must be externally imported...
2025-11-06 22:17:53.198 | DEBUG | cwl_loader:_on_process:82 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-11-06 22:17:53.198 | DEBUG | cwl_loader:_on_process:78 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#rio_warp_stack must be externally imported...
2025-11-06 22:17:53.199 | DEBUG | cwl_loader:_on_process:82 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-11-06 22:17:53.199 | DEBUG | cwl_loader:_on_process:78 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#rio_color must be externally imported...
2025-11-06 22:17:53.200 | DEBUG | cwl_loader:_on_process:82 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-11-06 22:17:53.201 | DEBUG | cwl_loader:load_cwl_from_yaml:167 - steps[].run successfully dereferenced! Dereferencing the FQNs...
2025-11-06 22:17:53.201 | DEBUG | cwl_loader:load_cwl_from_yaml:171 - CWL document successfully dereferenced! Now verifying steps[].run integrity...
2025-11-06 22:17:53.202 | DEBUG | cwl_loader:load_cwl_from_yaml:175 - All steps[].run link are resolvable!
2025-11-06 22:17:53.204 | DEBUG | cwl_loader:load_cwl_from_yaml:178 - Sorting Process instances by dependencies....
2025-11-06 22:17:53.205 | DEBUG | cwl_loader:load_cwl_from_yaml:180 - Sorting process is over.
2025-11-06 22:17:53.205 | DEBUG | cwl_loader:_load_cwl_from_stream:240 - Stream from https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl successfully load!
2. PlantUML diagrams¶
The samples below show how to render CWL document to a specific PlantUML diagram:
In [2]:
Copied!
from cwl2puml import (
to_puml,
DiagramType
)
from cwl_utils.parser import InputEnumSchema
from io import (
StringIO,
BytesIO
)
from IPython.display import display_png
from plantuml import deflate_and_encode
from PIL import Image
from urllib.request import urlopen
def render(
diagram_type: DiagramType,
debug: bool = False
):
out = StringIO()
to_puml(
cwl_document=cwl_document,
workflow_id='main', # 'main' by default, but define it for demo purposes
diagram_type=diagram_type,
output_stream=out
)
clear_output = out.getvalue()
if debug:
print(clear_output)
encoded = deflate_and_encode(clear_output)
diagram_url = f"https://uml.planttext.com/plantuml/png/{encoded}"
with urlopen(diagram_url) as url:
img = Image.open(BytesIO(url.read()))
display_png(img)
from cwl2puml import (
to_puml,
DiagramType
)
from cwl_utils.parser import InputEnumSchema
from io import (
StringIO,
BytesIO
)
from IPython.display import display_png
from plantuml import deflate_and_encode
from PIL import Image
from urllib.request import urlopen
def render(
diagram_type: DiagramType,
debug: bool = False
):
out = StringIO()
to_puml(
cwl_document=cwl_document,
workflow_id='main', # 'main' by default, but define it for demo purposes
diagram_type=diagram_type,
output_stream=out
)
clear_output = out.getvalue()
if debug:
print(clear_output)
encoded = deflate_and_encode(clear_output)
diagram_url = f"https://uml.planttext.com/plantuml/png/{encoded}"
with urlopen(diagram_url) as url:
img = Image.open(BytesIO(url.read()))
display_png(img)
In [3]:
Copied!
render(DiagramType.ACTIVITY)
render(DiagramType.ACTIVITY)
In [4]:
Copied!
render(DiagramType.COMPONENT)
render(DiagramType.COMPONENT)
In [5]:
Copied!
render(DiagramType.CLASS)
render(DiagramType.CLASS)
In [6]:
Copied!
render(DiagramType.SEQUENCE)
render(DiagramType.SEQUENCE)
In [7]:
Copied!
render(DiagramType.STATE)
render(DiagramType.STATE)