def add_atom_to( self, a1, bond_to_use=None, pos=None): """adds new atom bound to atom id with bond, the position of new atom can be specified in pos or is decided calling find_place(), if x, y is specified and matches already existing atom it will be used instead of creating new one """ if pos != None: x, y = pos else: if bond_to_use: x, y = self.find_place( a1, Screen.any_to_px( self.paper.standard.bond_length), added_order=bond_to_use.order) else: x, y = self.find_place( a1, Screen.any_to_px( self.paper.standard.bond_length)) a2 = None # the new atom if pos: # try if the coordinates are the same as of another atom for at in self.atoms: if abs( at.x - x) < 2 and abs( at.y - y) < 2 and not at == a1: a2 = at break if not a2: a2 = self.create_new_atom( x, y) b = bond_to_use or bond( self.paper.standard, order=1, type='n') self.add_edge( a1, a2, e=b) b.molecule = self b.draw() return a2, b
def add_atom_to(self, a1, bond_to_use=None, pos=None): """adds new atom bound to atom id with bond, the position of new atom can be specified in pos or is decided calling find_place(), if x, y is specified and matches already existing atom it will be used instead of creating new one """ if pos != None: x, y = pos else: if bond_to_use: x, y = self.find_place(a1, Screen.any_to_px( self.paper.standard.bond_length), added_order=bond_to_use.order) else: x, y = self.find_place( a1, Screen.any_to_px(self.paper.standard.bond_length)) a2 = None # the new atom if pos: # try if the coordinates are the same as of another atom for at in self.atoms: if abs(at.x - x) < 2 and abs(at.y - y) < 2 and not at == a1: a2 = at break if not a2: a2 = self.create_new_atom(x, y) b = bond_to_use or bond(self.paper.standard, order=1, type='n') self.add_edge(a1, a2, e=b) b.molecule = self b.draw() return a2, b
def switch_to_type( self, type): if type in "wha" and self.type not in "wha": # get the standard width only if the changes is not within the "wha" group self.wedge_width = Screen.any_to_px( self.paper.standard.wedge_width) elif type not in "wha" and self.type in "wha": # when both are outside the 'wha' do the similar self.bond_width = Screen.any_to_px( self.paper.standard.bond_width) self.type = type
def read_standard_values( self, standard, old_standard=None): meta_enabled.read_standard_values( self, standard, old_standard=old_standard) # wedge width if not old_standard or (standard.wedge_width != old_standard.wedge_width): self.wedge_width = Screen.any_to_px( standard.wedge_width) # line width if not old_standard or (standard.line_width != old_standard.line_width): self.line_width = Screen.any_to_px( standard.line_width) # bond width if not old_standard or (standard.bond_width != old_standard.bond_width): if hasattr( self, 'bond_width'): self.bond_width = misc.signum( self.bond_width) * Screen.any_to_px( standard.bond_width) else: self.bond_width = Screen.any_to_px( standard.bond_width)
def read_standard_values(self, standard, old_standard=None): meta_enabled.read_standard_values(self, standard, old_standard=old_standard) if not old_standard or (standard.line_width != old_standard.line_width): self.line_width = Screen.any_to_px(standard.line_width)
def get_transformed_template(self, n, coords, type="empty", paper=None): """type is type of connection - 'bond', 'atom1'(for single atom), 'atom2'(for atom with more than 1 bond), 'empty'""" pap = paper or Store.app.paper pap.onread_id_sandbox_activate() # must be here to mangle the ids current = molecule(pap, package=self.templates[n]) pap.onread_id_sandbox_finish(apply_to=[current]) # id mangling current.name = "" self._scale_ratio = 1 trans = transform() # type empty - just draws the template - no conection if type == "empty": xt1, yt1 = current.t_atom.get_xy() xt2, yt2 = current.next_to_t_atom.get_xy() x1, y1 = coords bond_length = Screen.any_to_px(Store.app.paper.standard.bond_length) current.delete_items([current.t_atom], redraw=0, delete_single_atom=0) trans.set_move(-xt2, -yt2) trans.set_scaling(bond_length / math.sqrt((xt1 - xt2) ** 2 + (yt1 - yt2) ** 2)) trans.set_move(x1, y1) # type atom elif type == "atom1" or type == "atom2": xt1, yt1 = current.t_atom.get_xy() xt2, yt2 = current.next_to_t_atom.get_xy() x1, y1, x2, y2 = coords trans.set_move(-xt2, -yt2) trans.set_scaling( math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) / math.sqrt((xt1 - xt2) ** 2 + (yt1 - yt2) ** 2) ) trans.set_rotation(math.atan2(xt1 - xt2, yt1 - yt2) - math.atan2(x1 - x2, y1 - y2)) trans.set_move(x2, y2) # type bond elif type == "bond": if not (current.t_bond_first and current.t_bond_second): warn("this template is not capable to be added to bond - sorry.") return None current.delete_items([current.t_atom], redraw=0, delete_single_atom=0) xt1, yt1 = current.t_bond_first.get_xy() xt2, yt2 = current.t_bond_second.get_xy() x1, y1, x2, y2 = coords self._scale_ratio = math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) / math.sqrt( (xt1 - xt2) ** 2 + (yt1 - yt2) ** 2 ) # further needed for bond.bond_width transformation trans.set_move(-xt1, -yt1) trans.set_rotation(math.atan2(xt1 - xt2, yt1 - yt2) - math.atan2(x1 - x2, y1 - y2)) trans.set_scaling(self._scale_ratio) trans.set_move(x1, y1) self.transform_template(current, trans) # remove obsolete info from template if type == "atom1": current.delete_items([current.t_atom], redraw=0, delete_single_atom=0) elif type == "atom2": current.t_atom.x = x1 current.t_atom.y = y1 current.t_atom = None current.t_bond_first = None current.t_bond_second = None # return ready template return current
def expand( self): """expands the group and returns list of atoms that new drawing afterwords""" if self.group_type == "builtin": names = Store.gm.get_template_names() if self.symbol in names: a2 = self.neighbors[0] x1, y1 = a2.get_xy() x2, y2 = self.get_xy() self.group_graph = Store.gm.get_transformed_template( names.index( self.symbol), (x1,y1,x2,y2), type='atom1') replacement = self.group_graph.next_to_t_atom else: print "unknown group %s" % a.symbol return None elif self.group_type == "chain": self.group_graph = self.molecule.create_graph() p = PT.formula_dict( self.symbol) n = p['C'] last = None for i in range( n): v = self.group_graph.add_vertex() v.x, v.y = None, None if last: self.group_graph.add_edge( last, v) last = v replacement = self.group_graph.vertices[0] replacement.x = self.x replacement.y = self.y elif self.group_type == "implicit": if not self.group_graph: self.set_name( self.symbol, occupied_valency=self.occupied_valency) for v in self.group_graph.vertices: v.x, v.y = None, None v.show = v.symbol != 'C' assert self.connecting_atom != None replacement = self.connecting_atom replacement.x = self.x replacement.y = self.y self.molecule.eat_molecule( self.group_graph) self.molecule.move_bonds_between_atoms( self, replacement) self.molecule.delete_vertex( self) if self.occupied_valency: oasa.coords_generator.calculate_coords( self.molecule, bond_length=-1) else: # if the group is the only vertex of the molecule we must set the bond_length explicitly # and the move the whole molecule replacement.x = None replacement.y = None x, y = self.x, self.y oasa.coords_generator.calculate_coords( self.molecule, bond_length=Screen.any_to_px( self.paper.standard.bond_length)) dx = x - replacement.x dy = y - replacement.y [a.move( dx, dy) for a in self.group_graph.vertices] return self.group_graph.vertices
def oasa_mol_to_bkchem_mol(mol, paper): m = molecule.molecule(paper) if None in reduce(operator.add, [[a.x, a.y] for a in mol.atoms], []): calc_position = 0 else: calc_position = 1 minx = None maxx = None miny = None maxy = None # atoms for a in mol.vertices: a2 = oasa_atom_to_bkchem_atom(a, paper, m) m.insert_atom(a2) if calc_position: # data for rescaling if not maxx or a2.x > maxx: maxx = a2.x if not minx or a2.x < minx: minx = a2.x if not miny or a2.y < miny: miny = a2.y if not maxy or a2.y > maxy: maxy = a2.y # bonds bond_lengths = [] for b in mol.edges: b2 = oasa_bond_to_bkchem_bond(b, paper) aa1, aa2 = b.vertices atom1 = m.atoms[mol.vertices.index(aa1)] atom2 = m.atoms[mol.vertices.index(aa2)] m.add_edge(atom1, atom2, b2) b2.molecule = m if calc_position: bond_lengths.append( math.sqrt((b2.atom1.x - b2.atom2.x)**2 + (b2.atom1.y - b2.atom2.y)**2)) # rescale if calc_position: bl = sum(bond_lengths) / len(bond_lengths) scale = Screen.any_to_px(paper.standard.bond_length) / bl movex = (maxx + minx) / 2 movey = (maxy + miny) / 2 trans = transform3d.transform3d() trans.set_move(-movex, -movey, 0) trans.set_scaling(scale) trans.set_move(320, 240, 0) for a in m.atoms: a.x, a.y, a.z = trans.transform_xyz(a.x, a.y, a.z) return m
def oasa_mol_to_bkchem_mol( mol, paper): m = molecule.molecule( paper) if None in reduce( operator.add, [[a.x, a.y] for a in mol.atoms], []): calc_position = 0 else: calc_position = 1 minx = None maxx = None miny = None maxy = None # atoms for a in mol.vertices: a2 = oasa_atom_to_bkchem_atom( a, paper, m) m.insert_atom( a2) if calc_position: # data for rescaling if not maxx or a2.x > maxx: maxx = a2.x if not minx or a2.x < minx: minx = a2.x if not miny or a2.y < miny: miny = a2.y if not maxy or a2.y > maxy: maxy = a2.y # bonds bond_lengths = [] for b in mol.edges: b2 = oasa_bond_to_bkchem_bond( b, paper) aa1, aa2 = b.vertices atom1 = m.atoms[ mol.vertices.index( aa1)] atom2 = m.atoms[ mol.vertices.index( aa2)] m.add_edge( atom1, atom2, b2) b2.molecule = m if calc_position: bond_lengths.append( math.sqrt( (b2.atom1.x-b2.atom2.x)**2 + (b2.atom1.y-b2.atom2.y)**2)) # rescale if calc_position: bl = sum( bond_lengths) / len( bond_lengths) scale = Screen.any_to_px( paper.standard.bond_length) / bl movex = (maxx+minx)/2 movey = (maxy+miny)/2 trans = transform3d.transform3d() trans.set_move( -movex, -movey, 0) trans.set_scaling( scale) trans.set_move( 320, 240, 0) for a in m.atoms: a.x, a.y, a.z = trans.transform_xyz( a.x, a.y, a.z) return m
def _set_x(self, x): self._x = Screen.any_to_px(x)
def done(self, button): """called on dialog exit""" self.dialog.deactivate() if button != _('OK'): pass else: #print self.marks.get() # apply changes for o in self.items: change = 0 # ATOM if o.object_type == 'atom': a = self.atom_show.index(Pmw.SELECT) if a != 2: o.show = a change = 1 # positionning a = self.atom_pos.index(Pmw.SELECT) if a != 2: o.pos = ('center-first', 'center-last')[a] change = 1 if self.atom_charge.get(): a = int(self.atom_charge.get()) if hasattr(o, 'charge') and o.charge != a: o.charge = a change = 1 # hydrogens a = int(self.atom_show_h.index(Pmw.SELECT)) if a != 2: o.show_hydrogens = a change = 1 # font is in common now # BOND elif o.object_type == 'bond': # width is in common now # bond_width d = Screen.any_to_px(self.bond_dist.getvalue()) if d: if d != abs(o.bond_width): o.bond_width = d * misc.signum(o.bond_width) change = 1 # wedge_width d = Screen.any_to_px(self.wedge_width.getvalue()) if d: if d != o.wedge_width: o.wedge_width = d change = 1 # ratio ratio = self.double_length_ratio.getvalue() if ratio: ratio = float(self.double_length_ratio.getvalue()) if ratio != o.double_length_ratio: o.double_length_ratio = ratio change = 1 # ARROW - most is in common now elif o.object_type == 'arrow': if self.arrow_start_changed: o.set_pins(start=self.arrow_start.get()) change = 1 if self.arrow_end_changed: o.set_pins(end=self.arrow_end.get()) change = 1 if self.spline_changed: o.spline = self.spline.get() change = 1 # TEXT - all is in common now # PLUS - all is in common now # VECTOR - all is in common now # COMMON PROPERTIES # LINE COLOR if hasattr(o, 'line_color') and self.line_color.color: if self.line_color.color != o.line_color: o.line_color = self.line_color.color change = 1 # AREA COLOR if hasattr(o, 'area_color') and self.area_color.color: if self.area_color.color != o.area_color: o.area_color = self.area_color.color change = 1 # LINE WIDTH if hasattr(o, 'line_width'): w = Screen.any_to_px(self.line_width.getvalue()) if w: if w != o.line_width: o.line_width = w change = 1 # FONT if hasattr(o, 'font_family'): if self.font_size.get(): a = int(self.font_size.get()) o.font_size = a change = 1 if self.font_family.getcurselection( ) and self.font_family.getcurselection( )[0] != self.used_family: a = self.font_family.getcurselection()[0] o.font_family = a change = 1 # APPLY THE CHANGES if change: o.redraw() self.changes_made = 1 self.cleanup()
def y(self, y): self._y = Screen.any_to_px( y)
def y(self, y): self._y = Screen.any_to_px(y)
def get_transformed_template(self, n, coords, type='empty', paper=None): """type is type of connection - 'bond', 'atom1'(for single atom), 'atom2'(for atom with more than 1 bond), 'empty'""" pap = paper or Store.app.paper pap.onread_id_sandbox_activate() # must be here to mangle the ids current = molecule(pap, package=self.templates[n]) pap.onread_id_sandbox_finish(apply_to=[current]) # id mangling current.name = '' self._scale_ratio = 1 trans = transform() # type empty - just draws the template - no conection if type == 'empty': xt1, yt1 = current.t_atom.get_xy() xt2, yt2 = current.next_to_t_atom.get_xy() x1, y1 = coords bond_length = Screen.any_to_px( Store.app.paper.standard.bond_length) current.delete_items([current.t_atom], redraw=0, delete_single_atom=0) trans.set_move(-xt2, -yt2) trans.set_scaling(bond_length / math.sqrt((xt1 - xt2)**2 + (yt1 - yt2)**2)) trans.set_move(x1, y1) #type atom elif type == 'atom1' or type == 'atom2': xt1, yt1 = current.t_atom.get_xy() xt2, yt2 = current.next_to_t_atom.get_xy() x1, y1, x2, y2 = coords trans.set_move(-xt2, -yt2) trans.set_scaling( math.sqrt((x1 - x2)**2 + (y1 - y2)**2) / math.sqrt((xt1 - xt2)**2 + (yt1 - yt2)**2)) trans.set_rotation( math.atan2(xt1 - xt2, yt1 - yt2) - math.atan2(x1 - x2, y1 - y2)) trans.set_move(x2, y2) #type bond elif type == 'bond': if not (current.t_bond_first and current.t_bond_second): warn( "this template is not capable to be added to bond - sorry." ) return None current.delete_items([current.t_atom], redraw=0, delete_single_atom=0) xt1, yt1 = current.t_bond_first.get_xy() xt2, yt2 = current.t_bond_second.get_xy() x1, y1, x2, y2 = coords self._scale_ratio = math.sqrt( (x1 - x2)**2 + (y1 - y2)**2) / math.sqrt( (xt1 - xt2)**2 + (yt1 - yt2)** 2) # further needed for bond.bond_width transformation trans.set_move(-xt1, -yt1) trans.set_rotation( math.atan2(xt1 - xt2, yt1 - yt2) - math.atan2(x1 - x2, y1 - y2)) trans.set_scaling(self._scale_ratio) trans.set_move(x1, y1) self.transform_template(current, trans) #remove obsolete info from template if type == 'atom1': current.delete_items([current.t_atom], redraw=0, delete_single_atom=0) elif type == 'atom2': current.t_atom.x = x1 current.t_atom.y = y1 current.t_atom = None current.t_bond_first = None current.t_bond_second = None #return ready template return current
def _set_x( self, x): self._x = Screen.any_to_px( x)
def _set_y(self, y): self._y = Screen.any_to_px(y)
def done( self, button): """called on dialog exit""" self.dialog.deactivate() if button != _('OK'): pass else: #print(self.marks.get()) # apply changes for o in self.items: change = 0 # ATOM if o.object_type == 'atom': a = self.atom_show.index( Pmw.SELECT) if a != 2: o.show = a change = 1 # positionning a = self.atom_pos.index( Pmw.SELECT) if a != 2: o.pos = ('center-first', 'center-last')[ a] change = 1 if self.atom_charge.get(): a = int( self.atom_charge.get()) if hasattr( o, 'charge') and o.charge != a: o.charge = a change = 1 # hydrogens a = int( self.atom_show_h.index( Pmw.SELECT)) if a != 2: o.show_hydrogens = a change = 1 # font is in common now # BOND elif o.object_type == 'bond': # width is in common now # bond_width d = Screen.any_to_px( self.bond_dist.getvalue()) if d: if d != abs( o.bond_width): o.bond_width = d * misc.signum( o.bond_width) change = 1 # wedge_width d = Screen.any_to_px( self.wedge_width.getvalue()) if d: if d != o.wedge_width: o.wedge_width = d change = 1 # ratio ratio = self.double_length_ratio.getvalue() if ratio: ratio = float( self.double_length_ratio.getvalue()) if ratio != o.double_length_ratio: o.double_length_ratio = ratio change = 1 # ARROW - most is in common now elif o.object_type == 'arrow': if self.arrow_start_changed: o.set_pins( start = self.arrow_start.get()) change = 1 if self.arrow_end_changed: o.set_pins( end = self.arrow_end.get()) change = 1 if self.spline_changed: o.spline = self.spline.get() change = 1 # TEXT - all is in common now # PLUS - all is in common now # VECTOR - all is in common now # COMMON PROPERTIES # LINE COLOR if hasattr( o, 'line_color') and self.line_color.color: if self.line_color.color != o.line_color: o.line_color = self.line_color.color change = 1 # AREA COLOR if hasattr( o, 'area_color') and self.area_color.color: if self.area_color.color != o.area_color: o.area_color = self.area_color.color change = 1 # LINE WIDTH if hasattr( o, 'line_width'): w = Screen.any_to_px( self.line_width.getvalue()) if w: if w != o.line_width: o.line_width = w change = 1 # FONT if hasattr( o, 'font_family'): if self.font_size.get(): a = int( self.font_size.get()) o.font_size = a change = 1 if self.font_family.getcurselection() and self.font_family.getcurselection()[0] != self.used_family: a = self.font_family.getcurselection()[0] o.font_family = a change = 1 # APPLY THE CHANGES if change: o.redraw() self.changes_made = 1 self.cleanup()
def expand(self): """expands the group and returns list of atoms that new drawing afterwords""" if self.group_type == "builtin": names = Store.gm.get_template_names() if self.symbol in names: a2 = self.neighbors[0] x1, y1 = a2.get_xy() x2, y2 = self.get_xy() self.group_graph = Store.gm.get_transformed_template( names.index(self.symbol), (x1, y1, x2, y2), type='atom1') replacement = self.group_graph.next_to_t_atom else: print("unknown group %s" % a.symbol) return None elif self.group_type == "chain": self.group_graph = self.molecule.create_graph() p = PT.formula_dict(self.symbol) n = p['C'] last = None for i in range(n): v = self.group_graph.add_vertex() v.x, v.y = None, None if last: self.group_graph.add_edge(last, v) last = v replacement = self.group_graph.vertices[0] replacement.x = self.x replacement.y = self.y elif self.group_type == "implicit": if not self.group_graph: self.set_name(self.symbol, occupied_valency=self.occupied_valency) for v in self.group_graph.vertices: v.x, v.y = None, None v.show = v.symbol != 'C' assert self.connecting_atom is not None replacement = self.connecting_atom replacement.x = self.x replacement.y = self.y self.molecule.eat_molecule(self.group_graph) self.molecule.move_bonds_between_atoms(self, replacement) self.molecule.delete_vertex(self) if self.occupied_valency: oasa.coords_generator.calculate_coords(self.molecule, bond_length=-1) else: # if the group is the only vertex of the molecule we must set the bond_length explicitly # and the move the whole molecule replacement.x = None replacement.y = None x, y = self.x, self.y oasa.coords_generator.calculate_coords( self.molecule, bond_length=Screen.any_to_px(self.paper.standard.bond_length)) dx = x - replacement.x dy = y - replacement.y [a.move(dx, dy) for a in self.group_graph.vertices] return self.group_graph.vertices
def _set_y( self, y): self._y = Screen.any_to_px( y)
def x( self, x): self._x = Screen.any_to_px( x)
def read_standard_values( self, standard, old_standard=None): meta_enabled.read_standard_values( self, standard, old_standard=old_standard) if not old_standard or (standard.line_width != old_standard.line_width): self.line_width = Screen.any_to_px( standard.line_width)
def x(self, x): self._x = Screen.any_to_px(x)