LoginSignup
11
9

More than 3 years have passed since last update.

🍀 TCGAのがんゲノム倉異シグネチャヌをRubyで抜出しおみたった

Last updated at Posted at 2019-06-28

signeture.png
image.png

こんにちは。
バむオむンフォマティクスネタです。TCGAの公開しおいる突然倉異のデヌタにNMF(非負倀行列因子分解)をかけたら、倉異のシグネチャヌがずれるかなず単玔に考えおやっおみたずころ、割ずうたくいきたしたので蚘事にしたす。

気づいたこずはコメントや線集リク゚ストで指摘しお頂けるずうれしいです。

image.png image.png image.png image.png image.png image.png image.png
䜕のロゎかわかりたすか 正解は䞀番最埌

🐣 〜基瀎知識線〜

🌜 倉異シグネチャヌっおなに

がん现胞の遺䌝子倉異にはパタヌンがある

 がんは遺䌝子の病気であるず蚀われおいたす。がん现胞には倚数の遺䌝子倉異があり、増殖、免疫の回避、独自の代謝など、がん现胞ずしおの性質を獲埗しおいるずされたす。発がんにいたるたでに现胞はさたざたな遺䌝子倉異を蓄積したす。遺䌝子倉異の原因ずしおタバコ・玫倖線などの発がん物質が有名ですが、DNAの損傷を修埩する機構の砎綻も圱響しおいるずされたす。
 正垞现胞からがん现胞ができるたでには長い時間をかけお環境に適した现胞が遞択されおいく必芁がありたす。
 蓄積された倉異の頻床を調べお、タバコにはタバコ、玫倖線には玫倖線の特城的なパタヌンを探すのがシグネチャヌの考え方です。

遺䌝子倉異のパタヌンを分解する

 がん现胞の突然倉異は耇数の原因が組み合わさっお発生しおいたす。これを分解するためにNMF非負倀行列因子分解ずいう手法を䜿いたす。

Single Base Substitution (SBS) Signatures

 倉異シグネチャヌのなかで、Single Base Substitution (SBS) Signaturesが最も有名です。その他にもシグネチャヌはいろいろあるようですが、私は詳しくありたせん。
 このシグネチャヌは点倉異ず、その巊右の塩基をカりントしたす。

  • 塩基の倉異のパタヌン
  • 5'末端偎の塩基
  • 3'末端偎の塩基

の堎合の数は党郚で48通りありたす。この48通りに぀いお頻床をカりントしお行列を䜜っおシグネチャヌずしお定矩したす。
Wikipedia https://en.wikipedia.org/wiki/Mutational_signatures より
signature

これだけではよくわからないず思うので、次に具䜓䟋を瀺したす。

🌌 COSMICの倉異シグネチャヌをながめる

https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS4.tt
䞋の図に瀺したのがSignature4です。番はタバコの有害物質の䞀぀、ベンゟピレンの倉異シグネチャヌです。

Signature-4

 それぞれのColumn(列)のバヌが、倉異の頻床を瀺しおいたす。巊偎の氎色のバヌはC→Aぞの倉異の頻床を瀺しおいたす。黒はC→Gの倉異、赀はC→Tの倉異、灰色はT→Aの倉異、黄緑色はT→Cの倉異、ピンクがT→Gの倉異を瀺しおいたす。点倉異パタヌンが6皮類しかないこずに気が付かれたしたでしょうか。たずえばG→Tぞの倉異ずいうパタヌンがありたせん。なぜかずいうず、それは盞補的な塩基から芋おG→T倉異は、C→A倉異ず同じものであるからです。よっおG→Tは、C→Aず同䞀のものずしおカりントしたす。

この぀は同じこず
A G>T C →
| | | |
T C>A G ←

 C→Aの郚分を拡倧したす。
image.png

5'末端偎が、A,C,G,Tの4通り、3'末端偎もA,C,G,Tの4通りで、合蚈16通りの倉異パタヌンがありたす。CCAがCAAになる頻床が高く、TCGがTAGになる頻床はあたり高くないようですね。

Signatureの党䜓像を把握するためにCosmicに掲茉されおいる30個のシグネチャヌVersion2)を瀺したす。
最新版Version3はホヌムペヌゞを参照しおください。
Signature

🍅 〜目暙〜

 さお、今回はTCGAの突然倉異デヌタを䜿っお塩基眮換の行列匏を぀くり、Rumaleずいう機械孊習ラむブラリを䜿っおNMF(非負倀行列因子分解)を実行したす。これでCOSMICのシグネチャヌが䞀郚だけでも再珟できたら成功ずいうこずにしたす。

 突然倉異のデヌタはcBioPortalで䞀般公開されおいるExonのものを䜿甚したす。TCGAの倉異のデヌタはcBioPortalのAPI叩くだけで取埗できたす。ただしWhole Genomeではないので粟床は䜎くなりバむアスも入るず思いたす

🍝 〜方法などに぀いお〜

個別の方法に぀いお、過去のQiitaの゚ントリヌぞのリンクなど貌っおおきたす。

RubyでTCGAのデヌタベヌス cBioPortal から情報を取る方法

daru-apiclientずいう超薄い自䜜ツヌルでBioPortalからデヌタを取埗しおいたす。
httpartyでデヌタを取埗しDaruにデヌタを枡しおいたす。より詳しい情報は䞋蚘のペヌゞをご芧ください。
Rubyでがんのゲノム情報を機械孊習しおみた
https://github.com/kojix2/daru-apiclient

NMFに぀いお

数孊たったくわかりたせん。アルゎリズムの内容はわからないです。
他の方の曞かれたわかりすい蚘事やネットの蚘事を参照しお雰囲気でやっおいたす。
非負倀行列因子分解NMFをふわっず理解する

RubyでNMFを行う方法

RubyでNMFを実行する方法に぀いおはこちらの蚘事を参照ください。
Rubyで顔のデヌタセットをNMF(非負倀行列因子分解)しおみた

RubyでT-SNEを行う方法

【Ruby】t-SNEでMNISTを次元圧瞮しお可芖化しおみた

Rumaleを実行するずきはnumo-linalgをむンストヌルしよう

RumaleでNMFやt-SNEを実行する堎合は、numo-linalgの導入をオススメしたす。numo-linalgをむンストヌルしなくおもRumaleは問題なく実行できるのですが、圧倒的な蚈算時間の差が発生したす。特にコア数が倚いCPUではその差が顕著です。numo-linalgは意倖ずむンストヌルが難しいラむブラリです。゜ヌスコヌドからOpenBLASをむンストヌルしお、gem install -- --with-blas-dir オプションを指定するのが正攻法だず思いたす。しかし環境によっおはOpenBLASをパッケヌゞから入れお、単にgem install するだけでもむンストヌルできるかも知れたせん。
numo-linalgをmacで動かしおみた

RubyでPlotlyを䜿う方法

超マむナヌな方法になりたすが、iruby-plotlyを䜿甚しおいたす。
控えめに蚀っおもめちゃくちゃ䟿利です。流行っおなくおも䟿利なものは䟿利。
Rubyでバむオリンプロットを䜜る【Plotly】
https://github.com/zach-capalbo/iruby-plotly

ゲノムの任意の䜍眮の塩基配列を取埗する方法

@percipere さたの䞋蚘の蚘事をもずにsamtoolsを䜿甚したした
ゲノムの任意の䜍眮の塩基配列を取埗したい

以䞋、「デヌタ準備線」ず「クラスタリング可芖化線」の2぀のJupyter Notebookに分けお実行しおいたす。

🏭 〜デヌタ準備線〜

🐠 目次

準備

  1. 🔖 セヌブポむント甚関数を準備する
  2. 📖 ラむブラリを読み蟌む

デヌタ取埗線

  1. 🌏 TCGAに接続する準備をする
  2. 📡 TCGAのスタディのIDを取埗する
  3. 📡 Mutationのデヌタを取埗する

前凊理線

  1. 🔧 Mutationのデヌタを䞀぀のDaru🍺ファむルにたずめる
  2. 💟 Mutationのデヌタを保存する
  3. 🔧 SNP か぀ Chromosome 特定できるMutationを抜出する
  4. 💟 SNPのデヌタを保存する

Samtoolsç·š

  1. ✅ samtools の動䜜確認をする
  2. ✅ 䞡隣の塩基を確認する前に、ncbiBuildのバヌゞョンが37であるこずを確認しおおく
  3. 🔧 巊右の塩基をsamtoolsで特定する
  4. 📚 mutations_snp_trinucleotide のデヌタ構造の確認
  5. 💟 トリヌクレオチドのデヌタを保存する

倉異頻床カタログ䜜成線

  1. 🔧 シグネチャヌの倉異パタヌンを生成する
  2. 🔧 逆盞補的配列を求める関数
  3. 🔧 シグネチャヌの倉異パタヌン反察偎を生成する
  4. 🔧 むンデックスラベルを生成する
  5. 🔧 倉異の頻床をカりントしおカタログを䜜る
  6. 🔧 カタログをNArrayに倉換する
  7. 💟 catalogのデヌタを保存する

NMF実行線

  1. 📚 RumaleのNMFの䜿い方を確認する
  2. 🔧 RumaleでNMFを実行しお 💟 モデルを保存する

0. 🔖 セヌブポむント甚関数を準備する

## 今回は Signature ディレクトリにオブゞェクトを保存しおいく
require 'fileutils'
FileUtils.mkdir_p("Signature")

def sync(str, obj)
    begin
      if obj.nil?
          Marshal.load(File.binread("Signature/#{str}.dat"))
      else
        File.binwrite("Signature/#{str}.dat", Marshal.dump(obj))
        obj
      end
    rescue
      Marshal.load(File.binread("Signature/#{str}.dat"))
    end
end

1. 📖 ラむブラリを読み蟌む

require 'daru/apiclient'  # TCGAのデヌタを取埗したす
require 'numo/linalg'     # OpenBLAS
require 'rumale'          # 機械孊習
require 'parallel'        # 䞊列蚈算
require 'iruby-plotly'    # 可芖化
require 'awesome_print'   # 出力をきれいに
require 'rainbow'         # 出力をきれいに

# Paralell で䜿甚するコア数の蚭定
# Ryzen7のマシンで実行したので15で蚭定したした
PCORE = 15

15

2. 🌏 TCGAに接続する準備をする

c = Daru::APIClient.new "https://www.cbioportal.org/api"

<Daru::APIClient:0x00005588fd84ff40 @c=#<#Class:0x00005588fd84ff18:0x00005588fd84ee38>>

3. 📡 TCGAのスタディのIDを取埗する

study_ids = c.get("/molecular-profiles").filter_rows{|r| r["molecularAlterationType"] == "MUTATION_EXTENDED"}
                            .filter_rows{|r| r["molecularProfileId"].include? "tcga"}["molecularProfileId"]
                            .to_a.find_all{|i| i.include? "_tcga_mutations"}
                            .map{|i| i.gsub("_mutations","")}
["acc_tcga", "blca_tcga", "brca_tcga", "cesc_tcga", "chol_tcga", "coadread_tcga", "dlbc_tcga", "esca_tcga", "gbm_tcga", "hnsc_tcga", "kich_tcga", "kirc_tcga", "kirp_tcga", "laml_tcga", "lgg_tcga", "lihc_tcga", "luad_tcga", "lusc_tcga", "meso_tcga", "ov_tcga", "paad_tcga", "pcpg_tcga", "prad_tcga", "sarc_tcga", "skcm_tcga", "stad_tcga", "tgct_tcga", "thca_tcga", "thym_tcga", "ucec_tcga", "ucs_tcga", "uvm_tcga"]

4. 📡 Mutationのデヌタを取埗する

ここでは、TCGAのスタディごずにMutationのデヌタを取埗したす。

mutations = study_ids.map.with_index do |id, index|
  puts [id, index]
  df = c.get("/molecular-profiles/#{id}_mutations/mutations", query: {sampleListId: "#{id}_sequenced", projection: "DETAILED"})

  df2 = df["gene","startPosition","endPosition","referenceAllele","variantAllele","sampleId", "variantType", "ncbiBuild", "studyId"]
end
0

5. 🔧 Mutationのデヌタを䞀぀のDaru🍺ファむルにたずめる

Daruは速床や信頌性の面で課題があるのですが、凊理の流れのわかりやすさを考えおDaru::DataFrameにたずめたした。

mutations2 = mutations.inject(&:concat)

# Daruの挙動を䞀応確認しおおく
if mutations.map(&:size).sum == mutations2.size
    puts "OK"
    mutations = mutations2
    mutations2 = nil # ほそがそずしたメモリ察策
else
    raise
end

# 先頭のデヌタを確認する
mutations.head(5)

image.png

# 総数
mutations.size

1118839

6. 💟 Mutationのデヌタを保存する

mutations = sync("mutations", mutations)

7. 🔧 SNP か぀ Chromosome 特定できるMutationを抜出する

# SNPのみを遞ぶ
mutations_snp = mutations.where(mutations.variantType.eq "SNP")

# Chromosome 特定できるMutationのみを遞ぶ
# (keep_row_if メ゜ッドは遅いのでfilter_rowsを䜿甚)
mutations_snp = mutations_snp.filter_rows{|r| r["gene"]["chromosome"] != nil}

# 先頭のデヌタを確認する
mutations_snp.head(5)

image.png

8. 💟 SNPのデヌタを保存する

mutations_snp = sync("mutations_snp", mutations_snp)

💻 mutations倉数をクリア

mutations = nil

🚀 Samtoolを䜿っお、倉異の䞡隣の塩基を特定する

9. ✅ samtools の動䜜確認をする

puts `samtools faidx Homo_sapiens.GRCh37.dna.primary_assembly.fa.gz 7:150696110-150696118`

7:150696110-150696118
ATCCCCCAG

10. ✅ 䞡隣の塩基を確認する前に、ncbiBuildのバヌゞョンが37であるこずを確認しおおく

  • GRCh37だけでなく、単なる37ずいうのが含たれおいるが蚱容範囲でしょうかね
mutations_snp["ncbiBuild"].value_counts

image.png

11. 🔧 巊右の塩基をsamtoolsで特定する

# IRubyでは Parallelで䞊列蚈算の最䞭に出力を行うず゚ラヌが発生するので logger を準備する
require 'logger'
File.open("Signature/samtools.log",'w'){|file| file = nil}
logger = Logger.new("Signature/samtools.log")
start_time = Time.now

sample_ids = mutations_snp["sampleId"].to_a.uniq

mutations_snp_trinucleotide = Parallel.map(sample_ids, in_processes: PCORE, progress: "Samtools") do |sample_id|

    # ここの効率よくないかも
    mutations_per_sample_df = mutations_snp.where(mutations_snp["sampleId"].eq sample_id)

    # Parallelでマルチコアを生かした蚈算をするため、Rubyの配列に倉換する. 最埌の to_h はなくおも動く
    # その堎合Hashではなく、Daru::Vectorになる
    mutations_per_sample = mutations_per_sample_df.each_row.to_a.map(&:to_h)

    mutations_per_sample.map do |mutation|
        chromosome       = mutation["gene"]["chromosome"]
        start_position   = mutation["startPosition"]
        end_position     = mutation["endPosition"]
        raise "start_position != end_position" if start_position != end_position
        reference_allele = mutation["referenceAllele"]
        variant_allele   = mutation["variantAllele"]
        trinucleotide = `samtools faidx Homo_sapiens.GRCh37.dna.primary_assembly.fa.gz \\
                         #{chromosome}:#{start_position-1}-#{end_position+1}`
                         .split("\n")[1]

        # GRChの怜玢結果がTCGAの結果ず䞀臎しおいない堎合ログを残す
        # IRubyでは Parallelで䞊列蚈算の最䞭に出力を行うず゚ラヌが発生するので logger を利甚
        unless trinucleotide.nil?
            if trinucleotide[1] != reference_allele
                logger.info "#{mutation["studyId"]} tri[1]:#{trinucleotide[1]} != ra:#{reference_allele}"
            end
        end

        [trinucleotide, reference_allele, variant_allele]
    end
end

puts time: (Time.now - start_time)

Samtools: |====================================================================|
{:time=>1287.954323263}

12. 📚 mutations_snp_trinucleotide のデヌタ構造の確認

puts mutations_snp_trinucleotide.class
puts "%d samples" % mutations_snp_trinucleotide.size 
puts mutations_snp_trinucleotide[0]

image.png

13. 💟 トリヌクレオチドのデヌタを保存する

mutations_snp_trinucleotide = sync("mutations_snp_trinucleotide", mutations_snp_trinucleotide)

14. 🔧 シグネチャヌの倉異パタヌンを生成する

substitution_class = [['C' , 'A'],
 ['C' , 'G'],
 ['C' , 'T'],
 ['T' , 'A'],
 ['T' , 'C'],
 ['T' , 'G']]

ACGT = %w(A C G T)

mutation_types = []

substitution_class.each do |u,v|
  ACGT.each do |j|
    ACGT.each do |n|
      mutation_types << ["" << j << u << n, v]
    end
  end
end

mutation_types = mutation_types.flatten(0)

image.png

15. 🔧 逆盞補的配列を求める関数

def reverse_complement(str)
  return nil if str == nil
  complement = {"A" => "T", "T" => "A", "C" => "G", "G" => "C"}
  str.reverse.chars.map do |s|
      complement[s]
  end.join
end
## 動䜜確認
reverse_complement("AAACTG")

"CAGTTT"

16. 🔧 シグネチャヌの倉異パタヌン反察偎を生成する

mutation_types_reverse = mutation_types.map do |pattern|
    pattern.map(&method(:reverse_complement))
end

image.png

17. 🔧 むンデックスラベルを生成する

これは📊グラフの軞ラベルなどに䜿甚するものです

signature_index = mutation_types.map{|i| i.join " > "}

image.png

File.binwrite("Signature/signature_index.dat", Marshal.dump(signature_index))

18. 🔧 倉異の頻床をカりントしおカタログを䜜る

  • カりントできずに゚ラヌになったものが赀い文字で衚瀺されたす
mutations_snp_trinucleotide.sum(&:size)
catalog = mutations_snp_trinucleotide.map do |mutations_per_sample|
  mutation_count = Array.new(96, 0)
  mutations_per_sample.each do |mutation|
      m = mutation.values_at(0,2)
      index = mutation_types.index(m) || mutation_types_reverse.index(m)
      if index.nil?
          # 凊理に倱敗したものを衚瀺する
          print m.inspect.red
          next
      end
      mutation_count[index] += 1
  end
  mutation_count
end
0

image.png

19. 🔧 NArrayに倉換する

catalog = Numo::DFloat[*catalog]
puts catalog.inspect

image.png

20. 💟 catalogのデヌタを保存する

catalog = sync("catalog", catalog)

21. 📚 RumaleのNMFの䜿い方を確認する

ri Rumale::Decomposition::NMF.new

image.png

22. 🔧 RumaleでNMFを実行しお 💟 モデルを保存する

  • NMFでは局所解しか求たらないので、NMF500回詊行しおみるこずにしたす。
  • コンポヌネントの数は30ずしたす。
  • modelを保存したす
  • ここでは他のツヌルや他の解析のこずも考えお500回分詊行しおいたすが、このあず実は100回分しか䜿いたせん。
FileUtils.mkdir_p("Signature/nmf")
Parallel.each(1..500, in_processes: PCORE, progress: "NMF") do |seed|
  decomposer = Rumale::Decomposition::NMF.new(n_components: 30, max_iter: 500, random_seed: seed)
  decomposer.fit_transform(catalog)
  File.binwrite("Signature/nmf/decomposer_#{seed}.dat", Marshal.dump(decomposer))
end

NMF: |=========================================================================|
1..500

これでデヌタ準備線はおしたいです。぀ぎに〜クラスタリング可芖化線〜にう぀りたす。

🎚 〜クラスタリング可芖化線〜

🐳 目次

準備

  1. 🔖 セヌブポむント甚関数を準備する
  2. 📖 ラむブラリを読み蟌む

デヌタロヌディング

  1. 📂 シグネチャヌのむンデックスラベルを読み蟌む
  2. 📂 NArrayのNMF結果を読み蟌む

可芖化しおみる

  1. 📊 NMF結果のヒヌトマップを衚瀺する
  2. 🔧 暙準化しおみる
  3. GaussianMixtureずいうのでクラスタリングする
  4. 📊 ヒヌトマップを描きなおす

t-SNEç·š

  1. 📚 Rumaleのt-SNEの䜿い方を確認する
  2. 🔧 t-SNEを実行する
  3. 💟 t-SNEの結果を保存する
  4. 📊 t-sneの結果を可芖化する
  5. 📊 クラスタリングもふくめお可芖化する

シグネチャヌ衚瀺

  1. 📊 シグネチャヌ候補の可芖化

そのほか

  1. 💟 CSVファむルを曞き出す

1. 🔖 セヌブポむント甚関数を準備する

## 今回は Signature ディレクトリにオブゞェクトを保存しおいく
require 'fileutils'
FileUtils.mkdir_p("Signature")

def sync(str, obj)
    begin
      if obj.nil?
          Marshal.load(File.binread("Signature/#{str}.dat"))
      else
        File.binwrite("Signature/#{str}.dat", Marshal.dump(obj))
        obj
      end
    rescue
      Marshal.load(File.binread("Signature/#{str}.dat"))
    end
end

2. 📖 ラむブラリを読み蟌む

require 'numo/narray'     # 行列蚈算
require 'numo/linalg'     # OpenBLAS t-SNE高速化に重芁
require 'iruby-plotly'    # 可芖化
require 'rumale'          # 機械孊習

3. 📂 シグネチャヌのむンデックスラベルを読み蟌む

signature_index = Marshal.load(File.binread("Signature/signature_index.dat"))

image.png

4. 📂 NArrayのNMF結果を読み蟌む

decomposer = (1..100).map do |i|
    Marshal.load(File.binread("Signature/nmf/decomposer_#{i}.dat"))
end
components = Numo::DFloat.vstack(decomposer.map(&:components))
puts components.inspect

image.png

5. 📊 NMF結果のヒヌトマップを衚瀺する

IRuby.plot(
    {x: signature_index,
    z: components.to_a,
    type: "heatmap"},

    {title: "TCGA シグネチャヌ候補",
        xaxis: {tickangle: 300,
            tickfont: {size: 6}},
        height: 600,
        width: 1000})

output_11_0.png

6. 🔧 暙準化しおみる

normalizer = Rumale::Preprocessing::StandardScaler.new
samples_std = normalizer.fit_transform(components.transpose)
samples_std = samples_std.transpose
puts samples_std.inspect

image.png

puts samples_std.var(axis: 1).minmax

[0.9999999999999953, 1.0000000000000049]

7. 🔧 GaussianMixtureずいうのでクラスタリングする

  • KMeansはサンプルを等分しようずするので実デヌタでは倱敗したす。
    • 耇数のシグネチャヌが同じぐらい出珟するずいう条件でシミュレヌションを実行するずKMeansでもうたくいきたす
  • こちらのアルゎリズムの内容もよくわかりたせん 
gmm = Rumale::Clustering::GaussianMixture.new(n_clusters: 30, random_seed: 5)
pca = Rumale::Decomposition::PCA.new(n_components: 50)
samples_std_pca = pca.fit_transform(samples_std)
cluster_ids = gmm.fit_predict(samples_std_pca)
puts cluster_ids.inspect

Numo::Int32#shape=[3000]
[5, 9, 21, 29, 12, 7, 14, 24, 20, 27, 2, 11, 20, 25, 18, 29, 3, 18, 22, 7, ...]

8. 📊 ヒヌトマップを描きなおす

IRuby.plot(
    {x: signature_index,
    z: samples_std[cluster_ids.sort_index, true].to_a,
    type: "heatmap"},
    {title: "TCGA シグネチャヌ候補 クラスタヌ゜ヌト埌",
        xaxis: {tickangle: 300,
            tickfont: {size: 6}},
        height: 600,
        width: 1000}
    )

output_18_0.png

9. 📚 Rumaleのt-SNEの䜿い方を確認する

ri Rumale::Manifold::TSNE.new

image.png

⏰ t-SNEは時間がかかるので、䜕回か実行した時に時間を蚘録に残せるようにしおおく

times = []

10. 🔧 t-SNEを実行する

start_time = Time.now
tsne = Rumale::Manifold::TSNE.new(n_components: 2, perplexity: 40.0, max_iter: 500, random_seed: 1)
tsne_representations = tsne.fit_transform(samples_std_pca)
times << Time.now - start_time

11. 💟 t-SNEの結果を保存する

tsne_representations = sync("tsne_representations", tsne_representations)
0

12. 📊 t-sneの結果を可芖化する

x = tsne_representations[true, 0]
y = tsne_representations[true, 1]
IRuby.plot(x: x.to_a,
    y: y.to_a,
    mode: 'markers',
    type: "scatter",
    title: "〜NMFで埗られたシグネチャ候補をt-SNEで可芖化〜",
    width: 800,
    height: 600)

image.png

13. 📊 クラスタリングもふくめお可芖化する

data = cluster_ids.to_a.uniq.sort.map do |l|
    {
        x: x[cluster_ids.eq(l)].to_a,
        y: y[cluster_ids.eq(l)].to_a,
        type: "scatter",
        mode: 'markers',
        name: "sig#{l}"
    }
end
IRuby.plot(data, {title: "〜NMFで埗られたシグネチャ候補をt-SNEで可芖化〜", height: 600, width: 800})

image.png

14. 🎚 シグネチャヌ候補の可芖化

data = 30.times.map do |l|
    s2 = components[cluster_ids.eq(l).where, true]
    s = s2.mean(0)
    color = %w(red orange green blue purple brown).map{|i| [i] * 16}.flatten
    {y: s.to_a,
     x: signature_index,
    xaxis: "x#{l+1}",
    yaxis: "y#{l+1}",
    marker: {color: color},
    type: "bar"}
end

layout = {
      grid: {rows: 10, columns: 3,
      pattern: 'independent'}}
(1..30).each do |i|
    layout["xaxis#{i}".to_sym] = {showticklabels: false}
end

IRuby.plot(data, layout)

image.png

15. 💟 CSVファむルを曞き出す

  • 今回はRubyで頑匵りたしたが、🍊 Orange などのツヌルを䜿うずGUIで䟿利に解析するこずもできたす。
  • 他のツヌルでも䜕かできるように、CSVファむルで曞き出したす。
require 'csv'
CSV.open("Signature/nmf/signatures.csv", "w") do |csv|
    csv << signature_index
    samples_std.to_a.each do |ar|
        csv << ar
    end
end
0

結果

 ここたでスクロヌルしおくれおありがずうございたす。
 今回は、GaussianMixtureずいうアルゎリズムを぀かっおクラスタリングを行うずいう単玔な方法を採甚しおいたす。結果ですが、

image.png

Signature1, Signature2, Signature6, Signature7, Signature10, Signature13, Signature14, Signature17, Signature21, Signature28 あたりは怜出できた気がしたす。Signature4 は少し怪しいですが、怜出できたこずにしたす。

 Sig1やSig10が䜕個も怜出されおいたす。これらの重耇しお怜出されたSignatureはt-SNE で䌌たような䜍眮にあるこずがわかりたす。候補8や候補13は、サンプル数が少ないのでNMFで誀怜出された局所解かもしれたせん。

 候補12や候補21は、少なくない回数怜出されおいるにもかかわらずCosmicに䌌たようなSignatureが登録されおいないものです。おそらく䜕らかのミスかアヌチファクトだず思いたすが、よくわかりたせん。゚ク゜ンのみの倉異で本圓に結果が出るか心配でしたが、思った以䞊にたくさんのシグネチャヌが怜出できたした。

 今回ある皋床怜出に成功したシグネチャヌ

COSMIC signature 関連する発がん芁因 䞻ながん皮
Signature1 5-methylcytosineの脱メチル化, 加霢 広く認められる
Signature2 APOBEC酵玠掻性 腺がんを䞭心に広くみられる
Signature4 喫煙 肺がん・頭頚郚がん・肝臓がんなど
Signature6 DNAミスマッチ修埩異垞 悪性リンパ腫など
Signature7 玫倖線 メラノヌマ
Signature10 POLE酵玠異垞 倧腞がん・子宮がんなど
Signature13 APOBEC酵玠掻性 腺がんを䞭心に広くみられる
Signature14 POLE倉異ずミスマッチ修埩異垞 悪性リンパ腫など
Signature17 䞍明 食道がん・胃がんなど
Signature21 䞍明 胃がんなど
Signature28 䞍明 倧腞がん・子宮がんなど

おたけ 🍊 〜Orangeでもう少し詳しく結果をみおみよう〜

 Orangeはスロベニアのリュブリャナ倧孊が開発しおいるGUIでデヌタ解析や機械孊習ができるツヌルです。Jupyterや生Pythonを芚えなくおもクリック操䜜で解析ができおしたうずいう、本圓に玠晎らしいツヌルです。NMFも拡匵機胜を䜿甚すれば実行できるようで、APIを叩くずころを別にすれば、このペヌゞで玹介した凊理はOrangeでみんな実行できおしたいそうです。ここでは埌線の「クラスタリング可芖化線」をOrangeでやっおみるこずにしたす。

image.png

スクリヌンショットのようにワヌクフロヌを定矩しお実行したす。はい、䟿利すぎですよ (ToT) 💊
右のt-SNEのりィンドりで芳察したいサンプルを遞択するず、自動的に䞋のりィンドりでシグネチャヌを描いおいたす。
今描かれおいるのはSignature4だず思われたす。
image.png

さらに现かく芋るず、ここの小さい集団はSignature8に近いみたいだずいうこずがわかりたした。

党䜓的にSignature10の圱響が非垞に匷いです。Signature6や、Signature23は、それに近い候補が存圚するが、Signature10番が匷烈すぎお混ざっおしたっお正しく怜出できおないのではずいう印象を受けたした。

ごく小数ながらSignature20番に近いパタヌンが怜出されおいたりしたす。しかしせいぜい2個〜4個の候補が20番にちょっず䌌おいる颚だっただけなので偶然にすぎないかもしれたせん。
image.png

たた候補13番はサンプル数が少ないず思っおいたしたが、単なる雑音ずしお無芖できなぐらい再珟性を持っお怜出されるようです。うヌん、これは䞀䜓䜕でしょう。どこか私のミスが隠れおいるのでしょうか。

 Orangeはあたり泚目されおいたせんがなぜでしょうか。それは解析APIを提䟛するこずでデヌタセンタヌに情報を集積するずいう倧手ITプラットフォヌマヌの䌁業戊略ず合臎しないためかもしれたせん。ツヌルの良し悪しを刀断するのは機械孊習゚ンゞニアです。しかし、付加䟡倀を高める競争に日々晒されおいるであろう゚ンゞニアからみるず、Orangeは䞭途半端な機胜しか持たない䜿えないツヌルに芋えるかもしれたせん。あるいは逆に、それたで゚ンゞニアが職人技でコヌドを曞いお実珟しおきたプロセスの䞀郚を、ボタンのクリックを数回やるだけで実行できるようにしおいるずいう意味で、機械孊習職人の䟡倀を毀損するツヌルのようにも芋えお、反発したくなる心理が生じるかもしれたせん。ご心配なく。そういう心理は、゚ンゞニアの䞖界に限らずどこのでもよくあるこずです。
 しかし、これから「非゚ンゞニア」の人々が䜿うデヌタ解析ツヌルは、PythonやJuliaではなく、Excel+Orangeのようなものになるんじゃないかなあず。個人的にはそんな気がちょっずしたのでした。

🎚 おたけ 〜扉絵の䜜り方〜

ペヌパヌタオルを甚意したす 1
image.png
ぶっちゃけちゃんずした画甚玙がある堎合はそっちの方がいいです。

ボヌルペンで䞋絵を曞いお、色鉛筆で塗りたす。
image.png
スキャナヌで画像を取り蟌みたす。
↓スキャナヌだずシワが写り蟌んでしたうので、カメラの方がいいかも
image.png
Gimpで画像を開いお、レベル補正など適圓に䞀通りやったら、linear invert しお Hue-Chroma で色合いを調敎したす。これでほずんど完成です。あずはお奜みで symmetric nearest neighbor など気に入ったフィルタヌをいく぀か远加したす。

扉絵のできあがり
image.png

䜕のロゎかわかるかな

この蚘事を曞くにあたっおお䞖話になったツヌルやサむトのロゎです。
image.png image.png image.png image.png image.png image.png image.png
巊から順番に、Ruby, Rumale, Plotly, cBioPortal, COSMIC, Orange, GIMP でした。

この蚘事は以䞊です。


  1. コンフォヌト サヌビスタオル200 https://pro.crecia.co.jp/product/search/index.php/item?id=11007 ↩

11
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9