React: AWS AmplifyコンソールでReact-routerを使用する

React-routerでページを遷移した後に更新ボタンを押すと、白紙のページになってしまいます。Amplify Console 200 (Rewrite) fails on SPA React (Router) Applicationを参考に、以下のように「書き換えて、リダイレクト」の設定を変更すると、無事動作しました。

Python: AWS Lambdaでメールを送信する

「AWS Lambda」->「関数の作成」->「一から作成」で関数を作成する。

import boto3

def send_email(source, to, subject, body):
    client = boto3.client('ses')
    response = client.send_email(
    Destination={
	'ToAddresses': [
            to
	],
    },
    Message={
	'Body': {
            'Text': {
		'Charset': 'UTF-8',
		'Data': body,
            },
	},
        'Subject': {
            'Charset': 'UTF-8',
            'Data': subject,
	},
    },
    Source=source
    )
    return response

def lambda_handler(event, context):
    source = '[メールアドレス]'
    to = '[メールアドレス]'
    subject = 'TEST'
    body = 'TEST\nTEST'
    r = send_email(source, to, subject, body)
    return r

IAMロールの設定を正しく行っていないと、以下のようなエラーが出力される。

{
  "errorMessage": "An error occurred (AccessDenied) when calling the SendEmail operation: User `XXXXXXXX’ is not authorized to perform `ses:SendEmail' on resource `XXXXXXXX’”,
  "errorType": "ClientError",
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      32,
      "lambda_handler",
      "r = send_email(source, to, subject, body)"
    ],
    [
      "/var/task/lambda_function.py",
      23,
      "send_email",
      "Source=source"
    ],
    [
      "/var/runtime/botocore/client.py",
      314,
      "_api_call",
      "return self._make_api_call(operation_name, kwargs)"
    ],
    [
      "/var/runtime/botocore/client.py",
      612,
      "_make_api_call",
      "raise error_class(parsed_response, operation_name)"
    ]
  ]
}

IAMロールにAmazonSESFullAccessポリシーをアタッチすることで解決。

Python: Boto3を使用してメールを送信する

boto3のインストール

pip install boto3

メールの送信

import boto3

def send_email(source, to, subject, body):
    client = boto3.client('ses')
    response = client.send_email(
    Destination={
	'ToAddresses': [
            to
	],
    },
    Message={
	'Body': {
            'Text': {
		'Charset': 'UTF-8',
		'Data': body,
            },
	},
        'Subject': {
            'Charset': 'UTF-8',
            'Data': subject,
	},
    },
    Source=source
    )
    return response

if __name__ == '__main__':
    source = '[送信元]'
    to = '[送信先]'
    subject = '[タイトル]'
    body = '[本文]'
    r = send_email(source, to, subject, body)
    print(r)

以下のようなエラーが出力される場合には、「Simple Email Service」->「Email Addresses」でメールアドレスを承認しておく。

Traceback (most recent call last):
  File "test.py", line 32, in 
    r = send_email(source, to, subject, body)
  File "[ファイル].py", line 23, in send_email
    Source=source
  File "/usr/local/lib/python3.7/site-packages/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/usr/local/lib/python3.7/site-packages/botocore/client.py", line 661, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.errorfactory.MessageRejected: An error occurred (MessageRejected) when calling the SendEmail operation: Email address is not verified. The following identities failed the check in region US-EAST-1: [メールアドレス]

Deep Learningを活用したゲノム変異解析ソフト「DeepVariant」を動かしてみる

「DeepVariant」はGoogle Brain と Verily Life Sciencesが開発したゲノム変異解析用のソフトウェアです。2016年には、ゲノム変異解析の精度を競う「PrecisionFDA Truth Challenge」で、現在デファクトスタンダードとなっている「GATK」などを抑えて「Highest SNP Performance賞」を受賞しました。「DeepVariant」は2017年12月4日にオープンソースとしてGitHub上にリリースされました。今回は、quick startに従って、Amazon EC2上で「DeepVariant」を実行してみます。

AWSコンソールから「サービス」->「EC2」->「インスタンス」->「インスタンスの作成」をクリックします。
Amazonマシンイメージには、「Ubuntu Server 18.04 LTS (HVM), SSD Volume Type – ami-0ac019f4fcb7cb7e6 (64 ビット x86)」、インスタンスタイプには「t2.micro」を選択しました。ストレージのサイズは8 GBで十分です。

まずは、dockerのインストールとイメージのダウンロードです。

BIN_VERSION="0.7.2"
MODEL_VERSION="0.7.2"

MODEL_NAME="DeepVariant-inception_v3-${MODEL_VERSION}+data-wgs_standard"
MODEL_HTTP_DIR="https://storage.googleapis.com/deepvariant/models/DeepVariant/${MODEL_VERSION}/${MODEL_NAME}"
DATA_HTTP_DIR="https://storage.googleapis.com/deepvariant/quickstart-testdata"

sudo apt -y update
sudo apt-get -y install docker.io
sudo docker pull gcr.io/deepvariant-docker/deepvariant:"${BIN_VERSION}"

続いて、Modelファイルをダウンロードしていきます。

mkdir -p ${MODEL_NAME}
wget -P ${MODEL_NAME} ${MODEL_HTTP_DIR}/model.ckpt.data-00000-of-00001
wget -P ${MODEL_NAME} ${MODEL_HTTP_DIR}/model.ckpt.index
wget -P ${MODEL_NAME} ${MODEL_HTTP_DIR}/model.ckpt.meta

[MODEL_NAME]フォルダの中に3つのファイルがダウンロードされたかと思います。これらは、TensorFlowのcheckpointフォーマットに当たります。

ls -1 "${MODEL_NAME}/"
#model.ckpt.data-00000-of-00001
#model.ckpt.index
#model.ckpt.meta

次に、サンプルデータをダウンロードします。

mkdir -p quickstart-testdata
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/NA12878_S1.chr20.10_10p1mb.bam
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/NA12878_S1.chr20.10_10p1mb.bam.bai
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/test_nist.b37_chr20_100kbp_at_10mb.bed
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/test_nist.b37_chr20_100kbp_at_10mb.vcf.gz
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/test_nist.b37_chr20_100kbp_at_10mb.vcf.gz.tbi
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/ucsc.hg19.chr20.unittest.fasta
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/ucsc.hg19.chr20.unittest.fasta.fai
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/ucsc.hg19.chr20.unittest.fasta.gz
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/ucsc.hg19.chr20.unittest.fasta.gz.fai
wget -P quickstart-testdata "${DATA_HTTP_DIR}"/ucsc.hg19.chr20.unittest.fasta.gz.gzi

quickstart-testdataフォルダの中に10つのファイルがダウンロードされました。

ls -1 quickstart-testdata/
NA12878_S1.chr20.10_10p1mb.bam
NA12878_S1.chr20.10_10p1mb.bam.bai
test_nist.b37_chr20_100kbp_at_10mb.bed
test_nist.b37_chr20_100kbp_at_10mb.vcf.gz
test_nist.b37_chr20_100kbp_at_10mb.vcf.gz.tbi
ucsc.hg19.chr20.unittest.fasta
ucsc.hg19.chr20.unittest.fasta.fai
ucsc.hg19.chr20.unittest.fasta.gz
ucsc.hg19.chr20.unittest.fasta.gz.fai
ucsc.hg19.chr20.unittest.fasta.gz.gzi

NA12878_S1.chr20.10_10p1mb.bamは参照配列にマッピング済みのBAMファイル、ucsc.hg19.chr20.unittest.fastaは参照配列のFASTAファイル、test_nist.b37_chr20_100kbp_at_10mb.vcf.gzは評価用の正解データ、test_nist.b37_chr20_100kbp_at_10mb.bedは評価する領域を示したBEDファイルです。

それでは、実際に実行していきます。まず、結果出力用のフォルダ作成と環境変数の設定です。

OUTPUT_DIR=${HOME}/quickstart-output
mkdir -p "${OUTPUT_DIR}"
REF=${HOME}/quickstart-testdata/ucsc.hg19.chr20.unittest.fasta
BAM=${HOME}/quickstart-testdata/NA12878_S1.chr20.10_10p1mb.bam
MODEL="${HOME}/${MODEL_NAME}/model.ckpt"

STEP1: make_examples

このステップでは、pileup(ゲノム座標ごとに塩基をカウントしたもの)を作成します。

sudo docker run \
  -v ${HOME}:${HOME} \
  gcr.io/deepvariant-docker/deepvariant:"${BIN_VERSION}" \
  /opt/deepvariant/bin/make_examples \
  --mode calling   \
  --ref "${REF}"   \
  --reads "${BAM}" \
  --regions "chr20:10,000,000-10,010,000" \
  --examples "${OUTPUT_DIR}/examples.tfrecord.gz"

2つファイルが作成されました。

ls -1 quickstart-output/
examples.tfrecord.gz
examples.tfrecord.gz.run_info.pbtxt

STEP2: call_variants

このステップでは、実際に変異解析を実行します。

sudo docker run \
>   -v ${HOME}:${HOME} \
>   gcr.io/deepvariant-docker/deepvariant:"${BIN_VERSION}" \
>   /opt/deepvariant/bin/call_variants \
>  --outfile "${CALL_VARIANTS_OUTPUT}" \
>  --examples "${OUTPUT_DIR}/examples.tfrecord@${N_SHARDS}.gz" \
>  --checkpoint "${MODEL}"
I0110 02:48:42.534190 140314581722880 call_variants.py:292] Set KMP_BLOCKTIME to 0
Traceback (most recent call last):
  File "/tmp/Bazel.runfiles_hh_Ngv/runfiles/com_google_deepvariant/deepvariant/call_variants.py", line 411, in 
    tf.app.run()
  File "/root/.local/lib/python2.7/site-packages/tensorflow/python/platform/app.py", line 125, in run
    _sys.exit(main(argv))
  File "/tmp/Bazel.runfiles_hh_Ngv/runfiles/com_google_deepvariant/deepvariant/call_variants.py", line 401, in main
    use_tpu=FLAGS.use_tpu,
  File "/tmp/Bazel.runfiles_hh_Ngv/runfiles/com_google_deepvariant/deepvariant/call_variants.py", line 295, in call_variants
    example_format = tf_utils.get_format_from_examples_path(examples_filename)
  File "/tmp/Bazel.runfiles_hh_Ngv/runfiles/com_google_deepvariant/deepvariant/tf_utils.py", line 177, in get_format_from_examples_path
    one_example = get_one_example_from_examples_path(source)
  File "/tmp/Bazel.runfiles_hh_Ngv/runfiles/com_google_deepvariant/deepvariant/tf_utils.py", line 156, in get_one_example_from_examples_path
    'Cannot find matching files with the pattern "{}"'.format(source))
ValueError: Cannot find matching files with the pattern "/home/ubuntu/quickstart-output/examples.tfrecord@.gz"

何も考えずにコピペしたら、エラーになりました。–examples “${OUTPUT_DIR}/examples.tfrecord@${N_SHARDS}.gz”の部分が、並列で実行する場合になっていました。再度実行します。

sudo docker run \
  -v ${HOME}:${HOME} \
  gcr.io/deepvariant-docker/deepvariant:"${BIN_VERSION}" \
  /opt/deepvariant/bin/call_variants \
 --outfile "${CALL_VARIANTS_OUTPUT}" \
 --examples "${OUTPUT_DIR}/examples.tfrecord.gz" \
 --checkpoint "${MODEL}"

call_variants_output.tfrecord.gzが作成されました。

ls -1 quickstart-output/
call_variants_output.tfrecord.gz
examples.tfrecord.gz
examples.tfrecord.gz.run_info.pbtxt

STEP3: postprocess_variants

このステップでは変異検出結果をVCFファイルに変換します。

FINAL_OUTPUT_VCF="${OUTPUT_DIR}/output.vcf.gz"

sudo docker run \
  -v ${HOME}:${HOME} \
  gcr.io/deepvariant-docker/deepvariant:"${BIN_VERSION}" \
  /opt/deepvariant/bin/postprocess_variants \
  --ref "${REF}" \
  --infile "${CALL_VARIANTS_OUTPUT}" \
  --outfile "${FINAL_OUTPUT_VCF}"

output.vcf.gzが作成されました。

ls -1 quickstart-output/
call_variants_output.tfrecord.gz
examples.tfrecord.gz
examples.tfrecord.gz.run_info.pbtxt
output.vcf.gz

結果は以下のようなフォーマットになります。

##fileformat=VCFv4.2
##FILTER=
##FILTER=
##FILTER=
##INFO=
##FORMAT=
##FORMAT=
##FORMAT=
##FORMAT=
##FORMAT=
##FORMAT=
##FORMAT=
##contig=
#CHROM  POS     ID      REF     ALT     QUAL    FILTER  INFO    FORMAT  NA12878
chr20   10000117        .       C       T       41.9    PASS    .       GT:GQ:DP:AD:VAF:PL      0/1:41:55:25,30:0.545455:41,0,49
chr20   10000211        .       C       T       46      PASS    .       GT:GQ:DP:AD:VAF:PL      0/1:46:59:30,29:0.491525:45,0,60
chr20   10000439        .       T       G       47.4    PASS    .       GT:GQ:DP:AD:VAF:PL      1/1:42:72:0,72:1:47,43,0
chr20   10000598        .       T       A       47.6    PASS    .       GT:GQ:DP:AD:VAF:PL      1/1:43:46:0,46:1:47,45,0
chr20   10000694        .       G       A       39.3    PASS    .       GT:GQ:DP:AD:VAF:PL      0/1:39:48:26,22:0.458333:39,0,63
chr20   10000758        .       T       A       46.5    PASS    .       GT:GQ:DP:AD:VAF:PL      1/1:43:56:0,56:1:46,46,0
chr20   10001019        .       T       G       4.6     PASS    .       GT:GQ:DP:AD:VAF:PL      0/1:5:44:31,13:0.295455:2,0,34
chr20   10001298        .       T       A       48.7    PASS    .       GT:GQ:DP:AD:VAF:PL      1/1:42:43:0,43:1:48,43,0
...

結果の評価

sudo docker pull pkrusche/hap.py
sudo docker run -it -v ${HOME}:${HOME} \
  pkrusche/hap.py /opt/hap.py/bin/hap.py \
  ${HOME}/quickstart-testdata/test_nist.b37_chr20_100kbp_at_10mb.vcf.gz \
  "${FINAL_OUTPUT_VCF}" \
  -f ${HOME}/quickstart-testdata/test_nist.b37_chr20_100kbp_at_10mb.bed \
  -r "${REF}" \
  -o "${OUTPUT_DIR}/happy.output" \
  --engine=vcfeval \
  -l chr20:10000000-10010000

良好な結果が得られました。

Benchmarking Summary:
  Type Filter  TRUTH.TOTAL  TRUTH.TP  TRUTH.FN  QUERY.TOTAL  QUERY.FP  QUERY.UNK  FP.gt  METRIC.Recall  METRIC.Precision  METRIC.Frac_NA  METRIC.F1_Score  TRUTH.TOTAL.TiTv_ratio  QUERY.TOTAL.TiTv_ratio  TRUTH.TOTAL.het_hom_ratio  QUERY.TOTAL.het_hom_ratio
 INDEL    ALL            4         4         0           13         0          9      0              1                 1        0.692308                1                     NaN                     NaN                   0.333333                   1.000000
 INDEL   PASS            4         4         0           13         0          9      0              1                 1        0.692308                1                     NaN                     NaN                   0.333333                   1.000000
   SNP    ALL           44        44         0           60         0         16      0              1                 1        0.266667                1                     1.2                1.307692                   0.333333                   0.363636
   SNP   PASS           44        44         0           60         0         16      0              1                 1        0.266667                1                     1.2                1.307692                   0.333333                   0.363636

AWS S3コマンドの使い方メモ

AWS Command Line Interfaceを使用してAWS S3を操作する方法をよく忘れるので、メモしておきます。

ファイルをダウンロード

aws s3 cp s3://[バケット名]/[ファイル名] .

ファイルをアップロード

aws s3 cp [ファイル名] s3://[バケット名]/

フォルダをダウンロード

aws s3 cp s3://[バケット名]/[フォルダ名]/ ./[フォルダ名] --recursive

フォルダをアップロード

aws s3 cp ./[フォルダ名] s3://[バケット名]/[フォルダ名]/ --recursive

Python: Boto3を使用してAmazon S3を操作するときのチートシート

インストール

$ pip install boto3
$ pip install awscli

初期設定

$ aws configure
AWS Access Key ID: [AWS Access Key ID]
AWS Secret Access Key: [AWS Secret Access Key]
Default region name: ap-northeast-1
Default output format:

S3の操作

バケットの作成

import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
bucket.create()

バケットの削除

import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
bucket.delete()

すべてのバケットを取得

import boto3

s3 = boto3.resource('s3')
for bucket in s3.buckets.all():
    print(bucket)
#s3.Bucket(name='[バケット名1]')
#s3.Bucket(name='[バケット名2]')
#...

バケット内のすべてのオブジェクトを取得

import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
for object in bucket.objects.all():
    print(object)
#s3.ObjectSummary(bucket_name='[バケット名]', key=u'[ファイル名1]')
#s3.ObjectSummary(bucket_name='[バケット名]', key=u'[フォルダ名1]/')
#s3.ObjectSummary(bucket_name='[バケット名]', key=u'[フォルダ名1]/[ファイル名2]')
#...

バケットのサイズを取得する

s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
bucket_size = 0
for object in bucket.objects.all():
    bucket_size += object.size

print('Bucket Size: {} bytes'.format(bucket_size))
#Bucket Size: [サイズ] bytes

ファイルをダウンロードする

import boto3

s3 = boto3.resource('s3')
s3.Object('[バケット名]', '[ファイル名(S3)]').download_file('[ファイル名(ローカル)]')

ファイルをアップロードする

import boto3

s3 = boto3.resource('s3')
s3.Object('[バケット名]', '[ファイル名(S3)]').upload_file('[ファイル名(ローカル)]')

署名付きURLを生成する

import boto3

s3 = boto3.client('s3')
presigned_url = s3.generate_presigned_url(
  ClientMethod = 'get_object',
  Params = {'Bucket' : '[バケット名]', 'Key' : '[ファイル名]'},
  ExpiresIn = [有効期間(秒)],
  HttpMethod = 'GET')
print(presigned_url)

Amazon Linux上で、Python + Selenium + Headless Chromeを使用してWEBスクレイピング

Amazon Linux上で、Python + Selenium + Headless Chromeを使用してWEBスクレイピングをしていきます。

前準備

まず、Amazon EC2で「Amazon Linux 2 AMI (HVM), SSD Volume Type – ami-009d6802948d06e52」を立ち上げます。

Chromeをインストールします。

sudo yum -y install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm

ChromeDriverをインストールします。

wget https://chromedriver.storage.googleapis.com/2.45/chromedriver_linux64.zip
unzip chromedriver_linux64.zip -d bin/

Python3とSeleniumをインストールします。

sudo yum install python3
sudo pip3 install Selenium

スクレイピング

test.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

def _main():
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    driver = webdriver.Chrome(options=options)

    driver.get('https://www.google.co.jp/')
    search = driver.find_element_by_name('q')
    search.send_keys('Python')
    search.send_keys(Keys.RETURN)

    time.sleep(3)
    driver.save_screenshot('search_results.png')

    driver.quit()

if __name__ == '__main__':
    _main()

Googleで「Python」を検索して、検索結果のスクリーンショットを取ります。

python3 test.py

以下のようにスクリーンショットが取得できました。

日本語の文字化け

ただし、この状態で日本語を検索すると、以下のように文字化けしてしまいます。

search.send_keys('パイソン')

そこで、日本語フォントをインストールします。

sudo yum install ipa-gothic-fonts ipa-mincho-fonts ipa-pgothic-fonts ipa-pmincho-fonts

再度実行すると、文字化けすることなく、スクリーンショットを取得できました。