Source code for msml.model.alphabet

# region gplv3preamble
# The Medical Simulation Markup Language (MSML) - Simplifying the biomechanical modeling workflow
#
# MSML has been developed in the framework of 'SFB TRR 125 Cognition-Guided Surgery'
#
# If you use this software in academic work, please cite the paper:
# S. Suwelack, M. Stoll, S. Schalck, N.Schoch, R. Dillmann, R. Bendl, V. Heuveline and S. Speidel,
# The Medical Simulation Markup Language (MSML) - Simplifying the biomechanical modeling workflow,
# Medicine Meets Virtual Reality (MMVR) 2014
#
# Copyright (C) 2013-2014 see Authors.txt
#
# If you have any questions please feel free to contact us at suwelack@kit.edu
#
# This program is free software: you can redistribute it and/or modify
# 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/>.
# endregion

from collections import OrderedDict
import pickle
import re

from ...sorts import *
from ...exceptions import *
from msml import sorts

from ..sequence import executeOperatorSequence
from msml.exceptions import MSMLUnknownModuleWarning
from ...log import debug,info, error, warn

from .operator import *

__author__ = "Alexander Weigl"
__date__ = "2014-01-25"


__all__ = ['Alphabet',
           'ObjectAttribute',
           'OAOutput',
           'OAConstraint',
           'OAMaterial',
           'Slot',
           'Operator',
           'SharedObjectOperator',
           'PythonOperator',
           'ShellOperator']


[docs]class Alphabet(object): """`Alphabet`holds the information about defined :py:class:`Operator`s and :py:class:`ObjectAttribute`s Normally it will created from a bunch of xml files. """ def __init__(self, elements=[]): self._operators = OrderedDict() self._object_attributes = OrderedDict() self.append(elements) @property def operators(self): """dictionary of defined operators :type: OrderedDict """ return self._operators @property def object_attributes(self): """a dictionary of all available object attributes :type: OrderedDict """ return self._object_attributes
[docs] def append(self, elements): """add a new element (operator or attribute) to the alphabet :type elements: list[Operator] or list[ObjectAttribute] .. seealso: :py:class:`Operator` :py:class:`ObjectAttribute` """ for e in elements: if isinstance(e, Operator): self._operators[e.name] = e elif isinstance(e, ObjectAttribute): self._object_attributes[e.name] = e
def __contains__(self, obj): """Test if the given `obj` is in the alphabet. :type obj: Operator or ObjectAttribute :rtype: bool :returns: """ return bool(self.type(obj)) def __getitem__(self, obj): return self.get(obj)
[docs] def type(self, obj): """ :returns: the type of the given `obj` :type obj: Operator or ObjectAttribute """ if obj in self._operators: return "operator" elif obj in self._object_attributes: return "element" return None
[docs] def get(self, obj): """ :param obj: an identifier for an :py:class:`Operator` or an :py:class:`ObjectAttribute` :type obj: str """ if obj in self._operators: return self._operators[obj] elif obj in self._object_attributes: return self._object_attributes[obj] return None
[docs] def validate(self): """Validates the alphabet. Calls `.validate()` on each contained element. """ r = map(lambda x: x.validate(), self._operators.values()) s = map(lambda x: x.validate(), self._object_attributes.values()) return all(r) and all(s)
def __str__(self): o = ",".join(self._operators.keys()) e = ",".join(self._object_attributes.keys()) return "Alphabet: (Operators: %s) (Elements: %s) " % (o, e)
[docs] def save(self, filename): """pickles the alphabet into a binary dump to the given `filename` :type filename: str """ with open(filename, 'w') as file: pickle.dump(self, file) # import jsonpickle # print(jsonpickle.encode(self))
@staticmethod
[docs] def load(filename): """loads a pickled alphabet from the given `filename` :param filename: :type filename: str """ with open(filename, 'r') as file: return pickle.load(file)
[docs]class ObjectAttribute(object): """Class of all user-defineable constraints, outputs, materials. """ def __init__(self, name, quantity='single', description="documentation N/A", parameters=None, inputs=None): self.name = name """The attribute name. This name is used by the user as xml tag name""" self.quantity = quantity """Unused. Should say how often the element can be used in an object definition""" self.description = description """Description by the user for this attribute""" self.parameters = parameters """Parameters of this ObjectAttribute. :type: dict[str,Slot] """ self.inputs = inputs """Unused and deprecated """ def __repr__(self): return "%s(name=%r, quantity=%r,description=%r,parameters=%r, inputs=%r)" % (self.__class__.__name__, self.name, self.quantity, self.description, self.parameters, self.inputs) @staticmethod
[docs] def find_class(category): """Finds the correct class for an given category. :returns: the suitable constructor :type category: str :rtype: type """ global _object_attribute_categories return _object_attribute_categories[category]
[docs] def validate(self): """Validation of this attribute""" return True
[docs]class OAOutput(ObjectAttribute): pass
[docs]class OAConstraint(ObjectAttribute):
[docs] def validate(self): """validates a Object Constraints. :constraints: * indices attribute have to present :rtype: bool """ #if 'indices' in self.parameters: # return True #else: # log.error("OAConstraint: %s does not have an indices attribute defined" % self.name) # return False return True
[docs]class OAMaterial(ObjectAttribute): pass
_object_attribute_categories = {'basic': ObjectAttribute, 'material': OAMaterial, 'constraint': OAConstraint, "output": OAOutput} """Register for attribute category and suitable class"""
[docs]class Slot(object): """An input, parameter or output slot of an operator or an element Consists of name, physical and logical type. Proxy for meta data. """ # : slot type is not set SLOT_TYPE_UNKNOWN = -1 #: slot is an input SLOT_TYPE_INPUT = 0 #: slot is an output SLOT_TYPE_OUTPUT = 1 #: slot is a parameter SLOT_TYPE_PARAMETER = 2 def __init__(self, name, physical, logical=None, required=True, default=None, meta=None, parent=None): if physical is None: pname = None if parent: pname = parent.name log.critical("Slot %s in parent %s does not have a physical type defined. " "This can cause conversion errors.", name, pname) self.name = name """slot name :type: str """ self.logical_type = logical """the logical type given by the user as str :type: str """ self.physical_type = physical """the physical type given by the user as str :type: str """ self.required = required """True iff. this slot has to be set in the xml tags :type: bool """ self.default = default """default value of this slot. has to be if :py:var:`required` is True""" self.meta = meta or dict() """various and arbitrary meta data :type: dict""" self.parent = parent """the parent of this slot. Can be an :py:class:`Operator` or :py:class:`ObjectAttribute` or an :py:class:`Exporter` :type: Operator or msml.exporter.Exporter or ObjectAttribute """ self.slot_type = Slot.SLOT_TYPE_UNKNOWN """slot type. see class SLOT\_TYPE\_\* variables. :type: int """ self.sort = None """the sort of this slot. derived from `physical_type` and `logical_type` :type: Sort """ self.target = False """True iff. this slot holds an output filename. :type: bool """ try: self.sort = get_sort(self.physical_type, self.logical_type) except AssertionError as ae: log.error("%s %s has physical_type %s" % (self.parent, self.name, self.physical_type)) self.sort = None def __getattr__(self, item): if 'meta' in self.__dict__ and item in self.meta: return self.meta[item] else: return self.__dict__[item] def __str__(self): return "<Slot %s: %s>" % (self.name, self.sort)