aims_project_windows 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|