class INotificationListenerFactory(IFactory): """Envisage required interface for the BaseNotificationListenerFactory. You should not need to use this directly. Refer to the BaseNotificationListenerFactory for documentation. """ listener_class = Type( "force_bdss.notification_listeners" ".base_notification_listener.BaseNotificationListener", allow_none=False, ) model_class = Type( "force_bdss.notification_listeners" ".base_notification_listener_model.BaseNotificationListenerModel", allow_none=False) def get_model_class(self): """ :return: model class. """ def get_listener_class(self): """ :return: listener class. """ def create_listener(self): """ :return: listener. """ def create_model(self): """
class ObjectFactory(HasStrictTraits): """ A factory with metadata. """ # A unique ID identifying the factory. id = Str() # A short, user-visible name for the object. name = Unicode() # A longer, user-visible description for the object. description = Unicode() # The type of the object. type = Type() # An Enaml UI for editing the object. The object will be passed to widget # via the 'obj' attribute. ui = Type('enaml.widgets.widget.Widget') # A factory for creating new instances of the object. # If not specified, objects are created by invoking the type constructor. factory = Callable() def create(self, *args, **kwds): """ Create an instance of the object. """ if self.factory: return self.factory(*args, **kwds) elif self.type: return self.type(*args, **kwds) else: raise RuntimeError('Cannot construct object from factory')
class IDataSourceFactory(IFactory): """Envisage required interface for the BaseDataSourceFactory. You should not need to use this directly. Refer to the BaseDataSourceFactory for documentation. """ data_source_class = Type( "force_bdss.data_sources.base_data_source.BaseDataSource", allow_none=False) model_class = Type( "force_bdss.data_sources.base_data_source_model.BaseDataSourceModel", allow_none=False) def get_data_source_class(self): """ :return: data source class. """ def get_model_class(self): """ :return: model class. """ def create_data_source(self): """Returns an instance of subclass BaseDataSource """ def create_model(self): """Returns an instance of subclass BaseDataSourceModel
class IMultiImageFactory(Interface): label = Str multi_image_class = Type(IMultiImage) reader_class = Type(IMultiImageReader) analyser_class = Type(IMultiImageAnalyser) parser_class = Type(IFileParser) viewer_class = Type(IMultiImageViewer) def get_label(self): """Returns key associated with this factory""" def get_multi_image(self): """Returns BaseMultiImage associated with this factory""" def get_reader(self): """Returns list of IMultiImageReader classes able to load the IMultiImage class created by this factory""" def get_analyser(self): """Returns list of IMultiImageAnalyser classes able to analyse the IMultiImage class created by this factory""" def get_parser(self): """Returns list of IFileParser classes able to parse files that are used to load the IMultiImage class created by this factory""" def get_viewer(self): """Returns list of IMultiImageViewer classes able to display
class BaseNotificationListenerFactory(BaseFactory): """Base class for notification listeners. Notification listeners are extensions that receive event notifications from the MCO and perform an associated action. """ #: The listener class that must be instantiated. Define this to your #: listener class. listener_class = Type(BaseNotificationListener, allow_none=False) #: The associated model to the listener. Define this to your #: listener model class. model_class = Type(BaseNotificationListenerModel, allow_none=False) def __init__(self, plugin, *args, **kwargs): """Initializes the instance. Parameters ---------- plugin: Plugin The plugin that holds this factory. """ super(BaseNotificationListenerFactory, self).__init__(plugin=plugin, *args, **kwargs) self.listener_class = self.get_listener_class() self.model_class = self.get_model_class() def get_listener_class(self): raise NotImplementedError( "get_listener_class was not implemented in factory {}".format( self.__class__)) def get_model_class(self): raise NotImplementedError( "get_model_class was not implemented in factory {}".format( self.__class__)) def create_listener(self): """ Creates an instance of the listener. """ return self.listener_class(self) def create_model(self, model_data=None): """ Creates an instance of the model. Parameters ---------- model_data: dict Data to use to fill the model. """ if model_data is None: model_data = {} return self.model_class(self, **model_data)
class IMCOFactory(IFactory): """Interface for the BaseMCOFactory. You should not need it, as its main use is for envisage support. Refer to BaseMCOFactory for documentation """ optimizer_class = Type("force_bdss.mco.base_mco.BaseMCO", allow_none=False) model_class = Type( "force_bdss.mco.base_mco_communicator.BaseMCOCommunicator", allow_none=False) communicator_class = Type("force_bdss.mco.base_mco_model.BaseMCOModel", allow_none=False) parameter_factory_classes = List( Type("force_bdss.mco.parameters.i_mco_parameter_factory" ".IMCOParameterFactory")) def get_model_class(self): """ :return: model class. """ def get_communicator_class(self): """ :return: model communicator class. """ def get_optimizer_class(self): """ :return: optimizer class """ def get_parameter_factory_classes(self): """Returns a list of classes that provide the IMCOParameterFactory interface""" def create_optimizer(self): """ :return: optimizer """ def create_model(self): """ :return: model """ def create_communicator(self): """
class IMultiImageReader(Interface): """File reader that loads a stack of Tiff images, represented by a IMultiImage subclass""" _supported_file_sets = List(IFileSet) _multi_image_class = Type(IMultiImage) def load_multi_image(self, file_set): """Image loader for MultiImage classes""" def get_supported_file_sets(self): """Returns class of IFileSets that will be supported.""" def get_filenames(self, file_set): """From a collection of files in a FileSet, yield each file that should be used """ def create_image_stack(self, filenames): """Return a list of numpy arrays suitable for the loader's IMultiImage type""" def load_image(self, filename): """Load a single image from a file""" def can_load(self, filename): """Perform check to see whether file is formatted
class FieldAction(Action): """ A widget action containing an IField When the value in the field is changed, the `on_perform` method is called with the new value as the argument. """ #: This is a widget action. style = Constant("widget") #: The field to display. field_type = Type(IField) #: The default trait values for the field. field_defaults = Dict(Str, Any) def create_control(self, parent): """ Called when creating a "widget" style action. This constructs an IField-based control directly and binds changes to the value to the `value_updated` method. Parameters ---------- parent : toolkit control The toolkit control, usually a toolbar. Returns ------- control : toolkit control A toolkit control or None. """ field = self.field_type(parent=parent, **self.field_defaults) field._create() field.observe(self.value_updated, "value") field.control._field = field return field.control def value_updated(self, event): """ Handle changes to the field value by calling perform. The event passed to `perform` has the `value` as an attribute. """ value = event.new action_event = ActionEvent(value=value) self.perform(action_event) def perform(self, event): """ Performs the action. This dispacthes to the on_perform method with the new value passed as an argument. Parameters ---------- event : ActionEvent instance The event which triggered the action. """ if self.on_perform is not None: self.on_perform(event.value)
class BaseMCOParameterFactory(BaseFactory): """Factory that produces the model instance of a given BaseMCOParameter instance. Must be reimplemented for the specific parameter. The generic create_model is generally enough, and the only entity to define is model_class with the appropriate class of the parameter. """ #: A reference to the MCO factory this parameter factory lives in. mco_factory = Instance('force_bdss.mco.base_mco_factory.BaseMCOFactory', allow_none=False) # The model class to instantiate when create_model is called. model_class = Type( "force_bdss.mco.parameters.base_mco_parameter.BaseMCOParameter", allow_none=False) def __init__(self, mco_factory, *args, **kwargs): super(BaseMCOParameterFactory, self).__init__(plugin={ 'id': mco_factory.plugin_id, 'name': mco_factory.plugin_name }, mco_factory=mco_factory, *args, **kwargs) self.model_class = self.get_model_class() def get_model_class(self): raise NotImplementedError( "get_model_class was not implemented in factory {}".format( self.__class__)) def create_model(self, data_values=None): """Creates the instance of the model class and returns it. You should not reimplement this, as the default is generally ok. Instead, just define model_class with the appropriate Parameter class. Parameters ---------- data_values: dict or None The dictionary of values for this parameter. If None, a default object will be returned. Returns ------- instance of model_class. """ if data_values is None: data_values = {} return self.model_class(self, **data_values) def _global_id(self, identifier): return mco_parameter_id(self.mco_factory.id, identifier)
class ToolbarPlot(Plot): #: Should we turn on the auto-hide feature on the toolbar? auto_hide = DelegatesTo('toolbar') toolbar = Instance(PlotToolbar) toolbar_class = Type(PlotToolbar) toolbar_added = False #: Location of the default toolbar that is created if a toolbar #: is not specified with the `toolbar` attribute. Changing this #: attribute after the ToolbarPlot instance is created has no effect; #: use obj.toolbar.location to dynamically change the location of the #: instance `obj`s toolbar. toolbar_location = Enum('top', 'right', 'bottom', 'left') def __init__(self, *args, **kw): # initialize the toolbar class before super() has a chance to create # the default using the default class. This can happen because of # ordering issues if "toolbar_class" in kw: self.toolbar_class = kw.pop("toolbar_class") super(ToolbarPlot, self).__init__(*args, **kw) self.toolbar.component = self self.add_toolbar() def _toolbar_default(self): return self.toolbar_class(self, location=self.toolbar_location) def add_toolbar(self): if not self.toolbar_added: self.overlays.append(self.toolbar) self.toolbar_added = True self.request_redraw() def remove_toolbar(self): if self.toolbar_added and self.auto_hide: self.overlays.remove(self.toolbar) self.toolbar_added = False self.request_redraw() def _bounds_changed(self, old, new): self.toolbar.do_layout(force=True) super(ToolbarPlot, self)._bounds_changed(old, new) @on_trait_change('toolbar') def _toolbar_changed(self, name, obj, old, new): if self.toolbar_added: # fixup the new toolbar's component to match the old one new.component = old.component self.overlays.remove(old) self.toolbar_added = False self.add_toolbar()
class ImageEnumEditor(EnumEditor): """ Editor factory for image enumeration editors. """ # ------------------------------------------------------------------------- # Trait definitions: # ------------------------------------------------------------------------- #: Prefix to add to values to form image names: prefix = Str() #: Suffix to add to values to form image names: suffix = Str() #: Path to use to locate image files: path = Str() #: Class used to derive the path to the image files: klass = Type() #: Module used to derive the path to the image files: module = Module def init(self): """ Performs any initialization needed after all constructor traits have been set. """ super().init() self._update_path() @observe("path, klass, module") def _update_path(self, event=None): """ Handles one of the items defining the path being updated. """ if self.path != "": self._image_path = self.path elif self.klass is not None: module = self.klass.__module__ if module == "___main___": module = "__main__" try: self._image_path = join( dirname(sys.modules[module].__file__), "images" ) except: self._image_path = self.path dirs = [ join(dirname(sys.argv[0]), "images"), join(getcwd(), "images"), ] for d in dirs: if exists(d): self._image_path = d break elif self.module is not None: self._image_path = join(dirname(self.module.__file__), "images")
class ModelTreeItem(HasStrictTraits): """ An item within a ModelTree. Used to compose the data for the model tree view. """ title = Unicode() icon = Instance(QIcon) model_object = Instance(ModelObject) parent = Instance('ModelTreeItem') controller = Instance(ModelEditorController) ui = Type(klass='enaml.widgets.widget.Widget', value=None) ui_kwargs = Dict(Unicode, Any) menu = Instance(Menu) _children = List(Instance('ModelTreeItem')) @classmethod def from_model_object(cls, model_object, **kwargs): return cls(title=model_object.name, model_object=model_object, **kwargs) def append_child(self, child): child.parent = self self._children.append(child) def child(self, row): if 0 <= row < len(self._children): return self._children[row] return None def child_count(self): return len(self._children) def row(self): if self.parent: return self.parent._children.index(self) return 0 def select(self): self.controller.selected_object = self.model_object self.controller.selected_ui = self.ui_instance() def default_ui(self): klass = type(self.model_object) factory = ObjectRegistry.instance().get_closest_by_type(klass) return factory.ui if factory else None def ui_instance(self): ui_klass = self.ui if self.ui else self.default_ui() if not ui_klass: return None return ui_klass(**dict(self.ui_kwargs))
class IMCOParameterFactory(IFactory): mco_factory = Instance('force_bdss.mco.base_mco_factory.BaseMCOFactory', allow_none=False) model_class = Type( "force_bdss.mco.parameters.base_mco_parameter.BaseMCOParameter", allow_none=False) def get_model_class(self): """Returns type of BaseMCOParameter subclass""" def create_model(self, data_values=None): """Returns instance of BaseMCOParameter subclass"""
class IUIHooksFactory(IFactory): """Envisage required interface for the BaseUIHooksFactory. You should not need to use this directly. Refer to the BaseUIHooksFactory for documentation. """ ui_hooks_manager_class = Type( "force_bdss.ui_hooks.base_ui_hooks_manager.BaseUIHooksManager", allow_none=False) def get_ui_hooks_manager_class(self): """ :return: hooks manager class """ def create_ui_hooks_manager(self): """
class BaseUIHooksFactory(BaseFactory): """Base class for UIHooksFactory. UI Hooks are extensions that perform actions associated to specific moments of the UI lifetime. """ #: The UI Hooks manager class to instantiate. Define this to your #: base hook managers. ui_hooks_manager_class = Type(BaseUIHooksManager, allow_none=False) def __init__(self, plugin, *args, **kwargs): """Initializes the instance. Parameters ---------- plugin: Plugin The plugin that holds this factory. """ super(BaseUIHooksFactory, self).__init__(plugin=plugin, *args, **kwargs) self.ui_hooks_manager_class = self.get_ui_hooks_manager_class() def get_ui_hooks_manager_class(self): raise NotImplementedError( "get_ui_hooks_manager_class was not implemented " "in factory {}".format(self.__class__)) def create_ui_hooks_manager(self): """Creates an instance of the hook manager. The hooks manager contains a set of methods that are applicable in various moments of the UI application lifetime. Returns ------- BaseUIHooksManager """ return self.ui_hooks_manager_class(self)
class BaseMCOFactory(BaseFactory): """Base class for the MultiCriteria Optimizer factory. """ # NOTE: any changes to the interface of this class must be replicated # in the IMCOFactory interface class. #: The optimizer class to instantiate. Define this to your MCO class. optimizer_class = Type(BaseMCO, allow_none=False) #: The model associated to the MCO. Define this to your MCO model class. model_class = Type(BaseMCOModel, allow_none=False) #: The communicator associated to the MCO. Define this to your MCO comm. communicator_class = Type(BaseMCOCommunicator, allow_none=False) #: The list of parameter factory classes this MCO supports. parameter_factory_classes = List(Type(IMCOParameterFactory)) #: The instantiated parameter factories. parameter_factories = List(Instance(IMCOParameterFactory)) def __init__(self, plugin, *args, **kwargs): super(BaseMCOFactory, self).__init__(plugin=plugin, *args, **kwargs) self.optimizer_class = self.get_optimizer_class() self.model_class = self.get_model_class() self.communicator_class = self.get_communicator_class() self.parameter_factory_classes = self.get_parameter_factory_classes() self.parameter_factories = self._create_parameter_factories() def get_optimizer_class(self): raise NotImplementedError( f"get_optimizer_class was not implemented " f"in factory {self.__class__}" ) def get_model_class(self): raise NotImplementedError( "get_model_class was not implemented " f"in factory {self.__class__}" ) def get_communicator_class(self): raise NotImplementedError( "get_communicator_class was not implemented " f"in factory {self.__class__}" ) def get_parameter_factory_classes(self): raise NotImplementedError( "get_parameter_factory_classes was not implemented " f"in factory {self.__class__}" ) def create_optimizer(self): """Factory method. Creates the optimizer with the given application and model and returns it to the caller. Returns ------- BaseMCO The optimizer """ return self.optimizer_class(self) def create_model(self, model_data=None): """Factory method. Creates the model object (or network of model objects) of the MCO. The model can provide a traits UI View according to traitsui specifications, so that a UI can be provided automatically. Parameters ---------- model_data: dict or None A dictionary of data that can be interpreted appropriately to recreate the model. If None, an empty (with defaults) model will be created and returned. Returns ------- BaseMCOModel The MCOModel """ if model_data is None: model_data = {} return self.model_class(self, **model_data) def create_communicator(self): """Factory method. Returns the communicator class that allows exchange between the MCO and the evaluator code. Returns ------- BaseMCOCommunicator An instance of the communicator """ return self.communicator_class(self) def _create_parameter_factories(self): """Returns the parameter factories supported by this MCO Returns ------- List of BaseMCOParameterFactory """ return [ factory_cls(self) for factory_cls in self.parameter_factory_classes ] def parameter_factory_by_id(self, parameter_id): for factory in self.parameter_factories: if factory.id == parameter_id: return factory raise KeyError( f"Invalid Parameter Factory id {parameter_id} for " f"the specified MCO Factory {self.__class__}. " "No plugin responsible for the id is found." )
class PolarDiscr(HasTraits): ''' Manager of the microplane arrays. This class is responsible for the generation and initialization and state management of an array of microplanes. Additionally, it can perform the setup of damage function parameters using the value of the microplane integrator object. ''' mfn_class = Type(None) #------------------------------------------------------------------------- # Common parameters for for isotropic and anisotropic damage function specifications #------------------------------------------------------------------------- n_mp = Range(0, 50, 6, label='Number of microplanes', auto_set=False) E = Float(34e+3, label="E", desc="Young's Modulus", auto_set=False, enter_set=True) nu = Float(0.2, label='nu', desc="Poison's ratio", auto_set=False, enter_set=True) c_T = Float( 0.0, label='c_T', desc='fraction of tangential stress accounted on each microplane', auto_set=False, enter_set=True) #------------------------------------------------------------------------- # list of angles #------------------------------------------------------------------------- alpha_list = Property(Array, depends_on='n_mp') @cached_property def _get_alpha_list(self): return array( [Pi / self.n_mp * (i - 0.5) for i in range(1, self.n_mp + 1)]) #------------------------------------------------------------------------- # Damage function specification #------------------------------------------------------------------------- phi_fn = EitherType(klasses=[ PhiFnGeneral, PhiFnGeneralExtended, PhiFnGeneralExtendedExp, PhiFnStrainSoftening, PhiFnStrainHardening, PhiFnStrainHardeningLinear, PhiFnStrainHardeningBezier ]) def _phi_fn_default(self): print('setting phi_fn default') return PhiFnStrainSoftening(polar_discr=self) def _phi_fn_changed(self): print('setting phi_fn changed') self.phi_fn.polar_discr = self varied_params = List(Str, []) #------------------------------------------------------------------------- # Management of spatially varying parameters depending on the value of mats_eval #------------------------------------------------------------------------- varpars = Dict def _varpars_default(self): return self._get_varpars() @on_trait_change('phi_fn,varied_params') def _update_varpars(self): self.varpars = self._get_varpars() def _get_varpars(self): ''' reset the varpar list according to the current phi_fn object. ''' params = self.phi_fn.identify_parameters() varset = {} for key in params: varset[key] = VariedParam(phi_fn=self.phi_fn, mats_eval=self, varname=key) if key in self.varied_params: varset[key].switched_on = True return varset varpar_list = Property(List(VariedParam), depends_on='varpars') @cached_property def _get_varpar_list(self): return [self.varpars[key] for key in self.phi_fn.identify_parameters()] # variable selectable in the table of varied params (just for viewing) current_varpar = Instance(VariedParam) def _current_varpar_default(self): if len(self.varpar_list) > 0: return self.varpar_list[0] return None @on_trait_change('phi_fn') def set_current_varpar(self): if len(self.varpar_list) > 0: self.current_varpar = self.varpar_list[0] #------------------------------------------------------------------------- # Get the damage state for all microplanes #------------------------------------------------------------------------- def get_phi_arr(self, sctx, e_max_arr): ''' Return the damage coefficients ''' # gather the coefficients for parameters depending on the orientation carr_list = [ self.varpars[key].polar_fn_vectorized(self.alpha_list) for key in self.phi_fn.identify_parameters() ] # vectorize the damage function evaluation n_arr = 1 + len(carr_list) phi_fn_vectorized = frompyfunc(self.phi_fn.get_value, n_arr, 1) # damage parameter for each microplane return phi_fn_vectorized(e_max_arr, *carr_list) def get_polar_fn_fracture_energy_arr(self, sctx, e_max_arr): ''' Return the fracture energy contributions ''' carr_list = [ self.varpars[key].polar_fn_vectorized(self.alpha_list) for key in self.phi_fn.identify_parameters() ] # vectorize the damage function evaluation n_arr = 1 + len(carr_list) integ_phi_fn_vectorized = frompyfunc(self.phi_fn.get_integ, n_arr, 1) return self.E * integ_phi_fn_vectorized(e_max_arr, *carr_list) polar_fn_group = Group( Group(Item('n_mp@', width=200), Item('E'), Item('nu'), Item('c_T'), Spring(), label='Elasticity parameters'), Group(Item('phi_fn@', show_label=False), label='Damage parameters'), Group(VSplit( Item('varpar_list', label='List of material variables', show_label=False, editor=varpar_editor), Item('current_varpar', label='Selected variable', show_label=False, style='custom', resizable=True), dock='tab', ), label='Angle-dependent variations'), Include('config_param_vgroup'), layout='tabbed', springy=True, dock='tab', id='ibvpy.mats.matsXD_cmdm.MATSXDPolarDiscr', ) traits_view = View(Include('polar_fn_group'), resizable=True, scrollable=True, width=0.6, height=0.9)
class ViewportToolbar(Container, AbstractOverlay): """ ViewportToolbar is a toolbar that is attached to the top of a viewport on the block canvas. """ button_spacing = Int(5) button_vposition = Int(6) always_on = Bool(True) toolbar_height = Float(30.0) order = Enum("left-to-right", "right-to-left") buttons = List(Type(Button)) # Override default values for inherited traits auto_size = False bgcolor = ColorTrait((0.5, 0.5, 0.5, 0.25)) def __init__(self, component=None, *args, **kw): # self.component should be a CanvasViewport self.component = component for buttontype in self.buttons: self.add_button(buttontype()) super(ViewportToolbar, self).__init__(*args, **kw) def _do_layout(self, component=None): if component is None: component = self.component if component is not None: self.x = component.x # FIXME: Adding 2 to the self.y because there is a tiny gap # at the top of the toolbar where components from the block # canvas show through. self.y = component.y2 - self.toolbar_height + 2 self.height = self.toolbar_height self.width = component.width metrics = font_metrics_provider() if self.order == "right-to-left": last_button_position = self.width - self.button_spacing for b in self.components: x, y, w, h = metrics.get_text_extent(b.label) b.width = w + 2 * b.label_padding b.x = last_button_position - b.width b.y = self.button_vposition last_button_position -= b.width + self.button_spacing * 2 else: last_button_position = 0 for b in self.components: x, y, w, h = metrics.get_text_extent(b.label) b.width = w + 2 * b.label_padding b.x = self.button_spacing + last_button_position b.y = self.button_vposition last_button_position += b.width + self.button_spacing * 2 def overlay(self, other_component, gc, view_bounds=None, mode="normal"): c = other_component self.do_layout(component=c) with gc: gc.clip_to_rect(c.x, c.y, c.width, c.height) Container._draw(self, gc, view_bounds) return def add_button(self, button): self.add(button) button.toolbar_overlay = self self._layout_needed = True return
class ExampleTypeModel(HasTraits): _class = Type(klass=BaseClass)
class PlotToolbar(Container, AbstractOverlay): """ A toolbar for embedding buttons in """ buttons = List(Type(ToolbarButton)) # Should the toolbar be hidden hiding = Bool(True) # should the toolbar go automatically go back into hiding when the mouse # is not hovering over it auto_hide = Bool(True) # the radius used to determine how round to make the toolbar's edges end_radius = Float(4.0) # button spacing is defined as the number of pixels on either side of # a button. The gap between 2 buttons will be 2 x the button spacing button_spacing = Float(5.0) # how many pixels to put before and after the set of buttons horizontal_padding = Float(5.0) # how many pixels to put on top and bottom the set of buttons vertical_padding = Float(5.0) # The edge against which the toolbar is placed. location = Enum('top', 'right', 'bottom', 'left') # Should tooltips be shown? show_tooltips = Bool(False) ############################################################ # PlotToolbar API ############################################################ def __init__(self, component=None, *args, **kw): super(PlotToolbar, self).__init__(*args, **kw) self.component = component if component is not None and hasattr(component, 'toolbar_location'): self.location = component.toolbar_location for buttontype in self.buttons: self.add_button(buttontype()) hover_tool = PlotToolbarHover(component=self, callback=self.on_hover) self.tools.append(hover_tool) if self.location in ['top', 'bottom']: self._calculate_width() else: self._calculate_height() def _buttons_default(self): return [ IndexAxisLogButton, ValueAxisLogButton, SaveAsButton, CopyToClipboardButton, ExportDataToClipboardButton, ZoomResetButton ] def add_button(self, button): """ adds a button to the toolbar """ self.add(button) button.toolbar_overlay = self self._layout_needed = True return def normal_mouse_move(self, event): """ handler for normal mouse move """ self.on_hover('') if self.hiding: self.hiding = False def on_hover(self, tooltip): if self.show_tooltips: self.component.window.set_tooltip(tooltip) def normal_left_down(self, event): """ handler for a left mouse click """ if self.hiding: return else: for button in self.components: if button.is_in(event.x, event.y): button.perform(event) event.handled = True break ############################################################ # AbstractOverlay API ############################################################ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): """ Draws this component overlaid on another component. """ starting_color = numpy.array([0.0, 1.0, 1.0, 1.0, 0.5]) ending_color = numpy.array([1.0, 0.0, 0.0, 0.0, 0.5]) x = self.x y = self.y height = self.height with gc: gc.begin_path() gc.move_to(x + self.end_radius, y) gc.arc_to(x + self.width, y, x + self.width, y + self.end_radius, self.end_radius) gc.arc_to(x + self.width, y + height, x + self.width - self.end_radius, y + height, self.end_radius) gc.arc_to(x, y + height, x, y + height - self.end_radius, self.end_radius) gc.arc_to(x, y, x + self.end_radius, y, self.end_radius) if self.location in ['top', 'bottom']: gc.linear_gradient(x, y, x, y + 100, numpy.array([starting_color, ending_color]), "pad") else: gc.linear_gradient(x, y, x + 100, y, numpy.array([starting_color, ending_color]), "pad") gc.draw_path() if not self.hiding: for button in self.components: button.draw(gc) def is_in(self, x, y): if (x >= self.x and x <= self.x2) and (y >= self.y and y <= self.y2): return True return False def _do_layout(self, component=None): if component is None: component = self.component if self.location in ['top', 'bottom']: if self.hiding: self.height = height = 10 else: tallest_button = max( [button.height for button in self.components]) self.height = height = (tallest_button + self.vertical_padding * 2) else: if self.hiding: self.width = width = 10 else: widest_button = max( [button.width for button in self.components]) self.width = width = (widest_button + self.horizontal_padding * 2) if component is not None: # Overlay positions are not relative to the component's position, # so we have to add in the component's position cx, cy = component.outer_position if self.location is 'top': self.x = (cx + (component.width - self.width) / 2 + component.padding_left) self.y = (cy + component.height + component.padding_bottom - height - 2) elif self.location is 'bottom': self.x = (cx + (component.width - self.width) / 2 + component.padding_left) self.y = cy + component.padding_bottom + 2 elif self.location is 'left': self.x = cx + component.padding_left + 2 self.y = (cy + (component.height - self.height) / 2 + component.padding_bottom) else: # 'right' self.x = (cx + component.width + component.padding_left - width - 2) self.y = (cy + (component.height - self.height) / 2 + component.padding_bottom) if self.location in ['top', 'bottom']: v_position = self.y + self.vertical_padding * 2 last_button_position = (self.x + self.horizontal_padding + self.button_spacing) for button in self.components: button.x = last_button_position button.y = v_position last_button_position += button.width + self.button_spacing * 2 else: # location is 'left' or 'right' h_position = self.x + self.horizontal_padding last_button_position = (self.y + self.vertical_padding + self.button_spacing) for button in reversed(self.components): h_offset = (self.width - button.width) / 2 button.y = last_button_position button.x = h_position + h_offset last_button_position += button.height + self.button_spacing * 2 def _dispatch_stateful_event(self, event, suffix): if self.is_in(event.x, event.y): if suffix == 'mouse_move': self.normal_mouse_move(event) elif suffix == 'left_down': self.normal_left_down(event) event.handled = True else: if self.auto_hide: self.hiding = True return ############################################################ # Trait handlers ############################################################ @on_trait_change('components, location') def _calculate_width(self): if self.location in ['top', 'bottom']: width = self.horizontal_padding * 2 for button in self.components: width += button.width + self.button_spacing * 2 self.width = max(10, width) self._layout_needed = True self.request_redraw() @on_trait_change('components, location') def _calculate_height(self): if self.location in ['left', 'right']: height = self.vertical_padding * 2 for button in self.components: height += button.height + self.button_spacing * 2 self.height = max(10, height) self._layout_needed = True self.request_redraw() @on_trait_change('hiding') def _hiding_changed(self): self._layout_needed = True self.request_redraw() @on_trait_change('auto_hide') def _auto_hide_changed(self): self.hiding = self.auto_hide self.request_redraw()
class BaseDataSourceFactory(BaseFactory): """Base class for DataSource factories. Reimplement this class to create your own DataSource. You must reimplement the following methods as from example:: class MyDataSourceFactory(BaseDataSourceFactory) def get_data_source_class(self): return MyDataSource def get_data_source_model(self): return MyDataSourceModel def get_name(self): return "My data source" def get_identifier(self): return "my_data_source" """ # NOTE: changes to this class must be ported also to the IDataSourceFactory #: The data source to be instantiated. Define this to your DataSource data_source_class = Type(BaseDataSource, allow_none=False) #: The model associated to the data source. #: Define this to your DataSourceModel model_class = Type(BaseDataSourceModel, allow_none=False) def __init__(self, plugin, *args, **kwargs): super(BaseDataSourceFactory, self).__init__(plugin=plugin, *args, **kwargs) self.data_source_class = self.get_data_source_class() self.model_class = self.get_model_class() def get_data_source_class(self): """Must be reimplemented to return the DataSource class. """ raise NotImplementedError( "get_data_source_class was not implemented in factory {}".format( self.__class__)) def get_model_class(self): """Must be reimplemented to return the DataSourceModel class. """ raise NotImplementedError( "get_model_class was not implemented in factory {}".format( self.__class__)) def create_data_source(self): """Factory method. Must return the factory-specific BaseDataSource instance. Returns ------- BaseDataSource The specific instance of the generated DataSource """ return self.data_source_class(self) def create_model(self, model_data=None): """Factory method. Creates the model object (or network of model objects) of the KPI calculator. The model can provide a traits UI View according to traitsui specifications, so that a UI can be provided automatically. Parameters ---------- model_data: dict or None A dictionary containing the information to recreate the model. If None, an empty (with defaults) model will be returned. Returns ------- BaseDataSourceModel The model """ if model_data is None: model_data = {} return self.model_class(self, **model_data)
class MATS2DMicroplaneDamage(MATSXDMicroplaneDamage, MATS2DEval): # implements(IMATSEval) # number of spatial dimensions # n_dim = Constant(2) # number of components of engineering tensor representation # n_eng = Constant(3) # planar constraint stress_state = Enum("plane_strain", "plane_stress") # Specify the class to use for directional dependence mfn_class = Type(MFnPolar) # get the normal vectors of the microplanes _MPN = Property(depends_on='n_mp') @cached_property def _get__MPN(self): return array([[cos(alpha), sin(alpha)] for alpha in self.alpha_list]) # get the weights of the microplanes _MPW = Property(depends_on='n_mp') @cached_property def _get__MPW(self): return ones(self.n_mp) / self.n_mp * 2 elasticity_tensors = Property(depends_on='E, nu, stress_state') @cached_property def _get_elasticity_tensors(self): ''' Intialize the fourth order elasticity tensor for 3D or 2D plane strain or 2D plane stress ''' # ---------------------------------------------------------------------------- # Lame constants calculated from E and nu # ---------------------------------------------------------------------------- E = self.E nu = self.nu # first Lame paramter la = E * nu / ((1 + nu) * (1 - 2 * nu)) # second Lame parameter (shear modulus) mu = E / (2 + 2 * nu) # ----------------------------------------------------------------------------------------------------- # Get the fourth order elasticity and compliance tensors for the 3D-case # ----------------------------------------------------------------------------------------------------- # The following lines correspond to the tensorial expression: # (using numpy functionality in order to avoid the loop): # # D4_e_3D = zeros((3,3,3,3),dtype=float) # C4_e_3D = zeros((3,3,3,3),dtype=float) # delta = identity(3) # for i in range(0,3): # for j in range(0,3): # for k in range(0,3): # for l in range(0,3): # # elasticity tensor (cf. Jir/Baz Inelastic analysis of structures Eq.D25): # D4_e_3D[i,j,k,l] = la * delta[i,j] * delta[k,l] + \ # mu * ( delta[i,k] * delta[j,l] + delta[i,l] * delta[j,k] ) # # elastic compliance tensor (cf. Simo, Computational Inelasticity, Eq.(2.7.16) AND (2.1.16)): # C4_e_3D[i,j,k,l] = (1+nu)/(2*E) * \ # ( delta[i,k] * delta[j,l] + delta[i,l]* delta[j,k] ) - \ # nu / E * delta[i,j] * delta[k,l] # # NOTE: swapaxes returns a reference not a copy! # (the index notation always refers to the initial indexing (i=0,j=1,k=2,l=3)) delta = identity(3) delta_ijkl = outer(delta, delta).reshape(3, 3, 3, 3) delta_ikjl = delta_ijkl.swapaxes(1, 2) delta_iljk = delta_ikjl.swapaxes(2, 3) D4_e_3D = la * delta_ijkl + mu * (delta_ikjl + delta_iljk) C4_e_3D = -nu / E * delta_ijkl + \ (1 + nu) / (2 * E) * (delta_ikjl + delta_iljk) # ----------------------------------------------------------------------------------------------------- # Get the fourth order elasticity and compliance tensors for the 2D-case # ----------------------------------------------------------------------------------------------------- # 1. step: Get the (6x6)-elasticity and compliance matrices # for the 3D-case: D2_e_3D = map3d_tns4_to_tns2(D4_e_3D) C2_e_3D = map3d_tns4_to_tns2(C4_e_3D) # 2. step: Get the (3x3)-elasticity and compliance matrices # for the 2D-cases plane stress and plane strain: D2_e_2D_plane_stress = get_D_plane_stress(D2_e_3D) D2_e_2D_plane_strain = get_D_plane_strain(D2_e_3D) C2_e_2D_plane_stress = get_C_plane_stress(C2_e_3D) C2_e_2D_plane_strain = get_C_plane_strain(C2_e_3D) if self.stress_state == 'plane_stress': D2_e = D2_e_2D_plane_stress if self.stress_state == 'plane_strain': D2_e = D2_e_2D_plane_strain # 3. step: Get the fourth order elasticity and compliance tensors # for the 2D-cases plane stress and plane strain (D4.shape = (2,2,2,2)) D4_e_2D_plane_stress = map2d_tns2_to_tns4(D2_e_2D_plane_stress) D4_e_2D_plane_strain = map2d_tns2_to_tns4(D2_e_2D_plane_strain) C4_e_2D_plane_stress = map2d_tns2_to_tns4(C2_e_2D_plane_stress) C4_e_2D_plane_strain = map2d_tns2_to_tns4(C2_e_2D_plane_strain) # ----------------------------------------------------------------------------------------------------- # assign the fourth order elasticity and compliance tensors as return values # ----------------------------------------------------------------------------------------------------- if self.stress_state == 'plane_stress': # print 'stress state: plane-stress' D4_e = D4_e_2D_plane_stress C4_e = C4_e_2D_plane_stress if self.stress_state == 'plane_strain': # print 'stress state: plane-strain' D4_e = D4_e_2D_plane_strain C4_e = C4_e_2D_plane_strain return D4_e, C4_e, D2_e def _get_explorer_config(self): '''Get the specific configuration of this material model in the explorer ''' c = super(MATS2DMicroplaneDamage, self)._get_explorer_config() from ibvpy.mats.mats2D.mats2D_rtrace_cylinder import MATS2DRTraceCylinder # overload the default configuration c['rtrace_list'] += [ MATS2DRTraceCylinder(name='Laterne', var_axis='time', idx_axis=0, var_surface='microplane_damage', record_on='update'), ] return c #------------------------------------------------------------------------- # Dock-based view with its own id #------------------------------------------------------------------------- traits_view = View(Include('polar_fn_group'), dock='tab', id='ibvpy.mats.mats3D.mats_2D_cmdm.MATS2D_cmdm', kind='modal', resizable=True, scrollable=True, width=0.6, height=0.8, buttons=['OK', 'Cancel'] )
class InstanceEditor(EditorFactory): """ Editor factory for instance editors. """ # ------------------------------------------------------------------------- # Trait definitions: # ------------------------------------------------------------------------- #: List of items describing the types of selectable or editable instances values = List(InstanceChoiceItem) #: Extended name of the context object trait containing the list of types #: of selectable or editable instances name = Str() #: Is the current value of the object trait editable (vs. merely #: selectable)? editable = Bool(True) #: Should the object trait value be selectable from a list of objects (a #: value of True forces a selection list to be displayed, while a value of #: False displays a selection list only if at least one object in the list #: of possible object values is selectable): selectable = Bool(False) #: Should the editor support drag and drop of objects to set the trait #: value (a value of True forces the editor to allow drag and drop, while #: a value of False only supports drag and drop if at least one item in the #: list of possible objects supports drag and drop): droppable = Bool(False) #: Should factory-created objects be cached? cachable = Bool(True) #: Optional label for button label = Str() #: Optional instance view to use view = AView #: Extended name of the context object trait containing the view, or name #: of the view, to use view_name = Str() #: The ID to use with the view id = Str() #: Kind of pop-up editor (live, modal, nonmodal, wizard) kind = AKind #: The orientation of the instance editor relative to the instance selector orientation = Enum("default", "horizontal", "vertical") #: The default adapter class used to create InstanceChoice compatible #: adapters for instance objects: adapter = Type(InstanceChoice, allow_none=False) # ------------------------------------------------------------------------- # Traits view definitions: # ------------------------------------------------------------------------- traits_view = View([ ["label{Button label}", "view{View name}", "|[]"], ["kind@", "|[Pop-up editor style]<>"], ])
class ToolkitEditorFactory(EditorFactory): """ Editor factory for instance editors. """ #------------------------------------------------------------------------- # Trait definitions: #------------------------------------------------------------------------- # List of items describing the types of selectable or editable instances values = List(InstanceChoiceItem) # Extended name of the context object trait containing the list of types of # selectable or editable instances name = Str # Is the current value of the object trait editable (vs. merely # selectable)? editable = Bool(True) # Should the object trait value be selectable from a list of objects (a # value of True forces a selection list to be displayed, while a value of # False displays a selection list only if at least one object in the list # of possible object values is selectable): selectable = Bool(False) # Should the editor support drag and drop of objects to set the trait value # (a value of True forces the editor to allow drag and drop, while a value # of False only supports drag and drop if at least one item in the list of # possible objects supports drag and drop): droppable = Bool(False) # Should factory-created objects be cached? cachable = Bool(True) # Optional label for button label = Unicode # Optional instance view to use view = AView # Extended name of the context object trait containing the view, or name of # the view, to use view_name = Str # The ID to use with the view id = Str # Kind of pop-up editor (live, modal, nonmodal, wizard) kind = AKind # The orientation of the instance editor relative to the instance selector orientation = Enum('default', 'horizontal', 'vertical') # The default adapter class used to create InstanceChoice compatible # adapters for instance objects: adapter = Type(InstanceChoice, allow_none=False) #------------------------------------------------------------------------- # Traits view definitions: #------------------------------------------------------------------------- traits_view = View([['label{Button label}', 'view{View name}', '|[]'], ['kind@', '|[Pop-up editor style]<>']])
class BaseMultiImageFactory(ABCHasStrictTraits): """Main component contributed by plugins to allow expansion of the software. Represents a multi-channel image that can be loaded from a single or multiple files, with an analysis routine. """ #: Label to be displayed in UI label = Str() #: Multi image class type associated with this factory multi_image_class = Type(IMultiImage) #: Reader class, used to load a BaseMultiImage from file reader_class = Type(IMultiImageReader) #: Analyser class, used to perform an analysis script on #: a specific image type analyser_class = Type(IMultiImageAnalyser) #: Parser class, used to collate files into sets parser_class = Type(IFileParser) #: Viewer class, used to display an image type viewer_class = Type(IMultiImageViewer) def __init__(self, **traits): label = self.get_label() multi_image = self.get_multi_image() reader = self.get_reader() analyser = self.get_analyser() parser = self.get_parser() viewer = self.get_viewer() super(BaseMultiImageFactory, self).__init__(label=label, multi_image_class=multi_image, reader_class=reader, analyser_class=analyser, parser_class=parser, viewer_class=viewer, **traits) @abstractmethod def get_label(self): """Returns key associated with this factory""" @abstractmethod def get_multi_image(self): """Returns BaseMultiImage associated with this factory""" @abstractmethod def get_reader(self): """Returns BaseMultiImageReader class able to load the BaseMultiImage class created by this factory""" @abstractmethod def get_analyser(self): """Returns BaseMultiImageAnalyser class able to analyse the BaseMultiImage class created by this factory""" @abstractmethod def get_parser(self): """Returns BaseFileParser class able to collate image files together""" @abstractmethod def get_viewer(self): """Returns BaseMultiImageViewer class able to display the BaseMultiImage class created by this factory""" def create_reader(self, **kwargs): """Public method used to return an instance of BaseMultiImageReader""" return self.reader_class(**kwargs) def create_analyser(self, **kwargs): """Public method used to return an instance of BaseMultiImageAnalyser""" return self.analyser_class(**kwargs) def create_parser(self, **kwargs): """Public method used to return an instance of BaseFileParser""" return self.parser_class(**kwargs) def create_viewer(self, **kwargs): """Public method used to return an instance of BaseMultiImageViewer""" return self.viewer_class(**kwargs)
class Variable(HasStrictTraits): """ Represents a variable in a data set. Typically corresponds to a column in a flat file or SQL database. """ # The name of the variable. name = Str() # The type of the variable, represented as a TraitType. # We use a TraitType instead of a NumPy dtype or SQL data type to avoid a # coupling to any particular data source. type = Type() # Whether the variable is categorical or numerical. # By default, this is inferred from the ``type`` attribute and boolean # types are treated as numerical. is_numerical = Bool() # An object identifying the source of a variable, e.g., a filename or a # SQL table name. source = Any() # Summary statistics for the variable. statistics = Dict(Str, Any) def __init__(self, name, type, **traits): super(Variable, self).__init__(name=name, type=type, **traits) def __repr__(self): type_str = 'None' if self.type is None else self.type.__name__ return 'Variable({0}, {1})'.format(repr(self.name), type_str) def __eq__(self, other): return (isinstance(other, Variable) and self.name == other.name and self.type == other.type and self.is_numerical == other.is_numerical and self.source == other.source) def _is_numerical_default(self): from traits.api import BaseStr return not issubclass(self.type, BaseStr) @classmethod def from_data_frame(cls, df, statistics=False, **traits): """ Extract a list of Variables from a pandas DataFrame. """ variables = [] for col, dtype in zip(df.columns, df.dtypes): var = cls.from_dtype(col, dtype, **traits) if statistics: var.statistics = dict(df[col].describe()) variables.append(var) return variables @classmethod def from_metadata(cls, df, type, **traits): """ Extract a list of Variables from a metadata table. """ variables = [] of_type = df[df['type'] == type] for _, row in of_type.iterrows(): name = row['name'] type = R_CLASS_TO_TRAIT[row['dtype']] variables.append(cls(name, type, **traits)) return variables @classmethod def from_dtype(cls, name, dtype, **traits): from traits.trait_numeric import dtype2trait if dtype.name == 'bool': type = Bool elif dtype.name == 'object': type = Str else: type = dtype2trait(dtype) return cls(name, type, **traits)
class XDomainFEGrid(BMCSTreeNode): hidden = Bool(False) #========================================================================= # Type and shape specification of state variables representing the domain #========================================================================= U_var_shape = Property(Int) def _get_U_var_shape(self): return self.mesh.n_dofs vtk_expand_operator = Property def _get_vtk_expand_operator(self): return self.fets.vtk_expand_operator K_type = Type(SysMtxArray) state_var_shape = Property(Tuple) def _get_state_var_shape(self): return ( self.mesh.n_active_elems, self.fets.n_m, ) #========================================================================= # Methods needed by XDomain to chain the subdomains #========================================================================= dof_offset = Property def _get_dof_offset(self): return self.mesh.dof_offset n_active_elems = Property def _get_n_active_elems(self): return self.mesh.n_active_elems def set_next(self, next_): self.mesh.next_grid = next_.mesh def set_prev(self, prev): self.mesh.prev_grid = prev.mesh #========================================================================= # Input parameters #========================================================================= coord_min = Array(Float, value=[0., 0., 0.], GEO=True) '''Grid geometry specification - min corner point ''' coord_max = Array(Float, value=[1., 1., 1.], MESH=True) '''Grid geometry specification - max corner point ''' shape = Array(Int, value=[1, 1, 1], MESH=True) '''Number of elements in the individual dimensions ''' geo_transform = Callable '''Geometry transformation ''' integ_factor = Float(1.0, input=True, CS=True) '''Integration factor used to multiply the integral ''' fets = Instance(IFETSEval, input=True, FE=True) '''Finite element type ''' n_u = Property """Dimension of the field variables in the finite element formulation """ def _get_n_u(self): return self.fets.n_nodal_dofs Diff1_abcd = Array(np.float_, input=True) '''Symmetric operator distributing the first order derivatives of the shape functions into the tensor field ''' def _Diff1_abcd_default(self): delta = np.identity(self.n_u) # symmetrization operator Diff1_abcd = 0.5 * (np.einsum('ac,bd->abcd', delta, delta) + np.einsum('ad,bc->abcd', delta, delta)) return Diff1_abcd #========================================================================= # Finite element discretization respecting the FE definition #========================================================================= mesh = Property(Instance(FEGrid), depends_on='MESH,GEO') @cached_property def _get_mesh(self): return FEGrid(coord_min=self.coord_min, coord_max=self.coord_max, shape=self.shape, geo_transform=self.geo_transform, fets_eval=self.fets) x_Eia = Property(depends_on='MESH,GEO,CS,FE') def _get_x_Eia(self): x_Ia = self.mesh.X_Id I_Ei = self.mesh.I_Ei x_Eia = x_Ia[I_Ei, :] return x_Eia x_Ema = Property(depends_on='MESH,GEO,CS,FE') def _get_x_Ema(self): return np.einsum('im,Eia->Ema', self.fets.N_im, self.x_Eia) o_Ia = Property(depends_on='MESH,GEO,CS,FE') @cached_property def _get_o_Ia(self): x_Ia = self.mesh.X_Id n_I, _ = x_Ia.shape n_a = self.mesh.n_nodal_dofs do = self.mesh.dof_offset return do + np.arange(n_I * n_a, dtype=np.int_).reshape(-1, n_a) o_Eia = Property(depends_on='MESH,GEO,CS,FE') @cached_property def _get_o_Eia(self): I_Ei = self.mesh.I_Ei return self.o_Ia[I_Ei] B1_Einabc = Property(depends_on='MESH,GEO,CS,FE') '''Kinematic mapping between displacement and strain in every visualization point ''' @cached_property def _get_B1_Einabc(self): inv_J_Enar = np.linalg.inv(self.J_Enar) return np.einsum('abcd,imr,Eidr->Eimabc', self.Diff1_abcd, self.fets.dN_inr, inv_J_Enar) I_Ei = Property(depends_on='MESH,GEO,CS,FE') '''[element, node] -> global node ''' def _get_I_Ei(self): return self.mesh.I_Ei det_J_Em = Property(depends_on='MESH,GEO,CS,FE') '''Jacobi matrix in integration points ''' @cached_property def _get_det_J_Em(self): return np.linalg.det(self.J_Emar) J_Emar = Property(depends_on='MESH,GEO,CS,FE') '''Jacobi matrix in integration points ''' @cached_property def _get_J_Emar(self): return np.einsum('imr,Eia->Emar', self.fets.dN_imr, self.x_Eia) J_Enar = Property(depends_on='MESH,GEO,CS,FE') '''Jacobi matrix in nodal points ''' @cached_property def _get_J_Enar(self): return np.einsum('inr,Eia->Enar', self.fets.dN_inr, self.x_Eia) #========================================================================= # Conversion between linear algebra objects and field variables #========================================================================= B1_Eimabc = Property(depends_on='MESH,GEO,CS,FE') '''Kinematic mapping between displacements and strains in every integration point. ''' @cached_property def _get_B1_Eimabc(self): inv_J_Emar = np.linalg.inv(self.J_Emar) return np.einsum('abcd,imr,Emrd->Eimabc', self.Diff1_abcd, self.fets.dN_imr, inv_J_Emar) B_Eimabc = Property(depends_on='MESH,GEO,CS,FE') '''Kinematic mapping between displacements and strains in every integration point. ''' @cached_property def _get_B_Eimabc(self): return self.B1_Eimabc BB_Emicjdabef = Property(depends_on='MESH,GEO,CS,FE') '''Quadratic form of the kinematic mapping. ''' def _get_BB_Emicjdabef(self): return np.einsum('...Eimabc,...Ejmefd, Em, m->...Emicjdabef', self.B_Eimabc, self.B_Eimabc, self.det_J_Em, self.fets.w_m) n_dofs = Property def _get_n_dofs(self): return self.mesh.n_dofs ################################################################## # def map_U_to_field(self, U_o): # n_c = self.fets.n_nodal_dofs U_Eia = U_o[self.o_Eia] eps_Emab = np.einsum('Eimabc,Eic->Emab', self.B_Eimabc, U_Eia) return eps_Emab def map_field_to_F(self, sig_Emab): _, n_i, _, _, _, n_c = self.B_Eimabc.shape f_Eic = self.integ_factor * np.einsum( 'm,Eimabc,Emab,Em->Eic', self.fets.w_m, self.B_Eimabc, sig_Emab, self.det_J_Em) f_Ei = f_Eic.reshape(-1, n_i * n_c) o_E = self.o_Eia.reshape(-1, n_i * n_c) return o_E.flatten(), f_Ei.flatten() def map_field_to_K(self, D_Emabef): K_Eicjd = self.integ_factor * np.einsum('Emicjdabef,Emabef->Eicjd', self.BB_Emicjdabef, D_Emabef) _, n_i, n_c, n_j, n_d = K_Eicjd.shape K_Eij = K_Eicjd.reshape(-1, n_i * n_c, n_j * n_d) o_Ei = self.o_Eia.reshape(-1, n_i * n_c) return SysMtxArray(mtx_arr=K_Eij, dof_map_arr=o_Ei) ########### debug_cell_data = Bool(False) # @todo - comment this procedure` def get_vtk_cell_data(self, position, point_offset, cell_offset): if position == 'nodes': subcell_offsets, subcell_lengths, subcells, subcell_types = \ self.fets.vtk_node_cell_data elif position == 'int_pnts': subcell_offsets, subcell_lengths, subcells, subcell_types = \ self.fets.vtk_ip_cell_data if self.debug_cell_data: print('subcell_offsets') print(subcell_offsets) print('subcell_lengths') print(subcell_lengths) print('subcells') print(subcells) print('subcell_types') print(subcell_types) n_subcells = subcell_types.shape[0] n_cell_points = self.n_cell_points subcell_size = subcells.shape[0] + n_subcells if self.debug_cell_data: print('n_cell_points', n_cell_points) print('n_cells', self.n_cells) vtk_cell_array = np.zeros((self.n_cells, subcell_size), dtype=int) idx_cell_pnts = np.repeat(True, subcell_size) if self.debug_cell_data: print('idx_cell_pnts') print(idx_cell_pnts) idx_cell_pnts[subcell_offsets] = False if self.debug_cell_data: print('idx_cell_pnts') print(idx_cell_pnts) idx_lengths = idx_cell_pnts == False if self.debug_cell_data: print('idx_lengths') print(idx_lengths) point_offsets = np.arange(self.n_cells) * n_cell_points point_offsets += point_offset if self.debug_cell_data: print('point_offsets') print(point_offsets) vtk_cell_array[:, idx_cell_pnts] = point_offsets[:, None] + subcells[None, :] vtk_cell_array[:, idx_lengths] = subcell_lengths[None, :] if self.debug_cell_data: print('vtk_cell_array') print(vtk_cell_array) n_active_cells = self.mesh.n_active_elems if self.debug_cell_data: print('n active cells') print(n_active_cells) cell_offsets = np.arange(n_active_cells, dtype=int) * subcell_size cell_offsets += cell_offset vtk_cell_offsets = cell_offsets[:, None] + subcell_offsets[None, :] if self.debug_cell_data: print('vtk_cell_offsets') print(vtk_cell_offsets) vtk_cell_types = np.zeros(self.n_cells * n_subcells, dtype=int).reshape(self.n_cells, n_subcells) vtk_cell_types += subcell_types[None, :] if self.debug_cell_data: print('vtk_cell_types') print(vtk_cell_types) return (vtk_cell_array.flatten(), vtk_cell_offsets.flatten(), vtk_cell_types.flatten()) n_cells = Property(Int) def _get_n_cells(self): '''Return the total number of cells''' return self.mesh.n_active_elems n_cell_points = Property(Int) def _get_n_cell_points(self): '''Return the number of points defining one cell''' return self.fets.n_vtk_r
class BaseExtensionPlugin(Plugin): """Base class for extension plugins, that is, plugins that are provided by external contributors. It provides a set of slots to be populated that end up contributing to the application extension points. To use the class, simply inherit it in your plugin, and reimplement the methods as from example:: class MyPlugin(BaseExtensionPlugin): id = plugin_id("enthought", "plugin_name", 0) def get_name(self): return "Enthought plugin" def get_version(self): return 0 def get_description(self): return "A long description" def get_factory_classes(self): return [ MyDataSourceFactory1, MyDataSourceFactory2, MyMCOFactory ] """ #: The user visible name of the plugin name = Str() #: An integer representing the version of the plugin version = Int() #: The user visible long description of the plugin description = Str() #: Reports if the plugin loaded its factories successfully or not. broken = Bool(False) #: The error message generated by the factory instantiations error_msg = Str() #: The error traceback generated by the factory instantiations. error_tb = Str() #: A list of all the factory classes to export. factory_classes = List( Either(Type(BaseDataSourceFactory), Type(BaseMCOFactory), Type(BaseNotificationListenerFactory), Type(BaseUIHooksFactory))) #: A list of available Multi Criteria Optimizers this plugin exports. mco_factories = List(IMCOFactory, contributes_to=ExtensionPointID.MCO_FACTORIES) #: A list of the available Data Sources this plugin exports. data_source_factories = List( IDataSourceFactory, contributes_to=ExtensionPointID.DATA_SOURCE_FACTORIES) #: A list of the available notification listeners this plugin exports notification_listener_factories = List( INotificationListenerFactory, contributes_to=ExtensionPointID.NOTIFICATION_LISTENER_FACTORIES) #: A list of the available ui hooks this plugin exports ui_hooks_factories = List( IUIHooksFactory, contributes_to=ExtensionPointID.UI_HOOKS_FACTORIES) #: The logger. _logger = Instance(logging.Logger) def __init__(self, *args, **kwargs): super(BaseExtensionPlugin, self).__init__(*args, **kwargs) try: self.name = self.get_name() self.description = self.get_description() self.version = self.get_version() self.factory_classes = self.get_factory_classes() self.mco_factories[:] = [ cls(self) for cls in self._factory_by_type(BaseMCOFactory) ] self.data_source_factories[:] = [ cls(self) for cls in self._factory_by_type(BaseDataSourceFactory) ] self.notification_listener_factories[:] = [ cls(self) for cls in self._factory_by_type( BaseNotificationListenerFactory) ] self.ui_hooks_factories[:] = [ cls(self) for cls in self._factory_by_type(BaseUIHooksFactory) ] except Exception as e: self._logger.exception(e) self.error_msg = str(e) self.error_tb = traceback.format_exc() self.name = "" self.description = "" self.version = 0 self.broken = True self.mco_factories[:] = [] self.data_source_factories[:] = [] self.notification_listener_factories[:] = [] self.ui_hooks_factories[:] = [] def get_name(self): raise NotImplementedError( "get_name was not implemented in plugin {}".format(self.__class__)) def get_version(self): raise NotImplementedError( "get_version was not implemented in plugin {}".format( self.__class__)) def get_description(self): return "No description available" def get_factory_classes(self): """Must return a list of factory classes that this plugin exports. """ raise NotImplementedError( "get_factory_classes was not implemented in plugin {}".format( self.__class__)) def _factory_by_type(self, type_): """Returns all the factories of the given type""" return [cls for cls in self.factory_classes if issubclass(cls, type_)] def __logger_default(self): return logging.getLogger(self.__class__.__name__)
class XDomainFE(BMCSTreeNode): hidden = Bool(False) #========================================================================= # Type and shape specification of state variables representing the domain #========================================================================= U_var_shape = Property(Int) def _get_U_var_shape(self): return self.mesh.n_dofs vtk_expand_operator = Property def _get_vtk_expand_operator(self): return self.fets.vtk_expand_operator K_type = Type(SysMtxArray) state_var_shape = Property(Tuple) def _get_state_var_shape(self): return ( self.mesh.n_active_elems, self.fets.n_m, ) #========================================================================= # Methods needed by XDomain to chain the subdomains #========================================================================= dof_offset = Property def _get_dof_offset(self): return self.mesh.dof_offset n_active_elems = Property def _get_n_active_elems(self): return self.mesh.n_active_elems def set_next(self, next_): self.mesh.next_grid = next_.mesh def set_prev(self, prev): self.mesh.prev_grid = prev.mesh #========================================================================= # Input parameters #========================================================================= # coord_min = Array(Float, value=[0., 0., 0.], GEO=True) # '''Grid geometry specification - min corner point # ''' # coord_max = Array(Float, value=[1., 1., 1.], MESH=True) # '''Grid geometry specification - max corner point # ''' # shape = Array(Int, value=[1, 1, 1], MESH=True) # '''Number of elements in the individual dimensions # ''' # geo_transform = Callable # '''Geometry transformation # ''' integ_factor = Float(1.0, input=True, CS=True) '''Integration factor used to multiply the integral ''' # fets = Instance(IFETSEval, input=True, FE=True) # '''Finite element type # ''' mesh = Instance(IFEUniformDomain) X_Id = DelegatesTo('mesh') # I_Ei = DelegatesTo('mesh') o_Ia = Property(depends_on='MESH,GEO,CS,FE') @cached_property def _get_o_Ia(self): x_Ia = self.mesh.X_Id n_I, _ = x_Ia.shape n_a = self.mesh.n_nodal_dofs do = self.mesh.dof_offset return do + np.arange(n_I * n_a, dtype=np.int_).reshape(-1, n_a) # for shell element, it's array([[ 0, 1, 2, 3, 4], # [ 5, 6, 7, 8, 9], # [10, 11, 12, 13, 14]]) o_Eia = Property(depends_on='MESH,GEO,CS,FE') @cached_property def _get_o_Eia(self): I_Ei = self.I_Ei return self.o_Ia[I_Ei]
class BaseDataSourceModel(BaseModel): """Base class for the factory specific DataSource models. This model will also provide, through traits/traitsui magic the View that will appear in the workflow manager UI. In your factory definition, your factory-specific model must reimplement this class. """ #: A reference to the creating factory, so that we can #: retrieve it as the originating factory. factory = Instance(IDataSourceFactory, visible=False, transient=True) #: Specifies binding between input slots and source for that value. #: Each InputSlotMap instance specifies this information for each of the #: slots. input_slot_info = List(Instance(InputSlotInfo), visible=False) #: Allows to assign names and KPI status to the output slots, so that #: they can be referenced somewhere else (e.g. another layer's #: DataSources). #: If the name is the empty string, it means that the user is not #: interested in preserving the information, and should therefore be #: discarded and not propagated further. output_slot_info = List(Instance(OutputSlotInfo), visible=False) #: This event claims that a change in the model influences the slots #: (either input or output). It must be triggered every time a specific #: option in your model implies a change in the slots. The UI will detect #: this and adapt the visual entries. changes_slots = Event() #: Type of the Data Source Start event _start_event_type = Type(DataSourceStartEvent, visible=False, transient=True) #: Type of the Data Source Finish event _finish_event_type = Type(DataSourceFinishEvent, visible=False, transient=True) def verify(self): """ Verify the data source model. The data source model must have: - input and output slots match between instance and model - all output slots named - no errors in input or output slots Returns ------- errors : list of VerifierErrors The list of all detected errors in the data source model. """ try: data_source = self.factory.create_data_source() except Exception: logger.exception( "Unable to create data source from factory '%s', plugin " "'%s'. This might indicate a programming error", self.factory.id, self.factory.plugin_id, ) raise try: input_slots, output_slots = data_source.slots(self) except Exception: logger.exception( "Unable to retrieve slot information from data source" " created by factory '%s', plugin '%s'. This might " "indicate a programming error.", self.factory.id, self.factory.plugin_id) raise factory = self.factory errors = [] if len(input_slots) != len(self.input_slot_info): local_error_txt = ("The number of input slots ({} values) returned" " by '{}' does not match the number" " of user-defined names specified ({} values)." " This is either a plugin error or a file" " error.").format(len(input_slots), factory.name, len(self.input_slot_info)) errors.append( VerifierError( subject=self, local_error=local_error_txt, global_error=("A data source model has incorrect number " "of input slots."), )) for input_slot in self.input_slot_info: errors += input_slot.verify() if len(output_slots) != len(self.output_slot_info): local_error_txt = ( "The number of output slots ({} values) returned" " by '{}' does not match the number" " of user-defined names specified ({} values)." " This is either a plugin error or a file" " error.").format(len(output_slots), factory.name, len(self.output_slot_info)) errors.append( VerifierError( subject=self, local_error=local_error_txt, global_error="A data source model has incorrect number " "of output slots.")) if self.output_slot_info and not any( output_slot.name for output_slot in self.output_slot_info): errors.append( VerifierError( subject=self, severity='warning', local_error="All output variables have undefined names", global_error=( "A data source model has no defined output names"), )) for output_slot in self.output_slot_info: errors += output_slot.verify() return errors def notify_start_event(self): """ Creates base event indicating the start of the MCO.""" self.notify( self._start_event_type(input_names=list( p.name for p in self.input_slot_info))) def notify_finish_event(self): """ Creates base event indicating the finished MCO.""" self.notify( self._finish_event_type(output_names=list( p.name for p in self.output_slot_info))) @on_trait_change("+changes_slots") def _trigger_changes_slots(self, obj, name, new): changes_slots = self.traits()[name].changes_slots if changes_slots: self.changes_slots = True @classmethod def from_json(cls, factory, json_data): """ Instantiate an BaseMCOModel object from a `json_data` dictionary and the generating `factory` object. Parameters ---------- factory: IDataSourceFactory Generating factory object json_data: dict Dictionary with a DataSourceModel serialized data Returns ---------- layer: BaseDataSourceModel BaseDataSourceModel instance with attributes values from the `json_data` dict """ data = deepcopy(json_data) input_slots = [InputSlotInfo(**d) for d in data["input_slot_info"]] data["input_slot_info"] = input_slots output_slots = [OutputSlotInfo(**d) for d in data["output_slot_info"]] data["output_slot_info"] = output_slots data_source = factory.create_model(data) return data_source