source: sasview/guiframe/state.py @ 2bd9927

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 2bd9927 was ca88b2e, checked in by Gervaise Alina <gervyh@…>, 15 years ago

working on history panel

  • Property mode set to 100644
File size: 7.1 KB
Line 
1"""
2    Object to manage the state of the application
3"""
4
5#TODO: use both CPUs and break the calculations in two threads
6#TODO: stop threads before starting a new one
7
8import wx
9import wx.lib.newevent
10
11import ModelParameters
12import history
13import modelData
14from model_thread import Calc2D, Calc1D, Calc2D_4fold, Calc2D_all
15from copy import deepcopy
16
17#TODO: State should report back to StateManager instead
18#    of firing these events itself
19(Refresh2DEvent, EVT_2DREFRESH) = wx.lib.newevent.NewEvent()
20(Refresh1DEvent, EVT_1DREFRESH) = wx.lib.newevent.NewEvent()
21
22# Debug printout
23from config import printEVT
24
25
26
27class State:
28   
29    def __init__(self, target=None, model=None, slicer=None):
30        self.target = target
31        self.model  = model
32        self.slicer = slicer
33        self.model_par_memento = None
34        self.detector_memento = None
35        self.averager_memento = None
36        self.pars1D_memento   = None
37       
38        # Keep the latest data
39        self._data_2D = None
40        self._data_1D = None
41        # The following should disappear
42        self.qmax = None
43        self.x_1D = None
44       
45        # Threads
46        self.active = True
47        self.calc_thread_2D = None
48        self.calc_thread_1D = None
49       
50        # Info for history
51        self.description = ''
52       
53    def clone(self):
54        obj          = State(self.target, self.model.clone(), self.slicer)
55        obj._data_1D = deepcopy(self._data_1D)
56        obj._data_2D = deepcopy(self._data_2D)
57        obj.qmax     = deepcopy(self.qmax)
58        obj.x_1D     = deepcopy(self.x_1D)
59        obj.model_par_memento = deepcopy(self.model_par_memento)
60        obj.detector_memento = deepcopy(self.detector_memento)
61        obj.averager_memento = deepcopy(self.averager_memento)
62        obj.description = self.description
63        return obj
64       
65    def clear_data(self):
66        self._data_1D = None
67        self._data_2D = None
68       
69    def stop(self):
70        self.active = False
71        if self.calc_thread_1D != None and self.calc_thread_1D.isrunning():
72            self.calc_thread_1D.stop()
73        if self.calc_thread_2D != None and self.calc_thread_2D.isrunning():
74            self.calc_thread_2D.stop()
75       
76    def setModelParMemento(self, memento):
77        self.model_par_memento = memento
78       
79    def setDetectorMemento(self, memento):
80        self.clear_data()
81        # Change description
82        self.description = '%s' % memento.toString(self.detector_memento)
83        self.detector_memento = memento
84       
85    def setPars1DMemento(self, memento):
86        self.clear_data()
87        # Change description
88        self.description = '%s' % memento.toString(self.pars1D_memento)
89        self.pars1D_memento = memento
90       
91    def setAveragerMemento(self, memento):
92        self.clear_data()
93        self.averager_memento = memento
94       
95    def setModel(self, model):
96        """
97            Set the model and send a history event
98        """
99        # Clean the data to invoke recalc
100        self._data_1D = None
101        self._data_2D = None
102       
103        # Set the model
104        self.model = model
105       
106        self.description = ''
107       
108        return str(self.model.name)
109       
110    def setParams(self, params):
111        """
112            Update parameters and return a name
113            that represents the change (key)
114        """
115        # Clean the data to invoke recalc
116        self._data_1D = None
117        self._data_2D = None
118
119        # Compose string to summarize change       
120        name = self.model.name
121       
122        # Identify and perform changes
123        for item in params:
124            name += "/%s=%-5.5g" % (item, self.model.getParam(item))
125            self.model.setParam(item, params[item])
126       
127        return name
128
129    def setSlicer(self, slicer):
130        self.slicer = slicer
131       
132    def get_data_1d(self, x):
133        """
134            Calculate the data
135            @param min: minimum q-value
136            @param max: maximum q-value
137        """
138       
139        printEVT("State.get_data_1d")
140        if not self.model:
141            return
142       
143        if self._data_1D == None:
144            self.x_1D = deepcopy(x)
145            if self.calc_thread_1D != None and self.calc_thread_1D.isrunning():
146                self.calc_thread_1D.stop()
147               
148            self.calc_thread_1D = Calc1D(x, self.model.clone(), 
149                                completefn=self.complete1D,
150                                updatefn=self.update1D)
151            self.calc_thread_1D.queue()
152            self.calc_thread_1D.ready(2.5)
153        else:
154            printEVT("Dispatch 1D non-recalc data") 
155            wx.PostEvent(self.target, Refresh1DEvent(name=self.model.name, x = self.x_1D,
156                                                     output=deepcopy(self._data_1D)))
157         
158   
159    def get_data_2d(self, max, x, y):
160        """
161            Calculate 2D data
162            @param max: maximum q-value
163        """
164        if not self.model:
165            return
166       
167        if self._data_2D == None:
168            self.qmax = max
169            if self.calc_thread_2D != None and self.calc_thread_2D.isrunning():
170                self.calc_thread_2D.stop()
171               
172            if self.detector_memento == None or self.detector_memento.sym4 == False:   
173                self.calc_thread_2D = Calc2D(x, y, self.model.clone(), 
174                                    completefn=self.complete2D,
175                                    updatefn=self.update2D,
176                                    yieldtime=0.0)
177            else:
178                self.calc_thread_2D = Calc2D_4fold(x, y, self.model.clone(), 
179                                    completefn=self.complete2D,
180                                    updatefn=self.update2D,
181                                    yieldtime=0.0)
182               
183            self.calc_thread_2D.queue()
184            self.calc_thread_2D.ready(2.5)
185        else:
186            printEVT("Dispatch 2D non-recalc data") 
187            wx.PostEvent(self.target, Refresh2DEvent(output=deepcopy(self._data_2D),
188                                                    qmax=self.qmax))
189           
190             
191    def update2D(self, output):
192        printEVT("State.updated2D")
193        if self.active:
194            #self._data_2D = output
195            self._data_2D = deepcopy(output)
196            wx.PostEvent(self.target, Refresh2DEvent(output=deepcopy(self._data_2D),
197                                                qmax=self.qmax))
198   
199    def complete2D(self, output, elapsed):
200        printEVT("%s: Calc 2D complete in %g sec" % (self.model.name, elapsed)) 
201        if self.active:
202            self._data_2D = deepcopy(output)
203            wx.PostEvent(self.target, Refresh2DEvent(output=deepcopy(self._data_2D),
204                                                qmax=self.qmax))
205        else:
206            printEVT("Active = False!")
207
208    def update1D(self, output):
209        pass
210   
211    def complete1D(self, output, elapsed):
212        printEVT("Calc 1D complete in %g sec" % elapsed) 
213        self._data_1D = deepcopy(output)
214        wx.PostEvent(self.target, Refresh1DEvent(name=self.model.name, x = self.x_1D,
215                                                 output=deepcopy(self._data_1D)))
216
217   
Note: See TracBrowser for help on using the repository browser.