Browse Source

Merge pull request #14 from ricet8ur/corrections-for-validator

Corrections for validator
ricet8ur 2 years ago
parent
commit
364d078e45

+ 15 - 15
TODO.md

@@ -4,16 +4,17 @@
     * What does it do?
     * What is Q circle?
     * What data formats are supported?
-2. [x] Change startup file to main.py and remove os and sys calls from frontend. Pass calc function to frontend function as an argument.
-3. [x] Add validation of separator + convertor to std backend input 
-4. Should we apply corrections for coupling losses? - yes, please add this option.
-5. Draw continuous Q circle on a Smith chart using coefficients a[0..2]
-6. Add axes labels to a Smith chart
-7. Pretty-print results and errors (7 digits after dot). Try latex output.
-8. Plot second chart: abs(S11) from f
-9. Add impedance data format (only frontend):
+2. [x] Add validation of separator + convertor to std backend input
+3. Should we apply corrections for coupling losses? - yes, please add this option.
+4. [x] Draw continuous Q circle on a Smith chart using coefficients a[0..2]
+5. [x] Add axes labels to a Smith chart
+6. Pretty-print results and errors (7 digits after dot). Try latex output.
+7. Advanced output options (only frontend):
+    * Option to choose output values precision
+8. Add approximation for second chart (abs(S11) from f)
+9. Add impedance input option (Z instread of S11)
     * additional field for omega
-    * convertion to reflection coeffitient (how?)
+    * convertion to reflection coeffitient (thats how: <https://radioprog.ru/post/195>)
 10. Codestyle fix:
     * Format all code files
     * Make a good code structure... If you can.
@@ -27,9 +28,8 @@
 12. Advanced file loading:
     * Show file preview
     * Options to skip first and last lines
-13. Advanced output options (only frontend):
-    * Option to choose output values precision
-14. Do we need to calculate systematic errors? - yes, if its not too hard.
-15. Add direct support for output files from different vna models
-16. Make charts more interactive
-17. Make an option to pass the whole program to .html site as a iframe
+
+13. Do we need to calculate systematic errors? - yes, if its not too hard.
+14. Add direct support for output files from different vna models
+15. Make charts more interactive
+16. Make an option to pass the whole program to .html site as a iframe

+ 1 - 2
source/backend/calc.py

@@ -148,5 +148,4 @@ def fl_fitting(freq, re, im):
         Q = Ql * (1 + qk)  # Q-factor = result
         print(f"Q0 = {Q} +- {sigmaQ0}")
     
-    return Q,sigmaQ0, Ql, sigmaQl,a
-    
+    return Q,sigmaQ0, Ql, sigmaQl,a

+ 94 - 46
source/frontend/front.py

@@ -1,42 +1,75 @@
+import math
+
+XLIM = [-1.1, 1.1]
+YLIM = [-1.1, 1.1]
+
+
+def round_up(x, n=7):
+    if x == 0:
+        return 0
+    deg = math.floor(math.log(abs(x), 10))
+    return (10 ** deg) * round(x / (10 ** deg), n - 1)
+
+
+def circle(ax, x, y, radius, color='#1946BA'):
+    from matplotlib.patches import Ellipse
+    circle = Ellipse((x, y), radius * 2, radius * 2, clip_on=False,
+                     zorder=2, linewidth=2, edgecolor=color, facecolor=(0, 0, 0, .0125))
+    ax.add_artist(circle)
+
+
 import streamlit as st
 import matplotlib.pyplot as plt
 import numpy as np
 import math
 
-def plot_data(r,i, g):
-    # unit circle
-    unit_circle_x = []
-    unit_circle_y = []
-    for x in np.arange(-1, 1, 0.01):
-        unit_circle_x.append(x)
-        unit_circle_y.append((1-x**2)**0.5)
-
-    unit_circle_x.append(1)
-    unit_circle_y.append(0)
 
-    for x in np.arange(-1, 1, 0.01)[::-1]:
-        unit_circle_x.append(x)
-        unit_circle_y.append(-(1-x**2)**0.5)
-
-    fig, ax = plt.subplots()
-    ax.plot(unit_circle_x, unit_circle_y)
+def plot_data(r, i, g):
+    fig = plt.figure(figsize=(10, 10))
+    ax = fig.add_subplot()
+    ax.set_xlim(XLIM)
+    ax.set_ylim(YLIM)
+    major_ticks = np.arange(-1.0, 1.1, 0.25)
+    minor_ticks = np.arange(-1.1, 1.1, 0.05)
+    ax.set_xticks(major_ticks)
+    ax.set_xticks(minor_ticks, minor=True)
+    ax.set_yticks(major_ticks)
+    ax.set_yticks(minor_ticks, minor=True)
+    ax.grid(which='major', color='grey', linewidth=1.5)
+    ax.grid(which='minor', color='grey', linewidth=0.5, linestyle=':')
+    plt.xlabel(r'$Re(\Gamma)$', color='gray', fontsize=16, fontname="Cambria")
+    plt.ylabel('$Im(\Gamma)$', color='gray', fontsize=16, fontname="Cambria")
+    plt.title('Smith chart', fontsize=24, fontname="Cambria")
+    # cirlce approximation
+    radius = abs(g[1] - g[0] / g[2]) / 2
+    x = ((g[1] + g[0] / g[2]) / 2).real
+    y = ((g[1] + g[0] / g[2]) / 2).imag
+    circle(ax, x, y, radius, color='#FF8400')
     #
-
-    # data
-    ax.plot(r, i, 'b+')
+    # unit circle
+    circle(ax, 0, 0, 1)
     #
-    ax.xlabel("x")
-    ax.ylabel("y")
-    #cirlce approximation
-    t=np.linspace(0,1,100)
-    z = (g[0]*t+g[1])/(g[2]+1)
-    ax.plot(z.real,z.imag)
+    # data
+    ax.plot(r, i, '+', ms=10, mew=2, color='#1946BA')
     #
 
-    ax.grid(True)
-    ax.axis('square')
-    ax.set_yticks(np.arange(-1, 1.2, 0.2))
-    ax.set_yticks(np.arange(-1, 1.2, 0.2))
+    st.pyplot(fig)
+
+
+def plot_ref_from_f(r, i, f):
+    fig = plt.figure(figsize=(10, 10))
+    abs_S = list(math.sqrt(r[n] ** 2 + i[n] ** 2) for n in range(len(r)))
+    xlim = [min(f)-abs(max(f)-min(f))*0.1, max(f)+abs(max(f)-min(f))*0.1]
+    ylim = [min(abs_S)-abs(max(abs_S)-min(abs_S))*0.5, max(abs_S)+abs(max(abs_S)-min(abs_S))*0.5]
+    ax = fig.add_subplot()
+    ax.set_xlim(xlim)
+    ax.set_ylim(ylim)
+    ax.grid(which='major', color='k', linewidth=1)
+    ax.grid(which='minor', color='grey', linestyle=':', linewidth=0.5)
+    plt.xlabel(r'$f,\; 1/c$', color='gray', fontsize=16, fontname="Cambria")
+    plt.ylabel('$|\Gamma|$', color='gray', fontsize=16, fontname="Cambria")
+    plt.title('Modulus of reflection coefficient from frequency', fontsize=24, fontname="Cambria")
+    ax.plot(f, abs_S, '+', ms=10, mew=2, color='#1946BA')
     st.pyplot(fig)
 
 
@@ -46,13 +79,13 @@ def run(calc_function):
     if uploaded_file is not None:
         data = uploaded_file.readlines()
 
-
     col1, col2 = st.columns(2)
 
     select_data_format = col1.selectbox('Choose data format from a list',['Frequency, Re(S11), Im(S11)','Frequency, Re(Zin), Im(Zin)'])
 
-    select_separator = col2.selectbox('Choose separator',['","' ,'" "','";"'])
-    select_coupling_losses = st.checkbox('I want to apply corrections for coupling losses (lossy coupling)')
+    select_separator = col2.selectbox('Choose separator',['" "' ,'","','";"'])
+    select_coupling_losses = st.checkbox('Apply corrections for coupling losses (lossy coupling)')
+    
     def is_float(element) -> bool:
         try:
             float(element)
@@ -62,19 +95,30 @@ def run(calc_function):
             return True
         except ValueError:
             return False
+
     def unpack_data(data):
+        nonlocal select_separator
+        nonlocal select_data_format
         f, r, i = [], [], []
         if select_data_format == 'Frequency, Re(S11), Im(S11)':
             for x in range(len(data)):
-                tru = data[x].split(select_separator)
+                # print(select_separator)
+                select_separator=select_separator.replace('\"','')
+                if select_separator==" ":
+                    tru = data[x].split()
+                else:
+                    data[x]=data[x].replace(select_separator,' ')
+                    tru = data[x].split()
+
+
                 if len(tru)!=3:
                     return f, r, i, 'Bad line in your file. №:' + str(x)
                 a, b, c = (y for y in tru)
                 if not ((is_float(a)) or (is_float(b)) or (is_float(c))):
                     return f, r, i, 'Bad data. Your data isnt numerical type. Number of bad line:' + str(x)
-                f.append(a)  # frequency
-                r.append(b)  # Re of S11
-                i.append(c)  # Im of S11
+                f.append(float(a))  # frequency
+                r.append(float(b))  # Re of S11
+                i.append(float(c))  # Im of S11
         else:
             return f, r, i, 'Bad data format'
         return f, r, i, 'very nice'
@@ -82,19 +126,23 @@ def run(calc_function):
 
     validator_status = 'nice'
     # calculate
-    circle_params=[]
+    circle_params = []
     if len(data) > 0:
-        f,r,i,validator_status = unpack_data(data)
+        f, r, i, validator_status = unpack_data(data)
 
-        Q0,sigmaQ0,QL,sigmaQl, circle_params =calc_function(f,r,i)
+        Q0, sigmaQ0, QL, sigmaQl, circle_params = calc_function(f, r, i)
+        Q0 = round_up(Q0)
+        sigmaQ0 = round_up(sigmaQ0)
+        QL = round_up(QL)
+        sigmaQl = round_up(sigmaQl)
         st.write("Cable attenuation")
-        st.write(f"Q0 = {Q0} +- {sigmaQ0}, epsilon Q0 ={sigmaQ0/Q0}")
-        st.write(f"QL = {QL} +- {sigmaQl}, epsilon QL ={sigmaQl/QL}")
-
+        st.latex(r'Q_0 =' + f'{Q0} \pm {sigmaQ0},  ' + r'\;\;\varepsilon_{Q_0} =' + f'{round_up(sigmaQ0 / Q0)}')
+        st.latex(r'Q_L =' + f'{QL} \pm {sigmaQl},  ' + r'\;\;\varepsilon_{Q_L} =' + f'{round_up(sigmaQl / QL)}')
 
-    st.write("Status: " +validator_status)
+    st.write("Status: " + validator_status)
 
     if len(data) > 0:
-        f,r,i,validator_status = unpack_data(data)
-        plot_data(r,i,circle_params)
-    
+        f, r, i, validator_status = unpack_data(data)
+        if validator_status == 'very nice':
+            plot_data(r, i, circle_params)
+            plot_ref_from_f(r, i, f)        

File diff suppressed because it is too large
+ 0 - 0
source/other/article_research/plan.drawio.svg


BIN
source/other/article_research/plan.png


File diff suppressed because it is too large
+ 0 - 0
source/other/article_research/plan.svg


Some files were not shown because too many files changed in this diff