aims_project_windows 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +5 -0
- data/bin/AimsCalc +367 -0
- data/bin/AimsProject +88 -0
- data/bin/AimsProjectManager +39 -0
- data/lib/aims_project/aims_project_exception.rb +42 -0
- data/lib/aims_project/aims_project_geometry.rb +52 -0
- data/lib/aims_project/app_controller.rb +245 -0
- data/lib/aims_project/atom.rb +95 -0
- data/lib/aims_project/calculation.rb +406 -0
- data/lib/aims_project/calculation_tree.rb +65 -0
- data/lib/aims_project/calculation_window.rb +141 -0
- data/lib/aims_project/crystal_viewer.rb +994 -0
- data/lib/aims_project/crystal_viewer_options.rb +103 -0
- data/lib/aims_project/geometry_console.rb +155 -0
- data/lib/aims_project/geometry_editor.rb +83 -0
- data/lib/aims_project/geometry_file.rb +183 -0
- data/lib/aims_project/geometry_window.rb +160 -0
- data/lib/aims_project/green_arrow.jpg +0 -0
- data/lib/aims_project/inspector.rb +183 -0
- data/lib/aims_project/material.rb +30 -0
- data/lib/aims_project/octree.rb +5 -0
- data/lib/aims_project/pan.gif +0 -0
- data/lib/aims_project/project.rb +102 -0
- data/lib/aims_project/project_tree.rb +62 -0
- data/lib/aims_project/rotate.gif +0 -0
- data/lib/aims_project/thread_callback_event.rb +19 -0
- data/lib/aims_project/zoom.gif +0 -0
- data/lib/aims_project.rb +158 -0
- data/skeleton/Capfile +37 -0
- data/skeleton/config/aims.sh +58 -0
- data/skeleton/config/tasks.rb +145 -0
- data/skeleton/config/user_variables.rb +37 -0
- data/skeleton/control/example.erb +41 -0
- data/skeleton/geometry/example +1 -0
- metadata +137 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'observer'
|
2
|
+
|
3
|
+
module AimsProject
|
4
|
+
class CrystalViewerOptions
|
5
|
+
|
6
|
+
include Wx
|
7
|
+
include Observable
|
8
|
+
|
9
|
+
def add_control(name, control)
|
10
|
+
instance_variable_set("@#{name.to_s}".to_sym, control)
|
11
|
+
instance_eval <<-EOS
|
12
|
+
def #{name.to_s}
|
13
|
+
@#{name.to_s}.get_value
|
14
|
+
end
|
15
|
+
|
16
|
+
def #{name.to_s}=(val)
|
17
|
+
@#{name.to_s}.set_value(val)
|
18
|
+
changed
|
19
|
+
notify_observers
|
20
|
+
end
|
21
|
+
EOS
|
22
|
+
control
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def initialize(inspector_window)
|
27
|
+
|
28
|
+
# Default padding around each element
|
29
|
+
border = 5
|
30
|
+
|
31
|
+
# Main Sizer
|
32
|
+
inspector_window.sizer = VBoxSizer.new
|
33
|
+
|
34
|
+
# Panel 1
|
35
|
+
panel1 = VBoxSizer.new
|
36
|
+
panel1.add_item(add_control(:show_bonds, CheckBox.new(inspector_window, :label => 'Show Bonds')), :flag => ALL,:border => border)
|
37
|
+
panel1.add_item(add_control(:show_lighting, CheckBox.new(inspector_window, :label => 'Show Lighting')), :flag => ALL, :border => border)
|
38
|
+
panel1.add_item(add_control(:show_supercell, CheckBox.new(inspector_window, :label => "Show Unit Cell")), :flag => ALL, :border => border)
|
39
|
+
panel1.add_item(add_control(:correct, CheckBox.new(inspector_window, :label => "Correct Geometry")), :flag => ALL, :border => border)
|
40
|
+
panel1.add_item(add_control(:solid_bg, CheckBox.new(inspector_window, :label => "Solid BG")), :flag => ALL, :border => border)
|
41
|
+
|
42
|
+
gsizer = GridSizer.new(2,1)
|
43
|
+
gsizer.add(StaticText.new(inspector_window, :label => "Bond Length"))
|
44
|
+
gsizer.add_item(add_control(:bond_length, SpinCtrl.new(inspector_window, :min => 1, :max => 100, :value => "4", :name => "Name")), :flag => EXPAND)
|
45
|
+
panel1.add_item(gsizer)
|
46
|
+
|
47
|
+
|
48
|
+
# Panel 2 : Clip Planes
|
49
|
+
panel2 = VBoxSizer.new
|
50
|
+
panel2.add_item(StaticText.new(inspector_window, -1, "Clip Planes:", :style => ALIGN_LEFT))
|
51
|
+
panel2.add_item(add_control(:show_xclip, CheckBox.new(inspector_window, :label => 'x')), :flag => Wx::ALIGN_CENTER, :border => border)
|
52
|
+
panel2.add_item(add_control(:show_yclip, CheckBox.new(inspector_window, :label => 'y')), :flag => Wx::ALIGN_CENTER, :border => border)
|
53
|
+
panel2.add_item(add_control(:show_zclip, CheckBox.new(inspector_window, :label => 'z')), :flag => Wx::ALIGN_CENTER, :border => border)
|
54
|
+
|
55
|
+
# Panel 3: Repeat
|
56
|
+
panel3 = VBoxSizer.new
|
57
|
+
panel3.add_item(StaticText.new(inspector_window, -1, "Repeat:", :style => ALIGN_LEFT), :flag => EXPAND)
|
58
|
+
|
59
|
+
panel3grid = GridSizer.new(3,2, border, border)
|
60
|
+
panel3grid.add(StaticText.new(inspector_window, :label => "x", :style => ALIGN_RIGHT),1, EXPAND)
|
61
|
+
panel3grid.add(add_control(:x_repeat, SpinCtrl.new(inspector_window, :value => "1", :min => 1, :max => 100, :initial => 1)),2)
|
62
|
+
|
63
|
+
panel3grid.add(StaticText.new(inspector_window, :label => "y",:style => ALIGN_RIGHT),1, EXPAND)
|
64
|
+
panel3grid.add(add_control(:y_repeat, SpinCtrl.new(inspector_window, :value => "1", :min => 1, :max => 100, :initial => 1)),2)
|
65
|
+
|
66
|
+
panel3grid.add(StaticText.new(inspector_window, :label => "z",:style => ALIGN_RIGHT),1, EXPAND)
|
67
|
+
panel3grid.add(add_control(:z_repeat, SpinCtrl.new(inspector_window, :value => "1", :min => 1, :max => 100, :initial => 1)),2)
|
68
|
+
|
69
|
+
panel3.add_item(panel3grid, :flag => EXPAND | ALIGN_CENTER)
|
70
|
+
|
71
|
+
# Event Handling
|
72
|
+
inspector_window.evt_checkbox(@show_bonds) {|evt| changed; notify_observers}
|
73
|
+
inspector_window.evt_checkbox(@show_lighting) {|evt| changed; notify_observers}
|
74
|
+
inspector_window.evt_checkbox(@show_supercell) {|evt| changed; notify_observers}
|
75
|
+
inspector_window.evt_checkbox(@solid_bg) {|evt| changed; notify_observers}
|
76
|
+
inspector_window.evt_checkbox(@correct) {|evt| changed; notify_observers }
|
77
|
+
inspector_window.evt_spinctrl(@bond_length) {|evt| changed; notify_observers }
|
78
|
+
inspector_window.evt_checkbox(@show_xclip) {|evt| changed; notify_observers}
|
79
|
+
inspector_window.evt_checkbox(@show_yclip) {|evt| changed; notify_observers}
|
80
|
+
inspector_window.evt_checkbox(@show_zclip) {|evt| changed; notify_observers}
|
81
|
+
inspector_window.evt_spinctrl(@x_repeat) {|evt| changed; notify_observers}
|
82
|
+
inspector_window.evt_spinctrl(@y_repeat) {|evt| changed; notify_observers}
|
83
|
+
inspector_window.evt_spinctrl(@z_repeat) {|evt| changed; notify_observers}
|
84
|
+
|
85
|
+
# Add sub-panels
|
86
|
+
inspector_window.sizer.add_item(panel1, :flag => EXPAND, :proportion => 1)
|
87
|
+
inspector_window.sizer.add_spacer(5)
|
88
|
+
inspector_window.sizer.add_item(panel2, :flag => EXPAND, :proportion => 1)
|
89
|
+
inspector_window.sizer.add_spacer(5)
|
90
|
+
inspector_window.sizer.add_item(panel3, :flag => EXPAND, :proportion => 1)
|
91
|
+
inspector_window.layout
|
92
|
+
end
|
93
|
+
|
94
|
+
def set_properties(props)
|
95
|
+
props.each{|k,v|
|
96
|
+
instance_variable_get("@#{k.to_s}").set_value(v)
|
97
|
+
}
|
98
|
+
changed
|
99
|
+
notify_observers
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
|
2
|
+
module AimsProject
|
3
|
+
|
4
|
+
class CommandHistory
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@history= []
|
8
|
+
@counter = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def save(cmd)
|
12
|
+
@history.push(cmd)
|
13
|
+
@counter = @history.size
|
14
|
+
end
|
15
|
+
|
16
|
+
def prev
|
17
|
+
@counter = @history.size unless @counter
|
18
|
+
if @counter > 0
|
19
|
+
@counter = @counter - 1
|
20
|
+
end
|
21
|
+
@history[@counter]
|
22
|
+
end
|
23
|
+
|
24
|
+
def succ
|
25
|
+
@counter = @history.size unless @counter
|
26
|
+
if @counter < @history.size-1
|
27
|
+
@counter = @counter + 1
|
28
|
+
end
|
29
|
+
@history[@counter]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class GeometryConsole < Wx::ScrolledWindow
|
34
|
+
|
35
|
+
include Wx
|
36
|
+
include Aims
|
37
|
+
|
38
|
+
def initialize(app, window)
|
39
|
+
super(window)
|
40
|
+
@app = app
|
41
|
+
@text_ctrl = RichTextCtrl.new(self)
|
42
|
+
@history = CommandHistory.new
|
43
|
+
sizer = BoxSizer.new(VERTICAL)
|
44
|
+
sizer.add_item(@text_ctrl, :proportion => 1, :flag => EXPAND | ALL, :border => 5)
|
45
|
+
|
46
|
+
set_auto_layout(true)
|
47
|
+
set_sizer(sizer)
|
48
|
+
prompt
|
49
|
+
|
50
|
+
@text_ctrl.evt_key_down do |evt|
|
51
|
+
k = evt.get_key_code
|
52
|
+
caret_pos = @text_ctrl.get_insertion_point
|
53
|
+
|
54
|
+
case k
|
55
|
+
when K_UP
|
56
|
+
prev = @history.prev
|
57
|
+
@text_ctrl.remove(@line_start, @text_ctrl.get_last_position)
|
58
|
+
@text_ctrl.append_text(prev) if prev
|
59
|
+
when K_DOWN
|
60
|
+
succ = @history.succ
|
61
|
+
@text_ctrl.remove(@line_start,@text_ctrl.get_last_position)
|
62
|
+
@text_ctrl.append_text(succ) if succ
|
63
|
+
when K_LEFT
|
64
|
+
if caret_pos > @line_start
|
65
|
+
@text_ctrl.set_insertion_point(caret_pos-1)
|
66
|
+
end
|
67
|
+
when K_RIGHT
|
68
|
+
if caret_pos < @text_ctrl.get_last_position
|
69
|
+
@text_ctrl.set_insertion_point(caret_pos+1)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
if caret_pos < @line_start
|
73
|
+
@text_ctrl.set_insertion_point(@line_start+1)
|
74
|
+
end
|
75
|
+
evt.skip
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@text_ctrl.evt_char do |evt|
|
80
|
+
k = evt.get_key_code
|
81
|
+
case k
|
82
|
+
when K_RETURN
|
83
|
+
cmd = @text_ctrl.get_range(@line_start, @text_ctrl.get_caret_position+1).strip
|
84
|
+
@history.save(cmd)
|
85
|
+
print "\n"
|
86
|
+
# evaluate
|
87
|
+
begin
|
88
|
+
result = get_binding.eval(cmd)
|
89
|
+
if result
|
90
|
+
result_str = result.to_s
|
91
|
+
print(result_str+"\n")
|
92
|
+
end
|
93
|
+
rescue Exception => e
|
94
|
+
print(e.message + "\n", Wx::RED)
|
95
|
+
end
|
96
|
+
|
97
|
+
prompt
|
98
|
+
when K_HOME # For some reason, ctrl-a maps to this
|
99
|
+
@text_ctrl.set_insertion_point(@line_start)
|
100
|
+
when K_HELP # For some reason, ctrl-e maps to this
|
101
|
+
@text_ctrl.set_insertion_point_end
|
102
|
+
else
|
103
|
+
evt.skip()
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_binding
|
110
|
+
unless @binding
|
111
|
+
@binding = binding()
|
112
|
+
end
|
113
|
+
@binding
|
114
|
+
end
|
115
|
+
|
116
|
+
def prompt
|
117
|
+
@text_ctrl.append_text(">> ")
|
118
|
+
@text_ctrl.move_end
|
119
|
+
@line_start = @text_ctrl.get_caret_position + 1
|
120
|
+
@text_ctrl.show_position(@line_start)
|
121
|
+
end
|
122
|
+
|
123
|
+
def print(str, color=Wx::BLACK)
|
124
|
+
start = @text_ctrl.get_caret_position
|
125
|
+
@text_ctrl.append_text(str)
|
126
|
+
stop = @text_ctrl.get_caret_position
|
127
|
+
@text_ctrl.set_style(start..stop, RichTextAttr.new(color))
|
128
|
+
end
|
129
|
+
|
130
|
+
def echo(str, color=Wx::BLACK)
|
131
|
+
print(str+"\n", color)
|
132
|
+
return nil
|
133
|
+
end
|
134
|
+
|
135
|
+
def ls(pattern = "*")
|
136
|
+
match = Dir[pattern]
|
137
|
+
print(match.join("\n") + "\n")
|
138
|
+
return nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def geometry
|
142
|
+
@app.geometry
|
143
|
+
end
|
144
|
+
|
145
|
+
def set_geometry(geom)
|
146
|
+
if geom.is_a? Aims::Geometry
|
147
|
+
puts "All Good"
|
148
|
+
@app.show_geometry(GeometryFile.new(geom))
|
149
|
+
else
|
150
|
+
echo("Not a valid geometry object")
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module AimsProject
|
2
|
+
|
3
|
+
class GeometryEditor < Wx::ScrolledWindow
|
4
|
+
|
5
|
+
include Wx
|
6
|
+
attr_accessor :app, :text_ctrl, :button_panel
|
7
|
+
|
8
|
+
@atom_ranges = {}
|
9
|
+
|
10
|
+
def initialize(app, window)
|
11
|
+
|
12
|
+
super(window)
|
13
|
+
|
14
|
+
@app = app
|
15
|
+
|
16
|
+
sizer = BoxSizer.new(VERTICAL)
|
17
|
+
|
18
|
+
@text_ctrl = StyledTextCtrl.new(self)
|
19
|
+
# @text_ctrl.set_sel_background(true, Colour.new("wheat"))
|
20
|
+
|
21
|
+
# Create the button panel (A toolbar for the top of this panel)
|
22
|
+
@button_panel = HBoxSizer.new
|
23
|
+
|
24
|
+
basedir = File.dirname(__FILE__)
|
25
|
+
arrow_icon = Image.new(File.join(basedir,"green_arrow.jpg"), BITMAP_TYPE_JPEG)
|
26
|
+
@eval_button = BitmapButton.new(self, :bitmap => arrow_icon.rescale(16,15).convert_to_bitmap,:style=>BU_EXACTFIT, :name => "evaluate")
|
27
|
+
|
28
|
+
@button_panel.add_item(@eval_button,3)
|
29
|
+
|
30
|
+
sizer.add_item(@button_panel, :flag => EXPAND)
|
31
|
+
sizer.add_item(@text_ctrl, :proportion => 1, :flag => EXPAND | ALL, :border => 5)
|
32
|
+
|
33
|
+
set_auto_layout(true)
|
34
|
+
set_sizer(sizer)
|
35
|
+
|
36
|
+
evt_button(@eval_button) {|event|
|
37
|
+
self.evaluate
|
38
|
+
}
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# Apply the edits to the geometry_file and evaluate
|
43
|
+
def evaluate
|
44
|
+
|
45
|
+
@unit_cell.raw_input = @text_ctrl.get_text
|
46
|
+
begin
|
47
|
+
@unit_cell.evaluate
|
48
|
+
rescue
|
49
|
+
# @button_pane.add_item(@clear_errors_button, 3)
|
50
|
+
@app.display_exception($!)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def unit_cell=(uc)
|
55
|
+
@unit_cell = uc
|
56
|
+
@text_ctrl.set_text(@unit_cell.input_geometry)
|
57
|
+
end
|
58
|
+
|
59
|
+
def select_atom(atom)
|
60
|
+
selectionStyle = Wx::RichTextAttr.new(Wx::BLACK, Wx::Colour.new("YELLOW"))
|
61
|
+
|
62
|
+
pattern = atom.format_geometry_in
|
63
|
+
puts "GeometryEditor.select_atom: pattern=#{pattern}"
|
64
|
+
|
65
|
+
matchdata = self.text_ctrl.get_text.match(pattern)
|
66
|
+
if matchdata
|
67
|
+
lineStart = matchdata.begin(0)
|
68
|
+
lineEnd = matchdata.end(0)
|
69
|
+
# self.text_ctrl.set_style(lineStart...lineEnd, selectionStyle)
|
70
|
+
self.text_ctrl.goto_pos(lineStart)
|
71
|
+
self.text_ctrl.set_selection_start(lineStart)
|
72
|
+
self.text_ctrl.set_selection_end(lineEnd)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# Return the text contents of this control
|
78
|
+
# after evaluating it with ERB
|
79
|
+
def get_contents
|
80
|
+
ERB.new(@text_ctrl.get_value).result
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'observer'
|
3
|
+
|
4
|
+
module AimsProject
|
5
|
+
# The geometry model utilized by this application
|
6
|
+
class GeometryFile
|
7
|
+
|
8
|
+
include Observable
|
9
|
+
|
10
|
+
# Include Aims here to ensure that ERB will evaluate ruby
|
11
|
+
# without prefixing Aims:: when using the builtin binding.
|
12
|
+
include Aims
|
13
|
+
|
14
|
+
# Read and parse a geometry file. Use the given binding to
|
15
|
+
# evaluate any embedded ruby
|
16
|
+
def GeometryFile.eval_geometry(str, _binding=nil)
|
17
|
+
|
18
|
+
b = if _binding
|
19
|
+
_binding
|
20
|
+
else
|
21
|
+
binding()
|
22
|
+
end
|
23
|
+
|
24
|
+
erb = ERB.new(str)
|
25
|
+
erb.result(b)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# The filename of the geometry file
|
30
|
+
attr_reader :file
|
31
|
+
|
32
|
+
# The Aims::Geometry object
|
33
|
+
attr_reader :aims_geometry
|
34
|
+
|
35
|
+
# The string representation of the parsed input geometry
|
36
|
+
attr_reader :input_geometry
|
37
|
+
|
38
|
+
# The raw unevaluated input.
|
39
|
+
attr_reader :raw_input
|
40
|
+
|
41
|
+
# Parse a geometry input
|
42
|
+
# Evaluate any embedded ruby using the given binding
|
43
|
+
# @param input If input is a File, the file is read and evaluated with ERB
|
44
|
+
# If input is a String, the input is directly evaluated with ERB
|
45
|
+
# @param _binding The binding to use when evaluating with EB
|
46
|
+
def initialize(input = nil, _binding=nil)
|
47
|
+
|
48
|
+
if input.nil?
|
49
|
+
@raw_input = ""
|
50
|
+
@input_geometry = ""
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
if input.respond_to? :read
|
55
|
+
@file = input
|
56
|
+
@raw_input = @file.read
|
57
|
+
elsif input.is_a? String
|
58
|
+
@raw_input = input
|
59
|
+
elsif input.is_a? Aims::Geometry
|
60
|
+
@aims_geometry = input
|
61
|
+
@input_geometry = @aims_geometry.format_geometry_in
|
62
|
+
@raw_input = @input_geometry
|
63
|
+
end
|
64
|
+
|
65
|
+
begin
|
66
|
+
# Attempt to evaluate the raw input, but don't require it.
|
67
|
+
@binding = _binding
|
68
|
+
evaluate(@binding)
|
69
|
+
rescue
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Set the raw input
|
74
|
+
# @param str The string to set the raw input to
|
75
|
+
# @param notify Whether or not to notify observer. Set this to false if you intend to call evaluate immediately after
|
76
|
+
def raw_input=(str)
|
77
|
+
@raw_input = str
|
78
|
+
end
|
79
|
+
|
80
|
+
# Evaluate the raw input and return a geometry String formatted in the Aims geometry.in format
|
81
|
+
#
|
82
|
+
def evaluate(_binding=nil)
|
83
|
+
if _binding
|
84
|
+
@binding = _binding
|
85
|
+
end
|
86
|
+
|
87
|
+
@input_geometry = GeometryFile.eval_geometry(@raw_input, @binding)
|
88
|
+
@aims_geometry = GeometryParser.parse_string(@input_geometry)
|
89
|
+
|
90
|
+
changed
|
91
|
+
notify_observers
|
92
|
+
|
93
|
+
@aims_geometry
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Delegate calls to the Aims::Geometry object if it exists.
|
98
|
+
def method_missing(symbol, *args, &block)
|
99
|
+
if @aims_geometry.nil?
|
100
|
+
raise GeometryEvaluationException.new
|
101
|
+
else
|
102
|
+
@aims_geometry.send(symbol, *args, &block)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Check the consistency between the raw, the evaluated and the object-space geometries
|
107
|
+
def is_valid?
|
108
|
+
begin
|
109
|
+
validate
|
110
|
+
return true
|
111
|
+
rescue Exception => e
|
112
|
+
return false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Check the consistency of all internal data models
|
117
|
+
# @return true, otherwise raises a GeoemtryValidationException
|
118
|
+
def validate
|
119
|
+
# The raw input evaluated must match the input_geometry
|
120
|
+
erb = ERB.new(@raw_input)
|
121
|
+
res = erb.result(@binding)
|
122
|
+
unless res == @input_geometry
|
123
|
+
raise GeometryValidationException.new("raw input doesn't match evaluated input")
|
124
|
+
end
|
125
|
+
|
126
|
+
# Also need to somehow validate against the Aims::Geometry
|
127
|
+
g = GeometryParser.parse_string(res)
|
128
|
+
unless g.atoms.size == @aims_geometry.atoms.size
|
129
|
+
raise GeometryValidationException("input geometry atom count doesn't match aims_geometry")
|
130
|
+
end
|
131
|
+
|
132
|
+
unless g.lattice_vectors.size == @aims_geometry.lattice_vectors.size
|
133
|
+
raise GeometryValidationException("input geometry lattice vector count doesn't match aims_geometry")
|
134
|
+
end
|
135
|
+
|
136
|
+
g.atoms.each{|a|
|
137
|
+
unless @aims_geometry.atoms.member?(a)
|
138
|
+
raise GeometryValidationException("atom mismatch")
|
139
|
+
end
|
140
|
+
}
|
141
|
+
|
142
|
+
g.lattice_vectors.each{|v|
|
143
|
+
unless @aims_geometry.lattice_vectors.member?(v)
|
144
|
+
raise GeometryValidationException("lattice vector mismatch")
|
145
|
+
end
|
146
|
+
}
|
147
|
+
|
148
|
+
return true
|
149
|
+
end
|
150
|
+
|
151
|
+
# Save this geometry
|
152
|
+
# raises an InvalidFilenameException unless @file is not nil
|
153
|
+
# @return self
|
154
|
+
def save
|
155
|
+
save_as(@file)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Save the raw input to file if it passes validation
|
159
|
+
# raises an InvalidFilenameException unless @file is not nil
|
160
|
+
# raises a GeometryValidationException if it fails to pass Validation
|
161
|
+
# @return A new GeometryFile object representing the geometry in the newly created file
|
162
|
+
# or this GeometryFile object if file = nil
|
163
|
+
def save_as(file)
|
164
|
+
|
165
|
+
if file.nil?
|
166
|
+
raise InvalidFilenameException(nil) unless @file
|
167
|
+
file = @file
|
168
|
+
end
|
169
|
+
|
170
|
+
# validate
|
171
|
+
|
172
|
+
File.open(file, 'w') {|f|
|
173
|
+
f.write @raw_input
|
174
|
+
}
|
175
|
+
|
176
|
+
return self
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module AimsProject
|
2
|
+
|
3
|
+
class GeometryWindow < Wx::Panel
|
4
|
+
|
5
|
+
include Wx
|
6
|
+
|
7
|
+
attr_accessor :update_unit_cell
|
8
|
+
|
9
|
+
def initialize(app, parent)
|
10
|
+
|
11
|
+
super(parent)
|
12
|
+
@app = app
|
13
|
+
|
14
|
+
# Initialize the selection of atoms
|
15
|
+
@selection = {}
|
16
|
+
|
17
|
+
# Tracks whether changes in inspector should update the unit cell
|
18
|
+
@update_unit_cell = false
|
19
|
+
|
20
|
+
# Get an inspector window to add into
|
21
|
+
@inspector_window = @app.inspector.add_inspector_window
|
22
|
+
|
23
|
+
# This is a model/controller for the inspector to pass to the crystal viewer
|
24
|
+
@options = CrystalViewerOptions.new(@inspector_window)
|
25
|
+
|
26
|
+
# Top level is a splitter
|
27
|
+
topSplitterWindow = SplitterWindow.new(self)
|
28
|
+
sizer = VBoxSizer.new
|
29
|
+
sizer.add_item(topSplitterWindow, :proportion => 1, :flag => EXPAND)
|
30
|
+
|
31
|
+
set_sizer(sizer)
|
32
|
+
@console = GeometryConsole.new(self, topSplitterWindow)
|
33
|
+
|
34
|
+
# The bottom is a vertical splitter
|
35
|
+
geomWindowSplitter = SplitterWindow.new(topSplitterWindow)
|
36
|
+
@geomEditor = GeometryEditor.new(self, geomWindowSplitter)
|
37
|
+
@geomViewer = CrystalViewer.new(self, geomWindowSplitter, @options)
|
38
|
+
|
39
|
+
geomWindowSplitter.split_vertically(@geomEditor, @geomViewer)
|
40
|
+
|
41
|
+
# Add top and bottom sides together
|
42
|
+
topSplitterWindow.split_horizontally(geomWindowSplitter, @console, -100)
|
43
|
+
layout
|
44
|
+
|
45
|
+
# Define events
|
46
|
+
evt_list_item_selected(@console) {|evt|
|
47
|
+
open_geometry_file(evt.get_item.get_data)
|
48
|
+
}
|
49
|
+
|
50
|
+
show_geometry(GeometryFile.new)
|
51
|
+
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def show_inspector
|
57
|
+
@app.inspector.show_inspector_window(@inspector_window)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Display a file dialog and attempt to open and display the file
|
61
|
+
def open_geometry_file(file = nil)
|
62
|
+
begin
|
63
|
+
unless file
|
64
|
+
fd = FileDialog.new(@app.frame, :message => "Open", :style => FD_OPEN, :default_dir => @working_dir)
|
65
|
+
if ID_OK == fd.show_modal
|
66
|
+
file = fd.get_path
|
67
|
+
@working_dir = fd.get_directory
|
68
|
+
else
|
69
|
+
return
|
70
|
+
end
|
71
|
+
end
|
72
|
+
@app.set_status "Opening #{file}"
|
73
|
+
|
74
|
+
if (@app.project)
|
75
|
+
show_geometry GeometryFile.new(File.new(file), @app.project.get_binding)
|
76
|
+
else
|
77
|
+
show_geometry GeometryFile.new(File.new(file))
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
rescue Exception => dang
|
82
|
+
@app.error_dialog(dang)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def image
|
87
|
+
@geomViewer.image
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get the currently displayed geometry
|
91
|
+
def geometry
|
92
|
+
@original_uc
|
93
|
+
end
|
94
|
+
|
95
|
+
# Display the given geometry
|
96
|
+
def show_geometry(geometry)
|
97
|
+
begin
|
98
|
+
@original_uc = geometry
|
99
|
+
@geomViewer.unit_cell = @original_uc
|
100
|
+
rescue AimsProjectException => e
|
101
|
+
@app.error_dialog(e)
|
102
|
+
ensure
|
103
|
+
@geomEditor.unit_cell = @original_uc
|
104
|
+
end
|
105
|
+
# @inspector.update(@geomViewer)
|
106
|
+
# @geomViewer.draw_scene
|
107
|
+
end
|
108
|
+
|
109
|
+
def select_atom(atom)
|
110
|
+
@selection[:atoms] = [atom]
|
111
|
+
puts "Selection:"
|
112
|
+
puts @selection[:atoms].each{|a| puts a.format_geometry_in}
|
113
|
+
@geomEditor.select_atom(atom)
|
114
|
+
@console.echo(atom.to_s)
|
115
|
+
end
|
116
|
+
|
117
|
+
def nudge_selected_atoms(x,y,z)
|
118
|
+
if @selection[:atoms]
|
119
|
+
@selection[:atoms].each{|a| a.displace!(x,y,z)}
|
120
|
+
end
|
121
|
+
@geomViewer.draw_scene
|
122
|
+
@geomEditor.update
|
123
|
+
end
|
124
|
+
|
125
|
+
def display_exception(e)
|
126
|
+
@console.print(e.message, Wx::RED)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Apply UI settings to viewer and re-render
|
130
|
+
def update_viewer
|
131
|
+
|
132
|
+
puts "GeometryWindow.update_viewer"
|
133
|
+
|
134
|
+
if @original_uc and self.update_unit_cell
|
135
|
+
if @correct.get_value
|
136
|
+
# @geomViewer.unit_cell = @original_uc.correct
|
137
|
+
new_geom = @original_uc.repeat(@x_repeat.get_value, @y_repeat.get_value, @z_repeat.get_value).correct
|
138
|
+
else
|
139
|
+
# @geomViewer.unit_cell = @original_uc
|
140
|
+
new_geom = @original_uc.repeat(@x_repeat.get_value, @y_repeat.get_value, @z_repeat.get_value)
|
141
|
+
end
|
142
|
+
@geomViewer.unit_cell = new_geom
|
143
|
+
@geomEditor.unit_cell = new_geom
|
144
|
+
self.update_unit_cell = false
|
145
|
+
end
|
146
|
+
|
147
|
+
# @geomViewer.repeat = [@inspector.x_repeat, @inspector.y_repeat, @inspector.z_repeat]
|
148
|
+
@geomViewer.show_bonds = @show_bonds.get_value
|
149
|
+
@geomViewer.bond_length = @bond_length.get_value
|
150
|
+
@geomViewer.lighting = @show_lighting.get_value
|
151
|
+
@geomViewer.show_supercell = @show_cell.get_value
|
152
|
+
@geomViewer.show_xclip = @show_xclip.get_value
|
153
|
+
@geomViewer.show_yclip = @show_yclip.get_value
|
154
|
+
@geomViewer.show_zclip = @show_zclip.get_value
|
155
|
+
@geomViewer.background.alpha = ((@transparent_bg.get_value) ? 0 : 1)
|
156
|
+
@geomViewer.draw_scene
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
Binary file
|