StreamlitでADIFファイルCSV変換ツールを作成する

Streamlit
この記事は約9分で読めます。

こんにちは、JS2IIUです。
今回はStreamlitを活用して、アマチュア無線で交信ログとして使われるADIFデータを読み込んで、CSVファイルとしてダウンロードできるようにするツールを作成しました。作成したツールはこちらで試すことができます。

ADIF/ADIファイル変換
GitHub last commit

何らかの不具合、修正要望がありましたら本ブログのコメントもしくはSNS経由でお知らせください。

GitHubのページも整えました。

GitHub - JS2IIU-MH/StreamlitADIF: ADIF utilities on Streamlit framework
ADIF utilities on Streamlit framework. Contribute to JS2IIU-MH/StreamlitADIF development by creating an account on GitHub.

プログラムの説明

作成したPythonプログラムは以下のとおりです。PandasとStreamlitのインストールが必要です。

import pandas as pd
import re
import streamlit as st

def parse_adif_record(record):
    # Find all fields in the format <FIELD:LENGTH>value
    fields = re.findall(r'<(.*?):(\d+)>([^<]*)', record)
    return {field[0].upper(): field[2] for field in fields}

def adif_to_dataframe(file_content):
    lines = file_content.decode("utf-8").splitlines()

    # Find the line where the header ends
    start_line = 0
    for i, line in enumerate(lines):
        if "<EOH>" in line:
            start_line = i + 1
            break

    # Process records after the header
    records = []
    adif_data = ''.join(lines[start_line:]).split("<EOR>")

    for record in adif_data:
        if record.strip():
            records.append(parse_adif_record(record))

    # Convert to DataFrame
    df = pd.DataFrame(records)
    return df

# Streamlit App
st.title("ADIF/ADIファイル変換")

# ファイルアップローダー (ADIFとADIファイルに対応)
uploaded_file = st.file_uploader("ADIFまたはADIファイルをアップロードしてください", type=["adif", "adi"])

# ファイルがアップロードされたら処理
if uploaded_file is not None:
    df = adif_to_dataframe(uploaded_file.read())
    st.write("ADIF/ADIファイルの内容:")
    st.dataframe(df)

    # DataFrameをCSVに変換
    csv = df.to_csv(index=False)

    # CSVダウンロードボタン
    st.download_button(
        label="CSVをダウンロード",
        data=csv,
        file_name="adif_data.csv",
        mime="text/csv"
    )

ツールではADIF形式から一旦PandasのDataFrame形式に読み込んでいます。次のステップとしてグラフ化ツールを作る予定なので、その前準備です。

こちらのプログラムは、ADIFまたはADI形式のアマチュア無線ログファイルを読み込み、そのデータをPandasのDataFrame形式に変換し、Streamlitを使ってウェブアプリ上で表示し、CSV形式でダウンロードできるようにするものです。各部分について詳しく解説します。

parse_adif_record 関数

def parse_adif_record(record):
    fields = re.findall(r'<(.*?):(\d+)>([^<]*)', record)
    return {field[0].upper(): field[2] for field in fields}
  • 目的: ADIFレコードの1つを解析し、フィールド名とその値を取得して辞書形式に変換します。
  • 詳細:
  • re.findall<FIELD:LENGTH>value 形式のフィールドを正規表現で抽出します。
    • FIELD はフィールド名、LENGTH は値の長さ、value はフィールドの値です。
  • 結果を辞書に格納し、フィールド名を大文字 (upper()) に変換しているので、後で一貫してフィールド名を扱いやすくしています。

adif_to_dataframe 関数

def adif_to_dataframe(file_content):
    lines = file_content.decode("utf-8").splitlines()

    start_line = 0
    for i, line in enumerate(lines):
        if "<EOH>" in line:
            start_line = i + 1
            break

    records = []
    adif_data = ''.join(lines[start_line:]).split("<EOR>")

    for record in adif_data:
        if record.strip():
            records.append(parse_adif_record(record))

    df = pd.DataFrame(records)
    return df
  • 目的: ADIFファイルの内容を読み取り、各レコードを解析してDataFrame形式に変換します。
  • 詳細:
  1. ファイルの内容を読み込む:
    • file_content.decode("utf-8") でバイト形式のファイルデータをUTF-8にデコードし、splitlines() で各行に分割します。
  2. ヘッダーの終了を検出:
    • ADIFファイルは通常、<EOH> (End of Header) タグがヘッダーの終わりを示します。これを見つけて、データの開始行を決定します。
  3. レコードの解析:
    • ヘッダーの後のデータ部分を1つの文字列として結合し、"<EOR>" (End of Record) タグでレコードごとに分割します。
    • 各レコードに対して、空でないレコードだけを parse_adif_record 関数で解析し、結果をリスト records に追加します。
  4. DataFrameに変換:
    • 解析された各レコードをリスト形式からPandasのDataFrameに変換し、これを返します。

Streamlitアプリケーションの部分

st.title("ADIF/ADIファイル変換")

uploaded_file = st.file_uploader("ADIFまたはADIファイルをアップロードしてください", type=["adif", "adi"])

if uploaded_file is not None:
    df = adif_to_dataframe(uploaded_file.read())
    st.write("ADIF/ADIファイルの内容:")
    st.dataframe(df)

    csv = df.to_csv(index=False)

    st.download_button(
        label="CSVをダウンロード",
        data=csv,
        file_name="adif_data.csv",
        mime="text/csv"
    )
  • Streamlitアプリ:
  • st.title("ADIF/ADIファイル変換") でアプリのタイトルを表示します。
  • ファイルアップローダー:
    • st.file_uploader でADIFまたはADIファイルをアップロードできるUIを提供します。
    • ユーザーがファイルをアップロードすると、ファイルの内容が uploaded_file に保存されます。
  • ファイルがアップロードされた場合:
    • adif_to_dataframe(uploaded_file.read()) でファイルの内容を解析し、PandasのDataFrameに変換します。
    • st.dataframe(df) で、変換されたDataFrameをアプリ上に表示します。
  • CSVに変換してダウンロード:
    • df.to_csv() でDataFrameをCSV形式に変換します。
    • st.download_button により、ユーザーは変換されたCSVファイルをダウンロードできます。

全体の流れ

  1. ユーザーがADIFまたはADIファイルをアップロード。
  2. ファイルの内容がパースされ、ヘッダーとレコードに分けられた後、各レコードが解析されてDataFrameに変換。
  3. 変換されたデータがアプリ上に表示され、CSV形式でダウンロード可能。

主な技術ポイント

  • 正規表現: ADIFレコードのフィールドを解析する際に使用されています。
  • Pandas: データの処理・変換・表示に利用されています。
  • Streamlit: シンプルなインタラクティブウェブアプリケーションを素早く構築するためのフレームワークです。

Streamlit Community Cloudで公開する

作成したプログラムはGithubのリポジトリとして公開します。今回はこちらのリポジトリになっています。

GitHub - JS2IIU-MH/StreamlitADIF: ADIF utilities on Streamlit framework
ADIF utilities on Streamlit framework. Contribute to JS2IIU-MH/StreamlitADIF development by creating an account on GitHub.

Streamlit Community Cloudでの公開までの手順

リポジトリ作成時の注意点として、pipのrequirements.txtを作成しておく必要があります。Streamlit Community Cloudで実行する際に環境構築するのでこのファイルが必要になります。

pip freeze > requirements.txt

Streamlit Cloud にアクセス

Streamlit Cloud にアクセスし、GitHubアカウントでログインします。

新しいアプリをデプロイ

ログイン後、「New app」ボタンをクリックします。

GitHubのリポジトリを選択し、デプロイしたいリポジトリを指定します。

デプロイするブランチ(通常は master または main)とアプリのエントリーポイント(通常は app.py または main.py)を指定します。今回はフォルダ構成などの都合上main/st_adi_df_csv.pyを指定しています。

アプリをデプロイ

「Deploy」ボタンをクリックすると、Streamlit Cloudがアプリを自動的にビルドし、公開します。

アプリがデプロイされると、共有可能なURLが生成されます。このURLを他の人に共有することで、アプリを利用してもらうことができます。

ADIF/ADIファイル変換
GitHub last commit

最後まで読んでいただきありがとうございました。今後はADIFファイルからグラフを作成するツールを作成していきたいと思います。

コメント

タイトルとURLをコピーしました