• R/O
  • HTTP
  • SSH
  • HTTPS

Molby: コミット

Molecular Modeling Software


コミットメタ情報

リビジョンecd68891964a02f236a3bd0715977f6cb20a9849 (tree)
日時2016-04-28 00:42:31
作者toshinagata1964 <toshinagata1964@a2be...>
コミッターtoshinagata1964

ログメッセージ

A CIF file with multiple structures now can be processed (multiple documents are opened in this case)

git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@594 a2be9bc6-48de-4e38-9406-05402d4bc13c

変更サマリ

差分

--- a/MolLib/Ruby_bind/ruby_bind.c
+++ b/MolLib/Ruby_bind/ruby_bind.c
@@ -5453,6 +5453,24 @@ s_Molecule_SetErrorMessage(VALUE klass, VALUE sval)
54535453 return sval;
54545454 }
54555455
5456+/*
5457+ * call-seq:
5458+ * set_molecule(Molecule)
5459+ *
5460+ * Duplicate the given molecule and set to self. The present molecule must be empty.
5461+ * This method is exclusively used for associating a new document with an existing molecule.
5462+ */
5463+static VALUE
5464+s_Molecule_SetMolecule(VALUE self, VALUE mval)
5465+{
5466+ Molecule *mp1, *mp2;
5467+ Data_Get_Struct(self, Molecule, mp1);
5468+ mp2 = MoleculeFromValue(mval);
5469+ MoleculeInitWithMolecule(mp1, mp2);
5470+ MoleculeCallback_notifyModification(mp1, 1);
5471+ return self;
5472+}
5473+
54565474 #pragma mark ------ Name attributes ------
54575475
54585476 /*
@@ -11462,6 +11480,7 @@ Init_Molby(void)
1146211480 rb_define_method(rb_cMolecule, "savedcd", s_Molecule_Savedcd, 1);
1146311481 rb_define_method(rb_cMolecule, "molload", s_Molecule_Load, -1);
1146411482 rb_define_method(rb_cMolecule, "molsave", s_Molecule_Save, -1);
11483+ rb_define_method(rb_cMolecule, "set_molecule", s_Molecule_SetMolecule, 1);
1146511484 rb_define_singleton_method(rb_cMolecule, "open", s_Molecule_Open, -1);
1146611485 rb_define_singleton_method(rb_cMolecule, "error_message", s_Molecule_ErrorMessage, 0);
1146711486 rb_define_singleton_method(rb_cMolecule, "set_error_message", s_Molecule_SetErrorMessage, 1);
--- a/Scripts/loadsave.rb
+++ b/Scripts/loadsave.rb
@@ -761,6 +761,7 @@ end_of_header
761761 alias :savegjf :savecom
762762
763763 def loadcif(filename)
764+ mol = self
764765 def getciftoken(fp)
765766 while @tokens.length == 0
766767 line = fp.gets
@@ -820,302 +821,329 @@ end_of_header
820821 end
821822 sym
822823 end
823- def find_atom_by_name(name)
824+ def find_atom_by_name(mol, name)
824825 name = name.delete(" ()")
825- ap = self.atoms[name] rescue ap = nil
826+ ap = mol.atoms[name] rescue ap = nil
826827 return ap
827828 end
828- warn_message = ""
829- verbose = nil
830- bond_defined = false
831- @tokens = []
832- special_positions = []
833- self.remove(All)
829+ selfname = self.name
834830 fp = open(filename, "rb")
835- cell = []
836- cell_trans = cell_trans_inv = Transform.identity
837- token = getciftoken(fp)
838- pardigits_re = /\(\d+\)/
839- calculated_atoms = []
840- while token != nil
841- if token =~ /^_cell/
842- val = getciftoken(fp)
843- if token == "_cell_length_a"
844- cell[0], cell[6] = float_strip_rms(val)
845- elsif token == "_cell_length_b"
846- cell[1], cell[7] = float_strip_rms(val)
847- elsif token == "_cell_length_c"
848- cell[2], cell[8] = float_strip_rms(val)
849- elsif token == "_cell_angle_alpha"
850- cell[3], cell[9] = float_strip_rms(val)
851- elsif token == "_cell_angle_beta"
852- cell[4], cell[10] = float_strip_rms(val)
853- elsif token == "_cell_angle_gamma"
854- cell[5], cell[11] = float_strip_rms(val)
855- end
856- if cell.length == 12 && cell.all?
857- self.cell = cell
858- puts "Unit cell is set to #{cell.inspect}." if verbose
859- cell = []
860- cell_trans = self.cell_transform
861- cell_trans_inv = cell_trans.inverse
862- end
863- token = getciftoken(fp)
864- next
865- elsif token.casecmp("#loop_") == 0
866- labels = []
867- while (token = getciftoken(fp)) && token[0] == ?_
868- labels.push(token)
869- end
870- if labels[0] =~ /symmetry_equiv_pos|atom_site_label|atom_site_aniso_label|geom_bond/
871- hlabel = Hash.new(-10000000)
872- labels.each_with_index { |lb, i|
873- hlabel[lb] = i
874- }
875- data = []
876- n = labels.length
877- a = []
878- while 1
879- break if token == nil || token[0] == ?_ || token[0] == ?#
880- a.push(token)
881- if a.length == n
882- data.push(a)
883- a = []
884- end
831+ data_identifier = nil
832+ @tokens = []
833+ count_up = 1
834+ while true
835+ warn_message = ""
836+ verbose = nil
837+ bond_defined = false
838+ special_positions = []
839+ mol.remove(All)
840+ cell = []
841+ cell_trans = cell_trans_inv = Transform.identity
842+ token = getciftoken(fp)
843+ pardigits_re = /\(\d+\)/
844+ calculated_atoms = []
845+ while token != nil
846+ if token =~ /^\#data_/i
847+ if token.casecmp("#data_global") == 0
848+ token = getciftoken(fp)
849+ next
850+ elsif data_identifier == nil
851+ # Continue processing of this molecule
852+ data_identifier = token
885853 token = getciftoken(fp)
854+ next
855+ else
856+ # Description of another molecule begins here
857+ data_identifier = token
858+ break
859+ end
860+ elsif token =~ /^_cell/
861+ val = getciftoken(fp)
862+ if token == "_cell_length_a"
863+ cell[0], cell[6] = float_strip_rms(val)
864+ elsif token == "_cell_length_b"
865+ cell[1], cell[7] = float_strip_rms(val)
866+ elsif token == "_cell_length_c"
867+ cell[2], cell[8] = float_strip_rms(val)
868+ elsif token == "_cell_angle_alpha"
869+ cell[3], cell[9] = float_strip_rms(val)
870+ elsif token == "_cell_angle_beta"
871+ cell[4], cell[10] = float_strip_rms(val)
872+ elsif token == "_cell_angle_gamma"
873+ cell[5], cell[11] = float_strip_rms(val)
874+ end
875+ if cell.length == 12 && cell.all?
876+ mol.cell = cell
877+ puts "Unit cell is set to #{cell.inspect}." if verbose
878+ cell = []
879+ cell_trans = self.cell_transform
880+ cell_trans_inv = cell_trans.inverse
881+ end
882+ token = getciftoken(fp)
883+ next
884+ elsif token.casecmp("#loop_") == 0
885+ labels = []
886+ while (token = getciftoken(fp)) && token[0] == ?_
887+ labels.push(token)
886888 end
887- if labels[0] =~ /^_symmetry_equiv_pos/
888- data.each { |d|
889- symstr = d[hlabel["_symmetry_equiv_pos_as_xyz"]]
890- symstr.delete("\"\'")
891- exps = symstr.split(/,/)
892- sym = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
893- exps.each_with_index { |s, i|
894- terms = s.scan(/([-+]?)(([.0-9]+)(\/([0-9]+))?([xXyYzZ])?|([xXyYzZ]))/)
895- terms.each { |a|
896- # a[0]: sign, a[2]: numerator, a[4]: denometer
897- if a[4] != nil
898- # The number part is a[2]/a[4]
899- num = Float(a[2])/Float(a[4])
900- elsif a[2] != nil
901- # The number part is either integer or a floating point
902- num = Float(a[2])
889+ if labels[0] =~ /symmetry_equiv_pos|atom_site_label|atom_site_aniso_label|geom_bond/
890+ hlabel = Hash.new(-10000000)
891+ labels.each_with_index { |lb, i|
892+ hlabel[lb] = i
893+ }
894+ data = []
895+ n = labels.length
896+ a = []
897+ while true
898+ break if token == nil || token[0] == ?_ || token[0] == ?#
899+ a.push(token)
900+ if a.length == n
901+ data.push(a)
902+ a = []
903+ end
904+ token = getciftoken(fp)
905+ end
906+ if labels[0] =~ /^_symmetry_equiv_pos/
907+ data.each { |d|
908+ symstr = d[hlabel["_symmetry_equiv_pos_as_xyz"]]
909+ symstr.delete("\"\'")
910+ exps = symstr.split(/,/)
911+ sym = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
912+ exps.each_with_index { |s, i|
913+ terms = s.scan(/([-+]?)(([.0-9]+)(\/([0-9]+))?([xXyYzZ])?|([xXyYzZ]))/)
914+ terms.each { |a|
915+ # a[0]: sign, a[2]: numerator, a[4]: denometer
916+ if a[4] != nil
917+ # The number part is a[2]/a[4]
918+ num = Float(a[2])/Float(a[4])
919+ elsif a[2] != nil
920+ # The number part is either integer or a floating point
921+ num = Float(a[2])
922+ else
923+ num = 1.0
924+ end
925+ num = -num if a[0][0] == ?-
926+ xyz = (a[5] || a[6])
927+ if xyz == "x" || xyz == "X"
928+ sym[i] = num
929+ elsif xyz == "y" || xyz == "Y"
930+ sym[i + 3] = num
931+ elsif xyz == "z" || xyz == "Z"
932+ sym[i + 6] = num
933+ else
934+ sym[9 + i] = num
935+ end
936+ }
937+ }
938+ puts "symmetry operation #{sym.inspect}" if verbose
939+ mol.add_symmetry(Transform.new(sym))
940+ }
941+ puts "#{mol.nsymmetries} symmetry operations are added" if verbose
942+ elsif labels[0] =~ /^_atom_site_label/
943+ # Create atoms
944+ data.each { |d|
945+ name = d[hlabel["_atom_site_label"]]
946+ elem = d[hlabel["_atom_site_type_symbol"]]
947+ fx = d[hlabel["_atom_site_fract_x"]]
948+ fy = d[hlabel["_atom_site_fract_y"]]
949+ fz = d[hlabel["_atom_site_fract_z"]]
950+ uiso = d[hlabel["_atom_site_U_iso_or_equiv"]]
951+ biso = d[hlabel["_atom_site_B_iso_or_equiv"]]
952+ occ = d[hlabel["_atom_site_occupancy"]]
953+ calc = d[hlabel["_atom_site_calc_flag"]]
954+ name = name.delete(" ()")
955+ if elem == nil || elem == ""
956+ if name =~ /[A-Za-z]{1,2}/
957+ elem = $&.capitalize
903958 else
904- num = 1.0
959+ elem = "Du"
905960 end
906- num = -num if a[0][0] == ?-
907- xyz = (a[5] || a[6])
908- if xyz == "x" || xyz == "X"
909- sym[i] = num
910- elsif xyz == "y" || xyz == "Y"
911- sym[i + 3] = num
912- elsif xyz == "z" || xyz == "Z"
913- sym[i + 6] = num
914- else
915- sym[9 + i] = num
961+ end
962+ ap = mol.add_atom(name, elem, elem)
963+ ap.fract_x, ap.sigma_x = float_strip_rms(fx)
964+ ap.fract_y, ap.sigma_y = float_strip_rms(fy)
965+ ap.fract_z, ap.sigma_z = float_strip_rms(fz)
966+ if biso
967+ ap.temp_factor, sig = float_strip_rms(biso)
968+ elsif uiso
969+ ap.temp_factor, sig = float_strip_rms(uiso)
970+ ap.temp_factor *= 78.9568352087149 # 8*pi*pi
971+ end
972+ ap.occupancy, sig = float_strip_rms(occ)
973+ if calc == "c" || calc == "calc"
974+ calculated_atoms.push(ap.index)
975+ end
976+ # Guess special positions
977+ (1...mol.nsymmetries).each { |isym|
978+ sr = ap.fract_r
979+ sr = (mol.transform_for_symop(isym) * sr) - sr;
980+ nx = (sr.x + 0.5).floor
981+ ny = (sr.y + 0.5).floor
982+ nz = (sr.z + 0.5).floor
983+ if (Vector3D[sr.x - nx, sr.y - ny, sr.z - nz].length2 < 1e-6)
984+ # [isym, -nx, -ny, -nz] transforms this atom to itself
985+ # The following line is equivalent to:
986+ # if special_positions[ap.index] == nil; special_positions[ap.index] = []; end;
987+ # special_positions[ap.index].push(...)
988+ (special_positions[ap.index] ||= []).push([isym, -nx, -ny, -nz])
916989 end
917- }
990+ }
991+ if verbose && special_positions[ap.index]
992+ puts "#{name} is on the special position: #{special_positions[ap.index].inspect}"
993+ end
918994 }
919- puts "symmetry operation #{sym.inspect}" if verbose
920- add_symmetry(Transform.new(sym))
921- }
922- puts "#{self.nsymmetries} symmetry operations are added" if verbose
923- elsif labels[0] =~ /^_atom_site_label/
924- # Create atoms
925- data.each { |d|
926- name = d[hlabel["_atom_site_label"]]
927- elem = d[hlabel["_atom_site_type_symbol"]]
928- fx = d[hlabel["_atom_site_fract_x"]]
929- fy = d[hlabel["_atom_site_fract_y"]]
930- fz = d[hlabel["_atom_site_fract_z"]]
931- uiso = d[hlabel["_atom_site_U_iso_or_equiv"]]
932- biso = d[hlabel["_atom_site_B_iso_or_equiv"]]
933- occ = d[hlabel["_atom_site_occupancy"]]
934- calc = d[hlabel["_atom_site_calc_flag"]]
935- name = name.delete(" ()")
936- if elem == nil || elem == ""
937- if name =~ /[A-Za-z]{1,2}/
938- elem = $&.capitalize
939- else
940- elem = "Du"
941- end
942- end
943- ap = self.add_atom(name, elem, elem)
944- ap.fract_x, ap.sigma_x = float_strip_rms(fx)
945- ap.fract_y, ap.sigma_y = float_strip_rms(fy)
946- ap.fract_z, ap.sigma_z = float_strip_rms(fz)
947- if biso
948- ap.temp_factor, sig = float_strip_rms(biso)
949- elsif uiso
950- ap.temp_factor, sig = float_strip_rms(uiso)
951- ap.temp_factor *= 78.9568352087149 # 8*pi*pi
952- end
953- ap.occupancy, sig = float_strip_rms(occ)
954- if calc == "c" || calc == "calc"
955- calculated_atoms.push(ap.index)
956- end
957- # Guess special positions
958- (1...nsymmetries).each { |isym|
959- sr = ap.fract_r
960- sr = (transform_for_symop(isym) * sr) - sr;
961- nx = (sr.x + 0.5).floor
962- ny = (sr.y + 0.5).floor
963- nz = (sr.z + 0.5).floor
964- if (Vector3D[sr.x - nx, sr.y - ny, sr.z - nz].length2 < 1e-6)
965- # [isym, -nx, -ny, -nz] transforms this atom to itself
966- # The following line is equivalent to:
967- # if special_positions[ap.index] == nil; special_positions[ap.index] = []; end;
968- # special_positions[ap.index].push(...)
969- (special_positions[ap.index] ||= []).push([isym, -nx, -ny, -nz])
970- end
995+ puts "#{mol.natoms} atoms are created." if verbose
996+ elsif labels[0] =~ /^_atom_site_aniso_label/
997+ # Set anisotropic parameters
998+ c = 0
999+ data.each { |d|
1000+ name = d[hlabel["_atom_site_aniso_label"]]
1001+ ap = find_atom_by_name(mol, name)
1002+ next if !ap
1003+ u11 = d[hlabel["_atom_site_aniso_U_11"]]
1004+ if u11
1005+ usig = []
1006+ u11, usig[0] = float_strip_rms(u11)
1007+ u22, usig[1] = float_strip_rms(d[hlabel["_atom_site_aniso_U_22"]])
1008+ u33, usig[2] = float_strip_rms(d[hlabel["_atom_site_aniso_U_33"]])
1009+ u12, usig[3] = float_strip_rms(d[hlabel["_atom_site_aniso_U_12"]])
1010+ u13, usig[4] = float_strip_rms(d[hlabel["_atom_site_aniso_U_13"]])
1011+ u23, usig[5] = float_strip_rms(d[hlabel["_atom_site_aniso_U_23"]])
1012+ ap.aniso = [u11, u22, u33, u12, u13, u23, 8] + usig
1013+ c += 1
1014+ end
9711015 }
972- if verbose && special_positions[ap.index]
973- puts "#{name} is on the special position: #{special_positions[ap.index].inspect}"
974- end
975- }
976- puts "#{self.natoms} atoms are created." if verbose
977- elsif labels[0] =~ /^_atom_site_aniso_label/
978- # Set anisotropic parameters
979- c = 0
980- data.each { |d|
981- name = d[hlabel["_atom_site_aniso_label"]]
982- ap = find_atom_by_name(name)
983- next if !ap
984- u11 = d[hlabel["_atom_site_aniso_U_11"]]
985- if u11
986- usig = []
987- u11, usig[0] = float_strip_rms(u11)
988- u22, usig[1] = float_strip_rms(d[hlabel["_atom_site_aniso_U_22"]])
989- u33, usig[2] = float_strip_rms(d[hlabel["_atom_site_aniso_U_33"]])
990- u12, usig[3] = float_strip_rms(d[hlabel["_atom_site_aniso_U_12"]])
991- u13, usig[4] = float_strip_rms(d[hlabel["_atom_site_aniso_U_13"]])
992- u23, usig[5] = float_strip_rms(d[hlabel["_atom_site_aniso_U_23"]])
993- ap.aniso = [u11, u22, u33, u12, u13, u23, 8] + usig
994- c += 1
995- end
996- }
997- puts "#{c} anisotropic parameters are set." if verbose
998- elsif labels[0] =~ /^_geom_bond/
999- # Create bonds
1000- exbonds = []
1001- data.each { |d|
1002- n1 = d[hlabel["_geom_bond_atom_site_label_1"]]
1003- n2 = d[hlabel["_geom_bond_atom_site_label_2"]]
1004- sym1 = d[hlabel["_geom_bond_site_symmetry_1"]] || "."
1005- sym2 = d[hlabel["_geom_bond_site_symmetry_2"]] || "."
1006- n1 = find_atom_by_name(n1)
1007- n2 = find_atom_by_name(n2)
1008- next if n1 == nil || n2 == nil
1009- n1 = n1.index
1010- n2 = n2.index
1011- sym1 = parse_symmetry_operation(sym1)
1012- sym2 = parse_symmetry_operation(sym2)
1013- if sym1 || sym2
1014- exbonds.push([n1, n2, sym1, sym2])
1015- else
1016- self.create_bond(n1, n2)
1017- end
1018- tr1 = (sym1 ? transform_for_symop(sym1) : Transform.identity)
1019- tr2 = (sym2 ? transform_for_symop(sym2) : Transform.identity)
1020- if special_positions[n1]
1021- # Add extra bonds for equivalent positions of n1
1022- special_positions[n1].each { |symop|
1023- sym2x = symop_for_transform(tr1 * transform_for_symop(symop) * tr1.inverse * tr2)
1024- exbonds.push([n1, n2, sym1, sym2x])
1025- }
1026- end
1027- if special_positions[n2]
1028- # Add extra bonds n2-n1.symop, where symop transforms n2 to self
1029- tr = (sym1 ? transform_for_symop(sym1) : Transform.identity)
1030- special_positions[n2].each { |symop|
1031- sym1x = symop_for_transform(tr2 * transform_for_symop(symop) * tr2.inverse * tr1)
1032- exbonds.push([n2, n1, sym2, sym1x])
1033- }
1034- end
1035- }
1036- bond_defined = true
1037- puts "#{self.nbonds} bonds are created." if verbose
1038- if calculated_atoms.length > 0
1039- # Guess bonds for calculated hydrogen atoms
1040- n1 = 0
1041- calculated_atoms.each { |ai|
1042- if atoms[ai].connects.length == 0
1043- as = find_close_atoms(ai)
1044- as.each { |aj|
1045- self.create_bond(ai, aj)
1046- n1 += 1
1016+ puts "#{c} anisotropic parameters are set." if verbose
1017+ elsif labels[0] =~ /^_geom_bond/
1018+ # Create bonds
1019+ exbonds = []
1020+ data.each { |d|
1021+ n1 = d[hlabel["_geom_bond_atom_site_label_1"]]
1022+ n2 = d[hlabel["_geom_bond_atom_site_label_2"]]
1023+ sym1 = d[hlabel["_geom_bond_site_symmetry_1"]] || "."
1024+ sym2 = d[hlabel["_geom_bond_site_symmetry_2"]] || "."
1025+ n1 = find_atom_by_name(mol, n1)
1026+ n2 = find_atom_by_name(mol, n2)
1027+ next if n1 == nil || n2 == nil
1028+ n1 = n1.index
1029+ n2 = n2.index
1030+ sym1 = parse_symmetry_operation(sym1)
1031+ sym2 = parse_symmetry_operation(sym2)
1032+ if sym1 || sym2
1033+ exbonds.push([n1, n2, sym1, sym2])
1034+ else
1035+ mol.create_bond(n1, n2)
1036+ end
1037+ tr1 = (sym1 ? mol.transform_for_symop(sym1) : Transform.identity)
1038+ tr2 = (sym2 ? mol.transform_for_symop(sym2) : Transform.identity)
1039+ if special_positions[n1]
1040+ # Add extra bonds for equivalent positions of n1
1041+ special_positions[n1].each { |symop|
1042+ sym2x = mol.symop_for_transform(tr1 * mol.transform_for_symop(symop) * tr1.inverse * tr2)
1043+ exbonds.push([n1, n2, sym1, sym2x])
10471044 }
1048- end
1049- }
1050- puts "#{n1} bonds are guessed." if verbose
1051- end
1052- if exbonds.length > 0
1053- h = Dialog.run("CIF Import: Symmetry Expansion") {
1054- layout(1,
1055- item(:text, :title=>"There are bonds including symmetry related atoms.\nWhat do you want to do?"),
1056- item(:radio, :title=>"Expand only atoms that are included in those extra bonds.", :tag=>"atoms_only"),
1057- item(:radio, :title=>"Expand fragments having atoms included in the extra bonds.", :tag=>"fragment", :value=>1),
1058- item(:radio, :title=>"Ignore these extra bonds.", :tag=>"ignore")
1059- )
1060- radio_group("atoms_only", "fragment", "ignore")
1061- }
1062- if h[:status] == 0 && h["ignore"] == 0
1063- atoms_only = (h["atoms_only"] != 0)
1064- if !atoms_only
1065- fragments = []
1066- self.each_fragment { |f| fragments.push(f) }
1067- end
1068- debug = nil
1069- exbonds.each { |ex|
1070- if debug; puts "extra bond #{ex[0]}(#{ex[2].inspect}) - #{ex[1]}(#{ex[3].inspect})"; end
1071- ex0 = ex.dup
1072- (2..3).each { |i|
1073- symop = ex[i]
1074- if symop == nil
1075- ex[i + 2] = ex[i - 2]
1076- else
1077- if debug; puts " symop = #{symop.inspect}"; end
1078- # Expand the atom or the fragment including the atom
1079- if atoms_only
1080- ig = IntGroup[ex[i - 2]]
1081- idx = 0
1045+ end
1046+ if special_positions[n2]
1047+ # Add extra bonds n2-n1.symop, where symop transforms n2 to self
1048+ tr = (sym1 ? mol.transform_for_symop(sym1) : Transform.identity)
1049+ special_positions[n2].each { |symop|
1050+ sym1x = mol.symop_for_transform(tr2 * mol.transform_for_symop(symop) * tr2.inverse * tr1)
1051+ exbonds.push([n2, n1, sym2, sym1x])
1052+ }
1053+ end
1054+ }
1055+ bond_defined = true
1056+ puts "#{mol.nbonds} bonds are created." if verbose
1057+ if calculated_atoms.length > 0
1058+ # Guess bonds for calculated hydrogen atoms
1059+ n1 = 0
1060+ calculated_atoms.each { |ai|
1061+ if mol.atoms[ai].connects.length == 0
1062+ as = mol.find_close_atoms(ai)
1063+ as.each { |aj|
1064+ mol.create_bond(ai, aj)
1065+ n1 += 1
1066+ }
1067+ end
1068+ }
1069+ puts "#{n1} bonds are guessed." if verbose
1070+ end
1071+ if exbonds.length > 0
1072+ h = Dialog.run("CIF Import: Symmetry Expansion") {
1073+ layout(1,
1074+ item(:text, :title=>"There are bonds including symmetry related atoms.\nWhat do you want to do?"),
1075+ item(:radio, :title=>"Expand only atoms that are included in those extra bonds.", :tag=>"atoms_only"),
1076+ item(:radio, :title=>"Expand fragments having atoms included in the extra bonds.", :tag=>"fragment", :value=>1),
1077+ item(:radio, :title=>"Ignore these extra bonds.", :tag=>"ignore")
1078+ )
1079+ radio_group("atoms_only", "fragment", "ignore")
1080+ }
1081+ if h[:status] == 0 && h["ignore"] == 0
1082+ atoms_only = (h["atoms_only"] != 0)
1083+ if !atoms_only
1084+ fragments = []
1085+ mol.each_fragment { |f| fragments.push(f) }
1086+ end
1087+ debug = nil
1088+ exbonds.each { |ex|
1089+ if debug; puts "extra bond #{ex[0]}(#{ex[2].inspect}) - #{ex[1]}(#{ex[3].inspect})"; end
1090+ ex0 = ex.dup
1091+ (2..3).each { |i|
1092+ symop = ex[i]
1093+ if symop == nil
1094+ ex[i + 2] = ex[i - 2]
10821095 else
1083- ig = fragments.find { |f| f.include?(ex[i - 2]) }
1084- ig.each_with_index { |n, ii| if n == ex[i - 2]; idx = ii; break; end }
1096+ if debug; puts " symop = #{symop.inspect}"; end
1097+ # Expand the atom or the fragment including the atom
1098+ if atoms_only
1099+ ig = IntGroup[ex[i - 2]]
1100+ idx = 0
1101+ else
1102+ ig = fragments.find { |f| f.include?(ex[i - 2]) }
1103+ ig.each_with_index { |n, ii| if n == ex[i - 2]; idx = ii; break; end }
1104+ end
1105+ symop[4] = ex[i - 2] # Base atom
1106+ if debug; puts " expanding #{ig} by #{symop.inspect}"; end
1107+ a = mol.expand_by_symmetry(ig, symop[0], symop[1], symop[2], symop[3])
1108+ ex[i + 2] = a[idx] # Index of the expanded atom
10851109 end
1086- symop[4] = ex[i - 2] # Base atom
1087- if debug; puts " expanding #{ig} by #{symop.inspect}"; end
1088- a = self.expand_by_symmetry(ig, symop[0], symop[1], symop[2], symop[3])
1089- ex[i + 2] = a[idx] # Index of the expanded atom
1090- end
1110+ }
1111+ if ex[4] && ex[5] && ex[4] != ex[5]
1112+ if debug; puts " creating bond #{ex[4]} - #{ex[5]}"; end
1113+ mol.create_bond(ex[4], ex[5])
1114+ end
10911115 }
1092- if ex[4] && ex[5] && ex[4] != ex[5]
1093- if debug; puts " creating bond #{ex[4]} - #{ex[5]}"; end
1094- self.create_bond(ex[4], ex[5])
1095- end
1096- }
1116+ end
10971117 end
1098- end
1099- puts "#{self.nbonds} bonds are created." if verbose
1118+ puts "#{mol.nbonds} bonds are created." if verbose
1119+ end
1120+ next
1121+ else
1122+ # puts "Loop beginning with #{labels[0]} is skipped"
11001123 end
1101- next
1102- else
1103- # puts "Loop beginning with #{labels[0]} is skipped"
1104- end
1105- else
1106- # Skip this token
1107- token = getciftoken(fp)
1124+ else
1125+ # Skip this token
1126+ token = getciftoken(fp)
1127+ end
1128+ # Skip tokens until next tag or reserved word is detected
1129+ while token != nil && token[0] != ?_ && token[0] != ?#
1130+ token = getciftoken(fp)
1131+ end
1132+ next
11081133 end
1109- # Skip tokens until next tag or reserved word is detected
1110- while token != nil && token[0] != ?_ && token[0] != ?#
1111- token = getciftoken(fp)
1134+ if !bond_defined
1135+ mol.guess_bonds
11121136 end
1113- next
1137+ if token != nil && token == data_identifier
1138+ # Process next molecule: open a new molecule and start adding atom on that
1139+ mol = Molecule.new
1140+ count_up += 1
1141+ (@aux_mols ||= []).push(mol)
1142+ next
1143+ end
1144+ break
11141145 end
11151146 fp.close
1116- if !bond_defined
1117- self.guess_bonds
1118- end
11191147 # self.undo_enabled = save_undo_enabled
11201148 return true
11211149 end
--- a/wxSources/MyDocument.cpp
+++ b/wxSources/MyDocument.cpp
@@ -68,6 +68,7 @@ BEGIN_EVENT_TABLE(MyDocument, wxDocument)
6868 EVT_COMMAND(MyDocumentEvent_insertFrameFromMD, MyDocumentEvent, MyDocument::OnInsertFrameFromMD)
6969 EVT_COMMAND(MyDocumentEvent_updateDisplay, MyDocumentEvent, MyDocument::OnUpdateDisplay)
7070 EVT_COMMAND(MyDocumentEvent_threadTerminated, MyDocumentEvent, MyDocument::OnSubThreadTerminated)
71+ EVT_COMMAND(MyDocumentEvent_openAuxiliaryDocuments, MyDocumentEvent, MyDocument::OnOpenAuxiliaryDocuments)
7172 EVT_MENU(myMenuID_Import, MyDocument::OnImport)
7273 EVT_MENU(myMenuID_Export, MyDocument::OnExport)
7374 EVT_MENU(myMenuID_ExportGraphic, MyDocument::OnExportGraphic)
@@ -229,6 +230,12 @@ MyDocument::DoOpenDocument(const wxString& file)
229230 return false;
230231 }
231232
233+ /* Does this document have multiple representation of molecules? */
234+ if (MolActionCreateAndPerform(newmol, SCRIPT_ACTION(";i"), "lambda { @aux_mols ? @aux_mols.count : 0 }", &len) == 0 && len > 0) {
235+ wxCommandEvent myEvent(MyDocumentEvent, MyDocumentEvent_openAuxiliaryDocuments);
236+ wxPostEvent(this, myEvent);
237+ }
238+
232239 if ((len = strlen(p)) > 4 && strcasecmp(p + len - 4, ".psf") == 0) {
233240 // Look for a ".pdb" file with the same basename
234241 char *buf;
@@ -254,6 +261,18 @@ MyDocument::DoOpenDocument(const wxString& file)
254261 return true;
255262 }
256263
264+void
265+MyDocument::OnOpenAuxiliaryDocuments(wxCommandEvent &event)
266+{
267+ MolActionCreateAndPerform(mol, SCRIPT_ACTION(""),
268+ "lambda {\n"
269+ " fn = self.name\n"
270+ " @aux_mols.each_with_index { |am, i| \n"
271+ " m = Molecule.open; m.set_molecule(am)\n"
272+ " m.set_name(fn + \"[#{i + 2}]\")\n"
273+ "}; @aux_mols = nil }");
274+}
275+
257276 bool
258277 MyDocument::Revert()
259278 {
--- a/wxSources/MyDocument.h
+++ b/wxSources/MyDocument.h
@@ -38,7 +38,8 @@ enum {
3838 MyDocumentEvent_insertFrameFromMD,
3939 MyDocumentEvent_threadTerminated,
4040 MyDocumentEvent_openFilesByIPC,
41- MyDocumentEvent_documentWillClose
41+ MyDocumentEvent_documentWillClose,
42+ MyDocumentEvent_openAuxiliaryDocuments
4243 };
4344
4445 class MyDocument: public wxDocument
@@ -151,6 +152,7 @@ public:
151152 void OnInsertFrameFromMD(wxCommandEvent &event);
152153 void OnUpdateDisplay(wxCommandEvent &event);
153154 void OnSubThreadTerminated(wxCommandEvent &event);
155+ void OnOpenAuxiliaryDocuments(wxCommandEvent &event);
154156
155157 void OnUpdateUI(wxUpdateUIEvent &event);
156158
旧リポジトリブラウザで表示