[BioRuby-cvs] bioruby/lib/bio map.rb,NONE,1.1

Jan Aerts aerts at dev.open-bio.org
Thu May 4 13:26:06 UTC 2006


Update of /home/repository/bioruby/bioruby/lib/bio
In directory dev.open-bio.org:/tmp/cvs-serv19039

Added Files:
	map.rb 
Log Message:
New module that can describe mapping information: maps, markers, and
the links between them. It also describes the modules ActsLikeMap and
ActsLikeMarker that can be mixed into other classes (e.g. to enable clones
to act as maps for BAC end-sequences).


--- NEW FILE: map.rb ---
#
# = bio/map.rb - biological mapping class
#
# Copyright::   Copyright (C) 2006
#               Jan Aerts <jan.aerts at bbsrc.ac.uk>
# License::     Ruby's
module Bio
  # = DESCRIPTION
  # The Bio::Module contains classes that describe mapping information and can
  # be used to contain linkage maps, radiation-hybrid maps, etc.
  # As the same marker can be mapped to more than one map, and a single map
  # typically contains more than one marker, the link between the markers and
  # maps is handled by Bio::Map::Mapping objects. Therefore, to link a map to
  # a marker, a Bio::Mapping object is added to that Bio::Map. See usage below.
  #
  # Not only maps in the strict sense have map-like features (and similarly
  # not only markers in the strict sense have marker-like features). For example,
  # a microsatellite is something that can be mapped on a linkage map (and
  # hence becomes a 'marker'), but a clone can also be mapped to a cytogenetic
  # map. In that case, the clone acts as a marker and has marker-like properties.
  # That same clone can also be considered a 'map' when BAC-end sequences are
  # mapped to it. To reflect this flexibility, the modules Bio::Map::ActsLikeMap
  # and Bio::Map::ActsLikeMarker define methods that are typical for maps and
  # markers.
  # 
  #--
  # In a certain sense, a biological sequence also has map- and marker-like
  # properties: things can be mapped to it at certain locations, and the sequence
  # itself can be mapped to something else (e.g. the BAC-end sequence example
  # above, or a BLAST-result).
  #++
  # 
  # = USAGE
  #   marker_a = Bio::Map::Marker.new('marker_a')
  #   marker_b = Bio::Map::Marker.new('marker_b')
  #   map_A = Bio::Map::SimpleMap.new('map_A', 'linkage', 'cM')
  #   puts map_A.contains_marker?('marker_b')   # method defined in Bio::Map::ActsLikeMap
  #
  # = TODO
  # Check if initialization of @mappings can be done in ActsLikeMap and
  # ActsLikeMarker, instead of in the classes that include these modules.
  module Map
  # = DESCRIPTION
  # The Bio::Map::ActsLikeMap module contains methods that are typical for
  # map-like things:
  # * add markers with their locations (through Bio::Map::Mappings)
  # * check if a given marker is mapped to it
  # , and can be mixed into other classes (e.g. Bio::Map::SimpleMap)
    module ActsLikeMap
      include Enumerable
      # = DESCRIPTION
      # Adds a Bio::Map::Mappings object to its array of mappings.
      # 
      # = USAGE
      #   # suppose we have a Bio::Map::SimpleMap object called my_map
      #   my_map.add_mapping(Bio::Map::Marker.new('marker_a'), '5')
      # ---
      # *Arguments*:
      # * _marker_ (required): Bio::Map::Marker object
      # * _location_: location of mapping. Should be a _string_, not a _number_.
      # *Returns*:: itself
      def add_mapping(marker, location = nil)
        unless marker.class.include?(Bio::Map::ActsLikeMarker)
          raise "[Error] marker is not object that implements Bio::Map::ActsLikeMarker"
        end
        my_mapping = Bio::Map::Mapping.new(self, marker, Bio::Location.new(location))
        @mappings.push(my_mapping)
        unless marker.mapped_to?(self)
          marker.mappings.push(my_mapping)
        end

        return self
      end
      
      # Checks whether a Bio::Map::Marker is mapped to this Bio::Map::SimpleMap.
      # ---
      # *Arguments*:
      # * _marker_: a Bio::Map::Marker object
      # *Returns*:: true or false
      def contains_marker?(marker)
        unless marker.class.include?(Bio::Map::ActsLikeMarker)
          raise "[Error] marker is not object that implements Bio::Map::ActsLikeMarker"
        end
        contains = false
        @mappings.each do |mapping|
          if mapping.marker == marker
            contains = true
            return contains
          end
        end
        return contains
      end
      
      # Go through all Bio::Map::Mapping objects linked to this Bio::Map::SimpleMap.
      def each
        @mappings.each do |mapping|
          yield mapping
        end
      end
    end #ActsLikeMap

    # = DESCRIPTION
    # The Bio::Map::ActsLikeMarker module contains methods that are typical for
    # marker-like things:
    # * map it to one or more maps
    # * check if it's mapped to a given map
    # , and can be mixed into other classes (e.g. Bio::Map::Marker)
    module ActsLikeMarker
      include Enumerable
      
      # = DESCRIPTION
      # Adds a Bio::Map::Mappings object to its array of mappings.
      # 
      # = USAGE
      #   # suppose we have a Bio::Map::Marker object called marker_a
      #   marker_a.add_mapping(Bio::Map::SimpleMap.new('my_map'), '5')
      # ---
      # *Arguments*:
      # * _map_ (required): Bio::Map::SimpleMap object
      # * _location_: location of mapping. Should be a _string_, not a _number_.
      # *Returns*:: itself
      def add_mapping (map, location = nil)
        unless map.class.include?(Bio::Map::ActsLikeMap)
          raise "[Error] map is not object that implements Bio::Map::ActsLikeMap"
        end
        my_mapping = Bio::Map::Mapping.new(map, self, Bio::Location.new(location))
        @mappings.push(my_mapping)
        unless map.contains_marker?(self)
          map.mappings.push(my_mapping)
        end
      end
      
      # Check whether this marker is mapped to a given Bio::Map::SimpleMap.
      # ---
      # *Arguments*:
      # * _map_: a Bio::Map::SimpleMap object
      # *Returns*:: true or false
      def mapped_to?(map)
        unless map.class.include?(Bio::Map::ActsLikeMap)
          raise "[Error] map is not object that implements Bio::Map::ActsLikeMap"
        end
				
        mapped = false
        @mappings.each do |mapping|
          if mapping.map == map
            mapped = true
            return mapped
          end
        end
        return mapped
      end
      
      # Go through all Mapping objects linked to this marker.
      def each
        @mappings.each do |mapping|
          yield mapping
        end
      end
    end #ActsLikeMarker
	  
    # = DESCRIPTION
    # Creates a new Bio::Map::Mapping object, which links Bio::Map::ActsAsMap-
    # and Bio::Map::ActsAsMarker-like objects. This class is typically not
    # accessed directly, but through map- or marker-like objects.
    class Mapping
      include Comparable
      
      # Creates a new Bio::Map::Mapping object
      # ---
      # *Arguments*:
      # * _map_: a Bio::Map::SimpleMap object
      # * _marker_: a Bio::Map::Marker object
      # * _location_: a Bio::Location object
      def initialize (map, marker, location = nil)
        @map, @marker, @location = map, marker, location
      end
      attr_accessor :map, :marker, :location
      
      # Compares the location of this mapping to another mapping.
      # ---
      # *Arguments*:
      # * other_mapping: Bio::Map::Mapping object
      # *Returns*::
      # * 1 if self < other location
      # * -1 if self > other location
      # * 0 if both location are the same
      # * nil if the argument is not a Bio::Location object
      def <=>(other)
        unless other.kind_of(Bio::Map::Mapping)
          raise "[Error] markers are not comparable"
        end
        return self.location.<=>(other.location)
      end
    end # Mapping
    
    # = DESCRIPTION
    # This class handles the essential storage of name, type and units of a map.
    # It includes Bio::Map::ActsLikeMap, and therefore supports the methods of
    # that module.
    # 
    # = USAGE
    #   my_map1 = Bio::Map::SimpleMap.new('RH_map_ABC (2006)', 'RH', 'cR')
    #   my_map1.add_marker(Bio::Map::Marker.new('marker_a', '17')
    #   my_map1.add_marker(Bio::Map::Marker.new('marker_b', '5')
    class SimpleMap
    include ActsLikeMap
    
      # Builds a new Bio::Map::SimpleMap object
      # ---
      # *Arguments*:
      # * name: name of the map
      # * type: type of the map (e.g. linkage, radiation_hybrid, cytogenetic, ...)
      # * units: unit of the map (e.g. cM, cR, ...)
      # *Returns*:: new Bio::Map::SimpleMap object
      def initialize (name = nil, type = nil, units = nil)
        @name, @type, @units = name, type, units
        @mappings = Array.new
      end
      
      # Name of the map
      attr_accessor :name
			
      # Type of the map
      attr_accessor :type
			
      # Units of the map
      attr_accessor :units
      
      # Array of mappings for the map
      attr_accessor :mappings
    end # SimpleMap
    
    # = DESCRIPTION
    # This class handles markers that are anchored to a Bio::Map::SimpleMap. It
    # includes Bio::Map::ActsLikeMarker, and therefore supports the methods of
    # that module.
    # 
    # = USAGE
    #   marker_a = Bio::Map::Marker.new('marker_a')
    #   marker_b = Bio::Map::Marker.new('marker_b')
    class Marker
      include ActsLikeMarker
      
      # Builds a new Bio::Map::Marker object
      # ---
      # *Arguments*:
      # * name: name of the marker
      # *Returns*:: new Bio::Map::Marker object
      def initialize(name)
        @name = name
        @mappings = Array.new
      end

      # Name of the marker
      attr_accessor :name
			
      # Array of mappings for the marker
      :mappings
    end # Marker
  end # Map
end # Bio

if __FILE__ == $0
  my_marker1 = Bio::Map::Marker.new('marker1')
#  my_marker2 = Bio::Map::Marker.new('marker2')
  my_marker3 = Bio::Map::Marker.new('marker3')

  my_map1 = Bio::Map::SimpleMap.new('RH_map_ABC (2006)', 'RH', 'cR')
  my_map2 = Bio::Map::SimpleMap.new('consensus', 'linkage', 'cM')

  my_map1.add_mapping(my_marker1, '17')
  my_map1.add_mapping(Bio::Map::Marker.new('marker2'), '5')
  my_marker3.add_mapping(my_map1, '9')


  puts "Does my_map1 contain marker3? => " + my_map1.contains_marker?(my_marker3).to_s
  puts "Does my_map2 contain marker3? => " + my_map2.contains_marker?(my_marker3).to_s
	
  my_map1.sort.each do |mapping|
    puts mapping.map.name + "\t" + mapping.marker.name + "\t" + mapping.location.from.to_s + ".." + mapping.location.to.to_s
  end
  puts my_map1.min.marker.name
  my_map2.each do |mapping|
    puts mapping.map.name + "\t" + mapping.marker.name + "\t" + mapping.location.from.to_s + ".." + mapping.location.to.to_s
  end

#  p my_map1.between?(my_mappable2,my_mappable3)
#  p my_map1.between?(my_mappable,my_mappable2)
end




More information about the bioruby-cvs mailing list