예제 #1
0
def apply_fresnel_zone_plate(input_beam, type_of_zp, diameter, delta_rn,
                             image_position, substrate_material,
                             substrate_thickness, zone_plate_material,
                             zone_plate_thickness):

    max_zones_number = int(diameter * 1000 / (4 * delta_rn))

    print("MZN", max_zones_number)

    focused_beam = input_beam.duplicate(history=False)

    if type_of_zp == PHASE_ZP:
        substrate_weight_factor = get_material_weight_factor(
            focused_beam, substrate_material, substrate_thickness)

        focused_beam._beam.rays[:,
                                6] = focused_beam._beam.rays[:,
                                                             6] * substrate_weight_factor[:]
        focused_beam._beam.rays[:,
                                7] = focused_beam._beam.rays[:,
                                                             7] * substrate_weight_factor[:]
        focused_beam._beam.rays[:,
                                8] = focused_beam._beam.rays[:,
                                                             8] * substrate_weight_factor[:]
        focused_beam._beam.rays[:,
                                15] = focused_beam._beam.rays[:,
                                                              15] * substrate_weight_factor[:]
        focused_beam._beam.rays[:,
                                16] = focused_beam._beam.rays[:,
                                                              16] * substrate_weight_factor[:]
        focused_beam._beam.rays[:,
                                17] = focused_beam._beam.rays[:,
                                                              17] * substrate_weight_factor[:]

    good_zones = []
    dark_zones = []
    r_zone_i_previous = 0.0
    for i in range(1, max_zones_number + 1):
        r_zone_i = numpy.sqrt(i * diameter * 1000 * delta_rn) * 1e-7
        if i % 2 == 0: good_zones.append([r_zone_i_previous, r_zone_i])
        else: dark_zones.append([r_zone_i_previous, r_zone_i])
        r_zone_i_previous = r_zone_i

    x = input_beam._beam.rays[:, 0]
    z = input_beam._beam.rays[:, 2]
    r = numpy.sqrt(x**2 + z**2)

    focused_beam._beam.rays[:, 9] = -100

    for zone in good_zones:
        t = numpy.where(numpy.logical_and(r >= zone[0], r <= zone[1]))

        intercepted_rays = focused_beam._beam.rays[t]

        # (see formulas in A.G. Michette, "X-ray science and technology"
        #  Institute of Physics Publishing (1993))

        x_int = intercepted_rays[:, 0]
        z_int = intercepted_rays[:, 2]
        xp_int = intercepted_rays[:, 3]
        zp_int = intercepted_rays[:, 5]
        k_mod_int = intercepted_rays[:, 10]

        r_int = numpy.sqrt(x_int**2 + z_int**2)

        k_x_int = k_mod_int * xp_int
        k_z_int = k_mod_int * zp_int
        d = zone[1] - zone[0]

        # computing G (the "grating" wavevector in Angstrom^-1)
        gx = -numpy.pi / d * (x_int / r_int)
        gz = -numpy.pi / d * (z_int / r_int)

        k_x_out = k_x_int + gx
        k_z_out = k_z_int + gz
        xp_out = k_x_out / k_mod_int
        zp_out = k_z_out / k_mod_int

        intercepted_rays[:, 3] = xp_out  # XP
        intercepted_rays[:, 5] = zp_out  # ZP
        intercepted_rays[:, 9] = 1

        focused_beam._beam.rays[t, 3] = intercepted_rays[:, 3]
        focused_beam._beam.rays[t, 4] = intercepted_rays[:, 4]
        focused_beam._beam.rays[t, 5] = intercepted_rays[:, 5]
        focused_beam._beam.rays[t, 9] = intercepted_rays[:, 9]

    if type_of_zp == PHASE_ZP:
        for zone in dark_zones:
            t = numpy.where(numpy.logical_and(r >= zone[0], r <= zone[1]))

            intercepted_rays = focused_beam._beam.rays[t]

            # (see formulas in A.G. Michette, "X-ray science and technology"
            #  Institute of Physics Publishing (1993))

            x_int = intercepted_rays[:, 0]
            z_int = intercepted_rays[:, 2]
            xp_int = intercepted_rays[:, 3]
            zp_int = intercepted_rays[:, 5]
            k_mod_int = intercepted_rays[:, 10]

            r_int = numpy.sqrt(x_int**2 + z_int**2)

            k_x_int = k_mod_int * xp_int
            k_z_int = k_mod_int * zp_int
            d = zone[1] - zone[0]

            # computing G (the "grating" wavevector in Angstrom^-1)
            gx = -numpy.pi / d * (x_int / r_int)
            gz = -numpy.pi / d * (z_int / r_int)

            k_x_out = k_x_int + gx
            k_z_out = k_z_int + gz
            xp_out = k_x_out / k_mod_int
            zp_out = k_z_out / k_mod_int

            intercepted_rays[:, 3] = xp_out  # XP
            intercepted_rays[:, 5] = zp_out  # ZP
            intercepted_rays[:, 9] = 1

            focused_beam._beam.rays[t, 3] = intercepted_rays[:, 3]
            focused_beam._beam.rays[t, 4] = intercepted_rays[:, 4]
            focused_beam._beam.rays[t, 5] = intercepted_rays[:, 5]
            focused_beam._beam.rays[t, 9] = intercepted_rays[:, 9]

    go = numpy.where(focused_beam._beam.rays[:, 9] == 1)
    lo = numpy.where(focused_beam._beam.rays[:, 9] != 1)

    intensity_go = numpy.sum(focused_beam._beam.rays[go, 6] ** 2 + focused_beam._beam.rays[go, 7] ** 2 + focused_beam._beam.rays[go, 8] ** 2 + \
                             focused_beam._beam.rays[go, 15] ** 2 + focused_beam._beam.rays[go, 16] ** 2 + focused_beam._beam.rays[go, 17] ** 2)

    intensity_lo = numpy.sum(focused_beam._beam.rays[lo, 6] ** 2 + focused_beam._beam.rays[lo, 7] ** 2 + focused_beam._beam.rays[lo, 8] ** 2 + \
                             focused_beam._beam.rays[lo, 15] ** 2 + focused_beam._beam.rays[lo, 16] ** 2 + focused_beam._beam.rays[lo, 17] ** 2)

    if type_of_zp == PHASE_ZP:
        wavelength = ShadowPhysics.getWavelengthFromShadowK(
            focused_beam._beam.rays[go, 10]) * 1e-8  #cm
        delta, beta = get_delta_beta(focused_beam._beam.rays[go],
                                     zone_plate_material)

        phi = 2 * numpy.pi * (zone_plate_thickness * 1e-7) * delta / wavelength
        r = beta / delta

        efficiency_zp = ((1 + numpy.exp(-2 * r * phi) -
                          (2 * numpy.exp(-r * phi) * numpy.cos(phi))) /
                         numpy.pi)**2

        efficiency_weight_factor = numpy.sqrt(efficiency_zp)
    elif type_of_zp == AMPLITUDE_ZP:
        efficiency_zp = numpy.ones(len(
            focused_beam._beam.rays[go])) / (numpy.pi**2)
        efficiency_weight_factor = numpy.sqrt(
            efficiency_zp * (1 + (intensity_lo / intensity_go)))

    print("EFF", efficiency_weight_factor**2,
          numpy.max(efficiency_weight_factor**2),
          numpy.min(efficiency_weight_factor**2))

    focused_beam._beam.rays[
        go, 6] = focused_beam._beam.rays[go, 6] * efficiency_weight_factor[:]
    focused_beam._beam.rays[
        go, 7] = focused_beam._beam.rays[go, 7] * efficiency_weight_factor[:]
    focused_beam._beam.rays[
        go, 8] = focused_beam._beam.rays[go, 8] * efficiency_weight_factor[:]
    focused_beam._beam.rays[
        go, 15] = focused_beam._beam.rays[go, 15] * efficiency_weight_factor[:]
    focused_beam._beam.rays[
        go, 16] = focused_beam._beam.rays[go, 16] * efficiency_weight_factor[:]
    focused_beam._beam.rays[
        go, 17] = focused_beam._beam.rays[go, 17] * efficiency_weight_factor[:]

    return focused_beam
예제 #2
0
    def apply_fresnel_zone_plate(cls, 
                                 zone_plate_beam,
                                 type_of_zp, 
                                 diameter, 
                                 delta_rn,                              
                                 substrate_material, 
                                 substrate_thickness,
                                 zone_plate_material,
                                 zone_plate_thickness,
                                 source_distance,
                                 workspace_units_to_m):
        
        max_zones_number = int(diameter*1000/(4*delta_rn))

        focused_beam = zone_plate_beam.duplicate(history=True)

        go = numpy.where(focused_beam._beam.rays[:, 9] == GOOD)

        if type_of_zp == PHASE_ZP: 
            substrate_weight_factor = ZonePlate.get_material_weight_factor(focused_beam._beam.rays[go], substrate_material, substrate_thickness)
        
            focused_beam._beam.rays[go, 6] = focused_beam._beam.rays[go, 6]*substrate_weight_factor[:]
            focused_beam._beam.rays[go, 7] = focused_beam._beam.rays[go, 7]*substrate_weight_factor[:]
            focused_beam._beam.rays[go, 8] = focused_beam._beam.rays[go, 8]*substrate_weight_factor[:]
            focused_beam._beam.rays[go, 15] = focused_beam._beam.rays[go, 15]*substrate_weight_factor[:]
            focused_beam._beam.rays[go, 16] = focused_beam._beam.rays[go, 16]*substrate_weight_factor[:]
            focused_beam._beam.rays[go, 17] = focused_beam._beam.rays[go, 17]*substrate_weight_factor[:]
        
        clear_zones = []
        dark_zones = []
        r_zone_i_previous = 0.0
        for i in range(1, max_zones_number+1):
            r_zone_i = numpy.sqrt(i*diameter*1e-6*delta_rn*1e-9)/workspace_units_to_m # to workspace unit
            if i % 2 == 0: clear_zones.append([r_zone_i_previous, r_zone_i])
            else: dark_zones.append([r_zone_i_previous, r_zone_i])
            r_zone_i_previous = r_zone_i
               
        focused_beam._beam.rays[go, 9] = LOST_ZP
        
        ZonePlate.analyze_zone(clear_zones, focused_beam, source_distance, workspace_units_to_m)
        if type_of_zp == PHASE_ZP: ZonePlate.analyze_zone(dark_zones, focused_beam, source_distance, workspace_units_to_m)
    
        go_2 = numpy.where(focused_beam._beam.rays[:, 9] == GOOD_ZP)

        intensity_go_2 = numpy.sum(focused_beam._beam.rays[go_2, 6] ** 2 + focused_beam._beam.rays[go_2, 7] ** 2 + focused_beam._beam.rays[go_2, 8] ** 2 + \
                                   focused_beam._beam.rays[go_2, 15] ** 2 + focused_beam._beam.rays[go_2, 16] ** 2 + focused_beam._beam.rays[go_2, 17] ** 2)

        if type_of_zp == PHASE_ZP:
            wavelength = ShadowPhysics.getWavelengthFromShadowK(focused_beam._beam.rays[go_2, 10])*1e-1 # nm
            delta, beta = ZonePlate.get_delta_beta(focused_beam._beam.rays[go_2], zone_plate_material)
            
            phi = 2*numpy.pi*zone_plate_thickness*delta/wavelength
            rho = beta/delta
               
            efficiency_zp = (1/(numpy.pi**2))*(1 + numpy.exp(-2*rho*phi) - (2*numpy.exp(-rho*phi)*numpy.cos(phi)))
            efficiency_weight_factor = numpy.sqrt(efficiency_zp)

        elif type_of_zp == AMPLITUDE_ZP:
            lo_2 = numpy.where(focused_beam._beam.rays[:, 9] == LOST_ZP)

            intensity_lo_2 = numpy.sum(focused_beam._beam.rays[lo_2, 6] ** 2 + focused_beam._beam.rays[lo_2, 7] ** 2 + focused_beam._beam.rays[lo_2, 8] ** 2 + \
                                       focused_beam._beam.rays[lo_2, 15] ** 2 + focused_beam._beam.rays[lo_2, 16] ** 2 + focused_beam._beam.rays[lo_2, 17] ** 2)

            efficiency_zp = numpy.ones(len(focused_beam._beam.rays[go_2]))/(numpy.pi**2)
            efficiency_weight_factor = numpy.sqrt(efficiency_zp*(1 + (intensity_lo_2/intensity_go_2)))

        focused_beam._beam.rays[go_2, 6]  = focused_beam._beam.rays[go_2, 6]*efficiency_weight_factor[:]
        focused_beam._beam.rays[go_2, 7]  = focused_beam._beam.rays[go_2, 7]*efficiency_weight_factor[:]
        focused_beam._beam.rays[go_2, 8]  = focused_beam._beam.rays[go_2, 8]*efficiency_weight_factor[:]
        focused_beam._beam.rays[go_2, 15] = focused_beam._beam.rays[go_2, 15]*efficiency_weight_factor[:]
        focused_beam._beam.rays[go_2, 16] = focused_beam._beam.rays[go_2, 16]*efficiency_weight_factor[:]
        focused_beam._beam.rays[go_2, 17] = focused_beam._beam.rays[go_2, 17]*efficiency_weight_factor[:]
        focused_beam._beam.rays[go_2, 9] = GOOD

        return focused_beam, max_zones_number
예제 #3
0
empty_element._oe.set_screens(n_screen, i_screen, i_abs, sl_dis, i_slit,
                              i_stop, k_slit, thick, file_abs, rx_slit,
                              rz_slit, cx_slit, cz_slit, file_scr_ext)

zone_plate_beam = ShadowBeam.traceFromOE(input_beam,
                                         empty_element,
                                         history=False)

go = numpy.where(zone_plate_beam._beam.rays[:, 9] == 1)

go_input_beam = ShadowBeam()
go_input_beam._beam.rays = copy.deepcopy(zone_plate_beam._beam.rays[go])

###################################################

avg_wavelength = ShadowPhysics.getWavelengthFromShadowK(
    numpy.average(go_input_beam._beam.rays[:, 10])) * 1e-1  #ANGSTROM->nm

print("W", avg_wavelength, "nm")

focal_distance = (delta_rn * (1000 * diameter) / avg_wavelength) * 1e-7  # cm
image_position = focal_distance * source_distance / (source_distance -
                                                     focal_distance)
magnification = numpy.abs(image_position / source_distance)

print("FD", focal_distance, "cm")
print("Q", image_position, "cm")
print("M", magnification)

out_beam = apply_fresnel_zone_plate(go_input_beam, type_of_zp, diameter,
                                    delta_rn, image_position,
                                    substrate_material, substrate_thickness,
예제 #4
0
    def traceOpticalElement(self):
        try:
            self.setStatusMessage("")
            self.progressBarInit()

            if ShadowCongruence.checkEmptyBeam(self.input_beam):
                if ShadowCongruence.checkGoodBeam(self.input_beam):
                    self.checkFields()

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

                    if self.trace_shadow:
                        grabber = TTYGrabber()
                        grabber.start()

                    ###########################################
                    # TODO: TO BE ADDED JUST IN CASE OF BROKEN
                    #       ENVIRONMENT: MUST BE FOUND A PROPER WAY
                    #       TO TEST SHADOW
                    self.fixWeirdShadowBug()
                    ###########################################

                    self.progressBarSet(10)

                    if self.source_distance_flag == 0:
                        self.source_distance = self.source_plane_distance

                    zone_plate_beam = self.get_zone_plate_beam()

                    go = numpy.where(zone_plate_beam._beam.rays[:, 9] == GOOD)

                    self.avg_wavelength = ShadowPhysics.getWavelengthFromShadowK(numpy.average(zone_plate_beam._beam.rays[go, 10]))*1e-1 #ANGSTROM->nm

                    self.focal_distance = (self.delta_rn*(self.diameter*1000)/self.avg_wavelength)* (1e-9/self.workspace_units_to_m)       # WS Units
                    self.image_position = self.focal_distance*self.source_distance/(self.source_distance-self.focal_distance)              # WS Units
                    self.magnification = numpy.abs(self.image_position/self.source_distance)

                    self.avg_wavelength = numpy.round(self.avg_wavelength, 6)      # nm
                    self.focal_distance = numpy.round(self.focal_distance, 6)
                    self.image_position = numpy.round(self.image_position, 6)
                    self.magnification = numpy.round(self.magnification, 6)

                    if self.automatically_set_image_plane == 1:
                        self.image_plane_distance = self.image_position

                    self.progressBarSet(30)

                    if self.type_of_zp == PHASE_ZP:
                        efficiency, max_efficiency, thickness_max_efficiency = ZonePlate.calculate_efficiency(self.avg_wavelength, # Angstrom
                                                                                                              self.zone_plate_material,
                                                                                                              self.zone_plate_thickness)

                        self.efficiency = numpy.round(100*efficiency, 3)
                        self.max_efficiency = numpy.round(100*max_efficiency, 3)
                        self.thickness_max_efficiency =  thickness_max_efficiency
                    else:
                        self.efficiency = numpy.round(100/(numpy.pi**2), 3)
                        self.max_efficiency = numpy.nan
                        self.thickness_max_efficiency =  numpy.nan

                    focused_beam, \
                    self.number_of_zones = ZonePlate.apply_fresnel_zone_plate(zone_plate_beam,  # WS Units
                                                                              self.type_of_zp,
                                                                              self.diameter,  # micron
                                                                              self.delta_rn, # nm
                                                                              self.substrate_material,
                                                                              self.substrate_thickness,
                                                                              self.zone_plate_material,
                                                                              self.zone_plate_thickness,
                                                                              self.source_distance, # WS Units
                                                                              self.workspace_units_to_m)

                    self.progressBarSet(60)

                    beam_out = self.get_output_beam(focused_beam)

                    self.progressBarSet(80)

                    if self.trace_shadow:
                        grabber.stop()

                        for row in grabber.ttyData:
                           self.writeStdOut(row)

                    self.setStatusMessage("Plotting Results")

                    self.plot_results(beam_out)
                    self.plot_efficiency()

                    self.setStatusMessage("")

                    beam_out.setScanningData(self.input_beam.scanned_variable_data)

                    self.send("Beam", beam_out)
                    self.send("Trigger", TriggerIn(new_object=True))
                else:
                    if self.not_interactive: self.sendEmptyBeam()
                    else: raise Exception("Input Beam with no good rays")
            else:
                if self.not_interactive: self.sendEmptyBeam()
                else: raise Exception("Empty Input Beam")

        except Exception as exception:
            QMessageBox.critical(self, "Error",
                                       str(exception), QMessageBox.Ok)

            if self.IS_DEVELOP: raise exception

        self.progressBarFinished()