Mercurial > repos > galaxyp > openms_databasesuitability
comparison fill_ctd.py @ 0:3f555d385d45 draft
"planemo upload for repository https://github.com/galaxyproteomics/tools-galaxyp/tree/master/tools/openms commit 55a2aeba8bfd8a6910630721de9857dcdfe05d3c"
| author | galaxyp |
|---|---|
| date | Tue, 13 Oct 2020 18:22:43 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:3f555d385d45 |
|---|---|
| 1 import collections | |
| 2 import json | |
| 3 import operator | |
| 4 import os | |
| 5 import re | |
| 6 import subprocess | |
| 7 import sys | |
| 8 from functools import reduce # forward compatibility for Python 3 | |
| 9 | |
| 10 from CTDopts.CTDopts import ( | |
| 11 _Choices, | |
| 12 _InFile, | |
| 13 _Null, | |
| 14 _NumericRange, | |
| 15 CTDModel | |
| 16 ) | |
| 17 | |
| 18 | |
| 19 def getFromDict(dataDict, mapList): | |
| 20 return reduce(operator.getitem, mapList, dataDict) | |
| 21 | |
| 22 | |
| 23 def setInDict(dataDict, mapList, value): | |
| 24 getFromDict(dataDict, mapList[:-1])[mapList[-1]] = value | |
| 25 | |
| 26 | |
| 27 def mergeDicts(d, e): | |
| 28 """ | |
| 29 insert values from the dict e into dict d | |
| 30 no values of d are overwritten | |
| 31 """ | |
| 32 for k, v in e.items(): | |
| 33 if (k in d and isinstance(d[k], dict) and isinstance(e[k], collections.abc.Mapping)): | |
| 34 mergeDicts(d[k], e[k]) | |
| 35 elif k not in d and not isinstance(e[k], collections.abc.Mapping): | |
| 36 d[k] = e[k] | |
| 37 else: | |
| 38 sys.stderr.write("fill_ctd.py: could not merge key %s for %s in %s" % (k, d, e)) | |
| 39 sys.exit(1) | |
| 40 | |
| 41 | |
| 42 def _json_object_hook_noenvlookup(d): | |
| 43 return _json_object_hook(d, envlookup=False) | |
| 44 | |
| 45 | |
| 46 def _json_object_hook(d, envlookup=True): | |
| 47 """ | |
| 48 wee helper to transform the json written by galaxy | |
| 49 while loading | |
| 50 - True/False (bool objects) -> "true"/"false" (lowercase string) | |
| 51 - data inputs with multiple and optional true give [None] if no file is given -> [] | |
| 52 - None -> "" (empty string) | |
| 53 - replace bash expressions (if envlookup is True): | |
| 54 - environment variables (need to consist capital letters and _) by their value | |
| 55 - expressions | |
| 56 """ | |
| 57 for k in d.keys(): | |
| 58 # if type(d[k]) is bool: | |
| 59 # d[k] = str(d[k]).lower() | |
| 60 # else | |
| 61 if type(d[k]) is list and len(d[k]) == 1 and d[k][0] is None: | |
| 62 d[k] = [] | |
| 63 elif d[k] is None: | |
| 64 d[k] = "" | |
| 65 elif envlookup and type(d[k]) is str and d[k].startswith("$"): | |
| 66 m = re.fullmatch(r"\$([A-Z_]+)", d[k]) | |
| 67 if m: | |
| 68 d[k] = os.environ.get(m.group(1), "") | |
| 69 continue | |
| 70 m = re.fullmatch(r"\$(\{[A-Z_]+):-(.*)\}", d[k]) | |
| 71 if m: | |
| 72 d[k] = os.environ.get(m.group(1), m.group(2)) | |
| 73 continue | |
| 74 | |
| 75 try: | |
| 76 p = subprocess.run("echo %s" % d[k], shell=True, check=True, stdout=subprocess.PIPE, encoding="utf8") | |
| 77 d[k] = p.stdout.strip() | |
| 78 except subprocess.CalledProcessError: | |
| 79 sys.stderr.write("fill_ctd error: Could not evaluate %s" % d[k]) | |
| 80 continue | |
| 81 return d | |
| 82 | |
| 83 | |
| 84 def qstring2list(qs): | |
| 85 """ | |
| 86 transform a space separated string that is quoted by " into a list | |
| 87 """ | |
| 88 lst = list() | |
| 89 qs = qs.split(" ") | |
| 90 quoted = False | |
| 91 for p in qs: | |
| 92 if p == "": | |
| 93 continue | |
| 94 if p.startswith('"') and p.endswith('"'): | |
| 95 lst.append(p[1:-1]) | |
| 96 elif p.startswith('"'): | |
| 97 quoted = True | |
| 98 lst.append(p[1:] + " ") | |
| 99 elif p.endswith('"'): | |
| 100 quoted = False | |
| 101 lst[-1] += p[:-1] | |
| 102 else: | |
| 103 if quoted: | |
| 104 lst[-1] += p + " " | |
| 105 else: | |
| 106 lst.append(p) | |
| 107 return lst | |
| 108 | |
| 109 | |
| 110 def fix_underscores(args): | |
| 111 if type(args) is dict: | |
| 112 for k in list(args.keys()): | |
| 113 v = args[k] | |
| 114 if type(v) is dict: | |
| 115 fix_underscores(args[k]) | |
| 116 if k.startswith("_"): | |
| 117 args[k[1:]] = v | |
| 118 del args[k] | |
| 119 elif type(args) is list: | |
| 120 for i, v in enumerate(args): | |
| 121 if type(v) is dict: | |
| 122 fix_underscores(args[i]) | |
| 123 | |
| 124 | |
| 125 input_ctd = sys.argv[1] | |
| 126 | |
| 127 # load user specified parameters from json | |
| 128 with open(sys.argv[2]) as fh: | |
| 129 args = json.load(fh, object_hook=_json_object_hook_noenvlookup) | |
| 130 | |
| 131 # load hardcoded parameters from json | |
| 132 with open(sys.argv[3]) as fh: | |
| 133 hc_args = json.load(fh, object_hook=_json_object_hook) | |
| 134 | |
| 135 # insert the hc_args into the args | |
| 136 mergeDicts(args, hc_args) | |
| 137 | |
| 138 if "adv_opts_cond" in args: | |
| 139 args.update(args["adv_opts_cond"]) | |
| 140 del args["adv_opts_cond"] | |
| 141 | |
| 142 # IDMapper has in and spectra:in params, in is used in out as format_source", | |
| 143 # which does not work in Galaxy: https://github.com/galaxyproject/galaxy/pull/9493" | |
| 144 # therefore hardcoded params change the name of spectra:in to spectra:_in | |
| 145 # which is corrected here again | |
| 146 # TODO remove once PR is in and adapt profile accordingly | |
| 147 fix_underscores(args) | |
| 148 | |
| 149 model = CTDModel(from_file=input_ctd) | |
| 150 | |
| 151 # transform values from json that correspond to | |
| 152 # - old style booleans (string + restrictions) -> transformed to a str | |
| 153 # - new style booleans that get a string (happens for hidden parameters [-test]) | |
| 154 # are transformed to a bool | |
| 155 # - unrestricted ITEMLIST which are represented as strings | |
| 156 # ("=quoted and space separated) in Galaxy -> transform to lists | |
| 157 # - optional data input parameters that have defaults and for which no | |
| 158 # value is given -> overwritte with the default | |
| 159 for p in model.get_parameters(): | |
| 160 | |
| 161 # check if the parameter is in the arguments from the galaxy tool | |
| 162 # (from the json file(s)), since advanced parameters are absent | |
| 163 # if the conditional is set to basic parameters | |
| 164 try: | |
| 165 getFromDict(args, p.get_lineage(name_only=True)) | |
| 166 except KeyError: | |
| 167 # few tools use dashes in parameters which are automatically replaced | |
| 168 # by underscores by Galaxy. in these cases the dictionary needs to be | |
| 169 # updated (better: then dash and the underscore variant are in the dict) | |
| 170 # TODO might be removed later https://github.com/OpenMS/OpenMS/pull/4529 | |
| 171 try: | |
| 172 lineage = [_.replace("-", "_") for _ in p.get_lineage(name_only=True)] | |
| 173 val = getFromDict(args, lineage) | |
| 174 except KeyError: | |
| 175 continue | |
| 176 else: | |
| 177 setInDict(args, p.get_lineage(name_only=True), val) | |
| 178 | |
| 179 if p.type is str and type(p.restrictions) is _Choices and set(p.restrictions.choices) == set(["true", "false"]): | |
| 180 v = getFromDict(args, p.get_lineage(name_only=True)) | |
| 181 setInDict(args, p.get_lineage(name_only=True), str(v).lower()) | |
| 182 elif p.type is bool: | |
| 183 v = getFromDict(args, p.get_lineage(name_only=True)) | |
| 184 if isinstance(v, str): | |
| 185 v = (v.lower() == "true") | |
| 186 setInDict(args, p.get_lineage(name_only=True), v) | |
| 187 elif p.is_list and (p.restrictions is None or type(p.restrictions) is _NumericRange): | |
| 188 v = getFromDict(args, p.get_lineage(name_only=True)) | |
| 189 if type(v) is str: | |
| 190 setInDict(args, p.get_lineage(name_only=True), qstring2list(v)) | |
| 191 elif p.type is _InFile and not (p.default is None or type(p.default) is _Null): | |
| 192 v = getFromDict(args, p.get_lineage(name_only=True)) | |
| 193 if v in [[], ""]: | |
| 194 setInDict(args, p.get_lineage(name_only=True), p.default) | |
| 195 | |
| 196 model.write_ctd(input_ctd, arg_dict=args) |
