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

ParabolicalMirrorParam optics with figure error #169

Open
leahwang1962 opened this issue Jan 19, 2024 · 3 comments
Open

ParabolicalMirrorParam optics with figure error #169

leahwang1962 opened this issue Jan 19, 2024 · 3 comments

Comments

@leahwang1962
Copy link

Hi,
For ParabolicalMirrorParam, do I need to write def xyz_to_param() to over write the default one?
My ParabolicalMirrorParam optic figure error is measured as Z at each surface point (x,y) (real Z - theoretical Z). Do you have a formula in hand to get local_r_distorted, local_n_distorted base on the measured (x,y,z)?
Thanks.

@kklmn
Copy link
Owner

kklmn commented Jan 20, 2024

Hi,

I have found my old example of applying NOM measurements to a parametric mirror and extracted it to a file examples/withRaycing/13_Warping/ExampleOfSlopeErrorMapToParametricMirror.py in this repository.

It defines a distorted parametric mirror, with the distortions given in a 3-column file as (x, y, z). You should adapt it to your file structure and your definitions of x, y, z in the file.

import numpy as np
from scipy import ndimage

import xrt.backends.raycing.oes as roe


class EllipticalMirrorParamNOM(roe.EllipticalMirrorParam):
    def __init__(self, *args, **kwargs):
        kwargs = self.__pop_kwargs(**kwargs)
        super().__init__(*args, **kwargs)
        self.nom_read()

    def __pop_kwargs(self, **kwargs):
        self.waviness = kwargs.pop('figureError')  # file name
        return kwargs

    def nom_read(self):
        # here, the file self.waviness has this structure:
        # x[mm]  y[mm]  z[nm]
        # 30.00  29.75  -31.498373
        # 30.50  29.75  -32.992258
        # 31.00  29.75  -33.864061
        # 31.50  29.75  -34.240630
        # ...
        xL, yL, zL = np.loadtxt(self.waviness, unpack=True)
        nX = (yL == yL[0]).sum()
        nY = (xL == xL[0]).sum()
        x = xL[:nX]
        y = yL[::nX]
        z = zL.reshape((nY, nX))
        dx = x[1] - x[0]
        dy = y[1] - y[0]
        b, a = np.gradient(z)  # NOM x is along (our y) and y is across (our x)
        # a, b = np.gradient(z)  # NOM x is across and y is along
        a = np.arctan(a/dy)
        b = np.arctan(b/dx)
        self.nom_rmsA = ((a**2).sum() / (nX * nY))**0.5
        self.nom_rmsB = ((b**2).sum() / (nX * nY))**0.5
        self.nom_splineZ = ndimage.spline_filter(z.T) * 1e-6  # mm to nm
        self.nom_splineA = ndimage.spline_filter(a.T) * 1e-6  # rad to µrad
        self.nom_splineB = ndimage.spline_filter(b.T) * 1e-6  # rad to µrad
        self.nom_nX = nX
        self.nom_nY = nY
        self.nom_x = x
        self.nom_y = y

    def local_r_distorted(self, s, phi):
        r = self.local_r(s, phi)
        x, y, z = self.param_to_xyz(s, phi, r)
        # if NOM x is along (our y) and y is across (our x):
        coords = np.array([
            (y/(self.nom_x[-1]-self.nom_x[0]) + 0.5) * (self.nom_nX-1),
            (x/(self.nom_y[-1]-self.nom_y[0]) + 0.5) * (self.nom_nY-1)])
        # coords.shape = (2, self.nrays)
        z += ndimage.map_coordinates(self.nom_splineZ, coords, prefilter=True)
        s1, phi1, r1 = self.xyz_to_param(x, y, z)
        return r1 - r

    def local_n_distorted(self, s, phi):
        r = self.local_r(s, phi)
        x, y, z = self.param_to_xyz(s, phi, r)
        # if NOM x is along (our y) and y is across (our x):
        coords = np.array([
            (y/(self.nom_x[-1]-self.nom_x[0]) + 0.5) * (self.nom_nX-1),
            (x/(self.nom_y[-1]-self.nom_y[0]) + 0.5) * (self.nom_nY-1)])
        # coords.shape = (2, self.nrays)
        a = ndimage.map_coordinates(self.nom_splineA, coords, prefilter=True)
        b = ndimage.map_coordinates(self.nom_splineB, coords, prefilter=True)
        return -a, -b

For the visualization of your NOM results you may want to examine the main example in the same folder.

@leahwang1962
Copy link
Author

It's really helpful. Greatly appreciate.

@leahwang1962
Copy link
Author

Hello
Need more help to understand the simulation results.
With a parabolic cylindrical mirror, when I copied the waveness figure error from warp.py, the results is correct. Then I modified the waveness figure error from cos function(only along ray direction) to a square wave function. I don't understand why there is bright line in the middle. I am expecting it should be a dark line as the other 2 dark lines, because it is the location with the biggest local_r_distorted and local_n_distorted just like the other 2 locations.
Thanks.

with cos function figure error:
image
image
with square wave function figure error:
image
image

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

No branches or pull requests

2 participants