Astropyでカラーバーがおかしい問題を解決した

## 元々は...
`APLpy`というモジュールの`FITSFigure`という関数(?)を使用していたが，どうやら最近の`Python`のアップデートに追いついていないらしく，`3.6`か`3.7`ぐらいでアップデートが終了し，それ以降のバージョンに対応していないようだった．
`Pyenv`でバージョン管理をしているので使えるといえば使えるがなんだか気持ち悪い．

ということで最新の`Python 3.10.1`でも`pip`経由できちんとインストールできた`astropy`だけでFITS画像の出力ができないか模索していた．

## そんなこんなで...

いろいろ参考にしてastropyとmatplotlibでFITS画像をプロットすることができたのだが．．．

```python
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from astropy.io import fits
import pyregion
from mpl_toolkits.axes_grid1 import make_axes_locatable

# read in the image
fits_name = 'fits/ngc1187_stellar_mass_distribution_3.6um_4.5um.fits'
f = fits.open(fits_name)

try:
    from astropy.wcs import WCS
    from astropy.visualization.wcsaxes import WCSAxes
    wcs = WCS(f[0].header)
    fig = plt.figure()
    ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], wcs=wcs)
    fig.add_axes(ax)
except ImportError:
    ax = plt.subplot(111)

image = ax.imshow(f[0].data, cmap=cm.jet, vmin=0., vmax=2e6)
reg_name = 'region/continuum.reg'
r = pyregion.open(reg_name).as_imagecoord(header=f[0].header)

#colorbar
divider = make_axes_locatable(ax)
colorbar_ax = divider.append_axes("top", "3%", pad="1%")
cbar = fig.colorbar(image, orientation='horizontal', cax=colorbar_ax)
colorbar_ax.xaxis.set_ticks_position('top')
plt.title('Stellar mass distribution', x=0.5, y=3)


from pyregion.mpl_helper import properties_func_default

# Use custom function for patch attribute
def fixed_color(shape, saved_attrs):
    attr_list, attr_dict = saved_attrs
    attr_dict["color"] = "red"
    kwargs = properties_func_default(shape, (attr_list, attr_dict))
    return kwargs

# select region shape with tag=="Group 1"
r1 = pyregion.ShapeList([rr for rr in r if rr.attr[1].get("tag") == "Group 1"])
patch_list1, artist_list1 = r1.get_mpl_patches_texts(fixed_color)
r2 = pyregion.ShapeList([rr for rr in r if rr.attr[1].get("tag") != "Group 1"])
patch_list2, artist_list2 = r2.get_mpl_patches_texts()
for p in patch_list1 + patch_list2:
    ax.add_patch(p)
for t in artist_list1 + artist_list2:
    ax.add_artist(t)

plt.show()
```

![cbar_okasii.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567602/7bea4888-5182-bacc-8770-56b49635e648.png)

カラーバーがなんかおかしい...なにこれ...
y軸消えないし，メッシュ入ってるし，x軸の目盛も画像に入り込んでる...
ちゃんと`colorbar_ax.xaxis.set_ticks_position('top')`とか指定してるのに...

## 色々調べた結果，解決策を発見！

冒頭に`import matplotlib.axes as maxes`を追加し，`colorbar_ax = divider.append_axes("top", "3%", pad="1%")`の部分に，`axes_class=maxes.Axes`を追加するのみ！

```python
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from astropy.io import fits
import pyregion
from mpl_toolkits.axes_grid1 import make_axes_locatable
import matplotlib.axes as maxes

# read in the image
fits_name = 'fits/ngc1187_stellar_mass_distribution_3.6um_4.5um.fits'
f = fits.open(fits_name)

try:
    from astropy.wcs import WCS
    from astropy.visualization.wcsaxes import WCSAxes
    wcs = WCS(f[0].header)
    fig = plt.figure()
    ax = WCSAxes(fig, [0.1, 0.1, 0.8, 0.8], wcs=wcs)
    fig.add_axes(ax)
except ImportError:
    ax = plt.subplot(111)

image = ax.imshow(f[0].data, cmap=cm.jet, vmin=0., vmax=2e6)
reg_name = 'region/continuum.reg'
r = pyregion.open(reg_name).as_imagecoord(header=f[0].header)

#colorbar
divider = make_axes_locatable(ax)
colorbar_ax = divider.append_axes("top", "3%", pad="1%", axes_class=maxes.Axes)
cbar = fig.colorbar(image, orientation='horizontal', cax=colorbar_ax)
colorbar_ax.xaxis.set_ticks_position('top')
plt.title('Stellar mass distribution', x=0.5, y=3)


from pyregion.mpl_helper import properties_func_default

# Use custom function for patch attribute
def fixed_color(shape, saved_attrs):
    attr_list, attr_dict = saved_attrs
    attr_dict["color"] = "red"
    kwargs = properties_func_default(shape, (attr_list, attr_dict))
    return kwargs

# select region shape with tag=="Group 1"
r1 = pyregion.ShapeList([rr for rr in r if rr.attr[1].get("tag") == "Group 1"])
patch_list1, artist_list1 = r1.get_mpl_patches_texts(fixed_color)
r2 = pyregion.ShapeList([rr for rr in r if rr.attr[1].get("tag") != "Group 1"])
patch_list2, artist_list2 = r2.get_mpl_patches_texts()
for p in patch_list1 + patch_list2:
    ax.add_patch(p)
for t in artist_list1 + artist_list2:
    ax.add_artist(t)

plt.show()
```

![cbar_saikou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567602/6b87c5de-f3b2-b92e-a7da-a4f6d92c6fb6.png)

あとは微調整するだけだ！ふううううううううう

## 参考
https://pyregion.readthedocs.io/en/latest/getting_started.html

https://stackoverflow.com/questions/47060939/matplotlib-colorbar-and-wcs-projection

### 余談

まあ，`pyregion`というモジュールはまだ3.10.1に対応していないんですけどね...
サポート続けてくれるかな...