comparison env/lib/python3.9/site-packages/galaxy/tool_util/parser/output_objects.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 from galaxy.util.dictifiable import Dictifiable
2 from .output_actions import ToolOutputActionGroup
3 from .output_collection_def import dataset_collector_descriptions_from_output_dict
4
5
6 class ToolOutputBase(Dictifiable):
7
8 def __init__(self, name, label=None, filters=None, hidden=False, from_expression=None):
9 super().__init__()
10 self.name = name
11 self.label = label
12 self.filters = filters or []
13 self.hidden = hidden
14 self.collection = False
15 self.from_expression = from_expression
16
17 def to_dict(self, view='collection', value_mapper=None, app=None):
18 return super().to_dict(view=view, value_mapper=value_mapper)
19
20
21 class ToolOutput(ToolOutputBase):
22 """
23 Represents an output datasets produced by a tool. For backward
24 compatibility this behaves as if it were the tuple::
25
26 (format, metadata_source, parent)
27 """
28
29 dict_collection_visible_keys = ['name', 'format', 'label', 'hidden', 'output_type', 'format_source',
30 'default_identifier_source', 'metadata_source', 'parent', 'count', 'from_work_dir']
31
32 def __init__(self, name, format=None, format_source=None, metadata_source=None,
33 parent=None, label=None, filters=None, actions=None, hidden=False,
34 implicit=False, from_expression=None):
35 super().__init__(name, label=label, filters=filters, hidden=hidden, from_expression=from_expression)
36 self.output_type = "data"
37 self.format = format
38 self.format_source = format_source
39 self.metadata_source = metadata_source
40 self.parent = parent
41 self.actions = actions
42
43 # Initialize default values
44 self.change_format = []
45 self.implicit = implicit
46 self.from_work_dir = None
47
48 # Tuple emulation
49
50 def __len__(self):
51 return 3
52
53 def __getitem__(self, index):
54 if index == 0:
55 return self.format
56 elif index == 1:
57 return self.metadata_source
58 elif index == 2:
59 return self.parent
60 else:
61 raise IndexError(index)
62
63 def __iter__(self):
64 return iter((self.format, self.metadata_source, self.parent))
65
66 def to_dict(self, view='collection', value_mapper=None, app=None):
67 as_dict = super().to_dict(view=view, value_mapper=value_mapper, app=app)
68 format = self.format
69 if format and format != "input" and app:
70 edam_format = app.datatypes_registry.edam_formats.get(self.format)
71 as_dict["edam_format"] = edam_format
72 edam_data = app.datatypes_registry.edam_data.get(self.format)
73 as_dict["edam_data"] = edam_data
74 as_dict['discover_datasets'] = list(map(lambda d: d.to_dict(), self.dataset_collector_descriptions))
75 return as_dict
76
77 @staticmethod
78 def from_dict(name, output_dict, tool=None):
79 output = ToolOutput(name)
80 output.format = output_dict.get("format", "data")
81 output.change_format = []
82 output.format_source = output_dict.get("format_source", None)
83 output.default_identifier_source = output_dict.get("default_identifier_source", None)
84 output.metadata_source = output_dict.get("metadata_source", "")
85 output.parent = output_dict.get("parent", None)
86 output.label = output_dict.get("label", None)
87 output.count = output_dict.get("count", 1)
88 output.filters = []
89 output.tool = tool
90 output.from_work_dir = output_dict.get("from_work_dir", None)
91 output.hidden = output_dict.get("hidden", "")
92 # TODO: implement tool output action group fixes
93 output.actions = ToolOutputActionGroup(output, None)
94 output.dataset_collector_descriptions = dataset_collector_descriptions_from_output_dict(output_dict)
95 return output
96
97
98 class ToolExpressionOutput(ToolOutputBase):
99 dict_collection_visible_keys = ('name', 'format', 'label', 'hidden', 'output_type')
100
101 def __init__(self, name, output_type, from_expression,
102 label=None, filters=None, actions=None, hidden=False):
103 super().__init__(name, label=label, filters=filters, hidden=hidden)
104 self.output_type = output_type # JSON type...
105 self.from_expression = from_expression
106 self.format = "expression.json" # galaxy.datatypes.text.ExpressionJson.file_ext
107
108 self.format_source = None
109 self.metadata_source = None
110 self.parent = None
111 self.actions = actions
112
113 # Initialize default values
114 self.change_format = []
115 self.implicit = False
116 self.from_work_dir = None
117
118
119 class ToolOutputCollection(ToolOutputBase):
120 """
121 Represents a HistoryDatasetCollectionAssociation of output datasets produced
122 by a tool.
123
124 .. code-block::
125
126 <outputs>
127 <collection type="list" label="${tool.name} on ${on_string} fasta">
128 <discover_datasets pattern="__name__" ext="fasta" visible="True" directory="outputFiles" />
129 </collection>
130 <collection type="paired" label="${tool.name} on ${on_string} paired reads">
131 <data name="forward" format="fastqsanger" />
132 <data name="reverse" format="fastqsanger"/>
133 </collection>
134 <outputs>
135 """
136 dict_collection_visible_keys = ['name', 'format', 'label', 'hidden', 'output_type', 'default_format',
137 'default_format_source', 'default_metadata_source', 'inherit_format', 'inherit_metadata']
138
139 def __init__(
140 self,
141 name,
142 structure,
143 label=None,
144 filters=None,
145 hidden=False,
146 default_format="data",
147 default_format_source=None,
148 default_metadata_source=None,
149 inherit_format=False,
150 inherit_metadata=False
151 ):
152 super().__init__(name, label=label, filters=filters, hidden=hidden)
153 self.output_type = "collection"
154 self.collection = True
155 self.default_format = default_format
156 self.structure = structure
157 self.outputs = {}
158
159 self.inherit_format = inherit_format
160 self.inherit_metadata = inherit_metadata
161
162 self.metadata_source = default_metadata_source
163 self.format_source = default_format_source
164 self.change_format = [] # TODO
165
166 def known_outputs(self, inputs, type_registry):
167 if self.dynamic_structure:
168 return []
169
170 # This line is probably not right - should verify structured_like
171 # or have outputs and all outputs have name.
172 if len(self.outputs) > 1:
173 output_parts = [ToolOutputCollectionPart(self, k, v) for k, v in self.outputs.items()]
174 else:
175 collection_prototype = self.structure.collection_prototype(inputs, type_registry)
176
177 def prototype_dataset_element_to_output(element, parent_ids=None):
178 parent_ids = parent_ids or []
179 name = element.element_identifier
180 format = self.default_format
181 if self.inherit_format:
182 format = element.dataset_instance.ext
183 output = ToolOutput(
184 name,
185 format=format,
186 format_source=self.format_source,
187 metadata_source=self.metadata_source,
188 implicit=True,
189 )
190 if self.inherit_metadata:
191 output.metadata_source = element.dataset_instance
192 return ToolOutputCollectionPart(
193 self,
194 element.element_identifier,
195 output,
196 parent_ids=parent_ids,
197 )
198
199 def prototype_collection_to_output(collection_prototype, parent_ids=None):
200 parent_ids = parent_ids or []
201 output_parts = []
202 for element in collection_prototype.elements:
203 element_parts = []
204 if not element.is_collection:
205 element_parts.append(prototype_dataset_element_to_output(element, parent_ids))
206 else:
207 new_parent_ids = parent_ids[:] + [element.element_identifier]
208 element_parts.extend(prototype_collection_to_output(element.element_object, new_parent_ids))
209 output_parts.extend(element_parts)
210
211 return output_parts
212
213 output_parts = prototype_collection_to_output(collection_prototype)
214
215 return output_parts
216
217 @property
218 def dynamic_structure(self):
219 return self.structure.dynamic
220
221 @property
222 def dataset_collector_descriptions(self):
223 if not self.dynamic_structure:
224 raise Exception("dataset_collector_descriptions called for output collection with static structure")
225 return self.structure.dataset_collector_descriptions
226
227 def to_dict(self, view='collection', value_mapper=None, app=None):
228 as_dict = super().to_dict(view=view, value_mapper=value_mapper, app=app)
229 as_dict['structure'] = self.structure.to_dict()
230 return as_dict
231
232 @staticmethod
233 def from_dict(name, output_dict, tool=None):
234 structure = ToolOutputCollectionStructure.from_dict(output_dict["structure"])
235 rval = ToolOutputCollection(
236 name,
237 structure=structure,
238 label=output_dict.get("label", None),
239 filters=None,
240 hidden=output_dict.get("hidden", False),
241 default_format=output_dict.get("default_format", "data"),
242 default_format_source=output_dict.get("default_format_source", None),
243 default_metadata_source=output_dict.get("default_metadata_source", None),
244 inherit_format=output_dict.get("inherit_format", False),
245 inherit_metadata=output_dict.get("inherit_metadata", False),
246 )
247 return rval
248
249
250 class ToolOutputCollectionStructure:
251
252 def __init__(
253 self,
254 collection_type,
255 collection_type_source=None,
256 collection_type_from_rules=None,
257 structured_like=None,
258 dataset_collector_descriptions=None,
259 ):
260 self.collection_type = collection_type
261 self.collection_type_source = collection_type_source
262 self.collection_type_from_rules = collection_type_from_rules
263 self.structured_like = structured_like
264 self.dataset_collector_descriptions = dataset_collector_descriptions or []
265 if collection_type and collection_type_source:
266 raise ValueError("Cannot set both type and type_source on collection output.")
267 if collection_type is None and structured_like is None and dataset_collector_descriptions is None and collection_type_source is None and collection_type_from_rules is None:
268 raise ValueError("Output collection types must specify source of collection type information (e.g. structured_like or type_source).")
269 if dataset_collector_descriptions and (structured_like or collection_type_from_rules):
270 raise ValueError("Cannot specify dynamic structure (discovered_datasets) and collection type attributes structured_like or collection_type_from_rules.")
271 self.dynamic = bool(dataset_collector_descriptions)
272
273 def collection_prototype(self, inputs, type_registry):
274 # either must have specified structured_like or something worse
275 if self.structured_like:
276 collection_prototype = inputs[self.structured_like].collection
277 else:
278 collection_type = self.collection_type
279 assert collection_type
280 collection_prototype = type_registry.prototype(collection_type)
281 collection_prototype.collection_type = collection_type
282 return collection_prototype
283
284 def to_dict(self):
285 return {
286 'collection_type': self.collection_type,
287 'collection_type_source': self.collection_type_source,
288 'collection_type_from_rules': self.collection_type_from_rules,
289 'structured_like': self.structured_like,
290 'discover_datasets': [d.to_dict() for d in self.dataset_collector_descriptions],
291 }
292
293 @staticmethod
294 def from_dict(as_dict):
295 structure = ToolOutputCollectionStructure(
296 collection_type=as_dict['collection_type'],
297 collection_type_source=as_dict['collection_type_source'],
298 collection_type_from_rules=as_dict['collection_type_from_rules'],
299 structured_like=as_dict['structured_like'],
300 dataset_collector_descriptions=dataset_collector_descriptions_from_output_dict(as_dict),
301 )
302 return structure
303
304
305 class ToolOutputCollectionPart:
306
307 def __init__(self, output_collection_def, element_identifier, output_def, parent_ids=None):
308 parent_ids = parent_ids or []
309 self.output_collection_def = output_collection_def
310 self.element_identifier = element_identifier
311 self.output_def = output_def
312 self.parent_ids = parent_ids
313
314 @property
315 def effective_output_name(self):
316 name = self.output_collection_def.name
317 part_name = self.element_identifier
318 effective_output_name = f"{name}|__part__|{part_name}"
319 return effective_output_name
320
321 @staticmethod
322 def is_named_collection_part_name(name):
323 return "|__part__|" in name
324
325 @staticmethod
326 def split_output_name(name):
327 assert ToolOutputCollectionPart.is_named_collection_part_name(name)
328 return name.split("|__part__|")