Reading a Cabrillo file
All contest loggers can output their data as Cabrillo format, slight warning however... some contests (looking at the RSGB,WAE) however have a modified format... I mean, we all like standard/non-standard stuff eh ?
In case you have no clue what I am talking about this is an old Cabrillo file - when I was in Oman
START-OF-LOG: 3.0 CALLSIGN: A45WG CONTEST: DARC-WAEDC-CW CATEGORY: SINGLE-OP HIGH CATEGORY-OPERATOR: SINGLE-OP CATEGORY-BAND: ALL CATEGORY-POWER: HIGH CATEGORY-MODE: CW CLAIMED-SCORE: 291226 CLUB: LOCATION: LL93FO CREATED-BY: RUMlogNG (2.11) by DL2RUM EMAIL: hi@dd.en NAME: Tim Seed ADDRESS: A House ADDRESS: A Road ADDRESS: A City ADDRESS: Sultanate of Oman OPERATORS: A45wg SOAPBOX: Very enjoyable - the QTC’s are a great idea. QSO: 14023 CW 2016-08-13 0340 A45WG 599 001 UW2M 599 205 0 QSO: 14045 CW 2016-08-13 0344 A45WG 599 002 IZ2GRG 599 129 0 QSO: 14045 CW 2016-08-13 0345 A45WG 599 003 HG7T 599 304 0 QSO: 14045 CW 2016-08-13 0345 A45WG 599 004 DJ5MW 599 262 0 QSO: 14045 CW 2016-08-13 0346 A45WG 599 005 UW7M 599 72 0 QSO: 14045 CW 2016-08-13 0346 A45WG 599 006 DM6V 599 328 0 QSO: 14045 CW 2016-08-13 0346 A45WG 599 007 RT4F 599 249 0 QSO: 14045 CW 2016-08-13 0347 A45WG 599 008 UW3U 599 195 0 QSO: 14045 CW 2016-08-13 0347 A45WG 599 009 RA1TU 599 010 0 QSO: 14045 CW 2016-08-13 0348 A45WG 599 010 SN7Q 599 292 0 QSO: 14045 CW 2016-08-13 0348 A45WG 599 011 9A5Y 599 316 0 QSO: 14045 CW 2016-08-13 0348 A45WG 599 012 LY9A 599 117 0 QSO: 14045 CW 2016-08-13 0349 A45WG 599 013 UT4U 599 264 0 QSO: 14045 CW 2016-08-13 0349 A45WG 599 014 ES5Q 599 278 0 QSO: 14045 CW 2016-08-13 0350 A45WG 599 015 HA6NL 599 179 0 QSO: 14045 CW 2016-08-13 0350 A45WG 599 016 RZ4AG 599 68 0 QSO: 14045 CW 2016-08-13 0351 A45WG 599 017 OH3GZ 599 1 0 QSO: 14045 CW 2016-08-13 0351 A45WG 599 018 DL5LYM 599 143 0 QSO: 14045 CW 2016-08-13 0352 A45WG 599 019 R4WAE 599 20 0 END-OF-LOG:
So .. lets's process that file. And by process - I mean read it.
Cabrillo Reading in Python
This is how to parse a CBR file
from dataclasses import dataclass from datetime import datetime #Open and Filter QSO Lines with open('data.cbr',"rt") as cbrfile: lines=[a for a in cbrfile.read().split('\n') if a.startswith('QSO')] @dataclass class CabrilloRec: "0 1 2 3 4 5 6 7 " "01234567890123456789012345678901234567890123456789012345678901234567890123456789" "QSO: 14006 CW 2021-07-10 1200 DX0HQ 599 PARA 8N3HQ 599 JARL " """Class for keeping track of an item in inventory.""" freq: int mode: str when: datetime sender: str senderrst: str senderex: str receiver: str receiverrst: str receiverex: str from pprint import pprint Records=[] for line in lines: # Uncomment if you are having data mis-alignment # print(line) # print(line[5:10]) # print(line[11:13]) # print(line[14:24]) # print(line[25:30]) # print(line[30:43]) # print(line[44:48]) # print(line[48:55]) # print(line[55:69]) # print(line[69:72]) # print(line[73:78]) Records.append(CabrilloRec(int(line[5:10]), line[11:14].strip(), datetime.strptime(line[14:24]+' '+line[25:29], '%Y-%m-%d %H%M'), line[30:43].strip(), line[44:48].strip(), line[48:55].strip(), line[55:69].strip(), line[69:72].strip(), line[73:78].strip()))
With the File now read in as a List of CabrilloRec objects, we can now create a Pandas DataFrame.
df_orig=pd.DataFrame.from_records(Records)