lib/rubabel/molecule_data.rb in rubabel-0.1.0 vs lib/rubabel/molecule_data.rb in rubabel-0.1.1
- old
+ new
@@ -1,88 +1,177 @@
\ No newline at end of file
+require 'openbabel'
+
+module Rubabel
+ # A hash-like interface for dealing with tag data in molecules inspired by
+ # the MoleculeData implementation in pybel. This does not actually hash the
+ # data, it just reads it from the OBMol object each time and acts like a
+ # hash.
+ class MoleculeData
+ include Enumerable
+
+ OB_PAIR_DATA_TYPE = OpenBabel::OBPairData.new.get_data_type
+ OB_COMMENT_DATA_TYPE = OpenBabel::OBCommentData.new.get_data_type
+
+ DATA_TYPES = [OB_PAIR_DATA_TYPE, OB_COMMENT_DATA_TYPE]
+
+ attr_accessor :obmol
+
+ def initialize(obmol)
+ @obmol = obmol
+ end
+
+ def pair_data(&block)
+ block or return enum_for(__method__)
+ # TODO: should do this with an ob iterator
+ @obmol.get_data.each do |ob_gd|
+ if DATA_TYPES.include?( ob_gd.get_data_type )
+ block.call( OpenBabel.to_pair_data( ob_gd ) )
+ end
+ end
+ end
+
+ def each(&block)
+ block or return enum_for(__method__)
+ pair_data.each do |pd|
+ block.call [pd.get_attribute, pd.get_value]
+ end
+ end
+
+ def to_a
+ each.to_a
+ end
+
+ def size
+ pair_data.to_a.size
+ end
+ alias_method :length, :size
+
+ def [](key)
+ pair_data.find {|pd| pd.get_attribute == key }.get_value
+ end
+
+ # returns the val
+ def []=(key,val)
+ if key?(key)
+ OpenBabel.to_pair_data(@obmol.get_data(key)).set_value(val)
+ val
+ else
+ pd = OpenBabel::OBPairData.new
+ pd.set_attribute(key)
+ pd.set_value(val)
+ @obmol.clone_data(pd)
+ val
+ end
+ end
+
+ def key?(key)
+ pair_data.any? {|pd| pd.get_attribute == key }
+ end
+
+ def keys
+ pair_data.map(&:get_attribute)
+ end
+
+ def values
+ pair_data.map(&:get_value)
+ end
+
+ def delete(key, &block)
+ if key?(key)
+ val = self[key]
+ @obmol.delete_data( @obmol.get_data(key) )
+ val
+ else
+ block ? block.call : nil
+ end
+ end
+
+ end
+end