class SeparateFrame(Immediate): description = "Separate the selected frame" menu_info = MenuInfo("default/_Object:tools/A_rrange:single", "_Separate frame", order=(0, 4, 1, 1, 2, 0)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating & initializing node = context.application.cache.node Frame = context.application.plugins.get_node("Frame") if not Frame.check_add(node.__class__): return False if node.get_fixed(): return False if not isinstance(node, GLTransformationMixin): return False if not node.parent.check_add(Frame): return False # C) passed all tests: return True def do(self): victim = context.application.cache.node Frame = context.application.plugins.get_node("Frame") frame = Frame(name="Frame of " + victim.name) primitive.Add(frame, victim.parent, index=victim.get_index()) primitive.Transform(frame, victim.transformation) primitive.Move(victim, frame) primitive.SetProperty(victim, "transformation", victim.Transformation())
class MoldenLabels(Immediate): description = "Label the atoms in molden style." menu_info = MenuInfo("default/_Object:tools/_Molecular:rearrange", "_Molden labels", order=(0, 4, 1, 5, 0, 2)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating cache = context.application.cache if cache.node is None: return False contains_atoms = False for cls in cache.child_classes: if issubclass(cls, Atom): contains_atoms = True break if not contains_atoms: return False # C) passed all tests return True def do(self): counter = 1 for node in context.application.cache.children: if isinstance(node, Atom): primitive.SetProperty( node, "name", periodic[node.number].symbol + str(counter)) counter += 1
class SelectBondedNeighbors(Immediate): description = "Select bonded neighbors" menu_info = MenuInfo("default/_Select:default", "_Bonded neighbors", ord("n"), False, order=(0, 3, 0, 5)) authors = [authors.bartek_szyja] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating if len(context.application.cache.nodes) == 0: return False # C) passed all tests: return True def do(self): Atom = context.application.plugins.get_node("Atom") to_select = [] for node in context.application.cache.nodes: if isinstance(node, Atom): to_select.append(node) for bond in node.iter_bonds(): if bond.children[ 0].target not in context.application.cache.nodes: to_select.append(bond.children[0].target) if bond.children[ 1].target not in context.application.cache.nodes: to_select.append(bond.children[1].target) context.application.main.select_nodes(to_select)
class EditSelectionFilter(Immediate): description = "Edit selection filter" menu_info = MenuInfo("default/_Select:preferences", "_Selection filter", order=(0, 3, 2, 0)) authors = [authors.toon_verstraelen] selection_filter = FieldsDialogSimple( "Selection filter", fields.group.Table(fields=[ fields.edit.CheckButton( label_text="Filter active", attribute_name="filter_active", show_popup=False, ), fields.faulty.Expression( label_text="Filter expression", attribute_name="filter_expression", show_popup=True, history_name="filter", ) ]), ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL), (gtk.STOCK_OK, gtk.RESPONSE_OK)) ) @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # C) passed all tests: return True def do(self): self.selection_filter.run(context.application.main)
class AddPlane(Immediate): description = "Add plane" menu_info = MenuInfo("default/_Object:tools/_Add:3d", "_Plane", image_name="plugins/basic/plane.svg", order=(0, 4, 1, 0, 0, 5)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating cache = context.application.cache if len(cache.nodes) < 3: return False if len(cache.translations) < 3: return False if cache.common_parent is None: return False # C) passed all tests: return True def do(self): cache = context.application.cache nodes = cache.nodes primitive.Add(Plane(targets=nodes), cache.common_parent, index=cache.highest_index + 1)
class About(Immediate): description = "Show the about box" menu_info = MenuInfo("help/_Help:default", "_About", image_name=gtk.STOCK_ABOUT, order=(1, 0, 0, 0)) authors = [authors.toon_verstraelen] def do(self): about.run()
class FileImport(Immediate): description = "Import a file in the current model" menu_info = MenuInfo("default/_File:impexp", "_Import", order=(0, 0, 1, 0)) repeatable = False authors = [authors.toon_verstraelen] def do(self): def file_import(filename): tmp_model = Model() tmp_model.file_open(filename) if len(tmp_model.universe.children) > 0: Frame = context.application.plugins.get_node("Frame") root_frame = Frame(name=os.path.basename(filename)) tmp = list(tmp_model.universe.children) while len(tmp_model.universe.children) > 0: tmp_model.universe.remove(tmp_model.universe.children[0]) for node in tmp: root_frame.add(node) del tmp context.application.model.universe.add(root_frame) if len(tmp_model.folder.children) > 0: Folder = context.application.plugins.get_node("Folder") root_folder = Folder(name=os.path.basename(filename)) tmp = list(tmp_model.folder.children) while len(tmp_model.folder.children) > 0: tmp_model.universe.remove(tmp_model.folder.children[0]) for node in tmp: root_folder.add(node) del tmp context.application.model.folder.add(root_folder) tmp_model.file_close() run_file_dialog(context.application.file_import_dialog, file_import)
class Cut(Immediate): description = "Cut the selection to the clipboard" menu_info = MenuInfo("default/_Edit:clipboard", "Cu_t", accel_key=ord("x"), image_name=gtk.STOCK_CUT, order=(0, 1, 1, 0)) repeatable = False authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating cache = context.application.cache if len(cache.nodes) == 0: return False if cache.some_nodes_without_children_fixed: return False # C) passed all tests: return True def do(self): source = list(context.application.cache.nodes_without_children) copy_to_clipboard(source) delete(source)
class WrapCellContents(Immediate): description = "Wrap the unit cell contents" menu_info = MenuInfo("default/_Object:tools/_Unit Cell:default", "_Wrap cell contents", ord("w"), order=(0, 4, 1, 4, 0, 3)) repeatable = False authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating universe = context.application.model.universe if sum(universe.cell.active) == 0: return False if len(universe.children) == 0: return False # C) passed all tests: return True def do(self): universe = context.application.model.universe for child in universe.children: if isinstance(child, GLTransformationMixin) and isinstance( child.transformation, Translation): cell_index = universe.cell.to_fractional( child.transformation.t) cell_index = numpy.floor(cell_index) if cell_index.any(): t = child.transformation.t - universe.cell.to_cartesian( cell_index) new_transformation = child.transformation.copy_with(t=t) primitive.SetProperty(child, "transformation", new_transformation)
class AutoConnectPhysical(AutoConnectMixin, Immediate): description = "Add bonds (database)" menu_info = MenuInfo("default/_Object:tools/_Molecular:add", "_Add bonds (database)", ord("b"), order=(0, 4, 1, 5, 1, 0)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not AutoConnectMixin.analyze_selection(): return False if not Immediate.analyze_selection(): return False # C) passed all tests: return True def allow_node(self, node): return isinstance(node, context.application.plugins.get_node("Atom")) def get_vector(self, atom0, atom1, distance): if atom0 in atom1.iter_neighbors(): return None bond_type = bonds.bonded(atom0.number, atom1.number, distance) if bond_type is None: return None else: return Bond(bond_type=bond_type, targets=[atom0, atom1]) def do(self): AutoConnectMixin.do(self, bonds.max_length)
class Duplicate(Immediate): description = "Duplicate nodes" menu_info = MenuInfo("default/_Edit:deldup", "_Duplicate", ord("d"), order=(0, 1, 2, 1)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating cache = context.application.cache if cache.some_nodes_fixed: return False if not isinstance(cache.parent, ContainerMixin): return False # D) passed all tests: return True def do(self): cache = context.application.cache originals = cache.nodes parent = cache.parent highest_index = cache.highest_index serialized = StringIO.StringIO() dump_to_file(serialized, originals) serialized.seek(0) duplicates = load_from_file(serialized) for duplicate in duplicates: highest_index += 1 primitive.Add(duplicate, parent, index=highest_index)
class Align(CenterAlignBase): description = "Align to parent" menu_info = MenuInfo("default/_Object:tools/_Transform:align", "_Align", order=(0, 4, 1, 2, 3, 0)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not CenterAlignBase.analyze_selection(): return False # B) validating cache = context.application.cache node = cache.node if not isinstance(node, GLTransformationMixin): return False if not isinstance(node.transformation, Rotation): return False if cache.some_neighbors_fixed: return False # C) passed all tests: return True def do(self): cache = context.application.cache rotation = Rotation(cache.node.transformation.r) CenterAlignBase.do(self, cache.parent, cache.transformed_neighbors, rotation)
class AutoConnectSprings(AutoConnectMixin, Immediate): description = "Connect overlapping atoms with springs" menu_info = MenuInfo("default/_Object:tools/_Builder:spring", "_Connect overlapping atoms with springs", order=(0, 4, 1, 6, 0, 0)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not AutoConnectMixin.analyze_selection(): return False if not Immediate.analyze_selection(): return False # C) passed all tests: return True def allow_node(self, node): return isinstance(node, context.application.plugins.get_node("Atom")) def get_vector(self, atom1, atom2, distance): for reference in atom2.references: referent = reference.parent if isinstance(referent, Spring): if (referent.children[0].target == atom1) or \ (referent.children[1].target == atom1): return None if 0.5 * (periodic[atom1.number].covalent_radius + periodic[atom2.number].covalent_radius) >= distance: return Spring(targets=[atom1, atom2]) else: return None def do(self): AutoConnectMixin.do(self, 2 * periodic.max_radius)
class FileSave(Immediate): description = "Save the current file" menu_info = MenuInfo("default/_File:default", "_Save", ord("s"), image_name=gtk.STOCK_SAVE, order=(0, 0, 0, 2)) repeatable = False authors = [authors.toon_verstraelen] def do(self): context.application.main.file_save()
class FileOpen(Immediate): description = "Open a file" menu_info = MenuInfo("default/_File:default", "_Open", ord("o"), image_name=gtk.STOCK_OPEN, order=(0, 0, 0, 1)) repeatable = False authors = [authors.toon_verstraelen] def do(self): context.application.main.file_open()
class FileQuit(Immediate): description = "Quit zeobuilder" menu_info = MenuInfo("default/_File:quit", "_Quit", ord("q"), image_name=gtk.STOCK_QUIT, order=(0, 0, 2, 0)) repeatable = False authors = [authors.toon_verstraelen] def do(self): context.application.main.file_quit()
class FileSaveAs(Immediate): description = "Save the current file under a new name" menu_info = MenuInfo("default/_File:default", "Save _as", ord("s"), True, True, image_name=gtk.STOCK_SAVE_AS, order=(0, 0, 0, 3)) repeatable = False authors = [authors.toon_verstraelen] def do(self): context.application.main.file_save_as()
class ViewPlugins(Immediate): description = "Plugins" menu_info = MenuInfo("help/_Help:default", "_Plugins", order=(1, 0, 0, 1)) plugins_dialog = PluginsDialog() authors = [authors.toon_verstraelen] def do(self): self.plugins_dialog.run()
class ConnectArrow(ConnectBase): description = "Connect with arrow" menu_info = MenuInfo("default/_Object:tools/_Connect:pair", "_Arrow", image_name="plugins/basic/arrow.svg", order=(0, 4, 1, 3, 0, 0)) authors = [authors.toon_verstraelen] def new_connector(self, begin, end): return Arrow(targets=[begin, end])
class ConnectSpring(ConnectBase): description = "Connect with spring" menu_info = MenuInfo("default/_Object:tools/_Connect:pair", "_Spring", image_name="plugins/builder/spring.svg", order=(0, 4, 1, 3, 0, 4)) authors = [authors.toon_verstraelen] def new_connector(self, begin, end): return Spring(targets=[begin, end])
class AddNotes(AddBase): description = "Add notes" menu_info = MenuInfo("default/_Object:tools/_Add:non3d", "_Notes", image_name="plugins/basic/notes.svg", order=(0, 4, 1, 0, 1, 1)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): return AddBase.analyze_selection(Notes) def do(self): AddBase.do(self, Notes)
class AddSphere(AddBase): description = "Add sphere" menu_info = MenuInfo("default/_Object:tools/_Add:3d", "_Sphere", image_name="plugins/basic/sphere.svg", order=(0, 4, 1, 0, 0, 1)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): return AddBase.analyze_selection(Sphere) def do(self): AddBase.do(self, Sphere)
class FileNew(Immediate): description = "Create a new file" menu_info = MenuInfo("default/_File:default", "_New", ord("n"), image_name=gtk.STOCK_NEW, order=(0, 0, 0, 0)) repeatable = False authors = [authors.toon_verstraelen] def do(self): Universe = context.application.plugins.get_node("Universe") universe = Universe(axes_visible=False) Folder = context.application.plugins.get_node("Folder") folder = Folder() context.application.main.file_new(universe, folder)
class AddFolder(AddBase): description = "Add folder" menu_info = MenuInfo("default/_Object:tools/_Add:non3d", "_Folder", image_name="plugins/basic/folder.svg", order=(0, 4, 1, 0, 1, 0)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): return AddBase.analyze_selection(Folder) def do(self): AddBase.do(self, Folder)
class AddPoint(AddBase): description = "Add point" menu_info = MenuInfo("default/_Object:tools/_Add:3d", "_Point", image_name="plugins/basic/point.svg", order=(0, 4, 1, 0, 0, 2)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): return AddBase.analyze_selection(Point) def do(self): AddBase.do(self, Point)
class TetraCoordination(Immediate): description = "T-atom coordination" menu_info = MenuInfo("default/_Object:tools/_Molecular:info", "_T-atom coordination", order=(0, 4, 1, 5, 2, 1)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # B) validating if len(context.application.cache.nodes) == 0: return False # C) passed all tests: return True def do(self): Atom = context.application.plugins.get_node("Atom") def iter_all_tetra(nodes): for node in nodes: if isinstance(node, Atom) and node.number > 12: yield node elif isinstance(node, ContainerMixin): for tetra in iter_all_tetra(node.children): yield tetra coordinated_tetra = [[] for i in xrange(5)] for tetra in iter_all_tetra( context.application.cache.nodes_without_children): coordination = 0 for bridging in tetra.iter_neighbors(): if bridging.number > 6: num_t = len([ t for t in bridging.iter_neighbors() if t.number > 12 ]) if num_t > 2: raise UserError("Invalid zeolite structure.") if num_t == 2: coordination += 1 if coordination > 4: raise UserError("Invalid zeolite structure.") coordinated_tetra[coordination].append(tetra) result_dialog = CoordinationDialog(coordinated_tetra) response = result_dialog.run() if response != gtk.RESPONSE_CLOSE: main = context.application.main main.select_nodes(coordinated_tetra[response])
class TranslateDialog(ImmediateWithMemory): description = "Apply translation" menu_info = MenuInfo("default/_Object:tools/_Transform:dialogs", "_Translate", order=(0, 4, 1, 2, 1, 2)) authors = [authors.toon_verstraelen] parameters_dialog = FieldsDialogSimple( "Translation", fields.composed.Translation( label_text="Translate with vector t", attribute_name="translation", ), ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL), (gtk.STOCK_OK, gtk.RESPONSE_OK))) @staticmethod def analyze_selection(parameters=None): # A) calling ancestor if not ImmediateWithMemory.analyze_selection(parameters): return False # B) validating cache = context.application.cache if len(cache.translated_nodes) == 0: return False if cache.parent_of_translated_nodes is None: return False if cache.some_nodes_fixed: return False # C) passed all tests: return True @classmethod def default_parameters(cls): result = Parameters() result.translation = Translation.identity() return result def ask_parameters(self): cache = context.application.cache last = cache.last parent = cache.parent_of_translated_nodes if isinstance(last, Vector): b = last.children[0].translation_relative_to(parent) e = last.children[1].translation_relative_to(parent) if (b is not None) and (e is not None): self.parameters.translation = Translation(e - b) else: self.parameters = self.last_parameters() if self.parameters_dialog.run(self.parameters) != gtk.RESPONSE_OK: self.parameters.clear() def do(self): for victim in context.application.cache.translated_nodes: primitive.Transform(victim, self.parameters.translation)
class SelectNone(Immediate): description = "Select none" menu_info = MenuInfo("default/_Select:default", "_None", order=(0, 3, 0, 0)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): # A) calling ancestor if not Immediate.analyze_selection(): return False # C) passed all tests: return True def do(self): context.application.main.tree_selection.unselect_all()
class AddBox(AddBase): description = "Add box" menu_info = MenuInfo("default/_Object:tools/_Add:3d", "_Box", image_name="plugins/basic/box.svg", order=(0, 4, 1, 0, 0, 0)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): return AddBase.analyze_selection(Box) def do(self): AddBase.do(self, Box)
class CloneOrder(Immediate): description = "Apply the order of the first selection to all the other." menu_info = MenuInfo("default/_Object:tools/_Molecular:rearrange", "_Clone order", order=(0, 4, 1, 5, 0, 3)) authors = [authors.toon_verstraelen] @staticmethod def analyze_selection(): if not Immediate.analyze_selection(): return False cache = context.application.cache if len(cache.nodes) < 2: return False Frame = context.application.plugins.get_node("Frame") for cls in cache.classes: if not issubclass(cls, Frame): return False return True def do(self): frame_ref = context.application.cache.nodes[0] graph_ref = create_molecular_graph([frame_ref]) try: match_generator = GraphSearch(EqualPattern(graph_ref)) except GraphError, e: raise UserError( "Could not setup a graph match definition to clone the order.") some_failed = False all_failed = True for frame_other in context.application.cache.nodes[1:]: graph_other = create_molecular_graph([frame_other]) try: match = match_generator(graph_other).next() all_failed = False except (StopIteration, GraphError): some_failed = True continue moves = [(index1, graph_other.molecule.atoms[index2]) for index1, index2 in match.forward.iteritems()] moves.sort() for new_index, atom2 in moves: primitive.Move(atom2, frame_other, new_index) if all_failed: raise UserError("None of the atom orders could be cloned.") elif some_failed: ok_error( "Some molecules/frames did not match the first frame, so they are not reordered." )