source: trunk/python/asapplotter.py @ 1819

Last change on this file since 1819 was 1819, checked in by Kana Sugimoto, 14 years ago

New Development: No

JIRA Issue: No (merge alma branch to trunk)

Ready for Test: Yes

Interface Changes: No

Test Programs: regressions may work

Module(s): all single dish modules

Description:

Merged all changes in alma (r1386:1818) and newfiller (r1774:1818) branch.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 52.5 KB
Line 
1from asap import rcParams, print_log, print_log_dec
2from asap import selector, scantable
3from asap import asaplog
4import matplotlib.axes
5from matplotlib.font_manager import FontProperties
6from matplotlib.text import Text
7
8import re
9
10class asapplotter:
11    """
12    The ASAP plotter.
13    By default the plotter is set up to plot polarisations
14    'colour stacked' and scantables across panels.
15    Note:
16        Currenly it only plots 'spectra' not Tsys or
17        other variables.
18    """
19    def __init__(self, visible=None , **kwargs):
20        self._visible = rcParams['plotter.gui']
21        if visible is not None:
22            self._visible = visible
23        self._plotter = self._newplotter(**kwargs)
24        # additional tool bar
25        self._plotter.figmgr.casabar=self._newcasabar()
26
27        self._panelling = None
28        self._stacking = None
29        self.set_panelling()
30        self.set_stacking()
31        self._rows = None
32        self._cols = None
33        self._autoplot = False
34        self._minmaxx = None
35        self._minmaxy = None
36        self._datamask = None
37        self._data = None
38        self._lmap = None
39        self._title = None
40        self._ordinate = None
41        self._abcissa = None
42        self._abcunit = None
43        self._usermask = []
44        self._maskselection = None
45        self._selection = selector()
46        self._hist = rcParams['plotter.histogram']
47        self._fp = FontProperties()
48        self._panellayout = self.set_panellayout(refresh=False)
49
50    def _translate(self, instr):
51        keys = "s b i p t".split()
52        if isinstance(instr, str):
53            for key in keys:
54                if instr.lower().startswith(key):
55                    return key
56        return None
57
58    def _newplotter(self, **kwargs):
59        backend=matplotlib.get_backend()
60        if not self._visible:
61            from asap.asaplot import asaplot
62        elif backend == 'TkAgg':
63            from asap.asaplotgui import asaplotgui as asaplot
64        elif backend == 'Qt4Agg':
65            from asap.asaplotgui_qt4 import asaplotgui as asaplot
66        elif backend == 'GTkAgg':
67            from asap.asaplotgui_gtk import asaplotgui as asaplot
68        else:
69            from asap.asaplot import asaplot
70        return asaplot(**kwargs)
71
72    def _newcasabar(self):
73        backend=matplotlib.get_backend()
74        if self._visible and backend == "TkAgg":
75            from asap.casatoolbar import CustomToolbarTkAgg
76            return CustomToolbarTkAgg(self)
77        else: return None
78
79    @print_log_dec
80    def plot(self, scan=None):
81        """
82        Plot a scantable.
83        Parameters:
84            scan:   a scantable
85        Note:
86            If a scantable was specified in a previous call
87            to plot, no argument has to be given to 'replot'
88            NO checking is done that the abcissas of the scantable
89            are consistent e.g. all 'channel' or all 'velocity' etc.
90        """
91        if self._plotter.is_dead:
92            if hasattr(self._plotter.figmgr,'casabar'):
93                del self._plotter.figmgr.casabar
94            self._plotter = self._newplotter()
95            self._plotter.figmgr.casabar=self._newcasabar()
96        self._plotter.hold()
97        self._plotter.clear()
98        if not self._data and not scan:
99            msg = "Input is not a scantable"
100            if rcParams['verbose']:
101                #print msg
102                asaplog.push( msg )
103                print_log( 'ERROR' )
104                return
105            raise TypeError(msg)
106        if scan: self.set_data(scan,refresh=False)
107        self._plot(self._data)
108        if self._minmaxy is not None:
109            self._plotter.set_limits(ylim=self._minmaxy)
110        if self._plotter.figmgr.casabar: self._plotter.figmgr.casabar.enable_button()
111        self._plotter.release()
112        self._plotter.tidy()
113        self._plotter.show(hardrefresh=False)
114        print_log()
115        return
116
117    def gca(self):
118        return self._plotter.figure.gca()
119
120    def refresh(self):
121        """Do a soft refresh"""
122        self._plotter.figure.show()
123
124    def create_mask(self, nwin=1, panel=0, color=None):
125        """
126        Interactively define a mask.It retruns a mask that is equivalent to
127        the one created manually with scantable.create_mask.
128        Parameters:
129            nwin:       The number of mask windows to create interactively
130                        default is 1.
131            panel:      Which panel to use for mask selection. This is useful
132                        if different IFs are spread over panels (default 0)
133        """
134        if self._data is None:
135            return []
136        outmask = []
137        self._plotter.subplot(panel)
138        xmin, xmax = self._plotter.axes.get_xlim()
139        marg = 0.05*(xmax-xmin)
140        self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
141        self.refresh()
142
143        def cleanup(lines=False, texts=False, refresh=False):
144            if lines:
145                del self._plotter.axes.lines[-1]
146            if texts:
147                del self._plotter.axes.texts[-1]
148            if refresh:
149                self.refresh()
150
151        for w in xrange(nwin):
152            wpos = []
153            self.text(0.05,1.0, "Add start boundary",
154                      coords="relative", fontsize=10)
155            point = self._plotter.get_point()
156            cleanup(texts=True)
157            if point is None:
158                continue
159            wpos.append(point[0])
160            self.axvline(wpos[0], color=color)
161            self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
162            point = self._plotter.get_point()
163            cleanup(texts=True, lines=True)
164            if point is None:
165                self.refresh()
166                continue
167            wpos.append(point[0])
168            self.axvspan(wpos[0], wpos[1], alpha=0.1,
169                         edgecolor=color, facecolor=color)
170            ymin, ymax = self._plotter.axes.get_ylim()
171            outmask.append(wpos)
172
173        self._plotter.axes.set_xlim(xmin, xmax)
174        self.refresh()
175        if len(outmask) > 0:
176            return self._data.create_mask(*outmask)
177        return []
178
179    # forwards to matplotlib axes
180    def text(self, *args, **kwargs):
181        if kwargs.has_key("interactive"):
182            if kwargs.pop("interactive"):
183                pos = self._plotter.get_point()
184                args = tuple(pos)+args
185        self._axes_callback("text", *args, **kwargs)
186
187    text.__doc__ = matplotlib.axes.Axes.text.__doc__
188
189    def arrow(self, *args, **kwargs):
190        if kwargs.has_key("interactive"):
191            if kwargs.pop("interactive"):
192                pos = self._plotter.get_region()
193                dpos = (pos[0][0], pos[0][1],
194                        pos[1][0]-pos[0][0],
195                        pos[1][1] - pos[0][1])
196                args = dpos + args
197        self._axes_callback("arrow", *args, **kwargs)
198
199    arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
200
201    def annotate(self, text, xy=None, xytext=None, **kwargs):
202        if kwargs.has_key("interactive"):
203            if kwargs.pop("interactive"):
204                xy = self._plotter.get_point()
205                xytext = self._plotter.get_point()
206        if not kwargs.has_key("arrowprops"):
207            kwargs["arrowprops"] = dict(arrowstyle="->")
208        self._axes_callback("annotate", text, xy, xytext, **kwargs)
209
210    annotate.__doc__ = matplotlib.axes.Axes.annotate.__doc__
211
212    def axvline(self, *args, **kwargs):
213        if kwargs.has_key("interactive"):
214            if kwargs.pop("interactive"):
215                pos = self._plotter.get_point()
216                args = (pos[0],)+args
217        self._axes_callback("axvline", *args, **kwargs)
218
219    axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
220
221    def axhline(self, *args, **kwargs):
222        if kwargs.has_key("interactive"):
223            if kwargs.pop("interactive"):
224                pos = self._plotter.get_point()
225                args = (pos[1],)+args
226        self._axes_callback("axhline", *args, **kwargs)
227
228    axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
229
230    def axvspan(self, *args, **kwargs):
231        if kwargs.has_key("interactive"):
232            if kwargs.pop("interactive"):
233                pos = self._plotter.get_region()
234                dpos = (pos[0][0], pos[1][0])
235                args = dpos + args
236        self._axes_callback("axvspan", *args, **kwargs)
237        # hack to preventy mpl from redrawing the patch
238        # it seem to convert the patch into lines on every draw.
239        # This doesn't happen in a test script???
240        #del self._plotter.axes.patches[-1]
241
242    axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
243
244    def axhspan(self, *args, **kwargs):
245        if kwargs.has_key("interactive"):
246            if kwargs.pop("interactive"):
247                pos = self._plotter.get_region()
248                dpos = (pos[0][1], pos[1][1])
249                args = dpos + args
250        self._axes_callback("axhspan", *args, **kwargs)
251        # hack to preventy mpl from redrawing the patch
252        # it seem to convert the patch into lines on every draw.
253        # This doesn't happen in a test script???
254        #del self._plotter.axes.patches[-1]
255
256    axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
257
258    def _axes_callback(self, axesfunc, *args, **kwargs):
259        panel = 0
260        if kwargs.has_key("panel"):
261            panel = kwargs.pop("panel")
262        coords = None
263        if kwargs.has_key("coords"):
264            coords = kwargs.pop("coords")
265            if coords.lower() == 'world':
266                kwargs["transform"] = self._plotter.axes.transData
267            elif coords.lower() == 'relative':
268                kwargs["transform"] = self._plotter.axes.transAxes
269        self._plotter.subplot(panel)
270        self._plotter.axes.set_autoscale_on(False)
271        getattr(self._plotter.axes, axesfunc)(*args, **kwargs)
272        self._plotter.show(False)
273        self._plotter.axes.set_autoscale_on(True)
274    # end matplotlib.axes fowarding functions
275
276    def set_data(self, scan, refresh=True):
277        """
278        Set a scantable to plot.
279        Parameters:
280            scan:      a scantable
281            refresh:   True (default) or False. If True, the plot is
282                       replotted based on the new parameter setting(s).
283                       Otherwise,the parameter(s) are set without replotting.
284        Note:
285           The user specified masks and data selections will be reset
286           if a new scantable is set. This method should be called before
287           setting data selections (set_selection) and/or masks (set_mask).
288        """
289        from asap import scantable
290        if isinstance(scan, scantable):
291            if self._data is not None:
292                if scan != self._data:
293                    self._data = scan
294                    # reset
295                    self._reset()
296                    msg = "A new scantable is set to the plotter. The masks and data selections are reset."
297                    asaplog.push( msg )
298                    print_log( 'INFO' )
299            else:
300                self._data = scan
301                self._reset()
302        else:
303            msg = "Input is not a scantable"
304            if rcParams['verbose']:
305                #print msg
306                asaplog.push( msg )
307                print_log( 'ERROR' )
308                return
309            raise TypeError(msg)
310
311        # ranges become invalid when unit changes
312        if self._abcunit and self._abcunit != self._data.get_unit():
313            self._minmaxx = None
314            self._minmaxy = None
315            self._abcunit = self._data.get_unit()
316            self._datamask = None
317        if refresh: self.plot()
318       
319
320    def set_mode(self, stacking=None, panelling=None, refresh=True):
321        """
322        Set the plots look and feel, i.e. what you want to see on the plot.
323        Parameters:
324            stacking:     tell the plotter which variable to plot
325                          as line colour overlays (default 'pol')
326            panelling:    tell the plotter which variable to plot
327                          across multiple panels (default 'scan'
328            refresh:      True (default) or False. If True, the plot is
329                          replotted based on the new parameter setting(s).
330                          Otherwise,the parameter(s) are set without replotting.
331        Note:
332            Valid modes are:
333                 'beam' 'Beam' 'b':     Beams
334                 'if' 'IF' 'i':         IFs
335                 'pol' 'Pol' 'p':       Polarisations
336                 'scan' 'Scan' 's':     Scans
337                 'time' 'Time' 't':     Times
338        """
339        msg = "Invalid mode"
340        if not self.set_panelling(panelling) or \
341               not self.set_stacking(stacking):
342            if rcParams['verbose']:
343                #print msg
344                asaplog.push( msg )
345                print_log( 'ERROR' )
346                return
347            else:
348                raise TypeError(msg)
349        if refresh and self._data: self.plot(self._data)
350        return
351
352    def set_panelling(self, what=None):
353        mode = what
354        if mode is None:
355             mode = rcParams['plotter.panelling']
356        md = self._translate(mode)
357        if md:
358            self._panelling = md
359            self._title = None
360            return True
361        return False
362
363    def set_layout(self,rows=None,cols=None,refresh=True):
364        """
365        Set the multi-panel layout, i.e. how many rows and columns plots
366        are visible.
367        Parameters:
368             rows:   The number of rows of plots
369             cols:   The number of columns of plots
370             refresh:  True (default) or False. If True, the plot is
371                       replotted based on the new parameter setting(s).
372                       Otherwise,the parameter(s) are set without replotting.
373        Note:
374             If no argument is given, the potter reverts to its auto-plot
375             behaviour.
376        """
377        self._rows = rows
378        self._cols = cols
379        if refresh and self._data: self.plot(self._data)
380        return
381
382    def set_stacking(self, what=None):
383        mode = what
384        if mode is None:
385             mode = rcParams['plotter.stacking']
386        md = self._translate(mode)
387        if md:
388            self._stacking = md
389            self._lmap = None
390            return True
391        return False
392
393    def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True):
394        """
395        Set the range of interest on the abcissa of the plot
396        Parameters:
397            [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
398            refresh:  True (default) or False. If True, the plot is
399                      replotted based on the new parameter setting(s).
400                      Otherwise,the parameter(s) are set without replotting.
401        Note:
402            These become non-sensical when the unit changes.
403            use plotter.set_range() without parameters to reset
404
405        """
406        if xstart is None and xend is None:
407            self._minmaxx = None
408        else:
409            self._minmaxx = [xstart,xend]
410        if ystart is None and yend is None:
411            self._minmaxy = None
412        else:
413            self._minmaxy = [ystart,yend]
414        if refresh and self._data: self.plot(self._data)
415        return
416
417    def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
418        """
419        Specify a mapping for the legend instead of using the default
420        indices:
421        Parameters:
422            mp:        a list of 'strings'. This should have the same length
423                       as the number of elements on the legend and then maps
424                       to the indeces in order. It is possible to uses latex
425                       math expression. These have to be enclosed in r'',
426                       e.g. r'$x^{2}$'
427            fontsize:  The font size of the label (default None)
428            mode:      where to display the legend
429                       Any other value for loc else disables the legend:
430                        0: auto
431                        1: upper right
432                        2: upper left
433                        3: lower left
434                        4: lower right
435                        5: right
436                        6: center left
437                        7: center right
438                        8: lower center
439                        9: upper center
440                        10: center
441            refresh:    True (default) or False. If True, the plot is
442                        replotted based on the new parameter setting(s).
443                        Otherwise,the parameter(s) are set without replotting.
444
445        Example:
446             If the data has two IFs/rest frequencies with index 0 and 1
447             for CO and SiO:
448             plotter.set_stacking('i')
449             plotter.set_legend(['CO','SiO'])
450             plotter.plot()
451             plotter.set_legend([r'$^{12}CO$', r'SiO'])
452        """
453        self._lmap = mp
454        self._plotter.legend(mode)
455        if isinstance(fontsize, int):
456            from matplotlib import rc as rcp
457            rcp('legend', fontsize=fontsize)
458        if refresh and self._data: self.plot(self._data)
459        return
460
461    def set_title(self, title=None, fontsize=None, refresh=True):
462        """
463        Set the title of the plot. If multiple panels are plotted,
464        multiple titles have to be specified.
465        Parameters:
466            refresh:    True (default) or False. If True, the plot is
467                        replotted based on the new parameter setting(s).
468                        Otherwise,the parameter(s) are set without replotting.
469        Example:
470             # two panels are visible on the plotter
471             plotter.set_title(["First Panel","Second Panel"])
472        """
473        self._title = title
474        if isinstance(fontsize, int):
475            from matplotlib import rc as rcp
476            rcp('axes', titlesize=fontsize)
477        if refresh and self._data: self.plot(self._data)
478        return
479
480    def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
481        """
482        Set the y-axis label of the plot. If multiple panels are plotted,
483        multiple labels have to be specified.
484        Parameters:
485            ordinate:    a list of ordinate labels. None (default) let
486                         data determine the labels
487            refresh:     True (default) or False. If True, the plot is
488                         replotted based on the new parameter setting(s).
489                         Otherwise,the parameter(s) are set without replotting.
490        Example:
491             # two panels are visible on the plotter
492             plotter.set_ordinate(["First Y-Axis","Second Y-Axis"])
493        """
494        self._ordinate = ordinate
495        if isinstance(fontsize, int):
496            from matplotlib import rc as rcp
497            rcp('axes', labelsize=fontsize)
498            rcp('ytick', labelsize=fontsize)
499        if refresh and self._data: self.plot(self._data)
500        return
501
502    def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
503        """
504        Set the x-axis label of the plot. If multiple panels are plotted,
505        multiple labels have to be specified.
506        Parameters:
507            abcissa:     a list of abcissa labels. None (default) let
508                         data determine the labels
509            refresh:     True (default) or False. If True, the plot is
510                         replotted based on the new parameter setting(s).
511                         Otherwise,the parameter(s) are set without replotting.
512        Example:
513             # two panels are visible on the plotter
514             plotter.set_ordinate(["First X-Axis","Second X-Axis"])
515        """
516        self._abcissa = abcissa
517        if isinstance(fontsize, int):
518            from matplotlib import rc as rcp
519            rcp('axes', labelsize=fontsize)
520            rcp('xtick', labelsize=fontsize)
521        if refresh and self._data: self.plot(self._data)
522        return
523
524    def set_colors(self, colmap, refresh=True):
525        """
526        Set the colours to be used. The plotter will cycle through
527        these colours when lines are overlaid (stacking mode).
528        Parameters:
529            colmap:     a list of colour names
530            refresh:    True (default) or False. If True, the plot is
531                        replotted based on the new parameter setting(s).
532                        Otherwise,the parameter(s) are set without replotting.
533        Example:
534             plotter.set_colors("red green blue")
535             # If for example four lines are overlaid e.g I Q U V
536             # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
537             # and 'V' will be 'red' again.
538        """
539        if isinstance(colmap,str):
540            colmap = colmap.split()
541        self._plotter.palette(0, colormap=colmap)
542        if refresh and self._data: self.plot(self._data)
543
544    # alias for english speakers
545    set_colours = set_colors
546
547    def set_histogram(self, hist=True, linewidth=None, refresh=True):
548        """
549        Enable/Disable histogram-like plotting.
550        Parameters:
551            hist:        True (default) or False. The fisrt default
552                         is taken from the .asaprc setting
553                         plotter.histogram
554            refresh:     True (default) or False. If True, the plot is
555                         replotted based on the new parameter setting(s).
556                         Otherwise,the parameter(s) are set without replotting.
557        """
558        self._hist = hist
559        if isinstance(linewidth, float) or isinstance(linewidth, int):
560            from matplotlib import rc as rcp
561            rcp('lines', linewidth=linewidth)
562        if refresh and self._data: self.plot(self._data)
563
564    def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
565        """
566        Set the linestyles to be used. The plotter will cycle through
567        these linestyles when lines are overlaid (stacking mode) AND
568        only one color has been set.
569        Parameters:
570             linestyles:     a list of linestyles to use.
571                             'line', 'dashed', 'dotted', 'dashdot',
572                             'dashdotdot' and 'dashdashdot' are
573                             possible
574            refresh:         True (default) or False. If True, the plot is
575                             replotted based on the new parameter setting(s).
576                             Otherwise,the parameter(s) are set without replotting.
577        Example:
578             plotter.set_colors("black")
579             plotter.set_linestyles("line dashed dotted dashdot")
580             # If for example four lines are overlaid e.g I Q U V
581             # 'I' will be 'solid', 'Q' will be 'dashed',
582             # U will be 'dotted' and 'V' will be 'dashdot'.
583        """
584        if isinstance(linestyles,str):
585            linestyles = linestyles.split()
586        self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
587        if isinstance(linewidth, float) or isinstance(linewidth, int):
588            from matplotlib import rc as rcp
589            rcp('lines', linewidth=linewidth)
590        if refresh and self._data: self.plot(self._data)
591
592    def set_font(self, refresh=True,**kwargs):
593        """
594        Set font properties.
595        Parameters:
596            family:    one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
597            style:     one of 'normal' (or 'roman'), 'italic'  or 'oblique'
598            weight:    one of 'normal or 'bold'
599            size:      the 'general' font size, individual elements can be adjusted
600                       seperately
601            refresh:   True (default) or False. If True, the plot is
602                       replotted based on the new parameter setting(s).
603                       Otherwise,the parameter(s) are set without replotting.
604        """
605        from matplotlib import rc as rcp
606        fdict = {}
607        for k,v in kwargs.iteritems():
608            if v:
609                fdict[k] = v
610        self._fp = FontProperties(**fdict)
611        if refresh and self._data: self.plot(self._data)
612
613    def set_panellayout(self,layout=[],refresh=True):
614        """
615        Set the layout of subplots.
616        Parameters:
617            layout:   a list of subplots layout in figure coordinate (0-1),
618                      i.e., fraction of the figure width or height.
619                      The order of elements should be:
620                      [left, bottom, right, top, horizontal space btw panels,
621                      vertical space btw panels].
622            refresh:  True (default) or False. If True, the plot is
623                      replotted based on the new parameter setting(s).
624                      Otherwise,the parameter(s) are set without replotting.
625        Note
626        * When layout is not specified, the values are reset to the defaults
627          of matplotlib.
628        * If any element is set to be None, the current value is adopted.
629        """
630        if layout == []: self._panellayout=self._reset_panellayout()
631        else:
632            self._panellayout=[None]*6
633            self._panellayout[0:len(layout)]=layout
634        #print "panel layout set to ",self._panellayout
635        if refresh and self._data: self.plot(self._data)
636
637    def _reset_panellayout(self):
638        ks=map(lambda x: 'figure.subplot.'+x,
639               ['left','bottom','right','top','hspace','wspace'])
640        return map(matplotlib.rcParams.get,ks)
641
642    def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
643                   location=None):
644        """
645        Plot a line catalog.
646        Parameters:
647            linecat:      the linecatalog to plot
648            doppler:      the velocity shift to apply to the frequencies
649            deltachan:    the number of channels to include each side of the
650                          line to determine a local maximum/minimum
651            rotate:       the rotation (in degrees) )for the text label (default 90.0)
652            location:     the location of the line annotation from the 'top',
653                          'bottom' or alternate (None - the default)
654        Notes:
655        If the spectrum is flagged no line will be drawn in that location.
656        """
657        if not self._data:
658            raise RuntimeError("No scantable has been plotted yet.")
659        from asap._asap import linecatalog
660        if not isinstance(linecat, linecatalog):
661            raise ValueError("'linecat' isn't of type linecatalog.")
662        if not self._data.get_unit().endswith("Hz"):
663            raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
664        from numpy import ma
665        for j in range(len(self._plotter.subplots)):
666            self._plotter.subplot(j)
667            lims = self._plotter.axes.get_xlim()
668            for row in range(linecat.nrow()):
669                # get_frequency returns MHz
670                base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
671                restf = linecat.get_frequency(row)/base[self._data.get_unit()]
672                c = 299792.458
673                freq = restf*(1.0-doppler/c)
674                if lims[0] < freq < lims[1]:
675                    if location is None:
676                        loc = 'bottom'
677                        if row%2: loc='top'
678                    else: loc = location
679                    maxys = []
680                    for line in self._plotter.axes.lines:
681                        v = line._x
682                        asc = v[0] < v[-1]
683
684                        idx = None
685                        if not asc:
686                            if v[len(v)-1] <= freq <= v[0]:
687                                i = len(v)-1
688                                while i>=0 and v[i] < freq:
689                                    idx = i
690                                    i-=1
691                        else:
692                           if v[0] <= freq <= v[len(v)-1]:
693                                i = 0
694                                while  i<len(v) and v[i] < freq:
695                                    idx = i
696                                    i+=1
697                        if idx is not None:
698                            lower = idx - deltachan
699                            upper = idx + deltachan
700                            if lower < 0: lower = 0
701                            if upper > len(v): upper = len(v)
702                            s = slice(lower, upper)
703                            y = line._y[s]
704                            maxy = ma.maximum(y)
705                            if isinstance( maxy, float):
706                                maxys.append(maxy)
707                    if len(maxys):
708                        peak = max(maxys)
709                        if peak > self._plotter.axes.get_ylim()[1]:
710                            loc = 'bottom'
711                    else:
712                        continue
713                    self._plotter.vline_with_label(freq, peak,
714                                                   linecat.get_name(row),
715                                                   location=loc, rotate=rotate)
716        self._plotter.show(hardrefresh=False)
717
718
719    def save(self, filename=None, orientation=None, dpi=None):
720        """
721        Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
722        Parameters:
723             filename:    The name of the output file. This is optional
724                          and autodetects the image format from the file
725                          suffix. If non filename is specified a file
726                          called 'yyyymmdd_hhmmss.png' is created in the
727                          current directory.
728             orientation: optional parameter for postscript only (not eps).
729                          'landscape', 'portrait' or None (default) are valid.
730                          If None is choosen for 'ps' output, the plot is
731                          automatically oriented to fill the page.
732             dpi:         The dpi of the output non-ps plot
733        """
734        self._plotter.save(filename,orientation,dpi)
735        return
736
737
738    def set_mask(self, mask=None, selection=None, refresh=True):
739        """
740        Set a plotting mask for a specific polarization.
741        This is useful for masking out "noise" Pangle outside a source.
742        Parameters:
743             mask:           a mask from scantable.create_mask
744             selection:      the spectra to apply the mask to.
745             refresh:        True (default) or False. If True, the plot is
746                             replotted based on the new parameter setting(s).
747                             Otherwise,the parameter(s) are set without replotting.
748        Example:
749             select = selector()
750             select.setpolstrings("Pangle")
751             plotter.set_mask(mymask, select)
752        """
753        if not self._data:
754            msg = "Can only set mask after a first call to plot()"
755            if rcParams['verbose']:
756                #print msg
757                asaplog.push( msg )
758                print_log( 'ERROR' )
759                return
760            else:
761                raise RuntimeError(msg)
762        if len(mask):
763            if isinstance(mask, list) or isinstance(mask, tuple):
764                self._usermask = array(mask)
765            else:
766                self._usermask = mask
767        if mask is None and selection is None:
768            self._usermask = []
769            self._maskselection = None
770        if isinstance(selection, selector):
771            self._maskselection = {'b': selection.get_beams(),
772                                   's': selection.get_scans(),
773                                   'i': selection.get_ifs(),
774                                   'p': selection.get_pols(),
775                                   't': [] }
776        else:
777            self._maskselection = None
778        if refresh: self.plot(self._data)
779
780    def _slice_indeces(self, data):
781        mn = self._minmaxx[0]
782        mx = self._minmaxx[1]
783        asc = data[0] < data[-1]
784        start=0
785        end = len(data)-1
786        inc = 1
787        if not asc:
788            start = len(data)-1
789            end = 0
790            inc = -1
791        # find min index
792        #while start > 0 and data[start] < mn:
793        #    start+= inc
794        minind=start
795        for ind in xrange(start,end+inc,inc):
796            if data[ind] > mn: break
797            minind=ind
798        # find max index
799        #while end > 0 and data[end] > mx:
800        #    end-=inc
801        #if end > 0: end +=1
802        maxind=end
803        for ind in xrange(end,start-inc,-inc):
804            if data[ind] < mx: break
805            maxind=ind
806        start=minind
807        end=maxind
808        if start > end:
809            return end,start+1
810        elif start < end:
811            return start,end+1
812        else:
813            return start,end
814
815    def _reset(self):
816        self._usermask = []
817        self._usermaskspectra = None
818        self.set_selection(None, False)
819
820    def _plot(self, scan):
821        savesel = scan.get_selection()
822        sel = savesel +  self._selection
823        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
824              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME' }
825        order = [d0[self._panelling],d0[self._stacking]]
826        sel.set_order(order)
827        scan.set_selection(sel)
828        d = {'b': scan.getbeam, 's': scan.getscan,
829             'i': scan.getif, 'p': scan.getpol, 't': scan._gettime }
830
831        polmodes = dict(zip(self._selection.get_pols(),
832                            self._selection.get_poltypes()))
833        # this returns either a tuple of numbers or a length  (ncycles)
834        # convert this into lengths
835        n0,nstack0 = self._get_selected_n(scan)
836        if isinstance(n0, int): n = n0
837        else: n = len(n0)
838        if isinstance(nstack0, int): nstack = nstack0
839        else: nstack = len(nstack0)
840        maxpanel, maxstack = 16,16
841        if n > maxpanel or nstack > maxstack:
842            maxn = 0
843            if nstack > maxstack: maxn = maxstack
844            if n > maxpanel: maxn = maxpanel
845            msg ="Scan to be plotted contains more than %d selections.\n" \
846                  "Selecting first %d selections..." % (maxn, maxn)
847            asaplog.push(msg)
848            print_log('WARN')
849            n = min(n,maxpanel)
850            nstack = min(nstack,maxstack)
851        if n > 1:
852            ganged = rcParams['plotter.ganged']
853            if self._panelling == 'i':
854                ganged = False
855            if self._rows and self._cols:
856                n = min(n,self._rows*self._cols)
857                self._plotter.set_panels(rows=self._rows,cols=self._cols,
858#                                         nplots=n,ganged=ganged)
859                                         nplots=n,layout=self._panellayout,ganged=ganged)
860            else:
861#                self._plotter.set_panels(rows=n,cols=0,nplots=n,ganged=ganged)
862                self._plotter.set_panels(rows=n,cols=0,nplots=n,layout=self._panellayout,ganged=ganged)
863        else:
864#            self._plotter.set_panels()
865            self._plotter.set_panels(layout=self._panellayout)
866        r=0
867        nr = scan.nrow()
868        a0,b0 = -1,-1
869        allxlim = []
870        allylim = []
871        newpanel=True
872        panelcount,stackcount = 0,0
873        while r < nr:
874            a = d[self._panelling](r)
875            b = d[self._stacking](r)
876            if a > a0 and panelcount < n:
877                if n > 1:
878                    self._plotter.subplot(panelcount)
879                self._plotter.palette(0)
880                #title
881                xlab = self._abcissa and self._abcissa[panelcount] \
882                       or scan._getabcissalabel()
883                ylab = self._ordinate and self._ordinate[panelcount] \
884                       or scan._get_ordinate_label()
885                self._plotter.set_axes('xlabel', xlab)
886                self._plotter.set_axes('ylabel', ylab)
887                lbl = self._get_label(scan, r, self._panelling, self._title)
888                if isinstance(lbl, list) or isinstance(lbl, tuple):
889                    if 0 <= panelcount < len(lbl):
890                        lbl = lbl[panelcount]
891                    else:
892                        # get default label
893                        lbl = self._get_label(scan, r, self._panelling, None)
894                self._plotter.set_axes('title',lbl)
895                newpanel = True
896                stackcount =0
897                panelcount += 1
898            if (b > b0 or newpanel) and stackcount < nstack:
899                y = []
900                if len(polmodes):
901                    y = scan._getspectrum(r, polmodes[scan.getpol(r)])
902                else:
903                    y = scan._getspectrum(r)
904                m = scan._getmask(r)
905                from numpy import logical_not, logical_and
906                if self._maskselection and len(self._usermask) == len(m):
907                    if d[self._stacking](r) in self._maskselection[self._stacking]:
908                        m = logical_and(m, self._usermask)
909                x = scan._getabcissa(r)
910                from numpy import ma, array
911                y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
912                if self._minmaxx is not None:
913                    s,e = self._slice_indeces(x)
914                    x = x[s:e]
915                    y = y[s:e]
916                if len(x) > 1024 and rcParams['plotter.decimate']:
917                    fac = len(x)/1024
918                    x = x[::fac]
919                    y = y[::fac]
920                llbl = self._get_label(scan, r, self._stacking, self._lmap)
921                if isinstance(llbl, list) or isinstance(llbl, tuple):
922                    if 0 <= stackcount < len(llbl):
923                        # use user label
924                        llbl = llbl[stackcount]
925                    else:
926                        # get default label
927                        llbl = self._get_label(scan, r, self._stacking, None)
928                self._plotter.set_line(label=llbl)
929                plotit = self._plotter.plot
930                if self._hist: plotit = self._plotter.hist
931                if len(x) > 0:
932                    plotit(x,y)
933                    xlim= self._minmaxx or [min(x),max(x)]
934                    allxlim += xlim
935                    ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
936                    allylim += ylim
937                else:
938                    xlim = self._minmaxx or []
939                    allxlim += xlim
940                    ylim= self._minmaxy or []
941                    allylim += ylim
942                stackcount += 1
943                # last in colour stack -> autoscale x
944                if stackcount == nstack and len(allxlim) > 0:
945                    allxlim.sort()
946                    self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
947                    # clear
948                    allxlim =[]
949
950            newpanel = False
951            a0=a
952            b0=b
953            # ignore following rows
954            if (panelcount == n) and (stackcount == nstack):
955                # last panel -> autoscale y if ganged
956                if rcParams['plotter.ganged'] and len(allylim) > 0:
957                    allylim.sort()
958                    self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
959                break
960            r+=1 # next row
961        #reset the selector to the scantable's original
962        scan.set_selection(savesel)
963       
964        #temporary switch-off for older matplotlib
965        #if self._fp is not None:
966        if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
967            for o in self._plotter.figure.findobj(Text):
968                o.set_fontproperties(self._fp)
969
970    def set_selection(self, selection=None, refresh=True, **kw):
971        """
972        Parameters:
973            selection:  a selector object (default unset the selection)
974            refresh:    True (default) or False. If True, the plot is
975                        replotted based on the new parameter setting(s).
976                        Otherwise,the parameter(s) are set without replotting.
977        """
978        if selection is None:
979            # reset
980            if len(kw) == 0:
981                self._selection = selector()
982            else:
983                # try keywords
984                for k in kw:
985                    if k not in selector.fields:
986                        raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
987                self._selection = selector(**kw)
988        elif isinstance(selection, selector):
989            self._selection = selection
990        else:
991            raise TypeError("'selection' is not of type selector")
992
993        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
994              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME' }
995        order = [d0[self._panelling],d0[self._stacking]]
996        self._selection.set_order(order)
997        if refresh and self._data: self.plot(self._data)
998
999    def _get_selected_n(self, scan):
1000        d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
1001             'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle }
1002        d2 = { 'b': self._selection.get_beams(),
1003               's': self._selection.get_scans(),
1004               'i': self._selection.get_ifs(),
1005               'p': self._selection.get_pols(),
1006               't': self._selection.get_cycles() }
1007        n =  d2[self._panelling] or d1[self._panelling]()
1008        nstack = d2[self._stacking] or d1[self._stacking]()
1009        return n,nstack
1010
1011    def _get_label(self, scan, row, mode, userlabel=None):
1012        if isinstance(userlabel, list) and len(userlabel) == 0:
1013            userlabel = " "
1014        pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
1015        if len(pms):
1016            poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
1017        else:
1018            poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
1019        d = {'b': "Beam "+str(scan.getbeam(row)),
1020             #'s': scan._getsourcename(row),
1021             's': "Scan "+str(scan.getscan(row))+\
1022                  " ("+str(scan._getsourcename(row))+")",
1023             'i': "IF"+str(scan.getif(row)),
1024             'p': poleval,
1025             't': str(scan.get_time(row)) }
1026        return userlabel or d[mode]
1027
1028    def plotazel(self, scan=None, outfile=None):
1029    #def plotazel(self):
1030        """
1031        plot azimuth and elevation versus time of a scantable
1032        """
1033        from matplotlib import pylab as PL
1034        from matplotlib.dates import DateFormatter, timezone
1035        from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
1036        from matplotlib.ticker import MultipleLocator
1037        from numpy import array, pi
1038        self._data = scan
1039        self._outfile = outfile
1040        dates = self._data.get_time(asdatetime=True)
1041        t = PL.date2num(dates)
1042        tz = timezone('UTC')
1043        PL.cla()
1044        PL.ioff()
1045        PL.clf()
1046        # Adjust subplot layouts
1047        if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1048        lef, bot, rig, top, wsp, hsp = self._panellayout
1049        PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1050                                 wspace=wsp,hspace=hsp)
1051       
1052        tdel = max(t) - min(t)
1053        ax = PL.subplot(2,1,1)
1054        el = array(self._data.get_elevation())*180./pi
1055        PL.ylabel('El [deg.]')
1056        dstr = dates[0].strftime('%Y/%m/%d')
1057        if tdel > 1.0:
1058            dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
1059            dstr = dstr + " - " + dstr2
1060            majloc = DayLocator()
1061            minloc = HourLocator(range(0,23,12))
1062            timefmt = DateFormatter("%b%d")
1063        elif tdel > 24./60.:
1064            timefmt = DateFormatter('%H:%M')
1065            majloc = HourLocator()
1066            minloc = MinuteLocator(30)
1067        else:
1068            timefmt = DateFormatter('%H:%M')
1069            majloc = MinuteLocator(interval=5)
1070            minloc = SecondLocator(30)
1071
1072        PL.title(dstr)
1073        if tdel == 0.0:
1074            th = (t - PL.floor(t))*24.0
1075            PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
1076        else:
1077            PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
1078            #ax.grid(True)
1079            ax.xaxis.set_major_formatter(timefmt)
1080            ax.xaxis.set_major_locator(majloc)
1081            ax.xaxis.set_minor_locator(minloc)
1082        ax.yaxis.grid(True)
1083        yloc = MultipleLocator(30)
1084        ax.set_ylim(0,90)
1085        ax.yaxis.set_major_locator(yloc)
1086        if tdel > 1.0:
1087            labels = ax.get_xticklabels()
1088        #    PL.setp(labels, fontsize=10, rotation=45)
1089            PL.setp(labels, fontsize=10)
1090
1091        # Az plot
1092        az = array(self._data.get_azimuth())*180./pi
1093        if min(az) < 0:
1094            for irow in range(len(az)):
1095                if az[irow] < 0: az[irow] += 360.0
1096
1097        ax2 = PL.subplot(2,1,2)
1098        #PL.xlabel('Time (UT [hour])')
1099        PL.ylabel('Az [deg.]')
1100        if tdel == 0.0:
1101            PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
1102        else:
1103            PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
1104            ax2.xaxis.set_major_formatter(timefmt)
1105            ax2.xaxis.set_major_locator(majloc)
1106            ax2.xaxis.set_minor_locator(minloc)
1107        #ax2.grid(True)
1108        ax2.set_ylim(0,360)
1109        ax2.yaxis.grid(True)
1110        #hfmt = DateFormatter('%H')
1111        #hloc = HourLocator()
1112        yloc = MultipleLocator(60)
1113        ax2.yaxis.set_major_locator(yloc)
1114        if tdel > 1.0:
1115            labels = ax2.get_xticklabels()
1116            PL.setp(labels, fontsize=10)
1117            PL.xlabel('Time (UT [day])')
1118        else:
1119            PL.xlabel('Time (UT [hour])')
1120
1121        PL.ion()
1122        PL.draw()
1123        if (self._outfile is not None):
1124           PL.savefig(self._outfile)
1125
1126    def plotpointing(self, scan=None, outfile=None):
1127    #def plotpointing(self):
1128        """
1129        plot telescope pointings
1130        """
1131        from matplotlib import pylab as PL
1132        from numpy import array, pi
1133        self._data = scan
1134        self._outfile = outfile
1135        dir = array(self._data.get_directionval()).transpose()
1136        ra = dir[0]*180./pi
1137        dec = dir[1]*180./pi
1138        PL.cla()
1139        #PL.ioff()
1140        PL.clf()
1141        # Adjust subplot layouts
1142        if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1143        lef, bot, rig, top, wsp, hsp = self._panellayout
1144        PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1145                                 wspace=wsp,hspace=hsp)
1146        ax = PL.gca()
1147        #ax = PL.axes([0.1,0.1,0.8,0.8])
1148        #ax = PL.axes([0.1,0.1,0.8,0.8])
1149        ax.set_aspect('equal')
1150        PL.plot(ra, dec, 'b,')
1151        PL.xlabel('RA [deg.]')
1152        PL.ylabel('Declination [deg.]')
1153        PL.title('Telescope pointings')
1154        [xmin,xmax,ymin,ymax] = PL.axis()
1155        PL.axis([xmax,xmin,ymin,ymax])
1156        #PL.ion()
1157        PL.draw()
1158        if (self._outfile is not None):
1159           PL.savefig(self._outfile)
1160
1161    # plot total power data
1162    # plotting in time is not yet implemented..
1163    def plottp(self, scan=None, outfile=None):
1164        if self._plotter.is_dead:
1165            if hasattr(self._plotter.figmgr,'casabar'):
1166                del self._plotter.figmgr.casabar
1167            self._plotter = self._newplotter()
1168            self._plotter.figmgr.casabar=self._newcasabar()
1169        self._plotter.hold()
1170        self._plotter.clear()
1171        from asap import scantable
1172        if not self._data and not scan:
1173            msg = "Input is not a scantable"
1174            if rcParams['verbose']:
1175                #print msg
1176                asaplog.push( msg )
1177                print_log( 'ERROR' )
1178                return
1179            raise TypeError(msg)
1180        if isinstance(scan, scantable):
1181            if self._data is not None:
1182                if scan != self._data:
1183                    self._data = scan
1184                    # reset
1185                    self._reset()
1186            else:
1187                self._data = scan
1188                self._reset()
1189        # ranges become invalid when abcissa changes?
1190        #if self._abcunit and self._abcunit != self._data.get_unit():
1191        #    self._minmaxx = None
1192        #    self._minmaxy = None
1193        #    self._abcunit = self._data.get_unit()
1194        #    self._datamask = None
1195
1196        # Adjust subplot layouts
1197        if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1198        lef, bot, rig, top, wsp, hsp = self._panellayout
1199        self._plotter.figure.subplots_adjust(
1200            left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
1201        if self._plotter.figmgr.casabar: self._plotter.figmgr.casabar.disable_button()
1202        self._plottp(self._data)
1203        if self._minmaxy is not None:
1204            self._plotter.set_limits(ylim=self._minmaxy)
1205        self._plotter.release()
1206        self._plotter.tidy()
1207        self._plotter.show(hardrefresh=False)
1208        print_log()
1209        return
1210
1211    def _plottp(self,scan):
1212        """
1213        private method for plotting total power data
1214        """
1215        from numpy import ma, array, arange, logical_not
1216        r=0
1217        nr = scan.nrow()
1218        a0,b0 = -1,-1
1219        allxlim = []
1220        allylim = []
1221        y=[]
1222        self._plotter.set_panels()
1223        self._plotter.palette(0)
1224        #title
1225        #xlab = self._abcissa and self._abcissa[panelcount] \
1226        #       or scan._getabcissalabel()
1227        #ylab = self._ordinate and self._ordinate[panelcount] \
1228        #       or scan._get_ordinate_label()
1229        xlab = self._abcissa or 'row number' #or Time
1230        ylab = self._ordinate or scan._get_ordinate_label()
1231        self._plotter.set_axes('xlabel',xlab)
1232        self._plotter.set_axes('ylabel',ylab)
1233        lbl = self._get_label(scan, r, 's', self._title)
1234        if isinstance(lbl, list) or isinstance(lbl, tuple):
1235        #    if 0 <= panelcount < len(lbl):
1236        #        lbl = lbl[panelcount]
1237        #    else:
1238                # get default label
1239             lbl = self._get_label(scan, r, self._panelling, None)
1240        self._plotter.set_axes('title',lbl)
1241        y=array(scan._get_column(scan._getspectrum,-1))
1242        m = array(scan._get_column(scan._getmask,-1))
1243        y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1244        x = arange(len(y))
1245        # try to handle spectral data somewhat...
1246        l,m = y.shape
1247        if m > 1:
1248            y=y.mean(axis=1)
1249        plotit = self._plotter.plot
1250        llbl = self._get_label(scan, r, self._stacking, None)
1251        self._plotter.set_line(label=llbl)
1252        if len(x) > 0:
1253            plotit(x,y)
1254
1255
1256    # forwards to matplotlib.Figure.text
1257    def figtext(self, *args, **kwargs):
1258        """
1259        Add text to figure at location x,y (relative 0-1 coords).
1260        This method forwards *args and **kwargs to a Matplotlib method,
1261        matplotlib.Figure.text.
1262        See the method help for detailed information.
1263        """
1264        self._plotter.text(*args, **kwargs)
1265    # end matplotlib.Figure.text forwarding function
1266
1267
1268    # printing header information
1269    def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
1270        """
1271        print data (scantable) header on the plot and/or logger.
1272        Parameters:
1273            plot:      whether or not print header info on the plot.
1274            fontsize:  header font size (valid only plot=True)
1275            autoscale: whether or not autoscale the plot (valid only plot=True)
1276            logger:    whether or not print header info on the logger.
1277            selstr:    additional selection string (not verified)
1278            extrastr:  additional string to print (not verified)
1279        """
1280        if not plot and not logger: return
1281        if not self._data: raise RuntimeError("No scantable has been set yet.")
1282        # Now header will be printed on plot and/or logger.
1283        # Get header information and format it.
1284        ssum=self._data.__str__()
1285        # Print Observation header to the upper-left corner of plot
1286        if plot:
1287            headstr=[ssum[ssum.find('Observer:'):ssum.find('Flux Unit:')]]
1288            headstr.append(ssum[ssum.find('Beams:'):ssum.find('Observer:')]
1289                         +ssum[ssum.find('Rest Freqs:'):ssum.find('Abcissa:')])
1290            if extrastr != '': headstr[0]=extrastr+'\n'+headstr[0]
1291            #headstr[1]='Data File:     '+(filestr or 'unknown')+'\n'+headstr[1]
1292            ssel='***Selections***\n'+(selstr+self._data.get_selection().__str__() or 'none')
1293            headstr.append(ssel)
1294            nstcol=len(headstr)
1295           
1296            self._plotter.hold()
1297            for i in range(nstcol):
1298                self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
1299                             headstr[i],
1300                             horizontalalignment='left',
1301                             verticalalignment='top',
1302                             fontsize=fontsize)
1303            import time
1304            self._plotter.figure.text(0.99,0.0,
1305                            time.strftime("%a %d %b %Y  %H:%M:%S %Z"),
1306                            horizontalalignment='right',
1307                            verticalalignment='bottom',fontsize=8)
1308            self._plotter.release()
1309            del headstr, ssel
1310        if logger:
1311            asaplog.push("----------------\n  Plot Summary\n----------------")
1312            asaplog.push(extrastr)
1313            asaplog.push(ssum[ssum.find('Beams:'):])
1314            print_log()
1315        del ssum
1316
1317
Note: See TracBrowser for help on using the repository browser.