import re import sys, wx, logging import string, numpy, math from copy import deepcopy from danse.common.plottools.plottables import Theory1D,Data2D from sans.guicomm.events import NewPlotEvent, StatusEvent from sans.guicomm.events import EVT_SLICER_PANEL,ERR_DATA from sans.fit.AbstractFitEngine import Model from fitproblem import FitProblem from fitpanel import FitPanel from fit_thread import FitThread import models import fitpage1D DEFAULT_BEAM = 0.005 DEFAULT_QMIN = 0.0 DEFAULT_QMAX = 0.1 DEFAULT_NPTS = 50 class Plugin: """ Fitting plugin is used to perform fit """ def __init__(self): ## Plug-in name self.sub_menu = "Fitting" ## Reference to the parent window self.parent = None #Provide list of models existing in the application self.menu_mng = models.ModelManager() ## List of panels for the simulation perspective (names) self.perspective = [] #list of panel to send to guiframe self.mypanels=[] # reference to the current running thread self.calc_thread = None # Start with a good default self.elapsed = 0.022 # the type of optimizer selected, park or scipy self.fitter = None #Flag to let the plug-in know that it is running stand alone self.standalone=True ## Fit engine self._fit_engine = 'scipy' #List of selected data self.selected_data_list=[] # Log startup logging.info("Fitting plug-in started") # model 2D view self.model2D_id=None #keep reference of the simultaneous fit page self.sim_page=None #dictionary containing data name and error on dy of that data self.err_dy={} def _on_data_error(self, event): """ receives and event from plotting plu-gins to store the data name and their errors of y coordinates for 1Data hide and show error """ self.err_dy= event.err_dy def populate_menu(self, id, owner): """ Create a menu for the Fitting plug-in @param id: id to create a menu @param owner: owner of menu @ return : list of information to populate the main menu """ #Menu for fitting self.menu1 = wx.Menu() id1 = wx.NewId() self.menu1.Append(id1, '&Simultaneous') wx.EVT_MENU(owner, id1, self.on_add_sim_page) #Set park engine id3 = wx.NewId() self.menu1.AppendCheckItem(id3, "park") wx.EVT_MENU(owner, id3, self._onset_engine) #menu for model menu2 = wx.Menu() self.menu_mng.populate_menu(menu2, owner) id2 = wx.NewId() owner.Bind(models.EVT_MODEL,self._on_model_menu) self.fit_panel.set_owner(owner) self.fit_panel.set_model_list(self.menu_mng.get_model_list()) owner.Bind(fitpage1D.EVT_MODEL_BOX,self._on_model_panel) #create menubar items return [(id, self.menu1, "Fitting"),(id2, menu2, "Model")] def on_add_sim_page(self, event): """ """ self.sim_page= self.fit_panel.add_sim_page() self.sim_page.add_model(self.page_finder) def help(self, evt): """ Show a general help dialog. TODO: replace the text with a nice image """ #from helpDialog import HelpWindow #dialog = HelpWindow(None, -1, 'HelpWindow') #if dialog.ShowModal() == wx.ID_OK: # pass #dialog.Destroy() from helpPanel import HelpWindow frame = HelpWindow(None, -1, 'HelpWindow') frame.Show(True) def get_context_menu(self, graph=None): """ Get the context menu items available for P(r) @param graph: the Graph object to which we attach the context menu @return: a list of menu items with call-back function """ self.graph=graph for item in graph.plottables: if item.__class__.__name__ is "Data2D": return [["Select data for Fitting",\ "Dialog with fitting parameters ", self._onSelect]] else: #if item.name==graph.selected_plottable and\ # item.__class__.__name__ is "Data1D": if item.name==graph.selected_plottable : return [["Select data for Fitting", \ "Dialog with fitting parameters ", self._onSelect]] return [] def get_panels(self, parent): """ Create and return a list of panel objects """ self.parent = parent # Creation of the fit panel self.fit_panel = FitPanel(self.parent, -1) #Set the manager forthe main panel self.fit_panel.set_manager(self) # List of windows used for the perspective self.perspective = [] self.perspective.append(self.fit_panel.window_name) # take care of saving data, model and page associated with each other self.page_finder = {} #index number to create random model name self.index_model = 0 self.index_theory= 0 self.parent.Bind(EVT_SLICER_PANEL, self._on_slicer_event) self.parent.Bind( ERR_DATA, self._on_data_error) #create the fitting panel #return [self.fit_panel] self.mypanels.append(self.fit_panel) return self.mypanels def _on_slicer_event(self, event): """ """ #print "fitting:slicer event ", event.panel if event.panel!=None: new_panel = event.panel # Set group ID if available event_id = self.parent.popup_panel(new_panel) self.menu1.Append(event_id, new_panel.window_caption, "Show %s plot panel" % new_panel.window_caption) # Set UID to allow us to reference the panel later new_panel.uid = event_id new_panel self.mypanels.append(new_panel) return def _on_show_panel(self, event): print "_on_show_panel: fitting" def get_perspective(self): """ Get the list of panel names for this perspective """ return self.perspective def on_perspective(self, event): """ Call back function for the perspective menu item. We notify the parent window that the perspective has changed. """ self.parent.set_perspective(self.perspective) def post_init(self): """ Post initialization call back to close the loose ends [Somehow openGL needs this call] """ self.parent.set_perspective(self.perspective) def copy_data(self, item, dy): """ """ detector=None source=None dxl=None dxw=None if hasattr(item, "dxl"): dxl = item.dxl if hasattr(item, "dxw"): dxw = item.dxw if hasattr(item, "detector"): detector =item.detector if hasattr(item, "source"): source =item.source from sans.guiframe import dataFitting data= dataFitting.Data1D(x=item.x, y=item.y, dy=dy, dxl=dxl, dxw=dxw) data.name=item.name data.detector=detector data.source= source return data def _onSelect(self,event): """ when Select data to fit a new page is created .Its reference is added to self.page_finder """ self.panel = event.GetEventObject() for item in self.panel.graph.plottables: if item.name == self.panel.graph.selected_plottable: if len(self.err_dy)>0: if item.name in self.err_dy.iterkeys(): dy= self.err_dy[item.name] data= self.copy_data(item, dy) else: data= item else: if item.dy==None: dy= numpy.zeros(len(item.y)) dy[dy==0]=1 data= self.copy_data(item, dy) else: data= item else: data= item if item.name == self.panel.graph.selected_plottable or\ item.__class__.__name__ is "Data2D": #find a name for the page created for notebook #print "fitting", self.panel try: #page = self.fit_panel.add_fit_page(item) page = self.fit_panel.add_fit_page(data) #page, model_name = self.fit_panel.add_fit_page(item) # add data associated to the page created if page !=None: #create a fitproblem storing all link to data,model,page creation self.page_finder[page]= FitProblem() #self.page_finder[page].save_model_name(model_name) self.page_finder[page].add_plotted_data(item) self.page_finder[page].add_fit_data(data) wx.PostEvent(self.parent, StatusEvent(status="Page Created")) else: wx.PostEvent(self.parent, StatusEvent(status="Page was already Created")) except: #raise wx.PostEvent(self.parent, StatusEvent(status="Creating Fit page: %s"\ %sys.exc_value)) return def schedule_for_fit(self,value=0,fitproblem =None): """ """ if fitproblem !=None: fitproblem.schedule_tofit(value) else: current_pg=self.fit_panel.get_current_page() for page, val in self.page_finder.iteritems(): if page ==current_pg : val.schedule_tofit(value) break def get_page_finder(self): """ @return self.page_finder used also by simfitpage.py""" return self.page_finder def set_page_finder(self,modelname,names,values): """ Used by simfitpage.py to reset a parameter given the string constrainst. @param modelname: the name ot the model for with the parameter has to reset @param value: can be a string in this case. @param names: the paramter name @note: expecting park used for fit. """ #sim_page=self.fit_panel.GetPage(1) sim_page= self.sim_page for page, value in self.page_finder.iteritems(): if page != sim_page: list=value.get_model() model=list[0] #print "fitting",model.name,modelname, values if model.name== modelname: value.set_model_param(names,values) break def split_string(self,item): """ receive a word containing dot and split it. used to split parameterset name into model name and parameter name example: paramaterset (item) = M1.A @return model_name =M1 , parameter name =A """ if string.find(item,".")!=-1: param_names= re.split("\.",item) model_name=param_names[0] param_name=param_names[1] return model_name,param_name def _single_fit_completed(self,result,pars,cpage,qmin,qmax,elapsed=None, ymin=None, ymax=None, xmin=None, xmax=None): """ Display fit result on one page of the notebook. @param result: result of fit @param pars: list of names of parameters fitted @param current_pg: the page where information will be displayed @param qmin: the minimum value of x to replot the model @param qmax: the maximum value of x to replot model """ #print "single fit ", pars,result.pvec,result.stderr,result.fitness wx.PostEvent(self.parent, StatusEvent(status="Single fit \ complete " , type="stop")) try: for page, value in self.page_finder.iteritems(): if page==cpage : #fitdata = value.get_data() list = value.get_model() model= list[0] break i = 0 for name in pars: if result.pvec.__class__==numpy.float64: model.setParam(name,result.pvec) else: #print "fitting result : chisqr",result.fitness #print "fitting result : pvec",result.pvec #print "fitting result : stderr",result.stderr #model.setParam(name,result.pvec[i]) # print "fitting: single fit", name, result.pvec[i] i += 1 cpage.onsetValues(result.fitness, result.pvec,result.stderr) #title="Fitted model 2D " self.plot_helper(currpage=cpage,qmin=qmin,qmax=qmax, ymin=ymin, ymax=ymax, xmin=xmin, xmax=xmax,title=None) except: #raise wx.PostEvent(self.parent, StatusEvent(status="Fitting error: %s" % sys.exc_value)) return def _simul_fit_completed(self,result,qmin,qmax, elapsed,pars=None,cpage=None, xmin=None, xmax=None, ymin=None, ymax=None): """ Parameter estimation completed, display the results to the user @param alpha: estimated best alpha @param elapsed: computation time """ if cpage!=None: self._single_fit_completed(result=result,pars=pars,cpage=cpage, qmin=qmin,qmax=qmax, ymin=ymin, ymax=ymax, xmin=xmin, xmax=xmax) return else: wx.PostEvent(self.parent, StatusEvent(status="Simultaneous fit \ complete ", type="stop")) #print "result",cpage,str(result),result.parameters,result.fitness,result.stderr try: for page, value in self.page_finder.iteritems(): if value.get_scheduled()==1: #fitdata = value.get_data() list = value.get_model() model= list[0] small_out = [] small_cov = [] i = 0 #Separate result in to data corresponding to each page for p in result.parameters: model_name,param_name = self.split_string(p.name) if model.name == model_name: small_out.append(p.value ) if p.stderr==None: p.stderr=numpy.nan small_cov.append(p.stderr) model.setParam(param_name,p.value) # Display result on each page #print "mmmm",p.value,p.stderr page.onsetValues(result.fitness, small_out,small_cov) #print "out,err",small_out,small_cov #Replot model self.plot_helper(currpage= page,qmin= qmin,qmax= qmax, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) except: wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fitting error: %s" % sys.exc_value)) return def stop_fit(self): """ """ if self.calc_thread != None and self.calc_thread.isrunning(): #self.calc_thread.interrupt() self.calc_thread.stop() wx.PostEvent(self.parent, StatusEvent(status="Fitting \ is cancelled" , type="stop")) def _on_single_fit(self,id=None,qmin=None, qmax=None,ymin=None, ymax=None,xmin=None,xmax=None): """ perform fit for the current page and return chisqr,out and cov @param engineName: type of fit to be performed @param id: unique id corresponding to a fit problem(model, set of data) @param model: model to fit """ #print "in single fitting" #set an engine to perform fit from sans.fit.Fitting import Fit self.fitter= Fit(self._fit_engine) #Setting an id to store model and data in fit engine self.fit_id= 0 if id!=None: self.fit_id= id page_fitted=None fit_problem=None #Get information (model , data) related to the page on #with the fit will be perform current_pg=self.fit_panel.get_current_page() #simul_pg=self.fit_panel.GetPage(1 ) simul_pg=self.sim_page pars=[] #for page, value in self.page_finder.iteritems(): if current_pg!= simul_pg: # if value.get_scheduled() ==1 : value = self.page_finder[current_pg] metadata = value.get_fit_data() list = value.get_model() model = list[0] smearer= value.get_smearer() #Create list of parameters for fitting used templist=[] try: #templist=current_pg.get_param_list() templist=current_pg.get_param_list() for element in templist: pars.append(str(element[0].GetLabelText())) pars.sort() #Do the single fit self.fitter.set_model(Model(model), self.fit_id, pars) if self._fit_engine=="scipy": wx.PostEvent(self.parent, StatusEvent(status="Parameters range will\ be ignored for %s fitting engine"%str(self._fit_engine))) #print "args...:",metadata,self.fit_id,smearer,qmin,qmax,ymin,ymax dy=[] x=[] y=[] if metadata.__class__ in ["Data1D","Theory1D"]: for i in range(len(metadata.dy)): if metadata.dy[i] !=0: dy.append(metadata.dy[i]) x.append(metadata.x[i]) y.append(metadata.y[i]) if len(dy)>0: metadata.dy=numpy.zeros(len(dy)) metadata.dy=dy metadata.y=numpy.zeros(len(y)) metadata.y=y metadata.x=numpy.zeros(len(x)) metadata.x=x self.fitter.set_data(data=metadata,Uid=self.fit_id, smearer=smearer,qmin= qmin,qmax=qmax, ymin=ymin,ymax=ymax) self.fitter.select_problem_for_fit(Uid=self.fit_id,value=value.get_scheduled()) page_fitted=current_pg #self.fit_id+=1 #self.schedule_for_fit( 0,value) except: wx.PostEvent(self.parent, StatusEvent(status="Single Fit error: %s" % sys.exc_value)) return # make sure to keep an alphabetic order #of parameter names in the list try: # If a thread is already started, stop it if self.calc_thread != None and self.calc_thread.isrunning(): self.calc_thread.stop() self.calc_thread =FitThread(parent =self.parent, fn= self.fitter, pars= pars, cpage= page_fitted, qmin=qmin, qmax=qmax, completefn=self._single_fit_completed, updatefn=None) self.calc_thread.queue() self.calc_thread.ready(2.5) except: wx.PostEvent(self.parent, StatusEvent(status="Single Fit error: %s" % sys.exc_value)) return def _on_simul_fit(self, id=None,qmin=None,qmax=None, ymin=None, ymax=None): """ perform fit for all the pages selected on simpage and return chisqr,out and cov @param engineName: type of fit to be performed @param id: unique id corresponding to a fit problem(model, set of data) in park_integration @param model: model to fit """ #set an engine to perform fit from sans.fit.Fitting import Fit self.fitter= Fit(self._fit_engine) self.fit_id= 0 #Setting an id to store model and data if id!=None: self.fit_id= id for page, value in self.page_finder.iteritems(): try: if value.get_scheduled()==1: metadata = value.get_fit_data() list = value.get_model() model= list[0] #Create dictionary of parameters for fitting used cpage= page print "" pars = [] templist = [] templist = page.get_param_list() for element in templist: try: name = str(element[0].GetLabelText()) pars.append(name) except: wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value)) return # need to check this print "new model " new_model=Model(model) param=value.get_model_param() if len(param)>0: for item in param: param_value = item[1] param_name = item[0] new_model.parameterset[ param_name].set( param_value ) self.fitter.set_model(new_model, self.fit_id, pars) #print "sim-->model",metadata,model,self.fit_id, pars dy=[] x=[] y=[] if metadata.__class__ in ["Data1D","Theory1D"]: for i in range(len(metadata.dy)): if metadata.dy[i] !=0: dy.append(metadata.dy[i]) x.append(metadata.x[i]) y.append(metadata.y[i]) if len(dy)>0: metadata.dy=numpy.zeros(len(dy)) metadata.dy=dy metadata.y=numpy.zeros(len(y)) metadata.y=y metadata.x=numpy.zeros(len(x)) metadata.x=x self.fitter.set_data(metadata,self.fit_id,qmin,qmax,ymin,ymax) #print "sim---->value of problem",value.get_scheduled() self.fitter.select_problem_for_fit(Uid=self.fit_id,value=value.get_scheduled()) self.fit_id += 1 value.clear_model_param() #self.schedule_for_fit( 0,value) except: wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value)) return #Do the simultaneous fit try: # If a thread is already started, stop it if self.calc_thread != None and self.calc_thread.isrunning(): self.calc_thread.stop() if self.fit_id==1: self.calc_thread =FitThread(parent =self.parent, fn= self.fitter, qmin=qmin, qmax=qmax, ymin= ymin, ymax= ymax, cpage=cpage, pars= pars, completefn= self._simul_fit_completed, updatefn=None) else: self.calc_thread =FitThread(parent =self.parent, fn= self.fitter, qmin=qmin, qmax=qmax, ymin= ymin, ymax= ymax, completefn= self._simul_fit_completed, updatefn=None) self.calc_thread.queue() self.calc_thread.ready(2.5) except: wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value)) return def _onset_engine(self,event): """ set engine to scipy """ if self._fit_engine== 'park': self._on_change_engine('scipy') else: self._on_change_engine('park') wx.PostEvent(self.parent, StatusEvent(status="Engine set to: %s" % self._fit_engine)) def _on_change_engine(self, engine='park'): """ Allow to select the type of engine to perform fit @param engine: the key work of the engine """ self._fit_engine = engine def _on_model_panel(self, evt): """ react to model selection on any combo box or model menu.plot the model """ model = evt.model name = evt.name #print "name fitting", name #sim_page=self.fit_panel.GetPage(1) sim_page=self.sim_page current_pg = self.fit_panel.get_current_page() if current_pg != sim_page: current_pg.set_panel(model) #model.name = self.page_finder[current_pg].get_name() #print "model name", model.name model.name="M"+str(self.index_model) try: metadata=self.page_finder[current_pg].get_data() M_name=model.name+"= "+name+"("+metadata.group_id+")" except: M_name=model.name+"= "+name self.index_model += 1 # save model name # save the name containing the data name with the appropriate model self.page_finder[current_pg].set_model(model,M_name) self.plot_helper(currpage= current_pg,qmin= None,qmax= None) if self.sim_page!=None: self.sim_page.add_model(self.page_finder) def set_smearer(self,smearer): """ """ current_pg=self.fit_panel.get_current_page() self.page_finder[current_pg].set_smearer(smearer) def redraw_model(self,qmin= None,qmax= None): """ Draw a theory according to model changes or data range. @param qmin: the minimum value plotted for theory @param qmax: the maximum value plotted for theory """ current_pg=self.fit_panel.get_current_page() for page, value in self.page_finder.iteritems(): if page ==current_pg : break self.plot_helper(currpage=page,qmin= qmin,qmax= qmax) def plot_helper(self,currpage, fitModel=None, qmin=None,qmax=None, ymin=None,ymax=None, xmin=None, xmax=None,title=None ): """ Plot a theory given a model and data @param model: the model from where the theory is derived @param currpage: page in a dictionary referring to some data """ if self.fit_panel.GetPageCount() >1: for page in self.page_finder.iterkeys(): if page==currpage : data=self.page_finder[page].get_plotted_data() list=self.page_finder[page].get_model() model=list[0] break #print "model in fitting",model if data!=None and data.__class__.__name__ != 'Data2D': theory = Theory1D(x=[], y=[]) theory.name = model.name theory.group_id = data.group_id theory.id = "Model" x_name, x_units = data.get_xaxis() y_name, y_units = data.get_yaxis() theory.xaxis(x_name, x_units) theory.yaxis(y_name, y_units) if qmin == None : qmin = min(data.x) if qmax == None : qmax = max(data.x) try: tempx = qmin tempy = model.run(qmin) theory.x.append(tempx) theory.y.append(tempy) except : wx.PostEvent(self.parent, StatusEvent(status="fitting \ skipping point x %g %s" %(qmin, sys.exc_value))) for i in range(len(data.x)): try: if data.x[i]> qmin and data.x[i]< qmax: tempx = data.x[i] tempy = model.run(tempx) theory.x.append(tempx) theory.y.append(tempy) except: wx.PostEvent(self.parent, StatusEvent(status="fitting \ skipping point x %g %s" %(data.x[i], sys.exc_value))) try: tempx = qmax tempy = model.run(qmax) theory.x.append(tempx) theory.y.append(tempy) except: wx.PostEvent(self.parent, StatusEvent(status="fitting \ skipping point x %g %s" %(qmin, sys.exc_value)) ) wx.PostEvent(self.parent, NewPlotEvent(plot=theory, title=str(data.name))) else: theory=Data2D(data.data, data.err_data) theory.name= model.name if title !=None: self.title = title theory.id= self.title theory.group_id= self.title+data.name else: self.title= "Analytical model 2D " theory.id= "Model" theory.group_id= "Model"+data.name theory.x_bins= data.x_bins theory.y_bins= data.y_bins tempy=[] #print "max x,y",max(data.xmax,data.xmin),max(data.ymax,data.ymin) if qmin==None: qmin=0#min(math.fabs(data.xmax),math.fabs(data.ymin)) if qmax==None: qmax=math.sqrt(math.pow(max(math.fabs(data.xmax),math.fabs(data.xmin)),2)/ +math.pow(max(math.fabs(data.ymax),math.fabs(data.ymin)),2)) if ymin==None: ymin=data.ymin if ymax==None: ymax=data.ymax if xmin ==None: xmin=data.xmin if xmax==None: xmax=data.xmax theory.data = numpy.zeros((len(data.y_bins),len(data.x_bins))) for j in range(len(data.y_bins)): for i in range(len(data.x_bins)): tempqij=math.sqrt((math.pow(data.y_bins[j],2)+math.pow(data.x_bins[i],2))) if tempqij>= qmin and tempqij<= qmax: theory.data[j][i]=model.runXY([data.y_bins[j],data.x_bins[i]]) else: theory.data[j][i]=0 #None # Later, We need to decide which of 0 and None is better. #print "len(data.x_bins),len(data.y_bins);",len(data.x_bins),len(data.y_bins),qmax #print "fitting : plot_helper:", theory.image #print "fitting : plot_helper:",theory.image theory.detector= data.detector theory.source= data.source theory.qmin= qmin theory.qmax= qmax theory.ymin= ymin theory.ymax= ymax theory.xmin= xmin theory.xmax= xmax wx.PostEvent(self.parent, NewPlotEvent(plot=theory, title=self.title +str(data.name))) def _on_model_menu(self, evt): """ Plot a theory from a model selected from the menu """ name = evt.model.__name__ if hasattr(evt.model, "name"): name = evt.model.name #print "on model menu", name model=evt.model() description=model.description # Create a model page. If a new page is created, the model # will be plotted automatically. If a page already exists, # the content will be updated and the plot refreshed self.fit_panel.add_model_page(model,description,name,topmenu=True) def draw_model(self,model,name ,data=None,description=None,enable1D=True, enable2D=False, qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS): """ draw model with default data value """ if data !=None: self.redraw_model(qmin,qmax) return self._draw_model1D(model,name,model.description, enable1D,qmin,qmax, qstep) self._draw_model2D(model=model, description=model.description, enable2D= enable2D, qmin=qmin, qmax=qmax, qstep=qstep) def _draw_model1D(self,model,name,description=None, enable1D=True, qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS): """ """ if enable1D: x= numpy.linspace(start= qmin, stop= qmax, num= qstep, endpoint=True ) xlen= len(x) y = numpy.zeros(xlen) if not enable1D: for i in range(xlen): y[i] = model.run(x[i]) try: new_plot = Theory1D(x, y) new_plot.name = name new_plot.xaxis("\\rm{Q}", 'A^{-1}') new_plot.yaxis("\\rm{Intensity} ","cm^{-1}") new_plot.id = "Model" new_plot.group_id ="Model" wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Analytical model 1D")) except: wx.PostEvent(self.parent, StatusEvent(status="Draw model 1D error: %s" % sys.exc_value)) #raise return else: for i in range(xlen): y[i] = model.run(x[i]) try: new_plot = Theory1D(x, y) #print "draw model 1D", name new_plot.name = name new_plot.xaxis("\\rm{Q}", 'A^{-1}') new_plot.yaxis("\\rm{Intensity} ","cm^{-1}") new_plot.id ="Model" new_plot.group_id ="Model" # Pass the reset flag to let the plotting event handler # know that we are replacing the whole plot wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Analytical model 1D ", reset=True )) except: #raise wx.PostEvent(self.parent, StatusEvent(status="Draw model 1D error: %s" % sys.exc_value)) return def update(self, output,time): """ """ pass def complete(self, output, elapsed, model, qmin, qmax,qstep=DEFAULT_NPTS): """ """ wx.PostEvent(self.parent, StatusEvent(status="Calc \ complete !" , type="stop")) #print "complete",output, model,qmin, qmax data = output temp= numpy.zeros(numpy.shape(data)) temp[temp==0]=1 theory= Data2D(image=data, err_image=temp) from DataLoader.data_info import Detector, Source detector = Detector() theory.detector=[] theory.detector.append(detector) theory.detector[0].distance=1e+32#13705.0 theory.source= Source() theory.source.wavelength=2*math.pi/1e+32#8.4 theory.x_bins =[] theory.y_bins =[] #Now qmax is xmax. xmax=2*theory.detector[0].distance*math.atan(qmax/(4*math.pi/theory.source.wavelength)) theory.detector[0].pixel_size.x= xmax/(qstep/2-0.5)#5.0 theory.detector[0].pixel_size.y= xmax/(qstep/2-0.5)#5.0 theory.detector[0].beam_center.x= qmax theory.detector[0].beam_center.y= qmax #print "xmax,qmax",xmax,qmax # compute x_bins and y_bins # Qx and Qy vectors distance = theory.detector[0].distance pixel = qstep/2-1 theta = pixel / distance / qstep#100.0 wavelength = theory.source.wavelength pixel_width_x = theory.detector[0].pixel_size.x pixel_width_y = theory.detector[0].pixel_size.y center_x = theory.detector[0].beam_center.x/pixel_width_x center_y = theory.detector[0].beam_center.y/pixel_width_y size_x, size_y= numpy.shape(theory.data) #print "size_x,size_y",size_x, size_y #This case, q and x are equivalent to each other. for i_x in range(size_x): theta = (i_x-center_x)*pixel_width_x / distance #/ size_x#100.0 qx = 4.0*math.pi/wavelength * math.tan(theta/2.0) theory.x_bins.append(qx) for i_y in range(size_y): theta = (i_y-center_y)*pixel_width_y / distance #/ size_y#100.0 qy =4.0*math.pi/wavelength * math.tan(theta/2.0) theory.y_bins.append(qy) #theory.err_data= numpy. theory.name= model.name theory.group_id ="Model" theory.id ="Model" theory.xmin= -qmax#/math.sqrt(2)#You can not do sqrt(2), that changes axis scale not data itself theory.xmax= qmax#/math.sqrt(2) theory.ymin= -qmax#/math.sqrt(2) theory.ymax= qmax#/math.sqrt(2) #print "model draw comptele xmax",theory.xmax,model.name wx.PostEvent(self.parent, NewPlotEvent(plot=theory, title="Analytical model 2D ", reset=True )) def _draw_model2D(self,model,description=None, enable2D=False, qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS): x= numpy.linspace(start= -1*qmax, stop= qmax, num= qstep, endpoint=True ) y = numpy.linspace(start= -1*qmax, stop= qmax, num= qstep, endpoint=True ) lx = len(x) #print x #data=numpy.zeros([len(x),len(y)]) self.model= model if enable2D: try: from sans.guiframe.model_thread import Calc2D # print "in draw model 2d ",self.model self.calc_thread = Calc2D(parent =self.parent,x=x, y=y,model= self.model, qmin=qmin, qmax=qmax, qstep=qstep, completefn=self.complete, updatefn=None) self.calc_thread.queue() self.calc_thread.ready(2.5) except: raise def show_panel2D(self, id=None ): self.parent.show_panel(self.model2D_id) if __name__ == "__main__": i = Plugin()