class UndulatorFull(ow_source.Source, WidgetDecorator): name = "Full Undulator" description = "Shadow Source: Full Undulator" icon = "icons/undulator.png" priority = 4 K = Setting(0.25) period_length = Setting(0.032) periods_number = Setting(50) energy_in_GeV = Setting(6.04) current = Setting(0.2) use_emittances_combo = Setting(1) sigma_x = Setting(400e-6) sigma_z = Setting(10e-6) sigma_divergence_x = Setting(10e-06) sigma_divergence_z = Setting(4e-06) number_of_rays = Setting(5000) seed = Setting(6775431) photon_energy = Setting(10500.0) harmonic = Setting(1.0) set_at_resonance = Setting(0) delta_e = Setting(1000.0) maxangle_urad = Setting(15) # advanced setting ng_t = Setting(51) ng_p = Setting(11) ng_j = Setting(20) ng_e = Setting(11) code_undul_phot = Setting(0) # 0=internal 1=pySRU 2=SRW flag_size = Setting(1) # 0=Point 1=Gaussian 2=backpropagate divergences coherent = Setting(0) # 0=No 1=Yes # aux file_to_write_out = 0 plot_aux_graph = 1 sourceundulator = None add_power = False power_step = None inputs = [("Trigger", TriggerOut, "sendNewBeam2")] WidgetDecorator.append_syned_input_data(inputs) def __init__(self): super().__init__() self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH) tabs_setting = oasysgui.tabWidget(self.controlArea) tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT) tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH - 5) tab_bas = oasysgui.createTabPage(tabs_setting, "Basic Setting") tab_sou = oasysgui.createTabPage(tabs_setting, "Source Setting") tab_grid = oasysgui.createTabPage(tabs_setting, "Advanced Settings") left_box_1 = oasysgui.widgetBox(tab_bas, "Monte Carlo", addSpace=True, orientation="vertical") oasysgui.lineEdit(left_box_1, self, "number_of_rays", "Number of rays", tooltip="Number of Rays", labelWidth=250, valueType=int, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "seed", "Seed", tooltip="Seed (0=clock)", labelWidth=250, valueType=int, orientation="horizontal") left_box_2 = oasysgui.widgetBox(tab_sou, "Machine Parameters", addSpace=True, orientation="vertical") oasysgui.lineEdit(left_box_2, self, "energy_in_GeV", "Energy [GeV]", labelWidth=250, tooltip="Energy [GeV]", valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2, self, "current", "Current [A]", labelWidth=250, tooltip="Current [A]", valueType=float, orientation="horizontal") gui.comboBox(left_box_2, self, "use_emittances_combo", label="Use Emittances?", items=["No", "Yes"], callback=self.set_UseEmittances, labelWidth=260, orientation="horizontal") self.box_use_emittances = oasysgui.widgetBox(left_box_2, "", addSpace=False, orientation="vertical") self.le_sigma_x = oasysgui.lineEdit(self.box_use_emittances, self, "sigma_x", "Size RMS H [m]", labelWidth=250, tooltip="Size RMS H [m]", valueType=float, orientation="horizontal") self.le_sigma_z = oasysgui.lineEdit(self.box_use_emittances, self, "sigma_z", "Size RMS V [m]", labelWidth=250, tooltip="Size RMS V [m]", valueType=float, orientation="horizontal") oasysgui.lineEdit(self.box_use_emittances, self, "sigma_divergence_x", "Divergence RMS H [rad]", labelWidth=250, tooltip="Divergence RMS H [rad]", valueType=float, orientation="horizontal") oasysgui.lineEdit(self.box_use_emittances, self, "sigma_divergence_z", "Divergence RMS V [rad]", labelWidth=250, tooltip="Divergence RMS V [rad]", valueType=float, orientation="horizontal") self.set_UseEmittances() left_box_3 = oasysgui.widgetBox(tab_sou, "Undulator Parameters", addSpace=True, orientation="vertical") oasysgui.lineEdit(left_box_3, self, "K", "K", labelWidth=250, tooltip="Undulator Deflection Parameter K", valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_3, self, "period_length", "period Length [m]", labelWidth=250, tooltip="Undulator Period Length [m]", valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_3, self, "periods_number", "Number of periods", labelWidth=250, tooltip="Number of periods", valueType=int, orientation="horizontal") left_box_4 = oasysgui.widgetBox(tab_sou, "Photon energy", addSpace=True, orientation="vertical") # gui.comboBox(left_box_4, self, "set_at_resonance", label="Set photon energy", addSpace=False, items=['User defined', 'Set to resonance'], valueType=int, orientation="horizontal", labelWidth=250, callback=self.set_UseResonance) self.box_photon_energy = gui.widgetBox(left_box_4) oasysgui.lineEdit(self.box_photon_energy, self, "photon_energy", "Photon energy [eV] (center)", tooltip="Photon energy [eV]", labelWidth=250, valueType=float, orientation="horizontal") self.box_harmonic = gui.widgetBox(left_box_4) oasysgui.lineEdit(self.box_harmonic, self, "harmonic", "Photon energy [N x Resonance]; N: ", tooltip="Photon energy [N x Resonance]; N: ", labelWidth=250, valueType=float, orientation="horizontal") self.box_maxangle_urad = gui.widgetBox(left_box_4) oasysgui.lineEdit( self.box_maxangle_urad, self, "maxangle_urad", "Max elevation angle for radiation [urad]", tooltip="Max elevation angle for radiation theta [urad]", labelWidth=250, valueType=float, orientation="horizontal") self.set_UseResonance() #self.box_photon_energy.setEnabled(False) oasysgui.lineEdit( left_box_4, self, "delta_e", "Photon energy width [eV] (0=monochr.)", tooltip="Photon energy interval [eV] (0=monochromatic)", labelWidth=250, valueType=float, orientation="horizontal") adv_other_box = oasysgui.widgetBox(tab_bas, "Optional file output", addSpace=False, orientation="vertical") gui.comboBox(adv_other_box, self, "file_to_write_out", label="Files to write out", labelWidth=120, items=["None", "begin.dat", "begin.dat+radiation.h5"], sendSelectedValue=False, orientation="horizontal") # advanced left_box_5 = oasysgui.widgetBox(tab_grid, "Advanced Settings", addSpace=True, orientation="vertical") # ng_t = 51 # ng_p = 11 # ng_j = 20 # ng_e = 11 # code_undul_phot = 0 # flag_size = 0 oasysgui.lineEdit(left_box_5, self, "ng_e", "Points in Photon energy (if polychromatic)", tooltip="Points in Photon energy", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(left_box_5, self, "ng_t", "Points in theta [elevation]", tooltip="Points in theta [elevation]", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(left_box_5, self, "ng_p", "Points in phi [azimuthal]", tooltip="Points in phi [azimuthal]", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(left_box_5, self, "ng_j", "Points in electron trajectory", tooltip="Points in electron trajectory", labelWidth=260, valueType=int, orientation="horizontal") gui.comboBox(left_box_5, self, "code_undul_phot", label="Calculation method", labelWidth=120, items=["internal", "pySRU", "SRW"], sendSelectedValue=False, orientation="horizontal") gui.comboBox(left_box_5, self, "flag_size", label="Radiation Size", labelWidth=120, items=["point", "Gaussian", "Far field backpropagated"], sendSelectedValue=False, orientation="horizontal") gui.comboBox(left_box_5, self, "coherent", label="Coherent beam", labelWidth=120, items=["No", "Yes"], sendSelectedValue=False, orientation="horizontal") gui.rubber(self.controlArea) undulator_plot_tab = oasysgui.widgetBox(self.main_tabs, addToLayout=0, margin=4) self.main_tabs.insertTab(1, undulator_plot_tab, "Undulator Plots") view_box = oasysgui.widgetBox(undulator_plot_tab, "Plotting Style", addSpace=False, orientation="horizontal") view_box_1 = oasysgui.widgetBox(view_box, "", addSpace=False, orientation="vertical", width=350) self.undulator_view_type_combo = gui.comboBox( view_box_1, self, "plot_aux_graph", label="Plot Graphs?", labelWidth=220, items=["No", "Yes"], callback=self.set_PlotAuxGraphs, sendSelectedValue=False, orientation="horizontal") self.undulator_tab = [] self.undulator_tabs = oasysgui.tabWidget(undulator_plot_tab) self.initializeUndulatorTabs() gui.rubber(self.mainArea) def sendNewBeam2(self, trigger): self.power_step = None self.add_power = False try: if trigger and trigger.new_object == True: if trigger.has_additional_parameter("seed_increment"): self.seed += trigger.get_additional_parameter( "seed_increment") if trigger.has_additional_parameter( "energy_value") and trigger.has_additional_parameter( "energy_step"): self.set_at_resonance = 0 self.photon_energy = trigger.get_additional_parameter( "energy_value") self.delta_e = trigger.get_additional_parameter( "energy_step") self.power_step = trigger.get_additional_parameter( "power_step") self.set_UseResonance() self.add_power = True self.runShadowSource() except: pass def set_UseEmittances(self): self.box_use_emittances.setVisible(self.use_emittances_combo == 1) def set_UseResonance(self): self.box_photon_energy.setVisible(self.set_at_resonance == 0) self.box_maxangle_urad.setVisible(self.set_at_resonance == 0) self.box_harmonic.setVisible(self.set_at_resonance > 0) def set_PlotAuxGraphs(self): # self.progressBarInit() self.initializeUndulatorTabs( ) # update number of tabs if monochromatic/polychromatic if self.sourceundulator is not None: try: self.initializeUndulatorTabs() self.plot_undulator_results() except Exception as exception: QtWidgets.QMessageBox.critical(self, "Error", str(exception), QtWidgets.QMessageBox.Ok) # self.progressBarFinished() def plot_undulator_results(self): if self.plot_aux_graph == 1: try: radiation, photon_energy, theta, phi = self.sourceundulator.get_radiation_polar( ) tabs_canvas_index = 0 plot_canvas_index = 0 polarization = self.sourceundulator.get_result_polarization() if self.delta_e == 0.0: self.plot_data2D(radiation[0], 1e6 * theta, phi, tabs_canvas_index, plot_canvas_index, title="radiation (photons/s/eV/rad2)", xtitle="theta [urad]", ytitle="phi [rad]") tabs_canvas_index += 1 self.plot_data2D(polarization[0], 1e6 * theta, phi, tabs_canvas_index, plot_canvas_index, title="polarization |Es|/(|Es|+|Ep|)", xtitle="theta [urad]", ytitle="phi [rad]") tabs_canvas_index += 1 radiation_interpolated, photon_energy, vx, vz = self.sourceundulator.get_radiation_interpolated_cartesian( ) self.plot_data2D(radiation_interpolated[0], 1e6 * vx, 1e6 * vz, tabs_canvas_index, plot_canvas_index, title="radiation", xtitle="vx [urad]", ytitle="vz [rad]") tabs_canvas_index += 1 x, y = self.sourceundulator.get_photon_size_distribution() self.plot_data1D(x * 1e6, y, tabs_canvas_index, plot_canvas_index, title="Photon emission size distribution", xtitle="Distance [um]", ytitle="Intensity [arbitrary units]") else: self.plot_data3D( radiation, photon_energy, 1e6 * theta, phi, tabs_canvas_index, plot_canvas_index, title="radiation (photons/s/eV/rad2)", xtitle="theta [urad]", ytitle="phi [rad]", callback_for_title=self.get_title_for_stack_view_flux) tabs_canvas_index += 1 self.plot_data3D(polarization, photon_energy, 1e6 * theta, phi, tabs_canvas_index, plot_canvas_index, title="polarization |Es|/(|Es|+|Ep|)", xtitle="theta [urad]", ytitle="phi [rad]", callback_for_title=self. get_title_for_stack_view_polarization) tabs_canvas_index += 1 radiation_interpolated, photon_energy, vx, vz = self.sourceundulator.get_radiation_interpolated_cartesian( ) self.plot_data3D( radiation_interpolated, photon_energy, 1e6 * vx, 1e6 * vz, tabs_canvas_index, plot_canvas_index, title="radiation", xtitle="vx [urad]", ytitle="vz [rad]", callback_for_title=self.get_title_for_stack_view_flux) tabs_canvas_index += 1 x, y = self.sourceundulator.get_photon_size_distribution() self.plot_data1D(x * 1e6, y, tabs_canvas_index, plot_canvas_index, title="Photon emission size distribution", xtitle="Distance [um]", ytitle="Intensity [arbitrary units]") # # if polychromatic, plot power density # intens_xy, vx, vz = self.sourceundulator.get_power_density_interpolated_cartesian( ) tabs_canvas_index += 1 self.plot_data2D(1e-6 * intens_xy, 1e6 * vx, 1e6 * vz, tabs_canvas_index, plot_canvas_index, title="power density W/mrad2", xtitle="vx [urad]", ytitle="vz [rad]") # # if polychromatic, plot flux(energy) # flux, spectral_power, photon_energy = self.sourceundulator.get_flux_and_spectral_power( ) tabs_canvas_index += 1 self.plot_data1D(photon_energy, flux, tabs_canvas_index, plot_canvas_index, title="Flux", xtitle="Photon Energy [eV]", ytitle="Flux [photons/s/0.1%bw]") tabs_canvas_index += 1 self.plot_data1D(photon_energy, spectral_power, tabs_canvas_index, plot_canvas_index, title="Spectral Power", xtitle="Photon Energy [eV]", ytitle="Spectral Power [W/eV]") print("\n\n") # print("Total power (integral [sum] of spectral power) [W]: ",spectral_power.sum()*(photon_energy[1]-photon_energy[0])) print( "Total power (integral [trapz] of spectral power) [W]: ", numpy.trapz(spectral_power, photon_energy)) print( "Total number of photons (integral [trapz] of flux): ", numpy.trapz(flux / (1e-3 * photon_energy), photon_energy)) print("\n\n") except Exception as exception: QtWidgets.QMessageBox.critical(self, "Error", str(exception), QtWidgets.QMessageBox.Ok) def get_title_for_stack_view_flux(self, idx): photon_energy = self.sourceundulator.get_result_photon_energy() return "Units: Photons/s/eV/rad2; Photon energy: %8.3f eV" % ( photon_energy[idx]) # # these are plottting routines hacked from xoppy code TODO: promote to higher level/superclass ? # def get_title_for_stack_view_polarization(self, idx): photon_energy = self.sourceundulator.get_result_photon_energy() return "|Es| / (|Es|+|Ep|); Photon energy: %8.3f eV" % ( photon_energy[idx]) def plot_data3D(self, data3D, dataE, dataX, dataY, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="", callback_for_title=(lambda idx: "")): for i in range(1 + self.undulator_tab[tabs_canvas_index].layout().count()): self.undulator_tab[tabs_canvas_index].layout().removeItem( self.undulator_tab[tabs_canvas_index].layout().itemAt(i)) ##self.tab[tabs_canvas_index].layout().removeItem(self.tab[tabs_canvas_index].layout().itemAt(0)) xmin = numpy.min(dataX) xmax = numpy.max(dataX) ymin = numpy.min(dataY) ymax = numpy.max(dataY) stepX = dataX[1] - dataX[0] stepY = dataY[1] - dataY[0] if len(dataE) > 1: stepE = dataE[1] - dataE[0] else: stepE = 1.0 if stepE == 0.0: stepE = 1.0 if stepX == 0.0: stepX = 1.0 if stepY == 0.0: stepY = 1.0 dim0_calib = (dataE[0], stepE) dim1_calib = (ymin, stepY) dim2_calib = (xmin, stepX) data_to_plot = numpy.swapaxes(data3D, 1, 2) colormap = { "name": "temperature", "normalization": "linear", "autoscale": True, "vmin": 0, "vmax": 0, "colors": 256 } self.und_plot_canvas[plot_canvas_index] = StackViewMainWindow() self.und_plot_canvas[plot_canvas_index].setGraphTitle(title) self.und_plot_canvas[plot_canvas_index].setLabels( ["Photon Energy [eV]", ytitle, xtitle]) self.und_plot_canvas[plot_canvas_index].setColormap(colormap=colormap) self.und_plot_canvas[plot_canvas_index].setStack( numpy.array(data_to_plot), calibrations=[dim0_calib, dim1_calib, dim2_calib]) self.und_plot_canvas[plot_canvas_index].setTitleCallback( callback_for_title) self.undulator_tab[tabs_canvas_index].layout().addWidget( self.und_plot_canvas[plot_canvas_index]) def plot_data2D(self, data2D, dataX, dataY, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle=""): for i in range(1 + self.undulator_tab[tabs_canvas_index].layout().count()): self.undulator_tab[tabs_canvas_index].layout().removeItem( self.undulator_tab[tabs_canvas_index].layout().itemAt(i)) origin = (dataX[0], dataY[0]) scale = (dataX[1] - dataX[0], dataY[1] - dataY[0]) data_to_plot = data2D.T colormap = { "name": "temperature", "normalization": "linear", "autoscale": True, "vmin": 0, "vmax": 0, "colors": 256 } self.und_plot_canvas[plot_canvas_index] = Plot2D() self.und_plot_canvas[plot_canvas_index].resetZoom() self.und_plot_canvas[plot_canvas_index].setXAxisAutoScale(True) self.und_plot_canvas[plot_canvas_index].setYAxisAutoScale(True) self.und_plot_canvas[plot_canvas_index].setGraphGrid(False) self.und_plot_canvas[plot_canvas_index].setKeepDataAspectRatio(True) self.und_plot_canvas[plot_canvas_index].yAxisInvertedAction.setVisible( False) self.und_plot_canvas[plot_canvas_index].setXAxisLogarithmic(False) self.und_plot_canvas[plot_canvas_index].setYAxisLogarithmic(False) self.und_plot_canvas[plot_canvas_index].getMaskAction().setVisible( False) self.und_plot_canvas[plot_canvas_index].getRoiAction().setVisible( False) self.und_plot_canvas[plot_canvas_index].getColormapAction().setVisible( False) self.und_plot_canvas[plot_canvas_index].setKeepDataAspectRatio(False) self.und_plot_canvas[plot_canvas_index].addImage( numpy.array(data_to_plot), legend="", scale=scale, origin=origin, colormap=colormap, replace=True) self.und_plot_canvas[plot_canvas_index].setActiveImage("") self.und_plot_canvas[plot_canvas_index].setGraphXLabel(xtitle) self.und_plot_canvas[plot_canvas_index].setGraphYLabel(ytitle) self.und_plot_canvas[plot_canvas_index].setGraphTitle(title) self.undulator_tab[tabs_canvas_index].layout().addWidget( self.und_plot_canvas[plot_canvas_index]) def plot_data1D(self, dataX, dataY, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle=""): self.undulator_tab[tabs_canvas_index].layout().removeItem( self.undulator_tab[tabs_canvas_index].layout().itemAt(0)) self.und_plot_canvas[plot_canvas_index] = oasysgui.plotWindow() self.und_plot_canvas[plot_canvas_index].addCurve( dataX, dataY, ) self.und_plot_canvas[plot_canvas_index].resetZoom() self.und_plot_canvas[plot_canvas_index].setXAxisAutoScale(True) self.und_plot_canvas[plot_canvas_index].setYAxisAutoScale(True) self.und_plot_canvas[plot_canvas_index].setGraphGrid(False) self.und_plot_canvas[plot_canvas_index].setXAxisLogarithmic(False) self.und_plot_canvas[plot_canvas_index].setYAxisLogarithmic(False) self.und_plot_canvas[plot_canvas_index].setGraphXLabel(xtitle) self.und_plot_canvas[plot_canvas_index].setGraphYLabel(ytitle) self.und_plot_canvas[plot_canvas_index].setGraphTitle(title) self.undulator_tab[tabs_canvas_index].layout().addWidget( self.und_plot_canvas[plot_canvas_index]) # # end plotting routines # def initializeUndulatorTabs(self): current_tab = self.undulator_tabs.currentIndex() size = len(self.undulator_tab) indexes = range(0, size) for index in indexes: self.undulator_tabs.removeTab(size - 1 - index) if self.delta_e == 0.0: self.undulator_tab = [ gui.createTabPage(self.undulator_tabs, "Radiation intensity (polar)"), gui.createTabPage(self.undulator_tabs, "Polarization (polar)"), gui.createTabPage( self.undulator_tabs, "Radiation intensity (cartesian - interpolated)"), gui.createTabPage(self.undulator_tabs, "Photon source size"), ] self.und_plot_canvas = [ None, None, None, None, ] else: self.undulator_tab = [ gui.createTabPage(self.undulator_tabs, "Radiation (polar)"), gui.createTabPage(self.undulator_tabs, "Polarization (polar)"), gui.createTabPage(self.undulator_tabs, "Radiation (interpolated)"), gui.createTabPage(self.undulator_tabs, "Photon source size"), gui.createTabPage(self.undulator_tabs, "Power Density (interpolated)"), gui.createTabPage(self.undulator_tabs, "Flux"), gui.createTabPage(self.undulator_tabs, "Spectral Power"), ] self.und_plot_canvas = [ None, None, None, None, None, None, None, ] for tab in self.undulator_tab: tab.setFixedHeight(self.IMAGE_HEIGHT) tab.setFixedWidth(self.IMAGE_WIDTH) # self.undulator_plot_canvas = [None, None, None] self.undulator_tabs.setCurrentIndex(current_tab) def runShadowSource(self): self.setStatusMessage("") self.progressBarInit() # this is to be able to start the widget out of Oasys try: tmp = self.workspace_units except: self.workspace_units = 'm' self.workspace_units_label = 'm' self.workspace_units_to_m = 1.0 self.workspace_units_to_cm = 1e2 self.workspace_units_to_mm = 1e3 self.checkFields() self.progressBarSet(10) self.setStatusMessage("Running SHADOW") sys.stdout = EmittingStream(textWritten=self.writeStdOut) if self.trace_shadow: grabber = TTYGrabber() grabber.start() self.progressBarSet(50) try: self.shadow_output.setText("") su = Undulator.initialize_as_vertical_undulator( K=self.K, period_length=self.period_length, periods_number=int(self.periods_number)) ebeam = ElectronBeam(energy_in_GeV=self.energy_in_GeV, energy_spread=0.0, current=self.current, number_of_bunches=1, moment_xx=(self.sigma_x)**2, moment_xxp=0.0, moment_xpxp=(self.sigma_divergence_x)**2, moment_yy=(self.sigma_z)**2, moment_yyp=0.0, moment_ypyp=(self.sigma_divergence_z)**2) print(ebeam.info()) codes = ["internal", "pySRU", "SRW"] selected_code = codes[self.code_undul_phot] self.sourceundulator = SourceUndulator( name="shadowOui-Full-Undulator", syned_electron_beam=ebeam, syned_undulator=su, flag_emittance=self.use_emittances_combo, flag_size=self.flag_size, emin=1000, # to be set later emax=1001, # to be set later ng_e=2, # to be set later maxangle=self.maxangle_urad * 1e-6, ng_t=self.ng_t, ng_p=self.ng_p, ng_j=self.ng_j, code_undul_phot=selected_code) if self.set_at_resonance == 0: if self.delta_e == 0: self.sourceundulator.set_energy_box( self.photon_energy, self.photon_energy, 1) else: self.sourceundulator.set_energy_box( self.photon_energy - 0.5 * self.delta_e, self.photon_energy + 0.5 * self.delta_e, self.ng_e) else: self.sourceundulator.set_energy_monochromatic_at_resonance( self.harmonic) if self.delta_e > 0.0: e0, e1, ne = self.sourceundulator.get_energy_box() self.sourceundulator.set_energy_box( e0 - 0.5 * self.delta_e, e0 + 0.5 * self.delta_e, self.ng_e) rays = self.sourceundulator.calculate_rays( user_unit_to_m=self.workspace_units_to_m, F_COHER=self.coherent, SEED=self.seed, NRAYS=self.number_of_rays) if self.plot_aux_graph: self.set_PlotAuxGraphs() print(self.sourceundulator.info()) shadow3_beam = Shadow3Beam(N=rays.shape[0]) shadow3_beam.rays = rays if self.file_to_write_out >= 1: shadow3_beam.write("begin.dat") print("File written to disk: begin.dat") if self.file_to_write_out >= 2: SourceUndulatorInputOutput.write_file_undul_phot_h5( self.sourceundulator.get_result_dictionary(), file_out="radiation.h5", mode="w", entry_name="radiation") beam_out = ShadowBeam(beam=shadow3_beam) beam_out.getOEHistory().append(ShadowOEHistoryItem()) if self.add_power: additional_parameters = {} pd, vx, vy = self.sourceundulator.get_power_density_interpolated_cartesian( ) total_power = self.power_step if self.power_step > 0 else pd.sum( ) * (vx[1] - vx[0]) * (vy[1] - vy[0]) additional_parameters["total_power"] = total_power additional_parameters["photon_energy_step"] = self.delta_e beam_out.setScanningData( ShadowBeam.ScanningData("photon_energy", self.photon_energy, "Energy for Power Calculation", "eV", additional_parameters)) if self.delta_e == 0.0: beam_out.set_initial_flux(self.sourceundulator.get_flux()[0]) self.progressBarSet(80) self.plot_results(beam_out) # # create python script for creating the shadow3 beam and display the script in the standard output # dict_parameters = { "K": self.K, "period_length": self.period_length, "periods_number": self.periods_number, "energy_in_GeV": self.energy_in_GeV, "energy_spread": 0.0, "current": self.current, "number_of_bunches": 1, "moment_xx": (self.sigma_x)**2, "moment_xxp": 0.0, "moment_xpxp": (self.sigma_divergence_x)**2, "moment_yy": (self.sigma_z)**2, "moment_yyp": 0.0, "moment_ypyp": (self.sigma_divergence_z)**2, "name": "shadowOui-Full-Undulator", "flag_emittance": self.use_emittances_combo, "flag_size": self.flag_size, "emin": 1000, # to be set later "emax": 1001, # to be set later "ng_e": 2, # to be set later "maxangle": self.maxangle_urad * 1e-6, "ng_t": self.ng_t, "ng_p": self.ng_p, "ng_j": self.ng_j, "code_undul_phot": selected_code, "user_unit_to_m": self.workspace_units_to_m, "F_COHER": self.coherent, "SEED": self.seed, "NRAYS": self.number_of_rays, "EMIN": self.sourceundulator._EMIN, "EMAX": self.sourceundulator._EMAX, "NG_E": self.sourceundulator._NG_E, "MAXANGLE": self.sourceundulator._MAXANGLE, } # write python script in standard output print(self.script_template().format_map(dict_parameters)) self.setStatusMessage("") self.send("Beam", beam_out) except Exception as exception: QtWidgets.QMessageBox.critical(self, "Error", str(exception), QtWidgets.QMessageBox.Ok) if self.IS_DEVELOP: raise exception self.progressBarFinished() def script_template(self): return """ # # script to calculate the shadow3 beam for the full undulator (created by ShadowOui:UndulatorFull\) # from syned.storage_ring.electron_beam import ElectronBeam from syned.storage_ring.magnetic_structures.undulator import Undulator from orangecontrib.shadow.util.undulator.source_undulator import SourceUndulator import Shadow from Shadow import Beam as Shadow3Beam su = Undulator.initialize_as_vertical_undulator( K={K}, period_length={period_length}, periods_number={periods_number}) ebeam = ElectronBeam( energy_in_GeV={energy_in_GeV}, energy_spread = {energy_spread}, current = {current}, number_of_bunches = {number_of_bunches}, moment_xx ={moment_xx}, moment_xxp ={moment_xxp}, moment_xpxp ={moment_xpxp}, moment_yy ={moment_yy}, moment_yyp ={moment_yyp}, moment_ypyp={moment_ypyp}) print(ebeam.info()) sourceundulator = SourceUndulator( name="{name}", syned_electron_beam=ebeam, syned_undulator=su, flag_emittance={flag_emittance}, flag_size={flag_size}, emin = {emin}, emax = {emax}, ng_e = {ng_e}, maxangle = {maxangle}, ng_t={ng_t}, ng_p={ng_p}, ng_j={ng_j}, code_undul_phot="{code_undul_phot}") sourceundulator._EMIN = {EMIN} sourceundulator._EMAX = {EMAX} sourceundulator._NG_E = {NG_E} sourceundulator._MAXANGLE = {MAXANGLE} rays = sourceundulator.calculate_rays( user_unit_to_m={user_unit_to_m}, F_COHER={F_COHER}, SEED={SEED}, NRAYS={NRAYS}) print(sourceundulator.info()) beam = Shadow3Beam(N=rays.shape[0]) beam.rays = rays Shadow.ShadowTools.plotxy(beam,1,3,nbins=101,nolost=1,title="Real space") # Shadow.ShadowTools.plotxy(beam,1,4,nbins=101,nolost=1,title="Phase space X") # Shadow.ShadowTools.plotxy(beam,3,6,nbins=101,nolost=1,title="Phase space Z") # # end script # """ def sendNewBeam(self, trigger): if trigger and trigger.new_object == True: self.runShadowSource() def checkFields(self): self.number_of_rays = congruence.checkPositiveNumber( self.number_of_rays, "Number of rays") self.seed = congruence.checkPositiveNumber(self.seed, "Seed") self.photon_energy = congruence.checkPositiveNumber( self.photon_energy, "Energy") self.delta_e = congruence.checkPositiveNumber(self.delta_e, "Delta Energy") self.energy_in_GeV = congruence.checkPositiveNumber( self.energy_in_GeV, "Energy [GeV]") self.current = congruence.checkPositiveNumber(self.current, "Current [A]") self.sigma_x = congruence.checkPositiveNumber(self.sigma_x, "Size RMS H") self.sigma_z = congruence.checkPositiveNumber(self.sigma_z, "Size RMS V") self.sigma_divergence_x = congruence.checkPositiveNumber( self.sigma_divergence_x, "Divergence RMS H") self.sigma_divergence_z = congruence.checkPositiveNumber( self.sigma_divergence_z, "Divergence RMS V") self.K = congruence.checkPositiveNumber(self.K, "K") self.period_length = congruence.checkPositiveNumber( self.period_length, "period length [m]") self.periods_number = congruence.checkStrictlyPositiveNumber( self.periods_number, "Number of periods") self.ng_t = int( congruence.checkStrictlyPositiveNumber( self.ng_t, "Number of points in theta")) self.ng_p = int( congruence.checkStrictlyPositiveNumber(self.ng_p, "Number of points in phi")) self.ng_j = int( congruence.checkStrictlyPositiveNumber( self.ng_j, "Number of points in trajectory")) self.ng_e = int( congruence.checkStrictlyPositiveNumber( self.ng_e, "Number of points in energy")) def receive_syned_data(self, data): if not data is None: if isinstance(data, synedb.Beamline): if not data.get_light_source() is None: if isinstance( data.get_light_source().get_magnetic_structure(), synedu.Undulator): light_source = data.get_light_source() # self.photon_energy = round(light_source.get_magnetic_structure().resonance_energy(light_source.get_electron_beam().gamma()), 3) self.set_at_resonance = 1 self.set_UseResonance() self.delta_e = 0.0 self.energy_in_GeV = light_source.get_electron_beam( ).energy() self.current = light_source.get_electron_beam( ).current() x, xp, y, yp = light_source.get_electron_beam( ).get_sigmas_all() self.sigma_x = x self.sigma_z = y self.sigma_divergence_x = xp self.sigma_divergence_z = yp self.period_length = light_source.get_magnetic_structure( ).period_length() self.periods_number = int( light_source.get_magnetic_structure( ).number_of_periods()) # in meter self.K = light_source.get_magnetic_structure( ).K_vertical() else: raise ValueError("Syned light source not congruent") else: raise ValueError( "Syned data not correct: light source not present") else: raise ValueError("Syned data not correct")
class OWOpticalElement(WiseWidget, WidgetDecorator): category = "" keywords = ["wise", "mirror"] inputs = [("Input", WiseData, "set_input"), ("PreInput", WisePreInputData, "set_pre_input")] WidgetDecorator.append_syned_input_data(inputs) oe_name = Setting("Optical Element") alpha = Setting(2.0) length = Setting(400.0) ignore = Setting(False) use_small_displacements = Setting(0) rotation = Setting(0.0) transverse = Setting(0.0) longitudinal = Setting(0.0) use_figure_error = Setting(0) figure_error_file = Setting("figure_error.dat") figure_error_step = Setting(0.002) figure_error_amplitude_scaling = Setting(1.0) figure_error_um_conversion = Setting(1.0) use_roughness = Setting(0) roughness_file = Setting("roughness.dat") roughness_x_scaling = Setting(1.0) roughness_y_scaling = Setting(1.0) roughness_fit_data = Setting(0) use_multipool = Setting(0) n_pools = Setting(5) number_of_cpus = multiprocessing.cpu_count() - 1 force_cpus = Setting(1) calculation_type = Setting(0) number_of_points = Setting(7000) input_data = None has_figure_error_box = True is_full_propagator = False def build_gui(self): self.tabs_setting = oasysgui.tabWidget(self.controlArea) self.tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT) self.tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH - 5) self.tab_bas = oasysgui.createTabPage(self.tabs_setting, "O.E. Setting") self.tab_pro = oasysgui.createTabPage(self.tabs_setting, "Calculation Setting") main_box = oasysgui.widgetBox(self.tab_bas, "O.E. Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 20) oasysgui.lineEdit(main_box, self, "oe_name", "O.E. Name", labelWidth=120, valueType=str, orientation="horizontal") oasysgui.lineEdit(main_box, self, "alpha", "Incidence Angle [deg]", labelWidth=240, valueType=float, orientation="horizontal") self.le_length = oasysgui.lineEdit(main_box, self, "length", "Length", labelWidth=240, valueType=float, orientation="horizontal") self.build_mirror_specific_gui(main_box) gui.comboBox(main_box, self, "ignore", label="Ignore", items=["No", "Yes"], labelWidth=240, sendSelectedValue=False, orientation="horizontal") gui.separator(main_box) self.tabs_mirror = oasysgui.tabWidget(main_box) self.tabs_mirror.setFixedWidth(self.CONTROL_AREA_WIDTH - 40) self.tab_pos = oasysgui.createTabPage(self.tabs_mirror, "Position") if self.has_figure_error_box: self.tab_err = oasysgui.createTabPage(self.tabs_mirror, "Figure Error") self.tab_dis = oasysgui.createTabPage(self.tabs_mirror, "Displacement") super(OWOpticalElement, self).build_positioning_directive_box( container_box=self.tab_pos, width=self.CONTROL_AREA_WIDTH - 50, element_type=ElementType.MIRROR) displacement_box = oasysgui.widgetBox(self.tab_dis, "Small Displacements", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 50) gui.comboBox(displacement_box, self, "use_small_displacements", label="Small Displacements", items=["No", "Yes"], labelWidth=240, callback=self.set_UseSmallDisplacement, sendSelectedValue=False, orientation="horizontal") self.use_small_displacements_box = oasysgui.widgetBox( displacement_box, "", addSpace=True, orientation="vertical", height=150, width=self.CONTROL_AREA_WIDTH - 65) self.use_small_displacements_box_empty = oasysgui.widgetBox( displacement_box, "", addSpace=True, orientation="vertical", height=150, width=self.CONTROL_AREA_WIDTH - 65) oasysgui.lineEdit(self.use_small_displacements_box, self, "rotation", "Rotation [deg]", labelWidth=240, valueType=float, orientation="horizontal") self.le_transverse = oasysgui.lineEdit( self.use_small_displacements_box, self, "transverse", "Transverse displacement", labelWidth=240, valueType=float, orientation="horizontal") self.le_longitudinal = oasysgui.lineEdit( self.use_small_displacements_box, self, "longitudinal", "Longitudinal displacement", labelWidth=240, valueType=float, orientation="horizontal") self.set_UseSmallDisplacement() # --------------------------------------------------------------------------- if self.has_figure_error_box: figure_error_tab = oasysgui.tabWidget(self.tab_err) error_tab = oasysgui.createTabPage(figure_error_tab, "Error Profile") roughness_tab = oasysgui.createTabPage(figure_error_tab, "Roughness") figure_error_box = oasysgui.widgetBox( error_tab, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 65) roughness_box = oasysgui.widgetBox(roughness_tab, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 65) gui.comboBox(figure_error_box, self, "use_figure_error", label="Error Profile", items=["None", "User Defined"], labelWidth=240, callback=self.set_UseFigureError, sendSelectedValue=False, orientation="horizontal") self.use_figure_error_box = oasysgui.widgetBox( figure_error_box, "", addSpace=True, orientation="vertical", height=150) self.use_figure_error_box_empty = oasysgui.widgetBox( figure_error_box, "", addSpace=True, orientation="vertical", height=150) file_box = oasysgui.widgetBox(self.use_figure_error_box, "", addSpace=False, orientation="horizontal") self.le_figure_error_file = oasysgui.lineEdit( file_box, self, "figure_error_file", "File Name", labelWidth=100, valueType=str, orientation="horizontal") gui.button(file_box, self, "...", callback=self.selectFigureErrorFile) self.le_figure_error_step = oasysgui.lineEdit( self.use_figure_error_box, self, "figure_error_step", "Step", labelWidth=240, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.use_figure_error_box, self, "figure_error_amplitude_scaling", "Amplitude scaling factor", labelWidth=240, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.use_figure_error_box, self, "figure_error_um_conversion", "User file u.m. to [m] factor", labelWidth=240, valueType=float, orientation="horizontal") self.set_UseFigureError() gui.comboBox(roughness_box, self, "use_roughness", label="Roughness", items=["None", "User Defined"], labelWidth=240, callback=self.set_UseRoughness, sendSelectedValue=False, orientation="horizontal") self.use_roughness_box = oasysgui.widgetBox(roughness_box, "", addSpace=True, orientation="vertical", height=150) self.use_roughness_box_empty = oasysgui.widgetBox( roughness_box, "", addSpace=True, orientation="vertical", height=150) file_box = oasysgui.widgetBox(self.use_roughness_box, "", addSpace=False, orientation="horizontal") self.le_roughness_file = oasysgui.lineEdit( file_box, self, "roughness_file", "File Name", labelWidth=100, valueType=str, orientation="horizontal") gui.button(file_box, self, "...", callback=self.selectRoughnessFile) oasysgui.lineEdit(self.use_roughness_box, self, "roughness_x_scaling", "x user file u.m. to [m] factor", labelWidth=240, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.use_roughness_box, self, "roughness_y_scaling", "y user file u.m. to [m^3] factor", labelWidth=240, valueType=float, orientation="horizontal") gui.comboBox(self.use_roughness_box, self, "roughness_fit_data", label="Fit numeric data with power law", items=["No", "Yes"], labelWidth=240, sendSelectedValue=False, orientation="horizontal") self.set_UseRoughness() # --------------------------------------------------------------------------- calculation_box = oasysgui.widgetBox(self.tab_pro, "Calculation Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 20) gui.comboBox(calculation_box, self, "calculation_type", label="Numeric Integration", items=[ "Automatic Number of Points", "User Defined Number of Points" ], labelWidth=140, callback=self.set_CalculationType, sendSelectedValue=False, orientation="horizontal") self.empty_box = oasysgui.widgetBox(calculation_box, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 40, height=50) self.number_box = oasysgui.widgetBox(calculation_box, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 40, height=50) oasysgui.lineEdit(self.number_box, self, "number_of_points", "Number of Points", labelWidth=240, valueType=int, orientation="horizontal") self.set_CalculationType() parallel_box = oasysgui.widgetBox(self.tab_pro, "Parallel Computing", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 20) gui.comboBox(parallel_box, self, "use_multipool", label="Use Parallel Processing", items=["No", "Yes"], labelWidth=240, callback=self.set_Multipool, sendSelectedValue=False, orientation="horizontal") self.use_multipool_box = oasysgui.widgetBox( parallel_box, "", addSpace=False, orientation="vertical", height=100, width=self.CONTROL_AREA_WIDTH - 40) self.use_multipool_box_empty = oasysgui.widgetBox( parallel_box, "", addSpace=False, orientation="vertical", height=100, width=self.CONTROL_AREA_WIDTH - 40) oasysgui.lineEdit(self.use_multipool_box, self, "n_pools", "Nr. Parallel Processes", labelWidth=240, valueType=int, orientation="horizontal") gui.separator(self.use_multipool_box) gui.comboBox(self.use_multipool_box, self, "force_cpus", label="Ignore Nr. Processes > Nr. CPUs", items=["No", "Yes"], labelWidth=240, sendSelectedValue=False, orientation="horizontal") le = oasysgui.lineEdit(self.use_multipool_box, self, "number_of_cpus", "Nr. Available CPUs", labelWidth=240, valueType=float, orientation="horizontal") le.setReadOnly(True) font = QFont(le.font()) font.setBold(True) le.setFont(font) palette = QPalette(le.palette()) palette.setColor(QPalette.Text, QColor('dark blue')) palette.setColor(QPalette.Base, QColor(243, 240, 140)) le.setPalette(palette) self.set_Multipool() def selectFigureErrorFile(self): self.le_figure_error_file.setText( oasysgui.selectFileFromDialog( self, self.figure_error_file, "Select File", file_extension_filter="Data Files (*.dat *.txt)")) def selectRoughnessFile(self): self.le_roughness_file.setText( oasysgui.selectFileFromDialog( self, self.roughness_file, "Select File", file_extension_filter="Data Files (*.dat *.txt)")) def set_FigureErrorPlot(self): if self.use_figure_error == 1: self.tab[2].setEnabled(True) self.plot_canvas[2]._backend.fig.set_facecolor("#FEFEFE") else: self.tab[2].setEnabled(False) self.plot_canvas[2]._backend.fig.set_facecolor("#D7DBDD") def set_UseFigureError(self): self.use_figure_error_box.setVisible(self.use_figure_error == 1) self.use_figure_error_box_empty.setVisible(self.use_figure_error == 0) def set_UseRoughness(self): self.use_roughness_box.setVisible(self.use_roughness == 1) self.use_roughness_box_empty.setVisible(self.use_roughness == 0) def set_UseSmallDisplacement(self): self.use_small_displacements_box.setVisible( self.use_small_displacements == 1) self.use_small_displacements_box_empty.setVisible( self.use_small_displacements == 0) def set_CalculationType(self): self.empty_box.setVisible(self.calculation_type == 0) self.number_box.setVisible(self.calculation_type == 1) def set_Multipool(self): self.use_multipool_box.setVisible(self.use_multipool == 1) self.use_multipool_box_empty.setVisible(self.use_multipool == 0) def after_change_workspace_units(self): super(OWOpticalElement, self).after_change_workspace_units() label = self.le_length.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") if self.has_figure_error_box: label = self.le_figure_error_step.parent().layout().itemAt( 0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_transverse.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_longitudinal.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") def build_mirror_specific_gui(self, container_box): raise NotImplementedError() def set_input(self, input_data): self.setStatusMessage("") if not input_data is None: try: if input_data.wise_beamline is None or input_data.wise_beamline.get_propagation_elements_number( ) == 0: if input_data.wise_wavefront is None: raise ValueError( "Input Data contains no wavefront and/or no source to perform wavefront propagation" ) self.input_data = input_data.duplicate() if self.is_automatic_run: self.compute() except Exception as e: QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) self.setStatusMessage("Error") def set_pre_input(self, data): if data is not None: try: if data.figure_error_file != WisePreInputData.NONE: self.figure_error_file = data.figure_error_file self.figure_error_step = data.figure_error_step self.figure_error_um_conversion = data.figure_user_units_to_m self.use_figure_error = 1 self.set_UseFigureError() if data.roughness_file != WisePreInputData.NONE: self.roughness_file = data.roughness_file self.roughness_x_scaling = data.roughness_x_scaling self.roughness_y_scaling = data.roughness_y_scaling self.use_roughness = 1 self.set_UseRoughness() except Exception as e: QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) self.setStatusMessage("Error") def check_fields(self): self.alpha = congruence.checkAngle(self.alpha, "Incidence Angle") self.length = congruence.checkStrictlyPositiveNumber( self.length, "Length") if self.use_figure_error == 1: congruence.checkFileName(self.figure_error_file) if self.use_roughness == 1: congruence.checkFileName(self.roughness_file) if self.calculation_type == 1: congruence.checkStrictlyPositiveNumber(self.number_of_points, "Number of Points") if self.use_multipool == 1: congruence.checkStrictlyPositiveNumber(self.n_pools, "Nr. Parallel Processes") if self.force_cpus == 0: if self.number_of_cpus == 1: raise Exception( "Parallel processing not available with 1 CPU") elif self.n_pools >= self.number_of_cpus: raise Exception( "Max number of parallel processes allowed on this computer (" + str(self.number_of_cpus) + ")") def do_wise_calculation(self): if self.input_data is None: raise Exception("No Input Data!") optical_element = self.get_optical_element( self.get_inner_wise_optical_element()) wise_optical_element = optical_element.wise_optical_element wise_optical_element.CoreOptics.ComputationSettings.Ignore = ( self.ignore == 1) if self.use_small_displacements == 1: wise_optical_element.CoreOptics.ComputationSettings.UseSmallDisplacements = True # serve per traslare/ruotare l'EO wise_optical_element.CoreOptics.SmallDisplacements.Rotation = numpy.deg2rad( self.rotation) wise_optical_element.CoreOptics.SmallDisplacements.Trans = self.transverse * self.workspace_units_to_m # Transverse displacement (rispetto al raggio uscente, magari faremo scegliere) wise_optical_element.CoreOptics.SmallDisplacements.Long = self.longitudinal * self.workspace_units_to_m # Longitudinal displacement (idem) else: wise_optical_element.CoreOptics.ComputationSettings.UseSmallDisplacements = False wise_optical_element.CoreOptics.SmallDisplacements.Rotation = 0.0 wise_optical_element.CoreOptics.SmallDisplacements.Trans = 0.0 wise_optical_element.CoreOptics.SmallDisplacements.Long = 0.0 if self.use_figure_error == 1: wise_optical_element.CoreOptics.ComputationSettings.UseFigureError = True wise_optical_element.CoreOptics.FigureErrorLoad( File=self.figure_error_file, Step=self.figure_error_step * self.workspace_units_to_m, # passo del file AmplitudeScaling=self.figure_error_amplitude_scaling * self.figure_error_um_conversion # fattore di scala ) else: wise_optical_element.CoreOptics.ComputationSettings.UseFigureError = False if self.use_roughness == 1: self.use_roughness = 0 self.set_UseRoughness() raise NotImplementedError("Roughness Not yet supported") else: wise_optical_element.CoreOptics.ComputationSettings.UseRoughness = False if self.calculation_type == 0: wise_optical_element.ComputationSettings.UseCustomSampling = False else: # l'utente decide di impostare a mano il campionamento wise_optical_element.ComputationSettings.UseCustomSampling = True wise_optical_element.ComputationSettings.NSamples = self.number_of_points output_data = self.input_data.duplicate() input_wavefront = output_data.wise_wavefront if output_data.wise_beamline is None: output_data.wise_beamline = WisePropagationElements() output_data.wise_beamline.add_beamline_element( WiseBeamlineElement(optical_element=optical_element)) parameters = PropagationParameters( wavefront=input_wavefront if not input_wavefront is None else WiseWavefront(wise_computation_results=None), propagation_elements=output_data.wise_beamline) parameters.set_additional_parameters( "single_propagation", True if PropagationManager.Instance().get_propagation_mode( WISE_APPLICATION) == PropagationMode.STEP_BY_STEP else (not self.is_full_propagator)) parameters.set_additional_parameters( "NPools", self.n_pools if self.use_multipool == 1 else 1) parameters.set_additional_parameters("is_full_propagator", self.is_full_propagator) output_data.wise_wavefront = PropagationManager.Instance( ).do_propagation(propagation_parameters=parameters, handler_name=WisePropagator.HANDLER_NAME) return output_data def get_inner_wise_optical_element(self): raise NotImplementedError() def get_optical_element(self, inner_wise_optical_element): raise NotImplementedError() def getTabTitles(self): return ["Field Intensity (O.E.)", "Phase (O.E.)", "Figure Error"] def getTitles(self): return ["Field Intensity (O.E.)", "Phase (O.E.)", "Figure Error"] def getXTitles(self): return [ "S [" + self.workspace_units_label + "]", "S [" + self.workspace_units_label + "]", "S [" + self.workspace_units_label + "]" ] def getYTitles(self): return ["|E0|**2", "Phase", "Height Error [nm]"] def getVariablesToPlot(self): return [(0, 1), (0, 2), (0, 1)] def getLogPlot(self): return [(False, False), (False, False), (False, False)] def extract_plot_data_from_calculation_output(self, calculation_output): output_wavefront = calculation_output.wise_wavefront if not output_wavefront is None and not output_wavefront.wise_computation_result is None: wise_optical_element = calculation_output.wise_beamline.get_wise_propagation_element( -1) S = output_wavefront.wise_computation_result.S E = output_wavefront.wise_computation_result.Field I = abs(E)**2 norm = max(I) norm = 1.0 if norm == 0.0 else norm I = I / norm #------------------------------------------------------------ data_to_plot = numpy.zeros((3, len(S))) data_to_plot[0, :] = S / self.workspace_units_to_m data_to_plot[1, :] = I data_to_plot[2, :] = numpy.imag(E) self.is_tab_2_enabled = False if not wise_optical_element.CoreOptics.FigureErrors is None and len( wise_optical_element.CoreOptics.FigureErrors) > 0: self.is_tab_2_enabled = True figure_error_x = numpy.linspace( 0, self.length, len(wise_optical_element.CoreOptics.FigureErrors[0])) data_to_plot_fe = numpy.zeros((2, len(figure_error_x))) data_to_plot_fe[0, :] = figure_error_x data_to_plot_fe[ 1, :] = wise_optical_element.CoreOptics.FigureErrors[ 0] * 1e9 # nm else: data_to_plot_fe = numpy.zeros((2, 1)) data_to_plot_fe[0, :] = numpy.zeros(1) data_to_plot_fe[1, :] = numpy.zeros(1) return data_to_plot, data_to_plot_fe else: return None, None def plot_results(self, plot_data, progressBarValue=80): if not self.view_type == 0: if not plot_data is None: plot_data_1 = plot_data[0] plot_data_2 = plot_data[1] self.view_type_combo.setEnabled(False) titles = self.getTitles() xtitles = self.getXTitles() ytitles = self.getYTitles() progress_bar_step = (100 - progressBarValue) / len(titles) for index in range(0, len(titles)): x_index, y_index = self.getVariablesToPlot()[index] log_x, log_y = self.getLogPlot()[index] try: if index < 2: if not plot_data_1 is None: self.plot_histo( plot_data_1[x_index, :], plot_data_1[y_index, :], progressBarValue + ((index + 1) * progress_bar_step), tabs_canvas_index=index, plot_canvas_index=index, title=titles[index], xtitle=xtitles[index], ytitle=ytitles[index], log_x=log_x, log_y=log_y) else: if not plot_data_2 is None: self.plot_histo( plot_data_2[x_index, :], plot_data_2[y_index, :], progressBarValue + ((index + 1) * progress_bar_step), tabs_canvas_index=index, plot_canvas_index=index, title=titles[index], xtitle=xtitles[index], ytitle=ytitles[index], log_x=log_x, log_y=log_y) if index == 2: self.set_FigureErrorPlot() except Exception as e: self.view_type_combo.setEnabled(True) raise Exception("Data not plottable: bad content\n" + str(e)) self.tabs.setCurrentIndex(0) self.view_type_combo.setEnabled(True) else: raise Exception("Empty Data") def receive_syned_data(self, data): if not data is None: try: beamline_element = data.get_beamline_element_at(-1) if beamline_element is None: raise Exception( "Syned Data not correct: Empty Beamline Element") optical_element = beamline_element._optical_element if optical_element is None: raise Exception( "Syned Data not correct: Empty Optical Element") if not isinstance(optical_element, Mirror): raise Exception( "Syned Data not correct: Optical Element is not a Mirror" ) self.check_syned_shape(optical_element) self.alpha = round( numpy.degrees(0.5 * numpy.pi - beamline_element._coordinates._angle_radial), 4) boundaries = optical_element._boundary_shape.get_boundaries() tangential_size = round( abs(boundaries[3] - boundaries[2]) / self.workspace_units_to_m, 6) sagittal_size = round( abs(boundaries[1] - boundaries[0]) / self.workspace_units_to_m, 6) axis = QInputDialog.getItem(self, "Projection Axis", "Select Direction", ("Horizontal", "Vertical"), 0, False) if axis == 0: self.length = sagittal_size else: self.length = tangential_size self.receive_specific_syned_data(optical_element) except Exception as e: QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) self.setStatusMessage("Error") def check_syned_shape(self, optical_element): raise NotImplementedError() def receive_specific_syned_data(self, optical_element): raise NotImplementedError()
class OWEllipticalMirror(WiseWidget, WidgetDecorator): name = "EllipticalMirror" id = "EllipticalMirror" description = "EllipticalMirror" icon = "icons/elliptical_mirror.png" priority = 2 category = "" keywords = ["wise", "elliptical"] inputs = [("Input", WiseOutput, "set_input"), ("PreInput", WisePreInputData, "set_pre_input")] WidgetDecorator.append_syned_input_data(inputs) f1 = Setting(98000) f2 = Setting(1200) alpha = Setting(2) length = Setting(400) use_figure_error = Setting(0) figure_error_file = Setting("figure_error.dat") figure_error_step = Setting(0.002) figure_error_um_conversion = Setting(1.0) use_roughness = Setting(0) roughness_file = Setting("roughness.dat") roughness_x_scaling = Setting(1.0) roughness_y_scaling = Setting(1.0) roughness_fit_data = Setting(0) calculation_type = Setting(0) number_of_points = Setting(0) detector_size = Setting(50) calculated_number_of_points = 0 input_data = None def set_input(self, input_data): self.setStatusMessage("") if not input_data is None: if input_data.has_optical_element(): QMessageBox.critical(self, "Error", "Propagation from previous O.E. not yet supported", QMessageBox.Ok) self.setStatusMessage("Error!") self.input_data = input_data if self.is_automatic_run: self.compute() def set_pre_input(self, data): if data is not None: if data.figure_error_file != WisePreInputData.NONE: self.figure_error_file = data.figure_error_file self.figure_error_step = data.figure_error_step self.figure_error_um_conversion = data.figure_user_units_to_m self.use_figure_error = 1 self.set_UseFigureError() if data.roughness_file != WisePreInputData.NONE: self.roughness_file=data.roughness_file self.roughness_x_scaling = data.roughness_x_scaling self.roughness_y_scaling = data.roughness_y_scaling self.use_roughness = 1 self.set_UseRoughness() def build_gui(self): self.tabs_setting = oasysgui.tabWidget(self.controlArea) self.tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT) self.tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH-5) self.tab_bas = oasysgui.createTabPage(self.tabs_setting, "Mirror Setting") self.tab_pro = oasysgui.createTabPage(self.tabs_setting, "Calculation Setting") main_box = oasysgui.widgetBox(self.tab_bas, "Elliptical Mirror Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-20) self.le_f1 = oasysgui.lineEdit(main_box, self, "f1", "F1", labelWidth=240, valueType=float, orientation="horizontal") self.le_f2 = oasysgui.lineEdit(main_box, self, "f2", "F2", labelWidth=240, valueType=float, orientation="horizontal") oasysgui.lineEdit(main_box, self, "alpha", "Incidence Angle [deg]", labelWidth=240, valueType=float, orientation="horizontal") self.le_length = oasysgui.lineEdit(main_box, self, "length", "Length", labelWidth=240, valueType=float, orientation="horizontal") figure_error_box = oasysgui.widgetBox(self.tab_bas, "Figure Error Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-20) gui.comboBox(figure_error_box, self, "use_figure_error", label="Error Profile", items=["None", "User Defined"], labelWidth=240, callback=self.set_UseFigureError, sendSelectedValue=False, orientation="horizontal") self.use_figure_error_box = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=80) self.use_figure_error_box_empty = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=80) file_box = oasysgui.widgetBox(self.use_figure_error_box, "", addSpace=False, orientation="horizontal") self.le_figure_error_file = oasysgui.lineEdit(file_box, self, "figure_error_file", "File Name", labelWidth=100, valueType=str, orientation="horizontal") gui.button(file_box, self, "...", callback=self.selectFigureErrorFile) self.le_figure_error_step = oasysgui.lineEdit(self.use_figure_error_box, self, "figure_error_step", "Step", labelWidth=240, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.use_figure_error_box, self, "figure_error_um_conversion", "user file u.m. to [m] factor", labelWidth=240, valueType=float, orientation="horizontal") self.set_UseFigureError() gui.comboBox(figure_error_box, self, "use_roughness", label="roughness", items=["None", "User Defined"], labelWidth=240, callback=self.set_UseRoughness, sendSelectedValue=False, orientation="horizontal") self.use_roughness_box = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=110) self.use_roughness_box_empty = oasysgui.widgetBox(figure_error_box, "", addSpace=True, orientation="vertical", height=110) file_box = oasysgui.widgetBox(self.use_roughness_box, "", addSpace=False, orientation="horizontal") self.le_roughness_file = oasysgui.lineEdit(file_box, self, "roughness_file", "File Name", labelWidth=100, valueType=str, orientation="horizontal") gui.button(file_box, self, "...", callback=self.selectroughnessFile) oasysgui.lineEdit(self.use_roughness_box, self, "roughness_x_scaling", "x user file u.m. to [m] factor", labelWidth=240, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.use_roughness_box, self, "roughness_y_scaling", "y user file u.m. to [m^3] factor", labelWidth=240, valueType=float, orientation="horizontal") gui.comboBox(self.use_roughness_box, self, "roughness_fit_data", label="Fit numeric data with power law", items=["No", "Yes"], labelWidth=240, sendSelectedValue=False, orientation="horizontal") self.set_UseRoughness() calculation_box = oasysgui.widgetBox(self.tab_pro, "Calculation Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-20) gui.comboBox(calculation_box, self, "calculation_type", label="Numeric Integration", items=["Automatic Number of Points", "User Defined Number of Points"], labelWidth=140, callback=self.set_CalculationType, sendSelectedValue=False, orientation="horizontal") self.detector_box = oasysgui.widgetBox(calculation_box, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-40) oasysgui.lineEdit(self.detector_box, self, "detector_size", "(Hypotetic) Detector Size [" + u"\u03BC" + "m]", labelWidth=240, valueType=float, orientation="horizontal") le_calculated_number_of_points = oasysgui.lineEdit(self.detector_box, self, "calculated_number_of_points", "Calculated Number of Points", labelWidth=240, valueType=float, orientation="horizontal") le_calculated_number_of_points.setReadOnly(True) font = QFont(le_calculated_number_of_points.font()) font.setBold(True) le_calculated_number_of_points.setFont(font) palette = QPalette(le_calculated_number_of_points.palette()) palette.setColor(QPalette.Text, QColor('dark blue')) palette.setColor(QPalette.Base, QColor(243, 240, 160)) le_calculated_number_of_points.setPalette(palette) self.number_box = oasysgui.widgetBox(calculation_box, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-40) oasysgui.lineEdit(self.number_box, self, "number_of_points", "Number of Points", labelWidth=240, valueType=int, orientation="horizontal") self.set_CalculationType() def selectFigureErrorFile(self): self.le_figure_error_file.setText(oasysgui.selectFileFromDialog(self, self.figure_error_file, "Select File", file_extension_filter="Data Files (*.dat *.txt)")) def selectroughnessFile(self): self.le_roughness_file.setText(oasysgui.selectFileFromDialog(self, self.roughness_file, "Select File", file_extension_filter="Data Files (*.dat *.txt)")) def set_UseFigureError(self): self.use_figure_error_box.setVisible(self.use_figure_error == 1) self.use_figure_error_box_empty.setVisible(self.use_figure_error == 0) def set_UseRoughness(self): self.use_roughness_box.setVisible(self.use_roughness == 1) self.use_roughness_box_empty.setVisible(self.use_roughness == 0) def set_CalculationType(self): self.detector_box.setVisible(self.calculation_type==0) self.number_box.setVisible(self.calculation_type==1) def after_change_workspace_units(self): label = self.le_f1.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_f2.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_length.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") label = self.le_figure_error_step.parent().layout().itemAt(0).widget() label.setText(label.text() + " [" + self.workspace_units_label + "]") def check_fields(self): self.f1 = congruence.checkStrictlyPositiveNumber(self.f1, "F1") self.f2 = congruence.checkStrictlyPositiveNumber(self.f2, "F2") self.alpha = congruence.checkAngle(self.alpha, "Incidence Angle") self.length = congruence.checkStrictlyPositiveNumber(self.length, "Length") if self.use_figure_error == 1: congruence.checkFileName(self.figure_error_file) if self.use_roughness == 1: congruence.checkFileName(self.roughness_file) if self.calculation_type == 0: #auto self.detector_size = congruence.checkStrictlyPositiveNumber(self.detector_size, "Detector Size") else: self.number_of_points = congruence.checkStrictlyPositiveNumber(self.number_of_points, "Number of Points") def do_wise_calculation(self): if self.input_data is None: raise Exception("No Input Data!") elliptic_mirror = Optics.Ellipse(f1 = self.f1 * self.workspace_units_to_m, f2 = self.f2 * self.workspace_units_to_m, Alpha = numpy.radians(self.alpha), L = self.length * self.workspace_units_to_m) if self.use_figure_error == 1: elliptic_mirror.FigureErrorAdd(numpy.loadtxt(self.figure_error_file) * self.figure_error_um_conversion, self.figure_error_step * self.workspace_units_to_m) # (m) if self.use_roughness == 1: elliptic_mirror.Roughness.NumericPsdLoadXY(self.roughness_file, xScaling = self.roughness_x_scaling * self.workspace_units_to_m, yScaling = self.roughness_y_scaling * self.workspace_units_to_m, xIsSpatialFreq = False) elliptic_mirror.Roughness.Options.FIT_NUMERIC_DATA_WITH_POWER_LAW = (self.roughness_fit_data == 1) elliptic_mirror.Options.USE_ROUGHNESS = True else: elliptic_mirror.Options.USE_ROUGHNESS = False #------------------------------------------------------------ source = self.input_data.get_source() if source.get_property("source_on_mirror_focus"): longitudinal_correction = float(source.get_property("longitudinal_correction")) transverse_correction = float(source.get_property("transverse_correction")) delta_theta = float(source.get_property("delta_theta")) if longitudinal_correction == 0.0: if transverse_correction == 0.0: alpha = 0 else: alpha = elliptic_mirror.p1_Angle + numpy.sign(transverse_correction)*numpy.pi/2 else: alpha = elliptic_mirror.p1_Angle + numpy.arctan(transverse_correction/longitudinal_correction) defocus = numpy.sqrt(longitudinal_correction**2 + transverse_correction**2) theta = elliptic_mirror.p1_Angle + delta_theta z_origin = elliptic_mirror.XYF1[0] + defocus*numpy.cos(alpha) y_origin = elliptic_mirror.XYF1[1] + defocus*numpy.sin(alpha) print("theta (deg)", numpy.degrees(theta), "Z", z_origin, "Y", y_origin) if (isinstance(source.inner_wise_source, Optics.GaussianSource_1d)): source.inner_wise_source = Optics.GaussianSource_1d(source.inner_wise_source.Lambda, source.inner_wise_source.Waist0, ZOrigin=z_origin, YOrigin=y_origin, Theta=theta) elif (isinstance(source.inner_wise_source, Optics.PointSource_1d)): source.inner_wise_source = Optics.GaussianSource_1d(source.inner_wise_source.Lambda, XOrigin=z_origin, YOrigin=y_origin) else: source.inner_wise_source.ZOrigin = z_origin source.inner_wise_source.YOrigin = y_origin source.inner_wise_source.ThetaPropagation = theta if self.calculation_type == WiseNumericalIntegrationParameters.AUTOMATIC: detector_size = self.detector_size*1e-6 number_of_points = -1 else: detector_size = 0.0 number_of_points = self.number_of_points numerical_integration_parameters = WiseNumericalIntegrationParameters(self.calculation_type, detector_size, number_of_points) propagation_parameter = WisePropagationParameters(propagation_type=WisePropagationParameters.MIRROR_ONLY, source=source.inner_wise_source, optical_element=elliptic_mirror, numerical_integration_parameters=numerical_integration_parameters) propagation_output = WisePropagatorsChain.Instance().do_propagation(propagation_parameter, WisePropagationAlgorithms.HuygensIntegral) if self.calculation_type == WiseNumericalIntegrationParameters.AUTOMATIC: self.calculated_number_of_points = propagation_output.number_of_points else: self.calculated_number_of_points = 0 wavefront_out = WiseWavefront(propagation_output.mir_x, propagation_output.mir_y, propagation_output.mir_s, propagation_output.mir_E, propagation_output.residuals) numerical_integration_parameters_out = WiseNumericalIntegrationParameters(self.calculation_type, detector_size, number_of_points, propagation_output.number_of_points) optical_element_out = WiseOpticalElement(inner_wise_optical_element=elliptic_mirror) data_to_plot = numpy.zeros((5, len(propagation_output.mir_s))) data_to_plot[0, :] = propagation_output.mir_s / self.workspace_units_to_m data_to_plot[1, :] = Amp(propagation_output.mir_E)**2 data_to_plot[2, :] = Cyc(propagation_output.mir_E) if len(propagation_output.residuals) > 0: figure_error_x = numpy.linspace(0, self.length, len(propagation_output.residuals)) data_to_plot_fe = numpy.zeros((2, len(figure_error_x))) data_to_plot_fe[0, :] = figure_error_x data_to_plot_fe[1, :] = propagation_output.residuals*1e9 # nm else: data_to_plot_fe = numpy.zeros((2, 1)) data_to_plot_fe[0, :] = numpy.zeros(1) data_to_plot_fe[1, :] = numpy.zeros(1) return source, optical_element_out, wavefront_out, numerical_integration_parameters_out, data_to_plot, data_to_plot_fe def getTabTitles(self): return ["Field Intensity (mirror)", "Optical Cycles (mirror)", "Figure Error"] def getTitles(self): return ["Field Intensity (mirror)", "Optical Cycles (mirror)", "Figure Error"] def getXTitles(self): return ["rho [" + self.workspace_units_label + "]", "Z [" + self.workspace_units_label + "]", "Z [$\mu$m]"] def getYTitles(self): return ["|E0|**2", "Optical Cycles", "Height Error [nm]"] def getVariablesToPlot(self): return [(0, 1), (0, 2), (0, 1)] def getLogPlot(self): return [(False, False), (False, False), (False, False)] def extract_plot_data_from_calculation_output(self, calculation_output): return calculation_output[4], calculation_output[5] def plot_results(self, plot_data, progressBarValue=80): if not self.view_type == 0: if not plot_data is None: plot_data_1 = plot_data[0] plot_data_2 = plot_data[1] self.view_type_combo.setEnabled(False) titles = self.getTitles() xtitles = self.getXTitles() ytitles = self.getYTitles() progress_bar_step = (100-progressBarValue)/len(titles) for index in range(0, len(titles)): x_index, y_index = self.getVariablesToPlot()[index] log_x, log_y = self.getLogPlot()[index] try: if index < 2: self.plot_histo(plot_data_1[x_index, :], plot_data_1[y_index, :], progressBarValue + ((index+1)*progress_bar_step), tabs_canvas_index=index, plot_canvas_index=index, title=titles[index], xtitle=xtitles[index], ytitle=ytitles[index], log_x=log_x, log_y=log_y) else: self.plot_histo(plot_data_2[x_index, :], plot_data_2[y_index, :], progressBarValue + ((index+1)*progress_bar_step), tabs_canvas_index=index, plot_canvas_index=index, title=titles[index], xtitle=xtitles[index], ytitle=ytitles[index], log_x=log_x, log_y=log_y) self.tabs.setCurrentIndex(index) except Exception as e: self.view_type_combo.setEnabled(True) raise Exception("Data not plottable: bad content\n" + str(e)) self.view_type_combo.setEnabled(True) else: raise Exception("Empty Data") def extract_wise_output_from_calculation_output(self, calculation_output): return WiseOutput(source=calculation_output[0], optical_element=calculation_output[1], wavefront=calculation_output[2], numerical_integration_parameters=calculation_output[3]) def receive_syned_data(self, data): if not data is None: beamline_element = data.get_beamline_element_at(-1) if beamline_element is None: raise Exception("Syned Data not correct: Empty Beamline Element") optical_element = beamline_element._optical_element if optical_element is None: raise Exception("Syned Data not correct: Empty Optical Element") if not isinstance(optical_element, Mirror): raise Exception("Syned Data not correct: Optical Element is not a Mirror") if not isinstance(optical_element._surface_shape, Ellipsoid): raise Exception("Syned Data not correct: Mirror Surface Shape is not Elliptical") self.alpha = round(numpy.degrees(0.5*numpy.pi-beamline_element._coordinates._angle_radial), 4) boundaries = optical_element._boundary_shape.get_boundaries() tangential_size=round(abs(boundaries[3] - boundaries[2])/self.workspace_units_to_m, 6) sagittal_size=round(abs(boundaries[1] - boundaries[0])/self.workspace_units_to_m, 6) axis = QInputDialog.getItem(self, "Projection Axis", "Select Direction", ("Horizontal", "Vertical"), 0, False) if axis == 0: self.length = sagittal_size else: self.length = tangential_size p, q = optical_element._surface_shape.get_p_q(numpy.radians(self.alpha)) self.f1 = numpy.round(p/self.workspace_units_to_m, 6) self.f2 = numpy.round(q/self.workspace_units_to_m, 6)
class Source(ow_generic_element.GenericElement): maintainer = "Luca Rebuffi" maintainer_email = "lrebuffi(@at@)anl.gov" category = "Sources" keywords = ["data", "file", "load", "read"] inputs = [("Trigger", TriggerOut, "sendNewBeam")] WidgetDecorator.append_syned_input_data(inputs) outputs = [{ "name": "Beam", "type": ShadowBeam, "doc": "Shadow Beam", "id": "beam" }] file_to_write_out = Setting(0) want_main_area = 1 TABS_AREA_HEIGHT = 618 CONTROL_AREA_WIDTH = 405 number_of_rays = Setting(5000) seed = Setting(5676561) def __init__(self, show_automatic_box=False): super().__init__(show_automatic_box=show_automatic_box) self.runaction = widget.OWAction("Copy Source Parameters", self) self.runaction.triggered.connect(self.copy_src_parameters) self.addAction(self.runaction) self.runaction = widget.OWAction("Paste Source Parameters", self) self.runaction.triggered.connect(self.paste_src_parameters) self.addAction(self.runaction) self.runaction = widget.OWAction("Run Shadow/Source", self) self.runaction.triggered.connect(self.runShadowSource) self.addAction(self.runaction) self.general_options_box.setVisible(False) button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal") button = gui.button(button_box, self, "Run Shadow/Source", callback=self.runShadowSource) font = QFont(button.font()) font.setBold(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Blue')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) button = gui.button(button_box, self, "Reset Fields", callback=self.callResetSettings) font = QFont(button.font()) font.setItalic(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Red')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) button.setFixedWidth(150) gui.separator(self.controlArea) def initializeTabs(self): current_tab = self.tabs.currentIndex() enabled = self.isFootprintEnabled() size = len(self.tab) indexes = range(0, size) for index in indexes: self.tabs.removeTab(size - 1 - index) show_effective_source_size = QSettings().value( "output/show-effective-source-size", 0, int) == 1 titles = self.getTitles() if show_effective_source_size: self.tab = [ oasysgui.createTabPage(self.tabs, titles[0]), oasysgui.createTabPage(self.tabs, titles[1]), oasysgui.createTabPage(self.tabs, titles[2]), oasysgui.createTabPage(self.tabs, titles[3]), oasysgui.createTabPage(self.tabs, titles[4]), oasysgui.createTabPage(self.tabs, titles[5]), ] self.plot_canvas = [None, None, None, None, None, None] else: self.tab = [ oasysgui.createTabPage(self.tabs, titles[0]), oasysgui.createTabPage(self.tabs, titles[1]), oasysgui.createTabPage(self.tabs, titles[2]), oasysgui.createTabPage(self.tabs, titles[3]), oasysgui.createTabPage(self.tabs, titles[4]), ] self.plot_canvas = [None, None, None, None, None] for tab in self.tab: tab.setFixedHeight(self.IMAGE_HEIGHT) tab.setFixedWidth(self.IMAGE_WIDTH) self.enableFootprint(enabled) self.tabs.setCurrentIndex(min(current_tab, len(self.tab) - 1)) def isFootprintEnabled(self): return False def enableFootprint(self, enabled=False): pass def get_write_file_options(self): write_begin_file = 0 write_start_file = 0 write_end_file = 0 if self.file_to_write_out == 1: write_begin_file = 1 if self.file_to_write_out == 2: write_begin_file = 1 if sys.platform == 'linux': QMessageBox.warning( self, "Warning", "Debug Mode is not yet available for sources in Linux platforms", QMessageBox.Ok) else: write_start_file = 1 write_end_file = 1 return write_begin_file, write_start_file, write_end_file def copy_src_parameters(self): global shadow_src_to_copy shadow_src_to_copy = ShadowSource.create_src() self.populateFields(shadow_src_to_copy) shadow_src_to_copy.set_source_type(self.__class__.__name__) def paste_src_parameters(self): global shadow_src_to_copy if not shadow_src_to_copy is None: try: if "BendingMagnet" in shadow_src_to_copy.source_type and not "BendingMagnet" in str( self.__class__): raise Exception( "Paste Parameters not allowed:\nDestination Source is not a BendingMagnet" ) elif "Undulator" in shadow_src_to_copy.source_type and not "Undulator" in str( self.__class__): raise Exception( "Paste Parameters not allowed:\nDestination Source is not an Undulator" ) elif "Geometrical" in shadow_src_to_copy.source_type and not "Geometrical" in str( self.__class__): raise Exception( "Paste Parameters not allowed:\nDestination Source is not a Geometrical Source" ) elif "Wiggler" in shadow_src_to_copy.source_type and not "Wiggler" in str( self.__class__): raise Exception( "Paste Parameters not allowed:\nDestination Source is not a Wiggler" ) if QMessageBox.information( self, "Confirm Operation", "Confirm Paste Operation?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: shadow_temp_file = congruence.checkFileName( "tmp_src_buffer.dat") shadow_src_to_copy.src.write(shadow_temp_file) shadow_file, type = ShadowFile.readShadowFile( shadow_temp_file) self.deserialize(shadow_file) except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) def sendNewBeam(self, trigger): if trigger and trigger.new_object == True: if trigger.has_additional_parameter("seed_increment"): self.seed += trigger.get_additional_parameter("seed_increment") self.runShadowSource() def populateFields(self, shadow_src): pass def deserialize(self, shadow_file): pass def plot_results(self, beam_out, footprint_beam=None, progressBarValue=80): show_effective_source_size = QSettings().value( "output/show-effective-source-size", 0, int) == 1 if show_effective_source_size: if len(self.tab) == 5: self.initializeTabs() else: if len(self.tab) == 6: self.initializeTabs() super().plot_results(beam_out, footprint_beam, progressBarValue) if show_effective_source_size and not self.view_type == 2: effective_source_size_beam = beam_out.duplicate(history=False) effective_source_size_beam._beam.retrace(0) variables = self.getVariablestoPlot() titles = self.getTitles() xtitles = self.getXTitles() ytitles = self.getYTitles() xums = self.getXUM() yums = self.getYUM() if self.view_type == 1: self.plot_xy_fast(effective_source_size_beam, 100, variables[0][0], variables[0][1], plot_canvas_index=5, title=titles[0], xtitle=xtitles[0], ytitle=ytitles[0]) elif self.view_type == 0: self.plot_xy(effective_source_size_beam, 100, variables[0][0], variables[0][1], plot_canvas_index=5, title=titles[0], xtitle=xtitles[0], ytitle=ytitles[0], xum=xums[0], yum=yums[0]) def runShadowSource(self): raise NotImplementedError("This method is abstract") def getTitles(self): return [ "X,Z", "X',Z'", "X,X'", "Z,Z'", "Energy", "Effective Source Size" ]
class Source(ow_generic_element.GenericElement): maintainer = "Luca Rebuffi" maintainer_email = "lrebuffi(@at@)anl.gov" category = "Sources" keywords = ["data", "file", "load", "read"] inputs = [("Trigger", TriggerOut, "sendNewBeam")] WidgetDecorator.append_syned_input_data(inputs) outputs = [{"name":"Beam", "type":ShadowBeam, "doc":"Shadow Beam", "id":"beam"}] file_to_write_out = Setting(0) want_main_area=1 TABS_AREA_HEIGHT = 618 CONTROL_AREA_WIDTH = 405 number_of_rays=Setting(5000) seed=Setting(5676561) def __init__(self, show_automatic_box=False): super().__init__(show_automatic_box=show_automatic_box) self.runaction = widget.OWAction("Copy Source Parameters", self) self.runaction.triggered.connect(self.copy_src_parameters) self.addAction(self.runaction) self.runaction = widget.OWAction("Paste Source Parameters", self) self.runaction.triggered.connect(self.paste_src_parameters) self.addAction(self.runaction) self.runaction = widget.OWAction("Run Shadow/Source", self) self.runaction.triggered.connect(self.runShadowSource) self.addAction(self.runaction) self.general_options_box.setVisible(False) button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal") button = gui.button(button_box, self, "Run Shadow/Source", callback=self.runShadowSource) font = QFont(button.font()) font.setBold(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Blue')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) button = gui.button(button_box, self, "Reset Fields", callback=self.callResetSettings) font = QFont(button.font()) font.setItalic(True) button.setFont(font) palette = QPalette(button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('Dark Red')) button.setPalette(palette) # assign new palette button.setFixedHeight(45) button.setFixedWidth(150) gui.separator(self.controlArea) def get_write_file_options(self): write_begin_file = 0 write_start_file = 0 write_end_file = 0 if self.file_to_write_out == 1: write_begin_file = 1 if self.file_to_write_out == 2: write_begin_file = 1 if sys.platform == 'linux': QMessageBox.warning(self, "Warning", "Debug Mode is not yet available for sources in Linux platforms", QMessageBox.Ok) else: write_start_file = 1 write_end_file = 1 return write_begin_file, write_start_file, write_end_file def copy_src_parameters(self): global shadow_src_to_copy shadow_src_to_copy = ShadowSource.create_src() self.populateFields(shadow_src_to_copy) shadow_src_to_copy.set_source_type(self.__class__.__name__) def paste_src_parameters(self): global shadow_src_to_copy if not shadow_src_to_copy is None: try: if "BendingMagnet" in shadow_src_to_copy.source_type and not "BendingMagnet" in str(self.__class__): raise Exception("Paste Parameters not allowed:\nDestination Source is not a BendingMagnet") elif "Undulator" in shadow_src_to_copy.source_type and not "Undulator" in str(self.__class__): raise Exception("Paste Parameters not allowed:\nDestination Source is not an Undulator") elif "Geometrical" in shadow_src_to_copy.source_type and not "Geometrical" in str(self.__class__): raise Exception("Paste Parameters not allowed:\nDestination Source is not a Geometrical Source") elif "Wiggler" in shadow_src_to_copy.source_type and not "Wiggler" in str(self.__class__): raise Exception("Paste Parameters not allowed:\nDestination Source is not a Wiggler") if QMessageBox.information(self, "Confirm Operation", "Confirm Paste Operation?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: shadow_temp_file = congruence.checkFileName("tmp_src_buffer.dat") shadow_src_to_copy.src.write(shadow_temp_file) shadow_file, type = ShadowFile.readShadowFile(shadow_temp_file) self.deserialize(shadow_file) except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) def sendNewBeam(self, trigger): if trigger and trigger.new_object == True: if trigger.has_additional_parameter("seed_increment"): self.seed += trigger.get_additional_parameter("seed_increment") self.runShadowSource() def populateFields(self, shadow_src): pass def deserialize(self, shadow_file): pass