Skip to content

Commit

Permalink
Merge pull request #14 from RFingAdam/dev
Browse files Browse the repository at this point in the history
Merge 3d plotting updates
  • Loading branch information
RFingAdam authored Sep 1, 2023
2 parents 69b7d7e + 4368ba0 commit 10b2aaf
Show file tree
Hide file tree
Showing 15 changed files with 542 additions and 347 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ __pycache__/
# Build and distribution folders
build/
dist/
debug/

# PyInstaller spec files
*.spec
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
# RFlect - Antenna Plot Tool
# RFlect - Antenna Plot Tool <img src="./assets/smith_logo.png" alt="RFlect Logo" width="40">

**Version:** 1.0.3

**Version:** 1.1.0

RFlect is a comprehensive antenna plotting tool, currently designed specifically for visualizing and analyzing antenna measurements from the Howland Company 3100 Antenna Chamber and WTL Test Lab outputs. Additionally, it offers support for .csv VNA files of S11/VSWR, making it a versatile choice for a wide range of antenna data processing needs. Through its user-friendly graphical interface, RFlect provides an intuitive way to handle various antenna metrics and visualize results.

## Installation
1. Run the provided installer from the latest release (`RFlect_vX.X.X.exe`)
2. Follow the on-screen instructions to complete the installation.

![Installation Steps](./assets/installation_steps.png)

## How to Use
### Select Scan Type:
- Choose from **Active(Future Implementation)**, **Passive**, or **.csv (VNA/S11 LogMAG)** scan.

![Scan Type Selection](./assets/scan_type_selection.png)

### Adjust Settings (if needed):
- Click the **Settings** button to open the settings window.
- Depending on your scan type selection, adjust the relevant settings.
- For VNA/S11 LogMAG scans, you can set limit lines.
![VSWR Settings Window](./assets/vswr_settings_window.png)
- For Passive scans, select between G&D or HPOL/VPOL.
![Passive Settings Window](./assets/passive_settings_window.png)
- For Active scans, *future implementation*

### Import Data:
Expand All @@ -28,7 +35,7 @@ RFlect is a comprehensive antenna plotting tool, currently designed specifically
- For other scan types, results will be displayed after data import.

## Additional Features
- Save your results using the **Save Results to File** button.(Not Implemented)
- Save your results using the **Save Results to File** button. (Not Implemented)
- Adjust the frequency and other parameters using the provided dropdown menus and input fields.

## Note to Users
Expand All @@ -37,4 +44,4 @@ RFlect is a comprehensive antenna plotting tool, currently designed specifically

---

**The software is under active development, and additional features and improvements are expected in the future. Please refer to the release notes for version-specific details.**
**The software is under active development, and additional features and improvements are expected in the future. Please refer to the release notes for version-specific details.**
6 changes: 6 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# RFlect - Release Notes

## Version 1.1.0 (09/01/2023)
- Codebase has been refactored into separate modules
- Added Docstrings
- Updated Images in README.md
- Added Passive 3D Plots, Theta, Phi, and Total Gain

## Version 1.0.3 (08/24/2023)
- Fixed Bug with Passive Scan Selection

Expand Down
Binary file added assets/gd_import.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/hpolvpol_import.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/installation_steps.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/passive_settings_window.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/scan_type_selection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/vswr_settings_window.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions plot_antenna/calculations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import numpy as np


#Auto Determine Polarization for HPOL & VPOL Files
def determine_polarization(file_path):
with open(file_path, 'r') as f:
content = f.read()
if "Horizontal Polarization" in content:
return "HPol"
else:
return "VPol"

#Verify angle data and frequencies are not mismatched
def angles_match(start_phi_h, stop_phi_h, inc_phi_h, start_theta_h, stop_theta_h, inc_theta_h,
start_phi_v, stop_phi_v, inc_phi_v, start_theta_v, stop_theta_v, inc_theta_v):

return (start_phi_h == start_phi_v and stop_phi_h == stop_phi_v and inc_phi_h == inc_phi_v and
start_theta_h == start_theta_v and stop_theta_h == stop_theta_v and inc_theta_h == inc_theta_v)

#Extract Frequency points for selection in the drop-down menu
def extract_passive_frequencies(file_path):
with open(file_path, 'r') as file:
content = file.readlines()

# Extracting frequencies
frequencies = [float(line.split("=")[1].split()[0]) for line in content if "Test Frequency" in line]

return frequencies

#Calculate Total Gain Vector and add cable loss etc - Use Phase for future implementation?
def calculate_passive_variables(hpol_data, vpol_data, cable_loss, start_phi, stop_phi, inc_phi, start_theta, stop_theta, inc_theta, freq_list, selected_frequency):
theta_points = int((stop_theta - start_theta) / inc_theta + 1)
phi_points = int((stop_phi - start_phi) / inc_phi + 1)
data_points = theta_points * phi_points

theta_angles_deg = np.zeros((data_points, len(freq_list)))
phi_angles_deg = np.zeros((data_points, len(freq_list)))
v_gain_dB = np.zeros((data_points, len(freq_list)))
h_gain_dB = np.zeros((data_points, len(freq_list)))
v_phase = np.zeros((data_points, len(freq_list)))
h_phase = np.zeros((data_points, len(freq_list)))

for m, (hpol_entry, vpol_entry) in enumerate(zip(hpol_data, vpol_data)):
for n, (theta_h, phi_h, mag_h, phase_h, theta_v, phi_v, mag_v, phase_v) in enumerate(zip(hpol_entry['theta'], hpol_entry['phi'], hpol_entry['mag'], hpol_entry['phase'], vpol_entry['theta'], vpol_entry['phi'], vpol_entry['mag'], vpol_entry['phase'])):
v_gain = mag_v
h_gain = mag_h
v_ph = phase_v
h_ph = phase_h

theta_angles_deg[n, m] = theta_h
phi_angles_deg[n, m] = phi_h
v_gain_dB[n, m] = v_gain
h_gain_dB[n, m] = h_gain
v_phase[n, m] = v_ph
h_phase[n, m] = h_ph

cable_loss_matrix = np.ones((phi_points * theta_points, len(freq_list))) * cable_loss
v_gain_dB += cable_loss_matrix
h_gain_dB += cable_loss_matrix

Total_Gain_dB = 10 * np.log10(10**(v_gain_dB/10) + 10**(h_gain_dB/10))


return theta_angles_deg, phi_angles_deg, v_gain_dB, h_gain_dB, Total_Gain_dB
22 changes: 22 additions & 0 deletions plot_antenna/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
Configuration file for the RFlect application.
This module contains constants and configuration values used throughout the application.
"""

#3D Plotting Interpolation Resolution
PHI_RESOLUTION = 1440 #default 360 = 1deg spacing
THETA_RESOLUTION = 720 #default 180 - 1deg spacing

# GUI Settings
# Colors
DARK_BG_COLOR = "#2E2E2E"
LIGHT_TEXT_COLOR = "#FFFFFF"
ACCENT_BLUE_COLOR = "#4A90E2"
BUTTON_COLOR = "#3A3A3A"
HOVER_COLOR = "#4A4A4A"
ACCENT_GREEN_COLOR = "#4CAF50"

# Fonts
HEADER_FONT = ("Arial", 14, "bold")
LABEL_FONT = ("Arial", 12)
124 changes: 124 additions & 0 deletions plot_antenna/file_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
from config import ACCENT_GREEN_COLOR, ACCENT_BLUE_COLOR

import os

#Read in TRP/Active Scan File
def read_active_file(file_path):
with open(file_path, 'r') as file:
content = file.readlines()
return parse_active_file(content)

# Read in Passive HPOL/VPOL Files
def read_passive_file(file_path):
with open(file_path, 'r') as file:
content = file.readlines()
return parse_passive_file(content)

# Function to parse the data from active TRP files
def parse_active_file(content):
#tbd
return

# Function to parse the data from HPOL/VPOL files
def parse_passive_file(content):
"""
Parse passive files and return a consolidated dataframe.
This function reads and processes passive scan files (typically in .csv format).
It consolidates the data from these files into a single dataframe.
Parameters:
- files (list): List of file paths to be parsed.
Returns:
- DataFrame: A pandas DataFrame containing the consolidated data from the files.
"""

# Initialize variables to store PHI and THETA details
all_data = []
start_phi, stop_phi, inc_phi = None, None, None
start_theta, stop_theta, inc_theta = None, None, None

# Extract Theta & PHI details
for line in content:
if "Axis1 Start Angle" in line:
start_phi = float(line.split(":")[1].split("Deg")[0].strip())
elif "Axis1 Stop Angle" in line:
stop_phi = float(line.split(":")[1].split("Deg")[0].strip())
elif "Axis1 Increment" in line:
inc_phi = float(line.split(":")[1].split("Deg")[0].strip())
elif "Axis2 Start Angle" in line:
start_theta = float(line.split(":")[1].split("Deg")[0].strip())
elif "Axis2 Stop Angle" in line:
stop_theta = float(line.split(":")[1].split("Deg")[0].strip())
elif "Axis2 Increment" in line:
inc_theta = float(line.split(":")[1].split("Deg")[0].strip())

# Calculate the expected number of data points
theta_points = (stop_theta - start_theta) / inc_theta + 1
phi_points = (stop_phi - start_phi) / inc_phi + 1
data_points = int(theta_points * phi_points)

# Extract data for each frequency
while content:
cal_factor_line = next((line for line in content if "Cal Std Antenna Peak Gain Factor" in line), None)
if not cal_factor_line:
break
cal_factor_value = float(cal_factor_line.split('=')[1].strip().split(' ')[0])

freq_line = next((line for line in content if "Test Frequency = " in line), None)
freq_value = float(freq_line.split('=')[1].strip().split(' ')[0])

start_index = next((i for i, line in enumerate(content) if "THETA\t PHI\t Mag\t Phase" in line), None)
if start_index is None:
break
start_index += 2

data_lines = content[start_index:start_index+data_points]
theta, phi, mag, phase = [], [], [], []
for line in data_lines:
line_data = line.strip().split('\t')
if len(line_data) != 4:
break
t, p, m, ph = map(float, line_data)
theta.append(t)
phi.append(p)
mag.append(m)
phase.append(ph)

freq_data = {
"frequency": freq_value,
"cal_factor": cal_factor_value,
"theta": theta,
"phi": phi,
"mag": mag,
"phase": phase
}
all_data.append(freq_data)
content = content[start_index + data_points:]

return all_data, start_phi, stop_phi, inc_phi, start_theta, stop_theta, inc_theta

def save_to_results_folder(filename, content, widget):
"""
Save the given data to the specified file within the results folder.
Parameters:
- filename (str): The name of the file to save to.
- data (Any): The data to be saved.
Returns:
- str: The path to the saved file.
"""

# Check if a results folder exists or not
if not os.path.exists("results"):
os.makedirs("results")

# Save the content to the file in the results folder
with open(os.path.join("results", filename), "w") as f:
f.write(content)

# Provide feedback through the widget (in this case, a button)
widget.config(text="Save Results to File (Saved!)", bg=ACCENT_GREEN_COLOR)
widget.after(2000, lambda: widget.config(text="Save Results to File", bg=ACCENT_BLUE_COLOR))
Loading

0 comments on commit 10b2aaf

Please sign in to comment.