Skip to main content
Solved

Incorrect datagrid.MinY for Geometric Image Analysis


We recently implemented the Geometric Image Analysis in ZOSPy 1.30. While doing so, we noticed that IAR_DataGrid.MinY does not return the lower bound of the y-axis for the output (at least when compared to the output in OpticStudio itself). It seems to be returning either the upper bound or the abolute value. E.g., when the analysis is centered at (0,0), the x- an y-axes in OpticStudio start at -25 while the API returns -25 for MinX and 25 for MinY. 

 

Could you elaborate on what MinY (and to an extend MinX) correspond to. So far, we thought the datagrids and their axes follow the normal matrix conventions, which was the case for all analyses we implemented and used. Is this not the case for Geometric Image Analysis, or is there an error in the API?

Best answer by MichaelH

This is definitely a bug for the ZOSAPI.Analysis.AnalysisIDM.GeometricImageAnalysis feature, but maybe not for the obvious reason.

What MinX and MinY are supposed to give is the physical coordinate of the “bottom left pixel” of the DataGrid (remembering that this is actually grid.Values[0, 0] and you’ll need to perform a flipud to get it in the same orientation as OpticStudio).  So, if you are using a WavefrontMap, MinX=-1 and MinY=-1 because of the normalized pupil but if you’re using FftPsf, then this value would be in microns.  To get the width and right most pixel value, you could use something like:

width = grid.Dx * grid.Nx
right = grid.MinX + width

where Dx is the delta between pixels in the x direction and Nx is the number of pixels in the x direction.

The IAR_ interface reads the ZDA file structure and populates the fields accordingly (there is no additional calculations performed in the ZOS-API...it simply “reads” the data being passed out of the core code).  Comparing the Text Tab for both the FFT PSF and the Geometric Image Analysis, it looks like the core code for FFT PSF actually calculates things like Dx and Reference Coordinate (to get calculate MinX).  However, for Geometric Image Analysis, the core code doesn’t pass back a corresponding value for the Reference Coordinate.  The Reference Coordinate is needed to get the physical MinX and MinY values.  The Reference Coordinate value is determined by the IAS_GeometricImageAnalysis.Reference property and can be:

  • ChiefRay (REAX/REAY)
  • Vertex (GLCX/GLCY)
  • Primary Chief (REAX/REAY)
  • Centroid (CENX/CENY)

You can get the values for the Reference Coordinate by using the MFE operands in parenthesis.  The Nx and Dx values for GeometricImageAnalysis are correct, so with the calculated Reference Coordinate, you can get the correct MinX and MinY values.

Since the Geometric Image Analysis doesn’t provide a Reference Coordinate in the ZDA, I would file a bug report with the ACE team.  The MinX and MinY values should be set to NaN so improper conclusions are not drawn by the engineer.

View original
Did this topic help you find an answer to your question?

11 replies

  • Author
  • Visible
  • 22 replies
  • December 2, 2024

Is there any update on this? I would like to know that MinY actually returns


David.Nguyen
Luminary
Forum|alt.badge.img+2
  • Luminary
  • 1085 replies
  • December 2, 2024

It might be worth tagging ​@MichaelH for such an issue.

Take care,


David


MichaelH
Ansys Staff
Forum|alt.badge.img+2
  • Ansys Staff
  • 342 replies
  • Answer
  • December 5, 2024

This is definitely a bug for the ZOSAPI.Analysis.AnalysisIDM.GeometricImageAnalysis feature, but maybe not for the obvious reason.

What MinX and MinY are supposed to give is the physical coordinate of the “bottom left pixel” of the DataGrid (remembering that this is actually grid.Values[0, 0] and you’ll need to perform a flipud to get it in the same orientation as OpticStudio).  So, if you are using a WavefrontMap, MinX=-1 and MinY=-1 because of the normalized pupil but if you’re using FftPsf, then this value would be in microns.  To get the width and right most pixel value, you could use something like:

width = grid.Dx * grid.Nx
right = grid.MinX + width

where Dx is the delta between pixels in the x direction and Nx is the number of pixels in the x direction.

The IAR_ interface reads the ZDA file structure and populates the fields accordingly (there is no additional calculations performed in the ZOS-API...it simply “reads” the data being passed out of the core code).  Comparing the Text Tab for both the FFT PSF and the Geometric Image Analysis, it looks like the core code for FFT PSF actually calculates things like Dx and Reference Coordinate (to get calculate MinX).  However, for Geometric Image Analysis, the core code doesn’t pass back a corresponding value for the Reference Coordinate.  The Reference Coordinate is needed to get the physical MinX and MinY values.  The Reference Coordinate value is determined by the IAS_GeometricImageAnalysis.Reference property and can be:

  • ChiefRay (REAX/REAY)
  • Vertex (GLCX/GLCY)
  • Primary Chief (REAX/REAY)
  • Centroid (CENX/CENY)

You can get the values for the Reference Coordinate by using the MFE operands in parenthesis.  The Nx and Dx values for GeometricImageAnalysis are correct, so with the calculated Reference Coordinate, you can get the correct MinX and MinY values.

Since the Geometric Image Analysis doesn’t provide a Reference Coordinate in the ZDA, I would file a bug report with the ACE team.  The MinX and MinY values should be set to NaN so improper conclusions are not drawn by the engineer.


  • Author
  • Visible
  • 22 replies
  • December 8, 2024

Thank you for the elaborate response as well as for filing a bug report! I will try to find a way to correct this in ZOSPy for now. Just to be sure: the only way to get any of REAX, REAY, GLCX, GLCY, CENX, CENY is through the MFE correct? That is by itself easy to implement, but I would rather not alter large merit functions that people are working with while running the analysis. I think recalculating a large merit function for the sake of running the GeometricImageAnalysis is not ideal. This leaves me with two other options that I can think of:

  1. Temporarily save the current merit function, clear the MFE, add e.g. REAX, REAY , calculate, reload the original merit function.
  2. Obtain e.g. REAX, REAY through another analysis.

I think option 2 would have my preference as we do not alter the MFE that way, but then I need an analysis that provides REAX, REAY in its output. Is there such an analysis ​@MichaelH? So far I cannot find one.

 


David.Nguyen
Luminary
Forum|alt.badge.img+2
  • Luminary
  • 1085 replies
  • December 9, 2024

@Luc.van Vught 

 

I’m not sure it’ll help but you can evaluate single Merit function operands outside the MFE with the method GetOperandValue (of the IMeritFunctionEditor interface).

It doesn’t work for operands which rely on other operands, but should be ok for REAX and REAY.

Also, I think ​@MichaelH is suggesting that you file a bug report in his original message.

Take care,

 

David


  • Author
  • Visible
  • 22 replies
  • December 18, 2024

@David.Nguyen thank you for the tip! I started with an implementation here.

 

@MichaelH follow up question: when wavelength is set to "All", reference to anything but "PrimaryChief" and there are multiple wavelengths, how does OpticStudio determine the Reference Coordinate? Does is calculate one for each wavelength and then average them? I cannot find this in the manual.


@MichaelH I have almost finished a fix for this for ZOSPy, which will be publicly available so others can benefit from it. I however still wonder about how to handle determining the reference coordinate when wavelength is set to "All". Can you help me with this, or point me to who can?


I have actually answered my own question regarding MinX and  MinY. It seems to be simpler that I thought it was. The edges seem to correspond to + or - half the Image Size from the grid center (0,0). Thus, MinX and  MinY can just be obtained by -Analysis.Settings.ImageSize/2 . The  Reference moves the data within that grid, but the edges remain equal (at least in OpticStudio itself). Please correct me if I make a wrong assumption here. 

 

I am still wondering how the reference is caluclated when it is set to ChiefRay whit multiple wavelengths present, but that is more a personal interest. When the reference is Centroid, one can calculate a polychromatic reference using CENX in GetOperandValue, but this cannot be done with REAX for ChiefRay.   

 

Anyways, thank you both for your help ​@MichaelH and ​@David.Nguyen.


MichaelH
Ansys Staff
Forum|alt.badge.img+2
  • Ansys Staff
  • 342 replies
  • March 3, 2025

Hi ​@Luc.van Vught,

Yes, the MinX & MinY can be found just like you said. 

I would rephrase your next sentence slightly:

The Reference recenters the image plane sampling grid, changing the grid’s physical bounds on the image plane.

For example, if you look at the Double Gauss 28 degree field.zmx example using all default settings expect Field is set to 2 (which has a chief ray of [0.0, 17.4]), you get the following 2 scenarios for a Reference of Chief Ray vs Vertex:

So the data on the image plane isn’t moving, just the data grid sampling the image plane is moving.

As for Chief Ray/Primary Chief Ray vs wavelength, you have the following 3 scenarios:

  1. Chief Ray/Monochromatic: uses the chief ray for the defined wavelength
  2. Chief Ray/Polychromatic: uses the primary wavelength chief ray
  3. Primary Chief Ray/Monochromatic: uses the primary wavelength chief ray
  4. Primary Chief Ray/Polychromatic: uses the primary wavelength chief ray

For almost all analysis that are chief ray based, if the wavelength is polychromatic, then the primary wavelength’s chief ray is used.  Analysis who don’t use the primary wavelength’s chief ray will explicitly state this in the Help Files such as lateral color, FFT PSF for the default distance between points (uses the shortest wavelength), etc.

For the longest time, you only had a reference of Chief RayVertex, and Centroid, but this did not allow granular control of the output between Geometric Image Analysis and a converted non-sequential file with a Detector Viewer.  Adding the Primary Chief Ray now means the grid for the Geometric Image Analysis won’t shift as you change wavelengths (just like a Detector Rectangle won’t shift in non-sequential mode when you make a Source Ellipse monochromatic).


Thank you again for the elaborate explanation!


 Hi ​@MichaelH, can I ask you for a little more information on  MinX and MinY ? If you feel like this question should be a separate forum post, I'm happy to create that as well, but it is related to your answer above. In your answer , you state:

What MinX and MinY are supposed to give is the physical coordinate of the “bottom left pixel” of the DataGrid (remembering that this is actually grid.Values[0, 0] and you’ll need to perform a flipud to get it in the same orientation as OpticStudio).  So, if you are using a WavefrontMap, MinX=-1 and MinY=-1 because of the normalized pupil but if you’re using FftPsf, then this value would be in microns.  To get the width and right most pixel value, you could use something like:

width = grid.Dx * grid.Nx
right = grid.MinX + width

where Dx is the delta between pixels in the x direction and Nx is the number of pixels in the x direction.

 

Say I have a very small 2x2 grid (which is not possible in OpticStudio but just to explain my question) with a pixel size of 1x1, a MinX of -1 and a MinY of -1:

   y
 1 +--+--+
   |  |  |
 0 +--+--+
   |  |  |
-1 +--+--+x
  -1  0  1

I obtain the values from this datagrid, which gives me a 2x2 matrix. Now if I ad column and row labels to that matrix (e.g. in a pandas.DataFrame in Python), I think it is logical if those labels represent the centers of the pixel rather than the edge ([-0.5, 0.5] for both the x- and y-axis in this example). To obtain that we can do the following in Python:

minx = datagrid.MinX + 0.5 * datagrid.Dx
xlabels = np.linspace(minx, minx + datagrid.Dx * (datagrid.Nx - 1), datagrid.Nx)

This ensures that if I would directly plot the grid using these labels, the plot is nicely centered around (0,0), as also happens in OpticStudio itself.

 

Cases where this does not seem correct

SurfaceCurvature

If have however also encountered analyses where this provides erroneous labels. E.g. in the SurfaceCurvature analysis. In this analysis, (datagrid.MinX, datagrid.MinY) seems to point to the exact coordinate at which the first value is obtained rather than to the edge of a pixel. Thus, then I have to do:

minx = datagrid.MinX
xlabels = np.linspace(minx, minx + datagrid.Dx * (datagrid.Nx - 1), datagrid.Nx)

If you for example perform the SurfaceCurvature analysis for surface 2 of the OpticStudio sample file Even Asphere, setting MinX = datagrid.MinX will give a datagrid centered on (0,0) with a MaxX of 15, while setting MinX = datagrid.MinX + 0.5 * datagrid.Dx will give a datagrid not centered on (0,0) with a MaxX of 15.234375. Note that this analysis has a samplesize of 65x65 rahter than the (often used) 64x64, so the coordinate (0,0) should be in the labels.

 

 

WavefrontMap

Above you give the example of the WavefrontMap, where MinX and MinY are both -1 due to normalization. I think this analysis handles MinX and MinY as pixel edges, similar to my initial description, rather than as exact coordinates. Given the normalization, and your calculations for  width  and right above, I expect width to be 2 and right to be at x=1.

However, in the same OpticStudio sample file Even Asphere, calculating WavefrontMap with samplesize 64x64 on the image surface gives me the following:

datagrid.MinX = -1

datagrid.Dx = 0.031746031746031744

datagrid.Nx = 64

And using that to calculate the width gives a width of 2.031746031746031744, which is essentially one pixel to much. Now, looking at the actual data, it seems that there is a dummy row and a dummy column at the start of the datagrid, which has no values. If I drop that row and collumn (making the grid 63x63) and than use MinX and MinY as pixel boundaries, my grid is nicely ranging from -1 to 1 and centered about 0. 

 

Questions

From this, it seems that MinX and MinY  are normally the edges of a pixel but sometimes exact coordinates. Can you elaborate on that?

 

Can you also elaborate on the “dummy row and column” in the WavefrontMap. Is this something that occurs in more analyses, and am I right to drop them, or should the be handles differently?


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings