Skip to content
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

Merged
merged 1 commit into from
Mar 5, 2025

Conversation

dmarek-flex
Copy link
Contributor

@dmarek-flex dmarek-flex commented Feb 26, 2025

Uses find_peaks functionality in scipy.signal to locate lobes in antenna radiation patterns.

  • Basic functionality for finding main/side lobes, width measures like FWHM/FNBW,
  • Improve input validation
  • More testing
  • improve docs

@dmarek-flex dmarek-flex self-assigned this Feb 26, 2025
@dmarek-flex dmarek-flex marked this pull request as draft February 26, 2025 16:15
@dmarek-flex
Copy link
Contributor Author

Basically given a plot like the blue line, we can find orange peaks and width measures like the red lines.

image

@dmarek-flex dmarek-flex force-pushed the dmarek/add_antenna_gain_and_efficiency branch 2 times, most recently from 88cf00a to ca98bd2 Compare February 26, 2025 20:44
Base automatically changed from dmarek/add_antenna_gain_and_efficiency to develop February 26, 2025 21:14
@dmarek-flex dmarek-flex force-pushed the dmarek/add_lobe_measures branch from 7e3260d to 265cd61 Compare February 27, 2025 21:51
@dmarek-flex dmarek-flex marked this pull request as ready for review February 27, 2025 21:52
@dmarek-flex
Copy link
Contributor Author

Ready for first pass review. Still need to improve validation of input data, but it is working well

@dmarek-flex dmarek-flex force-pushed the dmarek/add_lobe_measures branch 3 times, most recently from bb5316a to ba59405 Compare February 28, 2025 15:37
@dmarek-flex
Copy link
Contributor Author

dmarek-flex commented Feb 28, 2025

@yaugenst-flex Is there a need to change how I import Scipy? (regarding this issue)

@dmarek-flex dmarek-flex force-pushed the dmarek/add_lobe_measures branch from ba59405 to 1e49ba1 Compare February 28, 2025 16:49
@yaugenst-flex
Copy link
Collaborator

@yaugenst-flex Is there a need to change how I import Scipy? (regarding this issue)

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 components really depends on? In that case I think it might be fine, but maybe do the lazy import just in case? Along similar lines, if the functionality is optional, there is always the option of putting it in a plugin. There we are not constrained by these imports.

@dmarek-flex
Copy link
Contributor Author

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.

@dmarek-flex dmarek-flex force-pushed the dmarek/add_lobe_measures branch from 30bcd07 to d348103 Compare March 3, 2025 14:49
@dmarek-flex
Copy link
Contributor Author

I used the LobeMeasurer in this updated notebook.

Copy link
Collaborator

@weiliangjin2021 weiliangjin2021 left a 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,
Copy link
Collaborator

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?

Copy link
Contributor Author

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:
Copy link
Collaborator

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?

Copy link
Contributor Author

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.

Copy link
Contributor

@dbochkov-flexcompute dbochkov-flexcompute left a 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)
    
Screenshot_20250303_193425

@dmarek-flex
Copy link
Contributor Author

dmarek-flex commented Mar 4, 2025

One high-level question: what is the typical choice of radiation_pattern? Is that mostly far-field radiation power?

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.

@dmarek-flex
Copy link
Contributor Author

  • 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:

That is great, I'll add something like that

@dmarek-flex dmarek-flex force-pushed the dmarek/add_lobe_measures branch from d348103 to df3577f Compare March 4, 2025 22:04
@dmarek-flex
Copy link
Contributor Author

@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.

@dbochkov-flexcompute
Copy link
Contributor

@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

@dmarek-flex
Copy link
Contributor Author

Yea, my current workaround is to simply query axis using ax.get_ylim(). This will work unless the user later changes the rlim.

@dmarek-flex dmarek-flex force-pushed the dmarek/add_lobe_measures branch from df3577f to 0b32981 Compare March 5, 2025 19:45
@dmarek-flex
Copy link
Contributor Author

dmarek-flex commented Mar 5, 2025

@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 LobeMeasurer because I think it is different enough from monitors to warrant a different naming scheme.

@dmarek-flex dmarek-flex merged commit 19942bc into develop Mar 5, 2025
15 checks passed
@dmarek-flex dmarek-flex deleted the dmarek/add_lobe_measures branch March 5, 2025 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants