Files
Python-Shannon/Shannon.py.save
2026-02-19 08:49:56 +00:00

1025 lines
51 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
''' ----------------------------------------------------------------------------------------------------------------
Shannon Equation for Dummies - JPC Feb 2021
Educational Application
Exploration from Claude's Shannon initial theory to its practical application to satellite communications
The application Runs either in local windows or in web pages
The Web version via localhost is fully functional although not as convenient as the windowed version (only 1 plot open)
The Web version in remote does work for a single user (all users connected can send command but see the same page)
--------------------------------------------------------------------------------------------------------------------'''
''' ------------------------------------------ Imports ---------------------------------------------------
The GUI has been designed to be compatible with both PySimpleGUIWeb and PySimpleGUI
The PySimpleGUi version takes full benefit of the matplotlib windowing whereas the Web version is constrained to use
a web compatible method with only one graph at a time
'''
from math import *
import matplotlib.pyplot as plt
import numpy as np
import webbrowser
import Shannon_Dict as Shd
import sqlite3
import os
import binascii
import itur
from astropy.units import imperial
Web_Version=True #
Web_Remote=True #
imperial.enable()
if Web_Version :
import PySimpleGUIWeb as sg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg
import io
def draw_matfig(fig, element):
canv = FigureCanvasAgg(fig)
buf = io.BytesIO()
canv.print_figure(buf, format='png')
if buf is None:
return None
buf.seek(0)
data = buf.read()
element.update(data=data)
def window_matfig(fig, title_fig, title_win):
matlayout = [[sg.T(title_fig, font='Any 20')],
[sg.Image(key='-IMAGE-')],
[sg.B('Exit')]]
winmat = sg.Window(title_win, matlayout, finalize=True)
draw_matfig(fig, winmat['-IMAGE-'])
while True:
event, values = winmat.read()
if event == 'Exit' or event == sg.WIN_CLOSED:
break
plt.close()
winmat.close()
else:
import PySimpleGUI as sg
if Web_Version and Web_Remote :
web_cfg={"web_ip":'127.0.0.1',"web_port":8080,"web_start_browser":False}
else:
web_cfg={}
''' ------------------------------------------ Core Functions ---------------------------------------------------
These functions are mainly application of formulas given in the first panel and formatting functions
'''
def Combine_CNR(*CNR):
''' Combination of Carrier to Noise Ratio '''
NCR_l = 0
for CNR_dB in CNR:
NCR_l += 10 ** (-CNR_dB / 10) # Summation of normalized noise variances
return -10 * log(NCR_l, 10)
def Shannon(BW=36.0, CNR=10.0, Penalty=0.0):
''' Shannon Limit, returns Bit Rate '''
CNR_l = 10 ** ((CNR - Penalty) / 10)
return BW * log(1 + CNR_l, 2)
def BR_Multiplier(BW_mul=1.0, P_mul=2.0, CNR=10.0):
''' Returns BR multiplier '''
CNR_l = 10 ** (CNR / 10)
return BW_mul * log(1 + CNR_l * P_mul / BW_mul, 2) / log(1 + CNR_l, 2)
def Shannon_Points(BW=36.0, CNR=10.0):
''' Returns CNR_l, BR_inf, C/N0 and BR(BW,CNR) '''
CNR_l = 10 ** (CNR / 10)
C_N0_l = CNR_l * BW
BR_infinity = C_N0_l / log(2)
BR_constrained = Shannon(BW, CNR)
return CNR_l, BR_infinity, C_N0_l, BR_constrained
def Shannon_Sp_Eff(Sp_Eff=0.5, BW=36.0, CNR=10.0):
''' Returns values at required Spe : CNR, BW, BR '''
C_N0_l = 10 ** (CNR / 10) * BW
BW_Spe_1 = C_N0_l
BW_Spe = C_N0_l / (2 ** Sp_Eff - 1)
BR_Spe = BW_Spe * Sp_Eff
CNR_Spe = 10 * log(BW_Spe_1 / BW_Spe, 10)
return CNR_Spe, BW_Spe, BR_Spe
def BR_Format(BR=100):
return "{:.1f}".format(BR) + ' Mbps'
def Power_Format(Pow=100):
Pow_dB=10*log(Pow,10)
if Pow > 1 and Pow < 1e4 :
return "{:.1f}".format(Pow) + ' W .. ' + "{:.1f}".format(Pow_dB) + ' dBW'
elif Pow <= 1 and Pow > 1e-3 :
return "{:.4f}".format(Pow) + ' W .. ' + "{:.1f}".format(Pow_dB) + ' dBW'
else :
return "{:.1e}".format(Pow) + ' W .. ' + "{:.1f}".format(Pow_dB) + ' dBW'
def PFD_Format(Pow=1): # PSD in W per m2
Pow_dB=10*log(Pow,10)
return "{:.1e}".format(Pow) + ' W/m\N{SUPERSCRIPT TWO} .. ' + "{:.1f}".format(Pow_dB) + ' dBW/m\N{SUPERSCRIPT TWO}'
def PSD_Format(Pow=1): # PSD in W per MHz
Pow_dB=10*log(Pow,10)
return "{:.1e}".format(Pow) + ' W/MHz .. ' + "{:.1f}".format(Pow_dB) + ' dBW/MHz'
def Gain_Format(Gain=1000):
Gain_dB=10*log(Gain,10)
return "{:.1f}".format(Gain) + ' .. ' + "{:.1f}".format(Gain_dB) + ' dBi'
def PLoss_Format(Loss=10):
Loss_dB=10*log(Loss,10)
return "{:.2}".format(Loss) + ' m\N{SUPERSCRIPT TWO} .. ' + "{:.1f}".format(Loss_dB) + ' dBm\N{SUPERSCRIPT TWO}'
''' ------------------------------------------ Database Functions ---------------------------------------------------
Functions for management of users' contributions
'''
def Contribution_Write (DB_File) :
Sh_DB=sqlite3.connect(DB_File)
Sh_DB_c=Sh_DB.cursor()
Sh_DB_c.execute("CREATE TABLE IF NOT EXISTS contributions "
"(num INTEGER, name TEXT, title TEXT, keywords TEXT, text TEXT, date TEXT, password TEXT)")
Sh_DB.commit()
Sh_DB_c.execute("SELECT MAX(num) FROM contributions")
ID_Contrib=Sh_DB_c.fetchall()[0][0]
if ID_Contrib == None:
ID_Contrib = 0
print (ID_Contrib)
layout3 = [ [sg.Text('Initials / name',size=(20,1), justification='center'),
sg.Input('',size=(45,1), key='-Name-')],
[sg.Text('Title ', size=(20, 1), justification='center'),
sg.Input('', size=(45, 1), key='-Title-')],
[sg.Text('Keywords ',size=(20,1), justification='center'),
sg.Input('', size=(45,1), key='-Keywords-')],
[sg.Text('Password ', size=(20, 1), justification='center'),
sg.Input('', size=(45, 1), key='-Password-')],
[sg.Frame('Write your text here',
[[sg.Multiline('', size=(80, 15), key='-Text-')],
[sg.Button('Validate'),
sg.Button('Exit'),
sg.Button('Help')]],
element_justification='center')]
]
window3 = sg.Window('Write Contribution', layout3, finalize=True)
while True:
event3, values = window3.read()
print(event3)
if event3 == sg.WIN_CLOSED or event3 == 'Exit' : # if user closes window
break
elif event3 == 'Validate' :
ID_Contrib += 1
Sh_DB_c.execute("INSERT INTO contributions VALUES ( " + str (ID_Contrib) + ", '" + values['-Name-'] +
"', '" + values['-Title-'] + "', '" + values['-Keywords-'] + "', '" + values['-Text-'] +
"', " + "Date('now')" + ", '" + values['-Password-'] + "' )")
Sh_DB.commit()
window3['-Text-'].Update('Thank you, your contribution has been successfully stored, ID #'+str(ID_Contrib))
elif event3 == 'Help':
window3['-Text-'].Update('Write your contribution here as a free text. Edit it in the text window until you'
' are happy with the result and then Validate. \n\nContributions should be candid observations'
' about the technical subject, references to relevant material (ideally as web pointers), open '
' discussion items about adjacent subjects, suggestion for improvement... \n\nYou can retrieve'
' your contribution via a search from the Read Panel and delete them there with the relevant '
'password. Keeping the "no password" default will allow anyone to delete.')
Sh_DB.close()
window3.close()
return ID_Contrib
def Contribution_Read (DB_File) :
layout4 = [ [sg.Text('Filter on Name',size=(20,1), justification='center'),
sg.Input('',size=(45,1), key='-Name-')],
[sg.Text('Filter on Title ', size=(20, 1), justification='center'),
sg.Input('', size=(45, 1), key='-Title-')],
[sg.Text('Filter on Keywords ',size=(20,1), justification='center'),
sg.Input('', size=(45,1), key='-Keywords-')],
[sg.Text('Filter on Content ', size=(20, 1), justification='center'),
sg.Input('', size=(45, 1), key='-Content-')],
[sg.Frame('Contribution',
[[sg.Multiline('', size=(80, 15), key='-Text-')],
[sg.Button('Load / Filter', key='-Filter-'),
sg.Button('Read Next', key='-Next-'),
sg.Button('Delete', key='-Del-'),
sg.Button('Exit'),
sg.Button('Help')]],
element_justification='center')]
]
if os.path.isfile(DB_File):
Sh_DB = sqlite3.connect(DB_File)
Sh_DB_c = Sh_DB.cursor()
else:
sg.popup('No Database Found', keep_on_top=True)
return 0
window4 = sg.Window('Read Contributions', layout4)
DB_ind = 0
while True:
event4, values = window4.read()
print(event4)
if event4 == sg.WIN_CLOSED or event4 == 'Exit': # if user closes window
break
elif event4 == '-Filter-':
Name = "'%" + values['-Name-'] + "%'"
Title = "'%" + values['-Title-'] + "%'"
Keywords = "'%" + values['-Keywords-'] + "%'"
Content = "'%" + values['-Content-'] + "%'"
Sh_DB_c.execute("SELECT num, name, title, keywords, text, date, password FROM contributions WHERE " +
"name LIKE " + Name +
" AND title LIKE " + Title +
" AND keywords LIKE " + Keywords +
" AND text LIKE " + Content +
" ORDER BY num DESC "
" LIMIT 50 ")
DB_Extract = Sh_DB_c.fetchall()
print(len(DB_Extract))
if len(DB_Extract) > 0 : # First Contribution read automatically
window4['-Text-'].Update( DB_Extract[0][2] + ' , ' + DB_Extract[0][1]
+ '\n\n' + DB_Extract[0][4] + '\n\n Keywords : ' + DB_Extract[0][3]
+ '\n\n ID #' + str(DB_Extract[0][0]) + ' - ' + str(DB_Extract[0][5]) )
DB_ind = 1
elif event4 == '-Next-' and DB_ind>0 :
if DB_ind < len(DB_Extract):
window4['-Text-'].Update(DB_Extract[DB_ind][2] + ' , ' + DB_Extract[DB_ind][1]
+ '\n\n' + DB_Extract[DB_ind][4] + '\n\n Keywords : ' + DB_Extract[DB_ind][3]
+ '\n\n ID #' + str(DB_Extract[DB_ind][0]) + ' - ' + str(DB_Extract[DB_ind][5]))
DB_ind +=1
elif event4 == '-Del-':
Password = sg.popup_get_text('Enter Item\'s Password')
print (Password)
DB_ind -= 1
if DB_Extract[DB_ind][6] == Password :
Item_num=DB_Extract[DB_ind][0]
Sh_DB_c.execute("DELETE FROM contributions WHERE num = " + str(Item_num))
window4['-Text-'].Update('Item ID# '+ str(Item_num) + ' deleted')
else:
window4['-Text-'].Update('Incorrect password, item unaffected')
elif event4 == 'Help':
window4['-Text-'].Update('To read contributions you have to load them first. If the search fields are empty'
', all contributions will be loaded. You should only enter 1 item per search field.'
'\n\n You can delete items if you know the associated password. Items are not encrypted'
' in the Database and can be removed by the admin.')
Sh_DB.commit()
Sh_DB.close()
window4.close()
return DB_ind
''' ------------------------------------------ GUI Functions---------------------------------------------------
LEDs from PySimpleGUI demos
'''
def LEDIndicator(key=None, radius=30):
return sg.Graph(canvas_size=(radius, radius),
graph_bottom_left=(-radius, -radius),
graph_top_right=(radius, radius),
pad=(0, 0), key=key)
def SetLED(window, key, color):
graph = window[key]
graph.erase()
graph.draw_circle((0, 0), 12, fill_color=color, line_color='black')
''' ------------------------------------------ Main Program ---------------------------------------------------
The program has 2 main panels associated with events collection loops
As the loops are build, when the second panel is open, events are only collected for this panel
In the windowed version, matplotlib plots don't interfere with the event loops : as many as desired can be open
'''
# ---------------- First Panel : Shannon's Equation -------------------
form_i = {"size":(22,1),"justification":'left',"enable_events":True} # input label format
form_iv = {"size":(8,1),"justification":'center'} # imput value format
form_ov = {"size":(20,1),"justification":'center'} # output value format
form_o = {"size":(65,1),"justification":'right',"enable_events":True} # output label format, also using input elements
form_CRC = {"size":(8,1),"justification":'center',"enable_events":True} # CRC Format
sg.set_options(auto_size_buttons=False, button_element_size=(14,1))
col1=sg.Column([[sg.Frame('Theoretical Exploration',
[[sg.Text(' Reference C/N [dB] ', **form_i,key='-iCNR-'),sg.Input('12', **form_iv, key='-CNR-')],
[sg.Text(' Reference BW [MHz] ', **form_i,key='-iBW-'),sg.Input('36', **form_iv, key='-BW-'),
sg.Text('',size=(34,1)),sg.Text('', **form_CRC, key='-CRC-'), LEDIndicator('-OK-')],
[sg.Text('Carrier Power to Noise Power Density Ratio : C/N\N{SUBSCRIPT ZERO}', **form_o,key='-iC_N0-'),
sg.Input(**form_ov,key='-C_N0-')],
[sg.Text('Theoretical BR at infinite BW : 1.44 C/N\N{SUBSCRIPT ZERO}', **form_o,key='-iBRinf-'),
sg.Input(**form_ov,key='-BRinf-')],
[sg.Text('Theoretical BR at Spectral Efficiency = 1 : C/N\N{SUBSCRIPT ZERO}', **form_o,key='-iBRunit-'),
sg.Input(**form_ov,key='-BRunit-')],
[sg.Text('Theoretical BR at Reference (BW,C/N)', **form_o,key='-iBRbw-'),
sg.Input(**form_ov, key='-BRbw-')],
[sg.Text('Carrier to Noise Ratio : C / N = C / (N\N{SUBSCRIPT ZERO}.B)', **form_o,key='-iCNRlin-'),
sg.Input(**form_ov, key='-CNRlin-')],
[sg.Text(' BW Increase Factor ',**form_i,key='-iBWmul-'), sg.Input('1', **form_iv, key='-BWmul-')],
[sg.Text(' Power Increase Factor ',**form_i,key='-iCmul-'), sg.Input('2', **form_iv, key='-Cmul-')],
[sg.Text('Bit Rate Increase Factor', **form_o,key='-iBRmul-'), sg.Input(**form_ov, key='-BRmul-')],
[sg.Button('Evaluation', visible=False, key='-Evaluation-', bind_return_key = True),
sg.Button('BW Sensitivity', pad=((60,5),(2,2)), key='-BW_Graph-'),
sg.Button('Power Sensitivity',key='-Pow_Graph-'),
sg.Button('BR Factor Map', key='-Map-'),
sg.Button('Go to Real World', key='-Real-')]])]])
col2=sg.Column([[sg.Frame('Background Information (click on items)',
[[sg.Multiline('Click on parameter\'s label to get information',size=(80,15),key='-Dialog-')],
[sg.Button('Advanced'), sg.Button('Write Contribution', key='-Write_Ct-'),
sg.Button('Read Contributions',key='-Read_Ct-'),sg.Button('Help')]], element_justification='center')]])
layout=[
[sg.Button('Wiki : Claude_Shannon',size=(25,1), key='-Wiki-')],
[sg.Image(filename='Shannon.png',key='-iShannon-',enable_events=True, background_color='black')],
[col1,col2]
]
window = sg.Window('Shannon\'s Equation for Dummies', layout , finalize=True, element_justification='center', **web_cfg)
# Needed for the Web version (on a finalized window)
window['-CNR-'].Update('12')
window['-BW-'].Update('36')
window['-BWmul-'].Update('1')
window['-Cmul-'].Update('2')
File_CRC=hex(binascii.crc32(open('Shannon.py', 'rb').read()) & 0xFFFFFFFF)[2:].upper()
print("File's CRC : ", File_CRC)
Win_time_out = 500 # Time out approach required for enter capture in the Web version
First_Pass = True
Err_msg = False
while True:
event, values = window.read(timeout=Win_time_out, timeout_key='__TIMEOUT__')
if event != '__TIMEOUT__' : print (event)
try:
if event == sg.WIN_CLOSED: # if user closes window
break
elif event == '-Evaluation-' or event == '__TIMEOUT__' :
if First_Pass :
window['-Dialog-'].Update(Shd.Help['-iShannon-'])
First_Pass = False
CNR_List=values['-CNR-'] # CNR can be a combination of comma separated CNRs
CNR_Nyq=Combine_CNR(*[float(val) for val in CNR_List.split(',')])
BW_Nyq=float(values['-BW-'])
CNR_l, BRinf, C_N0_l, BRbw = Shannon_Points(BW_Nyq,CNR_Nyq)
BRunit = C_N0_l # Mbps / MHz : Sp Eff =1
window['-C_N0-'].Update("{:.1f}".format(C_N0_l) + ' MHz')
window['-BRinf-'].Update(BR_Format(BRinf))
window['-BRunit-'].Update(BR_Format(BRunit))
window['-BRbw-'].Update(BR_Format(BRbw))
window['-CNRlin-'].Update("{:.1f}".format(CNR_Nyq)+" [dB] .. "+"{:.1f}".format(CNR_l)+' [Linear]')
BWmul=float(values['-BWmul-'])
Cmul=float(values['-Cmul-'])
BRmul=BR_Multiplier(BWmul,Cmul,CNR_Nyq)
window['-BRmul-'].Update("{:.2f}".format(BRmul))
Params = str(CNR_Nyq)+','+str(BW_Nyq)+','+str(BWmul)+','+str(Cmul)
Params_CRC = (hex(binascii.crc32(Params.encode('ascii')) & 0xFFFFFFFF)[2:].upper()) # Params' CRC
elif event == '-Wiki-':
webbrowser.open('https://en.wikipedia.org/wiki/Claude_Shannon')
elif event in ('-iC_N0-','-iCNR-','-iBRinf-','-iBRunit-','-iBRbw-','-iCNRlin-','-iBRmul-','-iCmul-',
'-iBWmul-','-iBW-','-iShannon-', '-CRC-', 'Advanced','Help' ):
window['-Dialog-'].Update(Shd.Help[event])
elif event == '-BW_Graph-':
BW = np.zeros(20)
BR = np.zeros(20)
CNR = np.zeros(20)
CNR[0] = CNR_Nyq + 10 * log(8, 10)
BW[0] = BW_Nyq / 8
BR[0] = Shannon(BW[0], CNR[0])
for i in range(1, 20):
BW[i] = BW[i - 1] * 2 ** (1 / 3)
CNR[i] = CNR[i - 1] - 10 * log(BW[i] / BW[i - 1], 10)
BR[i] = Shannon(BW[i], CNR[i])
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
plt.plot(BW, BR, 'b')
Mark = ('D', 's', 'p', 'h', 'x')
for i in range(5):
ind = 3 * (i + 1)
BR_norm = BR[ind] / BR[9]
plt.plot(BW[ind], BR[ind], Mark[i] + 'b', label="{:.1f}".format(BW[ind]) + " MHz" +
" , {:.1f}".format(BR[ind]) + " Mbps" + " : {:.0%}".format(BR_norm))
plt.title('Theoretical Bit Rate at Constant Power\nC/N\N{SUBSCRIPT ZERO} = ' +
"{:.1f}".format(C_N0_l) + " MHz" )
plt.xlabel('Bandwidth [MHz]')
plt.ylabel('Bit Rate [Mbps]')
plt.grid(True)
plt.legend(loc='lower right')
if Web_Version:
window_matfig(fig, title_fig='Bandwidth Sensitivity', title_win='Shannon for Dummies')
else:
plt.show(block=False)
elif event == '-Pow_Graph-':
P_mul = np.zeros(20)
BR = np.zeros(20)
CNR = np.zeros(20)
P_mul[0] = 1 / 8
CNR[0] = CNR_Nyq - 10 * log(8, 10)
BR[0] = Shannon(BW_Nyq, CNR[0])
for i in range(1, 20):
P_mul[i] = P_mul[i-1] * 2 ** ( 1 / 3 )
CNR[i] = CNR[i - 1] + 10 * log( 2 ** ( 1 / 3 ), 10 )
BR[i] = Shannon(BW_Nyq, CNR[i])
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
plt.plot(P_mul, BR, 'b')
Mark = ('D', 's', 'p', 'h', 'x')
for i in range(5):
ind = 3 * (i + 1)
BR_norm = BR[ind] / BR[9]
plt.plot(P_mul[ind], BR[ind], Mark[i] + 'b', label='{:.2f}'.format(P_mul[ind]) +
'x , {:.1f}'.format(BR[ind]) + ' Mbps' + ' : {:.0%}'.format(BR_norm))
plt.title('Theoretical Bit Rate at Constant Bandwidth : ' + '{:.1f}'.format(BW_Nyq) + ' MHz \n'
'Reference : C/N = {:.1f}'.format(CNR_l) + ' [Linear Format]')
plt.xlabel('Power Multiplying Factor')
plt.ylabel('Bit Rate [Mbps]')
plt.grid(True)
plt.legend(loc='lower right')
if Web_Version:
window_matfig(fig, title_fig='Power Sensitivity', title_win='Shannon for Dummies')
else:
plt.show(block=False)
elif event == '-Map-' :
BR_mul=np.zeros((21,21))
BW_mul=np.zeros((21,21))
P_mul=np.zeros((21,21))
for i in range(21):
for j in range(21):
BW_mul[i, j] = (i + 1)/4
P_mul[i, j] = (j + 1)/4
BR_mul[i, j] = BR_Multiplier(BW_mul[i, j], P_mul[i, j], CNR_Nyq)
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
Map = plt.contour(BW_mul,P_mul,BR_mul, 20)
plt.clabel(Map, inline=1, fontsize=8,fmt='%.2f')
plt.title('Bit Rate Multiplying Factor, \n Reference : C/N = {:.1f}'.format(CNR_Nyq) + ' dB, BW = ' +
'{:.1f}'.format(BW_Nyq) + ' MHz , C/N\N{SUBSCRIPT ZERO} = ' + '{:.1f}'.format(C_N0_l) +
' MHz, BR = {:.1f}'.format(BRbw) + ' Mbps', fontsize=10)
plt.xlabel('Bandwidth Multiplying Factor')
plt.ylabel('Power Multiplying Factor')
plt.grid(True)
if Web_Version:
window_matfig(fig, title_fig='Multiplying Factors Map', title_win='Shannon for Dummies')
else:
plt.show(block=False)
elif event == '-Write_Ct-' :
Contribution_Write('Shannon_Theory.db')
elif event == '-Read_Ct-' :
Contribution_Read('Shannon_Theory.db')
elif event == '-Real-': # ---------------- Second Panel : Real World -------------------
P_i1, P_i2, P_i3 = '', '', ''
fr1 = sg.Frame('Satellite Link',[
[sg.Text('Satellite Altitude [km] ', **form_i, key='-iSatAlt-'),
sg.Input('35786', **form_iv, key='-SatAlt-'),
sg.Text('Satellite Lat, Long [\N{DEGREE SIGN}]', **form_i, key='-iSatLatLong-'),
sg.Input('0.0, 19.2', **form_iv, key='-SatLatLong-'),
sg.Text('Ground Station Lat, Long [\N{DEGREE SIGN}]', **form_i, key='-iGSLatLong-'),
sg.Input('49.7, 6.3', **form_iv, key='-GSLatLong-')],
[sg.Text('HPA Output Power [W]',**form_i,key='-iHPA-'),
sg.Input('120', **form_iv, key='-HPA_P-'),
sg.Text('Output Losses [dB]',**form_i,key='-iLoss-'),
sg.Input('2', **form_iv, key='-Losses-'),
sg.Text('TX Impairments, C/I [dB]', **form_i, key='-iSCIR-'),
sg.Input('25, 25', **form_iv, key='-Sat_CIR-')],
[sg.Text('Beam Diameter [\N{DEGREE SIGN}]', **form_i, key='-iSBeam-'),
sg.Input('3', **form_iv, key='-Sat_Beam-'),
sg.Text('Offset from Peak [dB] ', **form_i, key='-iGOff-'),
sg.Input('0', **form_iv, key='-Gain_Offset-'), sg.Text('', size=(7, 1)),
sg.Text('', **form_CRC, key='-CRC1-'), LEDIndicator('-OK1-')],
[sg.Text('Frequency [GHz]', **form_i, key='-iFreq-'),
sg.Input('12', **form_iv, key='-Freq-'),
sg.Text('Link Availability [%]', **form_i, key='-iAvail-'),
sg.Input('99.9', **form_iv, key='-Avail-')],
[sg.Text('Output Power', **form_o,key='-iOPow-'),
sg.Input('', size=(35, 1), key='-Feed_P-', justification='center')],
[sg.Text('Satellite Antenna Gain', **form_o,key='-iSGain-'),
sg.Input('', size=(35, 1), key='-Sat_G-', justification='center')],
[sg.Text('Equivalent Isotropic Radiated Power', **form_o,key='-iEIRP-'),
sg.Input('', size=(35, 1), key='-EIRP-', justification='center')],
[sg.Text('Path Length @ Elevation', **form_o, key='-iPathLength-'),
sg.Input('', size=(35, 1), key='-PathLength-', justification='center')],
[sg.Text('Path Dispersion Loss', **form_o, key='-iPLoss-'),
sg.Input('', size=(35, 1), key='-PLoss-', justification='center')],
[sg.Text('Atmospheric Attenuation', **form_o, key='-iAtmLoss-'),
sg.Input('', size=(35, 1), key='-AtmLoss-', justification='center')],
[sg.Text('Power Flux Density', **form_o,key='-iPFD-'),
sg.Input('', size=(35, 1), key='-PFD-', justification='center')],
], key='-SatLink-')
fr2=sg.Frame('Radio Front End ',[
[sg.Text('Receive Antenna Size [m]',**form_i,key='-iCPE-'),
sg.Input('0.6', **form_iv, key='-CPE_Ant-'),
sg.Text('Noise Temperature [K] ', **form_i, key='-iCPE_T-'),
sg.Input('140', **form_iv, key='-CPE_T-'), sg.Text('',size=(7, 1)),
sg.Text('', **form_CRC, key='-CRC2-'),LEDIndicator('-OK2-')],
[sg.Text('Customer Antenna Effective Area and G/T', **form_o,key='-iCGain-'),
sg.Input('', size=(35, 1), key='-CPE_G-', justification='center')],
[sg.Text('RX Power at Antenna Output', **form_o,key='-iRXPow-'),
sg.Input('', size=(35, 1), key='-RX_P-', justification='center')],
[sg.Text('Noise Power Density Antenna Output', **form_o, key='-iN0-'),
sg.Input('', size=(35, 1), key='-N0-', justification='center')],
[sg.Text('Bit Rate at infinite Bandwidth', **form_o,key='-iBRinf-'),
sg.Input('', size=(35, 1), key='-BRinf-', justification='center')],
[sg.Text('Bit Rate at Spectral Efficiency=1', **form_o,key='-iBRUnit-'),
sg.Input('', size=(35, 1), key='-BRUnit-', justification='center')],
[sg.Text('Bit Rate at Spectral Efficiency=2', **form_o,key='-iBRdouble-'),
sg.Input('', size=(35, 1), key='-BRdouble-', justification='center')]
], key='-iRadio-')
fr3=sg.Frame('Baseband Unit',[
[sg.Text('Occupied Bandwidth [MHz]',**form_i,key='-iBW-'),
sg.Input('36', **form_iv, key='-BW-'),
sg.Text('Nyquist Filter Rolloff [%]',**form_i,key='-iRO-'),
sg.Input('5', **form_iv, key='-RO-'),
sg.Text('Higher Layers Overhead [%]', **form_i, key='-iOH-'),
sg.Input('5', **form_iv, key='-OH-')],
[sg.Text('RX Impairments, C/I [dB]',**form_i,key='-iCIR-'),
sg.Input('20', **form_iv, key='-CIR-'),
sg.Text('Implementation Penalty [dB]',**form_i,key='-iPenalty-'),
sg.Input('1.5', **form_iv, key='-Penalty-'), sg.Text('',size=(7, 1)),
sg.Text('', **form_CRC, key='-CRC3-'), LEDIndicator('-OK3-')],
[sg.Text('Signal to Noise Ratio in Available BW', **form_o,key='-iCNRbw-'),
sg.Input('', size=(35, 1), key='-CNRbw-', justification='center')],
[sg.Text('Signal to Noise Ratio in Nyquist BW', **form_o,key='-iCNRnyq-'),
sg.Input('', size=(35, 1), key='-CNRnyq-', justification='center')],
[sg.Text('Signal to Noise Ratio at Receiver Output', **form_o,key='-iCNRrcv-'),
sg.Input('', size=(35, 1), key='-CNRrcv-', justification='center')],
[sg.Text('Theoretical Bit Rate', **form_o,key='-iBRnyq-'),
sg.Input('', size=(35, 1), key='-BRnyq-', justification='center')],
[sg.Text('Practical Bit Rate', **form_o,key='-iBRrcv-'),
sg.Input('', size=(35, 1), key='-BRrcv-', justification='center')],
[sg.Text('Practical Higher Layers Bit Rate', **form_o,key='-iBRhigh-'),
sg.Input('', size=(35, 1), key='-BRhigh-', justification='center')],
[sg.Button('Evaluation', key='-Evaluation-',visible=False, bind_return_key = True),
sg.Button('BW Sensitivity', pad=((100,5),(2,2)), key='-BW_Graph-'),
sg.Button('Power Sensitivity',key='-Pow_Graph-'),
sg.Button('BR Factor Map', key='-Map-'),
sg.Button('Back to Theory', key='-Back-')],
], key='-Baseband-')
fr4 = sg.Frame('Background Information (click on items)',
[[sg.Multiline('Click on parameter\'s label to get information', size=(80, 15),key='-Dialog-')],
[sg.Button('Advanced'), sg.Button('Write Contribution', key='-Write_Ct-'),
sg.Button('Read Contributions',key='-Read_Ct-'), sg.Button('Help')]],element_justification='center')
layout2 =[
[sg.Column([[fr1],[fr2],[fr3]]),
sg.Column([[sg.Text('', size=(55, 1), justification='center', key='-FCRC-')],
[sg.Button('Wiki : Harry Nyquist', size=(25,1), key='-W_Nyquist-'),
sg.Button('Wiki : Richard Hamming', size=(25,1), key='-W_Hamming-')],
[sg.Button('Wiki : Andrew Viterbi', size=(25,1), key='-W_Viterbi-'),
sg.Button('Wiki : Claude Berrou', size=(25,1), key='-W_Berrou-')],
[sg.Image(filename='Satellite.png', key='-Satellite-',background_color='black', enable_events=True)],
[fr4]], element_justification='center')]]
window2 = sg.Window('Shannon and Friends in the Real World', layout2, finalize=True)
window2['-FCRC-'].Update('Program\'s CRC: ' + File_CRC)
# Needed for the Web version (on a finalized window)
window2['-Freq-'].Update('12')
window2['-SatAlt-'].Update('35786')
window2['-SatLatLong-'].Update('0.0, 19.2')
window2['-Avail-'].Update('99.9')
window2['-GSLatLong-'].Update('49.7, 6.3')
window2['-HPA_P-'].Update('120')
window2['-Sat_CIR-'].Update('25, 25')
window2['-Sat_Beam-'].Update('3')
window2['-Gain_Offset-'].Update('0')
window2['-CPE_Ant-'].Update('0.6')
window2['-CPE_T-'].Update('120')
window2['-Penalty-'].Update('1.5')
window2['-BW-'].Update('36')
window2['-CIR-'].Update('25')
window2['-RO-'].Update('5')
window2['-OH-'].Update('5')
window2['-AtmLoss-'].Update(' ... LOADING ...')
First_Pass = True
while True:
event2, values = window2.read(timeout=Win_time_out,timeout_key = '__TIMEOUT__')
if event2 != '__TIMEOUT__' : print(event2)
P_err = 0 # Error ID
try:
if event2 == sg.WIN_CLOSED or event2 == '-Back-': # closes window
break
elif event2 == '-Evaluation-'or event2 == '__TIMEOUT__' :
if First_Pass :
window2['-Dialog-'].Update(Shd.Help2['-Satellite-'])
First_Pass = False
P_err = 1 # Error ID
Freq = float(values['-Freq-']) # GHz
HPA_Power = float(values['-HPA_P-']) # Watts
Sat_Loss = float(values['-Losses-']) # dB
Sat_CIR_List = values['-Sat_CIR-'] # list if comma separated CIR contributions in dB
Sat_CIR = Combine_CNR(*[float(val) for val in Sat_CIR_List.split(',')])
Sig_Power = HPA_Power * 10 ** (-Sat_Loss / 10) # Watts
Sat_Beam = float(values['-Sat_Beam-']) #dB
Gain_Offset = float(values['-Gain_Offset-']) #dB
Sat_Ant_eff = 0.65 # Factor
window2['-Feed_P-'].Update(Power_Format(Sig_Power))
Lambda = 300e6 / Freq / 1e9 # meter
Sat_Gain_l = Sat_Ant_eff * ( pi * 70 / Sat_Beam ) ** 2
Sat_Gain_l = Sat_Gain_l * 10**(-Gain_Offset/10)
Sat_Ant_d = 70 * Lambda / Sat_Beam
Sat_Gain_dB = 10 * log(Sat_Gain_l, 10)
window2['-Sat_G-'].Update(Gain_Format(Sat_Gain_l))
EIRP_l = Sig_Power * Sat_Gain_l
EIRP_dB = 10 * log(EIRP_l, 10)
window2['-EIRP-'].Update(Power_Format(EIRP_l))
Avail = float(values['-Avail-'])
R_earth=6378
[lat_GS, lon_GS] = [float(val) for val in values['-GSLatLong-'].split(',')]
[lat_sat, lon_sat] = [float(val) for val in values['-SatLatLong-'].split(',')]
h_sat = float(values['-SatAlt-'])
Path_Length = sqrt (h_sat**2 + 2 * R_earth * (R_earth + h_sat ) *
( 1 - cos(np.radians(lat_sat-lat_GS)) * cos(np.radians(lon_sat-lon_GS))))
# elevation = itur.utils.elevation_angle(h_sat, lat_sat, lon_sat, lat_GS, lon_GS) # non signed
Phi = acos(cos(np.radians(lat_sat-lat_GS)) * cos(np.radians(lon_sat-lon_GS)))
if Phi > 0 :
elevation = np.degrees(atan((cos(Phi)-R_earth/(R_earth+h_sat))/sqrt(1-cos(Phi)**2)))
else :
elevation = 90
if elevation <= 0 :
Atm_Loss = 999
else:
Atm_Loss = itur.atmospheric_attenuation_slant_path(lat_GS, lon_GS, Freq,
elevation, 100-Avail, 1).value
window2['-AtmLoss-'].Update("{:.1f}".format(10 ** (Atm_Loss/10)) + ' [Linear] .. ' +
"{:.1f}".format(Atm_Loss) + " [dB]")
window2['-PathLength-'].Update("{:.1f}".format(Path_Length) + " [km] @ " +
"{:.1f}".format(elevation) + " [\N{DEGREE SIGN}]")
Free_Space_Loss_l = (4 * pi * Path_Length * 1000 / Lambda) ** 2
Free_Space_Loss_dB = 10 * log(Free_Space_Loss_l, 10)
Path_Loss_l = 4 * pi * (Path_Length * 1000) ** 2
Path_Loss_dB = 10 * log(Path_Loss_l, 10)
window2['-PLoss-'].Update(PLoss_Format(Path_Loss_l))
PFD_l = EIRP_l / Path_Loss_l * 10 ** (-Atm_Loss/ 10)
PFD_dB = 10 * log(PFD_l, 10)
window2['-PFD-'].Update(PFD_Format(PFD_l))
P_err = 2 # Error ID
CPE_Ant_d = float(values['-CPE_Ant-']) # meter
CPE_T_Clear= float(values['-CPE_T-']) # K
CPE_Ant_eff = 0.6
CPE_T_Att = (CPE_T_Clear - 40) + 40 * 10 ** (-Atm_Loss/10) + 290 * (1 - 10 ** (-Atm_Loss/10))
k_Boltz = 1.38e-23 # J/K
P_err = 3 # Error ID
Penalties = float(values['-Penalty-']) # dB, overall implementation penalty
Bandwidth = float(values['-BW-']) # MHz
CNR_Imp_List = values['-CIR-'] # List of comma separated CNR impairments in dB
CNR_Imp = Combine_CNR(*[float(val) for val in CNR_Imp_List.split(',')])
Rolloff = float(values['-RO-']) # percent
Overheads = float(values['-OH-']) # percent
CPE_Ae = pi * CPE_Ant_d ** 2 / 4 * CPE_Ant_eff
CPE_Gain_l = (pi * CPE_Ant_d / Lambda) ** 2 * CPE_Ant_eff
CPE_Gain_dB = 10 * log(CPE_Gain_l, 10)
CPE_Beam = 70 * Lambda / CPE_Ant_d # diameter in degrees
CPE_G_T = 10 * log(CPE_Gain_l / CPE_T_Att, 10)
window2['-CPE_G-'].Update(
"{:.1f}".format(CPE_Ae)+" m\N{SUPERSCRIPT TWO} .. {:.1f}".format(CPE_G_T)+" dB/K")
RX_Power_l = PFD_l * CPE_Ae
# Alternative : RX_Power_l=EIRP_l/Free_Space_Loss_l*CPE_Gain_l
RX_Power_dB = 10 * log(RX_Power_l,10)
N0 = k_Boltz * CPE_T_Att # W/Hz
C_N0_l = RX_Power_l / N0 # Hz
C_N0_dB = 10 * log(C_N0_l, 10) # dBHz
window2['-RX_P-'].Update('C : ' + Power_Format(RX_Power_l))
window2['-N0-'].Update('N\N{SUBSCRIPT ZERO} : ' + PSD_Format(N0*1e6))
BW_Spe_1 = C_N0_l / 1e6 # C_N0 without Penalty in MHz
BW_Spe_1half = BW_Spe_1 / (2 ** 0.5 - 1) # MHz
BW_Spe_1quarter = BW_Spe_1 / (2 ** 0.25 - 1)
BW_Spe_double = BW_Spe_1 / (2 ** 2 - 1)
BR_Spe_1 = BW_Spe_1 # Mbps
BR_Spe_1half = BW_Spe_1half / 2
BR_Spe_1quarter = BW_Spe_1quarter / 4
BR_Spe_double= BW_Spe_double * 2
BR_infinity = BW_Spe_1 / log(2)
BR_Spe_1_Norm = BR_Spe_1 / BR_infinity
BR_Spe_1half_Norm = BR_Spe_1half / BR_infinity
BR_Spe_1quarter_Norm = BR_Spe_1quarter / BR_infinity
BR_Spe_double_Norm = BR_Spe_double / BR_infinity
window2['-BRinf-'].Update('1.443 C/N\N{SUBSCRIPT ZERO} : ' +
BR_Format(BR_infinity)+" .. {:.0%}".format(1))
window2['-BRUnit-'].Update('C/N\N{SUBSCRIPT ZERO} : ' +
BR_Format(BR_Spe_1)+" .. {:.0%}".format(BR_Spe_1_Norm))
window2['-BRdouble-'].Update('0.667 C/N\N{SUBSCRIPT ZERO} : ' +
BR_Format(BR_Spe_double)+" .. {:.0%}".format(BR_Spe_double_Norm))
CNR_Spe_1 = 0 # dB
CNR_Spe_1half = -10 * log(BW_Spe_1half / BW_Spe_1, 10)
CNR_Spe_1quarter = -10 * log(BW_Spe_1quarter / BW_Spe_1, 10)
CNR_Spe_double = -10 * log(BW_Spe_double/ BW_Spe_1, 10)
CNR_BW = CNR_Spe_1 + 10 * log(BW_Spe_1 / Bandwidth, 10) # dB
BW_Nyq = Bandwidth / (1 + Rolloff / 100) # MHz
CNR_Nyq = CNR_Spe_1 + 10 * log(BW_Spe_1 / BW_Nyq, 10) # dBB
CNR_Rcv = Combine_CNR (CNR_Nyq, CNR_Imp, Sat_CIR) #
BR_BW = Shannon (Bandwidth, CNR_BW) # Mbps
BR_Nyq = Shannon (BW_Nyq, CNR_Nyq) # Mbps
BR_Rcv = Shannon (BW_Nyq, CNR_Rcv,Penalties) # Mbps
BR_Rcv_Higher = BR_Rcv / (1 + Overheads / 100) # Mbps
BR_BW_Norm = BR_BW / BR_infinity
BR_Nyq_Norm = BR_Nyq / BR_infinity
BR_Rcv_Norm = BR_Rcv / BR_infinity
BR_Rcv_H_Norm = BR_Rcv_Higher / BR_infinity
Spe_BW = BR_BW / Bandwidth
Spe_Nyq = BR_Nyq / Bandwidth # Efficiency in available bandwidth
Bits_per_Symbol = BR_Nyq / BW_Nyq # Efficiency in Nyquist bandwidth
Spe_Rcv = BR_Rcv / Bandwidth
Spe_Higher = BR_Rcv_Higher / Bandwidth
window2['-CNRbw-'].Update("{:.1f}".format(CNR_BW)+" dB in "+"{:.1f}".format(Bandwidth)+" MHz")
window2['-CNRnyq-'].Update("{:.1f}".format(CNR_Nyq)+" dB in "+"{:.1f}".format(BW_Nyq)+" MHz")
window2['-CNRrcv-'].Update("{:.1f}".format(CNR_Rcv)+" dB")
window2['-BRnyq-'].Update(BR_Format(BR_Nyq) + " .. {:.0%}".format(BR_Nyq_Norm)+
" .. {:.1f}".format(Spe_Nyq)+" bps/Hz .. {:.1f}".format(Bits_per_Symbol)+" b/S")
window2['-BRrcv-'].Update(BR_Format(BR_Rcv) + " .. {:.0%}".format(BR_Rcv_Norm)+
" .. {:.1f}".format(Spe_Rcv)+" bps/Hz")
window2['-BRhigh-'].Update(BR_Format(BR_Rcv_Higher)+" .. {:.0%}".format(BR_Rcv_H_Norm)+
" .. {:.1f}".format(Spe_Higher)+" bps/Hz")
Params1 = str(Freq) + ',' + str(Path_Length) + ',' + str(Atm_Loss) + ',' + \
str(HPA_Power) + ',' + str(Sat_Loss) + ',' + str(Sat_CIR) + ',' + \
str(Sat_Beam) + ',' + str(Gain_Offset)
Params2 = str(CPE_Ant_d) + ',' + str(CPE_T_Clear)
Params3 = str(Bandwidth) + ',' + str(Rolloff) + ',' + str(Overheads) + ',' + \
str(CNR_Imp) + ',' + str(Penalties)
Params1_CRC=hex(binascii.crc32(Params1.encode('ascii')) & 0xFFFFFFFF)[2:].upper()
Params2_CRC = hex(binascii.crc32(Params2.encode('ascii')) & 0xFFFFFFFF)[2:].upper()
Params3_CRC = hex(binascii.crc32(Params3.encode('ascii')) & 0xFFFFFFFF)[2:].upper()
elif event2 in ('-iFreq-','-iHPA-','-iSBeam-','-iLoss-', '-iGOff-','-iFade-', '-iSCIR-',
'-iOPow-','-iSGain-', '-iEIRP-', '-iPFD-', '-iCPE-','-iCGain-','-iRXPow-',
'-iBRinf-','-iBRhalf-', '-iBRUnit-','-iBRdouble-','-iBW-','-iRO-','-iCIR-',
'-iPenalty-', '-iOH-','-iNBW-', '-iCNRbw-','-iCNRnyq-','-iCNRrcv-','-iBRbw-',
'-iBRnyq-','-iBRrcv-','-iBRhigh-','-Satellite-','-iPLoss-','Advanced','Help',
'-CRC1-', '-CRC2-', '-CRC3-', '-iN0-','-iCPE_T-', '-iSatAlt-','-iSatLatLong-',
'-iGSLatLong-', '-iAvail-', '-iPathLength-','-iAtmLoss-'):
window2['-Dialog-'].Update(Shd.Help2[event2])
elif event2 == '-BW_Graph-' :
BW = np.zeros(20)
BR = np.zeros(20)
CNR = np.zeros(20)
CNR[0] = CNR_Nyq+10*log(8,10)
BW[0] = Bandwidth/8
BR[0] = Shannon(BW[0]/(1+Rolloff/100), CNR[0], Penalties) / (1 + Overheads / 100)
for i in range(1, 20):
BW[i] = BW[i - 1] * 2 ** (1 / 3)
CNR[i] = CNR[i - 1] - 10 * log(BW[i] / BW[i - 1], 10)
CNR_Rcv_i = Combine_CNR(CNR[i], CNR_Imp, Sat_CIR)
BR[i] = Shannon(BW[i]/(1+Rolloff/100), CNR_Rcv_i, Penalties) / (1 + Overheads / 100)
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
plt.plot(BW, BR, 'b')
Mark = ('D', 's', 'p', 'h', 'x')
for i in range(5):
ind = 3 * (i + 1)
BR_norm = BR[ind] / BR[9]
plt.plot(BW[ind], BR[ind], Mark[i] + 'b',label="{:.1f}".format(BW[ind]) +
" MHz" + " , {:.1f}".format(BR[ind]) + " Mbps" + " : {:.0%}".format(BR_norm))
plt.title('Higher Layers Bit Rate at Constant HPA Output Power : ' +
"{:.1f}".format(HPA_Power) + " W")
plt.xlabel('Occupied Bandwidth [MHz]')
plt.ylabel('Bit Rate [Mbps]')
plt.grid(True)
plt.legend(loc='lower right')
if Web_Version:
window_matfig(fig, title_fig='Bandwidth Sensitivity',
title_win='Shannon and Friends in the Real World')
else:
plt.show(block=False)
elif event2 == '-Pow_Graph-' :
Power = np.zeros(20)
BR = np.zeros(20)
CNR = np.zeros(20)
Power[0] = HPA_Power / 8
CNR[0] = CNR_Nyq-10*log(8,10)
CNR_Rcv_i = Combine_CNR(CNR[0], CNR_Imp, Sat_CIR)
BR[0] = Shannon(BW_Nyq, CNR_Rcv_i, Penalties) / (1 + Overheads / 100)
for i in range(1, 20):
Power[i] = Power[i-1] * 2 ** (1 / 3)
CNR[i] = CNR[i - 1] + 10 * log( 2 ** (1 / 3) , 10 )
CNR_Rcv_i = Combine_CNR(CNR[i], CNR_Imp, Sat_CIR)
BR[i] = Shannon(BW_Nyq, CNR_Rcv_i, Penalties) / (1 + Overheads / 100)
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
plt.plot(Power, BR, 'b')
Mark = ('D', 's', 'p', 'h', 'x')
for i in range(5):
ind = 3 * (i + 1)
BR_norm=BR[ind]/BR[9]
plt.plot(Power[ind], BR[ind], Mark[i] + 'b', label="{:.1f}".format(Power[ind]) + " W" +
" , {:.1f}".format(BR[ind]) + " Mbps"+" : {:.0%}".format(BR_norm))
plt.title('Higher Layers Bit Rate at Constant Occupied Bandwidth : ' +
"{:.1f}".format(Bandwidth) + " MHz")
plt.xlabel('HPA Output Power @ Operating Point [Watts]')
plt.ylabel('Bit Rate [Mbps]')
plt.grid(True)
plt.legend(loc='lower right')
if Web_Version:
window_matfig(fig, title_fig='Power Sensitivity',
title_win='Shannon and Friends in the Real World')
else:
plt.show(block=False)
elif event2 == '-Map-':
BR_mul = np.zeros((21, 21))
BW_mul = np.zeros((21, 21))
P_mul = np.zeros((21, 21))
BR_00 = BR_Rcv_Higher
for i in range(21):
for j in range(21):
BW_mul[i, j] = (i + 1) / 4
P_mul[i, j] = (j + 1) / 4
CNR_ij = CNR_Nyq + 10 * log( P_mul[i, j] / BW_mul[i, j] , 10 )
CNR_Rcv_ij = Combine_CNR (CNR_ij, CNR_Imp, Sat_CIR)
BW_ij = BW_Nyq * BW_mul[i, j]
BR_ij = Shannon( BW_ij / (1 + Rolloff / 100), CNR_Rcv_ij, Penalties) / (1 + Overheads / 100)
BR_mul[i, j] = BR_ij / BR_00
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
Map = plt.contour(BW_mul, P_mul, BR_mul, 20)
plt.clabel(Map, inline=1, fontsize=8, fmt='%.2f')
plt.title('Bit Rate Multiplying Factor, \n Reference : Power = {:.1f}'.format(HPA_Power) +
' W , BW = ' + '{:.1f}'.format(Bandwidth) +
' MHz , BR = {:.1f}'.format(BR_Rcv_Higher) + ' Mbps')
plt.xlabel('Bandwidth Multiplying Factor')
plt.ylabel('Power Multiplying Factor')
plt.grid(True)
if Web_Version:
window_matfig(fig, title_fig='Multiplying Factors Map',
title_win='Shannon and Friends in the Real World')
else:
plt.show(block=False)
elif event2 == '-W_Nyquist-':
webbrowser.open('https://en.wikipedia.org/wiki/Harry_Nyquist')
elif event2 == '-W_Hamming-':
webbrowser.open('https://en.wikipedia.org/wiki/Richard_Hamming')
elif event2 == '-W_Viterbi-':
webbrowser.open('https://en.wikipedia.org/wiki/Andrew_Viterbi')
elif event2 == '-W_Berrou-':
webbrowser.open('https://en.wikipedia.org/wiki/Claude_Berrou')
elif event2 == '-Write_Ct-':
Contribution_Write('Shannon_Real.db')
elif event2 == '-Read_Ct-':
Contribution_Read('Shannon_Real.db')
else:
print("Untrapped event : "+event2)
except :
window2['-Dialog-'].Update('Invalid input fields')
if P_err == 1 :
window2['-CRC1-'].Update('-')
SetLED(window2, '-OK1-', 'red')
if P_err == 2 :
window2['-CRC2-'].Update('-')
SetLED(window2, '-OK2-', 'red')
if P_err == 3 :
window2['-CRC3-'].Update('-')
SetLED(window2, '-OK3-', 'red')
Err_msg=True
else:
window2['-CRC1-'].Update(Params1_CRC)
window2['-CRC2-'].Update(Params2_CRC)
window2['-CRC3-'].Update(Params3_CRC)
SetLED(window2, '-OK1-', 'green')
SetLED(window2, '-OK2-', 'green')
SetLED(window2, '-OK3-', 'green')
if Err_msg :
window2['-Dialog-'].Update('Input Validated')
Err_msg = False
window2.close()
except :
window['-Dialog-'].Update('Invalid input fields')
window['-CRC-'].Update('-')
SetLED(window, '-OK-', 'red')
Err_msg = True
else:
window['-CRC-'].Update(Params_CRC)
SetLED(window, '-OK-', 'green')
if Err_msg:
window['-Dialog-'].Update('Input Validated')
Err_msg = False
window.close()