チュートリアル

English

HSC Pipeline バイナリ配布所で配布しているパイプラインの 具体的な使い方を説明していきます。 ここを読む前にまずはインストールを済ませてください。

  1. 画像データの配置
  2. 較正用データを作成
  3. CCDごとの解析
  4. スタック
  5. スタック画像の解析
  6. スタック画像をレファレンスにして各CCDを測りなおす
  7. カタログを較正しなおす
  8. 画像を較正しなおす
  9. (余談) スクリプトの書き方例

画像データの配置

データフォルダの作成

データを置くフォルダを好きな場所に作ります。ここでは仮に ~/HSC として 進みます。

[user@example ~]$ mkdir ~/HSC
[user@example ~]$ # このフォルダを初期化するためのおまじない
[user@example ~]$ echo 'lsst.obs.hsc.HscMapper' > ~/HSC/_mapper

データのダウンロード

バイナリ配布所のデータリストの中から、 チュートリアル用画像をダウンロードしてください。 ダウンロードしたら、適当なディレクトリに展開してください。

[user@example ~]$ tar xvaf rawdata.tar.xz

画像を移動

ダウンロードした画像を、~/HSC の中に配置します。

[user@example ~]$ # hscPipe をセットアップ
[user@example ~]$ setup-hscpipe
[user@example ~]$ cd rawdata/
[user@example ~]$ # 画像を移動
[user@example ~]$ hscIngestImages.py ~/HSC  */*.fits --mode=move --create

↑ 移動先 (~/HSC) は絶対パスで指定しないとうまく動きません。

確認

~/HSC の下に移動した画像は、~/HSC/registry.sqlite3 に登録されます。 どのような画像が登録されたか見てみましょう。

[user@example ~]$ sqlite3 ~/HSC/registry.sqlite3
sqlite> .header on
sqlite> SELECT visit, filter, field, count(visit)
    FROM raw
    GROUP BY visit, filter, field;
sqlite> .q

次のような表示が出たら成功しています:

visit|filter|field|count(visit)
905496|HSC-G|DEN_C|112
905498|HSC-G|DEN_C|112
905500|HSC-G|DEN_C|112
905502|HSC-G|DEN_C|112
905504|HSC-G|DEN_C|112
907002|HSC-G|DOMEFLAT|112
907004|HSC-G|DOMEFLAT|112
907006|HSC-G|DOMEFLAT|112
907008|HSC-G|DOMEFLAT|112
907010|HSC-G|DOMEFLAT|112

↑もし右端のカラムの数が少ないならば、データが欠けています。

DOMEFLAT が visit=907002..907010:2 (始点..終点:間隔と表記します)、 DEN_C が visit=905496..905504:2 です。

較正用データを作成

フラットデータの作成

ドームフラットからフラットデータを作ります。 (ドームフラットの visit 番号については前述)

[user@example ~]$ reduceFlat.py $HOME/HSC \
    --calib=$HOME/HSC/CALIB_tutorial \
    --output=$HOME/HSC/rerun/calib_tutorial \
    --id visit=907002..907010:2 \
    --detrendId calibVersion=calib_tutorial \
    --config isr.doBias=False \
        isr.doDark=False \
        isr.doFringe=False \
    --do-exec --mpiexec "-n 4"

重要: --calib や calibVersion の値は、正規表現 [A-Za-z0-9_+-]+ に マッチするものでなければいけません。例えば、ピリオドを含んではいけません。

↑ "-n 4" は「4スレッドで」の意味です。

↑ --config の後ろに指定できる引数とそのデフォルト値は --show config で表示できます。

データができたら、それを登録します。

[user@example ~]$ genCalibRegistry.py \
    --root=$HOME/HSC/CALIB_tutorial \
    --camera=HSC \
    --create

ここではバイアス・ダーク・フリンジを無視しましたが、 同じようなコマンドで作れます(reduceBias.py, reduceDark.py, reduceFringe.py)。

CCDごとの解析

まずアストロメトリのために、astrometry_net_data を指定します。

[user@example ~]$ setup astrometry_net_data sdss-dr8

次にCCDごとの解析プログラムを走らせます。 (visit の範囲については前述)

[user@example ~]$ reduceFrames.py $HOME/HSC \
    --calib=$HOME/HSC/CALIB_tutorial \
    --rerun=tutorial \
    --id visit=905496..905504:2 \
    --config processCcd.isr.doBias=False \
        processCcd.isr.doDark=False \
        processCcd.isr.doFringe=False \
        doFocus=False $(: hscPipe 3.2.2 以降) \
    --do-exec --mpiexec "-n 4"
出力ファイル一覧

↑ --rerun=RERUN に指定した名前を使って、$HOME/HSC/rerun/RERUN というディレクトリが作成されます (今の場合 $HOME/HSC/rerun/tutorial)。 このディレクトリに出力ファイルが書きだされます。 これらのファイルはまた、以降のコマンドの入力ファイルとなります。

★結果のみかた★(工事中)

スタック

スカイマップを作る

モザイクの前に "tract" を作ります。 一つの WCS で張られる領域 (つまりだいたい 1 視野ぶん) を トラクトと呼びならわします。

[user@example ~]$ makeDiscreteSkyMap.py $HOME/HSC \
    --calib=$HOME/HSC/CALIB_tutorial \
    --rerun=tutorial \
    --id visit=905496..905504:2
出力ファイル一覧

↑これで tract 0 が作成されます。

モザイクする

この時点でもし latex と dvipng がシステムにインストールされていない場合、インストールしてください。 例えば redhat 系ならば

[user@example ~]$ sudo yum install dvipng texlive-latex

そしてモザイクします。

[user@example ~]$ mosaic.py $HOME/HSC \
    --calib=$HOME/HSC/CALIB_tutorial \
    --rerun=tutorial \
    --id visit=905496..905504:2 ccd=0..103 tract=0 \
    --config outputDiag=True \
        outputDir=$HOME/HSC/rerun/tutorial/output_mosaic \
    --clobber-config
出力ファイル一覧

スタックする

一つのトラクトは複数のパッチに分かれています (トラクト一個をまるまる扱うのは大きすぎるため)。 トラクトをスタックするには、スタックするパッチを指定する必要があります。 ではパッチの情報はどこにあるのかと言いますと、 (rerun ディレクトリ)/deepCoadd/skyMap.pickle に入っています。

実際に見てみましょう。

[user@example ~]$ cd $HOME/HSC/rerun/tutorial/deepCoadd
[user@example deepCoadd]$ python
>>> import pickle
>>> tracts = pickle.load(open("skyMap.pickle", "rb"))
>>> tract = tracts[0] # tract 番号 0 を選択
>>> print tract.getNumPatches()

↑この結果、下のように表示されるはずです。

(12, 12)

↑これは、12列 × 12行のパッチが存在する、という意味です(下図)

(0,0)(1,0)(11,0)
(0,1)(1,1)(11,1)
(0,11)(1,11)(11,11)

そのことがわかったら、もとのディレクトリに戻りましょう。

>>> exit()
[user@example deepCoadd]$ cd ~
[user@example ~]$

さて閑話休題です。 スタックしてパッチ (0,0) を作りたければ patch=0,0 と指定することになります。 パッチ (0,0) と (0,1) を各々作りたければ、patch=0,0^0,1 と ^ で繋げて指定します。 一つのトラクトの中の、全てのパッチを作りたければ patch=0,0^0,1^0,2.... と書いていくわけです。

しかしこれを手で書くのはやりきれないですから、次のようにします。

[user@example ~]$ # 現在のフィールド分割子を保存
[user@example ~]$ # (IFS は普通は空白文字ですから、必ず引用符で囲んでください)
[user@example ~]$ oldIFS="$IFS"
[user@example ~]$ # (0,0 0,1 0,2 ... 11,11) と全て列挙するのと同じ
[user@example ~]$ patches=({0..11},{0..11})
[user@example ~]$ # フィールド分割子を ^ にして
[user@example ~]$ IFS='^'
[user@example ~]$ # そのフィールド分割子で配列を結合する
[user@example ~]$ patches="${patches[*]}"
[user@example ~]$ # フィールド分割子を元に戻す
[user@example ~]$ IFS="$oldIFS"
[user@example ~]$ # (IFS は必ず元に戻してください)

↑この結果、$patches は次のようになっているはずです。

[user@example ~]$ echo $patches
0,0^0,1^0,2^0,3^(省略)^11,10^11,11

これを使ってスタックコマンドを発行します。

[user@example ~]$ stack.py $HOME/HSC \
    --calib=$HOME/HSC/CALIB_tutorial \
    --rerun=tutorial \
    --id filter=HSC-G tract=0 patch=$patches \
    --selectId visit=905496..905504:2 ccd=0..103 \
    --config \
        doBackgroundReference=False \
        makeCoaddTempExp.bgSubtracted=True \
        assembleCoadd.doMatchBackgrounds=False \
    --clobber-config \
    --do-exec --mpiexec "-n 4"
出力ファイル一覧

スタック画像の解析

スタック画像の解析は forcedPhotCoadd.py で行うのですが、 現在、たくさんのパッチを一度に突っ込むと タイムアウトしてしまう不具合があります。 ですので patch=$patches と書く代わりに for ループを回し、一つ一つ処理します。

[user@example ~]$ for i in {0..11},{0..11}
do
    forcedPhotCoadd.py $HOME/HSC \
        --calib=$HOME/HSC/CALIB_tutorial \
        --rerun=tutorial \
        --id filter=HSC-G tract=0 patch=$i \
        --config references.filter="HSC-G"
done
出力ファイル一覧

スタック画像をレファレンスにして各CCDを測りなおす

これも、visit=905496..905504:2 のように全部突っ込むとタイムアウトします。 ですので for ループを回して一つずつ処理します。

[user@example ~]$ # 905496..905504:2 ではないので注意
[user@example ~]$ for visit in {905496..905504..2}
do
    forcedPhotCcd.py $HOME/HSC \
        --calib=$HOME/HSC/CALIB_tutorial \
        --rerun=tutorial \
        --id visit=$visit ccd=0..103 tract=0 \
        --config references.filter="HSC-G"
done
出力ファイル一覧

カタログを較正しなおす

[user@example ~]$ calibrateCatalog.py $HOME/HSC \
    --calib=$HOME/HSC/CALIB_tutorial \
    --rerun=tutorial \
    --id visit=905496..905504:2 ccd=0..103 tract=0 \
    --config doApplyCalib=False \
    -j 4 # 4 スレッドで
出力ファイル一覧

画像を較正しなおす

[user@example ~]$ calibrateExposure.py $HOME/HSC \
    --calib=$HOME/HSC/CALIB_tutorial \
    --rerun=tutorial \
    --id visit=905496..905504:2 ccd=0..103 tract=0 \
    -j 4 # 4 スレッドで
出力ファイル一覧

以上で終了です。

(余談) スクリプトの書き方例

例えばパッチごとに細切れになった絵ではなく、全体の大きな絵が欲しい、と思ったとしてください。 hscPipe は Python 用ライブラリの巨大な集合体ですから、 Python スクリプトでそのライブラリを用いることができます。

パッチを貼り合わせて大きな絵を作るスクリプトは、例えば下のようになります。

#!/usr/bin/env python
# encoding: utf-8

# AFW (Application FrameWork) のうち画像に関するライブラリ
import lsst.afw.image as afwImage
# AFW のうちジオメトリに関するライブラリ
import lsst.afw.geom  as afwGeom

import sys

def main():
    """
    パッチを並べて大きな画像を作り、"large.fits" に保存する

    make-large-image PATCHES...
        (e.g. make-large-image *,*.fits)
    """

    if len(sys.argv) <= 1:
        print "一つ以上のパッチを指定してください"
        return 1

    largeImage = makeLargeImageFromPatches(sys.argv[1:])

    print "保存中 (しばらくお待ちください)..."
    largeImage.writeFits("large.fits")


def makeLargeImageFromPatches(filenames):
    """
    @param filenames ファイル名のリスト
    @return afwImage.ExposureF
    """

    # 全ての画像をロードするとメモリ的な意味でヤバイので
    # とりあえずメトリックの情報だけ取得する
    bboxes = []
    for filename in filenames:
        print "バウンディングボックスを取得:", filename, "..."
        bboxes.append(
            # 親 (= トラクト) におけるこのパッチの
            # バウンディング・ボックスを取得
            afwImage.ExposureF(filename).getBBox(afwImage.PARENT)
        )

    # 全ての BBox を含むような BBox を求める
    #     getMin/Max 系のメソッドの戻り値はインクルーシヴ
    #     (領域 = [min, max]) cf. getBegin/End (下で使用)
    x0 = min(bbox.getMinX() for bbox in bboxes)
    y0 = min(bbox.getMinY() for bbox in bboxes)
    x1 = max(bbox.getMaxX() for bbox in bboxes)
    y1 = max(bbox.getMaxY() for bbox in bboxes)

    width  = x1 - x0 + 1
    height = y1 - y0 + 1

    # 大きな画像を用意する
    print "画像を用意: ({}, {})".format(width, height)
    exposure = afwImage.ExposureF(width, height)

    # トラクト内における画像の位置を設定
    exposure.setXY0(afwGeom.Point2I(x0, y0))

    # Exposure から画像部分だけ抜き出す
    largeImage = exposure.getMaskedImage()

    # largeImage にパッチを貼り付けていく
    for filename in filenames:
        print "パッチを取得:", filename, "..."

        # 再びパッチをロード
        patch = afwImage.ExposureF(filename)
        bbox = patch.getBBox(afwImage.PARENT)

        # このパッチの、largeImage の中における位置
        #     getBegin/End 系のメソッドの戻り値は one past the end
        #     (領域 = [begin,end) ) cf. getMin/Max (上で使用)
        xp0 = bbox.getBeginX() - x0
        yp0 = bbox.getBeginY() - y0
        xp1 = bbox.getEndX  () - x0
        yp1 = bbox.getEndY  () - y0

        # パッチを張りつける ([]の中の記法については numpy のドキュメントなどを参考に)
        largeImage[xp0:xp1, yp0:yp1] = patch.getMaskedImage()[:]

        # 全てのパッチが同じ WCS その他の情報をもっているものだと盲信して
        # どれか一個を大きな画像にセットする
        if not exposure.hasWcs() and patch.hasWcs():
            exposure.setCalib   (patch.getCalib   ())
            exposure.setFilter  (patch.getFilter  ())
            exposure.setMetadata(patch.getMetadata())
            exposure.setWcs     (patch.getWcs     ())

    return exposure


if __name__ == "__main__":
    main()

↑のスクリプトを make-large-image.py として保存したとすると、 次のようにして使うことができます。

[user@example ~]$ setup-hscpipe
[user@example ~]$ python make-large-image.py \
    $HOME/HSC/rerun/tutorial/deepCoadd/HSC-G/0/*.fits

↑16GB以上メモリを積んでいるマシンで実行してください。 そうでないと Linux が生きることをあきらめてしまうことがあります。 出来上がった画像を閲覧するためにもそれくらいメモリが必要です。