本記事では、pycprops (pythonでCPROPSを使うモジュール) の使い方について紹介します。
まず pycprops をインストールします。
pip install pycprops
うまくいかない場合はドキュメントをしっかり読むか、エラーメッセージで google 検索して対処しましょう。
今回、適用データとして scimes に同梱されていた orion_12CO.fits (3D) と orion_12CO_mom0.fits (2D) を用います。
3D の場合
必要なものを import します。
import pycprops
import astropy.units as u
from astropy.io import fits
import numpy as np
import aplpy
import matplotlib.pyplot as plt
ドキュメント通りに以下を実行します。先に言っておくと、ヘッダの CTYPE3 を VELOCITY にして、さらに RESTFREQ が書かれていないとエラーが起こります。
cubefile = "orion_12CO.fits" # Your cube
mask = "orion_12CO.fits" # Mask defining where to find emission
d = 420.0 * u.pc # Distance (with units)
# ValueError: No spectral axes found in WCS
エラーが出ました。fits のヘッダを確認します。
fits.getheader(cubefile)
# SIMPLE = T / Written by IDL: Fri Sep 23 12:30:50 2005
# BITPIX = -32 / IEEE single precision floating point
# NAXIS = 3 /number of axes
# NAXIS1 = 209 /
# NAXIS2 = 177 /
# NAXIS3 = 150 /
# EXTEND = T /file may contain extensions
# BSCALE = 1.00000 / REAL = TAPE*BSCALE + BZERO
# BZERO = 0.00000 /
# BUNIT = 'K ' / UNIT OF TOTAL INTENSITY
# BLANK = -32768 / BLANK VALUE
# OBJECT = 'Orion ' / SOURCE NAME
# CRVAL1 = 226.000000000 / REF VALUE POINT DEGREE
# CRPIX1 = 1.00000000000 / REF POINT PIXEL LOCATION
# CTYPE1 = 'GLON-CAR ' / COORD TYPE : VALUE IS DEGR
# CDELT1 = -0.125000000000 / COORD VALUE INCREMENT WITH KM/S
# CROTA1 = 0.000000000000 / NO ROTATION
# CRVAL2 = -25.0000000000 / REF VALUE POINT DEGREE
# CRPIX2 = 1.00000000000 / REF POINT PIXEL LOCATION
# CTYPE2 = 'GLAT-CAR ' / COORD TYPE : VALUE IS DEGR
# CDELT2 = 0.125000000000 / COORD VALUE INCREMENT WITH COUNT DGR
# CROTA2 = 0.000000000000 / NO ROTATION
# CRVAL3 = 46485.9924316 / REF VALUE POINT DEGREE
# CRPIX3 = 1.00000000000 / REF POINT PIXEL LOCATION
# CTYPE3 = 'M/S ' / COORD TYPE : VALUE IS DEGR
# CDELT3 = -650.153696537 / COORD VALUE INCREMENT WITH COUNT DGR
# CROTA3 = 0.000000000000 / NO ROTATION
# TELESCOP= '1.2m ' /
# O_BSCALE= 0.000746469 / Original BSCALE Value
# O_BZERO = 6.91305 / Original BZERO Value
# BMAJ = 0.133333 /
# BMIN = 0.133333 /
3軸目が spectral だと認識していないようですので、以下のように書き換えます。
hdu = fits.open(cubefile)[0]
d, h = hdu.data, hdu.header
h["CTYPE3"] = "VELOCITY"
fits.PrimaryHDU(d, h).writeto(cubefile[:-5]+".header_change.fits", overwrite=True)
仕切り直してもう一回実行します。
cubefile = "orion_12CO.header_change.fits" # Your cube
mask = "orion_12CO.header_change.fits" # Mask defining where to find emission
d = 420.0 * u.pc # Distance (with units)
pycprops.fits2props(cubefile,
mask_file=mask,
distance=d,
asgnname=cubefile[:-5]+".asgn.fits",
propsname=cubefile[:-5]+".props.fits")
# ValueError: If converting from speed to wavelength/frequency, a reference wavelength/frequency is required.
長いプロセスの後にこれを言われました。RESTFREQ をヘッダに入れて仕切り直します。
hdu = fits.open(cubefile)[0]
d, h = hdu.data, hdu.header
h["RESTFREQ"] = 115271202000.0
fits.PrimaryHDU(d, h).writeto(cubefile[:-5]+".freq.fits", overwrite=True)
cubefile = "orion_12CO.header_change.freq.fits" # Your cube
mask = "orion_12CO.header_change.freq.fits" # Mask defining where to find emission
d = 420.0 * u.pc # Distance (with units)
pycprops.fits2props(cubefile,
mask_file=mask,
distance=d,
asgnname=cubefile[:-5]+".asgn.fits",
propsname=cubefile[:-5]+".props.fits")
# !!!異常に時間がかかります!!!
orion_12CO.header_change.freq.asgn.fits という名前で ID の cube が出力されます。astropy.io.fits で開いて、以下を参考にしながら自由に解析しましょう。
天文データ解析入門 その20 (pycupid: pythonでclumpfind等を使う)
テーブルは orion_12CO.header_change.freq.props.fits という名前で出力されます。
このファイルは以下のように開きます。
from astropy.table import Table
props = Table(fits.open(cubefile[:-5]+".props.fits")[1].data)
props
import pandas as pd
df = props.to_pandas()
2D の場合
結論から言うと、2D fits には対応していません。なので、無理やり cube にして実行します。
必要なものを import します。
import pycprops
import astropy.units as u
from astropy.io import fits
import numpy as np
import aplpy
import matplotlib.pyplot as plt
fitsname = "orion_12CO_mom0.fits"
hdu_2D = fits.open(fitsname)[0]
d = hdu_2D.data.reshape(1, hdu_2D.data.shape[0], hdu_2D.data.shape[1])
d_ = np.zeros_like(d)
d_[d_==0] = np.nan
d = np.concatenate([d, d_], axis=0)
h = hdu_2D.header
h["NAXIS"] = 3
h["NAXIS3"] = 2
h["CDELT3"] = 1
h["CRVAL3"] = 1
h["CRPIX3"] = 1
h["CTYPE3"] = "VELOCITY"
h["RESTFREQ"] = 115271202000.0
h["BUNIT"] = "K"
fits.PrimaryHDU(d, h).writeto(fitsname[:-5]+".fake3D.fits", overwrite=True)
orion_12CO_mom0.fake3D.fits を作りました。 0ch目にデータが入っており、1ch目には全部 NaN が入っています。
cubefile = "orion_12CO_mom0.fake3D.fits" # Your cube
mask = cubefile # Mask defining where to find emission
d = 420.0 * u.pc # Distance (with units)
pycprops.fits2props(cubefile,
mask_file=mask,
distance=d,
asgnname=cubefile[:-5]+".asgn.fits",
propsname=cubefile[:-5]+".props.fits")
# これは現実的な時間で終わります。
結果を plot してみます。
fig = plt.figure(figsize=(8, 8))
f = aplpy.FITSFigure(cubefile[:-5]+".asgn.fits", slices=[0],convention='wells', figure=fig)
f.show_colorscale(cmap="jet", aspect="equal")
f.add_colorbar()
f.colorbar.show()
plt.show()
出力されたテーブル (fits 形式) を見てみます。
from astropy.table import Table
props = Table(fits.open(cubefile[:-5]+".props.fits")[1].data)
props
pandas 形式で使いたい方は、以下のようにします。
import pandas as pd
df = props.to_pandas()
ここまで来ればあとは自由に解析できます。
同定パラメータについて
残念ながら pycprops のページには一切何も書かれていません。一応、pycprops.fits2props の引数としては以下のようになっています。
公式のページ を読むか、コードを見れば何かわかるかもしれません。
以上です。
リンク
目次