PythonでRINEXファイルを読み込んでみるぞ①

__RINEX(Receiver Independent Exchange Format)ファイル__とは、簡単に言うと衛星測位システムに用いられる電子基準点が衛星から受信してるデータです。...たぶん
因みに中がどんな情報なのかはほとんど知識ゼロなので、プログラムの練習も兼ねて適当に解析してみる

参考URL
 - [測位衛星システムのWiki](https://ja.wikipedia.org/wiki/%E8%A1%9B%E6%98%9F%E6%B8%AC%E4%BD%8D%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)
 - [電子基準点とは(国土交通省)](https://www.gsi.go.jp/denshi/denshi_about_GEONET-CORS.html) 

##構成環境
 - Windows10
 - Anaconda3 5.2.0 (2019年にインストールした)
 - Python3.7.3
 - PyCharm Community Edition 2019.1.1
 - 

##まずはGUI(ツールの見た目)を作るぞ
Anacondaインストールしたときに最初から入っている標準GUIライブラリである__tkinter__を使っていきます
オブジェクト指向についてはあまり意識せずにLet'sコーディング！

###GUIの実装
```Python:analyzer.py
import tkinter as tk
from calendar import isleap
from constant import *  # 自前の定義モジュール


class Widget:
    """
    GUIのウィジェット生成クラス
    """
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('RINEX Analyzer')
        self.root.columnconfigure(0, weight=1)
        self.flame = tk.Frame(self.root)
        self.flame.grid(row=0, column=0)
        [self.flame.columnconfigure(x, weight=1) for x in range(4)]

        # ここから先はボタンウィジェットなどの配置
        self.widget_dict = {}
        for cnt,ilist in enumerate(OPTION_LIST):
            tk.Label(self.flame, text=ilist[0].replace("_","\n")).grid(row=0, column=cnt)
            self.widget_dict[ilist[0]] = tk.StringVar()
            if "END" in ilist[0]:
                if not isleap(int(self.widget_dict["YEAR"].get())):
                    self.widget_dict[ilist[0]].set(ilist[1][-2])  # うるう年でないなら365
                else:
                    self.widget_dict[ilist[0]].set(ilist[1][-1])  # うるう年なら366
            else:
                self.widget_dict[ilist[0]].set(ilist[1][0])
            tk.OptionMenu(self.flame, self.widget_dict[ilist[0]], *ilist[1]).grid(row=1, column=cnt)

        self.widget_dict["GET_RINEX"] = tk.Button(self.flame, text="GET RINEX", bg="SkyBlue")
        self.widget_dict["GET_RINEX"].grid(row=2, column=3, padx=1, pady=1)
        self.widget_dict["GET_RINEX"].config(command=lambda: self.button_event())
        self.widget_dict["TEXT"] = tk.Text(self.flame, width=40, height=10)
        self.widget_dict["TEXT"].grid(row=3, column=0, columnspan=4, padx=5, pady=5)
        self.widget_dict["TEXT"].insert("end", "メッセージ出力\n")
        self.widget_dict["CANVAS"] = tk.Canvas(self.flame, width=50, height=50)
        self.widget_dict["CANVAS"].grid(row=4, column=0, columnspan=4)

        self.root.mainloop()

    def button_event(self):
        """
        ボタンを押したときの挙動を記述
        """
        # テキストボックスにメッセージ出力
        if int(self.widget_dict["START_DOY"].get()) > int(self.widget_dict["END_DOY"].get()):
            # START_DOYよりもEND_DOYが先になっている場合
            self.widget_dict["TEXT"].insert("end", "START_DOYよりもEND_DOYの日付が先になっています\n")
        elif not isleap(int(self.widget_dict["YEAR"].get())):
            # うるう年でない場合
            if int(self.widget_dict["START_DOY"].get()) == 366 or int(self.widget_dict["END_DOY"].get()) == 366:
                self.widget_dict["TEXT"].insert("end", "{0}年は366日ありません\n".format(self.widget_dict["YEAR"].get()))
            else:
                [self.widget_dict["TEXT"].insert("end", "{0}:{1}\n".format(x, self.widget_dict[x].get())) for x in LABEL_LIST]
        else:
            [self.widget_dict["TEXT"].insert("end", "{0}:{1}\n".format(x, self.widget_dict[x].get())) for x in LABEL_LIST]
        self.widget_dict["TEXT"].see("end")

# Pythonファイルをダブルクリックで起動するときに必要な記述
if __name__ == "__main__":
    try:
        Widget()  # スタートインターフェース
        print("\n正常終了")
    except Exception as _e:
        print(_e, type(_e))
        print("\n異常終了")
```

うるう年の処理が地味に面倒だった
というか、うるう年か判定できる関数あったんかい

###自前の定義モジュール
```Python:constant.py
"""定数定義モジュール"""
YEAR_LIST = ["2018", "2019", "2020", "2021", "2022"]    # とりあえず5年分定義
DOY_LIST = [str(x).zfill(3) for x in range(1, 367)]  # Day of year
ERP_LIST = ["0958", "3005", "3007", "3008", "3011",
            "3013","0223", "0224", "0753", "0754", "0755"]  # 電子基準点の局番号...とりあえず埼玉県のもを定義してみる
LABEL_LIST = ["YEAR", "START_DOY", "END_DOY", "ERP"]
OPTION_LIST = [[LABEL_LIST[cnt], i] for cnt,i in enumerate([YEAR_LIST, DOY_LIST, DOY_LIST, ERP_LIST])]  # 二重リスト
```
定数を定義したモジュールを作っときます
埼玉県の電子基準点は現在11個あるっぽい

###ここまででGUIはこんな感じ
![rnx_dler_gui 2020-04-20 224859.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299201/f6d5e749-7918-4722-db86-9132f9ebadee.png)
ふう、疲れたThey
`tkinter`の`OptionMenu`っていうは、リストボックスとかコンボボックスとか呼ばれてるものですね

##参考にしたサイトとか
- [TK Notebook いろいろなウィジェット](https://www.nakamuri.info/mw/index.php/%E3%81%84%E3%82%8D%E3%81%84%E3%82%8D%E3%81%AA%E3%82%A6%E3%82%A3%E3%82%B8%E3%82%A7%E3%83%83%E3%83%88)
- [DelftStack Tkinter でプルダウンメニューを作成します](https://www.delftstack.com/ja/howto/python-tkinter/how-to-create-dropdown-menu-in-tkinter/)
- [国土交通省 電子基準点一覧](https://terras.gsi.go.jp/observation_code.php)

##最後
ひとまず簡単なGUIはできたので
次回はRINEXファイルの取得まわりの実装をしていきたい
あと感じたのはPyCharmの使いやすさです
デバッグも簡単だし構文チェックとかPEP8規約チェックも勝手にやってくれて良い感じ

:arrow_backward: [前回の記事](https://qiita.com/kurosworld/items/7dcc28ce6f9f4b9bdbef) | [次回の記事] :arrow_forward: