sunpy.netを用いてJSOCのFITSデータをダウンロードする

NASAのSolar Dynamics Observatory(SDO)で観測されたデータは、Joint Science Operations Center (JSOC)にアーカイブされています。

JSOCのデータにアクセスするには、手動でダウンロードしたり、curlやwgetでダウンロードする方法もありますが、太陽のデータ取得や解析を行うためのライブラリである[sunpy](https://sunpy.org/)を使うのが一番便利です。

JSOCにアーカイブされたデータをsunpyを使ってダウンロードする方法を解説していきます。


## JSOCにメール登録
JSOCのデータをダウンロードするには、まずはJSOCにメールアドレスを登録する必要があります。登録は2~3分ほどで終わります。

①こちらのサイトでメールアドレスを入力します。
http://jsoc.stanford.edu/ajax/register_email.html

②こんなメールが送られてくるので、内容を変更せず返信します。
メール下部に書いてあるハッシュを見てるっぽいですね。
![スクリーンショット 2022-10-27 21.11.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78906/70d96fa9-8487-e3e4-c40c-a522a89231ab.png)

返信
![スクリーンショット 2022-10-27 21.12.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78906/b7f70acb-f0c5-4361-4cfa-72e58b39dd47.png)

③メール登録完了の確認メールがきます。


## JSOCClientを使ってダウンロード

```python
import astropy.units as u
from sunpy.net import jsoc
from sunpy.net import attrs as a

s_date = '2015/1/1T00:00:00' # 開始日時
e_date = '2015/1/2T00:00:00' # 終了日時
series = 'aia.lev1_euv_12s'  # シリーズ
email = 'me@example.com'     # 登録したメールアドレス

out_dir = "/path/to/save/directory" # 保存先

client = jsoc.JSOCClient()  

response = client.search(a.Time(s_date,e_date),
                         a.jsoc.Series(series),
                         a.jsoc.Segment('image'),
                         a.Wavelength(211*u.AA), #波長
                         a.Sample(72*u.minute), #サンプリング間隔
                         a.jsoc.Notify(email))
print(response)

requests = client.fetch(response, path=out_dir, progress=True)
```
日時の指定の仕方: http://jsoc.stanford.edu/ajax/RecordSetHelp.html
seriesのリスト: http://jsoc.stanford.edu/JsocSeries_DataProducts_map.html

シリーズに関しては、同じAIAでも、12s、24s、3600sなどいくつかのcadenceの選択肢があります。これらは単に同じデータを異なる時間間隔で保存しているのではなく、それぞれで保存してある波長が異なります。自分がダウンロードしたいシリーズがどれであるかをしっかり確認することをおすすめします。

サンプリング間隔も設定することができます。このコードでは、72分に1枚(24時間で20枚)という設定にしています。何も設定しないと、cadence=12sなので、24時間あたり約7200枚になります。

### ちょっと解説

JSOCClientによるダウンロードのプロセスは三段階に分割されます。

①`search`メソッドにより、検索クエリに一致するJSOCレコードを探索します。一致するレコードのテーブルが返り値として`response`に格納されます。

```
       T_REC         TELESCOP INSTRUME WAVELNTH CAR_ROT
-------------------- -------- -------- -------- -------
2011-06-01T00:00:02Z  SDO/AIA    AIA_2      211    2110
2011-06-01T04:48:02Z  SDO/AIA    AIA_2      211    2110
2011-06-01T09:36:02Z  SDO/AIA    AIA_2      211    2110
                 ...      ...      ...      ...     ...

2012-05-31T09:36:02Z  SDO/AIA    AIA_2      211    2124
2012-05-31T14:24:02Z  SDO/AIA    AIA_2      211    2124
2012-05-31T19:12:02Z  SDO/AIA    AIA_2      211    2124
Length = 1822 rows

# このログは例です。上のコードを実行してもこのような結果にはなりません

```

②次に、`fetch`メソッドにより、これらのレコードをダウンロード用にステージングするように要求します。このプロセスは結構時間がかかるときがあります。
```
Export request pending. [id="JSOC_20221028_540", status=2]
Waiting for 0 seconds...
Export request pending. [id="JSOC_20221028_540", status=1]
Waiting for 5 seconds...
Export request pending. [id="JSOC_20221028_540", status=1]
```

③ステージングが終了し、ダウンロードできるようになると、登録したメールアドレスに通知がきます。同時に、プログレスバーが表示され、ダウンロードが自動的に始まります。

![スクリーンショット 2022-10-29 3.24.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78906/e2dffee1-b504-aa32-fe38-739ad26fb2f7.png)
![スクリーンショット 2022-10-29 3.37.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78906/6bdae6a2-6a7d-8e45-a9d0-291eed65943a.png)

sunpy.netはdrmsを内部的に使用しているようです。drmsのquery stringなどのわかりにくい部分をよりヒューマンフレンドリーにしたのがsunpy.netということでしょうか。
逆にいえば、drmsを使えば全く同じことができますが、多くの人はsunpy.netで事足りると思います。