def test_2d_normalize_to_slope_error(self,combination="FF"):
        mirrorLength = 200.1 # cm
        Step = 1.0
        RandomSeed = 8788
        RMS = 0.2e-6 # 2.0e-6 # rad


        mirrorWidth = 40.0
        StepW = 1.0
        RandomSeedW = 8788
        RMSW = 0.5e-6 # 1.0e-6

        if combination == "EE": # TODO: not yet tested
            input_file = package_dirname("srxraylib.metrology") + "/mirror_1d.txt"
            values = numpy.loadtxt(input_file)
            x_l = values[:, 0]
            y_l = values[:, 1]
            x_w = values[:, 0]
            y_w = values[:, 1]
            print("File loaded: %s, Length:%f, StDev: %g"%(input_file,x_l[-1]-x_l[0],y_l.std()))
            x,y,z = simulate_profile_2D(random_seed_l=RandomSeed, error_type_l=SLOPE_ERROR, rms_l=RMS,
                                        correlation_length_l=30.0,power_law_exponent_beta_l=1.5,
                                        random_seed_w=RandomSeedW, error_type_w=SLOPE_ERROR, rms_w=RMSW,
                                        correlation_length_w=30.0,power_law_exponent_beta_w=1.5,
                                        x_l=x_l,y_l=y_l,x_w=x_w,y_w=y_w,
                                        combination=combination)
        else:
            x,y,z = simulate_profile_2D(mirror_length=mirrorLength, step_l=Step, random_seed_l=RandomSeed, error_type_l=SLOPE_ERROR, rms_l=RMS,
                                        correlation_length_l=30.0,power_law_exponent_beta_l=1.5,
                                        mirror_width=mirrorWidth, step_w=StepW, random_seed_w=RandomSeedW, error_type_w=SLOPE_ERROR, rms_w=RMSW,
                                        correlation_length_w=30.0,power_law_exponent_beta_w=1.5,
                                        combination=combination)

        tmp1 = slopes(z.T,x,y,return_only_rms=1)
        print("  target SLOPE error in WIDTH:  %g rad"%(RMSW))
        print("  target SLOPE error in LENGTH: %g rad"%(RMS))



        print("  obtained HEIGHT error (in LENGTH and WIDTH): %g"%(z.std()))
        print("  obtained SLOPE error in WIDTH: %g"%(tmp1[0]))
        print("  obtained SLOPE error in LENGTH: %g"%(tmp1[1]))

        print("  shape x,y,z:",x.shape,y.shape,z.shape)

        # the LENGTH direction must match!!
        assert numpy.abs( RMS - tmp1[1] ) < 0.01 * numpy.abs(RMS)

        if do_plot:
            from srxraylib.plot.gol import plot_surface
            plot_surface(z.T*1e7,x,y,xtitle="X [cm]",ytitle="Y [cm",ztitle="Z [nm]",title="test_2d_normalize_to_slope_error")
    def calculate_heigth_profile(self, not_interactive_mode=False):
        try:
            if self.server.y is None: raise Exception("No Profile Selected")

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.check_fields()

            combination = "EF"

            if self.modify_y == 2:
                profile_1D_y_x_temp = self.si_to_user_units * self.server.y
                if self.use_undetrended == 0: profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeights
                else: profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeightsUndetrended

                first_coord = profile_1D_y_x_temp[0]
                second_coord  = profile_1D_y_x_temp[1]
                last_coord = profile_1D_y_x_temp[-1]
                step = numpy.abs(second_coord - first_coord)
                length = numpy.abs(last_coord - first_coord)
                n_points_old = len(profile_1D_y_x_temp)

                if self.new_length > length:
                    difference = self.new_length - length

                    n_added_points = int(difference/step)
                    if difference % step == 0:
                        n_added_points += 1
                    if n_added_points % 2 != 0:
                        n_added_points += 1


                    profile_1D_y_x = numpy.arange(n_added_points + n_points_old) * step
                    profile_1D_y_y = numpy.ones(n_added_points + n_points_old) * self.filler_value * 1e-9 * self.si_to_user_units
                    profile_1D_y_y[int(n_added_points/2) : n_points_old + int(n_added_points/2)] = profile_1D_y_y_temp
                elif self.new_length < length:
                    difference = length - self.new_length

                    n_removed_points = int(difference/step)
                    if difference % step == 0:
                        n_removed_points -= 1
                    if n_removed_points % 2 != 0:
                        n_removed_points -= 1

                    if n_removed_points >= 2:
                        profile_1D_y_x = profile_1D_y_x_temp[0 : (n_points_old - n_removed_points)]
                        profile_1D_y_y = profile_1D_y_y_temp[(int(n_removed_points/2) - 1) : (n_points_old - int(n_removed_points/2) - 1)]

                    else:
                        profile_1D_y_x = profile_1D_y_x_temp
                        profile_1D_y_y = profile_1D_y_y_temp
                else:
                    profile_1D_y_x = profile_1D_y_x_temp
                    profile_1D_y_y = profile_1D_y_y_temp

            else:
                if self.modify_y == 0:
                    profile_1D_y_x = self.si_to_user_units * self.server.y
                elif self.modify_y == 1:
                    profile_1D_y_x = self.si_to_user_units * self.server.y * self.scale_factor_y

                if self.use_undetrended == 0: profile_1D_y_y = self.si_to_user_units * self.server.zHeights
                else: profile_1D_y_y = self.si_to_user_units * self.server.zHeightsUndetrended


            if self.center_y:
                first_coord = profile_1D_y_x[0]
                last_coord = profile_1D_y_x[-1]
                length = numpy.abs(last_coord - first_coord)

                profile_1D_y_x_temp = numpy.linspace(-length/2, length/2, len(profile_1D_y_x))

                profile_1D_y_x = profile_1D_y_x_temp

            if self.renormalize_y == 0:
                rms_y = None
            else:
                if self.error_type_y == profiles_simulation.FIGURE_ERROR:
                    rms_y = self.si_to_user_units * self.rms_y * 1e-9   # from nm to user units
                else:
                    rms_y = self.rms_y * 1e-6 # from urad to rad

            xx, yy, zz = profiles_simulation.simulate_profile_2D(combination = combination,
                                                                 error_type_l = self.error_type_y,
                                                                 rms_l = rms_y,
                                                                 x_l = profile_1D_y_x,
                                                                 y_l = profile_1D_y_y,
                                                                 mirror_width = self.dimension_x,
                                                                 step_w = self.step_x,
                                                                 rms_w = 0.0)

            self.xx = xx
            self.yy = yy
            self.zz = zz # in user units

            self.axis.clear()

            x_to_plot, y_to_plot = numpy.meshgrid(xx, yy)
            z_to_plot = zz * 1e9 / self.si_to_user_units #nm

            self.axis.plot_surface(x_to_plot, y_to_plot, z_to_plot,
                                   rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True)

            sloperms = profiles_simulation.slopes(zz.T, xx, yy, return_only_rms=1)

            title = ' Slope error rms in X direction: %f $\mu$rad' % (sloperms[0]*1e6) + '\n' + \
                    ' Slope error rms in Y direction: %f $\mu$rad' % (sloperms[1]*1e6)

            self.axis.set_xlabel("X [" + self.workspace_units_label + "]")
            self.axis.set_ylabel("Y [" + self.workspace_units_label + "]")
            self.axis.set_zlabel("Z [nm]")

            self.axis.set_title(title)
            self.axis.mouse_init()

            if not not_interactive_mode:
                try:
                    self.plot_canvas[5].draw()
                except:
                    pass

                self.tabs.setCurrentIndex(6)

                QMessageBox.information(self, "QMessageBox.information()",
                                        "Height Profile calculated: if the result is satisfactory,\nclick \'Generate Height Profile File\' to complete the operation ",
                                        QMessageBox.Ok)
        except Exception as exception:
            QMessageBox.critical(self, "Error",
                                 exception.args[0],
                                 QMessageBox.Ok)
Beispiel #3
0
    def test_2d_normalize_to_slope_error(self, combination="FF"):
        mirrorLength = 200.1  # cm
        Step = 1.0
        RandomSeed = 8788
        RMS = 0.2e-6  # 2.0e-6 # rad

        mirrorWidth = 40.0
        StepW = 1.0
        RandomSeedW = 8788
        RMSW = 0.5e-6  # 1.0e-6

        if combination == "EE":  # TODO: not yet tested
            input_file = package_dirname(
                "srxraylib.metrology") + "/mirror_1d.txt"
            values = numpy.loadtxt(input_file)
            x_l = values[:, 0]
            y_l = values[:, 1]
            x_w = values[:, 0]
            y_w = values[:, 1]
            print("File loaded: %s, Length:%f, StDev: %g" %
                  (input_file, x_l[-1] - x_l[0], y_l.std()))
            x, y, z = simulate_profile_2D(random_seed_l=RandomSeed,
                                          error_type_l=SLOPE_ERROR,
                                          rms_l=RMS,
                                          correlation_length_l=30.0,
                                          power_law_exponent_beta_l=1.5,
                                          random_seed_w=RandomSeedW,
                                          error_type_w=SLOPE_ERROR,
                                          rms_w=RMSW,
                                          correlation_length_w=30.0,
                                          power_law_exponent_beta_w=1.5,
                                          x_l=x_l,
                                          y_l=y_l,
                                          x_w=x_w,
                                          y_w=y_w,
                                          combination=combination)
        else:
            x, y, z = simulate_profile_2D(mirror_length=mirrorLength,
                                          step_l=Step,
                                          random_seed_l=RandomSeed,
                                          error_type_l=SLOPE_ERROR,
                                          rms_l=RMS,
                                          correlation_length_l=30.0,
                                          power_law_exponent_beta_l=1.5,
                                          mirror_width=mirrorWidth,
                                          step_w=StepW,
                                          random_seed_w=RandomSeedW,
                                          error_type_w=SLOPE_ERROR,
                                          rms_w=RMSW,
                                          correlation_length_w=30.0,
                                          power_law_exponent_beta_w=1.5,
                                          combination=combination)

        tmp1 = slopes(z.T, x, y, return_only_rms=1)
        print("  target SLOPE error in WIDTH:  %g rad" % (RMSW))
        print("  target SLOPE error in LENGTH: %g rad" % (RMS))

        print("  obtained HEIGHT error (in LENGTH and WIDTH): %g" % (z.std()))
        print("  obtained SLOPE error in WIDTH: %g" % (tmp1[0]))
        print("  obtained SLOPE error in LENGTH: %g" % (tmp1[1]))

        print("  shape x,y,z:", x.shape, y.shape, z.shape)

        # the LENGTH direction must match!!
        assert numpy.abs(RMS - tmp1[1]) < 0.01 * numpy.abs(RMS)

        if do_plot:
            from srxraylib.plot.gol import plot_surface
            plot_surface(z.T * 1e7,
                         x,
                         y,
                         xtitle="X [cm]",
                         ytitle="Y [cm",
                         ztitle="Z [nm]",
                         title="test_2d_normalize_to_slope_error")
    def calculate_heigth_profile(self, not_interactive_mode=False):
        try:
            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.check_fields()

            #### LENGTH

            if self.kind_of_profile_y == 2:
                combination = "E"

                if self.delimiter_y == 1:
                    profile_1D_y_x, profile_1D_y_y = numpy.loadtxt(self.heigth_profile_1D_file_name_y, delimiter='\t', unpack=True)
                else:
                    profile_1D_y_x, profile_1D_y_y = numpy.loadtxt(self.heigth_profile_1D_file_name_y, unpack=True)

                profile_1D_y_x *= self.conversion_factor_y_x * self.workspace_units_to_cm # to cm
                profile_1D_y_y *= self.conversion_factor_y_y * self.workspace_units_to_cm # to cm


                if self.modify_y == 2:
                    profile_1D_y_x_temp = profile_1D_y_x
                    profile_1D_y_y_temp = profile_1D_y_y

                    first_coord = profile_1D_y_x_temp[0]
                    second_coord  = profile_1D_y_x_temp[1]
                    last_coord = profile_1D_y_x_temp[-1]
                    step = numpy.abs(second_coord - first_coord)
                    length = numpy.abs(last_coord - first_coord)
                    n_points_old = len(profile_1D_y_x_temp)

                    if self.new_length > length:
                        difference = self.new_length - length

                        n_added_points = int(difference/step)
                        if difference % step == 0:
                            n_added_points += 1
                        if n_added_points % 2 != 0:
                            n_added_points += 1


                        profile_1D_y_x = numpy.arange(n_added_points + n_points_old) * step
                        profile_1D_y_y = numpy.ones(n_added_points + n_points_old) * self.filler_value * 1e-9 * self.si_to_user_units
                        profile_1D_y_y[int(n_added_points/2) : n_points_old + int(n_added_points/2)] = profile_1D_y_y_temp
                    elif self.new_length < length:
                        difference = length - self.new_length

                        n_removed_points = int(difference/step)
                        if difference % step == 0:
                            n_removed_points -= 1
                        if n_removed_points % 2 != 0:
                            n_removed_points -= 1

                        if n_removed_points >= 2:
                            profile_1D_y_x = profile_1D_y_x_temp[0 : (n_points_old - n_removed_points)]
                            profile_1D_y_y = profile_1D_y_y_temp[(int(n_removed_points/2) - 1) : (n_points_old - int(n_removed_points/2) - 1)]

                        else:
                            profile_1D_y_x = profile_1D_y_x_temp
                            profile_1D_y_y = profile_1D_y_y_temp
                    else:
                        profile_1D_y_x = profile_1D_y_x_temp
                        profile_1D_y_y = profile_1D_y_y_temp

                elif self.modify_y == 1:
                    profile_1D_y_x *= self.scale_factor_y

                if self.center_y:
                    first_coord = profile_1D_y_x[0]
                    last_coord = profile_1D_y_x[-1]
                    length = numpy.abs(last_coord - first_coord)

                    profile_1D_y_x_temp = numpy.linspace(-length/2, length/2, len(profile_1D_y_x))
                    profile_1D_y_x = profile_1D_y_x_temp


                if self.renormalize_y == 0:
                    rms_y = None
                else:
                    if self.error_type_y == profiles_simulation.FIGURE_ERROR:
                        rms_y = self.rms_y * 1e-7 # from nm to cm
                    else:
                        rms_y = self.rms_y * 1e-6 # from urad to rad
            else:
                if self.kind_of_profile_y == 0: combination = "F"
                else: combination = "G"

                profile_1D_y_x = None
                profile_1D_y_y = None

                if self.error_type_y == profiles_simulation.FIGURE_ERROR:
                    rms_y = self.rms_y * 1e-7 # from nm to cm
                else:
                    rms_y = self.rms_y * 1e-6 # from urad to rad

            #### WIDTH

            if self.kind_of_profile_x == 2:
                combination += "E"

                if self.delimiter_x == 1:
                    profile_1D_x_x, profile_1D_x_y = numpy.loadtxt(self.heigth_profile_1D_file_name_x, delimiter='\t', unpack=True)
                else:
                    profile_1D_x_x, profile_1D_x_y = numpy.loadtxt(self.heigth_profile_1D_file_name_x, unpack=True)

                profile_1D_x_x *= self.conversion_factor_x_x * self.workspace_units_to_cm
                profile_1D_x_y *= self.conversion_factor_x_y * self.workspace_units_to_cm

                if self.modify_x == 2:
                    profile_1D_x_x_temp = profile_1D_x_x
                    profile_1D_x_y_temp = profile_1D_x_y

                    first_coord = profile_1D_x_x_temp[0]
                    second_coord  = profile_1D_x_x_temp[1]
                    last_coord = profile_1D_x_x_temp[-1]
                    step = numpy.abs(second_coord - first_coord)
                    length = numpy.abs(last_coord - first_coord)
                    n_points_old = len(profile_1D_x_x_temp)

                    if self.new_length > length:
                        difference = self.new_length - length

                        n_added_points = int(difference/step)
                        if difference % step == 0:
                            n_added_points += 1
                        if n_added_points % 2 != 0:
                            n_added_points += 1


                        profile_1D_x_x = numpy.arange(n_added_points + n_points_old) * step
                        profile_1D_x_y = numpy.ones(n_added_points + n_points_old) * self.filler_value * 1e-9 * self.si_to_user_units
                        profile_1D_x_y[int(n_added_points/2) : n_points_old + int(n_added_points/2)] = profile_1D_x_y_temp
                    elif self.new_length < length:
                        difference = length - self.new_length

                        n_removed_points = int(difference/step)
                        if difference % step == 0:
                            n_removed_points -= 1
                        if n_removed_points % 2 != 0:
                            n_removed_points -= 1

                        if n_removed_points >= 2:
                            profile_1D_x_x = profile_1D_x_x_temp[0 : (n_points_old - n_removed_points)]
                            profile_1D_x_y = profile_1D_x_y_temp[(int(n_removed_points/2) - 1) : (n_points_old - int(n_removed_points/2) - 1)]

                        else:
                            profile_1D_x_x = profile_1D_x_x_temp
                            profile_1D_x_y = profile_1D_x_y_temp
                    else:
                        profile_1D_x_x = profile_1D_x_x_temp
                        profile_1D_x_y = profile_1D_x_y_temp

                elif self.modify_x == 1:
                    profile_1D_x_x *= self.scale_factor_x

                if self.center_x:
                    first_coord = profile_1D_x_x[0]
                    last_coord = profile_1D_x_x[-1]
                    length = numpy.abs(last_coord - first_coord)

                    profile_1D_x_x_temp = numpy.linspace(-length/2, length/2, len(profile_1D_x_x))
                    profile_1D_x_x = profile_1D_x_x_temp


                if self.renormalize_x == 0:
                    rms_x = None
                else:
                    if self.error_type_x == profiles_simulation.FIGURE_ERROR:
                        rms_x = self.rms_x * 1e-7 # from nm to cm
                    else:
                        rms_x = self.rms_x * 1e-6 # from urad to rad

            else:
                profile_1D_x_x = None
                profile_1D_x_y = None

                if self.kind_of_profile_x == 0: combination += "F"
                else: combination += "G"

                if self.error_type_x == profiles_simulation.FIGURE_ERROR:
                    rms_x = self.rms_x * 1e-7 # from nm to cm
                else:
                    rms_x = self.rms_x * 1e-6 # from urad to rad

            xx, yy, zz = profiles_simulation.simulate_profile_2D(combination = combination,
                                                                 mirror_length = self.dimension_y * self.workspace_units_to_cm, # to cm
                                                                 step_l = self.step_y * self.workspace_units_to_cm, # to cm
                                                                 random_seed_l = self.montecarlo_seed_y,
                                                                 error_type_l = self.error_type_y,
                                                                 rms_l = rms_y,
                                                                 power_law_exponent_beta_l = self.power_law_exponent_beta_y,
                                                                 correlation_length_l = self.correlation_length_y * self.workspace_units_to_cm, # to cm
                                                                 x_l = profile_1D_y_x,
                                                                 y_l = profile_1D_y_y,
                                                                 mirror_width = self.dimension_x * self.workspace_units_to_cm, # to cm
                                                                 step_w = self.step_x * self.workspace_units_to_cm,
                                                                 random_seed_w = self.montecarlo_seed_x,
                                                                 error_type_w = self.error_type_x,
                                                                 rms_w = rms_x,
                                                                 power_law_exponent_beta_w = self.power_law_exponent_beta_x,
                                                                 correlation_length_w = self.correlation_length_x * self.workspace_units_to_cm, # to cm
                                                                 x_w = profile_1D_x_x,
                                                                 y_w = profile_1D_x_y)

            self.xx = xx / self.workspace_units_to_cm # to user units
            self.yy = yy / self.workspace_units_to_cm # to user units
            self.zz = zz / self.workspace_units_to_cm # to user units

            self.axis.clear()

            x_to_plot, y_to_plot = numpy.meshgrid(self.xx, self.yy)
            z_to_plot = zz * 1e7

            self.axis.plot_surface(x_to_plot, y_to_plot, z_to_plot,
                                   rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True)

            sloperms = profiles_simulation.slopes(zz.T, xx, yy, return_only_rms=1)

            title = ' Slope error rms in X direction: %f $\mu$rad' % (sloperms[0]*1e6) + '\n' + \
                    ' Slope error rms in Y direction: %f $\mu$rad' % (sloperms[1]*1e6)

            self.axis.set_xlabel("X [" + self.workspace_units_label + "]")
            self.axis.set_ylabel("Y [" + self.workspace_units_label + "]")
            self.axis.set_zlabel("Z [nm]")
            self.axis.set_title(title)
            self.axis.mouse_init()

            if not not_interactive_mode:
                self.figure_canvas.draw()

                QMessageBox.information(self, "QMessageBox.information()",
                                        "Height Profile calculated: if the result is satisfactory,\nclick \'Generate Height Profile File\' to complete the operation ",
                                        QMessageBox.Ok)
        except Exception as exception:
            QMessageBox.critical(self, "Error",
                                 exception.args[0],
                                 QMessageBox.Ok)
Beispiel #5
0
def gen_figure_error(L=400e-3,
                     W=40e-3,
                     stepL=1e-3,
                     stepW=1e-3,
                     rmsL=1e-9,
                     rmsW=1e-9,
                     betaL=2.0,
                     betaW=2.0,
                     typeL='h',
                     typeW='h',
                     seedL=8787,
                     seedW=8454,
                     filename='',
                     plot=False,
                     print_out=False):

    from srxraylib.metrology import profiles_simulation

    # ==== Main Parameters ============================== #

    if (typeL == 'h'):
        typeL = 0  # (0) Normalize by Height RMS, (1) Normalize by Slope RMS
    elif (typeL == 's'):
        typeL = 1

    if (typeW == 'h'):
        typeW = 0  # (0) Normalize by Height RMS, (1) Normalize by Slope RMS
    elif (typeW == 's'):
        typeW = 1

    if (seedL == 0):
        fct = 1e4 if np.random.random() <= 0.5 else 1e3
        seedL = int(np.random.random() * fct)

    if (seedW == 0):
        fct = 1e4 if np.random.random() <= 0.5 else 1e3
        seedW = int(np.random.random() * fct)

    # ==== Creates 2D matrix ============================ #
    x, y, z = profiles_simulation.simulate_profile_2D(
        combination='FF',
        mirror_length=L,
        step_l=stepL,
        random_seed_l=seedL,
        error_type_l=typeL,
        rms_l=rmsL,
        power_law_exponent_beta_l=betaL,
        mirror_width=W,
        step_w=stepW,
        random_seed_w=seedW,
        error_type_w=typeW,
        rms_w=rmsW,
        power_law_exponent_beta_w=betaW)

    # ==== Formats matrix to the required by function === #
    mtx_fmt = np.zeros((len(x) + 1, len(y) + 1))
    mtx_fmt[0, 1:] = y
    mtx_fmt[1:, 0] = x
    mtx_fmt[1:, 1:] = np.transpose(z)

    if (print_out):
        print(filename)
        print('RMS = {0:.3f} nm'.format(np.std(z[:, 0] * 1e9)))
        print('PV = {0:.3f} nm\n'.format(
            np.max(z[:, 0] * 1e9) - np.min(z[:, 0] * 1e9)))

    # # ==== Writes files for shadow input ================ #
    if (filename != ''):
        write_shadow_height_error(mtx_fmt, filename, 1e3, ' ')  # [mm]

    # # ==== Preview Plots ================================ #
    if (plot):

        plt.figure(figsize=(6, 1))
        plt.pcolormesh(y, x, np.transpose(z))
        plt.autoscale(enable=True, tight=True)

        plt.figure()
        plt.plot(y, z[:, 0] * 1e9)
        plt.xlabel('L')
        plt.ylabel('height error')

        plt.show()

    return mtx_fmt