import re import sys, wx, logging import string, numpy, math from copy import deepcopy from danse.common.plottools.plottables import Data1D, Theory1D,Data2D from danse.common.plottools.PlotPanel import PlotPanel from sans.guicomm.events import NewPlotEvent, StatusEvent from sans.guicomm.events import EVT_SLICER_PANEL,ERR_DATA from sans.fit.AbstractFitEngine import Model,FitData1D,FitData2D#,Data, 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 import time import thread 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()