%matplotlib inline # %config InlineBackend.figure_format = 'svg' from IPython.core.pylabtools import figsize from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np import adif from math import pi,radians from mlocs import toLoc from azutil import to_polar, relative_offset_qth, all_dxcc, loc_for_dxcc import seaborn figsize(9,9) my_qth = 'IO91vk' my_log_file = 'log.adi' #'contacts.adi' all_qths = [ my_qth ] #,'CM86xx','DO13' ] # list of locations you operate from uses first as center print ('My QTH: {}, all QTHs: {}.'.format(my_qth,', '.join(all_qths))) def draw_qth(m,locs,marker='o',**kwargs): ''' Draw a series of locations on m. locs is array of maidenhead locators.''' coords = [ toLoc(loc) for loc in locs ] coords = [ m(c[1],c[0]) for c in coords ] # transpose to map coords for x,y in coords: m.plot(x,y,marker,linestyle='None',**kwargs) pass def draw_circle(m, qth0, qth_list, **kwargs): '''draw a great circle 'arc' to each locator in qth_list originating at qth0''' defaults = {'alpha' :0.75, 'color':'lightblue','linewidth':0.5} lat_0,lon_0 = toLoc(qth0) coords = [ toLoc(loc) for loc in qth_list ] for k,v in defaults.iteritems(): if k not in kwargs: kwargs[k] = v for lon,lat in [ (e[1], e[0]) for e in coords]: m.drawgreatcircle (lon_0,lat_0,lon,lat,**kwargs) adif_reader = adif.ADIFReader(open (my_log_file,'rU')) ad_contacts = adif_reader.load() '''TODO clean up extras''' ad_all_contact_dxcc = set([ q['dxcc'] for q in ad_contacts if 'dxcc' in q]) ad_contact_grids = set([ q['gridsquare'] for q in ad_contacts if 'gridsquare' in q]) ad_plotted_by_grid = set([ q['dxcc'] for q in ad_contacts if 'gridsquare' in q]) ad_plot_by_dxcc = ad_all_contact_dxcc.difference(ad_plotted_by_grid) ad_dxcc_grids = [ loc_for_dxcc(d) for d in ad_plot_by_dxcc ] #ad_no_grid = [ q for q in ad_contacts if 'gridsquare' not in q ] all_dxcc_locs = [ loc_for_dxcc(d) for d in all_dxcc() ] ctc_dxcc_locs = [ loc_for_dxcc(d) for d in ad_all_contact_dxcc ] def azmap(qth): proj='aeqd' #proj='ortho' lat,lon = toLoc(my_qth) m = Basemap(projection=proj,lat_0=lat,lon_0=lon) m.drawmapboundary() m.drawcountries(linewidth=0.25) m.drawcoastlines(linewidth=0.5) m.drawparallels(np.arange(-80.0,81,20),linewidth=0.25) m.drawmeridians(np.arange(-180,180,20),linewidth=0.25) if False: m.nightshade(dt.datetime.utcnow(),alpha=0.2) plt.title(qth) return m print ('Number of grid contacts: \t{}\nNumber of DXCC contacts: \t{}\nTotal Contacts: \t\t{}'.format( len(ad_contact_grids), len(ad_dxcc_grids), len(ad_contacts) )) m = azmap(my_qth) # Draw GCR lines to each contact draw_circle(m, my_qth, ad_contact_grids) draw_circle(m, my_qth, ad_dxcc_grids) # Draw our markers for contacts. draw_qth( m, ad_contact_grids, color='blue',alpha=0.5) draw_qth( m, all_qths, color='red', alpha=0.5, marker='8') draw_qth( m, ad_dxcc_grids, alpha=0.5, marker='h',color='yellow') title_text = plt.title('Contacts - {}'.format(my_qth)) m = azmap(my_qth) plt.title('All DXCC from {}'.format(my_qth)) draw_circle(m, my_qth, all_dxcc_locs) draw_qth(m,all_dxcc_locs,color='blue',alpha=0.5) draw_qth(m,ctc_dxcc_locs,color='red',alpha=0.5) def insert_ctc(d, dx,lonlat): if dx not in d: d[dx] = list() d[dx].append( np.array([ lonlat[1],lonlat[0] ] ) ) ctc_dict = dict() no_dx = 0 for c in ad_contacts: if 'dxcc' in c: dx = int(c['dxcc']) if dx > 0: if 'gridsquare' in c: g = c['gridsquare'] else: g = loc_for_dxcc(dx) insert_ctc(ctc_dict,dx,toLoc(g)) else: no_dx += 1 print ('{} has no DXCC'.format(c['callsign'])) # Average each DXCC co-ordinate list to a single lat lon for dx in ctc_dict: ctc_dict[dx] = np.mean(ctc_dict[dx],axis=0) ctc_bearings = [ to_polar(*relative_offset_qth(m,my_qth,lonlat_dest=ctc_dict[dx]))[1] for dx in ctc_dict ] dxcc_bearings = [ to_polar(*relative_offset_qth(m,my_qth,grid_dest=dxcc_loc))[1] for dxcc_loc in all_dxcc_locs ] print 'Contacted DXCCs : ',len(ctc_bearings),'/', len(dxcc_bearings) nbins = 16 def setup_polar_plot(): polar=True ax = plt.subplot(111,polar=polar) if polar: ax.set_theta_zero_location('N') ax.set_theta_direction(-1) ax.set_theta_direction('clockwise') ax.set_theta_zero_location('N') else: ax.set_yscale('log') return ax def bars(ax,theta,r,**kwargs): w = 2*pi/len(theta)*0.95 ax.bar(left=theta,height=r,width=w,alpha=0.5,linewidth=0,align='center',**kwargs) def bins(nbins=nbins): # return np.linspace(0,2*pi,nbins) return np.linspace(pi/nbins,(2*pi)-(pi/nbins),nbins) def to_bin(bearing,nbins=nbins): bsz = (2*pi)/nbins return (bearing/bsz)%nbins from math import degrees dxcc_data = np.empty(nbins) dxcc_data.fill(0) ctc_data = np.empty(nbins) ctc_data.fill(0) ''' Accumulate DXCCs by bearing ''' for theta in dxcc_bearings: dxcc_data[to_bin(theta)] += 1 for theta in ctc_bearings: ctc_data[to_bin(theta)] += 1 ax = setup_polar_plot() bars(ax,bins(), ctc_data,color='red') bars(ax,bins(), dxcc_data) p = plt.title('Number of DXCCs by Azimuth Angle from {}\n'.format(my_qth)) l = plt.legend(['Contacts','All DXCC']) ax = setup_polar_plot() bars(ax,bins(), np.log10([ x+0.49 for x in ctc_data]),color='red') bars(ax,bins(), np.log10(dxcc_data)) p = plt.title('Number of DXCCs ($log_{{10}}$) by Azimuth Angle from {}\n'.format(my_qth)) l = plt.legend(['My Contacts','All DXCC'])