使用SLIM / HAML等在Ruby脚本?(Use SLIM/HAML etc. in a Rub

2019-10-18 20:02发布

我目前正在制作一个脚本,分析了一些基因数据,然后产生一个彩色Word文档的输出。 该脚本,但是在脚本一个方法写的不好,创建Word文档的方法。

创建文档的方法创建一个独立的HTML文件,然后将其保存为“DOCX”的扩展,它可以让我给的文件不同的风格不同的部分。

下面是最起码要得到这个工作。 它包括将要在不同的方法只是最后的步骤之前被创建并存储在哈希一些样本的输入数据,以及必要的方法。

require 'bio'

def make_hash(input_file)
  input_read = Hash.new
  biofastafile = Bio::FlatFile.open(Bio::FastaFormat, input_file) 
  biofastafile.each_entry do |entry|
    input_read[entry.definition] = entry.aaseq
  end
  return input_read
end

def to_doc(hash, output, motif)
  output_file = File.new(output, "w")
  output_file.puts "<!DOCTYPE html><html><head><style> .id{font-weight: bold;} .signalp{color:#000099; font-weight: bold;} .motif{color:#FF3300; font-weight: bold;} h3 {word-wrap: break-word;} p {word-wrap: break-word; font-family:Courier New, Courier, Mono;}</style></head><body>"
  hash.each do |id, seq|
    sequence = seq.to_s.gsub("\[\"", "").gsub("\"\]", "")
    id.scan(/(\w+)(.*)/) do |id_start, id_end|
      output_file.puts "<p><span class=\"id\"> >#{id_start}</span><span>#{id_end}</span><br>"
      output_file.puts "<span class=\"signalp\">"
      sequence.scan(/(\w+)-(\w+)/) do |signalp, seq_end|
        output_file.puts signalp + "</span>" + seq_end.gsub(/#{motif}/, '<span class="motif">\0</span>')
        output_file.puts "</p>"
      end
    end
  end
  output_file.puts "</body></html>"
  output_file.close   
end

hash = make_hash("./sample.txt")
to_doc = to_doc(hash, "output.docx", "WL|KK|RR|KR|R..R|R....R"

这是一些样本数据。 在现实中,从品种分析基因数据时,这可以由序列的多10万周的的:

>isotig00001_f4_14 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00001_f4_15 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL
>isotig00003_f6_8 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00003_f6_9 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL
>isotig00004_f6_8 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00004_f6_9 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL
>isotig00009_f2_3 - Signal P Cleavage Site => 22:23
MLKCFSIIMGLILLLEIGGGCA-IYFYRAQIQAQFQKSLTDVTITDYRENADFQDLIDALQSGLSCCGVNSYEDWDNNIYFNCSGPANNPEALWCAFLLLYTGSSKRSSQHPVRLWSSFPRTTKYFPHKDLHHWLCGYVYNVD
>isotig00009_f3_9 - Signal P Cleavage Site => 16:17
MKTGIIIFISTVVVLP-ITLKPCGVPFSCCIPDQASGVANTQCGYGVRSPEQQNTFHTKIYTTGCADMFTMWINRYLYYIAGIAGVIVLVELFGFCFAHSLINDIKRQKARWAHR
>isotig00009_f6_13 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00009_f6_14 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL

每次读取由两个部分组成:SEQ ID(线开始用> )和序列。 此被分割,并存储在散列make_hash方法。 这个例子:

>isotig00001_f4_14 - Signal P Cleavage Site => 11:12

MMHLLCIVLLL-KWWLLL 

由。。。制成由。。。做成:

>isotig00001_f4_14  (the first part of the id - class="id")

Signal P Cleavage Site => 11:12 (the second part of the id - normal writing)

(new line)

MMHLLCIVLLL (first part of the sequence - class="signalp")

KW WL LL  (the second part of the sequence - the motif KW will be class="motif")

在HTML它会产生:

<p>
  <span class="id"> >isotig00001_f4_14</span><span>Signal P Cleavage Site => 11:12</span>
<br>
  <span class="signalp">MMHLLCIVLL</span><span>KW</span><span class="motif">KW</span><span>LL</span>

基本上,我想重写to_doc使用适当的HTML模板脚本如SLIM / HAML /引入nokogiri / ERB方法。 我试图完成这件事。

出于某种原因,一个循环内的循环没有工作,创建一个全局变量来存储这些变量也不能工作。

以上作品的剧本,只是样本数据保存为“sample.txt的”,然后运行该脚本。

我将是任何帮助非常感激。

Answer 1:

这里有一个出发点:

require 'haml'

haml_doc = <<EOT
%html
  %head
    :css
      .id {font-weight: bold;}
      .signalp {color:#000099; font-weight: bold;}
      .motif {color:#FF3300; font-weight: bold;}
      h3 {word-wrap: break-word;}
      p {word-wrap: break-word; font-family:Courier New, Courier, Mono;}
  %body
EOT

engine = Haml::Engine.new(haml_doc)
puts engine.render

其运行时输出这样的:

<html>
  <head>
    <style>
      .id {font-weight: bold;}
      .signalp {color:#000099; font-weight: bold;}
      .motif {color:#FF3300; font-weight: bold;}
      h3 {word-wrap: break-word;}
      p {word-wrap: break-word; font-family:Courier New, Courier, Mono;}
    </style>
  </head>
  <body></body>
</html>

从那里,你可以很容易地编写到使用文件:

File.write(output, engine.render)

而不是使用puts将其输出到控制台。

要使用此功能,你需要充实haml_doc额外Haml的循环在你的输入数据和按摩到一个数组或哈希,你可以清晰地迭代,不嵌入各种scan和条件逻辑。 视图应主要用于输出的内容,不处理数据。

就在上述engine = Haml...你会想读你的输入数据和按摩它,并将其存储在一个实例变量Haml的可以遍历行。 你有基本的想法在原来的代码,但而不是试图输出HTML,创建一个对象或子散,你可以传递给Haml的。

通常这都会被分离成单独的文件为模型,视图和控制器,就像在轨道或大Sinatra的应用程序,但是这真的不是一个大的应用程序,所以你可以把它们都放在一个文件。 保持你的逻辑干净,它会被罚款。

如果没有样本输入数据和预期输出很难做多,但会给你一个起点。


根据这些数据样本,这里的东西,在你得到的球场。 我不会把它擦亮,因为,毕竟,你必须做一些它,但是这是一个良好的开端。 第一部分是嘲讽了合理的东西像生物在你的代码中引用,但我从来没有见过。 你不需要这部分,但可能要通过它来看看:

module Bio

  FastaFormat = 1

SAMPLE_DATA = <<-EOT
>isotig00001_f4_14 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00001_f4_15 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL
>isotig00003_f6_8 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00003_f6_9 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL
>isotig00004_f6_8 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00004_f6_9 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL
>isotig00009_f2_3 - Signal P Cleavage Site => 22:23
MLKCFSIIMGLILLLEIGGGCA-IYFYRAQIQAQFQKSLTDVTITDYRENADFQDLIDALQSGLSCCGVNSYEDWDNNIYFNCSGPANNPEALWCAFLLLYTGSSKRSSQHPVRLWSSFPRTTKYFPHKDLHHWLCGYVYNVD
>isotig00009_f3_9 - Signal P Cleavage Site => 16:17
MKTGIIIFISTVVVLP-ITLKPCGVPFSCCIPDQASGVANTQCGYGVRSPEQQNTFHTKIYTTGCADMFTMWINRYLYYIAGIAGVIVLVELFGFCFAHSLINDIKRQKARWAHR
>isotig00009_f6_13 - Signal P Cleavage Site => 11:12
MMHLLCIVLLL-KWWLLL
>isotig00009_f6_14 - Signal P Cleavage Site => 10:11
MHLLCIVLLL-KWWLLL
EOT

  class FlatFile

    class Entry
      attr_reader :definition, :aaseq

      def initialize(definition, aaseq)
        @definition = definition
        @aaseq = aaseq
      end
    end

    def initialize
    end

    def self.open(filetype, filename)
      SAMPLE_DATA.split("\n").each_slice(2).map{ |seq_id, sequence| Entry.new(seq_id, sequence) }
    end

    def each_entry
      @sample_data.each do |_entry|
        yield _entry
      end
    end

  end
end

这里是有趣的开始。 我修改了get_hash程序来解析字符串我会怎么做。 代替散列的,它返回散列的阵列。 每个子散列准备好被使用,换言之,数据被解析并准备好输出:

include Bio

def make_array_of_hashes(input_file)
  Bio::FlatFile.open(
    Bio::FastaFormat,
    input_file
  ).map { |entry|

    id_start, id_end = entry.definition.split('-').map(&:strip)
    signalp, seq_end = entry.aaseq.split('-')
    motif = seq_end.scan(/(?:WL|KK|RR|KR|R..R|R....R)/)

    {
      :id_start => id_start,
      :id_end => id_end,
      :signalp => signalp,
      :motif => motif
    }
  }
end

这是一个简单的方式来定义脚本的体内HAML文件。 我只输出,有模板没有逻辑除了循环。 其他的一切处理处理之前的观点:

haml_doc = <<EOT
!!!
%html
  %head
    :css
      .id {font-weight: bold;}
      .signalp {color:#000099; font-weight: bold;}
      .motif {color:#FF3300; font-weight: bold;}
      h3 {word-wrap: break-word;}
      p {word-wrap: break-word; font-family:Courier New, Courier, Mono;}
  %body
  - data.each do |d|
    %p
      %span.id= d[:id_start]
      %span= d[:id_end]
      %br/
      %span.signalp= d[:signalp]
      - d[:motif].each do |m|
        %span= m
EOT

下面是如何使用它:

require 'haml'

data = make_array_of_hashes('sample.txt')

engine = Haml::Engine.new(haml_doc)
puts engine.render(Object.new, :data => data)

其中,在运行时的输出:

<!DOCTYPE html>
<html>
  <head>
    <style>
      .id {font-weight: bold;}
      .signalp {color:#000099; font-weight: bold;}
      .motif {color:#FF3300; font-weight: bold;}
      h3 {word-wrap: break-word;}
      p {word-wrap: break-word; font-family:Courier New, Courier, Mono;}
    </style>
  </head>
  <body></body>
  <p>
    <span class='id'>>isotig00001_f4_14</span>
    <span>Signal P Cleavage Site => 11:12</span>
    <br>
    <span class='signalp'>MMHLLCIVLLL</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00001_f4_15</span>
    <span>Signal P Cleavage Site => 10:11</span>
    <br>
    <span class='signalp'>MHLLCIVLLL</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00003_f6_8</span>
    <span>Signal P Cleavage Site => 11:12</span>
    <br>
    <span class='signalp'>MMHLLCIVLLL</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00003_f6_9</span>
    <span>Signal P Cleavage Site => 10:11</span>
    <br>
    <span class='signalp'>MHLLCIVLLL</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00004_f6_8</span>
    <span>Signal P Cleavage Site => 11:12</span>
    <br>
    <span class='signalp'>MMHLLCIVLLL</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00004_f6_9</span>
    <span>Signal P Cleavage Site => 10:11</span>
    <br>
    <span class='signalp'>MHLLCIVLLL</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00009_f2_3</span>
    <span>Signal P Cleavage Site => 22:23</span>
    <br>
    <span class='signalp'>MLKCFSIIMGLILLLEIGGGCA</span>
    <span>KR</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00009_f3_9</span>
    <span>Signal P Cleavage Site => 16:17</span>
    <br>
    <span class='signalp'>MKTGIIIFISTVVVLP</span>
    <span>KR</span>
  </p>
  <p>
    <span class='id'>>isotig00009_f6_13</span>
    <span>Signal P Cleavage Site => 11:12</span>
    <br>
    <span class='signalp'>MMHLLCIVLLL</span>
    <span>WL</span>
  </p>
  <p>
    <span class='id'>>isotig00009_f6_14</span>
    <span>Signal P Cleavage Site => 10:11</span>
    <br>
    <span class='signalp'>MHLLCIVLLL</span>
    <span>WL</span>
  </p>
</html>


文章来源: Use SLIM/HAML etc. in a Ruby script?