JF1DIR業務日誌(はてなblog版)

アマチュア無線局JF1DIRのアクティビティをつづっています。

バッテリーの充放電特性の測定

久々に運用でないネタです^^;
移動運用などでバッテリーを使用していると、バッテリーの調子や寿命が気になるところです。バッテリーが完全にダメになっているときは、満充電時放電直後の電圧がおかしかったり(瞬時に電圧が低下する)やいつまで経っても満充電されないなどの症状が出るので判明しやすいのですが、そうでないときはなかなか分かりません。シールドバッテリーだと電解液の様子がまるで分かりません。バッテリーの診断方法はいろいろあるようですが、充放電特性を計測してみるのが基本だと思いますので、やってみました。

任意の電流値でバッテリーを定電流放電させて、バッテリーの端子間電圧の時間経過を測定すればよいということです。定電流負荷は電子負荷を使えば簡単です。自作の電子負荷装置を活用してみました。電圧の測定はなんでも良いのですが、手持ちのDMM(Keithley 2000)をシリアル通信によってロギングすることにしました。プログラミングもせっかくなのでLinux上のpythonでやってみます。Linuxでシリアル通信は初めての試みなので、備忘録代わりに設定から書いてみます^^;

まずはシリアル通信の設定方法。使用しているPCには当然RS-232Cポートがないので、USBシリアル変換アダプターを用意しました。バッファロのBSUSRC06という型番のもので、FTDIのFT232RLが使われています。他のものでも動くと思います。PCに挿してdmesgコマンドを使うとどこのポートに割り当てられたかわかります。

jf1dir@dir:~$ dmesg | grep 'USB' | tail
・
・
・
[ 6828.533327] usb 2-1.1: new full-speed USB device number 7 using ehci-pci
[ 6828.626947] usb 2-1.1: New USB device found, idVendor=0403, idProduct=6001
[ 6828.626955] usb 2-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 6828.626959] usb 2-1.1: Product: USB <-> Serial
[ 6828.627682] ftdi_sio 2-1.1:1.0: FTDI USB Serial Device converter detected
[ 6828.628132] usb 2-1.1: FTDI USB Serial Device converter now attached to ttyUSB0
jf1dir@dir:~$ 

ここでは/dev/ttyUSB0に割り当てられたことがわかります。ubuntuだけの問題なのか、このポートは読み書きの権限が一般ユーザーにありません。

jf1dir@dir:~$ ls -l /dev/ttyUSB0 
crw-rw---- 1 root dialout 188, 0 1229 20:40 /dev/ttyUSB0
jf1dir@dir:~$ 

この問題を回避する方法で一番簡単なのが、/etc/udev/rules.dの下に.rulesという拡張子のファイル(ファイル名はなんでもOK)に

KERNEL="ttyUSB*", MODE="0666"

と書いておけばOKです。sudo service udev restartで再起動してもう一度変換アダプターをPCに挿すと書き込みの権限がついた状態でポートが生成されているはずです。

次に、DMMのRS-232C端子にUSBシリアルアダプタを接続して動作チェック。WindowsならハイパーターミナルやTeratermに、Unixならばgtktermで接続し、SCPIコマンド":INIT"の後、":MEAS:VOLT:DC?"とすると電圧をワンショット測定し測定結果が表示されるはずです。SCPIコマンドはメーカーに関係なくほぼ共通です。詳しくはDMMのマニュアルを参照^^;

次にハードの設定。バッテリーの端子とDMMを接続します。今回はマルチプレクサも用意できたのでスキャナカードのch1にバッテリー端子間、ch2に電子負荷の電流値シャント端子を接続しておきました(電流値を電圧値としてセンス)。

DMMとの通信チェックがOKならば、次に、pythonのシリアル通信ライブラリのpySerialをpipを使ってインストールします。せっかくなのでpython3用にインストールしました^^;

ロギングプログラムのpython3ソードコードはこちら。測定停止はCTRL+Cで強制停止させてます^^;

import serial
import time
ser = serial.Serial(port = '/dev/ttyUSB0', baudrate = 9600, 
                    bytesize = serial.EIGHTBITS,
                    parity = serial.PARITY_NONE,
                    xonxoff = 0,
                    rtscts = 0,
                    timeout = 1)
start = time.time()
ser.write(b':INIT:CONT\r\n')
ser.write(b':SENS:VOLT:NPLC 1\r\n')
while True:
	time.sleep(10)
	ser.write(b':ROUT:CLOS (@1)\r\n')
	ser.write(b':MEAS:VOLT:DC?\r\n')
	v_value = float(ser.readline().decode('utf-8'))
	ser.write(b':ROUT:CLOS (@2)\r\n')
	ser.write(b':MEAS:VOLT:DC?\r\n')
	i_value = float(ser.readline().decode('utf-8')) / 0.0317
	elasped_time = float(time.time() - start) / 60.0
	print("T:%6.2f, V:%10.6f, I:%10.6f" % (elasped_time, v_value, i_value))
ser.close()

python3のpySerialでは送受信データはstr型ではなくbytes型なのでb'foobar'のようにbをつけて明示的にbytes型にしないとエラーが出ます。センス電圧を0.0317で割ると電流値が得られるのでそう指定しておきます。
サンプリング間隔はsleep文で10秒に設定したのですが、NPLC(積分時間)が1秒なので測定に各チャンネル1秒必要になります。従って、約12秒ほどのサンプリング間隔となっています。

プログラム開始とともに電子負荷をONにすると定電流放電が始まります。ログファイルをグラフ化するとこのような放電特性が得られます。

ここで例としてかなり使い古した10.8V(単セル3.6V)10Ahのリチウムイオン電池を3A(0.3C)の定電流で放電したときの放電特性を示しました。約90分で電圧が急降下していることがわかりますが、90分ではまだ4.5Ahです。従って、だいぶ古くなっていることがわかりました(汗)。丁寧に調べるには放電電流を変えて、放電停止(1セルあたり2.5Vくらい)まで放電して特性を調べるとよいようです。

1エリアAMコンテスト参加

またしばらく更新をサボってしまいました。KCWAコンテストに参加したので参加記を書こうと思っていたのですが、忘れているうちに表題コンテストが始まったのでKCWAのことは省略です(7単で参加していたのですが15時には国内が聞こえなくなってつまらなかった、というだけ^^;)。

1エリアAMコンテストは一昨年に初めて参加しておしくも入賞を逃したので、今回で2回目ですがなんとか入賞を狙いたいところです。ちなみに去年は仕事の都合で参加ならず、今年は休暇を取りました。

運用した高台はそれほど高くなく、東京・横浜方面しか向いていないのですが、過去の実績によるとそれほど悪くないので、RadixのHB9CVを上げました。リグはFT-857に25Wです。今回は6mのAMモード(電話)のみなので、電信のセットがなくてセットアップは楽ちん。部門は1エリア移動局です。

開始10分前にバンドをワッチすると、なんと50.500〜50.700MHzはすべて使われている。こりゃ出遅れたかと悔やみつつ、50.720MHzをキープしコンテストに突入。最初はパラパラと呼ばれますが、低い方から呼んでくる人が大多数なので、この辺周波数は少し待てばパイルになるはず。こんな高い周波数で呼ばれるかどうか不安でしたが、10:15からパイルがずっと続きました。やはり電話でパイルを捌くのは格別です。90Q/hのペースでスタートダッシュはまずまずでしょうか。

11:30ごろからS/Pへ回ると、コンテスト周波数の50.500から50.900MHzまで10kHzセパでぎっしりと埋まっていました。ものすごい人気だということがよくわかりました。このコンテストの難しいところは、あまりにも強い局が相手だとゼロインしにくいようで、呼ばれる方は聞きにくくてけっこう大変です。また10kHzセパででているのがほとんどですが、中にはVFOが狂っているのか、聞こえなくて空いていると思って出ているのか隣とのセパが5kHzなどの半端なところに出てこられると、QRMMで呼ぶに呼べないRunning局が少なくなかったです。それと変調の調整が上手くいっていない局もわりに多くいつもよりも難儀しました。

とまぁスプリントでS/Pに深入りしすぎるといけないので、開いている周波数を探す目的でS/PとRunningを繰り返しました。あっという間に3時間が過ぎ、スコアは去年の2位くらいになりました。ロケのためかやっぱり東京・神奈川がほとんどでしたが、
1エリアはすべてQSOでき、エリア外は静岡のみでした。前回は7エリア取れたんだけど今年は出てなかったのかな。

今年のコンテストはこれで終わり。今年も多くのQSOありがとうございました。来年もお手柔らかにお願いします。

東京UHFコンテスト参加

本日も例年通り東京UHFコンテストに参加しました。
毎年ぼやいているかもしれませんが、祝日に開催しているせいで、違法モービル局からの妨害に参りました。特に高台からやっているとほぼ全ての周波数(430.000から439.980までほとんど)で聞こえてくるので、困ったものです。特に今年はひどい妨害を受けました。

去年は都外430MHz部門で2位を頂いたので、そろそろマルチバンドへ進出しようと、430と1200MHzだけですが、アンテナとリグを持参して高台に登って運用しました。430MHzはRadixの5エレ、1200MHzは改造7エレ八木、リグはそれぞれFT-857(10W)とDJ-G7(1W)です。1200MHzはFMのみの運用となりました。

開始早々、Running周波数の確保に失敗。メインからだいぶ離れたところなのかレートが悪くスタートダッシュに失敗します。早々にS/Pに回りなんとかレートを60Q/h台に載せましたが不本意。次に1200MHzへQSYしますが、設備が貧弱なためかS/Pではパイルに負けてしまってイマイチ。適当なところでRunningすると、設備の割りと呼ばれました。1200MHzでTK UHFに参加するのは初めてなので新鮮です。次に430MHz CWへQSYするとこれも結構呼ばれます。このコンテストは電信部門がないので(全て電信電話部門)CWをやるひとはあまり居ないはずなのですが・・・。すぐに呼ばれなくなるので430MHz FMへ行くのですが、相変わらず周波数の空きがなく満足に運用できない状態が続きました。1200MHz FMと430MHz SSBやCWへ行ったり来たりがしばらく続きました。

ラスト1時間になって433.080MHzという絶好の周波数を確保することができ(違法モービルから執拗な妨害を受けたけど)ラストスパートをかけなんとかスコアメイクできたようです。やはりRunning周波数は大事ですね。最終的には、313QSO(473pts)(マルチ内緒)となりました。


●ハイライト

  • 雨が振りそうなWXだったけど、なんとか(運用中は)持ってくれた。
  • 1200MHzのコンテスト運用は久々なのでちょっと新鮮。DJ-G7大活躍。
  • CWが意外に呼ばれて楽しかった。もちろん昼ごはんタイムはCW叩きながら。
  • ノートPCの電源がいつもは持たないので超節約モードで動作したら余裕で6時間持った。

●ローライト

  • DJ-G7の電源ケーブルを忘れた。内蔵バッテリーだけでなんとか持ってくれた。
  • リュックからFT-857を取り出すと、なんとセレクトつまみの軸が折れている。リグのファンクションを変えるのが極めて困難。FT-817もそうだけどこの機種の最大の弱点がこの軸(汗)。過去に3度ほど折っている。
  • 突如CTestWinが動かなくなる。なにか文字を入力すると強制終了に。再起動しても直らない。仕方ないので、4G接続が不安定な移動先でテザリング接続し最新バージョンのCTestWinをダウンロードし、古いのをアンイストールし、別のフォルダに再インストールするとなんとか直った。ダウンロードと再設定やらなにやらで30分以上ロスし、12時台は30Q/hしかできなかった。
  • 撤収時に雨が降ってきた(下山したらすぐに止んだ)。


といつもながらトラブル多発でしたが(汗)、去年実績の2位のスコアになりました。各局QSOありがとうございました。

泉州サバイバルマラソンコンテスト参加

数ある国内コンテストの中でもかなり異色な雰囲気がある泉州サバイバルマラソンコンテストに今年も参加しました。11/10〜20と11日間あるマラソンコンテストなのですが、平日はあまり乗り気がせずほとんど運用しませんでした。代わりに会期中に2回ある日曜日に高台へ移動して固めて運用してきました。従って、日数マルチはさっぱりなわけです。

ばっさばっさと捌いていくコンテストスタイルではなく、ちょっと雑談を挟みながらのんびりとやるのがこのコンテストのスタイル。なので、日曜日に固めて数多くQSOするというのは、ちょっと難しかったです。それでも約300QSOは日曜日だけで稼ぎました。

といはいえ、いつもはとは違った雰囲気が楽しめました。今年は1st QSOの方も多くいらしゃって(多くは復活再開局のようです)とてもFBでした。また2m各局来年(?)よろしくお願いします。

以前から気になっていたのですが、LRT局が指摘しているとおり、EMEや非TEST局とのQRMを避けるため、このコンテストもJARLコンテスト周波数に従ったほうが良いのではと思いました。意見箱に書いておきます。

Pandasでログ統計処理スクリプト(その3)

コールサイン文字列から国内エリアと日本以外の局を判別する関数です。あまり厳密な方法ではないです(例えば/MMやゲストオペレータのコールなど)。python正規表現のマッチングがシンプルに書けないし、後方参照が仕方がまどろっこしいので困ったものです。

def call_area(callsign):
	jacall_re = re.compile('(^J[AD-S]\d)|(^[78][J-N]\d)')
	area_ja_re = re.compile('^J[AD-S](\d)')
	area_7_re = re.compile('^7[K-N][1-4]')
	area_7j_re = re.compile('^7J(\d)')
	area_8_re = re.compile('^8[J-N](\d)')
	area_jd1_re = re.compile('^JD1')
	call_sp = callsign.split('/')
	if len(call_sp) >= 2:
		if jacall_re.search(call_sp[0]):
			m_areanum = re.match('(\d)', call_sp[1])
			if m_areanum:
				area = 'JA' + m_areanum.group(1)
			else:
				area = 'DX'
		else:
			area = 'DX'
	else:
		if jacall_re.search(callsign):
			m_ja = area_ja_re.search(callsign)
			m_7 = area_7_re.search(callsign)
			m_7j = area_7j_re.search(callsign)
			m_8 = area_8_re.search(callsign)
			if m_ja:
				area = 'JA' + m_ja.group(1)
			elif m_7:
				area = 'JA1'
			elif m_7j:
				area = 'JA' + m_7j.group(1)
			elif m_8:
				area = 'JA' + m_8.group(1)
		else:
			area = 'DX'
		m_jd1 = area_jd1_re.search(callsign)
		if m_jd1:
			area = 'DX'
	return area

この関数を使って例えば、

In [12]: call_area('JF1DIR')
Out[12]: 'JA1'

In [13]: call_area('JF1DIR/9')
Out[13]: 'JA9'

In [14]: call_area('KH0/JF1DIR')
Out[14]: 'DX'

とエリアに対応する文字列を返します。前回の(その2)でこの関数を使って新たに'area'列にエリア文字列の列を作っておきました。
さて、ここからが本番です。
まずはこのログからどのバンドの運用があったのかを調べるのは、

In [15]: set(log.freq)
Out[15]: {3.5, 7.0, 14.0, 21.0, 28.0}

とします。log.freqでfreq列のリストが得られ、そのset(重複を除いたリスト)を表示させればよいのです。
次に、ログのすべてのデータから、エリア別の統計を取りたい場合は、

In [16]: log.area.value_counts()
Out[16]: 
DX     419
JA1     29
JA3     12
JA2     11
JA0      9
JA7      7
JA6      6
JA4      4
JA8      2
JA5      1
Name: area, dtype: int64

で得られます。python/pandasの偉いところはIPythonのインタラクティブ表示やスクリプト内のprint()文で表示させるとちゃんと整形されて表示されるということです。ちなみに、このメソッドの返り値はSeries型になっているので、

In [17]: a = log.area.value_counts()

In [18]: a[0]
Out[18]: 419

In [19]: a.index[0]
Out[19]: 'DX'

で個々の値に参照することができます。
例えば7MHzの運用分だけでエリア別統計を取りたい場合は、freq列にフィルターをかけてカウントします。

In [20]: log[log.freq==7].area.value_counts()
Out[20]: 
DX     59
JA1    16
JA2     7
JA3     6
JA0     5
JA7     5
JA4     1
JA6     1
JA5     1
Name: area, dtype: int64

QSO数だけならば、

In [21]: log[log.freq==7].area.count()
Out[21]: 101

でよいです。
QSO時間でログを切り取る、例えば、2012年5月26日18時〜24時までのデータだけを切り出す場合は、

In [22]: log[(log.datetime>=datetime(2012,5,26,18,0,0,0))&(log.datetime

のようにします。
call列をキーにログ全体をソートするには、

In [23]: log.sort('call').head()
Out[23]: 
       call            datetime  urrst  myrst  freq mode  urnr  mynr area
66    3V8BB 2012-05-26 06:25:00    599    599  21.0   CW    67   503   DX
33     3Z2X 2012-05-26 05:20:00    599    599  21.0   CW    34    68   DX
41    6M0NR 2012-05-26 05:32:00    599    599  21.0   CW    42   172   DX
165   6M0NR 2012-05-26 11:38:00    599    599   7.0   CW   167   192   DX
141  7J1YAJ 2012-05-26 10:55:00    599    599   7.0   CW   143  3039  JA1

ただし元のlogデータフレームには影響しない非破壊のメソッドです。
以上のようなデータフレームに対するメソッドを駆使すればやりたいことは大体出来てしまいます。位置から自分でプログラミングすると結構面倒ですが、上記メソッドをスクリプト内に組み込んであげれば各種統計解析が可能となります。いかがでしょう?pythonの概念がわかってしまうと意外と簡単ですよね。

Pandasでログ統計処理スクリプト(その2)

pandasを使うとたった一行でCSV形式のログファイルをデータフレームに収めることができます。データフレームは行と列のインデックスで管理するExcelファイルのようなものです。まずはQSO数を確かめてみましょう。これはデータフレームの行数を調べれば良いので、

In [3]: len(log)
Out[3]: 500

などとします。他にもやり方がありますので調べてみてください。
さて、HAMLOG形式の文字列を取り込んでいるので不都合なことがあります。それは時刻です。'datetime'と'time'という列インデックスにとりあえず日付と時刻を当てはめてみましたが、このままでは文字列データに過ぎないので、大小の比較などができません。またJSTUTCが混在している場合もあります。そこで、以下のようなスクリプトUTCへ変換しかつdatetime形式にして'datetime'列に上書きしてしまいましょう。

date_list = log.datetime
time_list = log.time
datetime_list = []
for i, s in enumerate(date_list):
	date_str = s + '-' + time_list[i]
	logdate = datetime.strptime(date_str.rstrip('JZU'), '%y/%m/%d-%H:%M')
	if time_list[i].find('J') == 5:
		logdate = logdate - timedelta(hours = 9)
	datetime_list.append(logdate)
log.datetime = datetime_list
del log['time']; del log['jcc']; del log['gl']; del log['qsl']
del log['name']; del log['qth']; del log['rem3']

元のスクリプトlogstat.pyの後ろに上記スクリプトを書き加えてもう一度ipythonでrunさせます。log.head()でログデータの一部を見てみると、datetime列が若干変わっているはずです。GLやQTHなどの列もこの場合不要なのでdelコマンドで削除してしまいました。

In [5]: log.head()
Out[5]: 
     call            datetime  urrst  myrst  freq mode  urnr  mynr
0   HS7AT 2012-05-26 04:04:00    599    599  21.0   CW     1   137
1    R9UT 2012-05-26 04:13:00    599    599  21.0   CW     2    96
2  E21EIC 2012-05-26 04:14:00    599    599  21.0   CW     3   236
3    NH2T 2012-05-26 04:15:00    599    599  21.0   CW     4   559
4    PT5T 2012-05-26 04:16:00    599    599  21.0   CW     5   471

datetime列がpythonで時刻として扱える型になっています。確認したい場合は、列だけをリスト表示させます。長いのでやはり先頭の5つだけ表示させたいので、.head()をつけます。

In [7]: log.datetime.head()
Out[7]: 
0   2012-05-26 04:04:00
1   2012-05-26 04:13:00
2   2012-05-26 04:14:00
3   2012-05-26 04:15:00
4   2012-05-26 04:16:00
Name: datetime, dtype: datetime64[ns]

のようにリストの要素データの型がdatetime64となっているのを確認できます。
次に、コールサインからエリアを判別する関数call_area()を作っておいて(後述)、ログにあるコールを一つ一つその関数を呼び出してエリアの文字列をリストを作って、データフレームに'area'という列を新しく作って、加えるということをします。

callarea_list = []
for c in log.call:
	callarea_list.append(call_area(c))
log['area'] = callarea_list
In [11]: log.tail(30).head()
Out[11]: 
       call            datetime  urrst  myrst  freq mode  urnr  mynr area
470    P40H 2012-05-27 09:33:00    599    599  14.0   CW   473  1742   DX
471  JA2VHO 2012-05-27 11:19:00    599    599   7.0   CW   474   706  JA2
472    K7RF 2012-05-27 11:20:00    599    599   7.0   CW   475   849   DX
473   N6WIN 2012-05-27 11:23:00    599    591   7.0   CW   476   440   DX
474    KT5J 2012-05-27 11:27:00    599    599   7.0   CW   477  1353   DX

のように、area列に日本のコールにはエリア、日本以外のコールにはDXと識別されたデータを付与しておきます。以上で、データの加工は終わりました。次からログデータの統計処理です。

・・・つづく・・・

Pandasでログ統計処理スクリプト(その1)

特にブログに書くことがなくネタ切れであります。今回はコンテストでもなく移動運用でもなく自作ネタでもない、ソフトウエアの話題にしましょうか。

長年無線運用をやっていて交信ログがある程度の量になってくると、交信統計というのをやってみたくなるものです。例えば、バンド・モードごとやDX/国内エリア別の交信数の統計は運用スタイルやアクティビティを反映するものなので分析するとなかなか興味深いものです。

Turbo HAMLOGやCTestWinなどのログソフトでも統計分析が可能ですが、細かいところには手が届いていません。例えば、移動局と固定局の割合を調べたり、記念局の交信数を調べること(簡単には)できないようになっています。ログデータを解析するのはさほど難しくないので、PerlRuby, Pythonなどの文字列解析が得意なスクリプト言語に親和性のある方は、自分で解析スクリプトを作るのが良いかと思いますし、当局もRubyPythonの勉強がてら分析スクリプトを自分で作っています。

実際にプログラミングしたり開発環境を調べているとデータ分析用のライブラリとして有名なPandasを使うとなかなか便利だということに気が付きました。PandasはPythonで動作するデータ解析支援ライブラリで、科学技術数値データを扱うときに便利です。今回は交信ログの解析に使うので、かなりもったいない使い方ではありますが、後に述べるようにメソッドが充実しているので、こちらのプログラミングが非常に楽になります。せっかくですから最新プログラミングツールを無線活動に活用してみましょう。では例を少しお見せしたいと思います。

データはTurbo HAMLOGのCSV形式とします。CTestWinが出力するHAMLOG形式でもOKです。ご自分の交信ログからCSV形式でログを変換してみてください。他のログソフトでも少しカスタマイズすれば使えます。

次にPythonの開発環境を手に入れてください。WindowsMacでも良いですが、Unix(Linux)のほうがいろいろと便利です。Pythonはバージョン2と3があるのですが、2でもOKですが、できれば3を選んでください。
次に、IPythonを用意してください。Pythonインタラクティブツールで、これがあると割と便利です。IPythonも(できれば)バージョン3を選んでください。次にライブラリのPandasも必要となります。これらツールとライブラリはPIPで入手できます。すでにインストールされているライブラリはシェル上でこのようにして確認できます。

~$ pip3 list

pandasがこのリストに含まれていなかったら、

~$ pip3 install pandas

としてお使いの環境にPandasをPython3用にインストールしてください。

次に、以下のスクリプトをlogstat.pyという名前のファイルにセーブします。そのスクリプトと同ディレクトリにHAMLOGのcsvファイルを置いておきます。

# logstat.py
import sys
import re
import pandas as pd
from datetime import datetime, timedelta

columns_list = ['call', 'datetime', 'time', 'urrst', 'myrst', 'freq',
                'mode', 'jcc', 'gl', 'qsl', 'name', 'qth', 'urnr', 'mynr', 'rem3']
log = pd.read_csv(sys.argv[1], names=columns_list)

シェル上で、ipython3を実行します。

~$ ipython3
Python 3.5.2 (default, Sep 10 2016, 08:21:44) 
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: 

となるので、先のスクリプトCSVログファイル(2012WPXCW.csv)を指定して実行します。

In [1]: run logstat.py 2012WPXCW.csv

In [2]: 

となると成功。次にインタラクティブモードでログデータをいろいろ見てみましょう。log.head()はログデータ(2次元データフレーム)の先頭5行を表示するメソッド。

In [2]: log.head()
Out[2]: 
     call  datetime    time  urrst  myrst  freq mode  jcc  gl qsl  name  qth  \
0   HS7AT  12/05/26  04:04U    599    599  21.0   CW  NaN NaN   J   NaN  NaN   
1    R9UT  12/05/26  04:13U    599    599  21.0   CW  NaN NaN   J   NaN  NaN   
2  E21EIC  12/05/26  04:14U    599    599  21.0   CW  NaN NaN   J   NaN  NaN   
3    NH2T  12/05/26  04:15U    599    599  21.0   CW  NaN NaN   J   NaN  NaN   
4    PT5T  12/05/26  04:16U    599    599  21.0   CW  NaN NaN   J   NaN  NaN   

   urnr  mynr  rem3  
0     1   137     8  
1     2    96     8  
2     3   236     8  
3     4   559     8  
4     5   471     8  

In [3]: 

このように正しくCSVファイルを読み込んでpandasのデータフレームにおさめられていることがわかります。なお、これはCTestWinから出力させたCSVファイルの例で、HAMLOGから直接出力したものだとちょっと異なるかもしれませんので、カラム名などを適当にアレンジしてみてください。

・・・つづく・・・