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
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
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,
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()