source: sasview/sansmodels/Plotter1D.py @ f03b027

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 f03b027 was c510183, checked in by Gervaise Alina <gervyh@…>, 17 years ago
  • Property mode set to 100644
File size: 8.9 KB
RevLine 
[c510183]1"""
2    Class that manages what is being displayed on the 1D plot
3    of a SANS modeling application
4   
5    TODO: Eliminate the code to re-read the data in menu_Simple and Menu_Guinier.
6          Modify the way you store and handle the data in Data1D
7         
8    TODO: use only one menu entry for "Toggle between Q and Q**2 scale" instead
9          of have one menu entry for Q and one menu entry for Q**2.
10          You want to be consistent in the way you present options for the x-axis
11          and y-axis.
12           
13"""
14
15import wx
16import wx.lib.newevent
17
18(FunctionParamEvent, EVT_FUNC_PARS) = wx.lib.newevent.NewEvent()
19
20from PlotPanel import PlotPanel
21import numpy, pylab
22from plottables import Plottable, Graph
23import os
24import math
25from scipy import optimize
26
27
28
29DEFAULT_QMIN = 0
30DEFAULT_QMAX = 0.05
31DEFAULT_QSTEP = 0.001
32
33
34class Data1D(Plottable):
35    """Data plottable: scatter plot of x,y with errors in x and y.
36    """
37   
38    def __init__(self,x,y,dx=None,dy=None):
39        """Draw points specified by x[i],y[i] in the current color/symbol.
40        Uncertainty in x is given by dx[i], or by (xlo[i],xhi[i]) if the
41        uncertainty is asymmetric.  Similarly for y uncertainty.
42
43        The title appears on the legend.
44        The label, if it is different, appears on the status bar.
45        """
46        self.name = "DATA"
47        self.x = x
48        self.y = y
49        self.dx = dx
50        self.dy = dy
51        self.hidden = False
52       
53       
54
55    def render(self,plot,**kw):
56        plot.curve(self.x,self.y,dy=self.dy,**kw)
57
58    def changed(self):
59        return False
60
61    @classmethod
62    def labels(cls, collection):
63        """Build a label mostly unique within a collection"""
64        map = {}
65        for item in collection:
66            map[item] = r"$\rm{%s}$" % item.name
67        return map
68
69
70class ModelPanel1D(PlotPanel):
71    def __init__(self, parent, id = -1, color = None,\
72        dpi = None, style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
73        PlotPanel.__init__(self, parent, id = id, style = style, **kwargs)
74
75        self.parent = parent
76        self.qmin = DEFAULT_QMIN
77        self.qmax = DEFAULT_QMAX
78        self.qstep = DEFAULT_QSTEP
79       
80        self.figure.subplots_adjust(bottom=.25)
81
82        self.set_yscale('log')
83        self.set_xscale('linear')
84        self.x = pylab.arange(self.qmin, self.qmax+self.qstep*0.01, self.qstep)
85        # Error on x
86        self.dx = numpy.zeros(len(self.x))
87        # Intensity values
88        y  = numpy.ones(len(self.x))
89        # Error on y
90        self.dy = numpy.zeros(len(self.x))
91 
92        # Plottables
93        self.file_data = Data1D(x=[], y=[], dx=[], dy=[])
94        self.file_data.name = "Loaded 1D data"
95       
96        self.t = pylab.arange(0.0, 10, 1)
97        self.r = [0,3,2,4.5,6,1,2,4,7,9]
98        self.file_data1 = Data1D(x=self.t, y=[], dx=self.r, dy=self.r)
99       
100        # Graph       
101        self.graph = Graph()
102        self.graph.xaxis('\\rm{q} ', 'A^{-1}')
103        self.graph.yaxis("\\rm{Intensity} ","cm^{-1}")
104        self.graph.add(self.file_data)
105        #self.graph.add(self.file_data1)
106        self.graph.render(self)
107       
108       
109        # Bind events
110        self.parent.Bind(EVT_FUNC_PARS, self._onEVT_FUNC_PARS)
111
112    def onSave1DData(self, evt):
113        """
114            Saves the date in a file
115            @param evt: wx event
116        """
117        path = None
118        dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
119        if dlg.ShowModal() == wx.ID_OK:
120            path = dlg.GetPath()
121            mypath = os.path.basename(path)
122            print path
123        dlg.Destroy()
124        if not path == None:
125       
126            out = open(path, 'w')
127            out.write("<q>   <I_1D>\n")
128            for i in range(len(self.file_data.x)):
129                out.write("%g  %g\n" % (self.file_data.x[i], self.file_data.y[i]))
130            out.close()
131           
132    def onContextMenu(self, event):
133        """
134            Pop up a context menu
135        """
136        # Slicer plot popup menu
137        slicerpop = wx.Menu()
138        slicerpop.Append(314, "&Save 1D model points (%s)" % self.file_data.name,
139                              'Save randomly oriented data currently displayed')
140       
141        slicerpop.Append(316, '&Load 1D data file')
142        slicerpop.Append(321, '&Display Error')
143        slicerpop.AppendSeparator()
144        # Those labels were wrong. The way you coded it, it's note necessarily log(I)!
145        slicerpop.Append(315, '&Toggle Linear/Log intensity scale Y-axis')
146        slicerpop.Append(319, '&Plot Q')
147        slicerpop.Append(317, '&Plot Q**2')
148        slicerpop.Append(320, '&Plot log(Q)')
149       
150        wx.EVT_MENU(self, 314, self.onSave1DData)
151        wx.EVT_MENU(self, 315, self._onToggleScale)
152        wx.EVT_MENU(self, 316, self._onLoad1DData)
153       
154        wx.EVT_MENU(self, 319, self._onLinearQ)
155        wx.EVT_MENU(self, 317, self._onSquaredQ)
156        wx.EVT_MENU(self, 320, self._onLogQ)
157        wx.EVT_MENU(self, 321, self._onError)
158        pos = event.GetPosition()
159        pos = self.ScreenToClient(pos)
160        self.PopupMenu(slicerpop, pos)
161       
162    def _onError(self, event):
163        print self.file_data1.dx
164        a,b,c=self.points(x=self.file_data1.x, y=self.file_data1.y, \
165                    dx=self.file_data1.dx , dy=self.file_data1.dy)
166       
167        self.graph.add(b)
168        #self.graph.add(c)
169        self.graph.render(self)
170        self.subplot.figure.canvas.draw_idle()
171    def _onFit(self,event):
172        print "the SansFit goes here"
173       
174    def _onEVT_FUNC_PARS(self, event):
175        """
176            Plot x * cstA + cstB
177        """
178        a=event.cstA
179        b=event.cstB
180        temp=[]
181       
182        if self.file_data.x:
183            for x_i in self.file_data.x:
184                temp.append(Line_function(x_i,a,b))
185            self.file_data1.y =temp
186            self.file_data1.x= self.file_data.x
187        else: 
188       
189            for x_i in self.file_data1.x:
190                temp.append(Line_function(x_i,a,b))
191        self.file_data1.y =temp
192     
193        self.file_data1.name = "Loaded 1D data"     
194        self.graph.xaxis('\\rm{q} ', 'A^{-1}')
195        self.graph.yaxis("\\rm{Intensity} ","cm^{-1}")
196        self.graph.add(self.file_data1)
197        self.graph.render(self)
198        self.subplot.figure.canvas.draw_idle()
199       
200    def _onLoad1DData(self, event):
201        """
202            Load a data file
203        """
204        path = None
205        dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.OPEN)
206        if dlg.ShowModal() == wx.ID_OK:
207            path = dlg.GetPath()
208            mypath = os.path.basename(path)
209        dlg.Destroy()
210
211        file_x = []
212        file_y = []
213        if not path == None:
214            self.path =path
215            input_f = open(path,'r')
216            buff = input_f.read()
217            lines = buff.split('\n')
218            for line in lines:
219                try:
220                    toks = line.split()
221                    x = float(toks[0])
222                    y = float(toks[1])
223                    file_x.append(x)
224                    file_y.append(y)
225                except:
226                    print "READ ERROR", line
227           
228        self.file_data.x = file_x
229        self.file_data.y = file_y
230       
231        self.file_data.name = "Loaded 1D data"     
232        self.graph.xaxis('\\rm{q} ', 'A^{-1}')
233        self.graph.yaxis("\\rm{Intensity} ","cm^{-1}")
234       
235        self.graph.add(self.file_data)
236        self.graph.render(self)
237        self.subplot.figure.canvas.draw_idle()
238
239    def onMenuGuinier(self, event):
240        """
241            This method plot I vs Q**2   
242        """ 
243        file_x =[]
244        for entry in self.file_data.x:
245            file_x.append(entry * entry)
246        self.file_data.x = file_x
247        self.graph.xaxis('\\rm{q**2  } ', 'A^{-2}')
248             
249    def _onSquaredQ(self, event):
250        """
251            This method plots Q**2
252        """
253        self.graph.xaxis('\\rm{q}^2 ', 'A^{-2}')
254        self.set_xscale('squared')
255
256        self.graph.render(self)
257        self.subplot.figure.canvas.draw_idle()
258
259    def _onLinearQ(self, event):
260        """
261            This method plots Q   
262        """
263        self.graph.xaxis('\\rm{q} ', 'A^{-1}')     
264        self.set_xscale('linear')
265     
266        self.graph.render(self)
267        self.subplot.figure.canvas.draw_idle()
268
269    def _onToggleScale(self, event):
270        """
271            Toggle the scale of the y-axis
272        """
273        if self.get_yscale() == 'log':
274            self.set_yscale('linear')
275        else:
276            self.set_yscale('log')
277        self.subplot.figure.canvas.draw_idle()
278
279    def _onLogQ(self, event):
280        """
281            Plot log(q)
282        """
283        self.set_xscale('log')
284        self.graph.xaxis('\\rm{q} ', 'A^{-1}')
285       
286        self.graph.render(self)
287        self.subplot.figure.canvas.draw_idle()
288       
289       
290def Line_function(x, paramA, paramB):
291    """
292       linear function
293    """
294    return x * paramA + paramB
Note: See TracBrowser for help on using the repository browser.