YAML for serialization

One of the projects I’m working on for research has to deal with atomic potentials, or a way to try to describe the forces between atoms when they are in a certain configuration. The more realistic ones are fairly complicated functions.

One of the tricks in dealing with potentials is to try to plot some specific configurations, and see how the energy varies. ‘Wells’ represent stable points where atoms will tend to sit, while ‘humps’ are barriers between stable points that an atom must overcome somehow. The height of the hump gives you an idea of how stable the low points are.

Plotting one of these potentials is not super difficult, just looping over some positions and (in my case) outputting the positions and energies to a file, which is then plotted with gnuplot. One of the things I wanted to do, however, is to plot a bunch of variations with one of the parameters swept over a range of values. One way would be to create the potential as an object and modify the parameters that way. What I wanted to do, is have parameter file that I read in to setup the potential.

Enter YAML

It turns out that this is essentially built into ruby, through the YAML methods that are designed for marshaling objects over various communication methods between computers/processes. All you have to do is

require 'yaml' # you may not need this line
thing.to_yaml

and you get a string representation of the object. You can then save it to a file. After this, restoring the object is as simple as

YAML.load(string)

or

YAML.load_file(filename)

Even complicated things

One of the neatest things about this is that nested objects translate seamlessly with this. For example, I have to following files that I work with.

#atom.rb
class Atom
  attr_accessor :x, :y, :z

  def initialize
    @x = @y = @z = 0.0
  end

  def r_ij(atom_two)
    r_squared = (@x-atom_two.x)**2 + (@y-atom_two.y)**2 + (@z-atom_two.z)**2
    return Math.sqrt(r_squared)
  end
end

and

#molecule.rb
class Molecule
  attr_accessor :atoms
  def initialize
    @atoms = []
  end
end

which lets you do this

imac:~/code/ruby-yaml brian$ irb
irb(main):001:0> require 'atom'
=> true
irb(main):002:0> require 'molecule'
=> true
irb(main):003:0> require 'yaml'
=> true
irb(main):004:0> a = Atom.new
=> #<Atom:0x59e304 @x=0.0, @z=0.0, @y=0.0>
irb(main):005:0> a.x,a.y,a.z = [1.0,2.0,3.0]
=> [1.0, 2.0, 3.0]
irb(main):006:0> b = Atom.new
=> #<Atom:0x598774 @x=0.0, @z=0.0, @y=0.0>
irb(main):007:0> b.x,b.y,b.z = [4.0,5.0,6.0]
=> [4.0, 5.0, 6.0]
irb(main):008:0> m = Molecule.new
=> #<Molecule:0x592b08 @atoms=[]>
irb(main):009:0> m.atoms.push a
=> [#<Atom:0x59e304 @x=1.0, @z=3.0, @y=2.0>]
irb(main):010:0> m.atoms.push b
=> [#<Atom:0x59e304 @x=1.0, @z=3.0, @y=2.0>, 
    #<Atom:0x598774 @x=4.0, @z=6.0, @y=5.0>]
irb(main):011:0> print save = m.to_yaml
--- !ruby/object:Molecule 
atoms: 
- !ruby/object:Atom 
  x: 1.0
  y: 2.0
  z: 3.0
- !ruby/object:Atom 
  x: 4.0
  y: 5.0
  z: 6.0
=> nil
irb(main):013:0> new = YAML.load(save)
=> #<Molecule:0x586cf4 
           @atoms=[#<Atom:0x58726c @x=1.0, @z=3.0, @y=2.0>, 
                   #<Atom:0x586f38 @x=4.0, @z=6.0, @y=5.0>]>
irb(main):014:0>

YAML is plain text

From my perspective, the real advantage of doing this is having the output in a plain text file. I can then edit the text in an editor and tweak things this way. I can also markup the text and run it through a template engine and generate a whole bunch of files. This was part of the magic behind my rake example, where I generated 800 or so configurations in an hour or so, which was very cool.

Edit: tweaked the formatting in the irb section to see the code better

Advertisements

One Response to YAML for serialization

  1. Ian says:

    If you write a large amount of data with YAML, you might want to take a look here, for 1600% faster YAML.dump:

    http://gnomecoder.wordpress.com/2008/09/27/yaml-dump-1600-percent-faster/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: