-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add tool for calculating antenna lobe measures #2275
Conversation
88cf00a
to
ca98bd2
Compare
7e3260d
to
265cd61
Compare
Ready for first pass review. Still need to improve validation of input data, but it is working well |
bb5316a
to
ba59405
Compare
@yaugenst-flex Is there a need to change how I import Scipy? (regarding this issue) |
ba59405
to
1e49ba1
Compare
Hey @dmarek-flex thanks for thinking of this. Yes, if possible could you lazy import scipy and raise a meaningful error in case it's not found. Since this is a "tool", I assume the functionality is somewhat optional? Right now we are trying to avoid importing scipy into the global tidy3d namespace so you can import and validate most modules without having scipy installed. If I'm reading this correctly it actually seems like the lobe measurer class has to be imported by the user and is not something that |
Need to think about it, but I guess it makes more sense to put this in the microwave plugin, since it is a post processing tool. |
30bcd07
to
d348103
Compare
I used the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice feature! One high-level question: what is the typical choice of radiation_pattern
? Is that mostly far-field radiation power?
peaks, peak_props = find_peaks( | ||
signal, | ||
plateau_size=MIN_PLATEAU_SIZE, | ||
width=MIN_WIDTH_SAMPLES, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't fully get the meaning of width
. Could you explain a bit on the default value and how it affects the results?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the way I calculate the widths, so I no longer need it actually. Basically though when some parameters are missing, the data returned by the find_peaks
function will be a subset of all possible peak_props
. That is why I add plateau_size
, which I now explain in more detail.
return dataframe | ||
|
||
@cached_property | ||
def lobe_measures(self) -> DataFrame: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when do we need this property? seems we can just rename all_lobe_measures
to lobe_measures
as it contains everything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I will simplify it. Some of the measures I had added were mostly for making plots (location of the width measure lines). But I guess it does not hurt to include them, as long as I explain them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! A few comments:
- just a suggestion: an alternative name for the class could be
LobeData
to kinda match our monitor data name convention - regarding FNBW: is it supposed to be measured from nearest minima or from actual nearest nulls? I thought it's the latter, but probably our projection and directivity monitors would never return actual zeros numerically. Maybe need to introduce a parameter which tells what relative magnitude is considered to be a null (in addition to point being a minimum)?
- maybe would be useful to add some visualization method that plots found peaks and widths, something like
lobe_data.plot(lobe_ind=2, ax=ax)
.
Just some ideas what it could look like:import numpy as np import tidy3d as td from matplotlib import pyplot as plt from tidy3d.plugins.microwave import LobeMeasurer theta = np.linspace(0, 2 * np.pi, 301, endpoint=False) Urad = np.cos(theta) ** 2 * np.cos(3 * theta) ** 2 + 0.125 lobe_measurer = LobeMeasurer( angle=theta, radiation_pattern=Urad) lobe_measures = lobe_measurer.lobe_measures lobe_ind = 1 _, ax = plt.subplots(1, 1, subplot_kw={"projection": "polar"}) ax.plot(theta, Urad, "k") ax.axvline(lobe_measures["direction"][lobe_ind], color="tab:red", ls="-") ax.axvline(lobe_measures["direction"][lobe_ind] - 0.5 * lobe_measures["FNBW"][lobe_ind], color="tab:blue", lw=1, ls=":") ax.axvline(lobe_measures["direction"][lobe_ind] + 0.5 * lobe_measures["FNBW"][lobe_ind], color="tab:blue", lw=1, ls=":") ax.axvline(lobe_measures["direction"][lobe_ind] - 0.5 * lobe_measures["width"][lobe_ind], color="tab:orange", lw=1, ls="--") ax.axvline(lobe_measures["direction"][lobe_ind] + 0.5 * lobe_measures["width"][lobe_ind], color="tab:orange", lw=1, ls="--") ax.fill_between(np.linspace(lobe_measures["direction"][lobe_ind] - 0.5 * lobe_measures["FNBW"][lobe_ind], lobe_measures["direction"][lobe_ind] + 0.5 * lobe_measures["FNBW"][lobe_ind], 10), 0, 1.25 * lobe_measures["magnitude"][lobe_ind], alpha=0.2) ax.fill_between(np.linspace(lobe_measures["direction"][lobe_ind] - 0.5 * lobe_measures["width"][lobe_ind], lobe_measures["direction"][lobe_ind] + 0.5 * lobe_measures["width"][lobe_ind], 10), 0, 1.5 * lobe_measures["magnitude"][lobe_ind], alpha=0.2)

It can mean different things AFAIK, but the value should be a real non-negative number, i.e., a magnitude. It can represent field strength/radiation intensity/directivity/gain. It is more common to plot "power patterns", which may represent radiation intensity/directivity/gain. All of these parameters should have the same relative pattern, just scaled differently, except for field strength. |
That is great, I'll add something like that |
d348103
to
df3577f
Compare
@dbochkov-flexcompute Been trying to get this plotting working robustly! I think there is a bug in matplotlib that I reported. Trying to figure out a workaround, do you have any ideas I can try to fix this or achieve a similar result? I could just get rid of the fill. |
ah, sad, probably just easier not to do the fill after all. Even if you smartly choose filling limits based on data, there is nothing that prevents user to adjust limits after that, which would break the plot |
Yea, my current workaround is to simply query axis using |
df3577f
to
0b32981
Compare
@dbochkov-flexcompute Finally, I chose to remove the fill feature 😞. Otherwise, I implemented your suggested plotting and null threshold features. I made the executive decision to not rename the |
Uses
find_peaks
functionality in scipy.signal to locate lobes in antenna radiation patterns.