comparison image_math.py @ 0:33b2ca53a566 draft

planemo upload for repository https://github.com/BMCV/galaxy-image-analysis/tree/master/tools/image_math commit b356d76025941b691c156f8ff931cd759d35b107
author imgteam
date Sat, 09 Mar 2024 22:04:19 +0000
parents
children 48fa3ac55df2
comparison
equal deleted inserted replaced
-1:000000000000 0:33b2ca53a566
1 import argparse
2 import ast
3 import operator
4
5 import numpy as np
6 import skimage.io
7
8
9 supported_operators = {
10 ast.Add: operator.add,
11 ast.Sub: operator.sub,
12 ast.Mult: operator.mul,
13 ast.Div: operator.truediv,
14 ast.FloorDiv: operator.floordiv,
15 ast.Pow: operator.pow,
16 ast.USub: operator.neg,
17 }
18
19
20 supported_functions = {
21 'sqrt': np.sqrt,
22 'abs': abs,
23 }
24
25
26 def eval_ast_node(node, inputs):
27 """
28 Evaluates a node of the syntax tree.
29 """
30
31 # Numeric constants evaluate to numeric values.
32 if isinstance(node, ast.Constant):
33 assert type(node.value) in (int, float)
34 return node.value
35
36 # Variables are looked up from the inputs and resolved.
37 if isinstance(node, ast.Name):
38 assert node.id in inputs.keys()
39 return inputs[node.id]
40
41 # Binary operators are evaluated based on the `supported_operators` dictionary.
42 if isinstance(node, ast.BinOp):
43 assert type(node.op) in supported_operators.keys(), node.op
44 op = supported_operators[type(node.op)]
45 return op(eval_ast_node(node.left, inputs), eval_ast_node(node.right, inputs))
46
47 # Unary operators are evaluated based on the `supported_operators` dictionary.
48 if isinstance(node, ast.UnaryOp):
49 assert type(node.op) in supported_operators.keys(), node.op
50 op = supported_operators[type(node.op)]
51 return op(eval_ast_node(node.operand, inputs))
52
53 # Function calls are evaluated based on the `supported_functions` dictionary.
54 if isinstance(node, ast.Call):
55 assert len(node.args) == 1 and len(node.keywords) == 0
56 assert node.func.id in supported_functions.keys(), node.func.id
57 func = supported_functions[node.func.id]
58 return func(eval_ast_node(node.args[0], inputs))
59
60 # The node is unsupported and could not be evaluated.
61 raise TypeError(f'Unsupported node type: "{node}"')
62
63
64 def eval_expression(expr, inputs):
65 return eval_ast_node(ast.parse(expr, mode='eval').body, inputs)
66
67
68 if __name__ == '__main__':
69
70 parser = argparse.ArgumentParser()
71 parser.add_argument('--expression', type=str, required=True)
72 parser.add_argument('--output', type=str, required=True)
73 parser.add_argument('--input', default=list(), action='append', required=True)
74 args = parser.parse_args()
75
76 inputs = dict()
77 im_shape = None
78 for input in args.input:
79 name, filepath = input.split(':')
80 im = skimage.io.imread(filepath)
81 assert name not in inputs, 'Input name "{name}" is ambiguous.'
82 inputs[name] = im
83 if im_shape is None:
84 im_shape = im.shape
85 else:
86 assert im.shape == im_shape, 'Input images differ in size and/or number of channels.'
87
88 result = eval_expression(args.expression, inputs)
89
90 skimage.io.imsave(args.output, result)