pax_global_header 0000666 0000000 0000000 00000000064 14134276352 0014521 g ustar 00root root 0000000 0000000 52 comment=0f966f1d0118cc3e062e43545a1e58f665de5d7c
DispersionTransform-0.0.1/ 0000775 0000000 0000000 00000000000 14134276352 0015532 5 ustar 00root root 0000000 0000000 DispersionTransform-0.0.1/.flake8 0000664 0000000 0000000 00000000057 14134276352 0016707 0 ustar 00root root 0000000 0000000 [flake8]
filename = *.py
max-line-length = 120
DispersionTransform-0.0.1/.github/ 0000775 0000000 0000000 00000000000 14134276352 0017072 5 ustar 00root root 0000000 0000000 DispersionTransform-0.0.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14134276352 0021127 5 ustar 00root root 0000000 0000000 DispersionTransform-0.0.1/.github/workflows/ci.yml 0000664 0000000 0000000 00000001770 14134276352 0022252 0 ustar 00root root 0000000 0000000 name: ci
on:
push:
branches:
- main
pull_request:
schedule:
[cron: "0 12 * * 0"]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
python-version: [3.8]
name: ${{ matrix.os }}, Python ${{ matrix.python-version }}
defaults:
run:
shell: bash -l {0}
steps:
- uses: actions/checkout@v2
- uses: conda-incubator/setup-miniconda@v2
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements-dev.txt') }}-${{ matrix.python-version }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.python-version }}-
${{ runner.os }}-${{ matrix.python-version }}-
- run: pip install -r requirements-dev.txt
- run: pip install -e .
- name: Test
run: pytest -v
DispersionTransform-0.0.1/.github/workflows/linter.yml 0000664 0000000 0000000 00000000736 14134276352 0023155 0 ustar 00root root 0000000 0000000 name: linter
on: [push, pull_request]
jobs:
lint-flake8:
runs-on: ubuntu-latest
name: Lint
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.8 environment
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8
- name: Analysing the code with flake8
run: |
flake8 .
DispersionTransform-0.0.1/.gitignore 0000664 0000000 0000000 00000000125 14134276352 0017520 0 ustar 00root root 0000000 0000000 __pycache__/
.ipynb_checkpoints/
.pytest_cache/
.idea/
*.pyc
examples/
*.egg-info/ DispersionTransform-0.0.1/CHANGES.md 0000664 0000000 0000000 00000000074 14134276352 0017125 0 ustar 00root root 0000000 0000000 v0.0.1 (21-Oct-2021)
====================
Initial release.
DispersionTransform-0.0.1/LICENSE.md 0000664 0000000 0000000 00000002054 14134276352 0017137 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2021 John Garrett
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. DispersionTransform-0.0.1/README.md 0000664 0000000 0000000 00000010531 14134276352 0017011 0 ustar 00root root 0000000 0000000 Dispersion-Compensated Algorithm
================================
*Dispersion-Compensated Algorithm for the Analysis for Electromagnetic Waveguides*
This package allows you to map dispersive waveguide data from the frequency-domain to distance-domain, and vice versa. The benefit of this approach, compared to a standard Fourier transform, is that this algorithm compensates for dispersion. Normally, dispersion causes signals in the time-domain to broaden as the propagate, making it difficult to isolate or supress adjacent signals. In the distance-domain, the signals remain sharp, even over long distances, allowing you to easily identify, isolate or suppress specific signals.
For more information, see:
- J. D. Garrett and C. E. Tong, ["A Dispersion-Compensated Algorithm for the Analysis of Electromagnetic Waveguides",](https://ieeexplore.ieee.org/document/9447194) *IEEE Signal Processing Letters*, vol. 28, pp. 1175-1179, Jun. 2021, doi: [10.1109/LSP.2021.3086695](https://doi.org/10.1109/LSP.2021.3086695).
Example: Simple Waveguide Section
---------------------------------
Transmission through a 10" long gold-plated WR-2.8 waveguide:
Below, the time-domain response (calculated by an IFFT) is compared to the distance-domain response. Notice how much sharper the distance-domain response is.
Example: Waveguide Cavity Resonator
-----------------------------------
This is a quick example showing the power of the dispersion-compensated algorithm. See [the included notebook](https://github.com/garrettj403/DispersionTransform/blob/main/examples/example-waveguide-cavity.ipynb) for more information.
For this example, we will start with the frequency-domain response of a simple waveguide cavity resonator, as shown below. This is a 1 inch long WR-2.8 cavity. Whenever the length of the cavity is an integer number of the guided wavelength divided by two, there is a peak in transmission.
In the distance-domain, we can see a series of reflections corresponding to different signal paths within the resonator. The first peak is the signal passing straight through the resonator (distance = 1 inch), the second peak is the signal that undergoes ones internal back-and-forth reflection (distance = 3 inch), etc.
In the distance-domain, we can easily isolate the first peak and then return to the frequency-domain. The isolated reflection provides a very close match to theory.
Likewise, we can easily isolate the 6th peak and return to the frequency-domain. This is impossible in the time-domain because there is too much broadening and overlap between adjacent reflections.
Note: This example is similar to the example presented by [Garrett & Tong 2021](https://ieeexplore.ieee.org/document/9447194), but it is slightly different (e.g., different dimensions, different iris parameters, etc.). Please see this paper for more information.
Citing This Repo
----------------
If you use this code, please cite the following paper:
@article{Garrett2021,
author = {John D. Garrett and
Edward Tong},
title = {{A Dispersion-Compensated Algorithm for the Analysis of Electromagnetic Waveguides}},
volume = {28},
pages = {1175--1179},
month = jun,
year = {2021},
journal = {IEEE Signal Processing Letters},
doi = {10.1109/LSP.2021.3086695},
url = {https://ieeexplore.ieee.org/document/9447194}
}
DispersionTransform-0.0.1/disptrans.py 0000664 0000000 0000000 00000004351 14134276352 0020116 0 ustar 00root root 0000000 0000000 """Dispersion-compensated algorithm for mapping dispersive waveguide data from
the frequency-domain to distance-domain, and vice versa."""
import numba as nb
import numpy as np
@nb.njit
def freq2distance(f, fresp, beta, x):
"""Transform a frequency-domain signal to the distance-domain.
Compensates for dispersion.
Args:
f (np.ndarray): frequency for frequency-domain signal, in units [Hz]
fresp (np.ndarray): frequency-domain signal
beta (np.ndarray): phase constant, in units [rad/m]
x (np.ndarray): distance array for output data, in units [m]
Returns:
np.ndarray: distance-domain response
"""
# TODO: add default value for x
fpts = len(f) # number of frequency-domain points
xpts = len(x) # number of distance-domain points
# Calculate distance-domain response, xresp
# TODO: optimize
xresp = np.zeros(xpts, dtype=np.complex128)
for x_idx in range(xpts):
xresp[x_idx] = np.sum(fresp * np.exp(1j * beta * x[x_idx]))
# Normalize
xresp /= fpts
return xresp
@nb.njit
def distance2freq(x, xresp, beta, f):
"""Transform a distance-domain signal to the frequency-domain.
Compensates for dispersion.
Args:
x (np.ndarray): distance array for input data, in units [m]
xresp (np.ndarray): distance-domain response
beta (np.ndarray): phase constant, in units [rad/m]
f (np.ndarray): frequency for frequency-domain response, in units [Hz]
Returns:
np.ndarray: frequency-domain response
"""
# TODO: add default value for f
def _delta(xx):
"""Calculate derivative of xx."""
result = np.zeros_like(xx)
result[1:-1] = xx[2:] - xx[:-2]
result[0] = result[1]
result[-1] = result[-2]
return result / 2
fpts = len(f) # number of frequency-domain points
xstep = x[1] - x[0] # distance-domain step size
# Calculate frequency-domain response, fresp
# TODO: optimize
fresp = np.zeros(fpts, dtype=np.complex128)
for f_idx in range(fpts):
fresp[f_idx] = np.sum(xresp * np.exp(-1j * beta[f_idx] * x))
# Group velocity
vg = _delta(beta)
# Normalize
fresp *= fpts * xstep * vg / 2 / np.pi
return fresp
DispersionTransform-0.0.1/examples/ 0000775 0000000 0000000 00000000000 14134276352 0017350 5 ustar 00root root 0000000 0000000 DispersionTransform-0.0.1/examples/results/ 0000775 0000000 0000000 00000000000 14134276352 0021051 5 ustar 00root root 0000000 0000000 DispersionTransform-0.0.1/examples/results/cavity-distance-domain.jpg 0000664 0000000 0000000 00001356705 14134276352 0026130 0 ustar 00root root 0000000 0000000 JFIF ,, C
C
B"
} !1AQa"q2#BR$3br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
w !1AQaq"2B #3Rbr
$4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( :S
m 9sG=Suocjm!fWY6bBm*G?