class ToWorldNode(FlowNode): pins = [ FlowPin('In', FlowPin.In), FlowPin('Out', FlowPin.Out) ] properties = [ IntProperty('order', 1) ] def __init__(self): super(ToWorldNode, self).__init__() self.node_class = 'image.resample.ToWorldNode' self.title = 'ToWorld' self.category = 'Image/Resample' self.ui_class = 'one_to_one_node' def run(self, ctx): img = ctx.read_pin('In') if hasattr(img, 'spacing'): out = Image(zoom(img, img.spacing[::-1], order=self.order), img.pixel_type) out.spacing = [1]*len(img.spacing) ctx.write_pin('Out', out) else: ctx.write_pin('Out', img)
class JetNode(FlowNode): pins = [ FlowPin('In', FlowPin.In), FlowPin('Min', FlowPin.In), FlowPin('Max', FlowPin.In), FlowPin('Out', FlowPin.Out) ] def __init__(self): super(JetNode, self).__init__() self.node_class = 'image.colormap.JetNode' self.title = 'Jet' self.category = 'Image/Colormaps' def run(self, ctx): img = ctx.read_pin('In') if self.is_pin_linked('Min'): min = ctx.read_pin('Min') else: min = img.min() if self.is_pin_linked('Max'): max = ctx.read_pin('Max') else: max = img.max() out = Image(colorize(img, min, max, 'jet'), PixelType_Vec4u8) if hasattr(img, 'spacing'): out.spacing = img.spacing if hasattr(img, 'origin'): out.origin = img.origin ctx.write_pin('Out', out)
class PerceptuallyUniformNode(FlowNode): pins = [ FlowPin('In', FlowPin.In), FlowPin('Min', FlowPin.In), FlowPin('Max', FlowPin.In), FlowPin('Out', FlowPin.Out) ] properties = [ EnumProperty('colormap', ['viridis', 'inferno', 'plasma', 'magma'], 0), ] def __init__(self): super(PerceptuallyUniformNode, self).__init__() self.node_class = 'image.colormap.PerceptuallyUniformNode' self.title = 'PerceptuallyUniform' self.category = 'Image/Colormaps' def run(self, ctx): img = ctx.read_pin('In') if self.is_pin_linked('Min'): min = ctx.read_pin('Min') else: min = img.min() if self.is_pin_linked('Max'): max = ctx.read_pin('Max') else: max = img.max() out = Image(colorize(img, min, max, self.colormap), PixelType_Vec4u8) if hasattr(img, 'spacing'): out.spacing = img.spacing if hasattr(img, 'origin'): out.origin = img.origin ctx.write_pin('Out', out)
class TransformixNode(FlowNode): pins = [ FlowPin('Image', FlowPin.In), FlowPin('Transform', FlowPin.In), FlowPin('Out', FlowPin.Out), FlowPin('Def', FlowPin.Out), FlowPin('Jac', FlowPin.Out), ] def __init__(self): super(TransformixNode, self).__init__() self.node_class = 'elastix.Transformix' self.title = 'Transformix' self.category = 'Elastix' self.value = '' def run(self, ctx): temp_dir = ctx.temp_node_dir() img = ctx.read_pin('Image') if img != None: if type(img) == image.Image: medkit.write(img, os.path.join(temp_dir, 'in.mhd')) img = os.path.join(temp_dir, 'in.mhd') if type(img) != str: raise ValueError('Unexpected type for pin \'Image\'') do_def = False do_jac = False if self.is_pin_linked('Def'): do_def = True if self.is_pin_linked('Jac'): do_jac = True transform = ctx.read_pin('Transform') if type(transform) == Parameters: transform.write(os.path.join(temp_dir, 'tp.txt')) transform = os.path.join(temp_dir, 'tp.txt') if type(transform) != str: raise ValueError('Unexpected type for pin \'Transform\'') run_transformix(transform, temp_dir, img=img, df=do_def, jac=do_jac) if self.is_pin_linked('Out') and img != None: ctx.write_pin('Out', medkit.read(os.path.join(temp_dir, 'result.nii'))) if do_def: ctx.write_pin( 'Def', medkit.read(os.path.join(temp_dir, 'deformationField.nii'))) if do_jac: ctx.write_pin( 'Jac', medkit.read(os.path.join(temp_dir, 'spatialJacobian.nii')))
class SleepNode(FlowNode): pins = [FlowPin('In', FlowPin.In), FlowPin('Out', FlowPin.Out)] properties = [ IntProperty('time', 0), ] def __init__(self): super(SleepNode, self).__init__() self.node_class = 'flow.debug.Sleep' self.title = 'Sleep' self.category = 'Debug' self.value = '' def run(self, ctx): time.sleep(int(self.time)) ctx.write_pin('Out', ctx.read_pin('In'))
class ImageSpacingNode(FlowNode): pins = [ FlowPin('In', FlowPin.In), FlowPin('Out', FlowPin.Out) ] def __init__(self): super(ImageSpacingNode, self).__init__() self.node_class = 'image.image.ImageSpacingNode' self.title = 'Spacing' self.category = 'Image/Meta' self.ui_class = 'one_to_one_node' def run(self, ctx): img = ctx.read_pin('In') ctx.write_pin('Out', img.spacing)
class Grid2DNode(FlowNode): pins = [FlowPin('Out', FlowPin.Out)] properties = [ IntProperty('width', 0), IntProperty('height', 0), IntProperty('step', 1), IntProperty('thickness', 1), ] def __init__(self): super(Grid2DNode, self).__init__() self.node_class = 'image.grid.Grid2DNode' self.title = 'Grid2D' self.category = 'Image/New' self.ui_class = 'single_pin_node' def run(self, ctx): h = self.height w = self.width img_data = np.zeros((h, w)).astype('uint8') for y in range(0, int(h / self.step) + 1): for x in range(0, w): for t in range(0, min(self.thickness, h - y * self.step - 1)): img_data[y * self.step + t, x] = 1 for x in range(0, int(w / self.step) + 1): for y in range(0, h): for t in range(0, min(self.thickness, w - x * self.step - 1)): img_data[y, x * self.step + t] = 1 ctx.write_pin('Out', Image(img_data, PixelType_UInt8))
class DTypeNode(FlowNode): pins = [FlowPin('In', FlowPin.In), FlowPin('Out', FlowPin.Out)] def __init__(self): super(DTypeNode, self).__init__() self.node_class = 'image.info.DTypeNode' self.title = 'DType' self.category = 'Image/Info' self.ui_class = 'one_to_one_node' def run(self, ctx): img = ctx.read_pin('In') if img is None or not isinstance(img, np.ndarray): raise ValueError('Expected an Image object') ctx.write_pin('Out', str(img.dtype))
class RegistrationNode(FlowNode): pins = [ ArrayFlowPin('Fixed', FlowPin.In), ArrayFlowPin('Moving', FlowPin.In), FlowPin('ConstraintMask', FlowPin.In), FlowPin('ConstraintValues', FlowPin.In), FlowPin('StartingGuess', FlowPin.In), FlowPin('Deformation', FlowPin.Out), ] properties = [FileProperty('param_file', '')] def __init__(self): super(RegistrationNode, self).__init__() self.node_class = 'registration.Registration' self.title = 'Registration' self.category = 'Registration' def run(self, ctx): settings = { 'step_size': 0.5, 'regularization_weight': 0.05, 'block_size': (12, 12, 12), 'pyramid_level_min': 0, 'pyramid_level_max': 6, } if self.param_file is not '': settings.update(parse_settings_old(self.param_file)) eng = RegistrationEngine('blocked_graph_cut', image.PixelType_Float64, settings) if self.is_pin_linked('ConstraintValues') or self.is_pin_linked( 'ConstraintMask'): eng.set_contraints(ctx.read_pin('ConstraintValues'), ctx.read_pin('ConstraintMask')) if self.is_pin_linked('StartingGuess'): eng.set_starting_guess(ctx.read_pin('StartingGuess')) fixed = ctx.read_pin('Fixed') moving = ctx.read_pin('Moving') df = eng.execute(fixed, moving) ctx.write_pin('Deformation', df)
class ReadNode(FlowNode): pins = [FlowPin('File', FlowPin.In), FlowPin('Image', FlowPin.Out)] properties = [ FileProperty('file', '', FileProperty.File_Open, "Image (*.*)"), ] def __init__(self): super(ReadNode, self).__init__() self.node_class = 'medkit.io.ReadNode' self.title = 'Read' self.category = 'Image/IO' def run(self, ctx): f = self.file if self.is_pin_linked('File'): f = ctx.read_pin('File') ctx.write_pin('Image', read(f))
class ImageSetSpacingNode(FlowNode): pins = [ FlowPin('In', FlowPin.In), FlowPin('Spacing', FlowPin.In), FlowPin('Out', FlowPin.Out) ] def __init__(self): super(ImageSetSpacingNode, self).__init__() self.node_class = 'image.image.ImageSetSpacingNode' self.title = 'SetSpacing' self.category = 'Image/Meta' def run(self, ctx): img = ctx.read_pin('In') spacing = ctx.read_pin('Spacing') if type(spacing) != tuple and type(spacing) != list: raise ValueError('Invalid spacing, expected tuple or list') img.spacing = spacing ctx.write_pin('Out', img)
class SetSliceImageNode(FlowNode): pins = [ FlowPin('In', FlowPin.In), FlowPin('Value', FlowPin.In), FlowPin('Out', FlowPin.Out) ] properties = [ StringProperty('slice', '0,0'), ] def __init__(self): super(SetSliceImageNode, self).__init__() self.node_class = 'image.image.SetSliceImageNode' self.title = 'SetSlice' self.category = 'Image/Slice' def run(self, ctx): img = ctx.read_pin('In') if img is None or not isinstance(img, np.ndarray): raise ValueError('Expected an Image object') value = ctx.read_pin('Value') # Validate index index = '' tokens = self.slice.split(',') for i in range(0, len(tokens)): if i != len(tokens)-1 and tokens[i] == '': # Allow a trailing ',' index = index + ',' continue if re.match('[\-0-9:]+$', tokens[i].strip()): index = index + tokens[i].strip() if i != len(tokens)-1: index = index + ',' else: raise SyntaxError('Invalid syntax: %s' % self.slice) tmp = img exec('tmp[%s] = value' % index) ctx.write_pin('Out', tmp)
class WriteNode(FlowNode): pins = [FlowPin('Image', FlowPin.In), FlowPin('File', FlowPin.In)] properties = [ FileProperty('file', '', FileProperty.File_Save, "Image (*.*)"), ] def __init__(self): super(WriteNode, self).__init__() self.node_class = 'medkit.io.WriteNode' self.title = 'Write' self.category = 'Image/IO' def run(self, ctx): f = self.file if self.is_pin_linked('File'): f = ctx.read_pin('File') im = ctx.read_pin('Image') if im is not None: if os.path.splitext(f)[1] == '.png': write(im.astype(np.uint8), f) else: write(im, f)
class IndexNode(FlowNode): pins = [FlowPin('In', FlowPin.In), FlowPin('Out', FlowPin.Out)] properties = [ StringProperty('index', '0'), ] def __init__(self): super(IndexNode, self).__init__() self.node_class = 'flow.list.IndexNode' self.title = 'Slice' self.category = 'List' self.ui_class = 'one_to_one_node' self.ui_node_title_var = 'index' def run(self, ctx): lst = ctx.read_pin('In') # Validate index index = self.index.strip() if not re.match('[\-0-9:]+$', index): raise ValueError('Invalid index') ctx.write_pin('Out', eval('lst[%s]' % index))
class StringNode(FlowNode): pins = [FlowPin('Out', FlowPin.Out)] properties = [ StringProperty('value', ''), ] def __init__(self): super(StringNode, self).__init__() self.node_class = 'flow.constant.StringNode' self.title = 'String' self.category = 'Constants' self.ui_class = 'constant_node' def run(self, ctx): ctx.write_pin('Out', self.value)
class BoolNode(FlowNode): pins = [FlowPin('Out', FlowPin.Out)] properties = [ BoolProperty('value', False), ] def __init__(self): super(BoolNode, self).__init__() self.node_class = 'flow.constant.BoolNode' self.title = 'Bool' self.category = 'Constants' self.ui_class = 'constant_node' def run(self, ctx): ctx.write_pin('Out', self.value)
class IntNode(FlowNode): pins = [FlowPin('Out', FlowPin.Out)] properties = [ IntProperty('value', 0), ] def __init__(self): super(IntNode, self).__init__() self.node_class = 'flow.constant.IntNode' self.title = 'Integer' self.category = 'Constants' self.ui_class = 'constant_node' def run(self, ctx): ctx.write_pin('Out', self.value)
class BuildNode(FlowNode): pins = [ FlowPin('Out', FlowPin.Out), ArrayFlowPin('Item', FlowPin.In), ] def __init__(self): super(BuildNode, self).__init__() self.node_class = 'flow.list.BuildNode' self.title = 'Build' self.category = 'List' def run(self, ctx): lst = ctx.read_pin('Item') ctx.write_pin('Out', lst)
class EvalNode(FlowNode): pins = [ FlowPin('Out', FlowPin.Out) ] properties = [ StringProperty('code', ''), ] def __init__(self): super(EvalNode, self).__init__() self.node_class = 'flow.util.Eval' self.title = 'Eval' self.category = 'Flow' self.ui_class = 'single_pin_node' def run(self, ctx): ctx.write_pin('Out', eval(self.code))
class FileBrowse(FlowNode): pins = [ FlowPin('Out', FlowPin.Out) ] properties = [ FileProperty('file', ''), ] def __init__(self): super(FileBrowse, self).__init__() self.node_class = 'flow.util.FileBrowse' self.title = 'FileBrowse' self.category = 'Flow/Util' self.ui_class = 'single_pin_node' def run(self, ctx): ctx.write_pin('Out', self.file)
class ConcatenateNode(FlowNode): pins = [ FlowPin('Out', FlowPin.Out), ArrayFlowPin('Item', FlowPin.In), ] def __init__(self): super(ConcatenateNode, self).__init__() self.node_class = 'flow.list.ConcatenateNode' self.title = 'Concatenate' self.category = 'List' def run(self, ctx): lst = ctx.read_pin('Item') out = [] for l in lst: out.extend(l) ctx.write_pin('Out', out)
class FailNode(FlowNode): pins = [ FlowPin('In', FlowPin.In), ] properties = [ StringProperty('error', ''), ] def __init__(self): super(FailNode, self).__init__() self.node_class = 'flow.debug.Fail' self.title = 'Fail' self.category = 'Debug' self.value = '' def run(self, ctx): if self.error != '': raise ValueError(self.error)
class ZerosNode(FlowNode): pins = [FlowPin('Out', FlowPin.Out)] properties = [ StringProperty('shape', '(0, 0)'), ] def __init__(self): super(ZerosNode, self).__init__() self.node_class = 'image.new.ZerosNode' self.title = 'Zeros' self.category = 'Image/New' self.ui_class = 'constant_node' self.ui_node_title_var = 'shape' def run(self, ctx): if re.match('\((\s*\d+\s*,?\s*)*\)$', self.shape.strip()) is None: raise ValueError('Invalid shape specifier: %s' % self.shape) shape = eval(self.shape) ctx.write_pin('Out', Image(np.zeros(shape)))
class ImageInfoNode(UiFlowNode): pins = [FlowPin('In', FlowPin.In)] def __init__(self): super(ImageInfoNode, self).__init__() self.node_class = 'image.info.ImageInfoNode' self.title = 'Info' self.category = 'Image/Info' self.ui_class = 'text_view_node' def run(self, ctx): img = ctx.read_pin('In') text = '<b>Shape</b>: %s<br/><b>Format</b>: %s' % (str( img.shape), str(img.dtype)) if hasattr(img, 'spacing'): text += '<br/><b>Spacing</b>: %s' % str(img.spacing) if hasattr(img, 'origin'): text += '<br/><b>Origin</b>: %s' % str(img.origin) self.invoke_ui_method('set_text', text)
class VariableNode(FlowNode): pins = [ FlowPin('Out', FlowPin.Out) ] properties = [ StringProperty('name', ''), StringProperty('default', '') ] def __init__(self): super(VariableNode, self).__init__() self.node_class = 'flow.variable.VariableNode' self.title = 'Variable' self.category = 'Flow' self.ui_class = 'variable_node' def run(self, ctx): if self.name in ctx.env: ctx.write_pin('Out', ctx.env[self.name]) else: ctx.write_pin('Out', self.default)
class ElastixNode(FlowNode): pins = [ ArrayFlowPin('F', FlowPin.In), ArrayFlowPin('M', FlowPin.In), ArrayFlowPin('T', FlowPin.In), FlowPin('FixedMask', FlowPin.In), FlowPin('MovingMask', FlowPin.In), FlowPin('FixedLandmarks', FlowPin.In), FlowPin('MovingLandmarks', FlowPin.In), FlowPin('Out', FlowPin.Out), FlowPin('Transform', FlowPin.Out), ] properties = [ FileProperty('param_file', '') ] def __init__(self): super(ElastixNode, self).__init__() self.node_class = 'elastix.Elastix' self.title = 'Elastix' self.category = 'Elastix' def run(self, ctx): fixed = list(ctx.read_pin('F')) moving = list(ctx.read_pin('M')) fixed_mask = ctx.read_pin('FixedMask') moving_mask = ctx.read_pin('MovingMask') fp = ctx.read_pin('FixedLandmarks') mp = ctx.read_pin('MovingLandmarks') if (fp != None and type(fp) != str) or (mp != None and type(mp) != str): raise ValueError('Wrong values for landmarks, expected string') temp_dir = ctx.temp_node_dir() for i in range(0, len(fixed)): if type(fixed[i]) == image.Image: medkit.write(fixed[i], os.path.join(temp_dir, 'f'+str(i)+'.mhd')) fixed[i] = os.path.join(temp_dir, 'f'+str(i)+'.mhd') if type(moving[i]) == image.Image: medkit.write(moving[i], os.path.join(temp_dir, 'm'+str(i)+'.mhd')) moving[i] = os.path.join(temp_dir, 'm'+str(i)+'.mhd') if (fixed[i] != None and type(fixed[i]) != str) or (moving[i] != None and type(moving[i]) != str): raise ValueError('Wrong values for input images, expected string or image') if fixed_mask == image.Image: medkit.write(fixed_mask, os.path.join(temp_dir, 'fmask.mhd')) fixed_mask = os.path.join(temp_dir, 'fmask.mhd') if moving_mask == image.Image: medkit.write(moving_mask, os.path.join(temp_dir, 'mmask.mhd')) moving_mask = os.path.join(temp_dir, 'mmask.mhd') t = ctx.read_pin('T') if t: t = list(t) for i in range(0, len(t)): if type(t[i]) == Parameters: t[i].write(os.path.join(temp_dir, 't'+str(i)+'.txt')) t[i] = os.path.join(temp_dir, 't'+str(i)+'.txt') if self.param_file == '': raise ValueError('Parameter file not set') param_file = os.path.abspath(self.param_file) run_elastix(param_file, fixed, moving, temp_dir, t=t, fixed_mask=fixed_mask, moving_mask=moving_mask, fp=fp, mp=mp) if self.is_pin_linked('Out'): ctx.write_pin('Out', medkit.read(os.path.join(temp_dir, 'result.0.mhd'))) if self.is_pin_linked('Transform'): ctx.write_pin('Transform', Parameters(os.path.join(temp_dir, 'TransformParameters.0.txt')))