CASA Toolkitを自前のPython環境で使用する

## 概要

CASA (Common Astronomy Software Application)とそのコアをなすCASA Toolkitは、ALMAをはじめとするデータ解析に大変有用ですが、使用するには`casapy` (実体は`casapy.py`で生成されるIPythonシェル)の上で実行する必要があります。このため自前のPython環境での実行ができず、例えばJupyter notebook (IPython notebook)などでインタラクティブかつ再現性の高い解析をするなどが困難です。そこで、Mac OSXでCASA Toolkitをコピーし、自前のPython環境でモジュールとして利用できるようにしてしまいましょう[^linux]。

[^linux]: この方法は[こちら](https://newton.cx/~peter/2014/02/casa-in-python-without-casapy/)を参考に、Mac OSX版として筆者が作成したものです。公式にサポートされた方法ではありません。

## コピーの方法

CASA Toolkitは`casac`というモジュールとして`casapy`にインポートされていますので、関連するスクリプト (`*.py`)と共有ライブラリ (`*.so`, `*.dylib`)をコピーします。ただしこれだけではダメで、各共有ライブラリで使用されているPythonの共有ライブラリのパスを、自前のPython環境のパスに変更する必要があります。最後にコピーした`casac.py`をPythonが読みに行けるように`PYTHONPATH`・`CASAPATH`を追加します。

…という一連の作業は、以下のシェルスクリプトを実行することで完了するはずです[^cltools][^pyver][^casaver][^dependances]。実行の前に、CASAのパス(`casaapp`)・コピー先のパス (`output`)・`*PATH`の書き出し先(`profile`)を自前の環境に合わせてカスタマイズしてください。もちろん実行前にはバックアップを必ずとりましょう！

```bash
$ ./extract_casatk_osx.sh
```

[^cltools]: スクリプトの実行にはXcode Command Line Toolsが必要です。
[^pyver]: `pyenv`などで複数のPython環境がある場合は、Python 2.7.xを選択してから実行してください。CASA内部のPythonのバージョンと合わせるためです。
[^casaver]: スクリプトはMac OSX版のCASAのディレクトリ構造に合わせて書かれていますので、Linux版では正しく動作しません。また、動作確認はCASA 4.5.0でのみ行っています。
[^dependances]: 一部のツールはCASA内部のデータ (`casa-data`)に依存しますので、コピー元のCASAをアンインストールしたり移動したりすると使えなくなります (`ia`など)。`CASAPATH`はこれらのために設定しています。

## モジュールのインポート 

あとは、Pythonを実行して`casac`をインポートするだけです。例えばCASAイメージ関連のツール (`ia`)は、以下のように指定することで使えます！

```bash
$ python # or ipython, jupyter notebook
```
```py
>>> import casac
>>> ia = casac.casac.image()
>>> ia.open('casaimage.image')
True
```

## 最後に

CASAにサードパーティ製のライブラリを入れるだけなら[casa-pip][casa-pip]という方法もあります。

[casa-pip]: https://github.com/astrofrog/casa-python

## シェルスクリプト

```bash:extract_casatk_osx.sh
casaapp=/Applications/CASA.app # customize this!
outputdir=${HOME}/Documents    # customize this!
profile=~/.bash_profile        # customize this!

echo "CASA directory:  " ${casaapp}
echo "Output directory:" ${outputdir}
echo -n "Press any key to continue >"
read INPUT

echo "Step 1: creating casatk directory"
casart=${casaapp}/Contents
casatk=${outputdir}/casatk
mkdir -p ${casatk}/Frameworks
mkdir -p ${casatk}/Resources/python/__casac__

echo "Step 2: copying libraries and Python scripts from CASA app"
echo "        this may take a while ..."
cp -a ${casart}/Frameworks/lib ${casatk}/Frameworks
cp -a ${casart}/Frameworks/*.jar ${casatk}/Frameworks
cp -a ${casart}/Frameworks/*.dylib ${casatk}/Frameworks
cp -a ${casart}/Frameworks/Qt*.framework ${casatk}/Frameworks
cp -a ${casart}/Resources/python/casac.py ${casatk}/Resources/python
cp -a ${casart}/Resources/python/__casac__/*.so ${casatk}/Resources/python/__casac__
cp -a ${casart}/Resources/python/__casac__/*.py ${casatk}/Resources/python/__casac__

echo "Step 3: changing Python-framework's path of libraries"
libpy_so=@loader_path/../../../Frameworks/Python.framework/Versions/2.7/Python
libpy_dylib=@loader_path/lib/Python.framework/Versions/2.7/Python
libpy_user=`python -c "import glob; from distutils import sysconfig;
print(glob.glob(sysconfig.get_config_var('LIBDIR')+'/libpython*')[0])"`

for f in ${casatk}/Resources/python/__casac__/*.so ; do
    install_name_tool -change ${libpy_so} ${libpy_user} ${f}
done

for f in ${casatk}/Frameworks/*.dylib ; do
    install_name_tool -change ${libpy_dylib} ${libpy_user} ${f}
done

echo "Step 4: exporting PYTHONPATH and CASAPATH to profile"
casapath="${casart} darwin socorro-\$(uname -p) \$(hostname -s)"
pythonpath="${casatk}/Resources/python"
echo "export CASAPATH=\"${casapath}\"" >> ${profile}
echo "export PYTHONPATH=\$PYTHONPATH:${pythonpath}" >> ${profile}

echo "Done!"
```