Solved

# extract distortion percentage or ref height with ZPL

• 11 replies
• 128 views

• 8 replies

Hi, I have a question of how to extract the reference height or distortion in percentage with ZPL? I was using RAYY to get the real height but I’d like to extract the other two col data as well. Thanks!

icon

Best answer by David.Nguyen 15 December 2022, 12:07

View original

### 11 replies

Userlevel 6
+2

Hi zemax_user,

I’m not quite sure which are the two columns you are refering to. Based on the title of your post, I’m assuming you want the Distortion column at least. There are several ways to go about this, but the easiest might be via the DIST Merit function operand:

 DIST Distortion in waves contributed by the surface defined by Surf at the wavelength defined by Wave. This is the third order distortion calculated from the Seidel coefficients (see “Seidel Coefficients”), and is not valid for non-paraxial systems. If Surf is zero, the distortion is given in percent instead (see “Field Curvature/Distortion” for a detailed definition). If Absolute is set to 1, and the surface number is zero, the distortion is given as an absolute length rather than a percentage. See also DISG.

The way you call an optimization operand in ZPL is through the numeric functions OCOD and OPEV. Here is a specific example below:

``# Numeric code of DIST operandDIST_OPERAND = OCOD("DIST")# DIST operand parametersSurf = 0Wave = 1Absolute = 0# Evaluate DIST operanddistortion = OPEV(DIST_OPERAND, Surf, Wave, Absolute, 0, 0, 0)# Display distortion valuePRINT "Distortion: ", distortion, "%"``

The only issue with this approach is that it displays the maximum distortion given by the most extreme field value. In your case, that would be the field at 0.51560750 deg, and the distortion reported will be 0.00278748 %. A work around would be to define a single field, and change its value in a loop with the SETSYSTEMPROPERTY (or SYSP) keyword. Something like so:

``# Numeric code of DIST operandDIST_OPERAND = OCOD("DIST")# DIST operand parametersSurf = 0Wave = 1Absolute = 0# PRINT propertiesFORMAT "%.8f" LIT# Field propertiesY_FIELD = 103 # Code for field Y value in SYSPNUM_OF_FIELDS = 100 # Number of field values to evaluateMAX_FIELD = 14.0 # Maximum field valueFIELD_INC = MAX_FIELD / NUM_OF_FIELDS # Field value increment# Loop over the different field valuesFOR field_id, 0, NUM_OF_FIELDS, 1	# Calculate field value	field_value = field_id * FIELD_INC	# Update field value	SYSP Y_FIELD, 1, field_value	UPDATE	# Evaluate DIST operand	distortion = OPEV(DIST_OPERAND, Surf, Wave, Absolute, 0, 0, 0)	# Display distortion value	PRINT "Y Angle: ", field_value, "	",	PRINT "Distortion: ", distortion, " %"NEXT``

This is what it gives in the Double-Gauss 28 deg field sample file (with a single field):

I hope this helps, and take care,

David

Hi David,

Thank you very much for the detailed solution! I tried on the Zemax sample file it worked very well. However, I’m not sure if it’s because my Zemax lens I have was converted from CodeV, I have a weird problem that when I set field type to “real image height”, the first column on the distortion output window actually shows me “Angle”; And if I set field type to “angle”, the first column will show me “image height” instead, so setting the correct “MAX_FIELD” number gets very tricky. I tried both max real image height and the corresponding angle as “MAX_FIELD” but none of the distortion % number I output matches with what I have in the build-in distortion window output. Have you encountered problems like this? And btw, I should have the line “SYSP 100, xx” above the script right?

Hi David,

Actually I think I had some issue running the above script on the sample lens as well, below is the output of running on the double gauss 28deg lens. I used the script exactly as what you shared.

Userlevel 6
+2

Hi zemax_user,

Regarding SYSP 100, xx it is your choice whether you want to have it or not. If your lens already has the correct field type definition, you don’t need it. Otherwise, feel free to change it with this keyword.

The problem you show in your last reply is what I tried to describe in the second part of my answer. It seems I wasn’t clear enough. You cannot simply use the script with the double Gauss sample file directly. The reason is that DIST will always show you the distortion at the maximum field. If you don’t edit the sample file, the maximum field is at 14 degrees. Therefore, if you use the script as it is, it will always show you the distortion at 14 degrees, which is -0.89987 percent. Instead, what you should do is erase all the fields but one. That way the maximum field angle is always represented by this single field. Does this make sense? Let me show you with an example in the double Gauss. By default, 3 fields are defined: Y = 0.0, 10.0, and 14.0 degree. Therefore if you were to call DIST, it will give you DIST at 14 degree. If you run the script, it will increase the value of the first field to 0.14. So you’ll have the new fields: Y = 0.14, 10.0, and 14.0. DIST will still return the distorsion at 14 degree because it is the maximum field angle currently defined. What you have to do erase the fields: Y = 10.0, and 14.0 degree. You’ll be left with a single field: Y = 0.0. In this case, DIST will be the distortion at 0.0 degree. Then, the script changes to field: Y = 0.14 (only), and DIST is the distortion at 0.14 degree.

Hopefully this explain your issue with the script.

Take care,

David

Hi David,

Thank you very much for the detailed explanation! I was able to fix the problem as in my screenshot after setting the system to have only one field in the beginning. However, I have a new issue that my percentage distortion is very off from what shows in the distortion window. I tried the following cases:

Use double gauss 28 degree lens, Absolute = 0, field type: angle → relatively close % distortion as in distortion window

Use my lens, absolute = 0, field type =real image height → very off from what the distortion window shows

especially in the distortion window, even the largest distortion is less than 5%. So I’m not sure what’s going on here.

Userlevel 6
+2

Hi zemax_user,

I’m confused as to why you get different distortion values than mine in the Double Gauss? Have you modified the code? If so, can you share it here for troubleshooting?

At 0.14 degree, the distortion is -0.00717977 percent with my script and the Field Curv/Dist analysis. It isn’t relatively close, it is the same number. But somehow, you get -0.00710782 percent and I want to understsand why before going further.

Can you share your file, or a simplified version of it for us to look at?

Take care,

David

Hi David,

Yes I modified the code but I only changed the sampling. I used 11 samples instead of 100, so in my screenshot the  -0.00717977% is actually associated with 1.4deg, which is the same as your screenshot in the very beginning at 1.4deg.

Userlevel 6
+2

Hi zemax_user,

I’m sorry there’s something I don’t understand, even if I use 10 samples in the Double Gauss sample file, with the code below:

``# Numeric code of DIST operandDIST_OPERAND = OCOD("DIST")# DIST operand parametersSurf = 0Wave = 1Absolute = 0# PRINT propertiesFORMAT "%.8f" LIT# Field propertiesY_FIELD = 103 # Code for field Y value in SYSPNUM_OF_FIELDS = 10 # Number of field values to evaluateMAX_FIELD = 14.0 # Maximum field valueFIELD_INC = MAX_FIELD / NUM_OF_FIELDS # Field value increment# Loop over the different field valuesFOR field_id, 0, NUM_OF_FIELDS, 1	# Calculate field value	field_value = field_id * FIELD_INC	# Update field value	SYSP Y_FIELD, 1, field_value	UPDATE	# Evaluate DIST operand	distortion = OPEV(DIST_OPERAND, Surf, Wave, Absolute, 0, 0, 0)	# Display distortion value	PRINT "Y Angle: ", field_value, "	",	PRINT "Distortion: ", distortion, " %"NEXT``

I get the following results:

At 1.4 degree, the distortion is -0.00717977. and not -0.00710782 as you reported previously. Am I missing something? Can you share your file with us?

Take care,

David

Hi David,

Sorry for the confusion. I just checked, I think our distortion values were different at 1.4deg is because I accidentally wrote in different wavelength and wavelength weightings into the Double Gauss 28deg sample file after running the ZPL file. If I don’t change anything in the double gauss sample file, I do get the exactly same output as yours.

However, I do still have the issue as I described in a reply 14 days ago. If I run the same script on my lens, the only modification I had are: (1) adding “SYSP 100, 3” since my system field is defined in real image height. (2) changing the value of “MAX_FIELD”. The output doesn’t seem to be reasonable, I was wondering if you can tell what could be wrong here? Thanks!

Hi David,

One more thing I forgot to mention, in the above reply, field height of 0-2.1 actually match with what’s given by Zemax “distortion” window. However, starting from field height of 2.4 (or maybe smaller since I used relatively big interval), the distortion starts giving values that are way off (e.g. 80%, 143%). Is there maybe any limitation in using the DIST operand? Thanks!

Userlevel 2
+2

Hi @zemax_user,

Apologies on the delayed response to your follow-up question. I suspect that the reason that you are seeing divergence in values for greater field heights is due to a difference in the method with which both values are calculated. From the Help File (The Analyze Tab (sequential ui mode) > Image Quality Group > Aberrations (Image Quality Group) > Field Curvature and Distortion The Optimize Tab (sequential ui mode) > Automatic Optimization Group > Merit Function Editor (automatic optimization group) > Optimization Operands (Alphabetically)):

For the Field Curvature and Distortion Tool:

The reference ray height is computed by tracing a real ray from a very small field height, and then scaling the results as required. This generalization permits the computation of reasonable distortion values even for systems not well described by paraxial ray tracing.

For the DIST operand:

This is the third order distortion calculated from the Seidel coefficients (see “Seidel Coefficients”), and is not valid for non-paraxial systems.

I hope this helps clarify differences in the calculations.

Best,
Ethan