aims_project 0.3.0

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.
Binary file
@@ -0,0 +1,183 @@
1
+ module AimsProject
2
+ class Inspector < Wx::Frame
3
+
4
+ include Wx
5
+
6
+ class << self
7
+ def control_value_accessor(*args)
8
+ args.each do |cb|
9
+ class_eval <<-EOS
10
+ def #{cb.to_s}
11
+ @#{cb.to_s}.get_value
12
+ end
13
+ EOS
14
+ end
15
+ end
16
+ end
17
+
18
+ control_value_accessor :bond_length
19
+ control_value_accessor :show_bonds, :show_lighting, :show_cell
20
+ control_value_accessor :show_clip_planes, :show_xclip, :show_yclip, :show_zclip
21
+ control_value_accessor :x_repeat, :y_repeat, :z_repeat
22
+ control_value_accessor :correct
23
+ control_value_accessor :transparent_bg
24
+
25
+ attr_accessor :update_unit_cell
26
+
27
+ def initialize(app, frame)
28
+
29
+ super(frame, :style => (CLOSE_BOX | CAPTION | FRAME_FLOAT_ON_PARENT))
30
+
31
+ @app = app
32
+
33
+ # Array to track the inspector windows being shown
34
+ @windows = []
35
+
36
+ self.sizer = BoxSizer.new(VERTICAL)
37
+ set_auto_layout(true)
38
+ self.sizer.set_size_hints(self)
39
+ self.sizer.fit(self)
40
+
41
+ self.update_unit_cell = false
42
+ self.evt_close {|event| self.hide }
43
+ end
44
+
45
+ # Create a window to show in the inspector. Default is to not show this window.
46
+ # call show_inspector_window() to show it
47
+ # options are Wx:Sizer options
48
+ # return the window so that caller can add controls to it
49
+ def add_inspector_window(options = {})
50
+ window = Panel.new(self)
51
+ @windows << window
52
+ self.sizer.add_item(window, options)
53
+ self.sizer.show(window, false)
54
+ return window
55
+ end
56
+
57
+ # Show the inspector window
58
+ def show_inspector_window(window)
59
+ @windows.each {|w|
60
+ self.sizer.show(w, w == window)
61
+ }
62
+ self.sizer.fit(self)
63
+ end
64
+
65
+ # The view options
66
+ def view_options_panel(parent)
67
+
68
+ # Default padding around each element
69
+ border = 5
70
+
71
+ panel = Wx::VBoxSizer.new
72
+ parent.sizer = panel
73
+
74
+ # Panel 1
75
+ panel1 = Wx::VBoxSizer.new
76
+
77
+ @show_bonds = Wx::CheckBox.new(parent, :label => 'Show Bonds')
78
+ panel1.add_item(@show_bonds, :flag => ALL,:border => border)
79
+
80
+ @show_lighting = Wx::CheckBox.new(parent, :label => 'Show Lighting')
81
+ panel1.add_item(@show_lighting, :flag => ALL, :border => border)
82
+
83
+ @show_cell = Wx::CheckBox.new(parent, :label => "Show Unit Cell")
84
+ panel1.add_item(@show_cell, :flag => ALL, :border => border)
85
+
86
+ @correct = Wx::CheckBox.new(parent, :label => "Correct Geometry")
87
+ panel1.add_item(@correct, :flag => ALL, :border => border)
88
+
89
+ @transparent_bg = Wx::CheckBox.new(parent, :label => "Transparent BG")
90
+ panel1.add_item(@transparent_bg, :flag => ALL, :border => border)
91
+
92
+ gsizer = GridSizer.new(2,1)
93
+ gsizer.add(StaticText.new(parent, :label => "Bond Length"))
94
+ @bond_length = SpinCtrl.new(parent, :min => 1, :max => 100, :value => "4")
95
+ gsizer.add_item(@bond_length, :flag => EXPAND)
96
+ panel1.add_item(gsizer)
97
+
98
+ evt_checkbox(@show_bonds) {|evt| @app.update_viewer}
99
+ evt_checkbox(@show_lighting) {|evt| @app.update_viewer}
100
+ evt_checkbox(@show_cell) {|evt| @app.update_viewer}
101
+ evt_checkbox(@transparent_bg) {|evt| @app.update_viewer}
102
+ evt_checkbox(@correct) {|evt|
103
+ self.update_unit_cell = true
104
+ @app.update_viewer
105
+ }
106
+ evt_spinctrl(@bond_length) {|evt| @app.update_viewer }
107
+
108
+ # Panel 2 : Clip Planes
109
+ panel2 = Wx::VBoxSizer.new
110
+ panel2.add_item(StaticText.new(parent, -1, "Clip Planes:", :style => ALIGN_LEFT))
111
+ @show_xclip = Wx::CheckBox.new(parent, :label => 'x')
112
+ panel2.add_item(@show_xclip, 0, Wx::ALIGN_CENTER, border)
113
+ @show_yclip = Wx::CheckBox.new(parent, :label => 'y')
114
+ panel2.add_item(@show_yclip, 0, Wx::ALIGN_CENTER, border)
115
+ @show_zclip = Wx::CheckBox.new(parent, :label => 'z')
116
+ panel2.add_item(@show_zclip, 0, Wx::ALIGN_CENTER, border)
117
+
118
+
119
+ evt_checkbox(@show_xclip) {|evt| @app.update_viewer}
120
+ evt_checkbox(@show_yclip) {|evt| @app.update_viewer}
121
+ evt_checkbox(@show_zclip) {|evt| @app.update_viewer}
122
+
123
+ # Panel 3: Repeat
124
+ panel3 = Wx::VBoxSizer.new
125
+ panel3.add_item(StaticText.new(parent, -1, "Repeat:", :style => ALIGN_LEFT), 0, EXPAND)
126
+
127
+ panel3grid = GridSizer.new(3,2, border, border)
128
+
129
+ @x_repeat = Wx::SpinCtrl.new(parent, :value => "1", :min => 1, :max => 100, :initial => 1)
130
+ @y_repeat = Wx::SpinCtrl.new(parent, :value => "1", :min => 1, :max => 100, :initial => 1)
131
+ @z_repeat = Wx::SpinCtrl.new(parent, :value => "1", :min => 1, :max => 100, :initial => 1)
132
+
133
+ evt_spinctrl(@x_repeat) {|evt|
134
+ self.update_unit_cell = true
135
+ @app.update_viewer
136
+ }
137
+ evt_spinctrl(@y_repeat) {|evt|
138
+ self.update_unit_cell = true
139
+ @app.update_viewer
140
+ }
141
+ evt_spinctrl(@z_repeat) {|evt|
142
+ self.update_unit_cell = true
143
+ @app.update_viewer
144
+ }
145
+
146
+ panel3grid.add(StaticText.new(parent, :label => "x", :style => ALIGN_RIGHT),1, EXPAND)
147
+ panel3grid.add(@x_repeat,2)
148
+
149
+ panel3grid.add(StaticText.new(parent, :label => "y",:style => ALIGN_RIGHT),1, EXPAND)
150
+ panel3grid.add(@y_repeat,2)
151
+
152
+ panel3grid.add(StaticText.new(parent, :label => "z",:style => ALIGN_RIGHT),1, EXPAND)
153
+ panel3grid.add(@z_repeat,2)
154
+
155
+ panel3.add(panel3grid, 0, EXPAND | ALIGN_CENTER)
156
+
157
+ # Add sub-panels
158
+ panel.add(panel1, 0, Wx::ALL)
159
+ panel.add_spacer(5)
160
+ panel.add(panel2, 0, Wx::EXPAND)
161
+ panel.add_spacer(5)
162
+ panel.add(panel3, 0, Wx::EXPAND)
163
+
164
+
165
+ end
166
+
167
+ # Called when a new file is loaded
168
+ def update(viewer)
169
+ @show_bonds.set_value(viewer.show_bonds)
170
+ @show_lighting.set_value(viewer.lighting)
171
+ @show_cell.set_value(viewer.show_supercell)
172
+ @correct.set_value(false)
173
+ @show_xclip.set_value(viewer.show_xclip)
174
+ @show_yclip.set_value(viewer.show_yclip)
175
+ @show_zclip.set_value(viewer.show_zclip)
176
+ @bond_length.set_value(viewer.bond_length)
177
+ @x_repeat.set_value(1)
178
+ @y_repeat.set_value(1)
179
+ @z_repeat.set_value(1)
180
+ end
181
+
182
+ end
183
+ end
@@ -0,0 +1,30 @@
1
+ module AimsProject
2
+ class Material
3
+
4
+ include Gl
5
+
6
+ attr_accessor :r, :g, :b, :alpha
7
+
8
+ def Material.black
9
+ Material.new(0,0,0)
10
+ end
11
+
12
+ def initialize(r,g,b,alpha=1)
13
+ self.r = r
14
+ self.g = g
15
+ self.b = b
16
+ self.alpha = alpha
17
+ end
18
+
19
+ def apply(lighting = true)
20
+ if lighting
21
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, [self.r, self.g, self.b, self.alpha])
22
+ glMaterialfv(GL_FRONT, GL_SPECULAR, [self.r, self.g, self.b, self.alpha])
23
+ glMaterialf(GL_FRONT, GL_SHININESS, 50)
24
+ else
25
+ glColor3f(self.r, self.g, self.b)
26
+ end
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,5 @@
1
+ module AimsProject
2
+ class Octree
3
+
4
+ end
5
+ end
Binary file
@@ -0,0 +1,102 @@
1
+ require 'fileutils'
2
+
3
+ module AimsProject
4
+
5
+ class Project
6
+
7
+ # A project is a collection of calculations
8
+ # and tools for managing the execution and analysis of the calculations
9
+
10
+ # The name of this project
11
+ attr_accessor :name
12
+
13
+ # Load a Project from the serialized yaml file
14
+ def Project.load(filename)
15
+ yamlfile = [filename, filename+".yaml"].find{|f| File.exists?(f)}
16
+
17
+ File.open(yamlfile, 'r') do |f|
18
+ YAML.load(f)
19
+ end
20
+ end
21
+
22
+ # Create a new Project with the given name
23
+ # This will also create the directory structure
24
+ # for the project. Returns true if successful, false otherwise
25
+ def Project.create(name)
26
+
27
+ return nil unless name
28
+
29
+ p = Project.new(name)
30
+
31
+ # Create the project directory
32
+ FileUtils.mkdir(p.relative_path)
33
+ p.save(p.relative_path)
34
+ #
35
+ # # Create the config directory
36
+ # FileUtils.mkdir(File.join(p.relative_path, "config"))
37
+ #
38
+ # # Create the geometry directory
39
+ # FileUtils.mkdir(File.join(p.relative_path, AimsProject::GEOMETRY_DIR))
40
+ #
41
+ # # Create the control directory
42
+ # FileUtils.mkdir(File.join(p.relative_path, AimsProject::CONTROL_DIR))
43
+ #
44
+ # # Create the calculations directory
45
+ # FileUtils.mkdir(File.join(p.relative_path, AimsProject::CALCULATION_DIR))
46
+
47
+ return p
48
+ end
49
+
50
+ # Initialize a new project object with the given name.
51
+ # This does not create the project directory structure, use create for that.
52
+ def initialize(name)
53
+ self.name = name
54
+ end
55
+
56
+ # Return the binding for this project
57
+ def get_binding
58
+ binding
59
+ end
60
+
61
+ # The path of this project relative to project_root_dir
62
+ def relative_path
63
+ name
64
+ end
65
+
66
+ # The filename of the serialized yaml file representing this project
67
+ def serialized_filename
68
+ "#{self.name}.yaml"
69
+ end
70
+
71
+ # The full path to this project locally
72
+ def full_path
73
+ File.dirname(File.expand_path(serialized_filename))
74
+ end
75
+
76
+ # Serialize this project to a yaml file named after this project
77
+ # in the given directory
78
+ def save(dir = ".")
79
+ File.open(File.join(dir, "#{name}.yaml"), 'w') do |f|
80
+ f.print YAML.dump(self)
81
+ end
82
+ end
83
+
84
+ # Retreive the calcluations managed by this project.
85
+ # This array is loaded directly from serialized yaml
86
+ # files in each calculation directory
87
+ def calculations
88
+ calc_status_files = Dir.glob(File.join(AimsProject::CALCULATION_DIR, "*", AimsProject::CALC_STATUS_FILENAME))
89
+ # pick up sub-calculations
90
+ calc_status_files += Dir.glob(File.join(AimsProject::CALCULATION_DIR, "*", "*", AimsProject::CALC_STATUS_FILENAME))
91
+ calc_status_files.collect{|f|
92
+ Calculation.load(File.dirname(f))
93
+ }
94
+ end
95
+
96
+ # Retreive the geometries managed by this project.
97
+ def geometries
98
+ Dir.glob(File.join(AimsProject::GEOMETRY_DIR, "*"))
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,62 @@
1
+ module AimsProject
2
+
3
+ class ProjectTree < Wx::ScrolledWindow
4
+
5
+ include Wx
6
+
7
+ ROOT = "Root"
8
+ GEOMETRY = "Geometry"
9
+ CONTROL = "Control"
10
+ CALCULATIONS = "Calculations"
11
+
12
+
13
+ attr_accessor :app, :treeControl
14
+
15
+ def initialize(app, window)
16
+ super(window)
17
+ self.app = app
18
+
19
+ init_project_tree
20
+
21
+ sizer = BoxSizer.new(VERTICAL)
22
+ sizer.add(self.treeControl, 1, EXPAND | ALL, 5)
23
+
24
+ set_auto_layout(true)
25
+ set_sizer(sizer)
26
+ end
27
+
28
+ def init_project_tree
29
+ @treeControl = Wx::TreeCtrl.new(self)
30
+ @tree_map = {}
31
+ if self.app.project
32
+ @tree_map[ROOT] = self.treeControl.add_root(self.app.project.name)
33
+ @tree_map[GEOMETRY] = self.treeControl.append_item(@tree_map[ROOT], GEOMETRY)
34
+ @tree_map[CONTROL] = self.treeControl.append_item(@tree_map[ROOT], CONTROL)
35
+ @tree_map[CALCULATIONS] = self.treeControl.append_item(@tree_map[ROOT], CALCULATIONS)
36
+
37
+ self.app.project.geometries.each{|geom|
38
+ self.treeControl.append_item(@tree_map[GEOMETRY], geom)
39
+ }
40
+
41
+ self.app.project.calculations.each{|calc|
42
+ calcid = self.treeControl.append_item(@tree_map[CALCULATIONS], calc.name)
43
+ @tree_map[calcid] = calc
44
+ }
45
+
46
+ evt_tree_sel_changed(self.treeControl) {|evt|
47
+ itemid = evt.get_item
48
+ if @tree_map[GEOMETRY] == self.treeControl.get_item_parent(itemid)
49
+ self.app.open_file(self.treeControl.get_item_text(itemid))
50
+ elsif @tree_map[CALCULATIONS] == self.treeControl.get_item_parent(itemid)
51
+ calc = @tree_map[itemid]
52
+ self.app.show_calculation(calc)
53
+ end
54
+ }
55
+ else
56
+ @tree_map[ROOT] = self.treeControl.add_root(ROOT)
57
+ end
58
+ @treeControl.expand(@tree_map[ROOT])
59
+ end
60
+
61
+ end
62
+ end
Binary file
@@ -0,0 +1,19 @@
1
+ module AimsProject
2
+ class ThreadCallbackEvent < Wx::CommandEvent
3
+
4
+ @@event_type_id = 0
5
+
6
+ def ThreadCallbackEvent.set_event_type(id)
7
+ @@event_type_id = id
8
+ end
9
+
10
+ def ThreadCallbackEvent.event_type
11
+ @@event_type_id
12
+ end
13
+
14
+ def initialize
15
+ super(@@event_type_id)
16
+ end
17
+
18
+ end
19
+ end
Binary file
data/skeleton/Capfile ADDED
@@ -0,0 +1,37 @@
1
+ require 'aims_project'
2
+
3
+ load 'config/tasks.rb'
4
+
5
+ # The name of this project
6
+ set :project_name, '__PROJECT_NAME__'
7
+
8
+ # The following settings apply to calculations occuring on the remote host
9
+
10
+ # The base directory on the remote host
11
+ set :remote_project_dir, 'AimsProjects'
12
+
13
+ # Query the user for the number of parallel nodes when queueing calculations
14
+ set(:nodes) {Capistrano::CLI.ui.ask("How many compute nodes?: ")}
15
+
16
+ # The memory for each calculation
17
+ set :memory, 1024
18
+
19
+ # The time limit for each calculation
20
+ set :time, 24
21
+
22
+ # Set the qstat command
23
+ set :qstat_cmd, "qstat -u jns"
24
+
25
+ # The qsub command to execute
26
+ # There are some extra commands in here to forward SIGUSR1 and SIGUSR2 to aims_script
27
+ # so that the job status can be properly updated if the job is aborted
28
+ # aims_script is predefined to be 'aims.sh', if this is unsuitable
29
+ # it can be reset with: set :aims_script, 'foo'
30
+ set(:qsub) {
31
+ "parallel.q -n #{nodes} -d #{memory} -t #{time} -ns -k #{aims_script}; sed '/\\btime\\b/ i\\ trap : SIGUSR1 SIGUSR2' #{aims_script}.cmd > #{aims_script}.cmd.new; mv #{aims_script}.cmd.new #{aims_script}.cmd; qsub -notify #{aims_script}.cmd"
32
+ }
33
+
34
+ # The remote host for data transfer of large files
35
+ role :data_transfer, "Your Data Transfer Server Here"
36
+ # The remote host for job submission
37
+ role :queue_submission, "Your Compute Cluster Server Here"