OSDN Git Service

'show ortep' command is being implemented (not complete yet)
authortoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Mon, 10 Mar 2014 11:09:03 +0000 (11:09 +0000)
committertoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Mon, 10 Mar 2014 11:09:03 +0000 (11:09 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@451 a2be9bc6-48de-4e38-9406-05402d4bc13c

Scripts/crystal.rb
Scripts/startup.rb

index c74e5fe..bd4c054 100755 (executable)
@@ -1208,6 +1208,99 @@ def create_packing_diagram
   }
 end
 
+def cmd_show_ortep
+  mol = self
+  tmp = create_temp_dir("ortep", mol.name)
+  tepexe = "#{ResourcePath}/ortep3/ortep3"
+  if $platform == "win"
+    tepexe += ".exe"
+  end
+  tepdata = []
+  tepbounds = [0, 0, 400, 400]
+  Dialog.new("Show ORTEP:" + mol.name, nil, nil, :resizable=>true, :has_close_box=>true) {
+    tepview = nil  #  Forward declaration
+    on_update_ortep = lambda { |it|
+         #  Create ORTEP input in the temporary directory
+         open(tmp + "/TEP.IN", "w") { |fp| mol.export_ortep(fp) }
+         #  Run ORTEP
+         cwd = Dir.pwd
+         Dir.chdir(tmp)
+         if FileTest.exist?("TEP001.PRN")
+           File.unlink("TEP001.PRN")
+         end
+         pid = call_subprocess(tepexe, "Running ORTEP", nil, "NUL", "NUL")
+         if FileTest.exist?("TEP001.PRN")
+           File.rename("TEP001.PRN", "TEP001.ps")
+         end
+         Dir.chdir(cwd)
+         if pid != 0
+           msg = "ORTEP execution in #{tmp} failed with status #{pid}."
+           message_box(msg, "ORTEP Failed", :ok, :warning)
+         else
+           open(tmp + "/TEP001.ps", "r") { |fp|
+                 tepdata.clear
+                 tepbounds = [100000, 100000, -100000, -100000]
+                 fp.each_line { |ln|
+                   ln.chomp!
+                   x, y, c = ln.split
+                       x = x.to_i
+                       y = y.to_i
+                       if c == "m"
+                         tepdata.push([x, y])
+                       elsif c == "l"
+                         tepdata[-1].push(x, y)
+                       else
+                         next
+                       end
+                       tepbounds[0] = x if x < tepbounds[0]
+                       tepbounds[1] = y if y < tepbounds[1]
+                       tepbounds[2] = x if x > tepbounds[2]
+                       tepbounds[3] = y if y > tepbounds[3]
+                 }
+               }
+               tepview.refresh_rect(tepview[:frame])
+         end
+       }
+       on_draw_ortep = lambda { |it|
+         clear
+         frame = it[:frame]
+         rx = (frame[2] - 10.0) / (tepbounds[2] - tepbounds[0])
+         ry = (frame[3] - 10.0) / (tepbounds[3] - tepbounds[1])
+         rx = ry if rx > ry
+         dx = (frame[2] - (tepbounds[2] - tepbounds[0]) * rx) * 0.5
+         dy = (frame[3] + (tepbounds[3] - tepbounds[1]) * rx) * 0.5
+         tepdata.each { |d|
+           x0 = (dx + (d[0] - tepbounds[0]) * rx).to_i
+               y0 = (dy - (d[1] - tepbounds[1]) * rx).to_i
+               (d.length / 2 - 1).times { |i|
+                 x1 = (dx + (d[i * 2 + 2] - tepbounds[0]) * rx).to_i
+                 y1 = (dy - (d[i * 2 + 3] - tepbounds[1]) * rx).to_i
+                 draw_line(x0, y0, x1, y1)
+                 x0 = x1
+                 y0 = y1
+               }
+         }
+       }
+       @on_close = lambda { |*d|
+         puts "#{self}: on_close invoked"
+         cleanup_temp_dir(tmp)
+         tmp = nil
+         true
+       }
+       layout(1,
+         item(:view, :width=>400, :height=>400, :tag=>"ortep", :on_paint=>on_draw_ortep, :flex=>[0,0,0,0,1,1]),
+         layout(2,
+           item(:button, :title=>"Refresh", :action=>on_update_ortep, :align=>:left),
+               -1,
+               :flex=>[0,1,0,0,1,0]),
+         :flex=>[0,0,0,0,1,1])
+       tepview = item_with_tag("ortep")
+       listen(mol, "documentWillClose", :close )
+    on_update_ortep.call(nil)
+       show
+  }
+end
+
 if lookup_menu("Best-fit Planes...") < 0
   register_menu("", "")
   register_menu("Best-fit Planes...", :cmd_plane)
index 31e5bf5..d94d126 100755 (executable)
@@ -84,6 +84,64 @@ module Kernel
       return Dir.mkdir(path)
        end
   end
+  def create_temp_dir(tag, name = nil)
+    #  Create a temporary directory like HomeDirectory/Molby/tag/name.xxxxxx
+       name ||= "temp"
+       base = $home_directory + "/Molby/" + tag
+       mkdir_recursive(base)
+       10000.times { |n|
+         p = sprintf("%s/%s.%05d", base, name, n)
+         if !FileTest.exist?(p)
+           Dir.mkdir(p)
+               return p
+         end
+       }
+       raise "Cannot create temporary directory in #{base}"
+  end
+  def rm_recursive(path)
+    if FileTest.directory?(path)
+         Dir.foreach(path) { |en|
+           next if en == "." || en == ".."
+               rm_recursive(path + "/" + en)
+         }
+         Dir.rmdir(path)
+       else
+         File.unlink(path)
+       end
+  end
+  def cleanup_temp_dir(path, option = nil)
+    #  Clean-up temporary directories
+       #  If option is nil, then the directory at path is removed
+       #  If option is a number, then the directories that are in the same parent directory as path
+       #  are removed except for the newest ones
+       if path.index($home_directory + "/Molby/") != 0
+         raise "Bad cleanup_temp_dir call: the path does not begin with $HOME/Molby/ (#{path})"
+       end
+       if !FileTest.directory?(path)
+         raise "Bad cleanup_temp_dir call: the path is not a directory (#{path})"
+       end
+       option = option.to_i
+       if option <= 0
+         rm_recursive(path)
+       else
+         base = File.dirname(path)
+         ent = Dir.entries.sort_by { |en| File.mtime("#{base}/#{en}").to_i * (-1) } - [".", ".."]
+         if $platform == "mac"
+           ent -= [".DS_Store"]
+         end
+         ent[0, option] = []  #  Remove newest #{option} entries
+         #  Mark this directory to be ready to remove (see below)
+         open("#{path}/.done", "w") { |fp| }
+         #  Remove the older directories
+         ent.each { |en|
+           #  Check the existence of ".done" file (otherwise, we may accidentarily remove a directory
+           #  that is still in use in other threads)
+           if File.exist?("#{base}/#{en}/.done")
+             rm_recursive("#{base}/#{en}")
+               end
+         }
+       end
+  end
 end
 
 class IO