From: toshinagata1964 Date: Sat, 16 Nov 2013 01:30:04 +0000 (+0000) Subject: Bond/Angle with Sigma dialog is overhauled (now working). X-Git-Tag: v1.0.2~218 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f601934b23d496ec84c49fc9ec0ea2355d2b93b2;p=molby%2FMolby.git Bond/Angle with Sigma dialog is overhauled (now working). git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@420 a2be9bc6-48de-4e38-9406-05402d4bc13c --- diff --git a/Documents/src/molby_rb/AtomRef.html b/Documents/src/molby_rb/AtomRef.html index 48f1677..c24924f 100644 --- a/Documents/src/molby_rb/AtomRef.html +++ b/Documents/src/molby_rb/AtomRef.html @@ -416,6 +416,20 @@ Get/set the flag whether to exclude this atom from MM/MD calculation. The atom i +
+ +
+ +molecule → Molecule
+
+
+
+

+Get the parent molecule object. +

+
+
+
diff --git a/Documents/src/molby_rb/Molecule.html b/Documents/src/molby_rb/Molecule.html index d571290..f1b7b30 100644 --- a/Documents/src/molby_rb/Molecule.html +++ b/Documents/src/molby_rb/Molecule.html @@ -574,6 +574,20 @@ representing the array of atoms.
+
+ +
+ bond_exist?(idx1, idx2) → bool
+
+
+
+

+Returns true if bond exists between atoms idx1 and idx2, otherwise returns false. +Imaginary bonds between a pi-anchor and member atoms are not considered. +

+
+
+
diff --git a/MolLib/Ruby_bind/ruby_bind.c b/MolLib/Ruby_bind/ruby_bind.c index 84936f1..ed71a68 100644 --- a/MolLib/Ruby_bind/ruby_bind.c +++ b/MolLib/Ruby_bind/ruby_bind.c @@ -6720,6 +6720,34 @@ s_Molecule_GetBondOrder(VALUE self, VALUE idxval) /* * call-seq: + * bond_exist?(idx1, idx2) -> bool + * + * Returns true if bond exists between atoms idx1 and idx2, otherwise returns false. + * Imaginary bonds between a pi-anchor and member atoms are not considered. + */ +static VALUE +s_Molecule_BondExist(VALUE self, VALUE ival1, VALUE ival2) +{ + Molecule *mol; + Int idx1, idx2, i; + Atom *ap; + Int *cp; + Data_Get_Struct(self, Molecule, mol); + idx1 = NUM2INT(rb_Integer(ival1)); + idx2 = NUM2INT(rb_Integer(ival2)); + if (idx1 < 0 || idx1 >= mol->natoms || idx2 < 0 || idx2 >= mol->natoms) + rb_raise(rb_eMolbyError, "Atom index (%d or %d) out of range", idx1, idx2); + ap = ATOM_AT_INDEX(mol->atoms, idx1); + cp = AtomConnectData(&ap->connect); + for (i = 0; i < ap->connect.count; i++) { + if (cp[i] == idx2) + return Qtrue; + } + return Qfalse; +} + +/* + * call-seq: * add_angle(n1, n2, n3) -> Molecule * * Add angle n1-n2-n3. Returns self. Usually, angles are automatically added @@ -10416,6 +10444,7 @@ Init_Molby(void) rb_define_alias(rb_cMolecule, "assign_bond_orders", "assign_bond_order"); rb_define_method(rb_cMolecule, "get_bond_order", s_Molecule_GetBondOrder, 1); rb_define_alias(rb_cMolecule, "get_bond_orders", "get_bond_order"); + rb_define_method(rb_cMolecule, "bond_exist?", s_Molecule_BondExist, 2); rb_define_method(rb_cMolecule, "add_angle", s_Molecule_AddAngle, 3); rb_define_method(rb_cMolecule, "remove_angle", s_Molecule_RemoveAngle, 3); rb_define_method(rb_cMolecule, "add_dihedral", s_Molecule_AddDihedral, 4); diff --git a/Scripts/crystal.rb b/Scripts/crystal.rb index a184f24..2f39a17 100755 --- a/Scripts/crystal.rb +++ b/Scripts/crystal.rb @@ -703,6 +703,9 @@ def bond_angle_with_sigma(*args) # Unit cell parameter cell = self.cell + if cell.length == 6 + cell.push(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) # No sigma information + end # $a, $b, $c, $alpha, $beta, $gamma, $sig_a, $sig_b, $sig_c, $sig_alpha, $sig_beta, $sig_gamma = self.cell cos_a = cos(cell[3] * PI / 180.0) cos_b = cos(cell[4] * PI / 180.0) @@ -826,26 +829,6 @@ def bond_angle_with_sigma(*args) 6.times { |n| sig += (p[4 + n] * cell[6 + n]) ** 2 } - # Test - if nil - ncell = cell.dup - d0 = calc_bond(i, j) - dd = [0, 0, 0, 0, 0, 0] - 6.times { |n| - ncell[n] += 0.0001 - set_cell(ncell, true) - amend_by_symmetry(p[10]) - d1 = calc_bond(i, j) - dd[n] = (d1 - d0) / 0.0001 - ncell[n] = cell[n] - } - set_cell(ncell, true) - amend_by_symmetry(p[10]) - printf " dr/d{a,b,c} cal %10.5g %10.5g %10.5g\n", p[4], p[5], p[6] - printf " dr/d{a,b,c} est %10.5g %10.5g %10.5g\n", dd[0], dd[1], dd[2] - printf " dr/d{alpha,beta,gamma} cal %10.5g %10.5g %10.5g\n", p[7], p[8], p[9] - printf " dr/d{alpha,beta,gamma} est %10.5g %10.5g %10.5g\n", dd[3], dd[4], dd[5] - end sig = sqrt(sig) results.push([[i, j], notate_with_sigma.call(p[0], sig), symcode[i], symcode[j], nil]) } @@ -861,9 +844,6 @@ def bond_angle_with_sigma(*args) t123 = acos_safe((p0[0] ** 2 + p1[0] ** 2 - p2[0] ** 2) / (2 * p0[0] * p1[0])) t124 = acos_safe((p0[0] ** 2 + p3[0] ** 2 - p2[0] ** 2 * 0.25) / (2 * p0[0] * p3[0])) t324 = acos_safe((p1[0] ** 2 + p3[0] ** 2 - p2[0] ** 2 * 0.25) / (2 * p1[0] * p3[0])) - if nil - printf "t123 = %.2f t124+t324 = %.2f t124 = %.2f t324 = %.2f\n", t123*180/PI, (t124+t324)*180/PI, t124*180/PI, t324*180/PI - end dtdr12 = -(p0[0] ** 2 - p3[0] ** 2 + p2[0] ** 2 * 0.25) / (2 * p3[0] * (p0[0] ** 2) * sin(t124)) dtdr23 = -(p1[0] ** 2 - p3[0] ** 2 + p2[0] ** 2 * 0.25) / (2 * p3[0] * (p1[0] ** 2) * sin(t324)) dtdr13 = p2[0] / (sin(t124) * 4 * p0[0] * p3[0]) + p2[0] / (sin(t324) * 4 * p1[0] * p3[0]) @@ -878,25 +858,6 @@ def bond_angle_with_sigma(*args) c += diff_by_rn.call(p1, n, false) * (dtdr23 * 180.0 / PI) c += diff_by_rn.call(p2, n, false) * (dtdr13 * 180.0 / PI) c += diff_by_rn.call(p3, n, true) * (dtdr24 * 180.0 / PI) - # Test - if nil - apn = atoms[n] - r = apn.fract_r - t0 = calc_angle(i, j, k) - apn.fract_r = r + Vector3D[0.00001, 0, 0] - amend_by_symmetry(pp) - t1 = calc_angle(i, j, k) - apn.fract_r = r + Vector3D[0, 0.00001, 0] - amend_by_symmetry(pp) - t2 = calc_angle(i, j, k) - apn.fract_r = r + Vector3D[0, 0, 0.00001] - amend_by_symmetry(pp) - t3 = calc_angle(i, j, k) - apn.fract_r = r - amend_by_symmetry(pp) - printf " dt/dv[%d] cal %10.5g %10.5g %10.5g\n", n, c[0], c[1], c[2] - printf " dt/dv[%d] est %10.5g %10.5g %10.5g\n", n, (t1 - t0) / 0.00001, (t2 - t0) / 0.00001, (t3 - t0) / 0.00001 - end sig += c[0] * c[0] * s[0] * s[0] + c[1] * c[1] * s[1] * s[1] + c[2] * c[2] * s[2] * s[2] } dd = dtdr12 * p0[4] + dtdr23 * p1[4] + dtdr13 * p2[4] + dtdr24 * p3[4] @@ -919,63 +880,79 @@ end def cmd_bond_angle_with_sigma mol = self - Dialog.new("Bond & Angle with Sigma:" + self.name, "Close", nil) { + Dialog.new("Bond & Angle with Sigma:" + self.name, nil, nil) { values = [] clicked = [] sel = mol.selection - on_get_value = proc { |it, row, col| - val = values[row][col] - if col == 0 - val = val.collect { |i| ap = mol.atoms[i]; "#{ap.res_seq}:#{ap.name}" }.join("-") - elsif col >= 2 && col <= 4 - val ||= "." - end - val + on_get_value = proc { |it, row, col| values[row][col + 2] } + atom_name = proc { |ap| + (ap.molecule.nresidues >= 2 ? "#{ap.res_seq}:" : "") + ap.name } layout(1, item(:table, :width=>480, :height=>300, :tag=>"table", - :columns=>["Bond/Angle", "value(sigma)", "symop1", "symop2", "symop3"], + :columns=>[["Bond/Angle", 140], "value(sigma)", "symop1", "symop2", "symop3"], :on_count=> proc { values.count }, - :on_get_value=> on_get_value) + :on_get_value=> on_get_value), + layout(2, + item(:view, :width=>480, :height=>1), -1, + item(:button, :title=>"Dump to Console", :tag=>"dump", + :action=>proc { print "\n"; values.each { |val| print val[2..-1].join(" ") + "\n" } }, + :enabled=>false), + [item(:button, :title=>"Close", :action=>proc { hide }), {:align=>:right}]) ) on_document_modified = proc { newsel = mol.selection - puts "newsel = #{newsel}" + val1 = val2 = nil if sel != newsel - n0 = sel.count n1 = newsel.count - if n1 == 1 # New atom is clicked + if n1 == 0 + # Clear selection + clicked.clear + elsif n1 == 1 && !clicked.include?(newsel[0]) + # New atom + clicked.clear clicked[0] = newsel[0] - clicked[1..-1] = [] - if n0 == 1 - values[-1][0] = [clicked[0]] - else - values.push([[clicked[0]], "---", nil, nil, nil]) - end - elsif n1 == 2 # Bond - puts "new bond" - if newsel.include?(clicked[0]) - if newsel[0] == clicked[0] - clicked[1] = newsel[1] - else - clicked[1] = newsel[0] - end + val1 = [[clicked[0]], "---", "", "", ""] + elsif n1 == 2 && clicked.length == 1 + # New bond + if newsel[0] == clicked[0] + clicked[1] = newsel[1] + elsif newsel[1] == clicked[0] + clicked[1] = newsel[0] else clicked[0] = newsel[0] clicked[1] = newsel[1] end - clicked[2..-1] = [] - puts "clicked = #{clicked.inspect}" - val = mol.bond_angle_with_sigma(clicked) - puts "val = #{val.inspect}" - if n0 == 1 - values[-1] = val[0] - else - values.push(val[0]) - end + val1 = mol.bond_angle_with_sigma(clicked)[0] + elsif n1 == 3 && clicked.length == 2 && newsel.include?(clicked[0]) && newsel.include?(clicked[1]) + # New angle + clicked[2] = (newsel - clicked)[0] + val1 = mol.bond_angle_with_sigma(clicked[1..2])[0] + val2 = mol.bond_angle_with_sigma(clicked)[0] + else + return + end + [val1, val2].each { |val| + next unless val + label = "" + n = val[0].length + n.times { |i| + label += atom_name.call(mol.atoms[val[0][i]]) + if val[0][i + 1] + label += (mol.bond_exist?(val[0][i], val[0][i + 1]) ? "-" : "...") + end + } + val[1, 0] = label + val.unshift(n) # val = [count, indices, label, value(sigma), symop1, symop2, symop3] + } + if values[-1] && values[-1][0] == 1 + values.pop end + values.push(val1) if val1 + values.push(val2) if val2 sel = newsel item_with_tag("table")[:refresh] = true + item_with_tag("dump")[:enabled] = (values.length > 0) end } listen(mol, "documentModified", on_document_modified)