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 OWSRWGrating(OWSRWOpticalElement): tangential_size = Setting(1.2) sagittal_size = Setting(0.01) horizontal_position_of_mirror_center = Setting(0.0) vertical_position_of_mirror_center = Setting(0.0) add_acceptance_slit = Setting(0) has_height_profile = Setting(0) height_profile_data_file = Setting("mirror.dat") height_profile_data_file_dimension = Setting(0) height_amplification_coefficient = Setting(1.0) diffraction_order = Setting(1) grooving_density_0 = Setting( 800.0 ) # groove density [lines/mm] (coefficient a0 in the polynomial groove density: a0 + a1*y + a2*y^2 + a3*y^3 + a4*y^4) grooving_density_1 = Setting( 0.0) # groove density polynomial coefficient a1 [lines/mm\u00b2] grooving_density_2 = Setting( 0.0) # groove density polynomial coefficient a2 [lines/mm\u00b3] grooving_density_3 = Setting( 0.0) # groove density polynomial coefficient a3 [lines/mm\u2074] grooving_density_4 = Setting( 0.0) # groove density polynomial coefficient a4 [lines/mm\u2075] grooving_angle = Setting( 0.0 ) # angle between the groove direction and the sagittal direction of the substrate inputs = [("SRWData", SRWData, "set_input"), ("Trigger", TriggerOut, "propagate_new_wavefront"), ("PreProcessor Data", SRWPreProcessorData, "setPreProcessorData"), WidgetDecorator.syned_input_data()[0]] def __init__(self): super().__init__(azimuth_hor_vert=True) def draw_specific_box(self): tabs_grat = oasysgui.tabWidget(self.tab_bas) tab_grat = oasysgui.createTabPage(tabs_grat, "Grating") tab_errp = oasysgui.createTabPage(tabs_grat, "Error Profile") self.grating_setting = oasysgui.tabWidget(tab_grat) substrate_tab = oasysgui.createTabPage(self.grating_setting, "Substrate Mirror Setting") grooving_tab = oasysgui.createTabPage(self.grating_setting, "Grooving Setting") self.substrate_box = oasysgui.widgetBox(substrate_tab, "", addSpace=False, orientation="vertical") self.grooving_box = oasysgui.widgetBox(grooving_tab, "", addSpace=False, orientation="vertical") oasysgui.lineEdit(self.substrate_box, self, "tangential_size", "Tangential Size [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.substrate_box, self, "sagittal_size", "Sagittal_Size [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.substrate_box, self, "horizontal_position_of_mirror_center", "Horizontal position of mirror center [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.substrate_box, self, "vertical_position_of_mirror_center", "Vertical position of mirror center [m]", labelWidth=260, valueType=float, orientation="horizontal") gui.comboBox(self.substrate_box, self, "add_acceptance_slit", label="Add Acceptance Slit", items=["No", "Yes"], labelWidth=300, sendSelectedValue=False, orientation="horizontal") oasysgui.lineEdit(self.grooving_box, self, "diffraction_order", "Diffraction order", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit( self.grooving_box, self, "grooving_angle", "Angle between groove direction and\nsagittal direction of the substrate [deg]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.grooving_box, self, "grooving_density_0", "Groove density [lines/mm]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.grooving_box, self, "grooving_density_1", "Groove den. poly. coeff. a1 [lines/mm\u00b2]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.grooving_box, self, "grooving_density_2", "Groove den. poly. coeff. a2 [lines/mm\u00b3]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.grooving_box, self, "grooving_density_3", "Groove den. poly. coeff. a3 [lines/mm\u2074]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.grooving_box, self, "grooving_density_4", "Groove den. poly. coeff. a4 [lines/mm\u2075]", labelWidth=260, valueType=float, orientation="horizontal") self.error_box = oasysgui.widgetBox(tab_errp, "", addSpace=False, orientation="vertical") gui.comboBox(self.error_box, self, "has_height_profile", label="Use Height Error Profile", items=["No", "Yes"], labelWidth=300, sendSelectedValue=False, orientation="horizontal", callback=self.set_HeightProfile) gui.separator(self.error_box) self.height_profile_box_1 = oasysgui.widgetBox(self.error_box, "", addSpace=False, orientation="vertical", height=110) self.height_profile_box_2 = oasysgui.widgetBox(self.error_box, "", addSpace=False, orientation="vertical", height=110) file_box = oasysgui.widgetBox(self.height_profile_box_2, "", addSpace=False, orientation="horizontal") self.le_height_profile_data_file = oasysgui.lineEdit( file_box, self, "height_profile_data_file", "Height profile data file", labelWidth=155, valueType=str, orientation="horizontal") gui.button(file_box, self, "...", callback=self.selectHeightProfileDataFile) file_box_2 = oasysgui.widgetBox(self.height_profile_box_2, "", addSpace=False, orientation="horizontal") gui.comboBox(file_box_2, self, "height_profile_data_file_dimension", label="Dimension", items=["1", "2"], labelWidth=280, sendSelectedValue=False, orientation="horizontal") gui.button(file_box_2, self, "View", callback=self.view_height_profile) oasysgui.lineEdit(self.height_profile_box_2, self, "height_amplification_coefficient", "Height Amplification Coefficient", labelWidth=260, valueType=float, orientation="horizontal") self.set_HeightProfile() def selectHeightProfileDataFile(self): self.le_height_profile_data_file.setText( oasysgui.selectFileFromDialog(self, self.height_profile_data_file, "Height profile data file")) def set_HeightProfile(self): self.height_profile_box_1.setVisible(self.has_height_profile == 0) self.height_profile_box_2.setVisible(self.has_height_profile == 1) def get_optical_element(self): grating = self.get_grating_instance() grating.tangential_size = self.tangential_size grating.sagittal_size = self.sagittal_size grating.grazing_angle = numpy.radians(90 - self.angle_radial) grating.orientation_of_reflection_plane = self.orientation_azimuthal grating.invert_tangent_component = self.invert_tangent_component == 1 grating.add_acceptance_slit = self.add_acceptance_slit == 1 grating.height_profile_data_file = self.height_profile_data_file if self.has_height_profile else None grating.height_profile_data_file_dimension = self.height_profile_data_file_dimension + 1 grating.height_amplification_coefficient = self.height_amplification_coefficient grating.diffraction_order = self.diffraction_order grating.grooving_density_0 = self.grooving_density_0 grating.grooving_density_1 = self.grooving_density_1 grating.grooving_density_2 = self.grooving_density_2 grating.grooving_density_3 = self.grooving_density_3 grating.grooving_density_4 = self.grooving_density_4 grating.grooving_angle = numpy.radians(self.grooving_angle) return grating def set_additional_parameters(self, beamline_element, propagation_parameters, beamline): grating = beamline.get_beamline_element_at(-1).get_optical_element() orientation_of_the_output_optical_axis_vector_x, \ orientation_of_the_output_optical_axis_vector_y, \ orientation_of_the_output_optical_axis_vector_z, \ orientation_of_the_horizontal_base_vector_x , \ orientation_of_the_horizontal_base_vector_y = grating.get_output_orientation_vectors(self.input_srw_data.get_srw_wavefront().get_photon_energy()) self.oe_orientation_of_the_output_optical_axis_vector_x = round( orientation_of_the_output_optical_axis_vector_x, 8) self.oe_orientation_of_the_output_optical_axis_vector_y = round( orientation_of_the_output_optical_axis_vector_y, 8) self.oe_orientation_of_the_output_optical_axis_vector_z = round( orientation_of_the_output_optical_axis_vector_z, 8) self.oe_orientation_of_the_horizontal_base_vector_x = round( orientation_of_the_horizontal_base_vector_x, 8) self.oe_orientation_of_the_horizontal_base_vector_y = round( orientation_of_the_horizontal_base_vector_y, 8) super(OWSRWGrating, self).set_additional_parameters(beamline_element, propagation_parameters, beamline) def get_grating_instance(self): raise NotImplementedError() def receive_specific_syned_data(self, optical_element): if not optical_element is None: if isinstance(optical_element, Grating): boundaries = optical_element._boundary_shape.get_boundaries() self.tangential_size = round( abs(boundaries[3] - boundaries[2]), 6) self.sagittal_size = round(abs(boundaries[1] - boundaries[0]), 6) self.vertical_position_of_mirror_center = round( 0.5 * (boundaries[3] + boundaries[2]), 6) self.horizontal_position_of_mirror_center = round( 0.5 * (boundaries[1] + boundaries[0]), 6) self.grooving_density_0 = optical_element._ruling * 1e-3 self.receive_shape_specific_syned_data(optical_element) else: raise Exception( "Syned Data not correct: Optical Element is not a Grating") else: raise Exception("Syned Data not correct: Empty Optical Element") def receive_shape_specific_syned_data(self, optical_element): raise NotImplementedError def check_data(self): super().check_data() congruence.checkStrictlyPositiveNumber(self.tangential_size, "Tangential Size") congruence.checkStrictlyPositiveNumber(self.sagittal_size, "Sagittal Size") if self.has_height_profile: congruence.checkFile(self.height_profile_data_file) congruence.checkPositiveNumber(self.diffraction_order, "Diffraction Order") congruence.checkStrictlyPositiveNumber(self.grooving_density_0, "Groove density") def setPreProcessorData(self, data): if data is not None: try: if not data.error_profile_data is None: if data.error_profile_data.error_profile_data_file != SRWErrorProfileData.NONE: self.height_profile_data_file = data.error_profile_data.error_profile_data_file self.height_profile_data_file_dimension = 1 self.has_height_profile = 1 self.set_HeightProfile() changed = False if self.sagittal_size > data.error_profile_data.error_profile_x_dim or \ self.tangential_size > data.error_profile_data.error_profile_y_dim: changed = True if changed: if QMessageBox.information( self, "Confirm Modification", "Dimensions of this O.E. must be changed in order to ensure congruence with the error profile surface, accept?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: if self.sagittal_size > data.error_profile_data.error_profile_x_dim: self.sagittal_size = data.error_profile_data.error_profile_x_dim if self.tangential_size > data.error_profile_data.error_profile_y_dim: self.tangential_size = data.error_profile_data.error_profile_y_dim QMessageBox.information( self, "QMessageBox.information()", "Dimensions of this O.E. were changed", QMessageBox.Ok) except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) def view_height_profile(self): pass try: dialog = ShowErrorProfileDialog( parent=self, file_name=self.height_profile_data_file, dimension=self.height_profile_data_file_dimension + 1) dialog.show() except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)
class OWbm(XoppyWidget, WidgetDecorator): name = "BM" id = "orange.widgets.databm" description = "Bending Magnet Spectrum" icon = "icons/xoppy_bm.png" priority = 13 category = "" keywords = ["xoppy", "bm"] inputs = WidgetDecorator.syned_input_data() TYPE_CALC = Setting(0) MACHINE_NAME = Setting("ESRF bending magnet") RB_CHOICE = Setting(0) MACHINE_R_M = Setting(25.0) BFIELD_T = Setting(0.8) BEAM_ENERGY_GEV = Setting(6.0) CURRENT_A = Setting(0.2) HOR_DIV_MRAD = Setting(1.0) VER_DIV = Setting(0) PHOT_ENERGY_MIN = Setting(100.0) PHOT_ENERGY_MAX = Setting(100000.0) NPOINTS = Setting(500) LOG_CHOICE = Setting(1) PSI_MRAD_PLOT = Setting(1.0) PSI_MIN = Setting(-1.0) PSI_MAX = Setting(1.0) PSI_NPOINTS = Setting(500) FILE_DUMP = Setting(0) def __init__(self): super().__init__(show_script_tab=True) def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 #widget index 0 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "TYPE_CALC", label=self.unitLabels()[idx], addSpace=False, items=[ 'Energy or Power spectra', 'Angular distribution (all wavelengths)', 'Angular distribution (one wavelength)', '2D flux and power (angular,energy) distribution' ], valueType=int, orientation="horizontal", callback=self.set_TYPE_CALC) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 self.id_MACHINE_NAME = box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "MACHINE_NAME", label=self.unitLabels()[idx], addSpace=False, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "RB_CHOICE", label=self.unitLabels()[idx], addSpace=False, items=['Magnetic Radius', 'Magnetic Field'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_MACHINE_R_M = oasysgui.lineEdit(box1, self, "MACHINE_R_M", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_BFIELD_T = oasysgui.lineEdit(box1, self, "BFIELD_T", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_BEAM_ENERGY_GEV = oasysgui.lineEdit( box1, self, "BEAM_ENERGY_GEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_CURRENT_A = oasysgui.lineEdit(box1, self, "CURRENT_A", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HOR_DIV_MRAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "VER_DIV", label=self.unitLabels()[idx], addSpace=False, items=[ 'Full (integrated in Psi)', 'At Psi=0', 'In [PsiMin,PsiMax]', 'At Psi=Psi_Min' ], valueType=int, orientation="horizontal", callback=self.set_VER_DIV, labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOT_ENERGY_MIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOT_ENERGY_MAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "LOG_CHOICE", label=self.unitLabels()[idx], addSpace=False, items=['Lin', 'Log'], valueType=int, orientation="horizontal", labelWidth=350) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PSI_MRAD_PLOT", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PSI_MIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PSI_MAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 16 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PSI_NPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 17 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "FILE_DUMP", label=self.unitLabels()[idx], addSpace=False, items=['No', 'YES (bm.spec)'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return [ 'Type of calculation', 'Machine name', 'B from:', 'Machine Radius [m]', 'Magnetic Field [T]', 'Beam energy [GeV]', 'Beam Current [A]', 'Horizontal div Theta [mrad]', 'Psi (vertical div) for energy spectra', 'Min Photon Energy [eV]', 'Max Photon Energy [eV]', 'Number of points', 'Separation between energy points', 'Max Psi[mrad] for angular plots', 'Psi min [mrad]', 'Psi max [mrad]', 'Number of Psi points', 'Dump file' ] def unitFlags(self): return [ 'True', 'True', 'True', 'self.RB_CHOICE == 0', 'self.RB_CHOICE == 1', 'True', 'True', 'True', 'self.TYPE_CALC == 0', 'True', 'True', 'True', 'self.TYPE_CALC == 0', 'True', 'self.VER_DIV >= 2', 'self.VER_DIV == 2', 'self.VER_DIV == 2', 'True' ] def set_TYPE_CALC(self): self.initializeTabs() if self.TYPE_CALC == 3: self.VER_DIV = 2 def set_VER_DIV(self): if self.TYPE_CALC == 0: self.initializeTabs() def get_help_name(self): return 'bm' def check_fields(self): if self.RB_CHOICE == 0: self.MACHINE_R_M = congruence.checkStrictlyPositiveNumber( self.MACHINE_R_M, "Magnetic Radius") else: self.BFIELD_T = congruence.checkStrictlyPositiveNumber( self.BFIELD_T, "Magnetic Field") self.BEAM_ENERGY_GEV = congruence.checkStrictlyPositiveNumber( self.BEAM_ENERGY_GEV, "Beam Energy") self.CURRENT_A = congruence.checkStrictlyPositiveNumber( self.CURRENT_A, "Beam Current") self.HOR_DIV_MRAD = congruence.checkPositiveNumber( self.HOR_DIV_MRAD, "Horizontal div Theta") self.PHOT_ENERGY_MIN = congruence.checkPositiveNumber( self.PHOT_ENERGY_MIN, "Min Photon Energy") self.PHOT_ENERGY_MAX = congruence.checkStrictlyPositiveNumber( self.PHOT_ENERGY_MAX, "Max Photon Energy") congruence.checkLessThan(self.PHOT_ENERGY_MIN, self.PHOT_ENERGY_MAX, "Min Photon Energy", "Max Photon Energy") self.NPOINTS = congruence.checkStrictlyPositiveNumber( self.NPOINTS, "Number of Energy Points") self.PSI_MRAD_PLOT = congruence.checkNumber( self.PSI_MRAD_PLOT, "Max Psi for angular plots") if self.VER_DIV == 2: self.PSI_MIN = congruence.checkNumber(self.PSI_MIN, "Min Photon Energy") self.PSI_MAX = congruence.checkNumber(self.PSI_MAX, "Max Photon Max") congruence.checkLessThan(self.PSI_MIN, self.PSI_MAX, "Psi Min", "Psi Max") elif self.VER_DIV == 3: self.PSI_MIN = congruence.checkNumber(self.PSI_MIN, "Min Photon Energy") def plot_results(self, calculated_data, progressBarValue=80): if self.TYPE_CALC != 3: super().plot_results(calculated_data, progressBarValue) self.tabs.setCurrentIndex(len(self.getTitles()) - 1) elif not self.view_type == 0: if not calculated_data is None: self.view_type_combo.setEnabled(False) data = calculated_data.get_content("xoppy_data_3D") fm = data[0] a = data[1] energy_ev = data[2] try: self.plot_data2D(fm, a, energy_ev, 0, 0, xtitle="Psi [mrad]", ytitle="Photon energy [eV]", title="Flux [photons/s/0.1%bw]") self.plot_data2D(fm * codata.e * 1e3, a, energy_ev, 1, 1, xtitle="Psi [mrad]", ytitle="Photon energy [eV]", title="Spectral power [W/eV]") 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 do_xoppy_calculation(self): a6_T, fm, a, energy_ev = xoppy_calc_bm( TYPE_CALC=self.TYPE_CALC, MACHINE_NAME=self.MACHINE_NAME, RB_CHOICE=self.RB_CHOICE, MACHINE_R_M=self.MACHINE_R_M, BFIELD_T=self.BFIELD_T, BEAM_ENERGY_GEV=self.BEAM_ENERGY_GEV, CURRENT_A=self.CURRENT_A, HOR_DIV_MRAD=self.HOR_DIV_MRAD, VER_DIV=self.VER_DIV, PHOT_ENERGY_MIN=self.PHOT_ENERGY_MIN, PHOT_ENERGY_MAX=self.PHOT_ENERGY_MAX, NPOINTS=self.NPOINTS, LOG_CHOICE=self.LOG_CHOICE, PSI_MRAD_PLOT=self.PSI_MRAD_PLOT, PSI_MIN=self.PSI_MIN, PSI_MAX=self.PSI_MAX, PSI_NPOINTS=self.PSI_NPOINTS, FILE_DUMP=self.FILE_DUMP) # write python script in standard output dict_parameters = { "TYPE_CALC": self.TYPE_CALC, "MACHINE_NAME": self.MACHINE_NAME, "RB_CHOICE": self.RB_CHOICE, "MACHINE_R_M": self.MACHINE_R_M, "BFIELD_T": self.BFIELD_T, "BEAM_ENERGY_GEV": self.BEAM_ENERGY_GEV, "CURRENT_A": self.CURRENT_A, "HOR_DIV_MRAD": self.HOR_DIV_MRAD, "VER_DIV": self.VER_DIV, "PHOT_ENERGY_MIN": self.PHOT_ENERGY_MIN, "PHOT_ENERGY_MAX": self.PHOT_ENERGY_MAX, "NPOINTS": self.NPOINTS, "LOG_CHOICE": self.LOG_CHOICE, "PSI_MRAD_PLOT": self.PSI_MRAD_PLOT, "PSI_MIN": self.PSI_MIN, "PSI_MAX": self.PSI_MAX, "PSI_NPOINTS": self.PSI_NPOINTS, "FILE_DUMP": self.FILE_DUMP, } self.xoppy_script.set_code( self.script_template().format_map(dict_parameters)) return a6_T, fm, a, energy_ev def script_template(self): return """ # # script to make the calculations (created by XOPPY:bm) # from orangecontrib.xoppy.util.xoppy_bm_wiggler import xoppy_calc_bm # TYPE_CALC: # 0: 'Energy or Power spectra' # 1: 'Angular distribution (all wavelengths)' # 2: 'Angular distribution (one wavelength)' # 3: '2D flux and power (angular,energy) distribution' # a6_T, fm, a, energy_ev = xoppy_calc_bm( TYPE_CALC={TYPE_CALC}, MACHINE_NAME="{MACHINE_NAME}", RB_CHOICE={RB_CHOICE}, MACHINE_R_M={MACHINE_R_M}, BFIELD_T={BFIELD_T}, BEAM_ENERGY_GEV={BEAM_ENERGY_GEV}, CURRENT_A={CURRENT_A}, HOR_DIV_MRAD={HOR_DIV_MRAD}, VER_DIV={VER_DIV}, PHOT_ENERGY_MIN={PHOT_ENERGY_MIN}, PHOT_ENERGY_MAX={PHOT_ENERGY_MAX}, NPOINTS={NPOINTS}, LOG_CHOICE={LOG_CHOICE}, PSI_MRAD_PLOT={PSI_MRAD_PLOT}, PSI_MIN={PSI_MIN}, PSI_MAX={PSI_MAX}, PSI_NPOINTS={PSI_NPOINTS}, FILE_DUMP=True) # writes output to bm.spec # # end script # """ def add_specific_content_to_calculated_data(self, calculated_data): calculated_data.add_content("is_log_plot", self.LOG_CHOICE) calculated_data.add_content("calculation_type", self.TYPE_CALC) calculated_data.add_content("psi", self.VER_DIV) def get_data_exchange_widget_name(self): return "BM" def extract_data_from_xoppy_output(self, calculation_output): data, fm, a, energy_ev = calculation_output calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", data) calculated_data.add_content("xoppy_data_3D", [fm, a, energy_ev]) return calculated_data def getTitles(self): if self.TYPE_CALC == 0: return [ 'E/Ec', 'Flux s-pol/Flux total', 'Flux p-pol/Flux total', 'Flux', 'Spectral Power' ] elif self.TYPE_CALC == 1: return [ "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol", "Spectral Power" ] elif self.TYPE_CALC == 2: return [ "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol", "Flux", "Spectral Power" ] elif self.TYPE_CALC == 3: return [ "2D Flux (angle,energy)", "2D Spectral Power (angle,energy)" ] def getXTitles(self): if self.TYPE_CALC == 0: return [ "Energy [eV]", "Energy [eV]", "Energy [eV]", "Energy [eV]", "Energy [eV]" ] elif self.TYPE_CALC == 1: return [ "Psi [mrad]", "Psi [mrad]", "Psi [mrad]", "Psi [mrad]", "Psi [mrad]" ] elif self.TYPE_CALC == 2: return [ "Psi [mrad]", "Psi [mrad]", "Psi [mrad]", "Psi [mrad]", "Psi [mrad]", "Psi [mrad]" ] elif self.TYPE_CALC == 3: return [] def getYTitles(self): if self.TYPE_CALC == 0: if self.VER_DIV == 0: return [ 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux [Phot/sec/0.1%bw]', 'Power [Watts/eV]' ] elif self.VER_DIV == 1: return [ 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux [Phot/sec/0.1%bw/mrad(Psi)]', 'Power[Watts/eV/mrad(Psi)]' ] elif self.VER_DIV == 2: return [ 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux [Phot/sec/0.1%bw]', 'Power [Watts/eV]' ] elif self.VER_DIV == 3: return [ 'E/Ec', 'Flux_spol/Flux_total', 'Flux_ppol/Flux_total', 'Flux [Phot/sec/0.1%bw/mrad(Psi)]', 'Power [Watts/eV/mrad(Psi)]' ] elif self.TYPE_CALC == 1: return [ "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol", "Power [Watts/mrad(Psi)]" ] elif self.TYPE_CALC == 2: return [ "Psi[rad]*Gamma", "F", "F s-pol", "F p-pol", "Flux [Phot/sec/0.1%bw/mrad(Psi)]", "Power [Watts/mrad(Psi)]" ] elif self.TYPE_CALC == 3: return [] def getVariablesToPlot(self): if self.TYPE_CALC == 0: return [(0, 2), (0, 3), (0, 4), (0, 5), (0, 6)] elif self.TYPE_CALC == 1: return [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)] elif self.TYPE_CALC == 2: return [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)] elif self.TYPE_CALC == 3: return [] def getLogPlot(self): if self.TYPE_CALC == 0: return [(True, False), (True, False), (True, False), (True, True), (True, True)] elif self.TYPE_CALC == 1: return [(False, False), (False, False), (False, False), (False, False), (False, False)] elif self.TYPE_CALC == 2: return [(False, False), (False, False), (False, False), (False, False), (False, False), (False, False)] elif self.TYPE_CALC == 3: return [] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data is None: if not data._light_source is None and isinstance( data._light_source._magnetic_structure, BendingMagnet): light_source = data._light_source self.MACHINE_NAME = light_source._name self.BEAM_ENERGY_GEV = light_source._electron_beam._energy_in_GeV self.CURRENT_A = light_source._electron_beam._current self.BFIELD_T = light_source._magnetic_structure._magnetic_field self.MACHINE_R_M = light_source._magnetic_structure._radius self.set_enabled(False) else: self.set_enabled(True) raise ValueError("Syned data not correct") else: self.set_enabled(True) def set_enabled(self, value): if value == True: self.id_MACHINE_NAME.setEnabled(True) self.id_BEAM_ENERGY_GEV.setEnabled(True) self.id_CURRENT_A.setEnabled(True) self.id_BFIELD_T.setEnabled(True) self.id_MACHINE_R_M.setEnabled(True) else: self.id_MACHINE_NAME.setEnabled(False) self.id_BEAM_ENERGY_GEV.setEnabled(False) self.id_CURRENT_A.setEnabled(False) self.id_BFIELD_T.setEnabled(False) self.id_MACHINE_R_M.setEnabled(False)
class OWxwiggler(XoppyWidget,WidgetDecorator): name = "WIGGLER" id = "orange.widgets.dataxwiggler" description = "Wiggler Spectrum (Full Emission)" icon = "icons/xoppy_xwiggler.png" priority = 9 category = "" keywords = ["xoppy", "xwiggler"] FIELD = Setting(0) NPERIODS = Setting(12) ULAMBDA = Setting(0.125) K = Setting(14.0) ENERGY = Setting(6.04) PHOT_ENERGY_MIN = Setting(100.0) PHOT_ENERGY_MAX = Setting(100100.0) NPOINTS = Setting(100) NTRAJPOINTS = Setting(101) CURRENT = Setting(200.0) FILE = Setting("?") inputs = WidgetDecorator.syned_input_data() def __init__(self): super().__init__(show_script_tab=True) def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-5) idx = -1 #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_FIELD = gui.comboBox(box1, self, "FIELD", label=self.unitLabels()[idx], addSpace=False, items=['Sinusoidal', 'B from file', 'B from harmonics'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ULAMBDA = oasysgui.lineEdit(box1, self, "ULAMBDA", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_K = oasysgui.lineEdit(box1, self, "K", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ENERGY = oasysgui.lineEdit(box1, self, "ENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOT_ENERGY_MIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOT_ENERGY_MAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NTRAJPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) self.id_CURRENT = oasysgui.lineEdit(box1, self, "CURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) file_box = oasysgui.widgetBox(box1, "", addSpace=False, orientation="horizontal", height=25) self.le_file = oasysgui.lineEdit(file_box, self, "FILE", label=self.unitLabels()[idx], addSpace=False, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) gui.button(file_box, self, "...", callback=self.selectFile) def unitLabels(self): return ['Magnetic field: ','Number of periods','Wiggler period [m]','K value','Beam energy [GeV]', 'Min Photon Energy [eV]','Max Photon Energy [eV]','Number of energy points', 'Number of traj points per period','Electron Beam Current [mA]','File/Url with Magnetic Field'] def unitFlags(self): return ['True','True','self.FIELD != 1','self.FIELD == 0','True', 'True','True','True', 'self.FIELD != 1','True','self.FIELD != 0'] def selectFile(self): self.le_file.setText(oasysgui.selectFileFromDialog(self, self.FILE, "Open B File")) def get_help_name(self): return 'wiggler' def check_fields(self): self.NPERIODS = congruence.checkStrictlyPositiveNumber(self.NPERIODS, "Number of Periods") self.ENERGY = congruence.checkStrictlyPositiveNumber(self.ENERGY, "Beam Energy") self.PHOT_ENERGY_MIN = congruence.checkPositiveNumber(self.PHOT_ENERGY_MIN, "Min Photon Energy") self.PHOT_ENERGY_MAX = congruence.checkStrictlyPositiveNumber(self.PHOT_ENERGY_MAX, "Max Photon Energy") congruence.checkLessThan(self.PHOT_ENERGY_MIN, self.PHOT_ENERGY_MAX, "Min Photon Energy", "Max Photon Energy") self.NPOINTS = congruence.checkStrictlyPositiveNumber(self.NPOINTS, "Number of Energy Points") self.CURRENT = congruence.checkStrictlyPositiveNumber(self.CURRENT, "Electron Beam Current") if self.FIELD == 0: self.ULAMBDA = congruence.checkStrictlyPositiveNumber(self.ULAMBDA, "Wiggler period") self.K = congruence.checkStrictlyPositiveNumber(self.K, "K") self.NTRAJPOINTS = congruence.checkStrictlyPositiveNumber(self.NTRAJPOINTS, "Number of traj points per period") elif self.FIELD == 1: self.ULAMBDA = congruence.checkStrictlyPositiveNumber(self.ULAMBDA, "Wiggler period") self.NTRAJPOINTS = congruence.checkStrictlyPositiveNumber(self.NTRAJPOINTS, "Number of traj points per period") congruence.checkUrl(self.FILE) elif self.FIELD == 2: congruence.checkUrl(self.FILE) def do_xoppy_calculation(self): e, f0, p0, cumulated_power = xoppy_calc_wigg( FIELD=self.FIELD, NPERIODS=self.NPERIODS, ULAMBDA=self.ULAMBDA, K=self.K, ENERGY=self.ENERGY, PHOT_ENERGY_MIN=self.PHOT_ENERGY_MIN, PHOT_ENERGY_MAX=self.PHOT_ENERGY_MAX, NPOINTS=self.NPOINTS, NTRAJPOINTS=self.NTRAJPOINTS, CURRENT=self.CURRENT, FILE=self.FILE) # write python script in standard output dict_parameters = { "FIELD" : self.FIELD, "NPERIODS" : self.NPERIODS, "ULAMBDA" : self.ULAMBDA, "K" : self.K, "ENERGY" : self.ENERGY, "PHOT_ENERGY_MIN" : self.PHOT_ENERGY_MIN, "PHOT_ENERGY_MAX" : self.PHOT_ENERGY_MAX, "NPOINTS" : self.NPOINTS, "NTRAJPOINTS" : self.NTRAJPOINTS, "CURRENT" : self.CURRENT, "FILE" : self.FILE, } # print(self.script_template().format_map(dict_parameters)) # print(self.script_template().format_map(dict_parameters)) self.xoppy_script.set_code(self.script_template().format_map(dict_parameters)) return e, f0, p0 , cumulated_power def script_template(self): return """ # # script to make the calculations (created by XOPPY:wiggler) # from orangecontrib.xoppy.util.xoppy_bm_wiggler import xoppy_calc_wigg energy, flux, spectral_power, cumulated_power = xoppy_calc_wigg( FIELD={FIELD}, NPERIODS={NPERIODS}, ULAMBDA={ULAMBDA}, K={K}, ENERGY={ENERGY}, PHOT_ENERGY_MIN={PHOT_ENERGY_MIN}, PHOT_ENERGY_MAX={PHOT_ENERGY_MAX}, NPOINTS={NPOINTS}, NTRAJPOINTS={NTRAJPOINTS}, CURRENT={CURRENT}, FILE="{FILE}") # example plot from srxraylib.plot.gol import plot plot(energy,flux,ytitle="Flux [photons/s/o.1%bw]",xtitle="Poton energy [eV]",title="Wiggler Flux", xlog=True,ylog=True,show=False) plot(energy,spectral_power,ytitle="Power [W/eV]",xtitle="Poton energy [eV]",title="Wiggler Spectral Power", xlog=True,ylog=True,show=False) plot(energy,cumulated_power,ytitle="Cumulated Power [W]",xtitle="Poton energy [eV]",title="Wiggler Cumulated Power", xlog=False,ylog=False,show=True) # # end script # """ def extract_data_from_xoppy_output(self, calculation_output): e, f, sp, cumulated_power = calculation_output data = numpy.zeros((len(e), 4)) data[:,0] = numpy.array(e) data[:,1] = numpy.array(f) data[:,2] = numpy.array(sp) data[:,3] = numpy.array(cumulated_power) calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", data) return calculated_data def get_data_exchange_widget_name(self): return "XWIGGLER" def getTitles(self): return ['Flux', 'Spectral Power', 'Cumulated Power'] def getXTitles(self): return ["Energy [eV]", "Energy [eV]", "Energy [eV]"] def getYTitles(self): return ["Flux [Phot/sec/0.1%bw]", "Spectral Power [W/eV]", "Cumulated Power [W]"] def getLogPlot(self): return [(True, True), (True, True), (False, False)] def getVariablesToPlot(self): return [(0, 1), (0, 2), (0,3)] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance(data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.NPERIODS = int(light_source._magnetic_structure._number_of_periods) self.ENERGY = light_source._electron_beam._energy_in_GeV self.CURRENT = 1e3*light_source._electron_beam._current self.ULAMBDA = light_source._magnetic_structure._period_length self.K = light_source._magnetic_structure._K_vertical self.FIELD = 0 self.set_enabled(False) else: self.set_enabled(True) else: self.set_enabled(True) def set_enabled(self,value): if value == True: self.id_NPERIODS.setEnabled(True) self.id_ENERGY.setEnabled(True) self.id_CURRENT.setEnabled(True) self.id_ULAMBDA.setEnabled(True) self.id_K.setEnabled(True) self.id_FIELD.setEnabled(True) else: self.id_NPERIODS.setEnabled(False) self.id_ENERGY.setEnabled(False) self.id_CURRENT.setEnabled(False) self.id_ULAMBDA.setEnabled(False) self.id_K.setEnabled(False) self.id_FIELD.setEnabled(False)
class OWSRWMirror(OWSRWOpticalElement): tangential_size = Setting(1.2) sagittal_size = Setting(0.01) horizontal_position_of_mirror_center = Setting(0.0) vertical_position_of_mirror_center = Setting(0.0) add_acceptance_slit = Setting(0) has_height_profile = Setting(0) height_profile_data_file = Setting("mirror.dat") height_profile_data_file_dimension = Setting(0) height_amplification_coefficient = Setting(1.0) has_reflectivity = Setting(0) reflectivity_value = Setting(0.95) reflectivity_data_file = Setting("reflectivity.dat") reflectivity_energies_number = Setting(100) reflectivity_angles_number = Setting(100) reflectivity_components_number = Setting(0) reflectivity_energy_start = Setting(100.0) reflectivity_energy_end = Setting(10000.0) reflectivity_energy_scale_type = Setting(0) reflectivity_angle_start = Setting(0.001) reflectivity_angle_end = Setting(0.005) reflectivity_angle_scale_type = Setting(0) inputs = [("SRWData", SRWData, "set_input"), ("Trigger", TriggerOut, "propagate_new_wavefront"), ("PreProcessor Data #1", SRWPreProcessorData, "setPreProcessorData"), ("PreProcessor Data #2", SRWPreProcessorData, "setPreProcessorData"), WidgetDecorator.syned_input_data()[0]] def __init__(self): super().__init__(azimuth_hor_vert=True) def draw_specific_box(self): tabs_mirr = oasysgui.tabWidget(self.tab_bas) tab_mirr = oasysgui.createTabPage(tabs_mirr, "Mirror") tab_errp = oasysgui.createTabPage(tabs_mirr, "Error Profile") tab_refl = oasysgui.createTabPage(tabs_mirr, "Reflectivity") self.mirror_box = oasysgui.widgetBox(tab_mirr, "", addSpace=False, orientation="vertical") oasysgui.lineEdit(self.mirror_box, self, "tangential_size", "Tangential Size [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.mirror_box, self, "sagittal_size", "Sagittal_Size [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.mirror_box, self, "horizontal_position_of_mirror_center", "Horizontal position of mirror center [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.mirror_box, self, "vertical_position_of_mirror_center", "Vertical position of mirror center [m]", labelWidth=260, valueType=float, orientation="horizontal") gui.comboBox(self.mirror_box, self, "add_acceptance_slit", label="Add Acceptance Slit", items=["No", "Yes"], labelWidth=300, sendSelectedValue=False, orientation="horizontal") gui.separator(self.mirror_box) self.error_box = oasysgui.widgetBox(tab_errp, "", addSpace=False, orientation="vertical") gui.comboBox(self.error_box, self, "has_height_profile", label="Use Height Error Profile", items=["No", "Yes"], labelWidth=300, sendSelectedValue=False, orientation="horizontal", callback=self.set_HeightProfile) gui.separator(self.error_box) self.height_profile_box_1 = oasysgui.widgetBox(self.error_box, "", addSpace=False, orientation="vertical", height=110) self.height_profile_box_2 = oasysgui.widgetBox(self.error_box, "", addSpace=False, orientation="vertical", height=110) file_box = oasysgui.widgetBox(self.height_profile_box_2, "", addSpace=False, orientation="horizontal") self.le_height_profile_data_file = oasysgui.lineEdit(file_box, self, "height_profile_data_file", "Height profile data file", labelWidth=155, valueType=str, orientation="horizontal") gui.button(file_box, self, "...", callback=self.selectHeightProfileDataFile) file_box_2 = oasysgui.widgetBox(self.height_profile_box_2, "", addSpace=False, orientation="horizontal") gui.comboBox(file_box_2, self, "height_profile_data_file_dimension", label="Dimension", items=["1", "2"], labelWidth=280, sendSelectedValue=False, orientation="horizontal") gui.button(file_box_2, self, "View", callback=self.view_height_profile) oasysgui.lineEdit(self.height_profile_box_2, self, "height_amplification_coefficient", "Height Amplification Coefficient", labelWidth=260, valueType=float, orientation="horizontal") self.set_HeightProfile() self.reflectivity_box = oasysgui.widgetBox(tab_refl, "", addSpace=False, orientation="vertical") gui.comboBox(self.reflectivity_box, self, "has_reflectivity", label="Use Reflectivity", items=["No", "Single Value", "R vs E vs \u03b1 (vs \u03c3/\u03c0)"], labelWidth=200, sendSelectedValue=False, orientation="horizontal", callback=self.set_Reflectivity) gui.separator(self.reflectivity_box) self.reflectivity_box_1 = oasysgui.widgetBox(self.reflectivity_box, "", addSpace=False, orientation="vertical", height=200) self.reflectivity_box_2 = oasysgui.widgetBox(self.reflectivity_box, "", addSpace=False, orientation="vertical", height=200) oasysgui.lineEdit(self.reflectivity_box_2, self, "reflectivity_value", "Reflectivity Value", labelWidth=260, valueType=float, orientation="horizontal") self.reflectivity_box_3 = oasysgui.widgetBox(self.reflectivity_box, "", addSpace=False, orientation="vertical", height=270) file_box = oasysgui.widgetBox(self.reflectivity_box_3, "", addSpace=False, orientation="horizontal") self.le_reflectivity_data_file = oasysgui.lineEdit(file_box, self, "reflectivity_data_file", "Reflectivity data file", labelWidth=185, valueType=str, orientation="horizontal") gui.button(file_box, self, "...", callback=self.selectReflectivityDataFile) gui.separator(self.reflectivity_box_3) oasysgui.lineEdit(self.reflectivity_box_3, self, "reflectivity_energies_number", "Number of Energy Values", labelWidth=260, valueType=int, orientation="horizontal") energy_box = oasysgui.widgetBox(self.reflectivity_box_3, "", addSpace=False, orientation="horizontal") oasysgui.lineEdit(energy_box, self, "reflectivity_energy_start", "Energy Values [eV]: Initial", labelWidth=160, valueType=float, orientation="horizontal") oasysgui.lineEdit(energy_box, self, "reflectivity_energy_end", "Final", labelWidth=50, valueType=float, orientation="horizontal") gui.comboBox(self.reflectivity_box_3, self, "reflectivity_energy_scale_type", label="Energy Scale Type", items=["Linear", "Logarithmic"], labelWidth=250, sendSelectedValue=False, orientation="horizontal") gui.separator(self.reflectivity_box_3) oasysgui.lineEdit(self.reflectivity_box_3, self, "reflectivity_angles_number", "Number of Grazing Angle Values", labelWidth=260, valueType=int, orientation="horizontal") angle_box = oasysgui.widgetBox(self.reflectivity_box_3, "", addSpace=False, orientation="horizontal") oasysgui.lineEdit(angle_box, self, "reflectivity_angle_start", "Gr. Ang. Values [rad]: Initial", labelWidth=170, valueType=float, orientation="horizontal") oasysgui.lineEdit(angle_box, self, "reflectivity_angle_end", "Final", labelWidth=40, valueType=float, orientation="horizontal") gui.comboBox(self.reflectivity_box_3, self, "reflectivity_angle_scale_type", label="Grazing Angle Scale Type", items=["Linear", "Logarithmic"], labelWidth=250, sendSelectedValue=False, orientation="horizontal") gui.separator(self.reflectivity_box_3) gui.comboBox(self.reflectivity_box_3, self, "reflectivity_components_number", label="Polarization", items=["Total", "\u03c3/\u03c0"], labelWidth=280, sendSelectedValue=False, orientation="horizontal") self.set_Reflectivity() def selectHeightProfileDataFile(self): self.le_height_profile_data_file.setText(oasysgui.selectFileFromDialog(self, self.height_profile_data_file, "Height profile data file")) def selectReflectivityDataFile(self): self.le_reflectivity_data_file.setText(oasysgui.selectFileFromDialog(self, self.reflectivity_data_file, "Reflectivity data file")) def set_HeightProfile(self): self.height_profile_box_1.setVisible(self.has_height_profile==0) self.height_profile_box_2.setVisible(self.has_height_profile==1) def set_Reflectivity(self): self.reflectivity_box_1.setVisible(self.has_reflectivity==0) self.reflectivity_box_2.setVisible(self.has_reflectivity==1) self.reflectivity_box_3.setVisible(self.has_reflectivity==2) def get_optical_element(self): mirror = self.get_mirror_instance() mirror.tangential_size=self.tangential_size mirror.sagittal_size=self.sagittal_size mirror.grazing_angle=numpy.radians(90-self.angle_radial) mirror.orientation_of_reflection_plane=self.orientation_azimuthal mirror.invert_tangent_component = self.invert_tangent_component == 1 mirror.add_acceptance_slit=self.add_acceptance_slit == 1 mirror.height_profile_data_file=self.height_profile_data_file if self.has_height_profile else None mirror.height_profile_data_file_dimension=self.height_profile_data_file_dimension + 1 mirror.height_amplification_coefficient=self.height_amplification_coefficient if self.has_reflectivity == 1: mirror.set_reflectivity(reflectivity_data=self.reflectivity_value) elif self.has_reflectivity == 2: mirror.set_reflectivity(reflectivity_data=self.read_reflectivity_data_file(), energies_number=self.reflectivity_energies_number, angles_number=self.reflectivity_angles_number, components_number=self.reflectivity_components_number + 1, energy_start=self.reflectivity_energy_start, energy_end=self.reflectivity_energy_end, energy_scale_type=ScaleType.LINEAR if self.reflectivity_energy_scale_type==0 else ScaleType.LOGARITHMIC, angle_start=self.reflectivity_angle_start, angle_end=self.reflectivity_angle_end, angle_scale_type=ScaleType.LINEAR if self.reflectivity_angle_scale_type==0 else ScaleType.LOGARITHMIC) return mirror def read_reflectivity_data_file(self): return numpy.loadtxt(self.reflectivity_data_file).tolist() def get_mirror_instance(self): raise NotImplementedError() def receive_specific_syned_data(self, optical_element): if not optical_element is None: if isinstance(optical_element, Mirror): boundaries = optical_element._boundary_shape.get_boundaries() self.tangential_size=round(abs(boundaries[3] - boundaries[2]), 6) self.sagittal_size=round(abs(boundaries[1] - boundaries[0]), 6) self.vertical_position_of_mirror_center = round(0.5*(boundaries[3] + boundaries[2]), 6) self.horizontal_position_of_mirror_center = round(0.5*(boundaries[1] + boundaries[0]), 6) self.receive_shape_specific_syned_data(optical_element) else: raise Exception("Syned Data not correct: Optical Element is not a Mirror") else: raise Exception("Syned Data not correct: Empty Optical Element") def receive_shape_specific_syned_data(self, optical_element): raise NotImplementedError def check_data(self): super().check_data() congruence.checkStrictlyPositiveNumber(self.tangential_size, "Tangential Size") congruence.checkStrictlyPositiveNumber(self.sagittal_size, "Sagittal Size") if self.has_height_profile: congruence.checkFile(self.height_profile_data_file) if self.has_reflectivity == 1: congruence.checkStrictlyPositiveNumber(self.reflectivity_value, "Reflectivity Value") elif self.has_reflectivity == 2: congruence.checkFile(self.reflectivity_data_file) congruence.checkStrictlyPositiveNumber(self.reflectivity_energies_number, "Number of Energy Values") congruence.checkStrictlyPositiveNumber(self.reflectivity_energy_start, "Initial Energy Value") congruence.checkStrictlyPositiveNumber(self.reflectivity_energy_end, "Final Energy Value") congruence.checkGreaterOrEqualThan(self.reflectivity_energy_end, self.reflectivity_energy_start, "Final Energy Value", "Initial Energy Value") congruence.checkStrictlyPositiveNumber(self.reflectivity_angles_number, "Number of Grazing Angle Values") congruence.checkStrictlyPositiveNumber(self.reflectivity_angle_start, "Initial Grazing Angle Value") congruence.checkStrictlyPositiveNumber(self.reflectivity_angle_end, "Final Grazing Angle Value") congruence.checkGreaterOrEqualThan(self.reflectivity_angle_end, self.reflectivity_angle_start, "Final Grazing Angle Value", "Initial Grazing Angle Value") def setPreProcessorData(self, data): if data is not None: try: if not data.error_profile_data is None: if data.error_profile_data.error_profile_data_file != SRWErrorProfileData.NONE: self.height_profile_data_file = data.error_profile_data.error_profile_data_file self.height_profile_data_file_dimension = 1 self.has_height_profile = 1 self.set_HeightProfile() changed = False if self.sagittal_size > data.error_profile_data.error_profile_x_dim or \ self.tangential_size > data.error_profile_data.error_profile_y_dim: changed = True if changed: if QMessageBox.information(self, "Confirm Modification", "Dimensions of this O.E. must be changed in order to ensure congruence with the error profile surface, accept?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: if self.sagittal_size > data.error_profile_data.error_profile_x_dim: self.sagittal_size = data.error_profile_data.error_profile_x_dim if self.tangential_size > data.error_profile_data.error_profile_y_dim: self.tangential_size = data.error_profile_data.error_profile_y_dim QMessageBox.information(self, "QMessageBox.information()", "Dimensions of this O.E. were changed", QMessageBox.Ok) if not data.reflectivity_data is None: if data.reflectivity_data.reflectivity_data_file != SRWReflectivityData.NONE: self.has_reflectivity=2 self.reflectivity_data_file=data.reflectivity_data.reflectivity_data_file self.reflectivity_energies_number=data.reflectivity_data.energies_number self.reflectivity_angles_number=data.reflectivity_data.angles_number self.reflectivity_components_number=data.reflectivity_data.components_number-1 self.reflectivity_energy_start=data.reflectivity_data.energy_start self.reflectivity_energy_end=data.reflectivity_data.energy_end self.reflectivity_energy_scale_type=0 if data.reflectivity_data.energy_scale_type==ScaleType.LINEAR else 1 self.reflectivity_angle_start=data.reflectivity_data.angle_start self.reflectivity_angle_end=data.reflectivity_data.angle_end self.reflectivity_angle_scale_type=0 if data.reflectivity_data.angle_scale_type==ScaleType.LINEAR else 1 self.set_Reflectivity() except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) def view_height_profile(self): pass try: dialog = ShowErrorProfileDialog(parent=self, file_name=self.height_profile_data_file, dimension=self.height_profile_data_file_dimension+1) dialog.show() except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok)
class OWtc_slit(XoppyWidget): name = "TC-SLIT" id = "orange.widgets.data_tc_slit" description = "Undulator Tuning Curves (Flux on a slit)" icon = "icons/xoppy_xtc.png" priority = 6 category = "" keywords = ["xoppy", "tc_slit"] USEEMITTANCES = Setting(1) ELECTRONENERGY = Setting(6.037) ELECTRONENERGYSPREAD = Setting(0.001) ELECTRONCURRENT = Setting(0.2) ELECTRONBEAMSIZEH = Setting(4.99e-05) ELECTRONBEAMSIZEV = Setting(3.45e-06) ELECTRONBEAMDIVERGENCEH = Setting(0.000107) ELECTRONBEAMDIVERGENCEV = Setting(1.16e-06) PERIODID = Setting(0.042) NPERIODS = Setting(38) DISTANCE = Setting(26.0) GAPH = Setting(0.00258) GAPV = Setting(0.00195) KMIN = Setting(0.001) KMAX = Setting(3.0) KPOINTS = Setting(10) HARMONICS = Setting("1") # sequence of harmonics, separated by "," METHOD = Setting(2) inputs = WidgetDecorator.syned_input_data() def __init__(self): super().__init__(show_script_tab=True) def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 # # # idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "USEEMITTANCES", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGY = oasysgui.lineEdit( box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit( box1, self, "ELECTRONENERGYSPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit( box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "KMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) self.id_KMAX = oasysgui.lineEdit(box1, self, "KMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "KPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) # TODO: add validator oasysgui.lineEdit(box1, self, "HARMONICS", label=self.unitLabels()[idx], addSpace=False, valueType=str, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 16 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['US', 'URGENT', 'SRW'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return [ "Use emittances", "Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]", "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", "Period ID [m]", "Number of periods", "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]", "K Min", "K Max", "Number of K Points", "harmonics (e.g: 1,3)", "calculation code" ] def unitFlags(self): return [ "True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1", "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True", "True", "True", "True", "True", "True", "True", "True", "True", "True" ] def get_help_name(self): return 'tc_slit' def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber( self.ELECTRONENERGY, "Electron Energy") if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber( self.ELECTRONENERGYSPREAD, "Electron Energy Spread") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber( self.ELECTRONCURRENT, "Electron Current") self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEH, "Electron Beam Size H") self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEV, "Electron Beam Size V") self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H") self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V") self.PERIODID = congruence.checkStrictlyPositiveNumber( self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber( self.NPERIODS, "Number of Periods") self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit") self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H") self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V") self.KMIN = congruence.checkPositiveNumber(self.KMIN, "K Min") self.KMAX = congruence.checkStrictlyPositiveNumber(self.KMAX, "K Max") congruence.checkLessThan(self.KMIN, self.KMAX, "K Min", "K Max") self.KPOINTS = congruence.checkStrictlyPositiveNumber( self.KPOINTS, "Number of K Points") # self.HARMONICS = congruence.checkStrictlyPositiveNumber(self.HARMONIX, "Higher harmonic") def do_xoppy_calculation(self): return self.xoppy_calc_tc_slit() def extract_data_from_xoppy_output(self, calculation_output): K_scan, harmonics, P_scan, energy_values_at_flux_peak, flux_values = calculation_output harmonics_data = [] for ih in range(len(harmonics)): harmonic_number = int(harmonics[ih]) harmonics_data.append([harmonic_number, None]) data = numpy.zeros((K_scan.size, 5)) data[:, 0] = numpy.array(energy_values_at_flux_peak[:, ih]) data[:, 1] = numpy.array(flux_values[:, ih]) data[:, 2] = numpy.array(flux_values[:, ih]) * codata.e * 1e3 data[:, 3] = numpy.array(K_scan) data[:, 4] = numpy.array(P_scan) harmonics_data[ih][1] = data #send exchange calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) try: calculated_data.add_content("xoppy_data_harmonics", harmonics_data) calculated_data.add_content("plot_x_col", 1) calculated_data.add_content("plot_y_col", 2) except: pass try: calculated_data.add_content("labels", [ "Photon energy [eV]", "Flux [photons/s/0.1%bw]", "Ky", "Power [W]" ]) except: pass return calculated_data def plot_histo(self, x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="", log_x=False, log_y=False, harmonic=1, color='blue', control=True): h_title = "Harmonic " + str(harmonic) hex_r = hex(min(255, 128 + harmonic * 10))[2:].upper() hex_g = hex(min(255, 20 + harmonic * 15))[2:].upper() hex_b = hex(min(255, harmonic * 10))[2:].upper() if len(hex_r) == 1: hex_r = "0" + hex_r if len(hex_g) == 1: hex_g = "0" + hex_g if len(hex_b) == 1: hex_b = "0" + hex_b super().plot_histo(x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, h_title, xtitle, ytitle, log_x, log_y, color="#" + hex_r + hex_g + hex_b, replace=False, control=control) self.plot_canvas[plot_canvas_index].setGraphTitle(title) self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True) self.plot_canvas[plot_canvas_index].setDefaultPlotPoints(True) def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.view_type_combo.setEnabled(False) xoppy_data_harmonics = calculated_data.get_content( "xoppy_data_harmonics") 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] if not self.plot_canvas[index] is None: self.plot_canvas[index].clear() try: for h_index in range(0, len(xoppy_data_harmonics)): self.plot_histo( xoppy_data_harmonics[h_index][1][:, x_index], xoppy_data_harmonics[h_index][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, harmonic=xoppy_data_harmonics[h_index][0], control=True) self.plot_canvas[index].addCurve( numpy.zeros(1), numpy.array([ max(xoppy_data_harmonics[h_index][1][:, y_index]) ]), "Click on curve to highlight it", xlabel=xtitles[index], ylabel=ytitles[index], symbol='', color='white') 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) self.tabs.setCurrentIndex(0) else: raise Exception("Empty Data") def plot_histo(self, x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="", log_x=False, log_y=False, harmonic=1, color='blue', control=True): h_title = "Harmonic " + str(harmonic) hex_r = hex(min(255, 128 + harmonic * 10))[2:].upper() hex_g = hex(min(255, 20 + harmonic * 15))[2:].upper() hex_b = hex(min(255, harmonic * 10))[2:].upper() if len(hex_r) == 1: hex_r = "0" + hex_r if len(hex_g) == 1: hex_g = "0" + hex_g if len(hex_b) == 1: hex_b = "0" + hex_b super().plot_histo(x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, h_title, xtitle, ytitle, log_x, log_y, color="#" + hex_r + hex_g + hex_b, replace=False, control=control) self.plot_canvas[plot_canvas_index].setGraphTitle(title) self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True) self.plot_canvas[plot_canvas_index].setDefaultPlotPoints(True) def get_data_exchange_widget_name(self): return "TC_SLIT" def getTitles(self): return [ "Flux on slit", "Spectral power on slit", "Kv", "Total power on slit" ] def getXTitles(self): return ["Energy (eV)", "Energy (eV)", "Energy (eV)", "Kv"] def getYTitles(self): return [ "Flux (photons/s/0.1%bw)", "Spectral power (W/eV)", "Kv", "Total power (W)" ] def getVariablesToPlot(self): return [(0, 1), (0, 2), (0, 3), (3, 4)] def getLogPlot(self): return [(False, False), (False, False), (False, False), (False, False)] def xoppy_calc_tc_slit(self): bl = OrderedDict() bl['ElectronBeamDivergenceH'] = self.ELECTRONBEAMDIVERGENCEH bl['ElectronBeamDivergenceV'] = self.ELECTRONBEAMDIVERGENCEV bl['ElectronBeamSizeH'] = self.ELECTRONBEAMSIZEH bl['ElectronBeamSizeV'] = self.ELECTRONBEAMSIZEV bl['ElectronCurrent'] = self.ELECTRONCURRENT bl['ElectronEnergy'] = self.ELECTRONENERGY bl['ElectronEnergySpread'] = self.ELECTRONENERGYSPREAD bl['NPeriods'] = self.NPERIODS bl['PeriodID'] = self.PERIODID bl['distance'] = self.DISTANCE bl['gapH'] = self.GAPH bl['gapV'] = self.GAPV bl['gapHcenter'] = 0.0 bl['gapVcenter'] = 0.0 if self.USEEMITTANCES: zero_emittance = False else: zero_emittance = True if self.METHOD == 0: code = "us" if self.METHOD == 1: code = "urgent" if self.METHOD == 2: code = "srw" harmonics = str(self.HARMONICS).split(",") #[] # for i in range(self.HARMONICS+1): # if i % 2 != 0: harmonics.append(i) K_scan, harmonics, power_array, energy_values_at_flux_peak, flux_values = srundplug.tuning_curves_on_slit( bl, Kmin=self.KMIN, Kmax=self.KMAX, Kpoints=self.KPOINTS, harmonics=harmonics, zero_emittance=zero_emittance, do_plot_peaks=False, code=code) if zero_emittance: print("\nNo emittance calculation") print("Done") # write python script in standard output dict_parameters = { 'ElectronBeamDivergenceH': self.ELECTRONBEAMDIVERGENCEH, 'ElectronBeamDivergenceV': self.ELECTRONBEAMDIVERGENCEV, 'ElectronBeamSizeH': self.ELECTRONBEAMSIZEH, 'ElectronBeamSizeV': self.ELECTRONBEAMSIZEV, 'ElectronCurrent': self.ELECTRONCURRENT, 'ElectronEnergy': self.ELECTRONENERGY, 'ElectronEnergySpread': self.ELECTRONENERGYSPREAD, 'NPeriods': self.NPERIODS, 'PeriodID': self.PERIODID, 'distance': self.DISTANCE, 'gapH': self.GAPH, 'gapV': self.GAPV, 'gapHcenter': 0.0, 'gapVcenter': 0.0, 'HARMONICS': self.HARMONICS, 'Kmin': self.KMIN, 'Kmax': self.KMAX, 'Kpoints': self.KPOINTS, 'harmonics': harmonics, 'zero_emittance': zero_emittance, 'do_plot_peaks': False, 'code': code, } self.xoppy_script.set_code( self.script_template().format_map(dict_parameters)) return K_scan, harmonics, power_array, energy_values_at_flux_peak, flux_values def script_template(self): return """ # # script to make the calculations (created by XOPPY:tc_slit) # from collections import OrderedDict from orangecontrib.xoppy.util import srundplug bl = OrderedDict() bl['ElectronBeamDivergenceH'] = {ElectronBeamDivergenceH} bl['ElectronBeamDivergenceV'] = {ElectronBeamDivergenceV} bl['ElectronBeamSizeH'] = {ElectronBeamSizeH} bl['ElectronBeamSizeV'] = {ElectronBeamSizeV} bl['ElectronCurrent'] = {ElectronCurrent} bl['ElectronEnergy'] = {ElectronEnergy} bl['ElectronEnergySpread'] = {ElectronEnergySpread} bl['NPeriods'] = {NPeriods} bl['PeriodID'] = {PeriodID} bl['distance'] = {distance} bl['gapH'] = {gapH} bl['gapV'] = {gapV} bl['gapHcenter'] = 0.0 bl['gapVcenter'] = 0.0 harmonics = "{HARMONICS}".split(",") K_scan,harmonics,power_array, energy_values_at_flux_peak,flux_values = srundplug.tuning_curves_on_slit(bl, Kmin={Kmin}, Kmax={Kmax}, Kpoints={Kpoints}, harmonics=harmonics, zero_emittance={zero_emittance}, do_plot_peaks={do_plot_peaks}, code="{code}") from srxraylib.plot.gol import plot plot(energy_values_at_flux_peak,flux_values,xtitle="Photon energy [eV]",ytitle="Flux on slit [photons/s/0.1%bw]") # # end script # """ def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread self.ELECTRONCURRENT = light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.ELECTRONBEAMSIZEH = x self.ELECTRONBEAMSIZEV = y self.ELECTRONBEAMDIVERGENCEH = xp self.ELECTRONBEAMDIVERGENCEV = yp self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = light_source._magnetic_structure._number_of_periods self.KMAX = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self, value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONENERGYSPREAD.setEnabled(True) self.id_ELECTRONBEAMSIZEH.setEnabled(True) self.id_ELECTRONBEAMSIZEV.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KMAX.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONENERGYSPREAD.setEnabled(False) self.id_ELECTRONBEAMSIZEH.setEnabled(False) self.id_ELECTRONBEAMSIZEV.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KMAX.setEnabled(False)
class OWtcap(XoppyWidget): name = "Aperture Flux TC" id = "orange.widgets.datatcap" description = "On-axis Aperture Flux Undulator Tuning Curves" icon = "icons/xoppy_xtc.png" priority = 8 category = "" keywords = ["xoppy", "tcap"] #25 variables (minus one: TITLE removed) ENERGY = Setting(6.0) CURRENT = Setting(200.0) ENERGY_SPREAD = Setting(0.00138) SIGX = Setting(0.0148) SIGY = Setting(0.0037) SIGX1 = Setting(0.0029) SIGY1 = Setting(0.0015) PERIOD = Setting(2.8) NP = Setting(84) EMIN = Setting(3217.0) EMAX = Setting(11975.0) N = Setting(50) DISTANCE = Setting(30.0) XPS = Setting(1.0) YPS = Setting(1.0) XPC = Setting(0.0) YPC = Setting(0.0) HARMONIC_FROM = Setting(1) HARMONIC_TO = Setting(7) HARMONIC_STEP = Setting(2) HRED = Setting(0) HELICAL = Setting(0) NEKS = Setting(100) METHOD = Setting(0) BSL = Setting(0) inputs = WidgetDecorator.syned_input_data() def build_gui(self): self.IMAGE_WIDTH = 850 tabs_setting = oasysgui.tabWidget(self.controlArea) tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH-5) tab_1 = oasysgui.createTabPage(tabs_setting, self.name + " Input Parameters") tab_2 = oasysgui.createTabPage(tabs_setting, "Undulator Setting") box = oasysgui.widgetBox(tab_1, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-15) idx = -1 #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ENERGY = oasysgui.lineEdit(box1, self, "ENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_CURRENT = oasysgui.lineEdit(box1, self, "CURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ENERGY_SPREAD = oasysgui.lineEdit(box1, self, "ENERGY_SPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_SIGX = oasysgui.lineEdit(box1, self, "SIGX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_SIGY = oasysgui.lineEdit(box1, self, "SIGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_SIGX1 = oasysgui.lineEdit(box1, self, "SIGX1", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_SIGY1 = oasysgui.lineEdit(box1, self, "SIGY1", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_PERIOD = oasysgui.lineEdit(box1, self, "PERIOD", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_NP = oasysgui.lineEdit(box1, self, "NP", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "EMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "EMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "N", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "XPS", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "YPS", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 16 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "XPC", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 17 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "YPC", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) box = oasysgui.widgetBox(tab_2, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH-15) #widget index 18 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONIC_FROM", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 19 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONIC_TO", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 20 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONIC_STEP", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 21 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "HRED", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=350) self.show_at(self.unitFlags()[idx], box1) #widget index 22 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "HELICAL", label=self.unitLabels()[idx], addSpace=False, items=['Planar undulator', 'Helical undulator'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 23 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NEKS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 24 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['Infinite N +convolution (Dejus)','Infinite N +convolution (Dejus)','Infinite N +convolution(Walker)','Finite-N'], valueType=int, orientation="horizontal", labelWidth=150) self.show_at(self.unitFlags()[idx], box1) #widget index 25 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "BSL", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=350) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return ['Electron energy (GeV)','Current (mA)','Energy Spread (dE/E)', 'Sigma X (mm)','Sigma Y (mm)',"Sigma X' (mrad)","Sigma Y' (mrad)", 'Period length (cm)','Number of periods', 'E1 minimum energy (eV)','E1 maximum energy (eV)','Number of energy-points', 'Distance to Aperture [m]', 'Aperture Width H [mm]', 'Aperture Height V [mm]', 'Aperture Center H [mm]', 'Aperture Center V [mm]', 'Minimum harmonic number','Maximum harmonic number','Harmonic step size','Apply Harmonic Reduction', 'Mode','Neks OR % Helicity','Method','Baseline Subraction'] def unitFlags(self): return ['True' for i in range(26)] def get_help_name(self): return 'tcap' def check_fields(self): self.ENERGY = congruence.checkStrictlyPositiveNumber(self.ENERGY, "Electron Energy") self.CURRENT = congruence.checkStrictlyPositiveNumber(self.CURRENT, "Current") self.ENERGY_SPREAD = congruence.checkStrictlyPositiveNumber(self.ENERGY_SPREAD, "Energy Spread") self.SIGX = congruence.checkPositiveNumber(self.SIGX , "Sigma X") self.SIGY = congruence.checkPositiveNumber(self.SIGY , "Sigma Y") self.SIGX1 = congruence.checkPositiveNumber(self.SIGX1, "Sigma X'") self.SIGY1 = congruence.checkPositiveNumber(self.SIGY1, "Sigma Y'") self.PERIOD = congruence.checkStrictlyPositiveNumber(self.PERIOD, "Period length") self.NP = congruence.checkStrictlyPositiveNumber(self.NP, "Number of periods") self.EMIN = congruence.checkPositiveNumber(self.EMIN, "E1 minimum energy") self.EMAX = congruence.checkStrictlyPositiveNumber(self.EMAX, "E1 maximum energy") congruence.checkLessThan(self.EMIN, self.EMAX, "E1 minimum energy", "E1 maximum energy") self.N = congruence.checkStrictlyPositiveNumber(self.N, "Number of Energy Points") self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit") self.XPS = congruence.checkPositiveNumber(self.XPS, "Aperture Width H") self.YPS = congruence.checkPositiveNumber(self.YPS, "Aperture Height V") self.XPC = congruence.checkPositiveNumber(self.XPC, "Aperture Center H") self.YPC = congruence.checkPositiveNumber(self.YPC, "Aperture Center V") self.HARMONIC_FROM = congruence.checkStrictlyPositiveNumber(self.HARMONIC_FROM, "Minimum harmonic number") self.HARMONIC_TO = congruence.checkStrictlyPositiveNumber(self.HARMONIC_TO, "Maximum harmonic number") congruence.checkLessThan(self.HARMONIC_FROM, self.HARMONIC_TO, "Minimum harmonic number", "Maximum harmonic number") self.HARMONIC_STEP = congruence.checkStrictlyPositiveNumber(self.HARMONIC_STEP, "Harmonic step size") self.NEKS = congruence.checkStrictlyPositiveNumber(self.NEKS, "Neks OR % Helicity") def do_xoppy_calculation(self): return self.xoppy_calc_xtcap() def extract_data_from_xoppy_output(self, calculation_output): return calculation_output def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.view_type_combo.setEnabled(False) xoppy_data_harmonics = calculated_data.get_content("xoppy_data_harmonics") 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] if not self.plot_canvas[index] is None: self.plot_canvas[index].clear() try: for h_index in range(0, len(xoppy_data_harmonics)): self.plot_histo(xoppy_data_harmonics[h_index][1][:, x_index], xoppy_data_harmonics[h_index][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, harmonic=xoppy_data_harmonics[h_index][0], control=True) self.plot_canvas[index].addCurve(numpy.zeros(1), numpy.array([max(xoppy_data_harmonics[h_index][1][:, y_index])]), "Click on curve to highlight it", xlabel=xtitles[index], ylabel=ytitles[index], symbol='', color='white') self.plot_canvas[index].setActiveCurve("Click on curve to highlight it") self.plot_canvas[index].getLegendsDockWidget().setFixedHeight(150) self.plot_canvas[index].getLegendsDockWidget().setVisible(True) 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 plot_histo(self, x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="", log_x=False, log_y=False, harmonic=1, color='blue', control=True): h_title = "Harmonic " + str(harmonic) hex_r = hex(min(255, 128 + harmonic*10))[2:].upper() hex_g = hex(min(255, 20 + harmonic*15))[2:].upper() hex_b = hex(min(255, harmonic*10))[2:].upper() if len(hex_r) == 1: hex_r = "0" + hex_r if len(hex_g) == 1: hex_g = "0" + hex_g if len(hex_b) == 1: hex_b = "0" + hex_b #super().plot_histo(x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, h_title, xtitle, ytitle, # log_x, log_y, color="green", replace=False, control=control) super().plot_histo(x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, h_title, xtitle, ytitle, log_x, log_y, color="#" + hex_r + hex_g + hex_b, replace=False, control=control) self.plot_canvas[plot_canvas_index].setGraphTitle(title) self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True) def get_data_exchange_widget_name(self): return "XTCAP" def getTitles(self): return ["Flux peak","Ky","Total Power","Power density peak","Integrated Power on aperture"] def getXTitles(self): return ["Energy (eV)","Energy (eV)","Energy (eV)","Energy (eV)","Energy (eV)"] def getYTitles(self): return ["Flux (ph/s/mm^2/0.1%bw)","Ky","Total Power (W)","Power density (W/mm^2)","Integrated Power on Aperture (W)"] def getVariablesToPlot(self): return [(0, 1), (0, 3), (0, 4), (0, 5), (0, 6)] def getLogPlot(self): return[(False, True), (False, False), (False, False), (False, False),(False, False)] def xoppy_calc_xtcap(self): for file in ["tcap.inp","tcap.out","tcap.log"]: try: os.remove(os.path.join(locations.home_bin_run(),file)) except: pass with open("tcap.inp", "wt") as f: f.write("TCAP called from xoppy\n") f.write("%10.3f %10.2f %10.6f %s\n"%(self.ENERGY,self.CURRENT,self.ENERGY_SPREAD,"Ring-Energy(GeV) Current(mA) Beam-Energy-Spread")) f.write("%10.4f %10.4f %10.4f %10.4f %s\n"%(self.SIGX,self.SIGY,self.SIGX1,self.SIGY1,"Sx(mm) Sy(mm) Sx1(mrad) Sy1(mrad)")) f.write("%10.3f %d %s\n"%(self.PERIOD,self.NP,"Period(cm) N")) f.write("%10.1f %10.1f %d %s\n"%(self.EMIN,self.EMAX,self.N,"Emin Emax Ne")) f.write("%10.3f %10.3f %10.3f %10.3f %10.3f %d %d %s\n"%(self.DISTANCE,self.XPC,self.YPC,self.XPS,self.YPS,10,10,"d xpc ypc xps yps nxp nyp")) f.write("%d %d %d %d %s\n"%(self.HARMONIC_FROM,self.HARMONIC_TO,self.HARMONIC_STEP,self.HRED,"Hmin Hmax Hstep Hreduction")) f.write("%d %d %d %d %d %s\n"%(self.HELICAL,self.METHOD,1,self.NEKS,self.BSL,"Helical Method Print_K Neks Bsl-Subtr ")) f.write("foreground\n") if platform.system() == "Windows": command = "\"" + os.path.join(locations.home_bin(),'tcap.exe') + "\"" else: command = "'" + os.path.join(locations.home_bin(), 'tcap') + "'" print("Running command '%s' in directory: %s "%(command, locations.home_bin_run())) print("\n--------------------------------------------------------\n") # os.system(command) # # catch the optut and write the output to a log file as well as print it. # retvalue = os.popen(command).read() print(retvalue) with open("tcap.log", "wt") as f: f.write(retvalue) print("Output file: '%s/tcap.out'"%(os.getcwd()) ) print("\n--------------------------------------------------------\n") # # parse result files to exchange object # with open("tcap.out","r") as f: lines = f.readlines() # print output file # for line in lines: # print(line, end="") # remove returns lines = [line[:-1] for line in lines] harmonics_data = [] # separate numerical data from text floatlist = [] harmoniclist = [] txtlist = [] for line in lines: try: tmp = line.strip() if tmp.startswith("Harmonic"): # harmonic_number = int(tmp.split("Harmonic")[1].strip()) harmonic_number = int(tmp.split()[1]) if harmonic_number != self.HARMONIC_FROM: harmonics_data[-1][1] = harmoniclist harmoniclist = [] harmonics_data.append([harmonic_number, None]) tmp = float(line.strip()[0]) floatlist.append(line) harmoniclist.append(line) except: txtlist.append(line) harmonics_data[-1][1] = harmoniclist data = numpy.loadtxt(floatlist) for index in range(0, len(harmonics_data)): # print (harmonics_data[index][0], harmonics_data[index][1]) harmonics_data[index][1] = numpy.loadtxt(harmonics_data[index][1]) #send exchange calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name()) try: calculated_data.add_content("xoppy_data", data) calculated_data.add_content("xoppy_data_harmonics", harmonics_data) calculated_data.add_content("plot_x_col", 0) calculated_data.add_content("plot_y_col", 1) except: pass try: calculated_data.add_content("labels",["Energy(eV)","Flux(ph/s/0.1%bw)","FWHM(eV)","Ky", "Ptot(W)","Pd(W/mm^2)","IntP(W)"]) except: pass try: calculated_data.add_content("info",txtlist) except: pass return calculated_data def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data.get_light_source() is None and isinstance(data.get_light_source().get_magnetic_structure(), synedid): light_source = data.get_light_source() self.ENERGY = light_source.get_electron_beam().energy() self.ENERGY_SPREAD = light_source.get_electron_beam()._energy_spread self.CURRENT = 1000.0 * light_source.get_electron_beam().current() x, xp, y, yp = light_source.get_electron_beam().get_sigmas_all() self.SIGX = 1e3 * x self.SIGY = 1e3 * y self.SIGX1 = 1e3 * xp self.SIGY1 = 1e3 * yp self.PERIOD = 100.0 * light_source._magnetic_structure._period_length self.NP = light_source._magnetic_structure._number_of_periods self.EMIN = light_source.get_magnetic_structure().resonance_energy(gamma=light_source.get_electron_beam().gamma()) self.EMAX = 5 * self.EMIN self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self,value): if value == True: self.id_ENERGY.setEnabled(True) self.id_ENERGY_SPREAD.setEnabled(True) self.id_SIGX.setEnabled(True) self.id_SIGX1.setEnabled(True) self.id_SIGY.setEnabled(True) self.id_SIGY1.setEnabled(True) self.id_CURRENT.setEnabled(True) self.id_PERIOD.setEnabled(True) self.id_NP.setEnabled(True) else: self.id_ENERGY.setEnabled(False) self.id_ENERGY_SPREAD.setEnabled(False) self.id_SIGX.setEnabled(False) self.id_SIGX1.setEnabled(False) self.id_SIGY.setEnabled(False) self.id_SIGY1.setEnabled(False) self.id_CURRENT.setEnabled(False) self.id_PERIOD.setEnabled(False) self.id_NP.setEnabled(False)
class OWSRWCrystal(OWSRWOpticalElement): inputs = [("SRWData", SRWData, "set_input"), ("Trigger", TriggerOut, "propagate_new_wavefront"), ("ExchangeData", DataExchangeObject, "acceptExchangeData"), WidgetDecorator.syned_input_data()[0]] d_spacing = Setting(0.0) asymmetry_angle = Setting(0.0) thickness = Setting(0.0) psi_0r = Setting(0.0) psi_0i = Setting(0.0) psi_hr = Setting(0.0) psi_hi = Setting(0.0) psi_hbr = Setting(0.0) psi_hbi = Setting(0.0) diffraction_geometry = Setting(0) notes = Setting("") usage_path = os.path.join(resources.package_dirname("orangecontrib.srw.widgets.gui"), "misc", "crystal_usage.png") def __init__(self): super().__init__(azimuth_hor_vert=True) def draw_specific_box(self): self.crystal_box = oasysgui.widgetBox(self.tab_bas, "Crystal Setting", addSpace=False, orientation="vertical") oasysgui.lineEdit(self.crystal_box, self, "d_spacing", "d-spacing [Å]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.crystal_box, self, "asymmetry_angle", "Asymmetry Angle [rad]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.crystal_box, self, "thickness", "Crystal Thickness [m]", labelWidth=260, valueType=float, orientation="horizontal") polarization_box = oasysgui.widgetBox(self.crystal_box, "Crystal Polarizability", addSpace=False, orientation="horizontal") polarization_box_l = oasysgui.widgetBox(polarization_box, "", addSpace=False, orientation="vertical", width=200) polarization_box_r = oasysgui.widgetBox(polarization_box, "", addSpace=False, orientation="vartical") gui.label(polarization_box_l, self, " Real Part") oasysgui.lineEdit(polarization_box_l, self, "psi_0r" , "X0", labelWidth=50, valueType=float, orientation="horizontal") oasysgui.lineEdit(polarization_box_l, self, "psi_hr" , "Xh \u03c3", labelWidth=50, valueType=float, orientation="horizontal") oasysgui.lineEdit(polarization_box_l, self, "psi_hbr", "Xh \u03c0", labelWidth=50, valueType=float, orientation="horizontal") gui.label(polarization_box_r, self, "Imaginary Part") oasysgui.lineEdit(polarization_box_r, self, "psi_0i", "", labelWidth=50, valueType=float, orientation="horizontal") oasysgui.lineEdit(polarization_box_r, self, "psi_hi", "", labelWidth=50, valueType=float, orientation="horizontal") oasysgui.lineEdit(polarization_box_r, self, "psi_hbi", "", labelWidth=50, valueType=float, orientation="horizontal") self.notes_area = oasysgui.textArea(height=40, width=370) self.notes_area.setText(self.notes) self.crystal_box.layout().addWidget(self.notes_area) tab_usa = oasysgui.createTabPage(self.tabs_setting, "Use of the Widget") tab_usa.setStyleSheet("background-color: white;") usage_box = oasysgui.widgetBox(tab_usa, "", addSpace=True, orientation="horizontal") label = QLabel("") label.setAlignment(Qt.AlignCenter) label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) label.setPixmap(QPixmap(self.usage_path)) usage_box.layout().addWidget(label) def get_optical_element(self): return SRWCrystal(orientation_of_reflection_plane = self.orientation_azimuthal, invert_tangent_component = self.invert_tangent_component == 1, d_spacing = self.d_spacing, asymmetry_angle = self.asymmetry_angle, thickness = self.thickness, psi_0r = self.psi_0r, psi_0i = self.psi_0i, psi_hr = self.psi_hr, psi_hi = self.psi_hi, psi_hbr = self.psi_hbr, psi_hbi = self.psi_hbi, incident_angle = numpy.radians(90-self.angle_radial)) def receive_specific_syned_data(self, optical_element): if not optical_element is None: if isinstance(optical_element, Crystal): self.asymmetry_angle = optical_element._asymmetry_angle, self.thickness = optical_element._thickness, self.diffraction_geometry = optical_element._diffraction_geometry else: raise Exception("Syned Data not correct: Optical Element is not a Crystal") else: raise Exception("Syned Data not correct: Empty Optical Element") def check_data(self): super().check_data() congruence.checkStrictlyPositiveNumber(self.d_spacing, "d-spacing") def acceptExchangeData(self, exchangeData): if not exchangeData is None: try: if exchangeData.get_program_name() == "XRAYSERVER": if exchangeData.get_widget_name() == "X0H": self.notes = "Data from X-Ray Server: " + exchangeData.get_content("structure") + "(" + \ str(exchangeData.get_content("h")) + "," + str(exchangeData.get_content("k")) + "," + str(exchangeData.get_content("l")) + ")" + \ " at " + str(round(exchangeData.get_content("energy")*1000, 4)) + " eV" self.notes_area.setText(self.notes) self.angle_radial = 90 - exchangeData.get_content("bragg_angle") self.d_spacing = exchangeData.get_content("d_spacing") self.psi_0r = exchangeData.get_content("xr0") self.psi_0i = exchangeData.get_content("xi0") self.psi_hr = exchangeData.get_content("xrh_s") self.psi_hi = exchangeData.get_content("xih_s") self.psi_hbr = exchangeData.get_content("xrh_p") self.psi_hbi = exchangeData.get_content("xih_p") except Exception as e: QMessageBox.critical(self, "Error", str(e.args[0]), QMessageBox.Ok)
class OWundulator_power_density(XoppyWidget, WidgetDecorator): name = "Undulator Power Density" id = "orange.widgets.dataundulator_power_density" description = "Undulator Power Density" icon = "icons/xoppy_undulator_power_density.png" priority = 3 category = "" keywords = ["xoppy", "undulator_power_density"] USEEMITTANCES = Setting(1) ELECTRONENERGY = Setting(6.04) ELECTRONENERGYSPREAD = Setting(0.001) ELECTRONCURRENT = Setting(0.2) ELECTRONBEAMSIZEH = Setting(0.000395) ELECTRONBEAMSIZEV = Setting(9.9e-06) ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05) ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06) PERIODID = Setting(0.018) NPERIODS = Setting(222) KV = Setting(1.68) DISTANCE = Setting(30.0) GAPH = Setting(0.003) GAPV = Setting(0.003) HSLITPOINTS = Setting(41) VSLITPOINTS = Setting(41) METHOD = Setting(0) inputs = [WidgetDecorator.syned_input_data()] def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 # # # idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "USEEMITTANCES", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGY = oasysgui.lineEdit( box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit( box1, self, "ELECTRONENERGYSPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit( box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_KV = oasysgui.lineEdit(box1, self, "KV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "VSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['US', 'URGENT', 'SRW'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return [ "Use emittances", "Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]", "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", "Period ID [m]", "Number of periods", "Kv [undulator K value vertical field]", "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]", "Number of slit mesh points in H", "Number of slit mesh points in V", "calculation code" ] def unitFlags(self): return [ "True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1", "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True", "True", "True", "True", "True", "True", "True", "True", "True" ] def get_help_name(self): return 'undulator_power_density' def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber( self.ELECTRONENERGY, "Electron Energy") if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber( self.ELECTRONENERGYSPREAD, "Electron Energy Spread") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber( self.ELECTRONCURRENT, "Electron Current") self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEH, "Electron Beam Size H") self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEV, "Electron Beam Size V") self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H") self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V") self.PERIODID = congruence.checkStrictlyPositiveNumber( self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber( self.NPERIODS, "Number of Periods") self.KV = congruence.checkPositiveNumber(self.KV, "Kv") self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit") self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H") self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V") self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.HSLITPOINTS, "Number of slit mesh points in H") self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.VSLITPOINTS, "Number of slit mesh points in V") if self.METHOD == 1: # URGENT congruence.checkLessOrEqualThan( self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT ", " 51") congruence.checkLessOrEqualThan( self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT ", " 51") # if sys.platform == 'linux' and self.METHOD == 2: # raise Exception("SRW calculation code not supported under Linux") def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.initializeTabs( ) # added by srio to avoid overlapping graphs self.view_type_combo.setEnabled(False) data = calculated_data.get_content("xoppy_data") code = calculated_data.get_content("xoppy_code") h = data[0] v = data[1] p = data[2] try: print("Result arrays (shapes): ", h.shape, v.shape, p.shape) self.plot_data2D(p, h, v, 0, 0, xtitle='H [mm]', ytitle='V [mm]', title='Code ' + code + '; Power density [W/mm^2]') 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 do_xoppy_calculation(self): return xoppy_calc_undulator_power_density( ELECTRONENERGY=self.ELECTRONENERGY, ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD, ELECTRONCURRENT=self.ELECTRONCURRENT, ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH, ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV, ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH, ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV, PERIODID=self.PERIODID, NPERIODS=self.NPERIODS, KV=self.KV, DISTANCE=self.DISTANCE, GAPH=self.GAPH, GAPV=self.GAPV, HSLITPOINTS=self.HSLITPOINTS, VSLITPOINTS=self.VSLITPOINTS, METHOD=self.METHOD, USEEMITTANCES=self.USEEMITTANCES) def extract_data_from_xoppy_output(self, calculation_output): h, v, p, code = calculation_output calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", [h, v, p]) calculated_data.add_content("xoppy_code", code) return calculated_data def get_data_exchange_widget_name(self): return "UNDULATOR_POWER_DENSITY" def getTitles(self): return ['Undulator Power Density'] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread self.ELECTRONCURRENT = light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.ELECTRONBEAMSIZEH = x self.ELECTRONBEAMSIZEV = y self.ELECTRONBEAMDIVERGENCEH = xp self.ELECTRONBEAMDIVERGENCEV = yp self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = light_source._magnetic_structure._number_of_periods self.KV = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self, value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONENERGYSPREAD.setEnabled(True) self.id_ELECTRONBEAMSIZEH.setEnabled(True) self.id_ELECTRONBEAMSIZEV.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KV.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONENERGYSPREAD.setEnabled(False) self.id_ELECTRONBEAMSIZEH.setEnabled(False) self.id_ELECTRONBEAMSIZEV.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KV.setEnabled(False)
class OWundulator_spectrum(XoppyWidget, WidgetDecorator): name = "Undulator Spectrum" id = "orange.widgets.dataundulator_spectrum" description = "Undulator Spectrum" icon = "icons/xoppy_undulator_spectrum.png" priority = 1 category = "" keywords = ["xoppy", "undulator_spectrum"] USEEMITTANCES = Setting(1) ELECTRONENERGY = Setting(6.04) ELECTRONENERGYSPREAD = Setting(0.001) ELECTRONCURRENT = Setting(0.2) ELECTRONBEAMSIZEH = Setting(0.000395) ELECTRONBEAMSIZEV = Setting(9.9e-06) ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05) ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06) PERIODID = Setting(0.018) NPERIODS = Setting(222) KV = Setting(1.68) KH = Setting(0.0) KPHASE = Setting(0.0) DISTANCE = Setting(30.0) GAPH = Setting(0.001) GAPV = Setting(0.001) GAPH_CENTER = Setting(0.0) GAPV_CENTER = Setting(0.0) PHOTONENERGYMIN = Setting(3000.0) PHOTONENERGYMAX = Setting(55000.0) PHOTONENERGYPOINTS = Setting(500) METHOD = Setting(2) inputs = WidgetDecorator.syned_input_data() def __init__(self): super().__init__(show_script_tab=True) def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 # # # idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "USEEMITTANCES", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGY = oasysgui.lineEdit( box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit( box1, self, "ELECTRONENERGYSPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit( box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_KV = oasysgui.lineEdit(box1, self, "KV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9B idx += 1 box1 = gui.widgetBox(box) self.id_KH = oasysgui.lineEdit(box1, self, "KH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9C idx += 1 box1 = gui.widgetBox(box) self.id_KPHASE = oasysgui.lineEdit(box1, self, "KPHASE", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11B idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH_CENTER", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12B idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV_CENTER", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 16 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['US', 'URGENT', 'SRW'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return [ "Use emittances", "Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]", "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", "Period ID [m]", "Number of periods", "Kv [K value vertical field]", "Kh [K value horizontal field]", "Kphase [phase diff Kh - Kv in rad]", "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]", "Slit center H [m]", "Slit center V [m]", "photon Energy Min [eV]", "photon Energy Max [eV]", "photon Energy Points", "calculation code" ] def unitFlags(self): return [ "True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1", "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True", "True", "True", "self.METHOD != 0", "self.METHOD != 0", "True", "True", "True", "True", "True", "True", "True", "True", "True" ] def get_help_name(self): return 'undulator_spectrum' def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber( self.ELECTRONENERGY, "Electron Energy") if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber( self.ELECTRONENERGYSPREAD, "Electron Energy Spread") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber( self.ELECTRONCURRENT, "Electron Current") self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEH, "Electron Beam Size H") self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEV, "Electron Beam Size V") self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H") self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V") self.PERIODID = congruence.checkStrictlyPositiveNumber( self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber( self.NPERIODS, "Number of Periods") self.KV = congruence.checkPositiveNumber(self.KV, "Kv") self.KH = congruence.checkPositiveNumber(self.KH, "Kh") self.KPHASE = congruence.checkNumber(self.KPHASE, "KPHASE") self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit") self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H") self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V") self.GAPH_CENTER = congruence.checkPositiveNumber( self.GAPH_CENTER, "Slit center H") self.GAPV_CENTER = congruence.checkPositiveNumber( self.GAPV_CENTER, "Slit center V") self.PHOTONENERGYMIN = congruence.checkPositiveNumber( self.PHOTONENERGYMIN, "photon Energy Min") self.PHOTONENERGYMAX = congruence.checkStrictlyPositiveNumber( self.PHOTONENERGYMAX, "photon Energy Max") congruence.checkLessThan(self.PHOTONENERGYMIN, self.PHOTONENERGYMAX, "photon Energy Min", "photon Energy Max") self.PHOTONENERGYPOINTS = congruence.checkStrictlyPositiveNumber( self.PHOTONENERGYPOINTS, "photon Energy Points") if self.METHOD == 1: # URGENT congruence.checkLessThan(self.PHOTONENERGYPOINTS, 4701, "Number of energy points", "4701") # if sys.platform == 'linux' and self.METHOD == 2: # raise Exception("SRW calculation code not supported under Linux") def do_xoppy_calculation(self): energy, flux, spectral_power, cumulated_power = xoppy_calc_undulator_spectrum( ELECTRONENERGY=self.ELECTRONENERGY, ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD, ELECTRONCURRENT=self.ELECTRONCURRENT, ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH, ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV, ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH, ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV, PERIODID=self.PERIODID, NPERIODS=self.NPERIODS, KV=self.KV, KH=self.KH, KPHASE=self.KPHASE, DISTANCE=self.DISTANCE, GAPH=self.GAPH, GAPV=self.GAPV, GAPH_CENTER=self.GAPH_CENTER, GAPV_CENTER=self.GAPV_CENTER, PHOTONENERGYMIN=self.PHOTONENERGYMIN, PHOTONENERGYMAX=self.PHOTONENERGYMAX, PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS, METHOD=self.METHOD, USEEMITTANCES=self.USEEMITTANCES) # write python script in standard output dict_parameters = { "ELECTRONENERGY": self.ELECTRONENERGY, "ELECTRONENERGYSPREAD": self.ELECTRONENERGYSPREAD, "ELECTRONCURRENT": self.ELECTRONCURRENT, "ELECTRONBEAMSIZEH": self.ELECTRONBEAMSIZEH, "ELECTRONBEAMSIZEV": self.ELECTRONBEAMSIZEV, "ELECTRONBEAMDIVERGENCEH": self.ELECTRONBEAMDIVERGENCEH, "ELECTRONBEAMDIVERGENCEV": self.ELECTRONBEAMDIVERGENCEV, "PERIODID": self.PERIODID, "NPERIODS": self.NPERIODS, "KV": self.KV, "KH": self.KH, "KPHASE": self.KPHASE, "DISTANCE": self.DISTANCE, "GAPH": self.GAPH, "GAPV": self.GAPV, "GAPH_CENTER": self.GAPH_CENTER, "GAPV_CENTER": self.GAPV_CENTER, "PHOTONENERGYMIN": self.PHOTONENERGYMIN, "PHOTONENERGYMAX": self.PHOTONENERGYMAX, "PHOTONENERGYPOINTS": self.PHOTONENERGYPOINTS, "METHOD": self.METHOD, "USEEMITTANCES": self.USEEMITTANCES, } # print(self.script_template().format_map(dict_parameters)) self.xoppy_script.set_code( self.script_template().format_map(dict_parameters)) return energy, flux, spectral_power, cumulated_power def script_template(self): return """ # # script to make the calculations (created by XOPPY:undulator_spectrum) # from orangecontrib.xoppy.util.xoppy_undulators import xoppy_calc_undulator_spectrum energy, flux, spectral_power, cumulated_power = xoppy_calc_undulator_spectrum( ELECTRONENERGY={ELECTRONENERGY}, ELECTRONENERGYSPREAD={ELECTRONENERGYSPREAD}, ELECTRONCURRENT={ELECTRONCURRENT}, ELECTRONBEAMSIZEH={ELECTRONBEAMSIZEH}, ELECTRONBEAMSIZEV={ELECTRONBEAMSIZEV}, ELECTRONBEAMDIVERGENCEH={ELECTRONBEAMDIVERGENCEH}, ELECTRONBEAMDIVERGENCEV={ELECTRONBEAMDIVERGENCEV}, PERIODID={PERIODID}, NPERIODS={NPERIODS}, KV={KV}, KH={KH}, KPHASE={KPHASE}, DISTANCE={DISTANCE}, GAPH={GAPH}, GAPV={GAPV}, GAPH_CENTER={GAPH_CENTER}, GAPV_CENTER={GAPV_CENTER}, PHOTONENERGYMIN={PHOTONENERGYMIN}, PHOTONENERGYMAX={PHOTONENERGYMAX}, PHOTONENERGYPOINTS={PHOTONENERGYPOINTS}, METHOD={METHOD}, USEEMITTANCES={USEEMITTANCES}) # example plot from srxraylib.plot.gol import plot plot(energy,flux,ytitle="Flux [photons/s/o.1%bw]",xtitle="Poton energy [eV]",title="Undulator Flux", xlog=False,ylog=False,show=False) plot(energy,spectral_power,ytitle="Power [W/eV]",xtitle="Poton energy [eV]",title="Undulator Spectral Power", xlog=False,ylog=False,show=False) plot(energy,cumulated_power,ytitle="Cumulated Power [W]",xtitle="Poton energy [eV]",title="Undulator Cumulated Power", xlog=False,ylog=False,show=True) # # end script # """ def extract_data_from_xoppy_output(self, calculation_output): e, f, sp, csp = calculation_output data = numpy.zeros((len(e), 4)) data[:, 0] = numpy.array(e) data[:, 1] = numpy.array(f) data[:, 2] = numpy.array(sp) data[:, 3] = numpy.array(csp) calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", data) return calculated_data def get_data_exchange_widget_name(self): return "UNDULATOR_FLUX" def getTitles(self): return ['Undulator Flux', 'Spectral Power', 'Cumulated Power'] def getXTitles(self): return ["Energy [eV]", "Energy [eV]", "Energy [eV]"] def getYTitles(self): return [ "Flux [Phot/sec/0.1%bw]", "Spectral Power [W/eV]", "Cumulated Power [W]" ] def getLogPlot(self): return [(False, False), (False, False), (False, False)] def getVariablesToPlot(self): return [(0, 1), (0, 2), (0, 3)] def getDefaultPlotTabIndex(self): return 0 def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread self.ELECTRONCURRENT = light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.ELECTRONBEAMSIZEH = x self.ELECTRONBEAMSIZEV = y self.ELECTRONBEAMDIVERGENCEH = xp self.ELECTRONBEAMDIVERGENCEV = yp self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = int( light_source._magnetic_structure._number_of_periods) self.KV = light_source._magnetic_structure._K_vertical self.KH = light_source._magnetic_structure._K_horizontal # TODO self.KPHASE = light_source._magnetic_structure.... self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self, value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONENERGYSPREAD.setEnabled(True) self.id_ELECTRONBEAMSIZEH.setEnabled(True) self.id_ELECTRONBEAMSIZEV.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KV.setEnabled(True) self.id_KH.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONENERGYSPREAD.setEnabled(False) self.id_ELECTRONBEAMSIZEH.setEnabled(False) self.id_ELECTRONBEAMSIZEV.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KV.setEnabled(False) self.id_KH.setEnabled(False)
class OWundulator_radiation(XoppyWidget, WidgetDecorator): name = "Undulator Radiation" id = "orange.widgets.dataundulator_radiation" description = "Undulator Radiation" icon = "icons/xoppy_undulator_radiation.png" priority = 5 category = "" keywords = ["xoppy", "undulator_radiation"] # overwrite from outputs = [{"name": "xoppy_data", "type": DataExchangeObject, "doc": ""}] USEEMITTANCES = Setting(1) ELECTRONENERGY = Setting(6.04) ELECTRONENERGYSPREAD = Setting(0.001) ELECTRONCURRENT = Setting(0.2) ELECTRONBEAMSIZEH = Setting(0.000395) ELECTRONBEAMSIZEV = Setting(9.9e-06) ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05) ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06) PERIODID = Setting(0.018) NPERIODS = Setting(222) KV = Setting(1.68) DISTANCE = Setting(30.0) SETRESONANCE = Setting(0) HARMONICNUMBER = Setting(1) GAPH = Setting(0.003) GAPV = Setting(0.003) HSLITPOINTS = Setting(41) VSLITPOINTS = Setting(41) PHOTONENERGYMIN = Setting(6000.0) PHOTONENERGYMAX = Setting(8500.0) PHOTONENERGYPOINTS = Setting(20) METHOD = Setting(2) H5_FILE_DUMP = Setting(0) inputs = WidgetDecorator.syned_input_data() def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 # # # idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "USEEMITTANCES", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGY = oasysgui.lineEdit( box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit( box1, self, "ELECTRONENERGYSPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit( box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_KV = oasysgui.lineEdit(box1, self, "KV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) # widget <><><> idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "SETRESONANCE", label=self.unitLabels()[idx], addSpace=False, items=[ 'User defined', 'Set to resonance/central cone', 'Set to resonance/up to first ring' ], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget <><><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONICNUMBER", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "VSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['US', 'URGENT', 'SRW', 'pySRU'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 16 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "H5_FILE_DUMP", label=self.unitLabels()[idx], addSpace=False, items=[ 'None', 'Write h5 file: undulator_radiation.h5', 'Read from file...' ], valueType=int, orientation="horizontal", labelWidth=250, callback=self.read_or_write_file) self.show_at(self.unitFlags()[idx], box1) def read_or_write_file(self): value = self.H5_FILE_DUMP if value == 0: return elif value == 1: # write return elif value == 2: # read self.H5_FILE_DUMP = 0 tmp = ConfirmDialog.confirmed( self, message= "Please select in a hdf5 file a data block\n(such as XOPPY_RADIATION)\nthat contains a 'Radiation' entry", title="Confirm Action") if tmp == False: return dialog = DataFileDialog(self) dialog.setFilterMode(DataFileDialog.FilterMode.ExistingGroup) # dialog.setDirectory("") # Execute the dialog as modal result = dialog.exec_() if result: print("Selection:") print(dialog.selectedFile()) print(dialog.selectedUrl()) print(dialog.selectedDataUrl().data_path()) calculation_output = self.extract_data_from_h5file( dialog.selectedFile(), dialog.selectedDataUrl().data_path()) if calculation_output is None: raise Exception("Bad data from file.") else: self.calculated_data = self.extract_data_from_xoppy_output( calculation_output) try: self.set_fields_from_h5file( dialog.selectedFile(), dialog.selectedDataUrl().data_path()) except: pass # self.add_specific_content_to_calculated_data(self.calculated_data) # self.setStatusMessage("Plotting Results") self.plot_results(self.calculated_data, progressBarValue=60) self.setStatusMessage("") self.send("xoppy_data", self.calculated_data) self.set_enabled(True) def extract_data_from_h5file(self, file_h5, subtitle): hf = h5py.File(file_h5, 'r') try: p = hf[subtitle + "/Radiation/stack_data"].value e = hf[subtitle + "/Radiation/axis0"].value h = hf[subtitle + "/Radiation/axis1"].value v = hf[subtitle + "/Radiation/axis2"].value except: raise Exception("Data not plottable: bad content\n" + str(e)) code = "unknown" try: if hf[subtitle + "/parameters/METHOD"].value == 0: code = 'US' elif hf[subtitle + "/parameters/METHOD"].value == 1: code = 'URGENT' elif hf[subtitle + "/parameters/METHOD"].value == 2: code = 'SRW' elif hf[subtitle + "/parameters/METHOD"].value == 3: code = 'pySRU' except: pass hf.close() return e, h, v, p, code def set_fields_from_h5file(self, file_h5, subtitle): hf = h5py.File(file_h5, 'r') self.METHOD = hf[subtitle + "/parameters/METHOD"].value self.USEEMITTANCES = hf[subtitle + "/parameters/USEEMITTANCES"].value self.ELECTRONENERGY = hf[subtitle + "/parameters/ELECTRONENERGY"].value self.ELECTRONENERGYSPREAD = hf[ subtitle + "/parameters/ELECTRONENERGYSPREAD"].value self.ELECTRONCURRENT = hf[subtitle + "/parameters/ELECTRONCURRENT"].value self.ELECTRONBEAMSIZEH = hf[subtitle + "/parameters/ELECTRONBEAMSIZEH"].value self.ELECTRONBEAMSIZEV = hf[subtitle + "/parameters/ELECTRONBEAMSIZEV"].value self.ELECTRONBEAMDIVERGENCEH = hf[ subtitle + "/parameters/ELECTRONBEAMDIVERGENCEH"].value self.ELECTRONBEAMDIVERGENCEV = hf[ subtitle + "/parameters/ELECTRONBEAMDIVERGENCEV"].value self.PERIODID = hf[subtitle + "/parameters/PERIODID"].value self.NPERIODS = hf[subtitle + "/parameters/NPERIODS"].value self.KV = hf[subtitle + "/parameters/KV"].value self.DISTANCE = hf[subtitle + "/parameters/DISTANCE"].value self.SETRESONANCE = hf[subtitle + "/parameters/SETRESONANCE"].value self.HARMONICNUMBER = hf[subtitle + "/parameters/HARMONICNUMBER"].value self.GAPH = hf[subtitle + "/parameters/GAPH"].value self.GAPV = hf[subtitle + "/parameters/GAPV"].value self.HSLITPOINTS = hf[subtitle + "/parameters/HSLITPOINTS"].value self.VSLITPOINTS = hf[subtitle + "/parameters/VSLITPOINTS"].value self.PHOTONENERGYMIN = hf[subtitle + "/parameters/PHOTONENERGYMIN"].value self.PHOTONENERGYMAX = hf[subtitle + "/parameters/PHOTONENERGYMAX"].value self.PHOTONENERGYPOINTS = hf[subtitle + "/parameters/PHOTONENERGYPOINTS"].value hf.close() def unitLabels(self): return [ "Use emittances", "Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]", "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", "Period ID [m]", "Number of periods", "Kv [undulator K value vertical field]", "Distance to slit [m]", "Set photon energy and slit", "Harmonic number", "Slit gap H [m]", "Slit gap V [m]", "Number of slit mesh points in H", "Number of slit mesh points in V", "Photon Energy Min [eV]", "Photon Energy Max [eV]", "Number of Photon Energy Points", "calculation code", "hdf5 file" ] # TODO check energy spread flag: set to False (not used at all)!! def unitFlags(self): return [ "True", "True", "False", "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True", "True", "True", "True", "True", "self.SETRESONANCE > 0", "self.SETRESONANCE == 0", "self.SETRESONANCE == 0", "True", "True", "self.SETRESONANCE == 0", "self.SETRESONANCE == 0", "self.SETRESONANCE == 0", "True", "True" ] def get_help_name(self): return 'undulator_radiation' def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber( self.ELECTRONENERGY, "Electron Energy") if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber( self.ELECTRONENERGYSPREAD, "Electron Energy Spread") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber( self.ELECTRONCURRENT, "Electron Current") self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEH, "Electron Beam Size H") self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEV, "Electron Beam Size V") self.ELECTRONBEAMDIVERGENCEH = congruence.checkNumber( self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H") self.ELECTRONBEAMDIVERGENCEV = congruence.checkNumber( self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V") self.PERIODID = congruence.checkStrictlyPositiveNumber( self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber( self.NPERIODS, "Number of Periods") self.KV = congruence.checkPositiveNumber(self.KV, "Kv") self.DISTANCE = congruence.checkStrictlyPositiveNumber( self.DISTANCE, "Distance to slit") if self.SETRESONANCE == 0: self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H") self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V") self.PHOTONENERGYMIN = congruence.checkNumber( self.PHOTONENERGYMIN, "Photon Energy Min") self.PHOTONENERGYMAX = congruence.checkNumber( self.PHOTONENERGYMAX, "Photon Energy Max") congruence.checkGreaterOrEqualThan( self.PHOTONENERGYPOINTS, 2, "Number of Photon Energy Points", " 2") else: self.HARMONICNUMBER = congruence.checkStrictlyPositiveNumber( self.HARMONICNUMBER, "Harmonic number") self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.HSLITPOINTS, "Number of slit mesh points in H") self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.VSLITPOINTS, "Number of slit mesh points in V") if self.METHOD == 1: # URGENT congruence.checkLessOrEqualThan( self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT ", " 51") congruence.checkLessOrEqualThan( self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT ", " 51") def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.initializeTabs( ) # added by srio to avoid overlapping graphs self.view_type_combo.setEnabled(False) p, e, h, v = calculated_data.get_content("xoppy_data") code = calculated_data.get_content("xoppy_code") try: self.plot_data3D( p, e, h, v, 0, 0, xtitle='H [mm]', ytitle='V [mm]', title='Code ' + code + '; Flux [photons/s/0.1%bw/mm^2]', ) self.tabs.setCurrentIndex(0) except Exception as e: self.view_type_combo.setEnabled(True) raise Exception("Data not plottable: bad content\n" + str(e)) try: if len(e) > 1: energy_step = e[1] - e[0] else: energy_step = 1.0 self.plot_data2D( p.sum(axis=0) * energy_step * codata.e * 1e3, h, v, 1, 0, xtitle='H [mm]', ytitle='V [mm]', title='Code ' + code + '; Power density [W/mm^2]', ) except Exception as e: self.view_type_combo.setEnabled(True) raise Exception("Data not plottable: bad content\n" + str(e)) try: print("\nResult arrays (shapes): ", e.shape, h.shape, v.shape, p.shape) self.plot_data1D( e, p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) * (v[1] - v[0]), 2, 0, xtitle='Photon Energy [eV]', ytitle='Flux [photons/s/0.1%bw]', title='Code ' + code + '; Flux', ) except Exception as e: self.view_type_combo.setEnabled(True) raise Exception("Data not plottable: bad content\n" + str(e)) try: print("\nResult arrays (shapes): ", e.shape, h.shape, v.shape, p.shape) self.plot_data1D( e, p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) * (v[1] - v[0]) * codata.e * 1e3, 3, 0, xtitle='Photon Energy [eV]', ytitle='Spectral power [W/eV]', title='Code ' + code + '; Spectral power', ) 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 do_xoppy_calculation(self): if self.H5_FILE_DUMP == 0: h5_file = "" else: h5_file = "undulator_radiation.h5" dict_parameters = { "ELECTRONENERGY": self.ELECTRONENERGY, "ELECTRONENERGYSPREAD": self.ELECTRONENERGYSPREAD, "ELECTRONCURRENT": self.ELECTRONCURRENT, "ELECTRONBEAMSIZEH": self.ELECTRONBEAMSIZEH, "ELECTRONBEAMSIZEV": self.ELECTRONBEAMSIZEV, "ELECTRONBEAMDIVERGENCEH": self.ELECTRONBEAMDIVERGENCEH, "ELECTRONBEAMDIVERGENCEV": self.ELECTRONBEAMDIVERGENCEV, "PERIODID": self.PERIODID, "NPERIODS": self.NPERIODS, "KV": self.KV, "DISTANCE": self.DISTANCE, "SETRESONANCE": self.SETRESONANCE, "HARMONICNUMBER": self.HARMONICNUMBER, "GAPH": self.GAPH, "GAPV": self.GAPV, "HSLITPOINTS": self.HSLITPOINTS, "VSLITPOINTS": self.VSLITPOINTS, "METHOD": self.METHOD, "PHOTONENERGYMIN": self.PHOTONENERGYMIN, "PHOTONENERGYMAX": self.PHOTONENERGYMAX, "PHOTONENERGYPOINTS": self.PHOTONENERGYPOINTS, "USEEMITTANCES": self.USEEMITTANCES, "h5_file": h5_file, "h5_entry_name": "XOPPY_RADIATION", "h5_initialize": True } # write python script in standard output print(self.script_template().format_map(dict_parameters)) return xoppy_calc_undulator_radiation( ELECTRONENERGY=self.ELECTRONENERGY, ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD, ELECTRONCURRENT=self.ELECTRONCURRENT, ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH, ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV, ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH, ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV, PERIODID=self.PERIODID, NPERIODS=self.NPERIODS, KV=self.KV, DISTANCE=self.DISTANCE, SETRESONANCE=self.SETRESONANCE, HARMONICNUMBER=self.HARMONICNUMBER, GAPH=self.GAPH, GAPV=self.GAPV, HSLITPOINTS=self.HSLITPOINTS, VSLITPOINTS=self.VSLITPOINTS, METHOD=self.METHOD, PHOTONENERGYMIN=self.PHOTONENERGYMIN, PHOTONENERGYMAX=self.PHOTONENERGYMAX, PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS, USEEMITTANCES=self.USEEMITTANCES, h5_file=h5_file, h5_entry_name="XOPPY_RADIATION", h5_initialize=True, h5_parameters=dict_parameters, ) def script_template(self): return """ # # script to make the calculations (created by XOPPY:undulator_radiation) # from orangecontrib.xoppy.util.xoppy_undulators import xoppy_calc_undulator_radiation e, h, v, p, code = xoppy_calc_undulator_radiation( ELECTRONENERGY = {ELECTRONENERGY}, ELECTRONENERGYSPREAD = {ELECTRONENERGYSPREAD}, ELECTRONCURRENT = {ELECTRONCURRENT}, ELECTRONBEAMSIZEH = {ELECTRONBEAMSIZEH}, ELECTRONBEAMSIZEV = {ELECTRONBEAMSIZEV}, ELECTRONBEAMDIVERGENCEH = {ELECTRONBEAMDIVERGENCEH}, ELECTRONBEAMDIVERGENCEV = {ELECTRONBEAMDIVERGENCEV}, PERIODID = {PERIODID}, NPERIODS = {NPERIODS}, KV = {KV}, DISTANCE = {DISTANCE}, SETRESONANCE = {SETRESONANCE}, HARMONICNUMBER = {HARMONICNUMBER}, GAPH = {GAPH}, GAPV = {GAPV}, HSLITPOINTS = {HSLITPOINTS}, VSLITPOINTS = {VSLITPOINTS}, METHOD = {METHOD}, PHOTONENERGYMIN = {PHOTONENERGYMIN}, PHOTONENERGYMAX = {PHOTONENERGYMAX}, PHOTONENERGYPOINTS = {PHOTONENERGYPOINTS}, USEEMITTANCES = {USEEMITTANCES}, h5_file = "{h5_file}", h5_entry_name = "XOPPY_RADIATION", h5_initialize = True, ) # example plot from srxraylib.plot.gol import plot_image plot_image(p[0],h,v,title="Flux [photons/s] per 0.1 bw per mm2 at %f eV"%({PHOTONENERGYMIN}),xtitle="H [mm]",ytitle="V [mm]") # # end script # """ def extract_data_from_xoppy_output(self, calculation_output): e, h, v, p, code = calculation_output calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", [p, e, h, v]) calculated_data.add_content("xoppy_code", code) return calculated_data def get_data_exchange_widget_name(self): return "UNDULATOR_RADIATION" def getTitles(self): return [ 'Undulator Flux vs E,X,Y', 'Undulator Power Density vs X,Y', 'Undulator Flux vs E', 'Undulator Spectral Power vs E' ] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread self.ELECTRONCURRENT = light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.ELECTRONBEAMSIZEH = x self.ELECTRONBEAMSIZEV = y self.ELECTRONBEAMDIVERGENCEH = xp self.ELECTRONBEAMDIVERGENCEV = yp self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = light_source._magnetic_structure._number_of_periods self.KV = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self, value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONENERGYSPREAD.setEnabled(True) self.id_ELECTRONBEAMSIZEH.setEnabled(True) self.id_ELECTRONBEAMSIZEV.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KV.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONENERGYSPREAD.setEnabled(False) self.id_ELECTRONBEAMSIZEH.setEnabled(False) self.id_ELECTRONBEAMSIZEV.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KV.setEnabled(False)
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 OWundulator_radiation(XoppyWidget, WidgetDecorator): name = "Undulator Radiation" id = "orange.widgets.dataundulator_radiation" description = "Undulator Radiation" icon = "icons/xoppy_undulator_radiation.png" priority = 5 category = "" keywords = ["xoppy", "undulator_radiation"] USEEMITTANCES=Setting(1) ELECTRONENERGY = Setting(6.04) ELECTRONENERGYSPREAD = Setting(0.001) ELECTRONCURRENT = Setting(0.2) ELECTRONBEAMSIZEH = Setting(0.000395) ELECTRONBEAMSIZEV = Setting(9.9e-06) ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05) ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06) PERIODID = Setting(0.018) NPERIODS = Setting(222) KV = Setting(1.68) DISTANCE = Setting(30.0) SETRESONANCE = Setting(0) HARMONICNUMBER = Setting(1) GAPH = Setting(0.003) GAPV = Setting(0.003) HSLITPOINTS = Setting(41) VSLITPOINTS = Setting(41) PHOTONENERGYMIN = Setting(6000.0) PHOTONENERGYMAX = Setting(8500.0) PHOTONENERGYPOINTS = Setting(20) METHOD = Setting(2) inputs = [WidgetDecorator.syned_input_data()] def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-5) idx = -1 # # # idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "USEEMITTANCES", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGY = oasysgui.lineEdit(box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(box1, self, "ELECTRONENERGYSPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit(box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_KV = oasysgui.lineEdit(box1, self, "KV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) # widget <><><> idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "SETRESONANCE", label=self.unitLabels()[idx], addSpace=False, items=['User defined', 'Set to resonance/central cone','Set to resonance/up to first ring'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget <><><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONICNUMBER", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "VSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['US', 'URGENT', 'SRW','pySRU'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return ["Use emittances","Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]", "Electron Beam Size H [m]", "Electron Beam Size V [m]","Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", "Period ID [m]", "Number of periods","Kv [undulator K value vertical field]", "Distance to slit [m]", "Set photon energy and slit","Harmonic number", "Slit gap H [m]", "Slit gap V [m]", "Number of slit mesh points in H", "Number of slit mesh points in V", "Photon Energy Min [eV]","Photon Energy Max [eV]","Number of Photon Energy Points", "calculation code"] # TODO check energy spread flag: set to False (not used at all)!! def unitFlags(self): return ["True", "True", "False", "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1","self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True", "True", "True", "True", "True", "self.SETRESONANCE > 0", "self.SETRESONANCE == 0", "self.SETRESONANCE == 0", "True", "True", "self.SETRESONANCE == 0", "self.SETRESONANCE == 0","self.SETRESONANCE == 0", "True"] def get_help_name(self): return 'undulator_radiation' def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(self.ELECTRONENERGY, "Electron Energy") if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(self.ELECTRONENERGYSPREAD, "Electron Energy Spread") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(self.ELECTRONCURRENT, "Electron Current") self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEH, "Electron Beam Size H") self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEV, "Electron Beam Size V") self.ELECTRONBEAMDIVERGENCEH = congruence.checkNumber(self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H") self.ELECTRONBEAMDIVERGENCEV = congruence.checkNumber(self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V") self.PHOTONENERGYMIN = congruence.checkNumber(self.PHOTONENERGYMIN, "Photon Energy Min") self.PHOTONENERGYMAX = congruence.checkNumber(self.PHOTONENERGYMAX, "Photon Energy Max") self.PHOTONENERGYPOINTS = congruence.checkStrictlyPositiveNumber(self.PHOTONENERGYPOINTS, "Number of Photon Energy Points") self.PERIODID = congruence.checkStrictlyPositiveNumber(self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber(self.NPERIODS, "Number of Periods") self.KV = congruence.checkPositiveNumber(self.KV, "Kv") self.DISTANCE = congruence.checkStrictlyPositiveNumber(self.DISTANCE, "Distance to slit") self.HARMONICNUMBER = congruence.checkStrictlyPositiveNumber(self.HARMONICNUMBER, "Harminic number") self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H") self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V") self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber(self.HSLITPOINTS, "Number of slit mesh points in H") self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber(self.VSLITPOINTS, "Number of slit mesh points in V") if self.METHOD == 1: # URGENT congruence.checkLessOrEqualThan(self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT "," 51") congruence.checkLessOrEqualThan(self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT "," 51") def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.initializeTabs() # added by srio to avoid overlapping graphs self.view_type_combo.setEnabled(False) p,e,h,v = calculated_data.get_content("xoppy_data") code = calculated_data.get_content("xoppy_code") try: self.plot_data3D(p, e, h, v, 0, 0, xtitle='H [mm]', ytitle='V [mm]', title='Code '+code+'; Flux [photons/s/0.1%bw/mm^2]',) self.tabs.setCurrentIndex(0) except Exception as e: self.view_type_combo.setEnabled(True) raise Exception("Data not plottable: bad content\n" + str(e)) try: self.plot_data2D(p.sum(axis=0)*(e[1]-e[0])*codata.e*1e3, h, v, 1, 0, xtitle='H [mm]', ytitle='V [mm]', title='Code '+code+'; Power density [W/mm^2]',) # self.tabs.setCurrentIndex(1) except Exception as e: self.view_type_combo.setEnabled(True) raise Exception("Data not plottable: bad content\n" + str(e)) try: print("Result arrays (shapes): ",e.shape,h.shape,v.shape,p.shape) self.plot_data1D(e,p.sum(axis=2).sum(axis=1)*(h[1]-h[0])*(v[1]-v[0]), 2, 0, xtitle='Photon Energy [eV]', ytitle= 'Flux [photons/s/0.1%bw/mm^2]', title='Code '+code+'; Flux',) # self.tabs.setCurrentIndex(2) 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 do_xoppy_calculation(self): return xoppy_calc_undulator_radiation(ELECTRONENERGY=self.ELECTRONENERGY, ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD, ELECTRONCURRENT=self.ELECTRONCURRENT, ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH, ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV, ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH, ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV, PERIODID=self.PERIODID, NPERIODS=self.NPERIODS, KV=self.KV, DISTANCE=self.DISTANCE, SETRESONANCE=self.SETRESONANCE, HARMONICNUMBER=self.HARMONICNUMBER, GAPH=self.GAPH, GAPV=self.GAPV, HSLITPOINTS=self.HSLITPOINTS, VSLITPOINTS=self.VSLITPOINTS, METHOD=self.METHOD, PHOTONENERGYMIN=self.PHOTONENERGYMIN, PHOTONENERGYMAX=self.PHOTONENERGYMAX, PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS, USEEMITTANCES=self.USEEMITTANCES) def extract_data_from_xoppy_output(self, calculation_output): e, h, v, p, code = calculation_output calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", [p, e, h, v]) calculated_data.add_content("xoppy_code", code) return calculated_data def get_data_exchange_widget_name(self): return "UNDULATOR_RADIATION" def getTitles(self): return ['Undulator Flux','Undulator Power Density','Undulator Spectrum'] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance(data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread self.ELECTRONCURRENT = light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.ELECTRONBEAMSIZEH = x self.ELECTRONBEAMSIZEV = y self.ELECTRONBEAMDIVERGENCEH = xp self.ELECTRONBEAMDIVERGENCEV = yp self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = light_source._magnetic_structure._number_of_periods self.KV = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self,value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONENERGYSPREAD.setEnabled(True) self.id_ELECTRONBEAMSIZEH.setEnabled(True) self.id_ELECTRONBEAMSIZEV.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KV.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONENERGYSPREAD.setEnabled(False) self.id_ELECTRONBEAMSIZEH.setEnabled(False) self.id_ELECTRONBEAMSIZEV.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KV.setEnabled(False)
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
class OWundulator_spectrum(XoppyWidget, WidgetDecorator): name = "Undulator Spectrum" id = "orange.widgets.dataundulator_spectrum" description = "Undulator Spectrum" icon = "icons/xoppy_undulator_spectrum.png" priority = 1 category = "" keywords = ["xoppy", "undulator_spectrum"] USEEMITTANCES=Setting(1) ELECTRONENERGY = Setting(6.04) ELECTRONENERGYSPREAD = Setting(0.001) ELECTRONCURRENT = Setting(0.2) ELECTRONBEAMSIZEH = Setting(0.000395) ELECTRONBEAMSIZEV = Setting(9.9e-06) ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05) ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06) PERIODID = Setting(0.018) NPERIODS = Setting(222) KV = Setting(1.68) DISTANCE = Setting(30.0) GAPH = Setting(0.001) GAPV = Setting(0.001) PHOTONENERGYMIN = Setting(3000.0) PHOTONENERGYMAX = Setting(55000.0) PHOTONENERGYPOINTS = Setting(500) METHOD = Setting(0) inputs = [WidgetDecorator.syned_input_data()] def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH-5) idx = -1 # # # idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "USEEMITTANCES", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGY = oasysgui.lineEdit(box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit(box1, self, "ELECTRONENERGYSPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit(box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMSIZEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit(box1, self, "ELECTRONBEAMDIVERGENCEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_KV = oasysgui.lineEdit(box1, self, "KV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 16 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['US', 'URGENT', 'SRW'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return ["Use emittances","Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]", "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", "Period ID [m]", "Number of periods", "Kv [undulator K value vertical field]", "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]", "photon Energy Min [eV]", "photon Energy Max [eV]", "photon Energy Points", "calculation code"] def unitFlags(self): return ["True", "True", "self.USEEMITTANCES == 1 and self.METHOD != 1", "True", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "True", "True", "True", "True", "True", "True", "True", "True", "True", "True"] def get_help_name(self): return 'undulator_spectrum' def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber(self.ELECTRONENERGY, "Electron Energy") if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber(self.ELECTRONENERGYSPREAD, "Electron Energy Spread") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber(self.ELECTRONCURRENT, "Electron Current") self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEH, "Electron Beam Size H") self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber(self.ELECTRONBEAMSIZEV, "Electron Beam Size V") self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber(self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H") self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber(self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V") self.PERIODID = congruence.checkStrictlyPositiveNumber(self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber(self.NPERIODS, "Number of Periods") self.KV = congruence.checkPositiveNumber(self.KV, "Kv") self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit") self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H") self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V") self.PHOTONENERGYMIN = congruence.checkPositiveNumber(self.PHOTONENERGYMIN, "photon Energy Min") self.PHOTONENERGYMAX = congruence.checkStrictlyPositiveNumber(self.PHOTONENERGYMAX, "photon Energy Max") congruence.checkLessThan(self.PHOTONENERGYMIN, self.PHOTONENERGYMAX, "photon Energy Min", "photon Energy Max") self.PHOTONENERGYPOINTS = congruence.checkStrictlyPositiveNumber(self.PHOTONENERGYPOINTS, "photon Energy Points") if self.METHOD == 1: # URGENT congruence.checkLessThan(self.PHOTONENERGYPOINTS,4701,"Number of energy points","4701") # if sys.platform == 'linux' and self.METHOD == 2: # raise Exception("SRW calculation code not supported under Linux") def do_xoppy_calculation(self): return xoppy_calc_undulator_spectrum(ELECTRONENERGY=self.ELECTRONENERGY, ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD, ELECTRONCURRENT=self.ELECTRONCURRENT, ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH, ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV, ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH, ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV, PERIODID=self.PERIODID, NPERIODS=self.NPERIODS, KV=self.KV, DISTANCE=self.DISTANCE, GAPH=self.GAPH, GAPV=self.GAPV, PHOTONENERGYMIN=self.PHOTONENERGYMIN, PHOTONENERGYMAX=self.PHOTONENERGYMAX, PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS, METHOD=self.METHOD, USEEMITTANCES=self.USEEMITTANCES) def extract_data_from_xoppy_output(self, calculation_output): e, f, sp = calculation_output data = numpy.zeros((len(e), 3)) data[:, 0] = numpy.array(e) data[:, 1] = numpy.array(f) data[:, 2] = numpy.array(sp) calculated_data = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", data) return calculated_data def get_data_exchange_widget_name(self): return "UNDULATOR_FLUX" def getTitles(self): return ['Undulator Flux', 'Spectral Power'] def getXTitles(self): return ["Energy [eV]", "Energy [eV]"] def getYTitles(self): return ["Flux [Phot/sec/0.1%bw]", "Spectral Power [W/eV]"] def getLogPlot(self): return [(False, False), (False, False)] def getVariablesToPlot(self): return [(0, 1), (0, 2)] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance(data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread self.ELECTRONCURRENT = light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.ELECTRONBEAMSIZEH = x self.ELECTRONBEAMSIZEV = y self.ELECTRONBEAMDIVERGENCEH = xp self.ELECTRONBEAMDIVERGENCEV = yp self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = light_source._magnetic_structure._number_of_periods self.KV = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self,value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONENERGYSPREAD.setEnabled(True) self.id_ELECTRONBEAMSIZEH.setEnabled(True) self.id_ELECTRONBEAMSIZEV.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KV.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONENERGYSPREAD.setEnabled(False) self.id_ELECTRONBEAMSIZEH.setEnabled(False) self.id_ELECTRONBEAMSIZEV.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KV.setEnabled(False)
class PowerLoopPoint(widget.OWWidget): name = "Power Density Loop Point" description = "Tools: LoopPoint" icon = "icons/cycle.png" maintainer = "Luca Rebuffi" maintainer_email = "lrebuffi(@at@)anl.gov" priority = 5 category = "User Defined" keywords = ["data", "file", "load", "read"] inputs = WidgetDecorator.syned_input_data() inputs.append(("Trigger", TriggerIn, "passTrigger")) inputs.append( ("Energy Spectrum", DataExchangeObject, "acceptEnergySpectrum")) inputs.append(("Filters", DataExchangeObject, "acceptFilters")) outputs = [{ "name": "Trigger", "type": TriggerOut, "doc": "Trigger", "id": "Trigger" }] want_main_area = 1 current_new_object = 0 number_of_new_objects = 0 total_current_new_object = 0 total_new_objects = Setting(0) run_loop = True suspend_loop = False energies = Setting("") seed_increment = Setting(1) autobinning = Setting(1) auto_n_step = Setting(1001) auto_perc_total_power = Setting(99) send_power_step = Setting(0) electron_energy = Setting(6.0) K_vertical = Setting(1.943722) K_horizontal = Setting(0.0) period_length = Setting(0.025) number_of_periods = Setting(184) theta_x = Setting(0.0) theta_z = Setting(0.0) current_energy_binning = -1 current_energy_value = None current_energy_step = None current_power_step = None energy_binnings = None external_binning = False filters = None spectrum_data = None ################################# process_last = True ################################# def __init__(self): self.runaction = OWAction("Start", self) self.runaction.triggered.connect(self.startLoop) self.addAction(self.runaction) self.runaction = OWAction("Stop", self) self.runaction.triggered.connect(self.stopLoop) self.addAction(self.runaction) self.runaction = OWAction("Suspend", self) self.runaction.triggered.connect(self.suspendLoop) self.addAction(self.runaction) self.runaction = OWAction("Restart", self) self.runaction.triggered.connect(self.restartLoop) self.addAction(self.runaction) self.setFixedWidth(1200) self.setFixedHeight(710) button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=True, orientation="horizontal") self.start_button = gui.button(button_box, self, "Start", callback=self.startLoop) self.start_button.setFixedHeight(35) stop_button = gui.button(button_box, self, "Stop", callback=self.stopLoop) stop_button.setFixedHeight(35) font = QFont(stop_button.font()) font.setBold(True) stop_button.setFont(font) palette = QPalette(stop_button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('red')) stop_button.setPalette(palette) # assign new palette self.stop_button = stop_button button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=True, orientation="horizontal") suspend_button = gui.button(button_box, self, "Suspend", callback=self.suspendLoop) suspend_button.setFixedHeight(35) font = QFont(suspend_button.font()) font.setBold(True) suspend_button.setFont(font) palette = QPalette( suspend_button.palette()) # make a copy of the palette palette.setColor(QPalette.ButtonText, QColor('orange')) suspend_button.setPalette(palette) # assign new palette self.re_start_button = gui.button(button_box, self, "Restart", callback=self.restartLoop) self.re_start_button.setFixedHeight(35) self.re_start_button.setEnabled(False) tabs = oasysgui.tabWidget(self.controlArea) tab_loop = oasysgui.createTabPage(tabs, "Loop Management") tab_und = oasysgui.createTabPage(tabs, "Undulator") left_box_2 = oasysgui.widgetBox(tab_und, "Parameters From Syned", addSpace=False, orientation="vertical", width=385, height=560) oasysgui.lineEdit(left_box_2, self, "electron_energy", "Ring Energy [GeV]", labelWidth=260, valueType=float, orientation="horizontal").setReadOnly(True) oasysgui.lineEdit(left_box_2, self, "number_of_periods", "Number of Periods", labelWidth=260, valueType=float, orientation="horizontal").setReadOnly(True) oasysgui.lineEdit(left_box_2, self, "period_length", "Undulator Period [m]", labelWidth=260, valueType=float, orientation="horizontal").setReadOnly(True) oasysgui.lineEdit(left_box_2, self, "K_vertical", "K Vertical", labelWidth=260, valueType=float, orientation="horizontal").setReadOnly(True) oasysgui.lineEdit(left_box_2, self, "K_horizontal", "K Horizontal", labelWidth=260, valueType=float, orientation="horizontal").setReadOnly(True) left_box_1 = oasysgui.widgetBox(tab_loop, "", addSpace=False, orientation="vertical", width=385, height=560) oasysgui.lineEdit(left_box_1, self, "seed_increment", "Source Montecarlo Seed Increment", labelWidth=250, valueType=int, orientation="horizontal") gui.separator(left_box_1) gui.comboBox(left_box_1, self, "autobinning", label="Energy Binning", items=[ "Manual", "Automatic (Constant Power)", "Automatic (Constant Energy)" ], labelWidth=150, callback=self.set_Autobinning, sendSelectedValue=False, orientation="horizontal") self.autobinning_box_1 = oasysgui.widgetBox(left_box_1, "", addSpace=False, orientation="vertical", height=50) self.autobinning_box_2 = oasysgui.widgetBox(left_box_1, "", addSpace=False, orientation="vertical", height=140) # ---------------------------------------------- gui.button(self.autobinning_box_1, self, "Compute Bins", callback=self.calculate_energy_binnings) oasysgui.widgetLabel(self.autobinning_box_1, "Energy From, Energy To, Energy Step [eV]") # ---------------------------------------------- oasysgui.lineEdit(self.autobinning_box_2, self, "auto_n_step", "Number of Steps", labelWidth=250, valueType=int, orientation="horizontal") oasysgui.lineEdit(self.autobinning_box_2, self, "auto_perc_total_power", "% Total Power", labelWidth=250, valueType=float, orientation="horizontal") gui.comboBox(self.autobinning_box_2, self, "send_power_step", label="Send Power Step", items=["No", "Yes"], labelWidth=350, sendSelectedValue=False, orientation="horizontal") button_box = oasysgui.widgetBox(self.autobinning_box_2, "", addSpace=False, orientation="horizontal") gui.button(button_box, self, "Reload Spectrum and Filters", callback=self.read_spectrum_and_filters_file) gui.button(button_box, self, "Reload Spectrum Only", callback=self.read_spectrum_file_only) oasysgui.widgetLabel( self.autobinning_box_2, "Energy Value [eV], Energy Step [eV], Power Step [W]") def write_text(): self.energies = self.text_area.toPlainText() self.text_area = oasysgui.textArea(height=95, width=385, readOnly=False) self.text_area.setText(self.energies) self.text_area.setStyleSheet( "background-color: white; font-family: Courier, monospace;") self.text_area.textChanged.connect(write_text) left_box_1.layout().addWidget(self.text_area) gui.separator(left_box_1) self.le_number_of_new_objects = oasysgui.lineEdit( left_box_1, self, "total_new_objects", "Total Energy Values", labelWidth=250, valueType=int, orientation="horizontal") self.le_number_of_new_objects.setReadOnly(True) font = QFont(self.le_number_of_new_objects.font()) font.setBold(True) self.le_number_of_new_objects.setFont(font) palette = QPalette(self.le_number_of_new_objects.palette() ) # make a copy of the palette palette.setColor(QPalette.Text, QColor('dark blue')) palette.setColor(QPalette.Base, QColor(243, 240, 160)) self.le_number_of_new_objects.setPalette(palette) self.le_number_of_new_objects = oasysgui.lineEdit( left_box_1, self, "number_of_new_objects", "Current Binning Energy Values", labelWidth=250, valueType=int, orientation="horizontal") self.le_number_of_new_objects.setReadOnly(True) font = QFont(self.le_number_of_new_objects.font()) font.setBold(True) self.le_number_of_new_objects.setFont(font) palette = QPalette(self.le_number_of_new_objects.palette() ) # make a copy of the palette palette.setColor(QPalette.Text, QColor('dark blue')) palette.setColor(QPalette.Base, QColor(243, 240, 160)) self.le_number_of_new_objects.setPalette(palette) gui.separator(left_box_1) le_current_value = oasysgui.lineEdit(left_box_1, self, "total_current_new_object", "Total New " + self.get_object_name(), labelWidth=250, valueType=int, orientation="horizontal") le_current_value.setReadOnly(True) font = QFont(le_current_value.font()) font.setBold(True) le_current_value.setFont(font) palette = QPalette( le_current_value.palette()) # make a copy of the palette palette.setColor(QPalette.Text, QColor('dark blue')) palette.setColor(QPalette.Base, QColor(243, 240, 160)) le_current_value.setPalette(palette) le_current_value = oasysgui.lineEdit(left_box_1, self, "current_new_object", "Current Binning New " + self.get_object_name(), labelWidth=250, valueType=int, orientation="horizontal") le_current_value.setReadOnly(True) font = QFont(le_current_value.font()) font.setBold(True) le_current_value.setFont(font) palette = QPalette( le_current_value.palette()) # make a copy of the palette palette.setColor(QPalette.Text, QColor('dark blue')) palette.setColor(QPalette.Base, QColor(243, 240, 160)) le_current_value.setPalette(palette) le_current_value = oasysgui.lineEdit(left_box_1, self, "current_energy_value", "Current Energy Value", labelWidth=250, valueType=float, orientation="horizontal") le_current_value.setReadOnly(True) font = QFont(le_current_value.font()) font.setBold(True) le_current_value.setFont(font) palette = QPalette( le_current_value.palette()) # make a copy of the palette palette.setColor(QPalette.Text, QColor('dark blue')) palette.setColor(QPalette.Base, QColor(243, 240, 160)) le_current_value.setPalette(palette) gui.rubber(self.controlArea) tabs = oasysgui.tabWidget(self.mainArea) tabs.setFixedHeight(self.height() - 15) tabs.setFixedWidth(775) tab_plot = oasysgui.createTabPage(tabs, "Cumulated Power") tab_flux = oasysgui.createTabPage(tabs, "Spectral Flux") tab_fil = oasysgui.createTabPage(tabs, "Filter") self.cumulated_power_plot = oasysgui.plotWindow(tab_plot, position=True) self.cumulated_power_plot.setFixedHeight(self.height() - 20) self.cumulated_power_plot.setFixedWidth(775) self.cumulated_power_plot.setGraphXLabel("Energy [eV]") self.cumulated_power_plot.setGraphYLabel("Cumulated Power [W]") self.cumulated_power_plot.setGraphTitle("Cumulated Power") self.spectral_flux_plot = oasysgui.plotWindow(tab_flux, position=True) self.spectral_flux_plot.setFixedHeight(self.height() - 20) self.spectral_flux_plot.setFixedWidth(775) self.spectral_flux_plot.setGraphXLabel("Energy [eV]") self.spectral_flux_plot.setGraphYLabel("Flux [ph/s/.1%bw]") self.spectral_flux_plot.setGraphTitle("Spectral Flux") self.filter_plot = oasysgui.plotWindow(tab_fil, position=True) self.filter_plot.setFixedHeight(self.height() - 20) self.filter_plot.setFixedWidth(775) self.filter_plot.setGraphXLabel("Energy [eV]") self.filter_plot.setGraphYLabel("Intensity Factor") self.filter_plot.setGraphTitle("Filter on Flux") self.set_Autobinning() def set_Autobinning(self): self.autobinning_box_1.setVisible(self.autobinning == 0) self.autobinning_box_2.setVisible(self.autobinning == 1 or self.autobinning == 2) self.text_area.setReadOnly(self.autobinning >= 1) self.text_area.setFixedHeight(201 if self.autobinning >= 1 else 290) def read_spectrum_file(self, reset_filters=True): try: if reset_filters: self.filters = None self.filter_plot.clear() data = numpy.loadtxt("autobinning.dat", skiprows=1) calculated_data = DataExchangeObject(program_name="ShadowOui", widget_name="PowerLoopPoint") calculated_data.add_content("spectrum_data", data) self.acceptEnergySpectrum(calculated_data) except Exception as e: QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise e def read_spectrum_file_only(self): self.read_spectrum_file(True) def read_spectrum_and_filters_file(self): try: data = numpy.loadtxt("filters.dat", skiprows=1) calculated_data = DataExchangeObject(program_name="ShadowOui", widget_name="PowerLoopPoint") calculated_data.add_content("filters_data", data) self.acceptFilters(calculated_data) except Exception: self.filters = None self.read_spectrum_file(False) def receive_syned_data(self, data): if not data is None: try: if not data._light_source is None and isinstance( data._light_source, LightSource): light_source = data._light_source self.electron_energy = light_source._electron_beam._energy_in_GeV self.K_horizontal = light_source._magnetic_structure._K_horizontal self.K_vertical = light_source._magnetic_structure._K_vertical self.period_length = light_source._magnetic_structure._period_length self.number_of_periods = light_source._magnetic_structure._number_of_periods else: raise ValueError("Syned data not correct") except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) if self.IS_DEVELOP: raise exception def receive_specific_syned_data(self, data): raise NotImplementedError() def acceptFilters(self, exchange_data): if not exchange_data is None: try: # FROM XOPPY F1F2 write_file = True try: data = exchange_data.get_content("filters_data") write_file = False except: if not exchange_data.get_program_name() == "XOPPY": raise ValueError( "Only XOPPY F1F2 and CRYSTAL widgets are accepted") if exchange_data.get_widget_name() == "XF1F2": data = exchange_data.get_content("xoppy_data") elif exchange_data.get_widget_name() == "XCRYSTAL": data = exchange_data.get_content("xoppy_data") cols = data.shape[1] data = exchange_data.get_content("xoppy_data")[ 0:cols:cols - 1, 0:cols:cols - 1] elif exchange_data.get_widget_name() == "MLAYER": data = exchange_data.get_content("xoppy_data")[0:3:2, 0:3:2] self.filters = data energies = self.filters[:, 0] intensity_factors = self.filters[:, 1] if write_file: file = open("filters.dat", "w") file.write("Energy Filter") for energy, intensity_factor in zip( energies, intensity_factors): file.write("\n" + str(energy) + " " + str(intensity_factor)) file.flush() file.close() self.filter_plot.clear() self.filter_plot.addCurve(energies, intensity_factors, replace=True, legend="Intensity Factor") self.filter_plot.setGraphXLabel("Energy [eV]") self.filter_plot.setGraphYLabel("Intensity Factor") self.filter_plot.setGraphTitle("Filter on Flux") if self.autobinning == 0: if write_file: QMessageBox.information( self, "Info", "File filters.dat written on working directory, switch to Automatic binning to load it", QMessageBox.Ok) else: if write_file: QMessageBox.information( self, "Info", "File filters.dat written on working directory", QMessageBox.Ok) if not self.spectrum_data is None: calculated_data = DataExchangeObject( program_name="ShadowOui", widget_name="PowerLoopPoint") calculated_data.add_content("spectrum_data", self.spectrum_data) self.acceptEnergySpectrum(calculated_data) except Exception as e: QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise e def acceptEnergySpectrum(self, exchange_data): if not exchange_data is None: try: write_file = True try: data = exchange_data.get_content("spectrum_data") write_file = False except: try: data = exchange_data.get_content("srw_data") except: data = exchange_data.get_content("xoppy_data") self.spectrum_data = data.copy() energies = data[:, 0] flux_through_finite_aperture = data[:, 1] flux_through_finite_aperture_filtered = flux_through_finite_aperture.copy( ) if not self.filters is None: flux_through_finite_aperture_filtered *= numpy.interp( energies, self.filters[:, 0], self.filters[:, 1]) if write_file: file = open("autobinning.dat", "w") file.write("Energy Flux") for energy, flux in zip(energies, flux_through_finite_aperture): file.write("\n" + str(energy) + " " + str(flux)) file.flush() file.close() if self.autobinning == 0: if write_file: QMessageBox.information( self, "Info", "File autobinning.dat written on working directory, switch to Automatic binning to load it", QMessageBox.Ok) else: if write_file: QMessageBox.information( self, "Info", "File autobinning.dat written on working directory", QMessageBox.Ok) congruence.checkStrictlyPositiveNumber( self.auto_n_step, "(Auto) % Number of Steps") congruence.checkStrictlyPositiveNumber( self.auto_perc_total_power, "(Auto) % Total Power") energy_step = energies[1] - energies[0] # last energy do not contribute to the total (the approximated integral of the power is out of the range) power = flux_through_finite_aperture * (1e3 * energy_step * codata.e) cumulated_power = numpy.cumsum(power) total_power = cumulated_power[-1] if not self.filters is None: power_filtered = flux_through_finite_aperture_filtered * ( 1e3 * energy_step * codata.e) cumulated_power_filtered = numpy.cumsum(power_filtered) total_power_filtered = cumulated_power_filtered[-1] self.text_area.clear() self.cumulated_power_plot.clear() self.spectral_flux_plot.clear() good = numpy.where( cumulated_power <= self.auto_perc_total_power * 0.01 * total_power) energies = energies[good] cumulated_power = cumulated_power[good] flux_through_finite_aperture = flux_through_finite_aperture[ good] if not self.filters is None: cumulated_power_filtered = cumulated_power_filtered[ good] flux_through_finite_aperture_filtered = flux_through_finite_aperture_filtered[ good] if self.autobinning == 1: # constant power interpolated_cumulated_power = numpy.linspace( start=numpy.min(cumulated_power), stop=numpy.max(cumulated_power), num=self.auto_n_step + 1) interpolated_energies = numpy.interp( interpolated_cumulated_power, cumulated_power, energies) energy_steps = numpy.ediff1d(interpolated_energies) interpolated_energies = interpolated_energies[:-1] interpolated_cumulated_power = interpolated_cumulated_power[: -1] power_steps = numpy.ones( self.auto_n_step ) * cumulated_power[-1] / self.auto_n_step elif self.autobinning == 2: # constant energy minimum_energy = energies[0] maximum_energy = energies[-1] energy_step = (maximum_energy - minimum_energy) / self.auto_n_step interpolated_energies = numpy.arange( minimum_energy, maximum_energy, energy_step) interpolated_cumulated_power = numpy.interp( interpolated_energies, energies, cumulated_power) energy_steps = numpy.ones( self.auto_n_step) * energy_step power_steps = numpy.ediff1d( numpy.append(numpy.zeros(1), interpolated_cumulated_power)) flux_steps = numpy.interp(interpolated_energies, energies, flux_through_finite_aperture) self.energy_binnings = [] self.total_new_objects = 0 self.cumulated_power_plot.addCurve( energies, cumulated_power, replace=True, legend="Cumulated Power") if not self.filters is None: self.cumulated_power_plot.addCurve( energies, cumulated_power_filtered, replace=False, legend="Cumulated Power Filters", linestyle="--", color="#006400") self.cumulated_power_plot.setGraphXLabel("Energy [eV]") self.cumulated_power_plot.setGraphYLabel("Cumulated " + ( "" if self.filters is None else " (Filtered)") + " Power") if self.filters is None: self.cumulated_power_plot.setGraphTitle( "Total Power: " + str(round(power_steps.sum(), 2)) + " W") else: self.cumulated_power_plot.setGraphTitle( "Total (Filtered) Power: " + str(round(power_steps.sum(), 2)) + " (" + str(round(total_power_filtered, 2)) + ") W") self.spectral_flux_plot.addCurve( energies, flux_through_finite_aperture, replace=True, legend="Spectral Flux") if not self.filters is None: self.spectral_flux_plot.addCurve( energies, flux_through_finite_aperture_filtered, replace=False, legend="Spectral Flux Filters", linestyle="--", color="#006400") self.spectral_flux_plot.setGraphXLabel("Energy [eV]") self.spectral_flux_plot.setGraphYLabel("Flux [ph/s/.1%bw]") self.spectral_flux_plot.setGraphTitle("Spectral Flux" + ( "" if self.filters is None else " (Filtered)")) self.cumulated_power_plot.addCurve( interpolated_energies, interpolated_cumulated_power, replace=False, legend="Energy Binning", color="red", linestyle=" ", symbol="+") self.spectral_flux_plot.addCurve(interpolated_energies, flux_steps, replace=False, legend="Energy Binning", color="red", linestyle=" ", symbol="+") text = "" for energy_value, energy_step, power_step in zip( interpolated_energies, energy_steps, power_steps): energy_binning = EnergyBinning( energy_value=round(energy_value, 3), energy_step=round(energy_step, 3), power_step=round(power_step, 4)) text += str(round(energy_value, 3)) + ", " + \ str(round(energy_step, 3)) + ", " + \ str(round(power_step, 4)) + "\n" self.energy_binnings.append(energy_binning) self.total_new_objects += 1 self.text_area.setText(text) self.external_binning = True except Exception as e: QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise e else: self.energy_binnings = None self.total_new_objects = 0 self.external_binning = False self.text_area.setText("") def calculate_energy_binnings(self): if not self.external_binning: self.total_new_objects = 0 rows = self.energies.split("\n") for row in rows: data = row.split(",") if len(data) == 3: if self.energy_binnings is None: self.energy_binnings = [] energy_from = float(data[0].strip()) energy_to = float(data[1].strip()) energy_step = float(data[2].strip()) energy_binning = EnergyBinning(energy_value=energy_from, energy_value_to=energy_to, energy_step=energy_step) self.energy_binnings.append(energy_binning) self.total_new_objects += int( (energy_to - energy_from) / energy_step) def calculate_number_of_new_objects(self): if len(self.energy_binnings) > 0: if self.external_binning: self.number_of_new_objects = 1 else: energy_binning = self.energy_binnings[ self.current_energy_binning] self.number_of_new_objects = int( (energy_binning.energy_value_to - energy_binning.energy_value) / energy_binning.energy_step) else: self.number_of_new_objects = 0 def reset_values(self): self.current_new_object = 0 self.total_current_new_object = 0 self.current_energy_value = None self.current_energy_step = None self.current_energy_binning = -1 self.current_power_step = None if not self.external_binning: self.energy_binnings = None def startLoop(self): try: self.calculate_energy_binnings() self.current_new_object = 1 self.total_current_new_object = 1 self.current_energy_binning = 0 self.current_energy_value = round( self.energy_binnings[0].energy_value, 8) self.current_energy_step = round( self.energy_binnings[0].energy_step, 8) self.current_power_step = None if self.energy_binnings[ 0].power_step is None else ( None if self.send_power_step == 0 else round( self.energy_binnings[0].power_step, 8)) self.calculate_number_of_new_objects() self.start_button.setEnabled(False) self.text_area.setEnabled(False) self.setStatusMessage("Running " + self.get_object_name() + " " + str(self.total_current_new_object) + " of " + str(self.total_new_objects)) self.send( "Trigger", TriggerOut(new_object=True, additional_parameters={ "energy_value": self.current_energy_value, "energy_step": self.current_energy_step, "power_step": -1 if self.current_power_step is None else self.current_power_step, "seed_increment": self.seed_increment, "start_event": True })) except Exception as e: if self.IS_DEVELOP: raise e else: pass def stopLoop(self): try: if ConfirmDialog.confirmed( parent=self, message="Confirm Interruption of the Loop?"): self.run_loop = False self.reset_values() self.setStatusMessage("Interrupted by user") except Exception as e: if self.IS_DEVELOP: raise e else: pass def suspendLoop(self): try: if ConfirmDialog.confirmed( parent=self, message="Confirm Suspension of the Loop?"): self.run_loop = False self.suspend_loop = True self.stop_button.setEnabled(False) self.re_start_button.setEnabled(True) self.setStatusMessage("Suspended by user") except Exception as e: if self.IS_DEVELOP: raise e else: pass def restartLoop(self): try: self.run_loop = True self.suspend_loop = False self.stop_button.setEnabled(True) self.re_start_button.setEnabled(False) self.passTrigger(TriggerIn(new_object=True)) except Exception as e: if self.IS_DEVELOP: raise e else: pass def get_object_name(self): return "Beam" def passTrigger(self, trigger): if self.run_loop: if trigger: if trigger.interrupt: self.reset_values() self.start_button.setEnabled(True) self.text_area.setEnabled(True) self.setStatusMessage("") self.send("Trigger", TriggerOut(new_object=False)) elif trigger.new_object: if self.energy_binnings is None: self.calculate_energy_binnings() if self.current_energy_binning == -1: QMessageBox.critical( self, "Error", "Power Loop has to be started properly: press the button Start", QMessageBox.Ok) return if self.current_energy_binning < len(self.energy_binnings): energy_binning = self.energy_binnings[ self.current_energy_binning] self.total_current_new_object += 1 if self.current_new_object < self.number_of_new_objects: if self.current_energy_value is None: self.current_new_object = 1 self.calculate_number_of_new_objects() self.current_energy_value = round( energy_binning.energy_value, 8) else: self.current_new_object += 1 self.current_energy_value = round( self.current_energy_value + energy_binning.energy_step, 8) self.current_power_step = None if energy_binning.power_step is None else ( None if self.send_power_step == 0 else round( energy_binning.power_step, 8)) self.setStatusMessage( "Running " + self.get_object_name() + " " + str(self.total_current_new_object) + " of " + str(self.total_new_objects)) self.start_button.setEnabled(False) self.text_area.setEnabled(False) self.send( "Trigger", TriggerOut( new_object=True, additional_parameters={ "energy_value": self.current_energy_value, "energy_step": energy_binning.energy_step, "power_step": -1 if self.current_power_step is None else self.current_power_step, "seed_increment": self.seed_increment, "start_event": False })) else: self.current_energy_binning += 1 if self.current_energy_binning < len( self.energy_binnings): energy_binning = self.energy_binnings[ self.current_energy_binning] self.current_new_object = 1 self.calculate_number_of_new_objects() self.current_energy_value = round( energy_binning.energy_value, 8) self.current_power_step = None if energy_binning.power_step is None else ( None if self.send_power_step == 0 else round(energy_binning.power_step, 8)) self.setStatusMessage( "Running " + self.get_object_name() + " " + str(self.total_current_new_object) + " of " + str(self.total_new_objects)) self.start_button.setEnabled(False) self.text_area.setEnabled(False) self.send( "Trigger", TriggerOut( new_object=True, additional_parameters={ "energy_value": self.current_energy_value, "energy_step": energy_binning.energy_step, "power_step": -1 if self.current_power_step is None else self.current_power_step, "seed_increment": self.seed_increment, "start_event": False })) else: self.reset_values() self.start_button.setEnabled(True) self.text_area.setEnabled(True) self.setStatusMessage("") self.send("Trigger", TriggerOut(new_object=False)) else: self.reset_values() self.start_button.setEnabled(True) self.text_area.setEnabled(True) self.setStatusMessage("") self.send("Trigger", TriggerOut(new_object=False)) else: if not self.suspend_loop: self.reset_values() self.start_button.setEnabled(True) self.text_area.setEnabled(True) self.send("Trigger", TriggerOut(new_object=False)) self.setStatusMessage("") self.suspend_loop = False self.run_loop = True
class OWSRWGaussianSource(SRWWavefrontViewer, WidgetDecorator): maintainer = "Luca Rebuffi" maintainer_email = "lrebuffi(@at@)anl.gov" category = "Sources" keywords = ["data", "file", "load", "read"] name = "Gaussian Source" description = "SRW Source: Gaussian Source" icon = "icons/gaussian_source.png" priority = 10 inputs = WidgetDecorator.syned_input_data() inputs.append(("Trigger", TriggerOut, "sendNewWavefront")) outputs = [{ "name": "SRWData", "type": SRWData, "doc": "SRW Source Data", "id": "data" }] want_main_area = 1 source_name = None beam_center_at_waist_x = Setting(0.0) beam_center_at_waist_y = Setting(0.0) beam_center_at_waist_z = Setting(0.0) average_angle_at_waist_x = Setting(0.0) average_angle_at_waist_y = Setting(0.0) energy_per_pulse = Setting(0.001) repetition_rate = Setting(1) polarization = Setting(0) horizontal_sigma_at_waist = Setting(1e-6) vertical_sigma_at_waist = Setting(1e-6) pulse_duration = Setting(10e-15) transverse_gauss_hermite_mode_order_x = Setting(0) transverse_gauss_hermite_mode_order_y = Setting(0) wf_photon_energy = Setting(8000.0) wf_h_slit_gap = Setting(0.001) wf_v_slit_gap = Setting(0.001) wf_h_slit_points = Setting(100) wf_v_slit_points = Setting(100) wf_distance = Setting(10.0) wf_sampling_factor_for_adjusting_nx_ny = Setting(0.0) TABS_AREA_HEIGHT = 618 CONTROL_AREA_WIDTH = 405 def __init__(self, show_automatic_box=False): super().__init__(show_automatic_box=show_automatic_box) self.runaction = widget.OWAction("Run SRW", self) self.runaction.triggered.connect(self.runSRWSource) 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 SRW Source", callback=self.runSRWSource) 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) self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH) 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_source = oasysgui.createTabPage(self.tabs_setting, "Light Source Setting") left_box_1 = oasysgui.widgetBox(self.tab_source, "Gaussian Source Parameters", addSpace=True, orientation="vertical", height=380) oasysgui.lineEdit(left_box_1, self, "beam_center_at_waist_x", "Beam center at waist x [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "beam_center_at_waist_y", "Beam center at waist y [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "beam_center_at_waist_z", "Beam center at waist z [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "average_angle_at_waist_x", "Average angle at waist x [rad]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "average_angle_at_waist_y", "Average angle at waist y [rad]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "energy_per_pulse", "Energy per pulse [J]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "repetition_rate", "Repetition rate [Hz]", labelWidth=260, valueType=float, orientation="horizontal") gui.comboBox(left_box_1, self, "polarization", label="Polarization", items=Polarization.tuple(), labelWidth=150, sendSelectedValue=False, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "horizontal_sigma_at_waist", "\u03c3x at waist [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "vertical_sigma_at_waist", "\u03c3y at waist [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "pulse_duration", "Pulse duration [s]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "transverse_gauss_hermite_mode_order_x", "Transverse Gauss-Hermite mode order x", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "transverse_gauss_hermite_mode_order_y", "Transverse Gauss-Hermite mode order y", labelWidth=260, valueType=int, orientation="horizontal") self.tab_plots = oasysgui.createTabPage(self.tabs_setting, "Wavefront Setting") self.tabs_plots_setting = oasysgui.tabWidget(self.tab_plots) # PROPAGATION ------------------------------------------- tab_wav = oasysgui.createTabPage(self.tabs_plots_setting, "Propagation") wav_box = oasysgui.widgetBox(tab_wav, "Wavefront Parameters", addSpace=True, orientation="vertical") oasysgui.lineEdit(wav_box, self, "wf_photon_energy", "Photon Energy [eV]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_h_slit_gap", "H Slit Gap [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_v_slit_gap", "V Slit Gap [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_h_slit_points", "H Slit Points", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_v_slit_points", "V Slit Points", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_distance", "Propagation Distance [m]", labelWidth=260, valueType=float, orientation="horizontal") pre_box = oasysgui.widgetBox(tab_wav, "Precision Parameters", addSpace=False, orientation="vertical") oasysgui.lineEdit( pre_box, self, "wf_sampling_factor_for_adjusting_nx_ny", "Sampling factor for adjusting nx/ny\n(effective if > 0)", labelWidth=260, valueType=int, orientation="horizontal") gui.rubber(self.controlArea) def runSRWSource(self): self.setStatusMessage("") self.progressBarInit() try: self.checkFields() srw_source = self.get_srw_source() srw_source.name = self.source_name if not self.source_name is None else self.windowTitle( ), self.progressBarSet(10) self.setStatusMessage("Running SRW") sys.stdout = EmittingStream(textWritten=self.writeStdOut) self.progressBarSet(20) self.setStatusMessage("") beamline = SRWBeamline(light_source=srw_source) wavefront = self.calculate_wavefront_propagation(srw_source) tickets = [] if self.is_do_plots(): self.setStatusMessage("Plotting Results") self.run_calculation_intensity(wavefront, tickets) self.plot_results(tickets) self.setStatusMessage("") self.send("SRWData", SRWData(srw_beamline=beamline, srw_wavefront=wavefront)) except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) if self.IS_DEVELOP: raise exception self.progressBarFinished() def sendNewWavefront(self, trigger): if trigger and trigger.new_object == True: self.runSRWSource() def get_srw_source(self): return SRWGaussianLightSource( beam_center_at_waist_x=self.beam_center_at_waist_x, beam_center_at_waist_y=self.beam_center_at_waist_y, beam_center_at_waist_z=self.beam_center_at_waist_z, average_angle_at_waist_x=self.average_angle_at_waist_x, average_angle_at_waist_y=self.average_angle_at_waist_y, photon_energy=self.wf_photon_energy, energy_per_pulse=self.energy_per_pulse, repetition_rate=self.repetition_rate, polarization=self.polarization + 1, horizontal_sigma_at_waist=self.horizontal_sigma_at_waist, vertical_sigma_at_waist=self.vertical_sigma_at_waist, pulse_duration=self.pulse_duration, transverse_gauss_hermite_mode_order_x=self. transverse_gauss_hermite_mode_order_x, transverse_gauss_hermite_mode_order_y=self. transverse_gauss_hermite_mode_order_y) def checkFields(self): congruence.checkPositiveNumber(self.energy_per_pulse, "Energy per pulse") congruence.checkPositiveNumber(self.horizontal_sigma_at_waist, "\u03c3x at waist") congruence.checkPositiveNumber(self.vertical_sigma_at_waist, "\u03c3y at waist") congruence.checkPositiveNumber(self.pulse_duration, "Pulse duration") congruence.checkPositiveNumber( self.transverse_gauss_hermite_mode_order_x, "Transverse Gauss-Hermite mode order x") congruence.checkPositiveNumber( self.transverse_gauss_hermite_mode_order_y, "Transverse Gauss-Hermite mode order y") # WAVEFRONT congruence.checkStrictlyPositiveNumber( self.wf_photon_energy, "Wavefront Propagation Photon Energy") congruence.checkStrictlyPositiveNumber( self.wf_h_slit_gap, "Wavefront Propagation H Slit Gap") congruence.checkStrictlyPositiveNumber( self.wf_v_slit_gap, "Wavefront Propagation V Slit Gap") congruence.checkStrictlyPositiveNumber( self.wf_h_slit_points, "Wavefront Propagation H Slit Points") congruence.checkStrictlyPositiveNumber( self.wf_v_slit_points, "Wavefront Propagation V Slit Points") congruence.checkPositiveNumber(self.wf_distance, "Wavefront Propagation Distance") congruence.checkPositiveNumber( self.wf_sampling_factor_for_adjusting_nx_ny, "Wavefront Propagation Sampling Factor for adjusting nx/ny") def run_calculation_intensity(self, srw_wavefront, tickets, progress_bar_value=30): e, h, v, i = srw_wavefront.get_intensity(multi_electron=False) tickets.append( SRWPlot.get_ticket_2D(h * 1000, v * 1000, i[int(e.size / 2)])) self.progressBarSet(progress_bar_value) e, h, v, i = srw_wavefront.get_phase() tickets.append( SRWPlot.get_ticket_2D(h * 1000, v * 1000, i[int(e.size / 2)])) self.progressBarSet(progress_bar_value + 20) def calculate_wavefront_propagation(self, srw_source): wf_parameters = WavefrontParameters( photon_energy_min=self.wf_photon_energy, photon_energy_max=self.wf_photon_energy, photon_energy_points=1, h_slit_gap=self.wf_h_slit_gap, v_slit_gap=self.wf_v_slit_gap, h_slit_points=self.wf_h_slit_points, v_slit_points=self.wf_v_slit_points, distance=self.wf_distance, wavefront_precision_parameters=WavefrontPrecisionParameters( sampling_factor_for_adjusting_nx_ny=self. wf_sampling_factor_for_adjusting_nx_ny)) return srw_source.get_SRW_Wavefront( source_wavefront_parameters=wf_parameters) def receive_syned_data(self, data): if not data is None: QMessageBox.critical( self, "Error", "Syned data not supported for Gaussian Light Source", QMessageBox.Ok) def getVariablesToPlot(self): return [[1, 2], [1, 2]] def getTitles(self, with_um=False): if with_um: return ["Intensity [ph/s/.1%bw/mm\u00b2]", "Phase [rad]"] else: return ["Intensity", "Phase"] def getXTitles(self): return ["X [\u03bcm]", "X [\u03bcm]"] def getYTitles(self): return ["Y [\u03bcm]", "Y [\u03bcm]"] def getXUM(self): return ["X [\u03bcm]", "X [\u03bcm]"] def getYUM(self): return ["Y [\u03bcm]", "Y [\u03bcm]"]
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 OWws(XoppyWidget, WidgetDecorator): name = "WS" id = "orange.widgets.dataws" description = "Wiggler Spectrum on a Screen" icon = "icons/xoppy_ws.png" priority = 11 category = "" keywords = ["xoppy", "ws"] ENERGY = Setting(7.0) CUR = Setting(100.0) PERIOD = Setting(8.5) N = Setting(28) KX = Setting(0.0) KY = Setting(8.74) EMIN = Setting(1000.0) EMAX = Setting(200000.0) NEE = Setting(500) D = Setting(30.0) XPC = Setting(0.0) YPC = Setting(0.0) XPS = Setting(2.0) YPS = Setting(2.0) NXP = Setting(10) NYP = Setting(10) inputs = WidgetDecorator.syned_input_data() def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ENERGY = oasysgui.lineEdit(box1, self, "ENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_CUR = oasysgui.lineEdit(box1, self, "CUR", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_PERIOD = oasysgui.lineEdit(box1, self, "PERIOD", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_N = oasysgui.lineEdit(box1, self, "N", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) # COMMENTED AS IT IS NOT IMPLEMENTED!! #widget index 5 # idx += 1 # box1 = gui.widgetBox(box) # oasysgui.lineEdit(box1, self, "KX", # label=self.unitLabels()[idx], addSpace=False, # valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) # self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_KY = oasysgui.lineEdit(box1, self, "KY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "EMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "EMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NEE", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "D", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "XPC", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "YPC", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "XPS", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "YPS", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NXP", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 16 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NYP", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): # return ['Beam energy (GeV)','Beam current (mA)','Period (cm)','Number of periods','Kx','Ky','Min energy (eV)','Max energy (eV)','Number of energy steps','Distance (m)','X-pos. (mm)','Y-pos. (mm)','X slit [mm or mrad]','Y slit [mm or mrad]','Integration points X','Integration points Y'] return [ 'Beam energy (GeV)', 'Beam current (mA)', 'Period (cm)', 'Number of periods', 'Ky', 'Min energy (eV)', 'Max energy (eV)', 'Number of energy steps', 'Distance (m)', 'X-pos. (mm)', 'Y-pos. (mm)', 'X slit [mm or mrad]', 'Y slit [mm or mrad]', 'Integration points X', 'Integration points Y' ] def unitFlags(self): return [ 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True', 'True' ] def get_help_name(self): return 'ws' def check_fields(self): self.ENERGY = congruence.checkStrictlyPositiveNumber( self.ENERGY, "Beam Energy") self.CUR = congruence.checkStrictlyPositiveNumber( self.CUR, "Beam Current") self.PERIOD = congruence.checkStrictlyPositiveNumber( self.PERIOD, "Period") self.N = congruence.checkStrictlyPositiveNumber( self.N, "Number of Periods") self.KX = congruence.checkNumber(self.KX, "Kx") self.KY = congruence.checkNumber(self.KY, "Ky") self.EMIN = congruence.checkPositiveNumber(self.EMIN, "Min Energy") self.EMAX = congruence.checkStrictlyPositiveNumber( self.EMAX, "Max Energy") congruence.checkLessThan(self.EMIN, self.EMAX, "Min Energy", "Max Energy") self.NEE = congruence.checkStrictlyPositiveNumber( self.NEE, "Number of energy steps") self.D = congruence.checkPositiveNumber(self.D, "Distance") self.XPC = congruence.checkNumber(self.XPC, "X-pos") self.YPC = congruence.checkNumber(self.YPC, "Y-pos") self.XPS = congruence.checkNumber(self.XPS, "X slit") self.YPS = congruence.checkNumber(self.YPS, "Y Slit") self.NXP = congruence.checkStrictlyPositiveNumber( self.NXP, "Integration points X") self.NYP = congruence.checkStrictlyPositiveNumber( self.NYP, "Integration points Y") def do_xoppy_calculation(self): return xoppy_calc_ws(ENERGY=self.ENERGY, CUR=self.CUR, PERIOD=self.PERIOD, N=self.N, KX=self.KX, KY=self.KY, EMIN=self.EMIN, EMAX=self.EMAX, NEE=self.NEE, D=self.D, XPC=self.XPC, YPC=self.YPC, XPS=self.XPS, YPS=self.YPS, NXP=self.NXP, NYP=self.NYP) def get_data_exchange_widget_name(self): return "WS" def getTitles(self): return ['Flux', 'Spectral power', 'Cumulated power'] def getXTitles(self): return ["Energy [eV]", "Energy [eV]", "Energy [eV]"] def getYTitles(self): return [ "Flux [Photons/sec/0.1%bw]", "Spectral Power [W/eV]", "Cumulated Power [W]" ] def getVariablesToPlot(self): return [(0, 1), (0, 2), (0, 3)] def getLogPlot(self): return [(True, True), (True, True), (False, False)] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.N = int( light_source._magnetic_structure._number_of_periods) self.ENERGY = light_source._electron_beam._energy_in_GeV self.CUR = 1e3 * light_source._electron_beam._current self.PERIOD = 1e2 * light_source._magnetic_structure._period_length self.KY = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) else: self.set_enabled(True) def set_enabled(self, value): if value == True: self.id_N.setEnabled(True) self.id_ENERGY.setEnabled(True) self.id_CUR.setEnabled(True) self.id_PERIOD.setEnabled(True) self.id_KY.setEnabled(True) else: self.id_N.setEnabled(False) self.id_ENERGY.setEnabled(False) self.id_CUR.setEnabled(False) self.id_PERIOD.setEnabled(False) self.id_KY.setEnabled(False)
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 OWSRWSource(SRWWavefrontViewer, WidgetDecorator): maintainer = "Luca Rebuffi" maintainer_email = "lrebuffi(@at@)anl.gov" category = "Sources" keywords = ["data", "file", "load", "read"] inputs = WidgetDecorator.syned_input_data() inputs.append(("SynedData#2", Beamline, "receive_syned_data")) inputs.append(("Trigger", TriggerOut, "sendNewWavefront")) outputs = [{"name":"SRWData", "type":SRWData, "doc":"SRW Source Data", "id":"data"}] want_main_area=1 source_name = None electron_energy_in_GeV = Setting(2.0) electron_energy_spread = Setting(0.0007) ring_current = Setting(0.4) electron_beam_size_h = Setting(5.5453e-05) electron_beam_size_v = Setting(2.784e-06) electron_beam_divergence_h = Setting(4.5083e-06) electron_beam_divergence_v = Setting(8.98e-07) moment_x = Setting(0.0) moment_y = Setting(0.0) moment_z = Setting(0.0) moment_xp = Setting(0.0) moment_yp = Setting(0.0) moment_xx = Setting((0.05545e-3)**2) moment_xxp = Setting(0.0) moment_xpxp = Setting((4.5083e-06)**2) moment_yy = Setting((2.784e-6)**2) moment_yyp = Setting(0.0) moment_ypyp = Setting((8.98e-07)**2) horizontal_emittance = Setting(0.0) horizontal_beta = Setting(0.0) horizontal_alpha = Setting(0.0) horizontal_eta = Setting(0.0) horizontal_etap = Setting(0.0) vertical_emittance= Setting(0.0) vertical_beta = Setting(0.0) vertical_alpha = Setting(0.0) vertical_eta = Setting(0.0) vertical_etap = Setting(0.0) type_of_properties = Setting(1) type_of_initialization = Setting(0) wf_photon_energy = Setting(8000.0) wf_h_slit_gap = Setting(0.001) wf_v_slit_gap =Setting( 0.001) wf_h_slit_points=Setting(100) wf_v_slit_points=Setting(100) wf_distance = Setting(10.0) wf_sr_method = Setting(1) wf_relative_precision = Setting(0.01) wf_start_integration_longitudinal_position = Setting(0.0) wf_end_integration_longitudinal_position = Setting(0.0) wf_number_of_points_for_trajectory_calculation = Setting(50000) wf_use_terminating_terms = Setting(1) wf_sampling_factor_for_adjusting_nx_ny = Setting(0.0) TABS_AREA_HEIGHT = 618 CONTROL_AREA_WIDTH = 405 def __init__(self): super().__init__(show_general_option_box=False, show_automatic_box=False) self.runaction = widget.OWAction("Run SRW", self) self.runaction.triggered.connect(self.runSRWSource) self.addAction(self.runaction) button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal") button = gui.button(button_box, self, "Run SRW Source", callback=self.runSRWSource) 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) self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH) 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_source = oasysgui.createTabPage(self.tabs_setting, "Light Source Setting") left_box_1 = oasysgui.widgetBox(self.tab_source, "Electron Beam Parameters", addSpace=True, orientation="vertical", height=380) oasysgui.lineEdit(left_box_1, self, "electron_energy_in_GeV", "Energy [GeV]", labelWidth=260, valueType=float, orientation="horizontal", callback=self.callback_electron_energy) oasysgui.lineEdit(left_box_1, self, "electron_energy_spread", "Energy Spread", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_1, self, "ring_current", "Ring Current [A]", labelWidth=260, valueType=float, orientation="horizontal") tab_electron = oasysgui.tabWidget(left_box_1) tab_beam = oasysgui.createTabPage(tab_electron, "Beam") tab_traj = oasysgui.createTabPage(tab_electron, "Trajectory") gui.separator(tab_beam) gui.comboBox(tab_beam, self, "type_of_properties", label="Electron Beam Properties", labelWidth=350, items=["From 2nd Moments", "From Size/Divergence", "From Twiss"], callback=self.set_TypeOfProperties, sendSelectedValue=False, orientation="horizontal") self.left_box_2_1 = oasysgui.widgetBox(tab_beam, "", addSpace=False, orientation="vertical", height=185) gui.separator(self.left_box_2_1) oasysgui.lineEdit(self.left_box_2_1, self, "moment_xx", "\u03c3x\u22c5\u03c3x [m\u00b2]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_1, self, "moment_xxp", "\u03c3x\u22c5\u03c3x' [m\u22c5rad]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_1, self, "moment_xpxp", "\u03c3x'\u22c5\u03c3x' [rad\u00b2]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_1, self, "moment_yy", "\u03c3y\u22c5\u03c3y [m\u00b2]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_1, self, "moment_yyp", "\u03c3y\u22c5\u03c3y' [m\u22c5rad]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_1, self, "moment_ypyp", "\u03c3y'\u22c5\u03c3y' [rad\u00b2]", labelWidth=200, valueType=float, orientation="horizontal") self.left_box_2_2 = oasysgui.widgetBox(tab_beam, "", addSpace=False, orientation="vertical", height=185) gui.separator(self.left_box_2_2) oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_size_h", "\u03c3x [m]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_size_v", "\u03c3y [m]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_divergence_h", "\u03c3x' [rad]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_2_2, self, "electron_beam_divergence_v", "\u03c3y' [rad]", labelWidth=200, valueType=float, orientation="horizontal") self.left_box_2_3 = oasysgui.widgetBox(tab_beam, "", addSpace=False, orientation="horizontal", height=185) left_box_2_3_l = oasysgui.widgetBox(self.left_box_2_3, "", addSpace=False, orientation="vertical", height=185) left_box_2_3_r = oasysgui.widgetBox(self.left_box_2_3, "", addSpace=False, orientation="vertical", height=185) gui.separator(left_box_2_3_l) gui.separator(left_box_2_3_r) oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_emittance", "Emittance x [m]", labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_beta" , "\u03B2x [m]" , labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_alpha" , "\u03B1x [rad]" , labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_eta" , "\u03B7x [m]" , labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_l, self, "horizontal_etap" , "\u03B7x' [rad]" , labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_r, self, "vertical_emittance" , "Emittance y [m]", labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_r, self, "vertical_beta" , "\u03B2y [m]" , labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_r, self, "vertical_alpha" , "\u03B1y [rad]" , labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_r, self, "vertical_eta" , "\u03B7y [m]" , labelWidth=100, valueType=float, orientation="horizontal") oasysgui.lineEdit(left_box_2_3_r, self, "vertical_etap" , "\u03B7y' [rad]" , labelWidth=100, valueType=float, orientation="horizontal") self.set_TypeOfProperties() gui.comboBox(tab_traj, self, "type_of_initialization", label="Trajectory Initialization", labelWidth=140, items=["At Zero Point", "At Fixed Position", "Sampled from Phase Space"], callback=self.set_TypeOfInitialization, sendSelectedValue=False, orientation="horizontal") self.left_box_3_1 = oasysgui.widgetBox(tab_traj, "", addSpace=False, orientation="vertical", height=160) self.left_box_3_2 = oasysgui.widgetBox(tab_traj, "", addSpace=False, orientation="vertical", height=160) oasysgui.lineEdit(self.left_box_3_1, self, "moment_x", "x\u2080 [m]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_3_1, self, "moment_y", "y\u2080 [m]", labelWidth=200, valueType=float, orientation="horizontal") box = oasysgui.widgetBox(self.left_box_3_1, "", addSpace=False, orientation="horizontal") oasysgui.lineEdit(box, self, "moment_z", "z\u2080 [m]", labelWidth=160, valueType=float, orientation="horizontal") gui.button(box, self, "Auto", width=35, callback=self.set_z0Default) oasysgui.lineEdit(self.left_box_3_1, self, "moment_xp", "x'\u2080 [rad]", labelWidth=200, valueType=float, orientation="horizontal") oasysgui.lineEdit(self.left_box_3_1, self, "moment_yp", "y'\u2080 [rad]", labelWidth=200, valueType=float, orientation="horizontal") self.set_TypeOfInitialization() self.tab_plots = oasysgui.createTabPage(self.tabs_setting, "Wavefront Setting") self.tabs_plots_setting = oasysgui.tabWidget(self.tab_plots) # PROPAGATION ------------------------------------------- tab_wav = oasysgui.createTabPage(self.tabs_plots_setting, "Propagation") wav_box = oasysgui.widgetBox(tab_wav, "Wavefront Parameters", addSpace=True, orientation="vertical") self.build_wf_photon_energy_box(wav_box) oasysgui.lineEdit(wav_box, self, "wf_h_slit_gap", "H Slit Gap [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_v_slit_gap", "V Slit Gap [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_h_slit_points", "H Slit Points", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_v_slit_points", "V Slit Points", labelWidth=260, valueType=int, orientation="horizontal") oasysgui.lineEdit(wav_box, self, "wf_distance", "Propagation Distance [m]", labelWidth=260, valueType=float, orientation="horizontal") pre_box = oasysgui.widgetBox(tab_wav, "Precision Parameters", addSpace=False, orientation="vertical") gui.comboBox(pre_box, self, "wf_sr_method", label="Calculation Method", items=["Manual", "Auto"], labelWidth=260, sendSelectedValue=False, orientation="horizontal") oasysgui.lineEdit(pre_box, self, "wf_relative_precision", "Relative Precision", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(pre_box, self, "wf_start_integration_longitudinal_position", "Longitudinal position to start integration\n(effective if < zEndInteg) [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(pre_box, self, "wf_end_integration_longitudinal_position", "Longitudinal position to finish integration\n(effective if > zStartInteg) [m]", labelWidth=260, valueType=float, orientation="horizontal") oasysgui.lineEdit(pre_box, self, "wf_number_of_points_for_trajectory_calculation", "Number of points for trajectory calculation", labelWidth=260, valueType=int, orientation="horizontal") gui.comboBox(pre_box, self, "wf_use_terminating_terms", label="Use \"terminating terms\"\n(i.e. asymptotic expansions at zStartInteg\nand zEndInteg) or not", items=["No", "Yes"], labelWidth=260, sendSelectedValue=False, orientation="horizontal") oasysgui.lineEdit(pre_box, self, "wf_sampling_factor_for_adjusting_nx_ny", "Sampling factor for adjusting nx/ny\n(effective if > 0)", labelWidth=260, valueType=int, orientation="horizontal") gui.rubber(self.controlArea) def set_TypeOfProperties(self): self.left_box_2_1.setVisible(self.type_of_properties==0) self.left_box_2_2.setVisible(self.type_of_properties==1) self.left_box_2_3.setVisible(self.type_of_properties==2) def set_TypeOfInitialization(self): self.left_box_3_1.setVisible(self.type_of_initialization==1) self.left_box_3_2.setVisible(self.type_of_initialization!=1) def build_wf_photon_energy_box(self, box): oasysgui.lineEdit(box, self, "wf_photon_energy", "Photon Energy [eV]", labelWidth=260, valueType=float, orientation="horizontal") def runSRWSource(self): self.setStatusMessage("") self.progressBarInit() try: self.checkFields() srw_source = self.get_srw_source(self.get_electron_beam()) srw_source.name = self.source_name if not self.source_name is None else self.windowTitle(), self.progressBarSet(10) self.setStatusMessage("Running SRW") sys.stdout = EmittingStream(textWritten=self.writeStdOut) self.print_specific_infos(srw_source) self.progressBarSet(20) self.setStatusMessage("") beamline = SRWBeamline(light_source=srw_source) self.output_wavefront = self.calculate_wavefront_propagation(srw_source) if self.is_do_plots(): self.setStatusMessage("Plotting Results") tickets = [] self.run_calculation_for_plots(tickets, 50) self.plot_results(tickets, 80) self.setStatusMessage("") self.send("SRWData", SRWData(srw_beamline=beamline, srw_wavefront=self.output_wavefront)) except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) if self.IS_DEVELOP: raise exception self.progressBarFinished() def sendNewWavefront(self, trigger): if trigger and trigger.new_object == True: self.runSRWSource() def get_electron_beam(self): if self.type_of_initialization == 2: electron_beam = SRWElectronBeam(energy_in_GeV=numpy.random.normal(self.electron_energy_in_GeV, self.electron_energy_spread*self.electron_energy_in_GeV), energy_spread=self.electron_energy_spread, current=self.ring_current) else: electron_beam = SRWElectronBeam(energy_in_GeV=self.electron_energy_in_GeV, energy_spread=self.electron_energy_spread, current=self.ring_current) if self.type_of_properties == 0: electron_beam._moment_xx = self.moment_xx electron_beam._moment_xxp = self.moment_xxp electron_beam._moment_xpxp = self.moment_xpxp electron_beam._moment_yy = self.moment_yy electron_beam._moment_yyp = self.moment_yyp electron_beam._moment_ypyp = self.moment_ypyp x, xp, y, yp = electron_beam.get_sigmas_all() self.electron_beam_size_h = x self.electron_beam_size_v = y self.electron_beam_divergence_h = xp self.electron_beam_divergence_v = yp elif self.type_of_properties == 1: electron_beam.set_sigmas_all(sigma_x=self.electron_beam_size_h, sigma_y=self.electron_beam_size_v, sigma_xp=self.electron_beam_divergence_h, sigma_yp=self.electron_beam_divergence_v) self.moment_xx = electron_beam._moment_xx self.moment_xpxp = electron_beam._moment_xpxp self.moment_yy = electron_beam._moment_yy self.moment_ypyp = electron_beam._moment_ypyp elif self.type_of_properties == 2: electron_beam.set_moments_from_twiss(horizontal_emittance = self.horizontal_emittance, horizontal_beta = self.horizontal_beta, horizontal_alpha = self.horizontal_alpha, horizontal_eta = self.horizontal_eta, horizontal_etap = self.horizontal_etap, vertical_emittance = self.vertical_emittance, vertical_beta = self.vertical_beta, vertical_alpha = self.vertical_alpha, vertical_eta = self.vertical_eta, vertical_etap = self.vertical_etap) self.moment_xx = electron_beam._moment_xx self.moment_xpxp = electron_beam._moment_xpxp self.moment_yy = electron_beam._moment_yy self.moment_ypyp = electron_beam._moment_ypyp x, xp, y, yp = electron_beam.get_sigmas_all() self.electron_beam_size_h = round(x, 9) self.electron_beam_size_v = round(y, 9) self.electron_beam_divergence_h = round(xp, 10) self.electron_beam_divergence_v = round(yp, 10) if self.type_of_initialization == 0: # zero self.moment_x = 0.0 self.moment_y = 0.0 self.moment_z = self.get_default_initial_z() self.moment_xp = 0.0 self.moment_yp = 0.0 elif self.type_of_initialization == 2: # sampled self.moment_x = numpy.random.normal(0.0, self.electron_beam_size_h) self.moment_y = numpy.random.normal(0.0, self.electron_beam_size_v) self.moment_z = self.get_default_initial_z() self.moment_xp = numpy.random.normal(0.0, self.electron_beam_divergence_h) self.moment_yp = numpy.random.normal(0.0, self.electron_beam_divergence_v) electron_beam._moment_x = self.moment_x electron_beam._moment_y = self.moment_y electron_beam._moment_z = self.moment_z electron_beam._moment_xp = self.moment_xp electron_beam._moment_yp = self.moment_yp print("\n", "Electron Trajectory Initialization:") print("X0: ", electron_beam._moment_x) print("Y0: ", electron_beam._moment_y) print("Z0: ", electron_beam._moment_z) print("XP0: ", electron_beam._moment_xp) print("YP0: ", electron_beam._moment_yp) print("E0: ", electron_beam._energy_in_GeV, "\n") return electron_beam def set_z0Default(self): self.moment_z = self.get_default_initial_z() def get_default_initial_z(self): return NotImplementedError() def get_srw_source(self, electron_beam=ElectronBeam()): raise NotImplementedError() def checkFields(self): congruence.checkStrictlyPositiveNumber(self.electron_energy_in_GeV, "Energy") congruence.checkPositiveNumber(self.electron_energy_spread, "Energy Spread") congruence.checkStrictlyPositiveNumber(self.ring_current, "Ring Current") if self.type_of_properties == 0: congruence.checkPositiveNumber(self.moment_xx , "Moment xx") congruence.checkPositiveNumber(self.moment_xpxp , "Moment xpxp") congruence.checkPositiveNumber(self.moment_yy , "Moment yy") congruence.checkPositiveNumber(self.moment_ypyp , "Moment ypyp") elif self.type_of_properties == 1: congruence.checkPositiveNumber(self.electron_beam_size_h , "Horizontal Beam Size") congruence.checkPositiveNumber(self.electron_beam_divergence_h , "Vertical Beam Size") congruence.checkPositiveNumber(self.electron_beam_size_v , "Horizontal Beam Divergence") congruence.checkPositiveNumber(self.electron_beam_divergence_v , "Vertical Beam Divergence") elif self.type_of_properties == 2: congruence.checkPositiveNumber(self.horizontal_emittance , "Horizontal Emittance") congruence.checkPositiveNumber(self.vertical_emittance , "Vertical Emittance") self.checkLightSourceSpecificFields() if self.type_of_initialization == 2: congruence.checkNumber(self.moment_x , "x0") congruence.checkNumber(self.moment_xp , "xp0") congruence.checkNumber(self.moment_y , "y0") congruence.checkNumber(self.moment_yp , "yp0") congruence.checkNumber(self.moment_z , "z0") # WAVEFRONT self.checkWavefrontPhotonEnergy() congruence.checkStrictlyPositiveNumber(self.wf_h_slit_gap, "Wavefront Propagation H Slit Gap") congruence.checkStrictlyPositiveNumber(self.wf_v_slit_gap, "Wavefront Propagation V Slit Gap") congruence.checkStrictlyPositiveNumber(self.wf_h_slit_points, "Wavefront Propagation H Slit Points") congruence.checkStrictlyPositiveNumber(self.wf_v_slit_points, "Wavefront Propagation V Slit Points") congruence.checkGreaterOrEqualThan(self.wf_distance, self.get_minimum_propagation_distance(), "Wavefront Propagation Distance", "Minimum Distance out of the Source: " + str(self.get_minimum_propagation_distance())) congruence.checkStrictlyPositiveNumber(self.wf_relative_precision, "Wavefront Propagation Relative Precision") congruence.checkStrictlyPositiveNumber(self.wf_number_of_points_for_trajectory_calculation, "Wavefront Propagation Number of points for trajectory calculation") congruence.checkPositiveNumber(self.wf_sampling_factor_for_adjusting_nx_ny, "Wavefront Propagation Sampling Factor for adjusting nx/ny") def checkLightSourceSpecificFields(self): raise NotImplementedError() def checkWavefrontPhotonEnergy(self): congruence.checkStrictlyPositiveNumber(self.wf_photon_energy, "Wavefront Propagation Photon Energy") def run_calculation_for_plots(self, tickets, progress_bar_value): if not self.output_wavefront is None: if self.view_type == 1: e, h, v, i = self.output_wavefront.get_intensity(multi_electron=False) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) self.progressBarSet(progress_bar_value) e, h, v, i = self.output_wavefront.get_phase() tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) self.progressBarSet(progress_bar_value + 10) e, h, v, i = self.output_wavefront.get_intensity(multi_electron=True) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) self.progressBarSet(progress_bar_value + 20) elif self.view_type == 2: e, h, v, i = self.output_wavefront.get_intensity(multi_electron=False, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_HORIZONTAL) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) self.progressBarSet(progress_bar_value) #-- e, h, v, i = self.output_wavefront.get_intensity(multi_electron=False, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_VERTICAL) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) #-- e, h, v, i = self.output_wavefront.get_phase(polarization_component_to_be_extracted=PolarizationComponent.LINEAR_HORIZONTAL) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) self.progressBarSet(progress_bar_value + 10) e, h, v, i = self.output_wavefront.get_phase(polarization_component_to_be_extracted=PolarizationComponent.LINEAR_VERTICAL) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) #-- e, h, v, i = self.output_wavefront.get_intensity(multi_electron=True, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_HORIZONTAL) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) self.progressBarSet(progress_bar_value + 20) e, h, v, i = self.output_wavefront.get_intensity(multi_electron=True, polarization_component_to_be_extracted=PolarizationComponent.LINEAR_VERTICAL) tickets.append(SRWPlot.get_ticket_2D(h*1000, v*1000, i[int(e.size/2)])) def get_automatic_sr_method(self): raise NotImplementedError() def calculate_wavefront_propagation(self, srw_source): photon_energy = self.get_photon_energy_for_wavefront_propagation(srw_source) wf_parameters = WavefrontParameters(photon_energy_min = photon_energy, photon_energy_max = photon_energy, photon_energy_points=1, h_slit_gap = self.wf_h_slit_gap, v_slit_gap = self.wf_v_slit_gap, h_slit_points=self.wf_h_slit_points, v_slit_points=self.wf_v_slit_points, distance = self.wf_distance, wavefront_precision_parameters=WavefrontPrecisionParameters(sr_method=0 if self.wf_sr_method == 0 else self.get_automatic_sr_method(), relative_precision=self.wf_relative_precision, start_integration_longitudinal_position=self.wf_start_integration_longitudinal_position, end_integration_longitudinal_position=self.wf_end_integration_longitudinal_position, number_of_points_for_trajectory_calculation=self.wf_number_of_points_for_trajectory_calculation, use_terminating_terms=self.wf_use_terminating_terms, sampling_factor_for_adjusting_nx_ny=self.wf_sampling_factor_for_adjusting_nx_ny)) return srw_source.get_SRW_Wavefront(source_wavefront_parameters=wf_parameters) def get_photon_energy_for_wavefront_propagation(self, srw_source): return self.wf_photon_energy def get_minimum_propagation_distance(self): return round(self.get_source_length()*1.01, 6) def get_source_length(self): raise NotImplementedError() def receive_syned_data(self, data): if not data is None: try: if data.get_beamline_elements_number() > 0: slit_element = data.get_beamline_element_at(0) slit = slit_element.get_optical_element() coordinates = slit_element.get_coordinates() if isinstance(slit, Slit) and isinstance(slit.get_boundary_shape(), Rectangle): rectangle = slit.get_boundary_shape() self.wf_h_slit_gap = rectangle._x_right - rectangle._x_left self.wf_v_slit_gap = rectangle._y_top - rectangle._y_bottom self.wf_distance = coordinates.p() self.int_h_slit_gap = rectangle._x_right - rectangle._x_left self.int_v_slit_gap = rectangle._y_top - rectangle._y_bottom self.int_distance = coordinates.p() self.spe_h_slit_gap = rectangle._x_right - rectangle._x_left self.spe_v_slit_gap = rectangle._y_top - rectangle._y_bottom self.spe_distance = coordinates.p() elif not data._light_source is None and isinstance(data._light_source, LightSource): light_source = data._light_source self.source_name = light_source._name self.electron_energy_in_GeV = light_source._electron_beam._energy_in_GeV self.electron_energy_spread = light_source._electron_beam._energy_spread self.ring_current = light_source._electron_beam._current self.moment_xx = light_source._electron_beam._moment_xx self.moment_xxp = light_source._electron_beam._moment_xxp self.moment_xpxp = light_source._electron_beam._moment_xpxp self.moment_yy = light_source._electron_beam._moment_yy self.moment_yyp = light_source._electron_beam._moment_yyp self.moment_ypyp = light_source._electron_beam._moment_ypyp x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.electron_beam_size_h = round(x, 9) self.electron_beam_size_v = round(y, 9) self.electron_beam_divergence_h = round(xp, 10) self.electron_beam_divergence_v = round(yp, 10) self.type_of_properties = 0 self.set_TypeOfProperties() self.receive_specific_syned_data(data) else: raise ValueError("Syned data not correct") except Exception as exception: QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) def receive_specific_syned_data(self, data): raise NotImplementedError() def callback_electron_energy(self): pass
class OWundulator_power_density(XoppyWidget, WidgetDecorator): name = "Undulator Power Density" id = "orange.widgets.dataundulator_power_density" description = "Undulator Power Density" icon = "icons/xoppy_undulator_power_density.png" priority = 3 category = "" keywords = ["xoppy", "undulator_power_density"] USEEMITTANCES = Setting(1) ELECTRONENERGY = Setting(6.04) ELECTRONENERGYSPREAD = Setting(0.001) ELECTRONCURRENT = Setting(0.2) ELECTRONBEAMSIZEH = Setting(0.000395) ELECTRONBEAMSIZEV = Setting(9.9e-06) ELECTRONBEAMDIVERGENCEH = Setting(1.05e-05) ELECTRONBEAMDIVERGENCEV = Setting(3.9e-06) PERIODID = Setting(0.018) NPERIODS = Setting(222) KV = Setting(1.68) KH = Setting(0.0) KPHASE = Setting(0.0) DISTANCE = Setting(30.0) GAPH = Setting(0.01) GAPV = Setting(0.01) HSLITPOINTS = Setting(41) VSLITPOINTS = Setting(41) METHOD = Setting(2) MASK_FLAG = Setting(0) MASK_ROT_H_DEG = Setting(0.0) MASK_ROT_V_DEG = Setting(0.0) MASK_H_MIN = Setting(-1000.0) MASK_H_MAX = Setting(1000.0) MASK_V_MIN = Setting(-1000.0) MASK_V_MAX = Setting(1000.0) H5_FILE_DUMP = Setting(0) inputs = WidgetDecorator.syned_input_data() def __init__(self): super().__init__(show_script_tab=True) def build_gui(self): box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 # # # idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "USEEMITTANCES", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 0 idx += 1 box1 = gui.widgetBox(box) # self.id_ELECTRONENERGY = oasysgui.lineEdit(box1, self, "ELECTRONENERGY", # label=self.unitLabels()[idx], addSpace=False, # valueType=float, orientation="horizontal", labelWidth=250) self.id_ELECTRONENERGY = oasysgui.lineEdit( box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGYSPREAD = oasysgui.lineEdit( box1, self, "ELECTRONENERGYSPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit( box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 4 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMSIZEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMSIZEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEH = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONBEAMDIVERGENCEV = oasysgui.lineEdit( box1, self, "ELECTRONBEAMDIVERGENCEV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_KV = oasysgui.lineEdit(box1, self, "KV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 B idx += 1 box1 = gui.widgetBox(box) self.id_KH = oasysgui.lineEdit(box1, self, "KH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 C idx += 1 box1 = gui.widgetBox(box) self.id_KPHASE = oasysgui.lineEdit(box1, self, "KPHASE", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPH", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 12 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "GAPV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "VSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['US', 'URGENT', 'SRW'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) # # Mask # #widget index 16 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "MASK_FLAG", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 17 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "MASK_ROT_H_DEG", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 18 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "MASK_ROT_V_DEG", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 19 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "MASK_H_MIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 20 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "MASK_H_MAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 21 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "MASK_V_MIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 22 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "MASK_V_MAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 23 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "H5_FILE_DUMP", label=self.unitLabels()[idx], addSpace=False, items=['No', 'Yes: undulator_power_density.h5'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return ["Use emittances","Electron Energy [GeV]", "Electron Energy Spread", "Electron Current [A]",\ "Electron Beam Size H [m]", "Electron Beam Size V [m]", "Electron Beam Divergence H [rad]", "Electron Beam Divergence V [rad]", \ "Period ID [m]", "Number of periods", "Kv [K value vertical field]", \ "Kh [K value horizontal field]","Kphase [Phase diff Kh-Kv in rad]",\ "Distance to slit [m]", "Slit gap H [m]", "Slit gap V [m]", "Number of slit mesh points in H", "Number of slit mesh points in V",\ "calculation code",\ "modify slit","Rotation around H axis [deg]","Rotation around V axis [deg]","Mask H min [mm]","Mask H max [mm]",'Mask V min [mm]',"Mask V max [mm]",\ "Dump hdf5 file"] def unitFlags(self): return ["True","True", "self.USEEMITTANCES == 1 and self.METHOD != 1", "True",\ "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", "self.USEEMITTANCES == 1", \ "True", "True", "True",\ "self.METHOD != 0","self.METHOD != 0",\ "True", "True", "True", "True", "True",\ "True",\ "True","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1","self.MASK_FLAG == 1",\ "True"] def get_help_name(self): return 'undulator_power_density' def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber( self.ELECTRONENERGY, "Electron Energy") if not self.METHOD == 1: self.ELECTRONENERGYSPREAD = congruence.checkPositiveNumber( self.ELECTRONENERGYSPREAD, "Electron Energy Spread") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber( self.ELECTRONCURRENT, "Electron Current") self.ELECTRONBEAMSIZEH = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEH, "Electron Beam Size H") self.ELECTRONBEAMSIZEV = congruence.checkPositiveNumber( self.ELECTRONBEAMSIZEV, "Electron Beam Size V") self.ELECTRONBEAMDIVERGENCEH = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEH, "Electron Beam Divergence H") self.ELECTRONBEAMDIVERGENCEV = congruence.checkPositiveNumber( self.ELECTRONBEAMDIVERGENCEV, "Electron Beam Divergence V") self.PERIODID = congruence.checkStrictlyPositiveNumber( self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber( self.NPERIODS, "Number of Periods") self.KV = congruence.checkPositiveNumber(self.KV, "Kv") self.KH = congruence.checkPositiveNumber(self.KH, "Kh") self.KPHASE = congruence.checkNumber(self.KPHASE, "Kphase") self.DISTANCE = congruence.checkPositiveNumber(self.DISTANCE, "Distance to slit") self.GAPH = congruence.checkPositiveNumber(self.GAPH, "Slit gap H") self.GAPV = congruence.checkPositiveNumber(self.GAPV, "Slit gap V") self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.HSLITPOINTS, "Number of slit mesh points in H") self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.VSLITPOINTS, "Number of slit mesh points in V") if self.METHOD == 1: # URGENT congruence.checkLessOrEqualThan( self.HSLITPOINTS, 51, "Number of slit mesh points for URGENT ", " 51") congruence.checkLessOrEqualThan( self.VSLITPOINTS, 51, "Number of slit mesh points for URGENT ", " 51") # if sys.platform == 'linux' and self.METHOD == 2: # raise Exception("SRW calculation code not supported under Linux") def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.initializeTabs( ) # added by srio to avoid overlapping graphs self.view_type_combo.setEnabled(False) data = calculated_data.get_content("xoppy_data") code = calculated_data.get_content("xoppy_code") h = data[0] v = data[1] p = data[2] try: print("\nResult arrays (shapes): ", h.shape, v.shape, p.shape) self.plot_data2D(p, h, v, 0, 0, xtitle='H [mm]', ytitle='V [mm]', title='Code ' + code + '; Power density [W/mm^2]') 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 do_xoppy_calculation(self): if self.H5_FILE_DUMP == 0: h5_file = "" else: h5_file = "undulator_power_density.h5" h5_parameters = { "ELECTRONENERGY": self.ELECTRONENERGY, "ELECTRONENERGYSPREAD": self.ELECTRONENERGYSPREAD, "ELECTRONCURRENT": self.ELECTRONCURRENT, "ELECTRONBEAMSIZEH": self.ELECTRONBEAMSIZEH, "ELECTRONBEAMSIZEV": self.ELECTRONBEAMSIZEV, "ELECTRONBEAMDIVERGENCEH": self.ELECTRONBEAMDIVERGENCEH, "ELECTRONBEAMDIVERGENCEV": self.ELECTRONBEAMDIVERGENCEV, "PERIODID": self.PERIODID, "NPERIODS": self.NPERIODS, "KV": self.KV, "KH": self.KH, "KPHASE": self.KPHASE, "DISTANCE": self.DISTANCE, "GAPH": self.GAPH, "GAPV": self.GAPV, "HSLITPOINTS": self.HSLITPOINTS, "VSLITPOINTS": self.VSLITPOINTS, "METHOD": self.METHOD, "USEEMITTANCES": self.USEEMITTANCES, "MASK_FLAG": self.MASK_FLAG, "MASK_ROT_H_DEG": self.MASK_ROT_H_DEG, "MASK_ROT_V_DEG": self.MASK_ROT_V_DEG, "MASK_H_MIN": self.MASK_H_MIN, "MASK_H_MAX": self.MASK_H_MAX, "MASK_V_MIN": self.MASK_V_MIN, "MASK_V_MAX": self.MASK_V_MAX, } h, v, p, code = xoppy_calc_undulator_power_density( ELECTRONENERGY=self.ELECTRONENERGY, ELECTRONENERGYSPREAD=self.ELECTRONENERGYSPREAD, ELECTRONCURRENT=self.ELECTRONCURRENT, ELECTRONBEAMSIZEH=self.ELECTRONBEAMSIZEH, ELECTRONBEAMSIZEV=self.ELECTRONBEAMSIZEV, ELECTRONBEAMDIVERGENCEH=self.ELECTRONBEAMDIVERGENCEH, ELECTRONBEAMDIVERGENCEV=self.ELECTRONBEAMDIVERGENCEV, PERIODID=self.PERIODID, NPERIODS=self.NPERIODS, KV=self.KV, KH=self.KH, KPHASE=self.KPHASE, DISTANCE=self.DISTANCE, GAPH=self.GAPH, GAPV=self.GAPV, HSLITPOINTS=self.HSLITPOINTS, VSLITPOINTS=self.VSLITPOINTS, METHOD=self.METHOD, USEEMITTANCES=self.USEEMITTANCES, MASK_FLAG=self.MASK_FLAG, MASK_ROT_H_DEG=self.MASK_ROT_H_DEG, MASK_ROT_V_DEG=self.MASK_ROT_V_DEG, MASK_H_MIN=self.MASK_H_MIN, MASK_H_MAX=self.MASK_H_MAX, MASK_V_MIN=self.MASK_V_MIN, MASK_V_MAX=self.MASK_V_MAX, h5_file=h5_file, h5_entry_name="XOPPY_POWERDENSITY", h5_initialize=True, h5_parameters=h5_parameters, ) self.xoppy_script.set_code( self.script_template().format_map(h5_parameters)) return h, v, p, code def script_template(self): return """ # # script to make the calculations (created by XOPPY:undulator_spectrum) # from orangecontrib.xoppy.util.xoppy_undulators import xoppy_calc_undulator_power_density h5_parameters = dict() h5_parameters["ELECTRONENERGY"]= {ELECTRONENERGY} h5_parameters["ELECTRONENERGYSPREAD"]= {ELECTRONENERGYSPREAD} h5_parameters["ELECTRONCURRENT"]= {ELECTRONCURRENT} h5_parameters["ELECTRONBEAMSIZEH"]= {ELECTRONBEAMSIZEH} h5_parameters["ELECTRONBEAMSIZEV"]= {ELECTRONBEAMSIZEV} h5_parameters["ELECTRONBEAMDIVERGENCEH"]= {ELECTRONBEAMDIVERGENCEH} h5_parameters["ELECTRONBEAMDIVERGENCEV"]= {ELECTRONBEAMDIVERGENCEV} h5_parameters["PERIODID"]= {PERIODID} h5_parameters["NPERIODS"]= {NPERIODS} h5_parameters["KV"]= {KV} h5_parameters["KH"]= {KH} h5_parameters["KPHASE"]= {KPHASE} h5_parameters["DISTANCE"]= {DISTANCE} h5_parameters["GAPH"]= {GAPH} h5_parameters["GAPV"]= {GAPV} h5_parameters["HSLITPOINTS"]= {HSLITPOINTS} h5_parameters["VSLITPOINTS"]= {VSLITPOINTS} h5_parameters["METHOD"]= {METHOD} h5_parameters["USEEMITTANCES"]= {USEEMITTANCES} h5_parameters["MASK_FLAG"]= {MASK_FLAG} h5_parameters["MASK_ROT_H_DEG"]= {MASK_ROT_H_DEG} h5_parameters["MASK_ROT_V_DEG"]= {MASK_ROT_V_DEG} h5_parameters["MASK_H_MIN"]= {MASK_H_MIN} h5_parameters["MASK_H_MAX"]= {MASK_H_MAX} h5_parameters["MASK_V_MIN"]= {MASK_V_MIN} h5_parameters["MASK_V_MAX"]= {MASK_V_MAX} h, v, p, code = xoppy_calc_undulator_power_density( ELECTRONENERGY = h5_parameters["ELECTRONENERGY"], ELECTRONENERGYSPREAD = h5_parameters["ELECTRONENERGYSPREAD"], ELECTRONCURRENT = h5_parameters["ELECTRONCURRENT"], ELECTRONBEAMSIZEH = h5_parameters["ELECTRONBEAMSIZEH"], ELECTRONBEAMSIZEV = h5_parameters["ELECTRONBEAMSIZEV"], ELECTRONBEAMDIVERGENCEH = h5_parameters["ELECTRONBEAMDIVERGENCEH"], ELECTRONBEAMDIVERGENCEV = h5_parameters["ELECTRONBEAMDIVERGENCEV"], PERIODID = h5_parameters["PERIODID"], NPERIODS = h5_parameters["NPERIODS"], KV = h5_parameters["KV"], KH = h5_parameters["KH"], KPHASE = h5_parameters["KPHASE"], DISTANCE = h5_parameters["DISTANCE"], GAPH = h5_parameters["GAPH"], GAPV = h5_parameters["GAPV"], HSLITPOINTS = h5_parameters["HSLITPOINTS"], VSLITPOINTS = h5_parameters["VSLITPOINTS"], METHOD = h5_parameters["METHOD"], USEEMITTANCES = h5_parameters["USEEMITTANCES"], MASK_FLAG = h5_parameters["MASK_FLAG"], MASK_ROT_H_DEG = h5_parameters["MASK_ROT_H_DEG"], MASK_ROT_V_DEG = h5_parameters["MASK_ROT_V_DEG"], MASK_H_MIN = h5_parameters["MASK_H_MIN"], MASK_H_MAX = h5_parameters["MASK_H_MAX"], MASK_V_MIN = h5_parameters["MASK_V_MIN"], MASK_V_MAX = h5_parameters["MASK_V_MAX"], h5_file = "undulator_power_density.h5", h5_entry_name = "XOPPY_POWERDENSITY", h5_initialize = True, h5_parameters = h5_parameters, ) # example plot from srxraylib.plot.gol import plot_image plot_image(p,h,v,xtitle="H [mm]",ytitle="V [mm]",title="Power density W/mm2") # # end script # """ def extract_data_from_xoppy_output(self, calculation_output): h, v, p, code = calculation_output calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", [h, v, p]) calculated_data.add_content("xoppy_code", code) return calculated_data def get_data_exchange_widget_name(self): return "UNDULATOR_POWER_DENSITY" def getTitles(self): return ['Undulator Power Density'] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONENERGYSPREAD = light_source._electron_beam._energy_spread self.ELECTRONCURRENT = light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.ELECTRONBEAMSIZEH = x self.ELECTRONBEAMSIZEV = y self.ELECTRONBEAMDIVERGENCEH = xp self.ELECTRONBEAMDIVERGENCEV = yp self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = light_source._magnetic_structure._number_of_periods self.KV = light_source._magnetic_structure._K_vertical self.KH = light_source._magnetic_structure._K_horizontal # TODO self.KPHASE = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self, value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONENERGYSPREAD.setEnabled(True) self.id_ELECTRONBEAMSIZEH.setEnabled(True) self.id_ELECTRONBEAMSIZEV.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(True) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KV.setEnabled(True) self.id_KH.setEnabled(True) self.id_KPHASE.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONENERGYSPREAD.setEnabled(False) self.id_ELECTRONBEAMSIZEH.setEnabled(False) self.id_ELECTRONBEAMSIZEV.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEH.setEnabled(False) self.id_ELECTRONBEAMDIVERGENCEV.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KV.setEnabled(False) self.id_KH.setEnabled(False) self.id_KPHASE.setEnabled(False)
class OWxtc(XoppyWidget): name = "TC" id = "orange.widgets.dataxtc" description = "Undulator Tuning Curves" icon = "icons/xoppy_xtc.png" priority = 7 category = "" keywords = ["xoppy", "xtc"] #19 variables (minus one: TITLE removed) ENERGY = Setting(7.0) CURRENT = Setting(100.0) ENERGY_SPREAD = Setting(0.00096) SIGX = Setting(0.274) SIGY = Setting(0.011) SIGX1 = Setting(0.0113) SIGY1 = Setting(0.0036) PERIOD = Setting(3.23) NP = Setting(70) EMIN = Setting(2950.0) EMAX = Setting(13500.0) N = Setting(40) HARMONIC_FROM = Setting(1) HARMONIC_TO = Setting(15) HARMONIC_STEP = Setting(2) HELICAL = Setting(0) METHOD = Setting(1) NEKS = Setting(100) inputs = WidgetDecorator.syned_input_data() def build_gui(self): self.IMAGE_WIDTH = 850 box = oasysgui.widgetBox(self.controlArea, self.name + " Input Parameters", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 5) idx = -1 #widget index 1 idx += 1 box1 = gui.widgetBox(box) self.id_ENERGY = oasysgui.lineEdit(box1, self, "ENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_CURRENT = oasysgui.lineEdit(box1, self, "CURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 3 idx += 1 box1 = gui.widgetBox(box) self.id_ENERGY_SPREAD = oasysgui.lineEdit(box1, self, "ENERGY_SPREAD", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 5 idx += 1 box1 = gui.widgetBox(box) self.id_SIGX = oasysgui.lineEdit(box1, self, "SIGX", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 6 idx += 1 box1 = gui.widgetBox(box) self.id_SIGY = oasysgui.lineEdit(box1, self, "SIGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_SIGX1 = oasysgui.lineEdit(box1, self, "SIGX1", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_SIGY1 = oasysgui.lineEdit(box1, self, "SIGY1", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 10 idx += 1 box1 = gui.widgetBox(box) self.id_PERIOD = oasysgui.lineEdit(box1, self, "PERIOD", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) self.id_NP = oasysgui.lineEdit(box1, self, "NP", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "EMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "EMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, validator=QDoubleValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 15 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "N", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 17 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONIC_FROM", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 18 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONIC_TO", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 19 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HARMONIC_STEP", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 21 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "HELICAL", label=self.unitLabels()[idx], addSpace=False, items=['Planar undulator', 'Helical undulator'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 22 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "METHOD", label=self.unitLabels()[idx], addSpace=False, items=['Finite-N', 'Infinite N with convolution'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 24 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NEKS", label=self.unitLabels()[idx], addSpace=False, valueType=int, validator=QIntValidator(), orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return [ 'Electron energy (GeV)', 'Current (mA)', 'Energy Spread (DE/E)', 'Sigma X (mm)', 'Sigma Y (mm)', "Sigma X' (mrad)", "Sigma Y' (mrad)", 'Period length (cm)', 'Number of periods', 'E1 minimum energy (eV)', 'E1 maximum energy (eV)', 'Number of energy-points', 'Minimum harmonic number', 'Maximum harmonic number', 'Harmonic step size', 'Mode', 'Method', 'Intrinsic NEKS' ] def unitFlags(self): return ['True' for i in range(19)] def get_help_name(self): return 'tc' def check_fields(self): self.ENERGY = congruence.checkStrictlyPositiveNumber( self.ENERGY, "Electron Energy") self.CURRENT = congruence.checkStrictlyPositiveNumber( self.CURRENT, "Current") self.ENERGY_SPREAD = congruence.checkStrictlyPositiveNumber( self.ENERGY_SPREAD, "Energy Spread") self.SIGX = congruence.checkPositiveNumber(self.SIGX, "Sigma X") self.SIGY = congruence.checkPositiveNumber(self.SIGY, "Sigma Y") self.SIGX1 = congruence.checkPositiveNumber(self.SIGX1, "Sigma X'") self.SIGY1 = congruence.checkPositiveNumber(self.SIGY1, "Sigma Y'") self.PERIOD = congruence.checkStrictlyPositiveNumber( self.PERIOD, "Period length") self.NP = congruence.checkStrictlyPositiveNumber( self.NP, "Number of periods") self.EMIN = congruence.checkPositiveNumber(self.EMIN, "E1 minimum energy") self.EMAX = congruence.checkStrictlyPositiveNumber( self.EMAX, "E1 maximum energy") congruence.checkLessThan(self.EMIN, self.EMAX, "E1 minimum energy", "E1 maximum energy") self.N = congruence.checkStrictlyPositiveNumber( self.N, "Number of Energy Points") self.HARMONIC_FROM = congruence.checkStrictlyPositiveNumber( self.HARMONIC_FROM, "Minimum harmonic number") self.HARMONIC_TO = congruence.checkStrictlyPositiveNumber( self.HARMONIC_TO, "Maximum harmonic number") congruence.checkLessThan(self.HARMONIC_FROM, self.HARMONIC_TO, "Minimum harmonic number", "Maximum harmonic number") self.HARMONIC_STEP = congruence.checkStrictlyPositiveNumber( self.HARMONIC_STEP, "Harmonic step size") self.NEKS = congruence.checkPositiveNumber(self.NEKS, "Intrinsic NEKS") def do_xoppy_calculation(self): return self.xoppy_calc_xtc() def extract_data_from_xoppy_output(self, calculation_output): return calculation_output def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.view_type_combo.setEnabled(False) xoppy_data_harmonics = calculated_data.get_content( "xoppy_data_harmonics") 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] if not self.plot_canvas[index] is None: self.plot_canvas[index].clear() try: for h_index in range(0, len(xoppy_data_harmonics)): self.plot_histo( xoppy_data_harmonics[h_index][1][:, x_index], xoppy_data_harmonics[h_index][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, harmonic=xoppy_data_harmonics[h_index][0], control=True) self.plot_canvas[index].addCurve( numpy.zeros(1), numpy.array([ max(xoppy_data_harmonics[h_index][1][:, y_index]) ]), "Click on curve to highlight it", xlabel=xtitles[index], ylabel=ytitles[index], symbol='', color='white') self.plot_canvas[index].setActiveCurve( "Click on curve to highlight it") self.plot_canvas[index].getLegendsDockWidget( ).setFixedHeight(150) self.plot_canvas[index].getLegendsDockWidget( ).setVisible(True) 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 plot_histo(self, x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="", log_x=False, log_y=False, harmonic=1, color='blue', control=True): h_title = "Harmonic " + str(harmonic) hex_r = hex(min(255, 128 + harmonic * 10))[2:].upper() hex_g = hex(min(255, 20 + harmonic * 15))[2:].upper() hex_b = hex(min(255, harmonic * 10))[2:].upper() if len(hex_r) == 1: hex_r = "0" + hex_r if len(hex_g) == 1: hex_g = "0" + hex_g if len(hex_b) == 1: hex_b = "0" + hex_b super().plot_histo(x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, h_title, xtitle, ytitle, log_x, log_y, color="#" + hex_r + hex_g + hex_b, replace=False, control=control) self.plot_canvas[plot_canvas_index].setGraphTitle(title) self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True) self.plot_canvas[plot_canvas_index].setDefaultPlotPoints(True) def get_data_exchange_widget_name(self): return "XTC" def getTitles(self): return ["Brilliance", "Ky", "Total Power", "Power density"] def getXTitles(self): return ["Energy (eV)", "Energy (eV)", "Energy (eV)", "Energy (eV)"] def getYTitles(self): return [ "Brilliance (ph/s/mrad^2/mm^2/0.1%bw)", "Ky", "Total Power (W)", "Power density (W/mr^2)" ] def getVariablesToPlot(self): return [(1, 2), (1, 3), (1, 4), (1, 5)] def getLogPlot(self): return [(False, True), (False, False), (False, False), (False, False)] def xoppy_calc_xtc(self): for file in ["tc.inp", "tc.out"]: try: os.remove(os.path.join(locations.home_bin_run(), file)) except: pass with open("tc.inp", "wt") as f: f.write("TS called from xoppy\n") f.write("%10.3f %10.2f %10.6f %s\n" % (self.ENERGY, self.CURRENT, self.ENERGY_SPREAD, "Ring-Energy(GeV) Current(mA) Beam-Energy-Spread")) f.write("%10.4f %10.4f %10.4f %10.4f %s\n" % (self.SIGX, self.SIGY, self.SIGX1, self.SIGY1, "Sx(mm) Sy(mm) Sx1(mrad) Sy1(mrad)")) f.write("%10.3f %d %s\n" % (self.PERIOD, self.NP, "Period(cm) N")) f.write("%10.1f %10.1f %d %s\n" % (self.EMIN, self.EMAX, self.N, "Emin Emax Ne")) f.write("%d %d %d %s\n" % (self.HARMONIC_FROM, self.HARMONIC_TO, self.HARMONIC_STEP, "Hmin Hmax Hstep")) f.write("%d %d %d %d %s\n" % (self.HELICAL, self.METHOD, 1, self.NEKS, "Helical Method Print_K Neks")) f.write("foreground\n") if platform.system() == "Windows": command = os.path.join(locations.home_bin(), 'tc.exe') else: command = "'" + os.path.join(locations.home_bin(), 'tc') + "'" print("Running command '%s' in directory: %s " % (command, locations.home_bin_run())) print("\n--------------------------------------------------------\n") os.system(command) print("Output file: %s" % ("tc.out")) print("\n--------------------------------------------------------\n") # # parse result files to exchange object # with open("tc.out", "r") as f: lines = f.readlines() # print output file # for line in lines: # print(line, end="") # remove returns lines = [line[:-1] for line in lines] harmonics_data = [] # separate numerical data from text floatlist = [] harmoniclist = [] txtlist = [] for line in lines: try: tmp = line.strip() if tmp.startswith("Harmonic"): harmonic_number = int(tmp.split("Harmonic")[1].strip()) if harmonic_number != self.HARMONIC_FROM: harmonics_data[-1][1] = harmoniclist harmoniclist = [] harmonics_data.append([harmonic_number, None]) tmp = float(line.strip()[0]) floatlist.append(line) harmoniclist.append(line) except: txtlist.append(line) harmonics_data[-1][1] = harmoniclist data = numpy.loadtxt(floatlist) for index in range(0, len(harmonics_data)): # print (harmonics_data[index][0], harmonics_data[index][1]) harmonics_data[index][1] = numpy.loadtxt(harmonics_data[index][1]) #send exchange calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) try: calculated_data.add_content("xoppy_data", data) calculated_data.add_content("xoppy_data_harmonics", harmonics_data) calculated_data.add_content("plot_x_col", 1) calculated_data.add_content("plot_y_col", 2) except: pass try: calculated_data.add_content("labels", [ "Energy (eV) without emittance", "Energy (eV) with emittance", "Brilliance (ph/s/mrad^2/mm^2/0.1%bw)", "Ky", "Total Power (W)", "Power density (W/mr^2)" ]) except: pass try: calculated_data.add_content("info", txtlist) except: pass return calculated_data def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ENERGY = light_source._electron_beam._energy_in_GeV self.ENERGY_SPREAD = light_source._electron_beam._energy_spread self.CURRENT = 1000.0 * light_source._electron_beam._current x, xp, y, yp = light_source._electron_beam.get_sigmas_all() self.SIGX = 1e3 * x self.SIGY = 1e3 * y self.SIGX1 = 1e3 * xp self.SIGY1 = 1e3 * yp self.PERIOD = 100.0 * light_source._magnetic_structure._period_length self.NP = light_source._magnetic_structure._number_of_periods self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self, value): if value == True: self.id_ENERGY.setEnabled(True) self.id_ENERGY_SPREAD.setEnabled(True) self.id_SIGX.setEnabled(True) self.id_SIGX1.setEnabled(True) self.id_SIGY.setEnabled(True) self.id_SIGY1.setEnabled(True) self.id_CURRENT.setEnabled(True) self.id_PERIOD.setEnabled(True) self.id_NP.setEnabled(True) else: self.id_ENERGY.setEnabled(False) self.id_ENERGY_SPREAD.setEnabled(False) self.id_SIGX.setEnabled(False) self.id_SIGX1.setEnabled(False) self.id_SIGY.setEnabled(False) self.id_SIGY1.setEnabled(False) self.id_CURRENT.setEnabled(False) self.id_PERIOD.setEnabled(False) self.id_NP.setEnabled(False)
class OWwiggler_radiation(XoppyWidget, WidgetDecorator): name = "Wiggler Radiation" id = "wiggler_radiation" description = "Wiggler Radiation" icon = "icons/xoppy_wiggler_radiation.png" priority = 12 category = "" keywords = ["xoppy", "wiggler_radiation"] # overwrite from outputs = [{"name": "xoppy_data", "type": DataExchangeObject, "doc": ""}] ELECTRONENERGY = Setting(3.0) ELECTRONCURRENT = Setting(0.1) PERIODID = Setting(0.120) NPERIODS = Setting(37.0) KV = Setting(22.416) DISTANCE = Setting(30.0) HSLITPOINTS = Setting(500) VSLITPOINTS = Setting(500) PHOTONENERGYMIN = Setting(100.0) PHOTONENERGYMAX = Setting(100100.0) PHOTONENERGYPOINTS = Setting(101) H5_FILE_DUMP = Setting(0) NTRAJPOINTS = Setting(1001) FIELD = Setting(0) FILE = Setting("") POLARIZATION = Setting(0) h5_file = Setting("wiggler_radiation.h5", ) h5_entry_name = Setting("XOPPY_RADIATION", ) h5_initialize = Setting(True, ) h5_parameters = Setting(None, ) SHIFT_X_FLAG = Setting(0) SHIFT_X_VALUE = Setting(0.0) SHIFT_BETAX_FLAG = Setting(0) SHIFT_BETAX_VALUE = Setting(0.0) CONVOLUTION = Setting(1) PASSEPARTOUT = Setting(3.0) bm_magnetic_radius = Setting(10.0) bm_magnetic_field = Setting(1.001) bm_divergence = Setting(1.0e-3) inputs = WidgetDecorator.syned_input_data() filename = "" # IS_DEVELOP = False def __init__(self): super().__init__(show_script_tab=True) def build_gui(self): tabs_setting = oasysgui.tabWidget(self.controlArea) tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH - 5) tab_1 = oasysgui.createTabPage(tabs_setting, self.name + " Input Parameters") tab_2 = oasysgui.createTabPage(tabs_setting, "Advanced Settings") box0 = oasysgui.widgetBox(tab_1, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) idx = -1 # # # box = oasysgui.widgetBox(box0, "Electron beam", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONENERGY = oasysgui.lineEdit( box1, self, "ELECTRONENERGY", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 2 idx += 1 box1 = gui.widgetBox(box) self.id_ELECTRONCURRENT = oasysgui.lineEdit( box1, self, "ELECTRONCURRENT", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) box = oasysgui.widgetBox(box0, "Wiggler", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) #widget index 0 idx += 1 box1 = gui.widgetBox(box) self.id_FIELD = self.id_FIELD = gui.comboBox( box1, self, "FIELD", label=self.unitLabels()[idx], addSpace=False, items=['Sinusoidal', 'B from file', 'Bending magnet (cte B)'], valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 7 idx += 1 box1 = gui.widgetBox(box) self.id_PERIODID = oasysgui.lineEdit(box1, self, "PERIODID", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 8 idx += 1 box1 = gui.widgetBox(box) self.id_NPERIODS = oasysgui.lineEdit(box1, self, "NPERIODS", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) self.id_KV = oasysgui.lineEdit(box1, self, "KV", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) file_box = oasysgui.widgetBox(box1, "", addSpace=False, orientation="horizontal", height=25) self.le_file = oasysgui.lineEdit(file_box, self, "FILE", label=self.unitLabels()[idx], addSpace=False, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) gui.button(file_box, self, "...", callback=self.selectFile) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "bm_magnetic_radius", label=self.unitLabels()[idx], labelWidth=250, callback=self.calculateMagneticField, tooltip=self.unitLabels()[idx], valueType=float, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "bm_magnetic_field", label=self.unitLabels()[idx], labelWidth=250, callback=self.calculateMagneticRadius, tooltip=self.unitLabels()[idx], valueType=float, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) #widget index 11 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "bm_divergence", label=self.unitLabels()[idx], labelWidth=250, tooltip=self.unitLabels()[idx], valueType=float, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) box = oasysgui.widgetBox(box0, "Scan", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) #widget index 10 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "DISTANCE", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 13 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "HSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 14 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "VSLITPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMIN", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYMAX", label=self.unitLabels()[idx], addSpace=False, valueType=float, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index <><> idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PHOTONENERGYPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) box = oasysgui.widgetBox(box0, "Output", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) #widget index 16 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "H5_FILE_DUMP", label=self.unitLabels()[idx], addSpace=False, items=[ 'None', 'Write h5 file: wiggler_radiation.h5', 'Read from file...' ], valueType=int, orientation="horizontal", labelWidth=250, callback=self.read_or_write_file) self.show_at(self.unitFlags()[idx], box1) # # advanced # box0 = oasysgui.widgetBox(tab_2, "", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) box = oasysgui.widgetBox(box0, "Electron trajectory", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "NTRAJPOINTS", label=self.unitLabels()[idx], addSpace=False, valueType=int, orientation="horizontal", labelWidth=250) self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "SHIFT_BETAX_FLAG", label=self.unitLabels()[idx], items=[ "No shift", "Half excursion", "Minimum", "Maximum", "Value at zero", "User value" ], labelWidth=260, valueType=float, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "SHIFT_BETAX_VALUE", label=self.unitLabels()[idx], labelWidth=260, valueType=float, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "SHIFT_X_FLAG", label=self.unitLabels()[idx], items=[ "No shift", "Half excursion", "Minimum", "Maximum", "Value at zero", "User value" ], labelWidth=260, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "SHIFT_X_VALUE", label=self.unitLabels()[idx], labelWidth=260, valueType=float, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) box = oasysgui.widgetBox(box0, "Photon divergence", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) #widget index 9 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "CONVOLUTION", label=self.unitLabels()[idx], items=["No", "Yes [default]"], labelWidth=260, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) #widget index 9 idx += 1 box1 = gui.widgetBox(box) oasysgui.lineEdit(box1, self, "PASSEPARTOUT", label=self.unitLabels()[idx], labelWidth=260, valueType=float, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) box = oasysgui.widgetBox(box0, "Photon Polarization", orientation="vertical", width=self.CONTROL_AREA_WIDTH - 15) #widget index 9 idx += 1 box1 = gui.widgetBox(box) gui.comboBox(box1, self, "POLARIZATION", label=self.unitLabels()[idx], items=["Total", "Parellel", "Perpendicular"], labelWidth=260, orientation="horizontal") self.show_at(self.unitFlags()[idx], box1) def unitLabels(self): return [ "Electron Energy [GeV]", "Electron Current [A]", "Magnetic field: ", "Period ID [m]", "Number of periods", "Kv [K value vertical field]", 'File/Url with Magnetic Field', 'BM Magnetic radius [m]', 'BM Magnetic field [T]', 'BM divergence [rad]', "Distance to slit [m]", "Number of slit mesh points in H", "Number of slit mesh points in V", "Photon Energy Min [eV]", "Photon Energy Max [eV]", "Number of Photon Energy Points", "hdf5 file", 'Number of traj points per period', "Shift Transversal Velocity", "Value", "Shift Transversal Coordinate", "Value", "Convolution electron x' with photon div", "Passepartout in sigma' units at Emin", "Polarization", ] # TODO check energy spread flag: set to False (not used at all)!! def unitFlags(self): flags = ["True"] * len(self.unitLabels()) flags[3] = "self.FIELD == 0" flags[4] = "self.FIELD == 0" flags[5] = "self.FIELD == 0" flags[6] = "self.FIELD == 1" flags[7] = "self.FIELD == 2" flags[8] = "self.FIELD == 2" flags[9] = "self.FIELD == 2" flags[19] = "self.SHIFT_BETAX_FLAG == 5" flags[21] = "self.SHIFT_X_FLAG == 5" return flags def get_help_name(self): return 'wiggler_radiation' def selectFile(self): self.le_file.setText( oasysgui.selectFileFromDialog(self, self.FILE, "Open File with B map")) def read_or_write_file(self): value = self.H5_FILE_DUMP if value == 0: return elif value == 1: # write return elif value == 2: # read self.H5_FILE_DUMP = 0 use_silx_file_dialog = False # silx dialog is freezing the linux system, change to traditional if use_silx_file_dialog: tmp = ConfirmDialog.confirmed( self, message= "Please select in a hdf5 file a data block\n(such as XOPPY_RADIATION)\nthat contains a 'Radiation' entry", title="Confirm Action") if tmp == False: return dialog = DataFileDialog(self) dialog.setFilterMode(DataFileDialog.FilterMode.ExistingGroup) result = dialog.exec_() if not result: return print(dialog.selectedFile()) print(dialog.selectedUrl()) print(dialog.selectedDataUrl().data_path()) calculation_output = self.extract_data_from_h5file( dialog.selectedFile(), dialog.selectedDataUrl().data_path()) self.filename = dialog.selectedFile() else: tmp = ConfirmDialog.confirmed( self, message= "Please select a hdf5 file containing a data block\n named XOPPY_RADIATION which includes 'Radiation' entry", title="Confirm Action") if tmp == False: return self.filename = oasysgui.selectFileFromDialog( self, previous_file_path=self.filename, message="Open hdf5 File", start_directory="", file_extension_filter="*.*5") if self.filename == "": return try: calculation_output = self.extract_data_from_h5file( self.filename, "/XOPPY_RADIATION") except: QMessageBox.critical( self, "Error", str("Failed to load hdf5 /XOPPY_RADIATION"), QMessageBox.Ok) calculation_output = None if calculation_output is None: QMessageBox.critical(self, "Error", str("Bad data from file."), QMessageBox.Ok) else: self.calculated_data = self.extract_data_from_xoppy_output( calculation_output) try: self.set_fields_from_h5file(self.filename, "/XOPPY_RADIATION") except: QMessageBox.critical( self, "Error", "Failed to set fields hdf5 /XOPPY_RADIATION/parameters \n", QMessageBox.Ok) # self.add_specific_content_to_calculated_data(self.calculated_data) # self.setStatusMessage("Plotting Results") self.plot_results(self.calculated_data, progressBarValue=60) self.setStatusMessage("") # p, e, h, v = self.calculated_data.get_content("xoppy_data") # traj = self.calculated_data.get_content("xoppy_data") # data_to_send = DataExchangeObject("XOPPY", self.get_data_exchange_widget_name()) # data_to_send.add_content("xoppy_data", [p, e, h, v, traj]) self.send("xoppy_data", self.calculated_data) self.set_enabled(True) def extract_data_from_h5file(self, file_h5, subtitle): hf = h5py.File(file_h5, 'r') try: p = hf[subtitle + "/Radiation/stack_data"][:] e = hf[subtitle + "/Radiation/axis0"][:] h = hf[subtitle + "/Radiation/axis1"][:] v = hf[subtitle + "/Radiation/axis2"][:] traj = hf[subtitle + "/trajectory/traj"][:] except: QMessageBox.critical(self, "Error", "Failed to load hdf5 data\n", QMessageBox.Ok) hf.close() return e, h, v, p, traj def set_fields_from_h5file(self, file_h5, subtitle): hf = h5py.File(file_h5, 'r') self.ELECTRONENERGY = hf[subtitle + "/parameters/ELECTRONENERGY"].value self.ELECTRONCURRENT = hf[subtitle + "/parameters/ELECTRONCURRENT"].value self.PERIODID = hf[subtitle + "/parameters/PERIODID"].value self.NPERIODS = hf[subtitle + "/parameters/NPERIODS"].value self.KV = hf[subtitle + "/parameters/KV"].value self.DISTANCE = hf[subtitle + "/parameters/DISTANCE"].value self.HSLITPOINTS = hf[subtitle + "/parameters/HSLITPOINTS"].value self.VSLITPOINTS = hf[subtitle + "/parameters/VSLITPOINTS"].value self.PHOTONENERGYMIN = hf[subtitle + "/parameters/PHOTONENERGYMIN"].value self.PHOTONENERGYMAX = hf[subtitle + "/parameters/PHOTONENERGYMAX"].value self.PHOTONENERGYPOINTS = hf[subtitle + "/parameters/PHOTONENERGYPOINTS"].value self.FIELD = hf[subtitle + "/parameters/FIELD"].value self.FILE = hf[subtitle + "/parameters/FILE"].value self.POLARIZATION = hf[subtitle + "/parameters/POLARIZATION"].value self.CONVOLUTION = hf[subtitle + "/parameters/CONVOLUTION"].value self.PASSEPARTOUT = hf[subtitle + "/parameters/PASSEPARTOUT"].value self.SHIFT_X_FLAG = hf[subtitle + "/parameters/SHIFT_X_FLAG"].value self.SHIFT_BETAX_FLAG = hf[subtitle + "/parameters/SHIFT_BETAX_FLAG"].value self.SHIFT_X_VALUE = hf[subtitle + "/parameters/SHIFT_X_VALUE"].value self.SHIFT_BETAX_VALUE = hf[subtitle + "/parameters/SHIFT_BETAX_VALUE"].value hf.close() def check_fields(self): self.ELECTRONENERGY = congruence.checkStrictlyPositiveNumber( self.ELECTRONENERGY, "Electron Energy") self.ELECTRONCURRENT = congruence.checkStrictlyPositiveNumber( self.ELECTRONCURRENT, "Electron Current") self.PERIODID = congruence.checkStrictlyPositiveNumber( self.PERIODID, "Period ID") self.NPERIODS = congruence.checkStrictlyPositiveNumber( self.NPERIODS, "Number of Periods") self.KV = congruence.checkPositiveNumber(self.KV, "Kv") self.DISTANCE = congruence.checkStrictlyPositiveNumber( self.DISTANCE, "Distance to slit") self.PHOTONENERGYMIN = congruence.checkNumber(self.PHOTONENERGYMIN, "Photon Energy Min") self.PHOTONENERGYMAX = congruence.checkNumber(self.PHOTONENERGYMAX, "Photon Energy Max") congruence.checkGreaterOrEqualThan(self.PHOTONENERGYPOINTS, 2, "Number of Photon Energy Points", " 2") self.HSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.HSLITPOINTS, "Number of slit mesh points in H") self.VSLITPOINTS = congruence.checkStrictlyPositiveNumber( self.VSLITPOINTS, "Number of slit mesh points in V") self.NTRAJPOINTS = congruence.checkStrictlyPositiveNumber( self.NTRAJPOINTS, "Number Trajectory points") self.PASSEPARTOUT = congruence.checkStrictlyPositiveNumber( self.PASSEPARTOUT, "Passepartout in units of sigma' at Emin") def plot_results(self, calculated_data, progressBarValue=80): if not self.view_type == 0: if not calculated_data is None: self.initializeTabs( ) # added by srio to avoid overlapping graphs self.view_type_combo.setEnabled(False) p, e, h, v = calculated_data.get_content("xoppy_data") traj = calculated_data.get_content("xoppy_trajectory") # code = calculated_data.get_content("xoppy_code") try: self.plot_data3D( p, e, h, v, 0, 0, xtitle='H [mm]', ytitle='V [mm]', title='Flux [photons/s/0.1%bw/mm^2]', ) self.tabs.setCurrentIndex(0) except Exception as e: self.view_type_combo.setEnabled(True) QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise Exception("Data not plottable: bad content\n" + str(e)) try: if len(e) > 1: energy_step = e[1] - e[0] else: energy_step = 1.0 self.plot_data2D( p.sum(axis=0) * energy_step * codata.e * 1e3, h, v, 1, 0, xtitle='H [mm]', ytitle='V [mm]', title='Power density [W/mm^2]', ) except Exception as exception: self.view_type_combo.setEnabled(True) QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) if self.IS_DEVELOP: raise exception # except Exception as exception: # QMessageBox.critical(self, "Error", str(exception), QMessageBox.Ok) # # if self.IS_DEVELOP: raise exception return False try: self.plot_data1D( e, p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) * (v[1] - v[0]), 2, 0, xtitle='Photon Energy [eV]', ytitle='Flux [photons/s/0.1%bw]', title='Flux', ) except Exception as e: self.view_type_combo.setEnabled(True) QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise Exception("Data not plottable: bad content\n" + str(e)) try: self.plot_data1D( e, p.sum(axis=2).sum(axis=1) * (h[1] - h[0]) * (v[1] - v[0]) * codata.e * 1e3, 3, 0, xtitle='Photon Energy [eV]', ytitle='Spectral power [W/eV]', title='Spectral power', ) except Exception as e: self.view_type_combo.setEnabled(True) QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise Exception("Data not plottable: bad content\n" + str(e)) try: self.plot_data1D( traj[1, :], traj[0, :], 4, 0, xtitle="s [m]", ytitle="X [m]", title="Transversal Trajectory X(s)", ) except Exception as e: self.view_type_combo.setEnabled(True) QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise Exception("Data not plottable: bad content\n" + str(e)) try: self.plot_data1D( traj[1, :], traj[3, :], 5, 0, xtitle="s [m]", ytitle="betaX [c units]", title="Transversal velocity betaX(s)", ) except Exception as e: self.view_type_combo.setEnabled(True) QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise Exception("Data not plottable: bad content\n" + str(e)) try: self.plot_data1D( traj[1, :], traj[7, :], 6, 0, xtitle="s [m]", ytitle="Bz [T]", title="Magnetic field Bz(s)", ) except Exception as e: self.view_type_combo.setEnabled(True) QMessageBox.critical(self, "Error", str(e), QMessageBox.Ok) if self.IS_DEVELOP: raise Exception("Data not plottable: bad content\n" + str(e)) self.view_type_combo.setEnabled(True) else: QMessageBox.critical(self, "Error", "Empty data", QMessageBox.Ok) if self.IS_DEVELOP: raise Exception("Empty Data") def do_xoppy_calculation(self): if self.H5_FILE_DUMP == 0: h5_file = "" else: h5_file = "wiggler_radiation.h5" if self.FIELD == 0: FILE = "" FIELD = 0 elif self.FIELD == 1: FILE = self.FILE FIELD = 1 elif self.FIELD == 2: FILE = "bending_magnet_field.dat" create_magnetic_field_for_bending_magnet( do_plot=False, filename=FILE, B0=self.bm_magnetic_field, divergence=self.bm_divergence, radius=self.bm_magnetic_radius, npoints=self.NTRAJPOINTS) FIELD = 1 if self.H5_FILE_DUMP == 0: h5_file = "" else: h5_file = "wiggler_radiation.h5" dict_parameters = { "ELECTRONENERGY": self.ELECTRONENERGY, "ELECTRONCURRENT": self.ELECTRONCURRENT, "PERIODID": self.PERIODID, "NPERIODS": self.NPERIODS, "KV": self.KV, "DISTANCE": self.DISTANCE, "HSLITPOINTS": self.HSLITPOINTS, "VSLITPOINTS": self.VSLITPOINTS, "PHOTONENERGYMIN": self.PHOTONENERGYMIN, "PHOTONENERGYMAX": self.PHOTONENERGYMAX, "PHOTONENERGYPOINTS": self.PHOTONENERGYPOINTS, "FIELD": FIELD, "FILE": FILE, "POLARIZATION": self.POLARIZATION, "SHIFT_X_FLAG": self.SHIFT_X_FLAG, "SHIFT_X_VALUE": self.SHIFT_X_VALUE, "SHIFT_BETAX_FLAG": self.SHIFT_BETAX_FLAG, "SHIFT_BETAX_VALUE": self.SHIFT_BETAX_VALUE, "CONVOLUTION": self.CONVOLUTION, "PASSEPARTOUT": self.PASSEPARTOUT, } # write python script self.xoppy_script.set_code( self.script_template().format_map(dict_parameters)) e, h, v, p, traj = xoppy_calc_wiggler_radiation( ELECTRONENERGY=self.ELECTRONENERGY, ELECTRONCURRENT=self.ELECTRONCURRENT, PERIODID=self.PERIODID, NPERIODS=self.NPERIODS, KV=self.KV, DISTANCE=self.DISTANCE, HSLITPOINTS=self.HSLITPOINTS, VSLITPOINTS=self.VSLITPOINTS, PHOTONENERGYMIN=self.PHOTONENERGYMIN, PHOTONENERGYMAX=self.PHOTONENERGYMAX, PHOTONENERGYPOINTS=self.PHOTONENERGYPOINTS, FIELD=FIELD, FILE=FILE, POLARIZATION=self.POLARIZATION, SHIFT_X_FLAG=self.SHIFT_X_FLAG, SHIFT_X_VALUE=self.SHIFT_X_VALUE, SHIFT_BETAX_FLAG=self.SHIFT_BETAX_FLAG, SHIFT_BETAX_VALUE=self.SHIFT_BETAX_VALUE, CONVOLUTION=self.CONVOLUTION, PASSEPARTOUT=self.PASSEPARTOUT, h5_file=h5_file, h5_entry_name="XOPPY_RADIATION", h5_initialize=True, h5_parameters=dict_parameters, ) return e, h, v, p, traj def script_template(self): return """ # # script to make the calculations (created by XOPPY:wiggler_radiation) # from orangecontrib.xoppy.util.xoppy_bm_wiggler import xoppy_calc_wiggler_radiation h5_parameters = dict() h5_parameters["ELECTRONENERGY"] = {ELECTRONENERGY} h5_parameters["ELECTRONCURRENT"] = {ELECTRONCURRENT} h5_parameters["PERIODID"] = {PERIODID} h5_parameters["NPERIODS"] = {NPERIODS} h5_parameters["KV"] = {KV} h5_parameters["FIELD"] = {FIELD} # 0= sinusoidal, 1=from file h5_parameters["FILE"] = '{FILE}' h5_parameters["POLARIZATION"] = {POLARIZATION} # 0=total, 1=s, 2=p h5_parameters["DISTANCE"] = {DISTANCE} h5_parameters["HSLITPOINTS"] = {HSLITPOINTS} h5_parameters["VSLITPOINTS"] = {VSLITPOINTS} h5_parameters["PHOTONENERGYMIN"] = {PHOTONENERGYMIN} h5_parameters["PHOTONENERGYMAX"] = {PHOTONENERGYMAX} h5_parameters["PHOTONENERGYPOINTS"] = {PHOTONENERGYPOINTS} h5_parameters["SHIFT_X_FLAG"] = {SHIFT_X_FLAG} h5_parameters["SHIFT_X_VALUE"] = {SHIFT_X_VALUE} h5_parameters["SHIFT_BETAX_FLAG"] = {SHIFT_BETAX_FLAG} h5_parameters["SHIFT_BETAX_VALUE"] = {SHIFT_BETAX_VALUE} h5_parameters["CONVOLUTION"] = {CONVOLUTION} h5_parameters["PASSEPARTOUT"] = {PASSEPARTOUT} e, h, v, p, traj = xoppy_calc_wiggler_radiation( ELECTRONENERGY = h5_parameters["ELECTRONENERGY"] , ELECTRONCURRENT = h5_parameters["ELECTRONCURRENT"] , PERIODID = h5_parameters["PERIODID"] , NPERIODS = h5_parameters["NPERIODS"] , KV = h5_parameters["KV"] , FIELD = h5_parameters["FIELD"] , FILE = h5_parameters["FILE"] , POLARIZATION = h5_parameters["POLARIZATION"] , DISTANCE = h5_parameters["DISTANCE"] , HSLITPOINTS = h5_parameters["HSLITPOINTS"] , VSLITPOINTS = h5_parameters["VSLITPOINTS"] , PHOTONENERGYMIN = h5_parameters["PHOTONENERGYMIN"] , PHOTONENERGYMAX = h5_parameters["PHOTONENERGYMAX"] , PHOTONENERGYPOINTS = h5_parameters["PHOTONENERGYPOINTS"] , SHIFT_X_FLAG = h5_parameters["SHIFT_X_FLAG"] , SHIFT_X_VALUE = h5_parameters["SHIFT_X_VALUE"] , SHIFT_BETAX_FLAG = h5_parameters["SHIFT_BETAX_FLAG"] , SHIFT_BETAX_VALUE = h5_parameters["SHIFT_BETAX_VALUE"] , CONVOLUTION = h5_parameters["CONVOLUTION"] , PASSEPARTOUT = h5_parameters["PASSEPARTOUT"] , h5_file = "wiggler_radiation.h5" , h5_entry_name = "XOPPY_RADIATION" , h5_initialize = True , h5_parameters = h5_parameters , ) # example plot from srxraylib.plot.gol import plot_image plot_image(p[0],h,v,title="Flux [photons/s] per 0.1 bw per mm2 at %9.3f eV"%({PHOTONENERGYMIN}),xtitle="H [mm]",ytitle="V [mm]") # # end script # """ def extract_data_from_xoppy_output(self, calculation_output): e, h, v, p, traj = calculation_output calculated_data = DataExchangeObject( "XOPPY", self.get_data_exchange_widget_name()) calculated_data.add_content("xoppy_data", [p, e, h, v]) calculated_data.add_content("xoppy_trajectory", traj) calculated_data.add_content("xoppy_code", "srfunc") return calculated_data def get_data_exchange_widget_name(self): return "WIGGLER_RADIATION" def getTitles(self): return [ 'Wiggler Flux vs E,X,Y', 'Wiggler Power Density vs X,Y', 'Wiggler Flux vs E', 'Wiggler Spectral Power vs E', 'e- trajectory', 'e- velocity', 'Bz' ] def receive_syned_data(self, data): if isinstance(data, synedb.Beamline): if not data._light_source is None and isinstance( data._light_source._magnetic_structure, synedid.InsertionDevice): light_source = data._light_source self.ELECTRONENERGY = light_source._electron_beam._energy_in_GeV self.ELECTRONCURRENT = light_source._electron_beam._current self.FIELD = 0 self.PERIODID = light_source._magnetic_structure._period_length self.NPERIODS = light_source._magnetic_structure._number_of_periods self.KV = light_source._magnetic_structure._K_vertical self.set_enabled(False) else: self.set_enabled(True) # raise ValueError("Syned data not correct") else: self.set_enabled(True) # raise ValueError("Syned data not correct") def set_enabled(self, value): if value == True: self.id_ELECTRONENERGY.setEnabled(True) self.id_ELECTRONCURRENT.setEnabled(True) self.id_PERIODID.setEnabled(True) self.id_NPERIODS.setEnabled(True) self.id_KV.setEnabled(True) self.id_FIELD.setEnabled(True) else: self.id_ELECTRONENERGY.setEnabled(False) self.id_ELECTRONCURRENT.setEnabled(False) self.id_PERIODID.setEnabled(False) self.id_NPERIODS.setEnabled(False) self.id_KV.setEnabled(False) self.id_FIELD.setEnabled(False) def calculateMagneticField(self): self.bm_magnetic_field = numpy.round( (1e9 / codata.c) * self.ELECTRONENERGY / self.bm_magnetic_radius, 3) def calculateMagneticRadius(self): self.bm_magnetic_radius = numpy.round( numpy.abs((1e9 / codata.c) * self.ELECTRONENERGY / self.bm_magnetic_field), 3)