4 # Created by Toshi Nagata on 2008/06/28.
5 # Copyright 2008 Toshi Nagata. All rights reserved.
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation version 2 of the License.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
18 def cmd_assign_residue
23 atoms = sel.inspect.sub!("IntGroup[", "").sub!("]", "")
24 hash = Dialog.run("Assign Residue") {
26 item(:text, :title=>"New residue name/number\n(like \"RES.1\")\nfor atoms #{atoms}"),
27 item(:textfield, :width=>120, :tag=>"residue"))
30 residue = hash["residue"]
31 assign_residue(sel, residue)
35 def cmd_offset_residue
40 atoms = sel.inspect.sub!("IntGroup[", "").sub!("]", "")
41 hash = Dialog.run("Offset Residues") {
43 item(:text, :title=>"Offset residue number:\nfor atoms #{atoms}"),
44 item(:textfield, :width=>120, :tag=>"offset"))
47 offset = hash["offset"].to_i
48 offset_residue(sel, offset)
52 def cmd_sort_by_residue
57 sorted = sel.sort_by { |i| [self.atoms[i].res_seq, i] }
60 (0...natoms).each { |i|
64 break if j >= sorted.length
69 self.renumber_atoms(ary)
75 hash = Dialog.run("Delete Frames") {
77 item(:text, :title=>"Start"),
78 item(:textfield, :width=>120, :tag=>"start", :value=>"0"),
79 item(:text, :title=>"End"),
80 item(:textfield, :width=>120, :tag=>"end", :value=>(n - 1).to_s),
81 item(:text, :title=>"Keeping frames every..."),
83 item(:text, :title=>"Step"),
84 item(:textfield, :width=>120, :tag=>"step", :value=>"0"))
87 sframe = Integer(hash["start"])
88 eframe = Integer(hash["end"])
89 step = Integer(hash["step"])
90 return if sframe > eframe
91 eframe = n - 1 if eframe >= n
92 fgroup = IntGroup[sframe..eframe]
94 while sframe <= eframe
103 def cmd_reverse_frames
106 hash = Dialog.run("Reverse Frames") {
108 item(:text, :title=>"Start"),
109 item(:textfield, :width=>120, :tag=>"start", :value=>"0"),
110 item(:text, :title=>"End"),
111 item(:textfield, :width=>120, :tag=>"end", :value=>(n - 1).to_s))
113 if hash[:status] == 0
114 sframe = Integer(hash["start"])
115 eframe = Integer(hash["end"])
116 return if sframe > eframe
117 eframe = n - 1 if eframe >= n
118 frames = (0...sframe).to_a + (sframe..eframe).to_a.reverse + ((eframe + 1)...n).to_a
119 reorder_frames(frames)
123 def cmd_extra_properties
125 get_count = lambda { |it| mol.nframes }
126 get_value = lambda { |it, row, col|
130 sprintf("%.8f", mol.get_property(col - 1, row)) rescue ""
133 mol.open_auxiliary_window("Extra Props", nil, nil, :resizable=>true, :has_close_box=>true) {
135 @on_document_modified = lambda { |m|
136 if (n = m.property_names) != names
138 col = [["frame", 40]] + names.map { |nn| [nn, 120] }
139 item_with_tag("table")[:columns] = col
141 item_with_tag("table")[:refresh] = true
144 item(:table, :width=>320, :height=>300, :flex=>[0,0,0,0,1,1], :tag=>"table",
145 :on_count=>get_count,
146 :on_get_value=>get_value),
149 set_min_size(320, 200)
150 # listen(mol, "documentModified", on_document_modified)
151 # listen(mol, "documentWillClose", lambda { |m| close } )
152 on_document_modified.call(mol)
161 d = open_auxiliary_window("Energy", nil, nil, :resizable=>true, :has_close_box=>true) {
162 graph_item = nil # Forward declaration
164 draw_graph = lambda { |it|
166 f = graph_item[:frame]
167 draw_rectangle(0, 0, f[2], f[3])
170 draw_line(16, 0, 16, height + 12, width + 20, height + 12)
174 h = (h == 0.0 ? 1.0 : height / h)
176 w = (w == 0 ? 1.0 : Float(width) / w)
178 wave.each_with_index { |d, i|
180 a.push(height - (d - min) * h + 12)
184 a.push(height - (wave[0] - min) * h + 12)
187 brush(:color=>[0.2, 0.2, 1.0])
190 yy = height - (y - min) * h + 12
191 draw_ellipse(cur * w + 16, height - (y - min) * h + 12, 6)
193 @on_document_modified = lambda { |m|
197 wave = [mol.get_property("energy", 0)] * 2
199 wave = (0...mol.nframes).map { |i| mol.get_property("energy", i) }
201 f = graph_item[:frame]
202 item_with_tag("energy")[:title] = sprintf("Energy = %.10f hartree, Frame = %d", mol.get_property("energy", cur), cur)
203 graph_item.refresh_rect([0, 0, f[2], f[3]])
206 item(:text, :title=>"Energy = ", :tag=>"energy"),
207 item(:view, :frame=>[0, 0, 320, 240], :tag=>"graph", :on_paint=>draw_graph, :flex=>[0,0,0,0,1,1]),
208 # item(:button, :title=>"Update", :action=>doc_modified, :align=>:center, :flex=>[1,1,1,0,0,0]),
209 # item(:button, :title=>"Close", :action=>proc { hide }, :align=>:center, :flex=>[1,1,1,0,0,0]),
212 graph_item = item_with_tag("graph")
216 @on_document_modified.call(mol)
222 def cmd_create_surface
224 mol.open_auxiliary_window("MO Surface", nil, nil, :resizable=>true, :has_close_box=>true) {
225 motype = mol.get_mo_info(:type)
226 alpha = mol.get_mo_info(:alpha)
227 beta = mol.get_mo_info(:beta)
228 ncomps = mol.get_mo_info(:ncomps)
231 coltable = [[0,0,1], [1,0,0], [0,1,0], [1,1,0], [0,1,1], [1,0,1], [0,0,0]]
236 mo_menu = ["1000 (-00.00000000)"] # Dummy entry; create later
241 a_idx, label, nprims = mol.get_gaussian_shell_info(i)
242 if a_idx_old != a_idx
245 n = mol.atoms[a_idx].name
249 tabvals.push([a, n, label, a_idx])
251 on_get_value = lambda { |it, row, col|
257 coeffs = mol.get_mo_coefficients(mo_index)
259 coeffs = (0...ncomps).map { |i| (i == mo_index ? 1.0 : 0.0) }
262 sprintf("%.6f", coeffs[row])
265 h = {"mo"=>nil, "color"=>nil, "opacity"=>nil, "threshold"=>nil, "expand"=>nil, "grid"=>nil}
267 on_action = lambda { |it|
270 if tag == "color" || tag == "opacity"
271 opac = value("opacity").to_f
272 opac = 0.0 if opac < 0.0
273 opac = 1.0 if opac > 1.0
275 color = coltable[col] + [opac]
276 color0 = [1,1,1,opac]
277 mol.set_surface_attr(:color=>color, :color0=>color0)
279 elsif tag == "threshold"
280 thres = it[:value].to_f
281 thres = 0.001 if thres >= 0.0 && thres < 0.001
282 thres = -0.001 if thres <= 0.0 && thres > -0.001
283 mol.set_surface_attr(:thres=>thres)
286 should_update = false
289 if val && h[key] != val
294 item_with_tag("update")[:enabled] = should_update
297 on_mo_action = lambda { |it|
301 mo_index = (mo / 2) + (mo % 2 == 1 ? ncomps : 0) + 1
309 item_with_tag("table")[:refresh] = true
312 on_set_action = lambda { |it|
313 if mo_ao != it[:value]
316 mo_menu = (1..(ncomps * i)).map { |n|
320 c1 = (i2 == 0 ? "B" : "A")
321 c2 = (i1 > (i2 == 0 ? beta : alpha) ? "*" : "")
326 c2 = (i1 > alpha ? "*" : "")
328 en = mol.get_mo_energy(i1 + (i2 == 0 ? ncomps : 0))
329 sprintf("%d%s%s (%.8f)", i1, c1, c2, en)
334 mo_menu[i] = sprintf("AO%d: %s (%s)", i + 1, tabvals[i][2], mol.atoms[tabvals[i][3]].name)
337 it0 = item_with_tag("mo")
338 it0[:subitems] = mo_menu
340 on_mo_action.call(it0)
343 on_update = lambda { |it|
347 opac = h["opacity"].to_f
348 opac = 0.0 if opac < 0.0
349 opac = 1.0 if opac > 1.0
350 color = coltable[h["color"]] + [opac]
351 color0 = [1, 1, 1, opac]
352 thres = h["threshold"].to_f
353 thres = 0.001 if thres >= 0.0 && thres < 0.001
354 thres = -0.001 if thres <= 0.0 && thres > -0.001
355 expand = h["expand"].to_f
356 expand = 0.01 if expand < 0.01
357 expand = 10.0 if expand > 10.0
358 grid = h["grid"].to_i
366 mol.set_mo_coefficients(0, 0.0, coeffs)
368 mol.create_surface(idx, :npoints=>grid, :color=>color, :thres=>thres, :expand=>expand, :color0=>color0)
373 item(:text, :title=>"Orbital Set"),
374 item(:popup, :tag=>"mo_ao", :subitems=>["Molecular Orbitals", "Atomic Orbitals"], :action=>on_set_action),
375 item(:text, :title=>"Select"),
376 item(:popup, :tag=>"mo", :subitems=>mo_menu, :action=>on_mo_action)),
378 item(:text, :title=>"Color"),
379 item(:popup, :tag=>"color", :subitems=>["blue", "red", "green", "yellow", "cyan", "magenta", "black"], :action=>on_action),
380 item(:text, :title=>"Opacity"),
381 item(:textfield, :tag=>"opacity", :width=>80, :value=>"0.6", :action=>on_action),
382 item(:text, :title=>"Threshold"),
383 item(:textfield, :tag=>"threshold", :width=>80, :value=>"0.05", :action=>on_action),
384 item(:text, :title=>"Box Limit"),
385 item(:textfield, :tag=>"expand", :width=>80, :value=>"1.0", :action=>on_action)),
387 item(:text, :title=>"Number of Grid Points"),
388 item(:textfield, :tag=>"grid", :width=>120, :value=>"512000", :action=>on_action)),
389 item(:table, :width=>300, :height=>300, :tag=>"table",
390 :columns=>[["Atom", 60], ["Name", 60], ["Label", 60], ["Coeff", 120]],
391 :on_count=> lambda { |it| tabvals.count },
392 :on_get_value=>on_get_value,
393 :flex=>[0,0,0,0,1,1]),
394 item(:button, :tag=>"update", :title=>"Update", :action=>on_update, :flex=>[0,1,0,0,0,0]),
397 on_set_action.call(item_with_tag("mo_ao"))
399 set_min_size(size[0], 250)
400 item_with_tag("table")[:refresh] = true
407 $test_dialog = Dialog.new("Test") { item(:text, :title=>"test"); show }
414 sdir = get_global_settings("global.scratch_dir")
416 p = Dialog.open_panel("Please select scratch directory", sdir, nil, true)
419 error_message_box("Please avoid path containing a white space.\n" + p.sub(/ /, "<!> <!>"))
423 set_global_settings("global.scratch_dir", p)
433 register_menu("Assign residue...", :cmd_assign_residue, :non_empty)
434 register_menu("Offset residue...", :cmd_offset_residue, :non_empty)
435 register_menu("Sort by residue", :cmd_sort_by_residue, :non_empty)
436 register_menu("", "")
437 register_menu("Delete Frames...", :cmd_delete_frames, lambda { |m| m && m.nframes > 1 } )
438 register_menu("Reverse Frames...", :cmd_reverse_frames, lambda { |m| m && m.nframes > 1 } )
439 register_menu("", "")
440 register_menu("Show Energy Window...", :cmd_show_energy, lambda { |m| m && m.property_names.include?("energy") } )
441 register_menu("Show MO Surface...", :cmd_create_surface, lambda { |m| m && m.get_mo_info(:type) != nil } )
442 #register_menu("cmd test", :cmd_test)