Exemple #1
0
 def outputs(self) -> List[j.TOutput]:
     return [
         j.TOutput("out_file", j.File, doc="Single file to compare"),
         j.TOutput("line_count", j.Int, doc="Number of lines in the file"),
         j.TOutput("misc_files",
                   j.Array(j.File),
                   doc="array of output file, to show array index"),
     ]
Exemple #2
0
    def ingest_cwl_type(self, cwl_type, secondary_files):
        inp_type = self.from_cwl_inner_type(cwl_type)
        if secondary_files:
            array_optional_layers = []
            while isinstance(inp_type, j.Array):
                array_optional_layers.append(inp_type.optional)
                inp_type = inp_type.subtype()

            inp_type = self.get_data_type_from_secondaries(
                secondaries=self.process_secondary_files(secondary_files),
                optional=inp_type.optional,
            )
            for is_optional in array_optional_layers[::-1]:
                inp_type = j.Array(inp_type, optional=is_optional)

        return inp_type
Exemple #3
0
    def parse_wdl_type(self, t: WDL.Type.Base):
        optional = t.optional
        if isinstance(t, WDL.Type.Int):
            return j.Int(optional=optional)
        elif isinstance(t, WDL.Type.String):
            return j.String(optional=optional)
        elif isinstance(t, WDL.Type.Float):
            return j.Float(optional=optional)
        elif isinstance(t, WDL.Type.Boolean):
            return j.Boolean(optional=optional)
        elif isinstance(t, WDL.Type.File):
            return j.File(optional=optional)
        elif isinstance(t, WDL.Type.Directory):
            return j.Directory(optional=optional)
        elif isinstance(t, WDL.Type.Array):
            return j.Array(self.parse_wdl_type(t.item_type), optional=optional)

        raise Exception(
            f"Didn't handle WDL type conversion for '{t}' ({type(t)})")
Exemple #4
0
# 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
    ),
)

# This will automatically be an array of files
# because wf.run_toolwithtwoinputs has a scatter block.
wf.output("out", source=wf.run_toolwithtwoinputs.out)
Exemple #5
0
    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)

if __name__ == "__main__":
    ToolWithSecondaryFiles().translate("wdl")
    # WorkflowWithSecondaries().translate("wdl")
Exemple #6
0
    def from_cwl_inner_type(self, cwl_type) -> j.DataType:
        if isinstance(cwl_type, str):
            optional = "?" in cwl_type
            cwl_type = cwl_type.replace("?", "")
            array_count = 0
            while cwl_type.endswith("[]"):
                array_count += 1
                cwl_type = cwl_type[:-2]

            if cwl_type == "File":
                inner = j.File
            elif cwl_type == "Directory":
                inner = j.Directory
            elif cwl_type == "string":
                inner = j.String
            elif cwl_type == "int":
                inner = j.Int
            elif cwl_type == "float":
                inner = j.Float
            elif cwl_type == "boolean":
                inner = j.Boolean
            elif cwl_type == "stdout":
                inner = j.Stdout
            elif cwl_type == "stderr":
                inner = j.Stderr
            elif cwl_type == "Any":
                inner = j.String
            elif cwl_type == "long":
                inner = j.Int
            else:
                raise Exception(f"Can't detect type {cwl_type}")
            return inner(optional=optional)

        elif isinstance(cwl_type, list):
            optional = None
            types = []
            for c in cwl_type:
                if c == "null":
                    optional = True
                else:
                    types.append(self.ingest_cwl_type(c, []))

            if len(types) == 1:
                if optional is not None:
                    types[0].optional = optional
                return types[0]
            else:
                from janis_core.types.common_data_types import UnionType

                if optional is not None:
                    for inner in types:
                        inner.optional = optional

                return UnionType(*types)

        elif isinstance(cwl_type, self.cwlgen.CommandInputArraySchema):
            return j.Array(self.from_cwl_inner_type(cwl_type.items))
        elif isinstance(cwl_type, self.cwlgen.InputArraySchema):
            return j.Array(self.from_cwl_inner_type(cwl_type.items))
        elif isinstance(cwl_type, self.cwlgen.CommandOutputArraySchema):
            return j.Array(self.from_cwl_inner_type(cwl_type.items))
        elif isinstance(cwl_type, self.cwlgen.OutputArraySchema):
            return j.Array(self.from_cwl_inner_type(cwl_type.items))
        elif isinstance(cwl_type, self.cwlgen.InputEnumSchema):
            return j.String()

        else:
            raise Exception(f"Can't parse type {type(cwl_type).__name__}")
Exemple #7
0
 def outputs(self) -> List[j.TOutput]:
     return [j.TOutput("out", j.Array(j.Int))]
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.
    tool(**inps),
    # declaring the scatter information
    scatter=j.ScatterDescription(fields=list(fields_to_scatter),
                                 method=scatter_method),
)
 def outputs(self):
     return [j.TOutput("out", j.Array(j.String()))]
Exemple #10
0
NB: Although WDL supports optional files, some backends of Cromwell do not.
"""

import janis_core as j

ToolWithOptionalWildcardOutput = j.CommandToolBuilder(
    tool="optional_wildcard_output_tool",
    version="v0.1.0",
    container="ubuntu:latest",
    base_command=None,
    # write '1' to a file called 'out.csv'
    arguments=[j.ToolArgument("echo 1 > out.csv", shell_quote=False)],
    inputs=[j.ToolInput("inp", j.File, localise_file=True)],
    outputs=[
        j.ToolOutput("out_csv_files",
                     j.Array(j.File),
                     selector=j.WildcardSelector("*.csv")),
        # the next two are functionally equivalent
        j.ToolOutput("out_single_csv_file_1",
                     j.Array(j.File),
                     selector=j.WildcardSelector("*.csv", select_first=True)),
        j.ToolOutput("out_single_csv_file_2",
                     j.Array(j.File),
                     selector=j.WildcardSelector("*.csv")[0]),

        # OPTIONAL glob outputs
        # capture all files with *.txt pattern (but select the first if possible)
        j.ToolOutput("out_optional_glob",
                     j.File(optional=True),
                     selector=j.WildcardSelector("*.txt", select_first=True))
    ],
# 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

CommandLineThatBindsArrays = j.CommandToolBuilder(
    tool="CommandLineThatBindsArrays",
    container="ubuntu:latest",
    version="development",
    base_command="echo",
    inputs=[
        # NO prefix, joined by space (' ')  [DEFAULT]
        #   need a position to ensure it binds onto the command line
        j.ToolInput("array1", j.Array(j.String), position=0),
        #
        # No prefix, joined by commans (',')
        j.ToolInput("array2", j.Array(j.String), separator=",", position=1),
        #
        # Single prefix, then joined by space (' ')
        j.ToolInput("array3", j.Array(j.String), prefix="--prefix"),
        #
        # Single prefix, then joined by commas (',')
        j.ToolInput("array4",
                    j.Array(j.String),
                    prefix="--prefix",
                    separator=","),
        #
        # Prefix applies to each element
        j.ToolInput(
# it under the terms of the GNU General Public License as published by
# 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

wf = j.WorkflowBuilder("scatter_execution")

wf.input("inputs", j.Array(j.String))

wf.step(
    "print",
    # Connect the regular array inputs
    Echo(inp=wf.inputs),
    # Scatter of the 'inp' input of Echo.
    scatter="inp",
)

# This will automatically be an array of files
# because wf.print has a scatter block.
wf.output("out", source=wf.print.out)
#
# 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")

if __name__ == "__main__":
    w.translate("wdl")
Exemple #14
0
 def outputs(self) -> List[j.TOutput]:
     return [j.TOutput("out_regions", j.Array(Bed))]
# 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",
               j.Array(j.String(optional=True)))
workflow.input("my_list_of_optional_strings_2", List[Optional[str]])
Exemple #16
0
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
We'll use Janis to _try_ and collect a SINGLE file with the extension '.txt',
but one won't exist. CWL will automatically coerce the empty File[0] to File? (null).

However, in WDL, we have do this slightly differently:
    File? out = if length(glob("*.txt")) > 0 then glob("*.txt")[0] else None

NB: Although WDL supports optional files, some backends of Cromwell do not.
"""

import janis_core as j

ToolWithDynamicGlob = j.CommandToolBuilder(
    tool="tool_with_dynamic_glob",
    version="v0.1.0",
    container="ubuntu:latest",
    base_command=None,
    # write '1' to a file called 'out.csv'
    arguments=[j.ToolArgument("echo 1 > out.csv", shell_quote=False)],
    inputs=[j.ToolInput("extension", str)],
    outputs=[
        j.ToolOutput("out_csv_files", j.Array(j.File), selector=j.WildcardSelector("*" + j.InputSelector("extension"))),
    ],
)

if __name__ == "__main__":
    ToolWithDynamicGlob().translate("cwl")