File: distance_matrix.rb

package info (click to toggle)
ruby-bio 1.5.0-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 7,480 kB
  • ctags: 9,428
  • sloc: ruby: 74,117; xml: 3,383; makefile: 17; perl: 13; sh: 1
file content (96 lines) | stat: -rw-r--r-- 2,690 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#
# = bio/appl/phylip/distance_matrix.rb - phylip distance matrix parser
#
# Copyright:: Copyright (C) 2006
#             GOTO Naohisa <ng@bioruby.org>
#
# License:: The Ruby License
#
#  $Id: distance_matrix.rb,v 1.3 2007/04/05 23:35:40 trevor Exp $
#
# = About Bio::Phylip::DistanceMatrix
#
# Please refer document of Bio::Phylip::DistanceMatrix class.
#

require 'matrix'

module Bio
  module Phylip

    # This is a parser class for phylip distance matrix data
    # created by dnadist, protdist, or restdist commands.
    #
    class DistanceMatrix

      # creates a new distance matrix object
      def initialize(str)
        data = str.strip.split(/(?:\r\n|\r|\n)/)
        @otus = data.shift.to_s.strip.to_i
        prev = nil
        data.collect! do |x|
          if /\A +/ =~ x and prev then
            prev.concat x.strip.split(/\s+/)
            nil
          else
            prev = x.strip.split(/\s+/)
            prev
          end
        end
        data.compact!
        if data.size != @otus then
          raise "inconsistent data (OTUs=#{@otus} but #{data.size} rows)"
        end
        @otu_names = data.collect { |x| x.shift }
        mat = data.collect do |x|
          if x.size != @otus then
            raise "inconsistent data (OTUs=#{@otus} but #{x.size} columns)"
          end
          x.collect { |y| y.to_f }
        end
        @matrix = Matrix.rows(mat, false)
        @original_matrix = Matrix.rows(data, false)
      end

      # distance matrix (returns Ruby's Matrix object)
      attr_reader :matrix

      # matrix contains values as original strings.
      # Use it when you doubt precision of floating-point numbers.
      attr_reader :original_matrix

      # number of OTUs
      attr_reader :otus

      # names of OTUs
      attr_reader :otu_names

      # Generates a new phylip distance matrix formatted text as a string.
      def self.generate(matrix, otu_names = nil, options = {})
        if matrix.row_size != matrix.column_size then
          raise "must be a square matrix"
        end
        otus = matrix.row_size
        names = (0...otus).collect do |i|
          name = ((otu_names and otu_names[i]) or "OTU#{i.to_s}")
          name
        end
        data = (0...otus).collect do |i|
          x = (0...otus).collect { |j|  sprintf("%9.6f", matrix[i, j]) }
          x.unshift(sprintf("%-10s", names[i])[0, 10])

          str = x[0, 7].join(' ') + "\n"
          7.step(otus + 1, 7) do |k|
            str << ' ' + x[k, 7].join(' ') + "\n"
          end
          str
        end
        sprintf("%5d\n", otus) + data.join('')
      end
        
    end #class DistanceMatrix

  end #module Phylip

end #module Bio