I installed remote RX antenna switch (RAS-4) to select one of my beverage antennas (NW/SE/NE/SW beverages). It is driven by Hamation (former Array Solutions) Bandmaster V with homebrew software.

I installed remote RX antenna switch (RAS-4) to select one of my beverage antennas (NW/SE/NE/SW beverages). It is driven by Hamation (former Array Solutions) Bandmaster V with homebrew software.

Wrote time adjustment tool for WSJT-X on Linux (gtk+). It can change system time and interact with the NTP (or equivalent) services to turn on/off automatic clock updating:

I tested it on Arch Linux but it should work on other distros as well. One annoying pending issue is still that when turning NTP back on, it prompts for root password. The code can be found from github.com:
https://github.com/jmeloranta/timeadj
Compile with: make
And install with: make install
By default it installs under /usr/local directory. Needs gtk+ graphics library.
My Elecraft K4D has two receivers that can be used for diversity receive. In order to improve my FT8 RX capabilities on 160 m and 80 m bands, I wanted to fully utilize my antennas (inverted L and Beverage on ground receiving antennas) in kind of “FT8 diversity” set up. Note that these two antennas have different polarizations as well as differences in their radiation patterns. Since there is always some small audio phase difference between the two RXs, it is not a good idea to try to add them together to form a single audio stream and then decode the resultant signal with WSJT-X. Instead, I decided to feed audio from the two RXs into two separate decoders. But, of course, WSJT-X does not currently support this kind of setup. This is kind of “diversity” receive within the limitation of the 15 second RX period of FT8. The quotes emphasize that this is not the same diversity receive that one can do on CW/SSB but corresponds to two separate simultaneous decodes using the two RXs.
In the first iteration I ran two separate WSJT-X instances – one for each RX. While it did work, it was a rather clumsy approach. One of the WSJT-X instances was the master (responsible for running QSO) and the second one was just receiving. If only the second RX received a decode but the first one did not then one would have to manually account for this during QSO. Very easy to mess things up! By the way, this is a great way to compare antennas (for FT8 mode). However, the situation with true diversity receive on CW/SSB may be different with those antennas. In other words, the mode must always be considered when comparing antennas.
So, I decided to write a “middle man” program that sits between WSJT-X GUI and the decoder (program called JT9). This still requires running two WSJT-X (2nd with the -r option) instances so that they both feed their audio data to the corresponding shared memory blocks. The second WSJT-X (“slave”) just hangs around and does nothing. The first WSJT-X (“master”) instance gets all the decodes from the middle man. Normally JT9 picks up the data from these blocks, performs decode, and reports back to WSJT-X. In order to have everything passed to the same WSJT-X, the middle man program must get audio data from both WSJT-X instances, run JT9 on them, combine the decodes and report back to the master WSJT-X. WSJT-X eliminates multiple decodes that it receives, so the middle man should eliminate duplicates that come from both RXs in such way that the weakest SNR decode is discarded. Another decode that must be eliminated is my own transmission which appears on the audio feed of the second RX. To indicate where the decode came from, labels ‘a’, ‘b’, or ‘=’ are added to the decoded lines (replaces the ~ character in the original format output). Label ‘a’ means that the decode from the first RX was used (as it had the best SNR), ‘b’ it came from the second RX and the equal sign indicates that both were equally good. I may add the dB difference in the output at some point. But that information is already available by runinng two separate WSJT-X instances.
The code I came up with is on github: https://github.com/jmeloranta/multi . Since the JT9 executable path is hardcoded into WJST-X GUI, the installation is a bit clumsy, see install-multi script.
Be careful not to overwrite the original jt9 program (perhaps make a backup copy). Then start two WSJT-X processes (the default settings assume -r 2; determines the shared memory block name):
$ (wsjtx &); (wsjtx -r 2 &)
This is done in script called start-multi. The first one should have audio input set to left stereo channel and the second right stereo channel. The radio needs to be in the diversity receive mode so that both RXs are active and have the same behavior. The slave WSJT-X can be minimized (but do not quit it). QSOs can be run normally using the master WSJT-X. Adjust the audio levels in both WSJT-X’s so that they are about the same. Also, need to turn off rig control on the slave WSJT-X – otherwise it will clash with the master.
This is what it looks like:

The above test (sorry about the fuzzy image) was run on 10m with the two RXs having different audio levels in order to have some difference between them. I will find out tonight how this will work on 160 m and 80 m. Update: Since it is summer time, there is lightning all over the place. At this time of the year my BOG antenna beats the inverted L in receiving pretty much all the time. During winter time the situation will be different though.
The current signal indicator limits are:
= means both RXs are within 2 dB of each other
a means that RX a is more than 2 dB better than b
b means that RX b is more than 2 dB better than a
A means that RX a is more than 8 dB better than b
B means that RX b is more than 8 dB better than a
Additionally, if either RX misses the decode completely, this is indicated by adding ‘!’ character after the above indicator.
The actual S/N numbers can be recorded by specifying COLLECT_STATS environment variable in start-multi script.

The top waterfall corresponds to RX a and the bottom to RX b.
Also, there are now two helper scripts to set up a separate WSJT-X installation under /usr/local that won’t interfere with the main installation (see the github repo). Read those scripts before running them! But the basic installation goes (installer works only on Arch Linux):
$ make
$ sudo ./install-multi
Before using start-multi script, change your call sign in it & see if you want to use some of the options there. To start the program use (remember to configure both WSJT-X instances; see above):
$ start-multi
NOTE: The filtering capability of WSJT-X improved does not work well with the “middle man” (multi). I don’t know why but you need to disable the filters. There is a built-in filter capability in multi (see FILTER and CONTINENT environment variables in start-multi script). Since two decoders are run simultaneously, it may be a good idea to only use 2-stage decoding as 3-stage can be too slow (and lead to missed decodes).
Although NEC is not a terribly reliable model for beverage on ground, here are couple of screen shots from OH6CK (eznec) for “entertainment”:


And, yes, radikaalit should be radiaalit. The spell checker strikes again.
Cleared up & installed another 300′ reversible BOG along NW / SE direction (black/red antenna wire on the ground):

Still need to apply some round up to keep the greenies at bay. At this point, I lead my dog in the number of ticks 5 to 4 ! Won’t be going back there before I get proper tick spray… Except I could not stay away. Installed the ground rod and radials. Next remote RX antenna switch.
I improved the antenna status widget to also change antennas for bands. The protocol for this device has not been published, so I had to snoop on the RS-232 traffic to find out how to talk to it. Here is the new code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <gtk/gtk.h>
// Define the antenna names
#define ANTENNA1 "6m beam"
#define ANTENNA2 "WARC beam"
#define ANTENNA3 "20-15-10 stack"
#define ANTENNA4 "40m beam"
#define ANTENNA5 "No antenna"
#define ANTENNA6 "BOG NE"
#define ANTENNA7 "BOG SW"
#define ANTENNA8 "BOG NW"
#define ANTENNA9 "BOG SE"
#define ANTENNA10 "No antenna"
#define ANTENNA11 "No antenna"
#define ANTENNA12 "No antenna"
#define MAX_ANTENNAS 12
// Device for BM5
#define DEVICE "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_B003ISA1-if00-port0"
// Update every 100 msec
#define UPDATE 100
char *antennas[] = {ANTENNA1, ANTENNA2, ANTENNA3, ANTENNA4, ANTENNA5, ANTENNA6,
ANTENNA7, ANTENNA8, ANTENNA9, ANTENNA10, ANTENNA11, ANTENNA12};
#define MAX_SM 11
char *stack_match[] = {"No antenna", "Top antenna", "Mid antenna", "Top+mid antennas",
"Bottom antenna", "Top+bot antennas", "Mid+bot antennas",
"All antennas", "AUX", "Unknown", "Phase"};
/*
* RX antenna control:
*
* BOG NE = antenna 6 (no antenna; no relays selected)
* BOG SW = antenna 7 (select relay 9)
* BOG NW = antenna 8 (select relay 10)
* BOG SE = antenna 9 (select relay 11)
*
* BOG selected for can be selected for 160, 80, 75, and 60. TX antenna is unaffected (radio -> acom -> inv L)
*
* Numbers below (6, 7, 8, 9) refer to antenna numbers defined in bandmaster V. Bands 40 - 6m are always
* unchanged. Remember bandmaster uses hexadecimal everywhere.
*
*/
char *bogs[] = {"[R29T09H060606060402030203020301]\r", "[R29T09H070707070402030203020301]\r",
"[R29T09H080808080402030203020301]\r", "[R29T09H090909090402030203020301]\r"};
int fd, tx_on = 0;
GtkWidget *ant, *sm;
struct packet {
unsigned char cmd;
unsigned char dst;
unsigned char src;
unsigned char channel;
int len;
unsigned char data[256];
};
int read_untilcr(int fd, char *buf, int maxlen) {
int pos = 0, bytes_rd;
while(1) {
if((bytes_rd = read(fd, buf + pos, 1)) < 0) return -1;
if(bytes_rd == 0) {
sleep(1); // could be less than 1sec
continue;
}
if(!pos && (*buf == '\r' || *buf == '\n')) continue;
if(pos == maxlen) return -1;
if(buf[pos] == '\r') break;
pos++;
}
buf[pos] = '\0';
return pos;
}
int parse_packet(char *str, struct packet *packet) {
memset((void *) packet, 0, sizeof(struct packet));
if(sscanf(str, "[T%2xR%2x%2xH%2xM%[^]]", &(packet->cmd), &(packet->dst), &(packet->src), &(packet->channel), &(packet->data)) != 5) return -1;
return 0;
}
void set_tty() {
struct termios param;
if(tcgetattr(fd, ¶m) < 0) {
fprintf(stderr, "Status get failed.\n");
exit(1);
}
param.c_cflag &= ~PARENB;
param.c_cflag &= ~CSTOPB;
param.c_cflag |= CS8;
param.c_cflag &= ~CRTSCTS;
param.c_cflag |= CREAD | CLOCAL;
param.c_lflag &= ~ICANON;
param.c_lflag &= ~ECHO;
param.c_lflag &= ~ECHOE;
param.c_lflag &= ~ECHONL;
param.c_lflag &= ~ISIG;
param.c_iflag &= ~(IXON | IXOFF | IXANY);
param.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
param.c_oflag &= ~OPOST;
param.c_oflag &= ~ONLCR;
cfsetispeed(¶m, B57600);
cfsetospeed(¶m, B57600);
if(tcsetattr(fd, TCSANOW, ¶m) < 0) {
fprintf(stderr, "Status set failed.\n");
exit(1);
}
}
static gboolean update_band_info(void *asd) {
int len, antenna, relay;
struct packet packet;
char buf[512];
if((len = read_untilcr(fd, buf, sizeof(buf))) < 0) {
fprintf(stderr, "Read error.\n");
exit(1);
}
if(parse_packet(buf, &packet) < 0) {
printf("Incomplete packet -- skipping.\n");
return 1;
}
switch(packet.cmd) {
case 0xc4: // C4 = Bandmaster 5 status
if(sscanf(packet.data, "%2x01EEEEEEEEEEEE%4x", &antenna, &relay) != 2) {
printf("Error extracting antenna & relay information.");
antenna = 99;
}
if(antenna > 0 && antenna < MAX_ANTENNAS)
sprintf(buf, "<span color='blue'>%s (relays = %x)</span>", antennas[antenna-1], relay);
else
sprintf(buf, "<span color='red'>Unknown</span>");
gtk_label_set_markup(GTK_LABEL(ant), buf);
break;
case 0x45: // Stack match
sscanf(packet.data, "%2x", &antenna);
if(antenna >= 128) {
antenna -= 128; // transmitting
tx_on = 1;
} else tx_on = 0;
if(antenna >= 0 && antenna < MAX_SM)
sprintf(buf, "<span color='blue'>%s (%s)</span>", stack_match[antenna], tx_on?"TX":"RX");
else
strcpy(buf, "<span color='red'>Unknown state</span>");
gtk_label_set_markup(GTK_LABEL(sm), buf);
break;
case 0x13: // decoder data
printf("Decoder data ignored.\n");
break;
default:
printf("Unknown packet (%x) - ignored.\n", packet.cmd);
}
return 1;
}
void closewin(GtkWidget *win, gpointer data) {
gtk_main_quit();
}
void bog_ne(GtkWidget *win, gpointer data) {
if(!tx_on) {
printf("BOG NE selected\n");
write(fd, bogs[0], strlen(bogs[0]));
}
}
void bog_sw(GtkWidget *win, gpointer data) {
if(!tx_on) {
printf("BOG SW selected\n");
write(fd, bogs[1], strlen(bogs[1]));
}
}
void bog_nw(GtkWidget *win, gpointer data) {
if(!tx_on) {
printf("BOG NW selected\n");
write(fd, bogs[2], strlen(bogs[2]));
}
}
void bog_se(GtkWidget *win, gpointer data) {
if(!tx_on) {
printf("BOG SE selected\n");
write(fd, bogs[3], strlen(bogs[3]));
}
}
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *ant_label, *sm_label, *hbox1, *hbox2, *hbox3, *vbox, *button1, *button2, *button3, *button4;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Antenna Status");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 350, 80);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(closewin), NULL);
ant_label = gtk_label_new("Antenna:");
gtk_label_set_xalign(GTK_LABEL(ant_label), 0.0); // 0 = left, 1 = right
sm_label = gtk_label_new("Stack match:");
gtk_label_set_xalign(GTK_LABEL(sm_label), 0.0);
ant = gtk_label_new("-----");
gtk_label_set_xalign(GTK_LABEL(ant), 0.5);
sm = gtk_label_new("-----");
gtk_label_set_xalign(GTK_LABEL(sm), 0.5);
hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
hbox3 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
gtk_box_pack_start(GTK_BOX(hbox1), ant_label, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox1), ant, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox2), sm_label, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox2), sm, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(vbox), hbox1, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 5);
button1 = gtk_button_new_with_label("BOG NE");
button2 = gtk_button_new_with_label("BOG SW");
button3 = gtk_button_new_with_label("BOG NW");
button4 = gtk_button_new_with_label("BOG SE");
gtk_box_pack_start(GTK_BOX(hbox3), button1, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox3), button2, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox3), button3, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox3), button4, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(vbox), hbox3, TRUE, TRUE, 5);
gtk_container_add(GTK_CONTAINER(window), vbox);
g_signal_connect(button1, "clicked", G_CALLBACK(bog_ne), NULL);
g_signal_connect(button2, "clicked", G_CALLBACK(bog_sw), NULL);
g_signal_connect(button3, "clicked", G_CALLBACK(bog_nw), NULL);
g_signal_connect(button4, "clicked", G_CALLBACK(bog_se), NULL);
if((fd = open(DEVICE, O_RDWR)) < 0) {
fprintf(stderr, "Can't open device.\n");
exit(1);
}
set_tty();
bog_ne(NULL, NULL); // BOG NE is the default on start up
g_timeout_add(UPDATE, update_band_info, NULL);
gtk_widget_show_all(window);
gtk_main();
close(fd);
return 0;
}
In addition to performing automatic antenna switching for my tower (40 m – 6 m), it now can switch between four receive antennas for 160 m – 60m. You probably guessed that these are four BOGs oriented NE, SW, NW, SE.
The previously described ft8cmp code and the above code are now both on github.com:
https://github.com/jmeloranta/ft8cmp.git
https://github.com/jmeloranta/antenna-widget.git
The KD9SV reversible beverage on ground (RBOG) now finally works! Tested on 160 m, 80 m, and 60 m towards EU. It beats my inverted L on both 160 and 80 m bands. The antenna also now shows proper F/B (switching between forward and reverse; 10-12 dB).
The antenna is 300′ long made out of non-twisted pair cable (18 AWG) laid along the ground. Both ends have 4′ ground rod + three 40′ radials. The feed points have mix 31 ferrite rings with 9 rounds of the RG6 coax wrapped around them (choke).
Here is a quick test on 80 m FT8 (evening; band open to EU):

Some stations that RBOG did not hear (pointed towards EU) were located in south America. The current RBOG is oriented NE/SW and I need to add another one for NW/SE. For explanation of the graph, see the earlier blog post.
Using the two independent receivers on my Elecraft K4D, I can compare the performance of two receive antennas. RX1 is set to antenna 1 (inverted L) and RX2 to beverage on ground (BOG; 160′ long pointed towards EU). Then putting the radio in diversity mode, the output is set up such that RX1 audio appears on the left stereo channel and RX2 on the right channel. On the computer I run two independent WSJT-X instances which read the audio from the left and right channels. Note that the second WSJT-X must be started with the -r option to avoid conflict with the first instance. After running the set up for a couple of hours, I then collect the relevant data from the corresponding ALL.TXT files (.local/share/WSJT-X*) and feed them to the following program to analyze.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CTY_DAT "cty.dat" // cty file
#define FREQ_TOL 3 // Hz
// #define REQUIRE_BOTH // Requre decoded line to be in both files
typedef struct {
int date;
int time;
int db;
int freq;
char call[25];
} log_entry;
#define MAX_PREFIX 32768
#define MAX_PREFLEN 16
char prefixes[MAX_PREFIX][MAX_PREFLEN];
int nprefixes = 0;
#ifdef CTY_DAT
void read_cty(char *file) {
FILE *fp;
char buf[512];
int i, j, prev_j, state = 0;
if(!(fp = fopen(CTY_DAT, "r"))) {
fprintf(stderr, "Can't open %s.\n", file);
exit(1);
}
while (1) {
if(fgets(buf, sizeof(buf), fp) == NULL) break;
if(buf[0] == '#') continue;
prev_j = 0;
switch(state) {
case 0:
// no relevant info on this line
state = 1;
break;
case 1:
for (j = 0; ; j++) {
if(buf[j] == ' ' || buf[j] == '=') {
prev_j = j + 1;
continue;
}
if(buf[j] == ',' || buf[j] == ';' || buf[j] == '(' || buf[j] == '[') {
if(nprefixes == MAX_PREFIX) {
fprintf(stderr, "Increase MAX_PREFIX.\n");
exit(1);
}
strncpy(prefixes[nprefixes], &buf[prev_j], j - prev_j);
prefixes[nprefixes][j - prev_j + 1] = '\0';
// printf("%d %s\n", nprefixes, prefixes[nprefixes]);fflush(stdout);
nprefixes++;
if(buf[j] == '(') {
for ( ; buf[j] != ')'; j++);
j++;
}
if(buf[j] == '[') {
for ( ; buf[j] != ']'; j++);
j++;
}
prev_j = j + 1;
}
if(buf[j] == ';') {
state = 0;
break;
}
if(buf[j] == ',' && buf[j+1] == '\r') {
state = 1;
break;
}
}
}
}
fprintf(stderr, "Number of prefixes read = %d\n", nprefixes);
fclose(fp);
}
#endif
int check_prefix(char *call) { // 0 = not wanted, 1 = wanted
int i;
for (i = 0; i < nprefixes; i++) {
if(!strncmp(prefixes[i], call, strlen(prefixes[i]))) return 1;
}
return 0;
}
void read_log(char *file, log_entry *log, int *nbr) {
*nbr = 0;
char tmp1[64], tmp2[64], tmp3[64], tmp4[4], buf[256];
FILE *fp;
if(!(fp = fopen(file, "r"))) {
fprintf(stderr, "Can't open file %s\n", file);
exit(1);
}
while(1) {
tmp1[0] = tmp2[0] = tmp3[0] = tmp4[0] = '\0';
if(fgets(buf, sizeof(buf), fp) == NULL) break;
sscanf(buf, "%d_%d %*f %*s %*s %d %*f %d %s %s %s %s", &(log[*nbr].date),
&(log[*nbr].time), &(log[*nbr].db), &(log[*nbr].freq), tmp1, tmp2, tmp3, tmp4);
if(tmp4[0] == '\0' || tmp4[0] == 'a') strcpy(log[*nbr].call, tmp2);
else strcpy(log[*nbr].call, tmp3);
#ifdef CTY_DAT
if(check_prefix(log[*nbr].call)) *nbr += 1; // otherwise ignore
#else
*nbr += 1;
#endif
}
fclose(fp);
}
int main(int argc, char **argv) {
log_entry log1[2048], log2[2048];
int i, j, n1, n2;
if(argc != 3) {
fprintf(stderr, "Usage: ft8cmp ALL1.DAT ALL2.DAT\n");
exit(1);
}
#ifdef CTY_DAT
read_cty(CTY_DAT);
#endif
read_log(argv[1], log1, &n1);
fprintf(stderr, "%d lines read from %s (unwanted prefixed excluded).\n", n1, argv[1]);
read_log(argv[2], log2, &n2);
fprintf(stderr, "%d lines read from %s (unwanted prefixed excluded).\n", n2, argv[2]);
// search for every ALL1.TXT entries
for(i = 0; i < n1; i++) {
for (j = 0; j < n2; j++)
if(log1[i].date == log2[j].date && log1[i].time == log2[j].time &&
abs(log1[i].freq - log2[j].freq) <= FREQ_TOL && !strcmp(log1[i].call, log2[j].call)) {
printf("# %s (%d-%d)\n", log1[i].call, log1[i].date, log1[i].time);
printf("%d %d\n", log1[i].db, log2[j].db);
break;
}
#ifndef REQUIRE_BOTH
if(j && j == n2) {
printf("# %s (%d-%d)\n", log1[i].call, log1[i].date, log1[i].time);
printf("%d -26\n", log1[i].db); // not received in ALL2.TXT
}
#endif
}
#ifndef REQUIRE_BOTH
// search for every ALL2.TXT entries - only entries that are missing in ALL1.TXT
for(j = 0; j < n2; j++) {
for (i = 0; i < n1; i++)
if(log1[i].date == log2[j].date && log1[i].time == log2[j].time &&
abs(log1[i].freq - log2[j].freq) <= FREQ_TOL && !strcmp(log1[i].call, log2[j].call))
break;
if(i && i == n1) {
printf("# %s (%d-%d)\n", log2[j].call, log2[j].date, log2[j].time);
printf("-26 %d\n", log2[j].db); // not received in ALL1.TXT
}
}
#endif
}
The cty.dat file above is the AD1C cty.dat ASCII file that includes the countries of interest for the analysis. In my case I excluded the US and Canada (removed them from the cty.dat file), so the test focused on DX receive. Since BOG is directional, I should also exclude DX stations that are not in the direction of the BOG (to be done). Note that the program compares data obtained from the two receivers during the exact same time slice. This eliminates the QSB and other effects that could play a significant role if different time slices were used in the comparison. The two RXs are identical, so the RX bias is minimal. This could be tested by reversing the roles of the two RXs. Of course, the test yields the data within the 15 second FT8 transmission cycle but both antennas have the exact same change of decoding the signals during that time slice.
The first test was on 80 m FT8 (evening time; band open to EU). The x-axis is the decoded signal strength in dB from the RX that was connected to the inverted L and y-axis signal strength from the RX connected to the BOG. The red line shows where inv L and BOG would be equally good in receiving. Points representing a single decode above the red line has BOG obtaining better signal to noise (S/N) where as below it inverted L has better S/N. Results from collecting data for a couple of hours is shown below.

Well, BOG seems to work (very short test!!!) but another thing that this highlights the fact that running two independent WSJT-X processes with different types of antennas can improve FT8 receive a lot. There were many instances where BOG was able to decode but not inverted L and vice versa. The stations that BOG could not copy were mostly in South America (BOG was oriented towards EU). The “BOG only copy” stations on the other hand were in EU.
Below is another comparison between 60 m dipole and the same BOG as above (band open to EU):

On 60 m band BOG beat dipole hands down. There were many stations that BOG heard but dipole did not. And dipole was not able to hear anything that BOG did not.
NOTE: While this can still be used, multi program (see another blog post) can collect the statistics for direct visualization.