def ingest_workflow(self, workflow): wf = j.WorkflowBuilder( identifier=self.get_tag_from_identifier(workflow.id), friendly_name=workflow.label, doc=workflow.doc, ) for inp in workflow.inputs: self.ingest_workflow_input(wf, inp) steps_to_process = workflow.steps iters = len(steps_to_process)**2 while len(steps_to_process) > 0: stp = steps_to_process.pop(0) try: self.ingest_workflow_step(wf, stp) except KeyError as e: steps_to_process.append(stp) if iters < 0: print("") iters -= 1 if iters < 0: print("Oh god...") if iters < -len(steps_to_process)**2: raise Exception("Probably stuck in some weird loop, we're ") # for stp in workflow.steps: # self.ingest_workflow_step(wf, stp) for out in workflow.outputs: self.ingest_workflow_output(wf, out) return wf
def from_loaded_workflow(self, obj: WDL.Workflow): wf = j.WorkflowBuilder(identifier=obj.name) for inp in obj.inputs: self.add_decl_to_wf_input(wf, inp) for call in obj.body: self.add_call_to_wf(wf, call) return wf
def test_basic_extension_override(self): w = j.WorkflowBuilder("wf") w.step("stp", ct) w.output("out", source=w.stp.out, extension="_fastqc.txt") outputs = WorkflowManager.evaluate_output_params(wf=w, inputs={}, submission_id="SID", run_id="RID") self.assertEqual("_fastqc.txt", outputs[0].extension)
# the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import janis_core as j # from ... import ToolWithTwoInputs wf = j.WorkflowBuilder("scatter_execution") # Two inputs that can have different lengths wf.input("input1", j.Array(j.String)) wf.input("input2", j.Array(j.String)) wf.step( "run_toolwithtwoinputs", # Connect the inputs as normal ToolWithTwoInputs(toolInput1=wf.input1, toolInput2=wf.input2), # Scatter of the 'inp' input of Echo. scatter=j.ScatterDescription( fields=["toolInput1", "toolInput2"], method=j.ScatterMethod.cross ), )
ToolWithSecondaryFiles = j.CommandToolBuilder( tool="secondary_files", version="v0.1.0", container="ubuntu:latest", base_command="echo", inputs=[j.ToolInput("inp", MyDataTypeWithSecondaries, position=0)], outputs=[ j.ToolOutput( "out", MyDataTypeWithSecondaries, selector="file.txt", ) ], ) WorkflowWithSecondaries = j.WorkflowBuilder("workflow_with_secondaries") inner_dt = MyDataTypeWithSecondaries scatter = None # helper method to show how scatters / not scatters work should_scatter = False if should_scatter: inner_dt = j.Array(MyDataTypeWithSecondaries) scatter = "inp" WorkflowWithSecondaries.input("inp", inner_dt) WorkflowWithSecondaries.step( "stp", ToolWithSecondaryFiles(inp=WorkflowWithSecondaries.inp), scatter=scatter ) WorkflowWithSecondaries.output("out", source=WorkflowWithSecondaries.stp.out)
import janis_core as j from janis_core import ToolInput, ToolOutput, Int, Stdout, File from janis_unix.tools import Echo AddTwo = j.CommandToolBuilder( tool="expr", base_command=None, arguments=[j.ToolArgument("expr 2 + ", position=0, shell_quote=False)], version="dev", container="ubuntu:latest", inputs=[ ToolInput("inp", Int(), position=1) ], outputs=[ ToolOutput("out", Stdout()), ] ) w = j.WorkflowBuilder("str_to_int") w.input("str_input", str) w.step("echo", Echo(inp=w.str_input)) w.step("exp", AddTwo(inp=w.echo.out.contents().as_int())) w.output("out", source=w.exp.out) if __name__ == "__main__": w.translate("wdl")
type: string expression: '${return {out: inputs._printout.contents }}' outputs: - id: out type: string outputSource: _evaluate-output-out/out In WDL this is translated as you'd expect: output { String out = read_string(print.out) } """ import janis_core as j from janis_unix.tools import Echo w = j.WorkflowBuilder("readfile") w.input("file_to_read", j.File) # Read the contents of a file to give to Echo w.step("print", Echo(inp="File contents: " + w.file_to_read.contents())) # Read the contents of the output of "print" to return as the output w.output("out", source=w.print.out.contents()) if __name__ == "__main__": w.translate("cwl")
# the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import janis_core as j from janis_unix.tools import Echo # Declare workflow builder w = j.WorkflowBuilder("my_conditional_workflow") # Expose an input called 'inp' which is an optional string w.input("inp", j.String(optional=True), doc="Will br printed if the string has value") w.input("my_integer", int) my_operation = True & w.my_other_boolean_input w.step( "print_if_has_value", Echo(inp=w.inp), # only print if the input "inp" is defined. when=w.my_integer > 5)
import janis_core as j from janis.tools import Echo w = j.WorkflowBuilder("workflowId") w.input("input_id", j.String, default="Hello, World!") w.step("step_id", Echo(inp=w.input_id)) w.output("output_id", source=w.step_id.out) # Will print the CWL, input file and relevant tools to the console if __name__ == "__main__": w.translate("cwl", to_disk=False) # or "wdl"
import janis_core as j # Choose a tool from janis_unix.tools import Cat tool = Cat() # Declare which input (ids) to scatter on fields_to_scatter = {"file"} # State how to scatter those inputs scatter_method = j.ScatterMethod.dot # Declare a workflow called {tool.id() + "_scattered"} w = j.WorkflowBuilder(tool.id() + "_scattered") # Pass through the inputs, but make any "fields_to_scatter" a j.Array, store these values in a map of inputs inps = { inp.id(): w.input( inp.id(), j.Array(inp.intype) if inp.id() in fields_to_scatter else inp.intype, ) for inp in tool.tool_inputs() } # Create a step: stp = w.step( # with step_id same as the tool name tool.id().lower(), # by spreading those inputs (we just declared) onto the tool.
class ToUpper(j.PythonTool): @staticmethod def code_block(inp: str) -> dict: # list splits "abc" into ["a", "b", "c"] return {"out": inp.upper()} def outputs(self): return [j.TOutput("out", j.String())] # Now that we have our tool definitions, we can construct our workflow # Workflow definition called "split_and_upper" wf = j.WorkflowBuilder("split_and_upper") # The workflow input, which is of type STRING wf.input("input_text", j.String()) # Create a step called 'split', call `SplitText` that takes a string input called 'inp'. # The output can be accessed by `wf.split.out`, which will have type Array(String). wf.step("split", SplitText(inp=wf.input_text)) # Create a step called 'toupper', called the `ToUpper` tool which has a single # input called 'inp'. Because we're operating on an array, we'll use the `scatter="inp"` # argument, to scatter over the ToUpper's input called "inp". # The output will be implicitly _gathered_, and hence `wf.toupper.out` will have type Array(String). wf.step("toupper", ToUpper(inp=wf.split.out), scatter="inp") # We'll use the gathered output, and use the janis `j.standard.JoinOperator(iterable, separator)`
# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. """ Create a step whose value is dependent on multiplying an input number, and the length of an list input. We construct the combination of operators using fairly natural Python syntax. """ import janis_core as j from janis_unix.tools import Echo w = j.WorkflowBuilder("multiply") w.input("number_input", int) w.input("list_input", j.Array(j.String())) # The input expression: # (w.number_input * w.list_input.length()).as_str() # is equivalent to the following manually constructed: # j.AsStringOperator(j.MultiplyOperator(w.number_inputs, j.LengthOperator(w.list_input))) w.step("multiply", Echo(inp=(w.number_input * w.list_input.length()).as_str())) w.output("out", source=w.number_input.as_str() + w.multiply.out.contents() + "my-output")
@staticmethod def name(): return "SubFile" ToolThatAcceptsSubFile = j.CommandToolBuilder( tool="acceptingSubFile", base_command="cat", inputs=[j.ToolInput("inp", SubFile)], outputs=[j.ToolOutput("out", j.Stdout(SubFile))], version="test", container="ubuntu:latest", ) # Declare workflow we're we'll use the type alias w = j.WorkflowBuilder("aliasing") w.input("inp", SubFile) w.step("stp1", Cat(file=w.inp)) # This line would cause the following critical message to be logged: # [CRITICAL]: Mismatch of types when joining 'stp1.out' to 'stp2.inp': stdout<File> -/→ SubFile # w.step("stp2", ToolThatAcceptsSubFile(inp=w.stp1.out)) # Instead, we'll use the .as_type method: w.step("stp2", ToolThatAcceptsSubFile(inp=w.stp1.out.as_type(SubFile))) w.output("out", source=w.stp2.out) if __name__ == "__main__": w.translate("wdl")
from typing import Optional, List import janis_core as j # Although not preferred, you can use Python primitives, and typing # annotations in place of the Janis types: # str - j.String() # int - j.Int() # float - j.Float() # bool - j.Boolean() # # typing.Optional[str] - j.String(optional=True) # typing.List[str] - j.Array(j.String()) workflow = j.WorkflowBuilder("typing_tests") workflow.input("my_string_input_1", j.String()) workflow.input("my_string_input_2", str) workflow.input("my_optional_str_input_1", j.String(optional=True)) workflow.input("my_optional_str_input_2", Optional[str]) workflow.input("my_list_of_strings_input_1", j.Array(j.String())) workflow.input("my_list_of_strings_input_2", List[str]) workflow.input("my_optional_list_of_strings_1", j.Array(j.String(), optional=True)) workflow.input("my_optional_list_of_strings_2", Optional[List[str]]) workflow.input("my_list_of_optional_strings_1",