Changeset 10bfeb3 in sasview for plottools/src/danse/common/plottools/plottables.py
- Timestamp:
- Apr 27, 2012 10:23:08 AM (12 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- f60a8c2
- Parents:
- 8a621ac
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
plottools/src/danse/common/plottools/plottables.py
r82a54b8 r10bfeb3 44 44 import copy 45 45 import numpy 46 import math47 46 import sys 48 47 … … 51 50 def any(L): 52 51 for cond in L: 53 if cond: return True 52 if cond: 53 return True 54 54 return False 55 55 56 def all(L): 56 57 for cond in L: … … 59 60 return True 60 61 61 # Graph structure for holding multiple plottables 62 62 63 class Graph: 63 64 """ … … 129 130 (as opposed to changing the basic properties) 130 131 """ 131 if units != "": 132 132 if units != "": 133 name = "%s (%s)" % (name, units) 133 134 self.prop["xlabel"] = name 134 135 self.prop["xunit"] = units … … 140 141 (as opposed to changing the basic properties) 141 142 """ 142 if units != "": 143 143 if units != "": 144 name = "%s (%s)" % (name, units) 144 145 self.prop["ylabel"] = name 145 146 self.prop["yunit"] = units … … 149 150 Properties of the x axis. 150 151 """ 151 if units != "": 152 152 if units != "": 153 name = "%s (%s)" % (name, units) 153 154 self.prop["xlabel"] = name 154 155 self.prop["xunit"] = units … … 160 161 Properties of the y axis. 161 162 """ 162 if units != "": 163 163 if units != "": 164 name = "%s (%s)" % (name, units) 164 165 self.prop["ylabel"] = name 165 166 self.prop["yunit"] = units … … 200 201 if plottable in self.plottables: 201 202 return True 202 return False 203 return False 203 204 204 205 def add(self, plottable, color=None): … … 211 212 self.color += plottable.colors() 212 213 self.plottables[plottable] = self.color 213 214 214 215 def changed(self): 215 216 """Detect if any graphed plottables have changed""" … … 250 251 if plottable in self.plottables: 251 252 del self.plottables[plottable] 252 self.color = len(self.plottables) 253 self.color = len(self.plottables) 253 254 254 255 def reset_scale(self): … … 263 264 self.color = -1 264 265 self.symbol = 0 265 self.prop = {"xlabel": "", "xunit":None,266 "ylabel": "","yunit":None,267 "title": ""}266 self.prop = {"xlabel": "", "xunit": None, 267 "ylabel": "", "yunit": None, 268 "title": ""} 268 269 self.plottables = {} 269 270 … … 297 298 """ 298 299 This method returns a dictionary of plottables contained in graph 299 It is just by Plotpanel to interact with the complete list of plottables 300 It is just by Plotpanel to interact with the complete list of plottables 300 301 inside the graph. 301 302 """ … … 310 311 for p in self.plottables: 311 312 if p.custom_color is not None: 312 p.render(plot, color=p.custom_color, symbol=0, 313 p.render(plot, color=p.custom_color, symbol=0, 313 314 markersize=p.markersize, label=labels[p]) 314 315 else: 315 p.render(plot, color=self.plottables[p], symbol=0, 316 p.render(plot, color=self.plottables[p], symbol=0, 316 317 markersize=p.markersize, label=labels[p]) 317 318 plot.render() … … 346 347 menu for the graph. 347 348 348 type: operational axis. This determines whether the 349 type: operational axis. This determines whether the 349 350 transform should appear on x,y or z axis context 350 351 menus, or if it should appear in the context menu for … … 353 354 inventory: (not implemented) 354 355 a dictionary of user settable parameter names and 355 their associated types. These should appear as keyword 356 arguments to the transform call. For example, Fresnel 356 their associated types. These should appear as keyword 357 arguments to the transform call. For example, Fresnel 357 358 reflectivity requires the substrate density: 358 359 { 'rho': type.Value(10e-6/units.angstrom**2) } 359 360 360 Supply reasonable defaults in the callback so that 361 limited plotting clients work even though they cannot 361 Supply reasonable defaults in the callback so that 362 limited plotting clients work even though they cannot 362 363 set the inventory. 363 364 … … 373 374 the standard x,dx,y,dy,z,dz attributes appropriately. 374 375 375 If the call raises a NotImplemented error the dataline 376 If the call raises a NotImplemented error the dataline 376 377 will not be plotted. The associated string will usually 377 378 be 'Not a valid transform', though other strings are possible. … … 380 381 381 382 """ 382 raise NotImplemented, "Not a valid transform"383 raise NotImplemented, "Not a valid transform" 383 384 384 385 # Related issues … … 387 388 # log scale: 388 389 # All axes have implicit log/linear scaling options. 389 # 390 # 390 391 # normalization: 391 392 # Want to display raw counts vs detector efficiency correction … … 401 402 # 402 403 # multiline graph: 403 # How do we show/hide data parts. E.g., data or theory, or 404 # How do we show/hide data parts. E.g., data or theory, or 404 405 # different polarization cross sections? One way is with 405 406 # tags: each plottable has a set of tags and the tags are … … 420 421 """ 421 422 """ 422 # Short ascii name to refer to the plottable in a menu 423 # Short ascii name to refer to the plottable in a menu 423 424 short_name = None 424 425 # Fancy name … … 434 435 interactive = True 435 436 custom_color = None 436 markersize = 5 #default marker size is 'size 5'437 markersize = 5 # default marker size is 'size 5' 437 438 438 439 def __init__(self): … … 441 442 self._xunit = "" 442 443 self._yaxis = "" 443 self._yunit = "" 444 self._yunit = "" 444 445 445 446 def __setattr__(self, name, value): … … 495 496 def labels(cls, collection): 496 497 """ 497 Construct a set of unique labels for a collection of plottables of 498 Construct a set of unique labels for a collection of plottables of 498 499 the same type. 499 500 … … 509 510 else: 510 511 for i in xrange(len(collection)): 511 map[collection[i]] = "%s %d" %(basename, i)512 map[collection[i]] = "%s %d" % (basename, i) 512 513 return map 514 513 515 ##Use the following if @classmethod doesn't work 514 516 # labels = classmethod(labels) … … 526 528 def set_View(self, x, y): 527 529 """Load View""" 528 self.x = x530 self.x = x 529 531 self.y = y 530 532 self.reset_view() … … 541 543 """ 542 544 The base class makes sure the correct units are being used for 543 subsequent plottable. 544 545 For now it is assumed that the graphs are commensurate, and if you 545 subsequent plottable. 546 547 For now it is assumed that the graphs are commensurate, and if you 546 548 put a Qx object on a Temperature graph then you had better hope 547 549 that it makes sense. … … 560 562 return False 561 563 562 563 564 def colors(self): 564 565 """Return the number of colors need to render the object""" … … 577 578 return self.view.returnXview() 578 579 579 def check_data_PlottableX(self): 580 """ 581 Since no transformation is made for log10(x), check that 580 def check_data_PlottableX(self): 581 """ 582 Since no transformation is made for log10(x), check that 582 583 no negative values is plot in log scale 583 584 """ 584 585 self.view.check_data_logX() 585 586 586 def check_data_PlottableY(self): 587 def check_data_PlottableY(self): 587 588 """ 588 589 Since no transformation is made for log10(y), check that 589 590 no negative values is plot in log scale 590 591 """ 591 self.view.check_data_logY() 592 self.view.check_data_logY() 592 593 593 594 def transformX(self, transx, transdx): 594 595 """ 595 Receive pointers to function that transform x and dx 596 Receive pointers to function that transform x and dx 596 597 and set corresponding View pointers 597 598 … … 604 605 def transformY(self, transy, transdy): 605 606 """ 606 Receive pointers to function that transform y and dy 607 Receive pointers to function that transform y and dy 607 608 and set corresponding View pointers 608 609 … … 628 629 """ 629 630 self.view.onFitRangeView(xmin, xmax) 630 631 632 631 633 class View: 632 634 """ … … 666 668 :param x: array of x values 667 669 :param y: array of y values 668 :param dx: array of errors values on x 670 :param dx: array of errors values on x 669 671 :param dy: array of error values on y 670 672 … … 675 677 has_err_y = not (dy == None or len(dy) == 0) 676 678 677 if(x != None) and (y != None): 678 if not dx == None and not len(dx) == 0 and not len(x) == len(dx):679 if(x != None) and (y != None): 680 if not dx == None and not len(dx) == 0 and not len(x) == len(dx): 679 681 msg = "Plottable.View: Given x and dx are not" 680 msg += " of the same length" 682 msg += " of the same length" 681 683 raise ValueError, msg 682 684 # Check length of y array … … 686 688 raise ValueError, msg 687 689 688 if not dy == None and not len(dy) == 0 and not len(y) ==len(dy):690 if not dy == None and not len(dy) == 0 and not len(y) == len(dy): 689 691 msg = "Plottable.View: Given y and dy are not of the same " 690 msg += "length: len(y)=%s, len(dy)=%s" % (len(y),len(dy))692 msg += "length: len(y)=%s, len(dy)=%s" % (len(y), len(dy)) 691 693 raise ValueError, msg 692 694 self.x = [] … … 708 710 for i in range(len(x)): 709 711 try: 710 tempx = self.funcx(x[i],y[i])711 tempy = self.funcy(y[i],x[i])712 tempx = self.funcx(x[i], y[i]) 713 tempy = self.funcy(y[i], x[i]) 712 714 if has_err_x: 713 715 tempdx = self.funcdx(x[i], y[i], dx[i], dy[i]) … … 727 729 if not len(self.x) == len(self.y): 728 730 msg = "Plottable.View: transformed x " 729 msg += "and y are not of the same length" 731 msg += "and y are not of the same length" 730 732 raise ValueError, msg 731 733 if has_err_x and not (len(self.x) and len(self.dx)): 732 734 msg = "Plottable.View: transformed x and dx" 733 msg += " are not of the same length" 735 msg += " are not of the same length" 734 736 raise ValueError, msg 735 737 if has_err_y and not (len(self.y) and len(self.dy)): 736 738 msg = "Plottable.View: transformed y" 737 msg += " and dy are not of the same length" 739 msg += " and dy are not of the same length" 738 740 raise ValueError, msg 739 741 # Check that negative values are not plot on x and y axis for … … 750 752 """ 751 753 Reset x,y,dx and y in their full range and in the initial scale 752 in case their previous range has changed 753 754 in case their previous range has changed 754 755 """ 755 756 self.x = self.Xreel … … 758 759 self.dy = self.DYreel 759 760 760 def setTransformX(self, funcx, funcdx): 761 """ 762 Receive pointers to function that transform x and dx 761 def setTransformX(self, funcx, funcdx): 762 """ 763 Receive pointers to function that transform x and dx 763 764 and set corresponding View pointers 764 765 765 766 :param transx: pointer to function that transforms x 766 767 :param transdx: pointer to function that transforms dx 767 768 768 """ 769 769 self.funcx = funcx … … 772 772 def setTransformY(self, funcy, funcdy): 773 773 """ 774 Receive pointers to function that transform y and dy 774 Receive pointers to function that transform y and dy 775 775 and set corresponding View pointers 776 776 777 777 :param transx: pointer to function that transforms y 778 778 :param transdx: pointer to function that transforms dy 779 780 """ 779 """ 781 780 self.funcy = funcy 782 781 self.funcdy = funcdy … … 788 787 return self.x, self.y, self.dx, self.dy 789 788 790 def check_data_logX(self): 789 def check_data_logX(self): 791 790 """ 792 791 Remove negative value in x vector to avoid plotting negative 793 792 value of Log10 794 795 793 """ 796 794 tempx = [] … … 802 800 if self.dy == None: 803 801 self.dy = numpy.zeros(len(self.y)) 804 if self.xLabel == "log10(x)" 802 if self.xLabel == "log10(x)": 805 803 for i in range(len(self.x)): 806 804 try: … … 812 810 except: 813 811 print "check_data_logX: skipping point x %g" % self.x[i] 814 print sys.exc_value 812 print sys.exc_value 815 813 pass 816 814 self.x = tempx … … 819 817 self.dy = tempdy 820 818 821 def check_data_logY(self): 822 """ 823 Remove negative value in y vector 819 def check_data_logY(self): 820 """ 821 Remove negative value in y vector 824 822 to avoid plotting negative value of Log10 825 823 … … 833 831 if self.dy == None: 834 832 self.dy = numpy.zeros(len(self.y)) 835 if (self.yLabel == "log10(y)" 833 if (self.yLabel == "log10(y)"): 836 834 for i in range(len(self.x)): 837 835 try: 838 836 if (self.y[i] > 0): 839 837 tempx.append(self.x[i]) … … 841 839 tempy.append(self.y[i]) 842 840 tempdy.append(self.dy[i]) 843 844 print "check_data_logY: skipping point %g" % self.y[i]845 print sys.exc_value 841 except: 842 print "check_data_logY: skipping point %g" % self.y[i] 843 print sys.exc_value 846 844 pass 847 845 self.x = tempx … … 865 863 self.dx = numpy.zeros(len(self.x)) 866 864 if self.dy == None: 867 self.dy =numpy.zeros(len(self.y))865 self.dy = numpy.zeros(len(self.y)) 868 866 if (xmin != None) and (xmax != None): 869 867 for i in range(len(self.x)): … … 876 874 self.y = tempy 877 875 self.dx = tempdx 878 self.dy = tempdy 879 876 self.dy = tempdy 877 878 880 879 class Data2D(Plottable): 881 880 """ … … 910 909 self._yunit = 'A^{-1}' 911 910 912 ### might remove that later 911 ### might remove that later 913 912 ## Vector of Q-values at the center of each bin in x 914 913 self.x_bins = [] … … 1003 1002 plot.image(self.data, self.qx_data, self.qy_data, 1004 1003 self.xmin, self.xmax, self.ymin, 1005 self.ymax, self.zmin, self.zmax, **kw) 1004 self.ymax, self.zmin, self.zmax, **kw) 1006 1005 1007 1006 def changed(self): … … 1021 1020 map[item] = item.label 1022 1021 return map 1022 1023 1023 1024 1024 class Data1D(Plottable): … … 1060 1060 if self.interactive == True: 1061 1061 kw['symbol'] = self.symbol 1062 kw['id'] = 1062 kw['id'] = self.id 1063 1063 kw['hide_error'] = self.hide_error 1064 1064 kw['markersize'] = self.markersize 1065 1065 plot.interactive_points(self.view.x, self.view.y, 1066 1066 dx=self.view.dx, dy=self.view.dy, 1067 name=self.name, **kw) 1067 name=self.name, **kw) 1068 1068 else: 1069 1069 kw['id'] = self.id … … 1072 1072 kw['color'] = self.custom_color 1073 1073 kw['markersize'] = self.markersize 1074 plot.points(self.view.x, self.view.y, dx=self.view.dx, 1074 plot.points(self.view.x, self.view.y, dx=self.view.dx, 1075 1075 dy=self.view.dy, marker=self.symbollist[self.symbol], **kw) 1076 1076 … … 1089 1089 map[item] = item.label 1090 1090 return map 1091 1091 1092 1092 1093 class Theory1D(Plottable): … … 1121 1122 """ 1122 1123 """ 1123 if self.interactive==True: 1124 1125 kw['id'] = self.id 1124 if self.interactive == True: 1125 kw['id'] = self.id 1126 1126 plot.interactive_curve(self.view.x, self.view.y, 1127 1127 dy=self.view.dy, 1128 1128 name=self.name, **kw) 1129 1129 else: 1130 kw['id'] = 1130 kw['id'] = self.id 1131 1131 plot.curve(self.view.x, self.view.y, dy=self.view.dy, **kw) 1132 1132 … … 1139 1139 map = {} 1140 1140 for item in collection: 1141 #map[item] = label(item, collection)1142 #map[item] = r"$\rm{%s}$" % item.name1143 1141 if item.label == "theory": 1144 1142 item.label = item.name … … 1175 1173 return self.data.changed() or self.theory.changed() 1176 1174 1175 1177 1176 # --------------------------------------------------------------- 1178 1177 class Text(Plottable): … … 1190 1189 self.ypos = ypos 1191 1190 1192 def render(self, plot,**kw):1191 def render(self, plot, **kw): 1193 1192 """ 1194 1193 """ 1195 1194 from matplotlib import transforms 1196 1195 1197 xcoords =transforms.blended_transform_factory(plot.subplot.transAxes,1198 plot.subplot.transAxes)1196 xcoords = transforms.blended_transform_factory(plot.subplot.transAxes, 1197 plot.subplot.transAxes) 1199 1198 plot.subplot.text(self.xpos, 1200 1199 self.ypos, … … 1206 1205 def setText(self, text): 1207 1206 """Set the text string.""" 1208 self.text = 1207 self.text = text 1209 1208 1210 1209 def getText(self, text): … … 1230 1229 class Chisq(Plottable): 1231 1230 """ 1232 Chisq plottable plots the chisq 1231 Chisq plottable plots the chisq 1233 1232 """ 1234 1233 def __init__(self, chisq=None): … … 1265 1264 Set the chisq value. 1266 1265 """ 1267 self._chisq = 1266 self._chisq = chisq 1268 1267 1269 1268 … … 1275 1274 # Construct a simple graph 1276 1275 if False: 1277 x = nx.array([1,2,3,4,5,6], 'd')1278 y = nx.array([4,5,6,5,4,5], 'd')1276 x = nx.array([1,2,3,4,5,6], 'd') 1277 y = nx.array([4,5,6,5,4,5], 'd') 1279 1278 dy = nx.array([0.2, 0.3, 0.1, 0.2, 0.9, 0.3]) 1280 1279 else: 1281 x = nx.linspace(0, 1.,10000)1280 x = nx.linspace(0, 1., 10000) 1282 1281 y = nx.sin(2 * nx.pi * x * 2.8) 1283 1282 dy = nx.sqrt(100 * nx.abs(y)) / 100 … … 1289 1288 graph.add(data) 1290 1289 graph.add(Theory1D(x, y, dy=dy)) 1291 return graph 1290 return graph 1291 1292 1292 1293 1293 def demo_plotter(graph): … … 1306 1306 1307 1307 class GraphUpdate: 1308 callnum=0 1308 callnum = 0 1309 1309 1310 def __init__(self, graph, plotter): 1310 1311 self.graph, self.plotter = graph, plotter 1312 1311 1313 def __call__(self): 1312 if self.graph.changed(): 1314 if self.graph.changed(): 1313 1315 self.graph.render(self.plotter) 1314 1316 return True 1315 1317 return False 1318 1316 1319 def onIdle(self, event): 1317 #print "On Idle checker %d"%(self.callnum)1318 1320 self.callnum = self.callnum + 1 1319 1321 if self.__call__(): 1320 pass # event.RequestMore()1322 pass # event.RequestMore() 1321 1323 update = GraphUpdate(graph, plotter) 1322 1324 frame.Bind(wx.EVT_IDLE, update.onIdle) 1323 1325 app.MainLoop() 1324 1325 import sys; print sys.version1326 if __name__ == "__main__":1327 demo_plotter(sample_graph())1328
Note: See TracChangeset
for help on using the changeset viewer.