1import sys
2#import math
3#import ctypes
4import atexit
5import os
6import tempfile
7import time
8import subprocess
9import getpass
10from ast import literal_eval
11
12import numpy as np
13
14try:
15    from PySide import QtNetwork, QtGui
16except ImportError as err1:
17    try:
18        from PyQt4 import QtNetwork, QtGui
19    except ImportError as err2:
20        raise ImportError("{} and {}. One of the two is required.".format(err1, err2))
21
22QtGui.QApplication([""])
23
24
25def clean_tmp_file(tmp_file):
26    os.remove(tmp_file.name)
27
28def b2str(val):
29    if isinstance(val, bool):
30        return "True" if val else "False"
31    return str(val)
32
33
34class Client(object):
35    """ An interface to a running kst session.
36
37    A client provides a connection to a running kst session.
38
39    The constructor creates a connection to either a running
40    kst session with name <server_name>, or if none exists, a new one.
41
42    If <server_name> is not specified (the default), it creates a connection with an
43    unnamed kst session, or if none exists, a new unnamed session.
44
45    The Client provides functions which effect the entire kst session,
46    provides convenience functions to create objects within kst (eg,
47    ``client.new_generated_vector(0, 1, 6)``), and provides
48    convenience functions to access objects already within kst (eg,
49    ``client.vector("V2")``.  This is the suggested method.
50
51    Alternatively, the constructor for every class inside pykst accepts
52    an instance of Client which it uses to interact with a kst session.
53
54    To connect to a kst session named ``kstSession`` (starting kst if necessary)::
55
56        import pykst as kst
57        client = kst.Client("kstSession")
58
59    """
60
61    def __init__(self, server_name=""):
62
63        user_name = getpass.getuser()
64
65        if server_name:
66            self.server_name = server_name + "--" + user_name
67        else:
68            self.server_name = user_name
69
70        self.local_socket = QtNetwork.QLocalSocket()
71        self.local_socket.connectToServer(self.server_name)
72        self.local_socket.waitForConnected(300)
73
74        if self.local_socket.state() == QtNetwork.QLocalSocket.UnconnectedState:
75            subprocess.Popen(["kst2", "--serverName="+str(self.server_name)])
76            time.sleep(.5)
77
78            while self.local_socket.state() == QtNetwork.QLocalSocket.UnconnectedState:
79                self.local_socket.connectToServer(self.server_name)
80                self.local_socket.waitForConnected(300)
81
82    def send(self, command):
83        """ Sends a command to kst and returns a response.
84
85        You should never use
86        this directly, as there is no guarantee that the internal command
87        list kst uses won't change. Instead use the convenience classes
88        included with pykst.
89        """
90        self.local_socket.write(command)
91        self.local_socket.flush()
92        self.local_socket.waitForReadyRead(300000)
93        return_message = self.local_socket.readAll()
94        return return_message
95
96    def send_si(self, handle, command):
97        self.send(b2str("beginEdit("+handle+")"))
98        return_message = self.send(command)
99        self.send(b2str("endEdit()"))
100        return return_message
101
102    def test_command(self):
103        self.send("testCommand()")
104
105    def clear(self):
106        """ Clears all objects from kst.
107
108        Equivalent to file->close from the menubar inside kst.
109        """
110        self.send("clear()")
111
112    def open_kst_file(self, filename):
113        """ open a .kst file in kst. """
114        self.send("fileOpen("+b2str(filename)+")")
115
116    def save_kst_file(self, filename):
117        """ save a .kst file in kst. """
118        self.send("fileSave("+b2str(filename)+")")
119
120    def export_graphics_file(self, filename, graphics_format=None, width=1280, height=1024,
121                             display=2, all_tabs=False, autosave_period=0):
122        """
123        export the kst session as a set of graphics files.
124
125        :param filename: the name of the file to be saved
126        :param graphics_format: the format to be used.  if None, the format is determined from
127                                the filename extension.
128        :param width: width of the plot, in pixels, if required by the display setting.
129        :param height: the height of the plot, in pixels, if required by the display setting.
130        :param display: how the dimensions are interpreted.
131        :param all_tabs: if True, all tabs are exported as <filename>_<tabname>.<ext>
132        :param autosave_period: save the image every <autosave_period> seconds.
133                                If 0, only save once.
134
135        *display* determines the shape of the plot.  Values are ::
136
137            0   Width set by user, maintain aspect ratio
138            1   Height set by user, maintain aspect ratio
139            2   Width and Height set by user.
140            3   a Width x Width square plot.
141
142        """
143
144        if graphics_format is None:
145            graphics_format = os.path.splitext(filename)[1][1:].strip().lower()
146
147        self.send("exportGraphics("+str(filename)+","+str(graphics_format)+","+str(width)+","+
148                  str(height)+","+str(display)+","+str(all_tabs)+","+str(autosave_period) + ")")
149
150
151    def screen_back(self):
152        """ Equivalent to "Range>Back One Screen" from the menubar inside kst. """
153        self.send("screenBack()")
154
155    def screen_forward(self):
156        """ Equivalent to "Range>Forward One Screen" from the menubar inside kst. """
157        self.send("screenForward()")
158
159    def count_from_end(self):
160        """ Equivalent to "Range>Count From End" from the menubar inside kst. """
161        self.send("countFromEnd()")
162
163    def read_to_end(self):
164        """ Equivalent to "Range>Read To End" from the menubar inside kst. """
165        self.send("readToEnd()")
166
167    def set_paused(self):
168        """ Equivalent to checking "Range>Pause" from the menubar inside kst."""
169        self.send("setPaused()")
170
171    def unset_paused(self):
172        """ Equivalent to unchecking "Range>Pause" from the menubar inside kst."""
173        self.send("unsetPaused()")
174
175    def hide_window(self):
176        """
177        Hide the kst window.
178
179        pyKst operations which effect the display are far faster when the window is hidden.
180
181        Restore with show_window() or maximize_window()."""
182
183        self.send("hide()")
184
185    def quit(self):
186        """
187        Tell the kst window to terminate
188
189        After this, client will no longer be valid."""
190
191        self.send("quit()")
192
193    def minimize_window(self):
194        """ Minimize the kst window. """
195        self.send("minimize()")
196
197    def maximize_window(self):
198        """ Maximize the kst window. """
199        self.send("maximize()")
200
201    def show_window(self):
202        """ unminimize and show the kst window. """
203        self.send("show()")
204
205    def tab_count(self):
206        """ Get the number of tabs open in the current document. """
207        return self.send("tabCount()")
208
209    def new_tab(self):
210        """ Create a new tab in the current document and switch to it. """
211        return self.send("newTab()")
212
213    def set_tab(self, tab):
214        """ Set the index of the current tab.
215
216        tab must be greater or equal to 0 and less than tabCount().
217        """
218        self.send("setTab("+b2str(tab)+")")
219
220    def set_tab_text(self, new_name):
221        """ Set the text of the current tab.
222
223        """
224        self.send("renameTab("+new_name+")")
225
226    def cleanup_layout(self, columns="Auto"):
227        """ Cleanup layout in the current tab.
228
229         If columns is not set, use auto-layout.
230
231        """
232        self.send("cleanupLayout("+b2str(columns)+")")
233
234    def get_scalar_list(self):
235        """ returns the scalar names from kst """
236
237        return_message = self.send("getScalarList()")
238        name_list = return_message.data().split('|')
239        return [Scalar(self, name=n) for n in name_list]
240
241    def new_generated_string(self, string, name=""):
242        """ Create a new generated string in kst.
243
244        See :class:`GeneratedString`
245        """
246        return GeneratedString(self, string, name)
247
248    def generated_string(self, name):
249        """ Returns a generated string from kst given its name.
250
251        See :class:`GeneratedString`
252        """
253        return GeneratedString(self, "", name, new=False)
254
255    def new_datasource_string(self, filename, field, name=""):
256        """ Create a New Data Source String in kst.
257
258        See :class:`DataSourceString`
259        """
260        return DataSourceString(self, filename, field, name)
261
262    def datasource_string(self, name):
263        """ Returns a datasource string from kst given its name.
264
265        See :class:`DataSourceString`
266        """
267        return DataSourceString(self, "", "", name, new=False)
268
269    def new_generated_scalar(self, value, name=""):
270        """ Create a New Generated Scalar in kst.
271
272        See :class:`GeneratedScalar`
273        """
274        return GeneratedScalar(self, value, name)
275
276    def generated_scalar(self, name):
277        """ Returns a Generated Scalar from kst given its name.
278
279        See :class:`GeneratedScalar`
280        """
281        return GeneratedScalar(self, "", name, new=False)
282
283    def new_datasource_scalar(self, filename, field, name=""):
284        """ Create a New DataSource Scalar in kst.
285
286        See :class:`DataSourceScalar`
287        """
288        return DataSourceScalar(self, filename, field, name)
289
290    def datasource_scalar(self, name):
291        """ Returns a DataSource Scalar from kst given its name.
292
293        See :class:`DataSourceScalar`
294        """
295        return DataSourceScalar(self, "", "", name, new=False)
296
297    def new_vector_scalar(self, filename, field, frame=-1, name=""):
298        """ Create a New VectorScalar in kst.
299
300        See :class:`VectorScalar`
301        """
302        return VectorScalar(self, filename, field, frame, name)
303
304    def vector_scalar(self, name):
305        """ Returns a VectorScalar from kst given its name.
306
307        See :class:`VectorScalar`
308        """
309        return VectorScalar(self, "", "", 0, name, new=False)
310
311    def new_data_vector(self, filename, field, start=0, num_frames=-1,
312                        skip=0, boxcarFirst=False, name=""):
313        """ Create a New DataVector in kst.
314
315        See :class:`DataVector`
316        """
317        return DataVector(self, filename, field, start, num_frames,
318                          skip, boxcarFirst, name)
319
320    def data_vector(self, name):
321        """ Returns a DataVector from kst given its name.
322
323        See :class:`DataVector`
324        """
325        return DataVector(self, "", "", name=name, new=False)
326
327    def new_generated_vector(self, x0, x1, n, name=""):
328        """ Create a New GeneratedVector in kst.
329
330        See :class:`GeneratedVector`
331        """
332        return GeneratedVector(self, x0, x1, n, name)
333
334    def generated_vector(self, name):
335        """ Returns a GeneratedVector from kst given its name.
336
337        See :class:`GeneratedVector`
338        """
339        return GeneratedVector(self, 0, 0, 0, name, new=False)
340
341    def new_editable_vector(self, np_array=None, name=""):
342        """ Create a New Editable Vector in kst.
343
344        See :class:`EditableVector`
345        """
346        return EditableVector(self, np_array, name)
347
348    def editable_vector(self, name):
349        """ Returns an Editable Vector from kst given its name.
350
351        See :class:`EditableVector`
352        """
353        return EditableVector(self, None, name, new=False)
354
355
356    def get_vector_list(self):
357        """ returns vectors from kst. """
358
359        return_message = self.send("getVectorList()")
360        name_list = return_message.data().split('|')
361        return [VectorBase(self, name=n) for n in name_list]
362
363    def get_data_vector_list(self):
364        """ returns data vectors from kst. """
365
366        return_message = self.send("getDataVectorList()")
367        name_list = return_message.data().split('|')
368        return [DataVector(self, "", "", name=n, new=False) for n in name_list]
369
370    def get_generated_vector_list(self):
371        """ returns generated vectors from kst. """
372
373        return_message = self.send("getGeneratedVectorList()")
374        name_list = return_message.data().split('|')
375        return [GeneratedVector(self, name=n, new=False) for n in name_list]
376
377    def get_editable_vector_list(self):
378        """ returns editable vectors from kst. """
379
380        return_message = self.send("getEditableVectorList()")
381        name_list = return_message.data().split('|')
382        return [EditableVector(self, name=n, new=False) for n in name_list]
383
384
385    def new_data_matrix(self, filename, field, start_x=0, start_y=0, num_x=-1, num_y=-1,
386                        min_x=0, min_y=0, dx=1, dy=1, name=""):
387        """ Create a New DataMatrix in kst.
388
389        See :class:`DataMatrix`
390        """
391        return DataMatrix(self, filename, field, start_x, start_y, num_x, num_y,
392                          min_x, min_y, dx, dy, name)
393
394    def data_matrix(self, name):
395        """ Returns a DataMatrix from kst given its name.
396
397        See :class:`DataMatrix`
398        """
399        return DataMatrix(self, "", "", name=name, new=False)
400
401    def new_editable_matrix(self, np_array=None, name=""):
402        """ Create a New Editable Matrix in kst.
403
404        See :class:`EditableMatrix`
405        """
406        return EditableMatrix(self, np_array, name)
407
408    def editable_matrix(self, name):
409        """ Returns an Editable Matrix from kst given its name.
410
411        See :class:`EditableMatrix`
412        """
413        return EditableMatrix(self, None, name, new=False)
414
415    def get_matrix_list(self):
416        """ returns matrixes from kst. """
417
418        return_message = self.send("getMatrixList()")
419        name_list = return_message.data().split('|')
420        return [Matrix(self, name=n) for n in name_list]
421
422
423    def new_curve(self, x_vector, y_vector, name=""):
424        """ Create a New Curve in kst.
425
426        See :class:`Curve`
427        """
428        return Curve(self, x_vector, y_vector, name)
429
430    def curve(self, name):
431        """ Returns a Curve from kst given its name.
432
433        See :class:`Curve`
434        """
435        return Curve(self, "", "", name, new=False)
436
437    def new_image(self, matrix, name=""):
438        """ Create a new Image in kst.
439
440        See :class:`Image`
441        """
442        return Image(self, matrix, name)
443
444    def image(self, name):
445        """ Returns an Image from kst given its name.
446
447        See :class:`Image`
448        """
449        return Image(self, "", "", name, new=False)
450
451    def new_equation(self, x_vector, equation, interpolate=True, name=""):
452        """ Create a new Equation in kst.
453
454        See :class:`Equation`
455        """
456        return Equation(self, x_vector, equation, interpolate, name)
457
458
459    def equation(self, name):
460        """ Returns an Equation from kst given its name.
461
462        See :class:`Equation`
463        """
464        return Equation(self, "", "", name, new=False)
465
466    def new_histogram(self, vector, bin_min=0, bin_max=1, num_bins=60,
467                      normalization=0, auto_bin=True, name=""):
468        """ Create a new histogram in kst.
469
470        See :class:`Histogram`
471        """
472        return Histogram(self, vector, bin_min, bin_max, num_bins,
473                         normalization, auto_bin, name)
474
475
476    def histogram(self, name):
477        """ Returns a histogram from kst given its name.
478
479        See :class:`Histogram`
480        """
481        return Histogram(self, "", 0, 0, 0, name=name, new=False)
482
483    def new_cross_spectrum(self,
484                           V1, V2,
485                           fft_size=10,
486                           sample_rate=1.0,
487                           name=""):
488        """ Create a cross spectrum object in kst.
489
490        See :class:`CrossSpectrum`
491        """
492        return CrossSpectrum(self, V1, V2, fft_size, sample_rate, name)
493
494
495    def new_spectrum(self,
496                     vector,
497                     sample_rate=1.0,
498                     interleaved_average=False,
499                     fft_length=10,
500                     apodize=True,
501                     remove_mean=True,
502                     vector_units="",
503                     rate_units="Hz",
504                     apodize_function=0,
505                     sigma=1.0,
506                     output_type=0,
507                     name=""):
508        """ Create a new Spectrum in kst.
509
510        See :class:`Spectrum`
511        """
512        return Spectrum(self,
513                        vector,
514                        sample_rate,
515                        interleaved_average,
516                        fft_length,
517                        apodize,
518                        remove_mean,
519                        vector_units,
520                        rate_units,
521                        apodize_function,
522                        sigma,
523                        output_type,
524                        name)
525
526    def spectrum(self, name):
527        """ Returns a spectrum from kst given its name.
528
529        See :class:`Spectrum`
530        """
531        return Spectrum(self, "", name=name, new=False)
532
533    def new_linear_fit(self, x_vector, y_vector, weightvector=0, name=""):
534        """ Create a New Linear Fit in kst.
535
536        See :class:`LinearFit`
537        """
538        return LinearFit(self, x_vector, y_vector, weightvector, name)
539
540    def linear_fit(self, name):
541        """ Returns a linear fit from kst given its name.
542
543        See :class:`LinearFit`
544        """
545        return LinearFit(self, "", "", 0, name, new=False)
546
547
548    def new_polynomial_fit(self, order, x_vector, y_vector, weightvector=0, name=""):
549        """ Create a New Polynomial Fit in kst.
550
551        See :class:`PolynomialFit`
552        """
553        return PolynomialFit(self, order, x_vector, y_vector, weightvector, name)
554
555    def polynomial_fit(self, name):
556        """ Returns a polynomial fit from kst given its name.
557
558        See :class:`PolynomialFit`
559        """
560        return PolynomialFit(self, 0, "", "", 0, name, new=False)
561
562
563    def new_sum_filter(self, y_vector, step_dX, name=""):
564        """ Create a cumulative sum filter inside kst.
565
566        See :class:`SumFilter`
567        """
568        return SumFilter(self, y_vector, step_dX, name)
569
570
571    def new_flag_filter(self, y_vector, flag, mask="0xffffff", valid_is_zero=True, name=""):
572        """ Create a flag filter inside kst.
573
574        See :class:`FlagFilter`
575        """
576        return FlagFilter(self, y_vector, flag, mask, valid_is_zero, name)
577
578    def flag_filter(self, name):
579        """ Returns a flag_filter from kst given its name.
580
581        See :class:`FlagFilter`
582        """
583        return FlagFilter(self, "", "", name, new=False)
584
585
586    def new_label(self, text, pos=(0.5, 0.5), rot=0, font_size=12,
587                  bold=False, italic=False, font_color="black",
588                  font_family="Serif", name=""):
589        """ Create a New Label in kst.
590
591        See :class:`Label`
592        """
593        return Label(self, text, pos, rot, font_size, bold, italic,
594                     font_color, font_family, name)
595
596    def label(self, name):
597        """ Returns a Label from kst given its name.
598
599        See :class:`Label`
600        """
601        return Label(self, "", name=name, new=False)
602
603    def get_label_list(self):
604        """ Get a list of all labels in kst.
605
606        See :class:`Label`
607        """
608        return_message = self.send("getLabelList()")
609        name_list = return_message.data()[1:-1].split("][")
610        return [Label(self, "", name=n, new=False) for n in name_list]
611
612
613    def new_box(self, pos=(0.1, 0.1), size=(0.1, 0.1), rot=0,
614                fill_color="white", fill_style=1, stroke_style=1, stroke_width=1,
615                stroke_brush_color="black", stroke_brush_style=1,
616                stroke_join_style=1, stroke_cap_style=1, fix_aspect=False, name=""):
617        """ Create a New Box in kst.
618
619        See :class:`Box`
620        """
621        return Box(self, pos, size, rot, fill_color, fill_style, stroke_style,
622                   stroke_width, stroke_brush_color, stroke_brush_style,
623                   stroke_join_style, stroke_cap_style, fix_aspect, name)
624
625    def box(self, name):
626        """ Returns a Box from kst given its name.
627
628        See :class:`Box`
629        """
630        return Box(self, name=name, new=False)
631
632    def get_box_list(self):
633        """ Get a list of all boxes in kst.
634
635        See :class:`Box`
636        """
637        return_message = self.send("getBoxList()")
638        name_list = return_message.data()[1:-1].split("][")
639        return [Box(self, name=n, new=False) for n in name_list]
640
641
642    def new_legend(self, plot, name=""):
643        """ Create a new Legend in a plot in kst.
644
645        See :class:'Legend'
646        """
647        return Legend(self, plot, name)
648
649    def legend(self, name):
650        """ Returns a Legend from kst given its name.
651
652        See :class:`Legend`
653        """
654        return Legend(self, 0, name=name, new=False)
655
656    def get_legend_list(self):
657        """ Get a list of all legends in kst.
658
659        See :class:`Legend`
660        """
661        return_message = self.send("getLegendList()")
662        name_list = return_message.data()[1:-1].split("][")
663        return [Legend(self, 0, name=n, new=False) for n in name_list]
664
665
666    def new_circle(self, pos=(0.1, 0.1), diameter=0.1,
667                   fill_color="white", fill_style=1, stroke_style=1,
668                   stroke_width=1, stroke_brush_color="grey", stroke_brush_style=1, name=""):
669        """ Create a New Circle in kst.
670
671        See :class:`Circle`
672        """
673        return Circle(self, pos, diameter, fill_color, fill_style, stroke_style,
674                      stroke_width, stroke_brush_color, stroke_brush_style, name)
675
676    def circle(self, name):
677        """ Returns a Circle from kst given its name.
678
679        See :class:`Circle`
680        """
681        return Circle(self, name=name, new=False)
682
683    def get_circle_list(self):
684        """ Get a list of all ciircles in kst.
685
686        See :class:`Circle`
687        """
688        return_message = self.send("getCircleList()")
689        name_list = return_message.data()[1:-1].split("][")
690        return [Circle(self, name=n, new=False) for n in name_list]
691
692    def new_ellipse(self, pos=(0.1, 0.1), size=(0.1, 0.1),
693                    rot=0, fill_color="white", fill_style=1, stroke_style=1,
694                    stroke_width=1, stroke_brush_color="black", stroke_brush_style=1,
695                    fix_aspect=False, name=""):
696        """ Create a New Ellipse in kst.
697
698        See :class:`Ellipse`
699        """
700        return Ellipse(self, pos, size, rot, fill_color, fill_style, stroke_style,
701                       stroke_width, stroke_brush_color, stroke_brush_style,
702                       fix_aspect, name)
703
704    def ellipse(self, name):
705        """ Returns an ellipse from kst given its name.
706
707        See :class:`Ellipse`
708        """
709        return Ellipse(self, name=name, new=False)
710
711    def get_ellipse_list(self):
712        """ Get a list of all ellipse in kst.
713
714        See :class:`Ellipse`
715        """
716        return_message = self.send("getEllipseList()")
717        name_list = return_message.data()[1:-1].split("][")
718        return [Ellipse(self, name=n, new=False) for n in name_list]
719
720    def new_line(self, start=(0, 0), end=(1, 1),
721                 stroke_style=1, stroke_width=1, stroke_brush_color="black",
722                 stroke_brush_style=1, stroke_cap_style=1, name=""):
723        """ Create a New Line in kst.
724
725        See :class:`Line`
726        """
727        return Line(self, start, end, stroke_style, stroke_width,
728                    stroke_brush_color, stroke_brush_style, stroke_cap_style, name)
729
730    def line(self, name):
731        """ Returns a Line from kst given its name.
732
733        See :class:`Line`
734        """
735        return Line(self, name=name, new=False)
736
737    def get_line_list(self):
738        """ Get a list of all lines in kst.
739
740        See :class:`Line`
741        """
742        return_message = self.send("getLineList()")
743        name_list = return_message.data()[1:-1].split("][")
744        return [Line(self, name=n, new=False) for n in name_list]
745
746
747    def new_arrow(self, start=(0, 0), end=(1, 1),
748                  arror_at_start=False, arrow_at_end=True, arrow_size=12.0,
749                  stroke_style=1, stroke_width=1, stroke_brush_color="black",
750                  stroke_brush_style=1, stroke_cap_style=1, name=""):
751        """ Create a New Arrow in kst.
752
753        See :class:`Arrow`
754        """
755        return Arrow(self, start, end, arror_at_start, arrow_at_end, arrow_size,
756                     stroke_style, stroke_width, stroke_brush_color, stroke_brush_style,
757                     stroke_cap_style, name)
758
759    def arrow(self, name):
760        """ Returns an Arrow from kst given its name.
761
762        See :class:`Arrow`
763        """
764        return Arrow(self, name=name, new=False)
765
766    def get_arrow_list(self):
767        """ Get a list of all arrows in kst.
768
769        See :class:`Arrow`
770        """
771        return_message = self.send("getArrowList()")
772        name_list = return_message.data()[1:-1].split("][")
773        return [Arrow(self, name=n, new=False) for n in name_list]
774
775    def new_picture(self, filename, pos=(0.1, 0.1), width=0.1, rot=0, name=""):
776        """ Create a New Picture in kst.
777
778        See :class:`Picture`
779        """
780        return Picture(self, filename, pos, width, rot, name)
781
782    def picture(self, name):
783        """ Returns a Picture from kst given its name.
784
785        See :class:`Picture`
786        """
787        return Picture(self, "", name=name, new=False)
788
789    def get_picture_list(self):
790        """ Get a list of all pictures in kst.
791
792        See :class:`Picture`
793        """
794        return_message = self.send("getPictureList()")
795        name_list = return_message.data()[1:-1].split("][")
796        return [Picture(self, "", name=n, new=False) for n in name_list]
797
798    def new_SVG(self, filename, pos=(0.1, 0.1), width=0.1, rot=0, name=""):
799        """ Create a New SVG in kst.
800
801        See :class:`SVG`
802        """
803        return SVG(self, filename, pos, width, rot, name)
804
805    def SVG(self, name):
806        """ Returns a SVG from kst given its name.
807
808        See :class:`SVG`
809        """
810        return SVG(self, "", name=name, new=False)
811
812    def get_SVG_list(self):
813        """ Get a list of all SVGs in kst.
814
815        See :class:`SVG`
816        """
817        return_message = self.send("getSVGList()")
818        name_list = return_message.data()[1:-1].split("][")
819        return [SVG(self, "", name=n, new=False) for n in name_list]
820
821    def new_plot(self, pos=(0.1, 0.1), size=(0, 0), rot=0, font_size=0, columns=0,
822                 fill_color="white", fill_style=1, stroke_style=1, stroke_width=1,
823                 stroke_brush_color="black", stroke_brush_style=1,
824                 stroke_join_style=1, stroke_cap_style=1, fix_aspect=False,
825                 auto_position=True, name=""):
826        """ Create a New Plot in kst.
827
828        See :class:`Plot`
829        """
830        return Plot(self, pos, size, rot, font_size, columns, fill_color, fill_style, stroke_style,
831                    stroke_width, stroke_brush_color, stroke_brush_style,
832                    stroke_join_style, stroke_cap_style, fix_aspect, auto_position, name)
833
834    def plot(self, name):
835        """ Returns a Plot from kst given its name.
836
837        See :class:`Plot`
838        """
839        return Plot(self, name=name, new=False)
840
841    def get_plot_list(self):
842        """ Get a list of all plots in kst.
843
844        See :class:`Plot`
845        """
846        return_message = self.send("getPlotList()")
847        name_list = return_message.data()[1:-1].split("][")
848        return [Plot(self, name=n, new=False) for n in name_list]
849
850    def set_datasource_option(self, option, value, filename, data_source="Ascii File"):
851        """ Sets the value of a data source configuration option.
852
853        :param option: the name of the option - eg ""Data Start"
854        :param value: True or False
855        :param filename: the name of the file or 0 to set global default
856        :param data_source: the type of data source
857
858        Examples:
859
860        Tell kst that trial1.csv is a file with the field names in row 1 and units in row 2::
861
862            import pykst as kst
863            client = kst.Client()
864            client.set_datasource_option("Column Delimiter", ",", "trial1.csv")
865            client.set_datasource_option("Column Type", 2, "trial1.csv")
866            client.set_datasource_option("Data Start", 3-1, "trial1.csv")
867            client.set_datasource_option("Fields Line", 1-1, "trial1.csv")
868            client.set_datasource_option("Read Fields", True, "trial1.csv")
869            client.set_datasource_option("Units Line", 2-1, "trial1.csv")
870            client.set_datasource_option("Read Units", True, "trial1.csv")
871
872        Configuration options supported by the ASCII data source (default) are::
873
874            "ASCII Time format"
875            "Column Delimiter"
876            "Column Type"
877            "Column Width"
878            "Column Width is const"
879            "Comment Delimiters"
880            "Data Rate for index"
881            "Data Start"
882            "Default INDEX Interpretation"
883            "Fields Line"
884            "Filename Pattern"
885            "Index"
886            "Limit file buffer size"
887            "NaN value"
888            "Read Fields"
889            "Read Units"
890            "Size of limited file buffer"
891            "Units Line"
892            "Use Dot"
893            "Use threads when parsing Ascii data"
894            "date/time offset"
895            "relative offset"
896            "updateType"
897            "use an explicit date/time offset"
898            "use file time/date as offset"
899            "use relative file time offset"
900
901
902        """
903
904        if filename == 0:
905            filename = "$DEFAULT"
906
907        if isinstance(value, bool):
908            self.send("setDatasourceBoolConfig("+data_source+","+filename+","+option+","+
909                      b2str(value)+")")
910        elif isinstance(value, int):
911            self.send("setDatasourceIntConfig("+data_source+","+filename+","+option+","+
912                      str(value)+")")
913        else:
914            v = value
915            v.replace(',', '`')
916            self.send("setDatasourceStringConfig("+data_source+","+filename+","+option+","+
917                      str(v)+")")
918
919
920
921class NamedObject(object):
922    """ Convenience class. You should not use it directly."""
923    def __init__(self, client):
924        self.client = client
925        self.handle = ""
926
927    def set_name(self, name):
928        """ Set the name of the object inside kst. """
929        self.client.send_si(self.handle, b2str("setName("+b2str(name)+")"))
930
931    def name(self):
932        """ Returns the name of the object from inside kst. """
933        return self.client.send_si(self.handle, "name()")
934
935    def description_tip(self):
936        """  Returns a string describing the object """
937        return self.client.send_si(self.handle, "descriptionTip()")
938
939    def test_command(self):
940        return self.client.send_si(self.handle, "testCommand()")
941
942
943class Object(NamedObject):
944    """ Convenience class. You should not use it directly."""
945    def __init__(self, client):
946        NamedObject.__init__(self, client)
947
948    def type_str(self):
949        """ Returns the type of the object from inside kst. """
950        return self.client.send_si(self.handle, "type()")
951
952
953class String(Object):
954    """ Convenience class. You should not use it directly."""
955    def __init__(self, client):
956        Object.__init__(self, client)
957
958    def value(self):
959        """ Returns the string. """
960        return self.client.send_si(self.handle, "value()")
961
962class GeneratedString(String):
963    """ A string constant inside kst.
964
965    This class represents a string you would create via
966    "Create>String>Generated" from the menubar inside kst.
967
968    :param string: The value of the string.
969
970    To import the string "Hello World" into kst::
971
972      import pykst as kst
973      client = kst.Client()
974      s = client.new_generatedString("Hello World")
975
976    """
977    def __init__(self, client, string, name="", new=True):
978        String.__init__(self, client)
979
980        if new:
981            self.client.send("newGeneratedString()")
982            self.handle = self.client.send("endEdit()")
983            self.handle.remove(0, self.handle.indexOf("ing ")+4)
984
985            self.set_value(string)
986            self.set_name(name)
987        else:
988            self.handle = name
989
990    def set_value(self, val):
991        """ set the value of the string inside kst. """
992        self.client.send_si(self.handle, b2str("setValue("+b2str(val)+")"))
993
994class DataSourceString(String):
995    """ A string read from a data source inside kst.
996
997    This class represents a string you would create via
998    "Create>String>Read from Data Source" from the menubar inside kst.
999
1000    :param filename: The name of the file/data source to read the string from.
1001    :param field: the name of the field in the data source.
1002
1003    To read "File path" from the data source "tmp.dat" into kst::
1004
1005      import pykst as kst
1006      client = kst.Client()
1007      s = client.new_datasource_string("tmp.dat", "File Path")
1008
1009    """
1010    def __init__(self, client, filename, field, name="", new=True):
1011        String.__init__(self, client)
1012
1013        if new:
1014            self.client.send("newDataString()")
1015            self.handle = self.client.send("endEdit()")
1016            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1017            self.change(filename, field)
1018        else:
1019            self.handle = name
1020
1021    def change(self, filename, field, frame = 0):
1022        """ Change a DataSource String.
1023
1024        Change the file and field of a DataSourceString in kst.
1025
1026        :param filename: The name of the file/data source to read the string from.
1027        :param field: the name of the field in the data source.
1028        :param frame: the frame number if the string is a function of frame number.
1029        """
1030        self.client.send_si(self.handle, b2str("change("+b2str(filename)+","+b2str(field)+","+b2str(frame)+")"))
1031
1032
1033class Scalar(Object):
1034    """ Convenience class. You should not use it directly."""
1035    def __init__(self, client, name=""):
1036        Object.__init__(self, client)
1037
1038        self.handle = name
1039
1040    def value(self):
1041        """ Returns the scalar. """
1042        return self.client.send_si(self.handle, "value()")
1043
1044class GeneratedScalar(Scalar):
1045    """ A scalar constant inside kst.
1046
1047    This class represents a scalar you would create via
1048    "Create>Scalar>Generate" from the menubar inside kst.
1049
1050    :param value: the value to assign to the scalar constant.
1051
1052    To import the scalar of value 42 into kst::
1053
1054      import pykst as kst
1055      client = kst.Client()
1056      s = client.new_generated_scalar(42)
1057
1058    """
1059    def __init__(self, client, value, name="", new=True):
1060        Scalar.__init__(self, client)
1061
1062        if new:
1063            self.client.send("newGeneratedScalar()")
1064            self.handle = self.client.send("endEdit()")
1065            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1066
1067            self.set_value(value)
1068            self.set_name(name)
1069        else:
1070            self.handle = name
1071
1072    def set_value(self, val):
1073        """ set the value of the string inside kst. """
1074        self.client.send_si(self.handle, b2str("setValue("+b2str(val)+")"))
1075
1076
1077class DataSourceScalar(Scalar):
1078    """ A scalar read from a data source inside kst.
1079
1080    This class represents a scalar you would create via
1081    "Create>Scalar>Read from Data Source" from the menubar inside kst.
1082
1083    :param filename: The name of the file/data source to read the scalar from.
1084    :param field: the name of the field in the data source.
1085
1086    To read "CONST1" from the data source "tmp.dat" into kst::
1087
1088      import pykst as kst
1089      client = kst.Client()
1090      x = client.new_datasource_scalar("tmp.dat", "CONST1")
1091
1092    """
1093    def __init__(self, client, filename, field, name="", new=True):
1094        Scalar.__init__(self, client)
1095
1096        if new:
1097            self.client.send("newDataScalar()")
1098            self.handle = self.client.send("endEdit()")
1099            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1100
1101            self.change(filename, field)
1102        else:
1103            self.handle = name
1104
1105    def change(self, filename, field):
1106        """ Change a DataSource Scalar.
1107
1108        Change the file and field of a DataSourceScalar in kst.
1109
1110        :param filename: The name of the file/data source to read the scalar from.
1111        :param field: the name of the field in the data source.
1112        """
1113        self.client.send_si(self.handle, "change("+filename+","+field+")")
1114
1115    def file(self):
1116        """ Returns the data source file name. """
1117        return self.client.send_si(self.handle, "file()")
1118
1119    def field(self):
1120        """ Returns the field. """
1121        return self.client.send_si(self.handle, "field()")
1122
1123
1124class VectorScalar(Scalar):
1125    """ A scalar in kst read from a vector from a data source.
1126
1127    This class represents a scalar you would create via
1128    "Create>Scalar>Read from vector" from the menubar inside kst.
1129
1130    :param filename: The name of the file/data source to read the scalar from.
1131    :param field: the name of the vector in the data source.
1132    :param frame: which frame of the vector to read the scalar from.
1133                  frame = -1 (the default) reads from the end of the file.
1134
1135    To read the last value of the vector INDEX from the file "tmp.dat"
1136    into kst::
1137
1138      import pykst as kst
1139      client = kst.Client()
1140      x = client.new_vector_scalar("tmp.dat", "INDEX", -1)
1141
1142    """
1143    def __init__(self, client, filename, field, frame=-1, name="", new=True):
1144        Scalar.__init__(self, client)
1145
1146        if new:
1147            self.client.send("newVectorScalar()")
1148            self.handle = self.client.send("endEdit()")
1149            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1150
1151            self.change(filename, field, frame)
1152        else:
1153            self.handle = name
1154
1155    def change(self, filename, field, frame):
1156        """ Change a Vector Scalar in kst.
1157
1158        Change the file, field and frame of a VectorScalar in kst.
1159
1160        :param filename: The name of the file/data source to read the scalar from.
1161        :param field: the name of the vector in the data source.
1162        :param frame: which frame of the vector to read the scalar from.
1163                      frame = -1 reads from the end of the file.
1164        """
1165        self.client.send_si(self.handle, b2str("change("+b2str(filename)+","+
1166                                               b2str(field)+","+b2str(frame)+")"))
1167
1168    def file(self):
1169        """ Returns the data source file name. """
1170        return self.client.send_si(self.handle, "file()")
1171
1172    def field(self):
1173        """ Returns the field. """
1174        return self.client.send_si(self.handle, "field()")
1175
1176    def frame(self):
1177        """ Returns the fame. """
1178        return self.client.send_si(self.handle, "frame()")
1179
1180class VectorBase(Object):
1181    """ Convenience class. You should not use it directly."""
1182    def __init__(self, client, name=""):
1183        Object.__init__(self, client)
1184        self.handle = name
1185
1186    def value(self, index):
1187        """  Returns element i of this vector. """
1188        return self.client.send_si(self.handle, "value("+b2str(index)+")")
1189
1190    def length(self):
1191        """  Returns the number of samples in the vector. """
1192        return self.client.send_si(self.handle, "length()")
1193
1194    def min(self):
1195        """  Returns the minimum value in the vector. """
1196        return self.client.send_si(self.handle, "min()")
1197
1198    def mean(self):
1199        """  Returns the mean of the vector. """
1200        return self.client.send_si(self.handle, "mean()")
1201
1202    def max(self):
1203        """  Returns the maximum value in the vector. """
1204        return self.client.send_si(self.handle, "max()")
1205
1206    def get_numpy_array(self):
1207        """ get a numpy array which contains the kst vector values """
1208        with tempfile.NamedTemporaryFile() as f:
1209            self.client.send_si(self.handle, "store(" + f.name + ")")
1210            array = np.fromfile(f.name, dtype=np.float64)
1211
1212        return array
1213
1214
1215class DataVector(VectorBase):
1216    """ A vector in kst, read from a data source.
1217
1218    This class represents a vector you would create via
1219    "Create>Vector>Read from Data Source" from the menubar inside kst.
1220
1221    The parameters of this function mirror the parameters within
1222    "Create>Vector>Read from Data Source".
1223
1224    :param filename: The name of the file/data source to read the scalar from.
1225    :param field: the name of the vector in the data source.
1226    :param start: The starting index of the vector.
1227                  start = -1 for count from end.
1228    :param num_frames: The number of frames to read.
1229                    num_frames = -1 for read to end.
1230    :param skip: The number of frames per sample read.
1231                 skip = 0 to read every sample.
1232    :param boxcarFirst: apply a boxcar filter before skiping.
1233
1234    To create a vector from "tmp.dat" with field "INDEX" from
1235    frame 3 to frame 10, reading a sample every other frame without
1236    a boxcar filter::
1237
1238      import pykst as kst
1239      client = kst.Client()
1240      v = client.new_data_vector("tmp.dat", "INDEX", 3, 10, 2, False)
1241
1242    """
1243    def __init__(self, client, filename, field, start=0, num_frames=-1,
1244                 skip=0, boxcarFirst=False, name="", new=True):
1245        VectorBase.__init__(self, client)
1246
1247        if new:
1248            self.client.send("newDataVector()")
1249            self.handle = self.client.send("endEdit()")
1250            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1251            self.change(filename, field, start, num_frames, skip, boxcarFirst)
1252        else:
1253            self.handle = name
1254
1255    def change(self, filename, field, start, num_frames, skip, boxcarFirst):
1256        """ Change the parameters of a data vector.
1257
1258        :param filename: The name of the file/data source to read the scalar from.
1259        :param field: the name of the vector in the data source.
1260        :param start: The starting index of the vector.
1261                      start = -1 for count from end.
1262        :param num_frames: The number of frames to read.
1263                        num_frames = -1 for read to end.
1264        :param skip: The number of frames per sample read.
1265                    skip = 0 to read every sample.
1266        :param boxcarFirst: apply a boxcar filter before skiping.
1267
1268        """
1269        self.client.send_si(self.handle, "change("+filename+","+field+","
1270                            +b2str(start)+","+b2str(num_frames)+","+b2str(skip)
1271                            +","+b2str(boxcarFirst)+")")
1272
1273    def change_frames(self, start, num_frames, skip, boxcarFirst):
1274        """ Change the parameters of a data vector.
1275
1276        :param start: The starting index of the vector.
1277                      start = -1 for count from end.
1278        :param num_frames: The number of frames to read.
1279                        num_frames = -1 for read to end.
1280        :param skip: The number of frames per sample read.
1281                    skip = 0 to read every sample.
1282        :param boxcarFirst: apply a boxcar filter before skiping.
1283
1284        """
1285        self.client.send_si(self.handle, "changeFrames("
1286                            +b2str(start)+","+b2str(num_frames)+","+b2str(skip)
1287                            +","+b2str(boxcarFirst)+")")
1288
1289    def field(self):
1290        """  Returns the fieldname. """
1291        return self.client.send_si(self.handle, "field()")
1292
1293    def filename(self):
1294        """  Returns the filename. """
1295        return self.client.send_si(self.handle, "filename()")
1296
1297    def start(self):
1298        """  Returns the index of first frame in the vector.
1299        -1 means count from end. """
1300        return self.client.send_si(self.handle, "start()")
1301
1302    def n_frames(self):
1303        """  Returns the number of frames to be read. -1 means read to end. """
1304        return self.client.send_si(self.handle, "NFrames()")
1305
1306    def skip(self):
1307        """  Returns number of frames to be skipped between samples read. """
1308        return self.client.send_si(self.handle, "skip()")
1309
1310    def boxcar_first(self):
1311        """  True if boxcar filtering has been applied before skipping. """
1312        return self.client.send_si(self.handle, "boxcarFirst()")
1313
1314class GeneratedVector(VectorBase):
1315    """ Create a generated vector in kst.
1316
1317    This class represents a vector you would create via
1318    "Create>Vector>Generate" from the menubar inside kst.
1319
1320    :param x0: The first value in the vector.
1321    :param x1: The last value in the vector.
1322    :param n: The number of evenly spaced values in the vector.
1323
1324    To create the vector {0, 0.2, 0.4, 0.6, 0.8, 1.0}::
1325
1326      import pykst as kst
1327      client = kst.Client()
1328      v = client.new_generated_vector(0, 1, 6)
1329
1330    """
1331    def __init__(self, client, x0=0, x1=1, n=100, name="", new=True):
1332        VectorBase.__init__(self, client)
1333
1334        if new:
1335            self.client.send("newGeneratedVector()")
1336            self.handle = self.client.send("endEdit()")
1337            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1338
1339            self.change(x0, x1, n)
1340            self.set_name(name)
1341        else:
1342            self.handle = name
1343
1344    def change(self, x0, x1, n):
1345        """ Change the parameters of a Generated Vector inside kst.
1346
1347        :param x0: The first value in the vector.
1348        :param x1: The last value in the vector.
1349        :param n: The number of evenly spaced values in the vector.
1350        """
1351        self.client.send_si(self.handle, "change("+b2str(x0)+","+b2str(x1)+
1352                            ","+b2str(n)+")")
1353
1354class EditableVector(VectorBase):
1355    """ A vector in kst, which is editable from python.
1356
1357    This vector in kst can be created from a numpy array,
1358    (with ''load()'') or edited point by point (with ''setValue()'').
1359    "Create>Vector>Generate" from the menubar inside kst.
1360
1361    :param np_array: initialize the vector in kst to this (optional) 1D numpy array.
1362
1363    To create a from the num py array np::
1364
1365      import pykst as kst
1366      client = kst.Client()
1367      v = client.new_editable_vector(np)
1368
1369    """
1370    def __init__(self, client, np_array=None, name="", new=True):
1371        VectorBase.__init__(self, client)
1372
1373        if new:
1374            self.client.send("newEditableVector()")
1375            if np_array is not None:
1376                assert np_array.dtype == np.float64
1377
1378                with tempfile.NamedTemporaryFile(delete=False) as f:
1379                    f.close()
1380                    #atexit.register(clean_tmp_file, f)
1381                    np_array.tofile(f.name)
1382                    self.client.send("load(" + f.name + ")")
1383                    os.unlink(f.name)
1384
1385            self.handle = self.client.send("endEdit()")
1386            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1387
1388            self.set_name(name)
1389        else:
1390            self.handle = name
1391
1392    def load(self, np_array):
1393        """  sets the value of the vector to that of the float64
1394        1D np array """
1395
1396        assert np_array.dtype == np.float64
1397        with tempfile.NamedTemporaryFile(delete=False) as f:
1398            f.close()
1399            #atexit.register(clean_tmp_file, f)
1400            np_array.tofile(f.name)
1401            retval = self.client.send_si(self.handle, "load(" + f.name + ")")
1402            os.unlink(f.name)
1403
1404        return retval
1405
1406class Matrix(Object):
1407    """ Convenience class. You should not use it directly."""
1408    def __init__(self, client, name=""):
1409        Object.__init__(self, client)
1410
1411        self.handle = name
1412
1413
1414    def value(self, i_x, i_y):
1415        """  Returns element (i_x, i_y} of this matrix. """
1416        return self.client.send_si(self.handle, "value("+b2str(i_x)+
1417                                   ","+b2str(i_y)+")")
1418
1419    def length(self):
1420        """  Returns the number of elements in the matrix. """
1421        return self.client.send_si(self.handle, "length()")
1422
1423    def min(self):
1424        """  Returns the minimum value in the matrix. """
1425        return self.client.send_si(self.handle, "min()")
1426
1427    def mean(self):
1428        """  Returns the mean of the matrix. """
1429        return self.client.send_si(self.handle, "mean()")
1430
1431    def max(self):
1432        """  Returns the maximum value in the matrix. """
1433        return self.client.send_si(self.handle, "max()")
1434
1435    def width(self):
1436        """  Returns the X dimension of the matrix. """
1437        return self.client.send_si(self.handle, "width()")
1438
1439    def height(self):
1440        """  Returns the Y dimension of the matrix. """
1441        return self.client.send_si(self.handle, "height()")
1442
1443    def dx(self):
1444        """  Returns the X spacing of the matrix, for when the matrix is used in an image. """
1445        return self.client.send_si(self.handle, "dX()")
1446
1447    def dy(self):
1448        """  Returns the Y spacing of the matrix, for when the matrix is used in an image. """
1449        return self.client.send_si(self.handle, "dY()")
1450
1451    def min_x(self):
1452        """  Returns the minimum X location of the matrix, for when the matrix
1453        is used in an image. """
1454        return self.client.send_si(self.handle, "minX()")
1455
1456    def min_y(self):
1457        """  Returns the minimum X location of the matrix, for when the matrix
1458        is used in an image. """
1459        return self.client.send_si(self.handle, "minY()")
1460
1461    def get_numpy_array(self):
1462        """ get a numpy array which contains the kst matrix values """
1463        with tempfile.NamedTemporaryFile() as f:
1464            args = str(self.client.send_si(self.handle, "store(" + f.name + ")"))
1465            dims = tuple(map(int, args.split()))
1466            array = np.fromfile(f.name, dtype=np.float64)
1467            array = array.reshape((dims))
1468
1469        return array
1470
1471
1472class DataMatrix(Matrix):
1473    """  Create a Data Matrix which reads from a data source inside kst.
1474
1475    This class represents a matrix you would create via
1476    "Create>Vector>Read from Data Source" from the menubar inside kst.
1477    The parameters of this function mirror the parameters within
1478    "Create>Matrix>Read from Data Source".
1479
1480    :param filename: The name of the file/data source to read the scalar from.
1481    :param field: the name of the vector in the data source.
1482    :param start_x/start_y: the x/y index to start reading from. start_x/Y = -1
1483                     to count from the right/bottom.
1484    :param num_x/num_y: the number of columns/rows to read.  num_x/Y = -1 to read
1485                 to the end.
1486    :param min_x/min_y: Hint to Images of the coordinates corresponding to the
1487                   the left/bottom of the Matrix
1488    :param dx/dy: Hint to Images of the spacing between points.
1489
1490    To create a matrix from 'foo.png' with field '1'::
1491
1492      import pykst as kst
1493      client = kst.Client()
1494      v = client.new_data_matrix("foo.png", "1")
1495
1496    """
1497    def __init__(self, client, filename, field, start_x=0, start_y=0, num_x=-1, num_y=-1,
1498                 min_x=0, min_y=0, dx=1, dy=1, name="", new=True):
1499        Matrix.__init__(self, client)
1500
1501        if new:
1502            self.client.send("newDataMatrix()")
1503            self.handle = self.client.send("endEdit()")
1504            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1505
1506            self.change(filename, field, start_x, start_y, num_x, num_y, min_x, min_y, dx, dy)
1507        else:
1508            self.handle = name
1509
1510    def change(self, filename, field, start_x=0, start_y=0, num_x=-1, num_y=-1,
1511               min_x=0, min_y=0, dx=1, dy=1):
1512        """ Change the parameters if a Data Matrix inside kst.
1513
1514        :param filename: The name of the file/data source to read the scalar from.
1515        :param field: the name of the vector in the data source.
1516        :param start_x/start_y: the x/y index to start reading from. start_x/y = -1
1517                        to count from the right/bottom.
1518        :param num_x/num_y: the number of columns/rows to read.  num_x/Y = -1 to read
1519                    to the end.
1520        :param min_x/min_y: Hint to Images of the coordinates corresponding to the
1521                      the left/bottom of the Matrix
1522        :param dx/dy: Hint to Images of the spacing between points.
1523        """
1524        self.client.send_si(self.handle, "change("+b2str(filename)+","+
1525                            b2str(field)+","+b2str(start_x)+","+
1526                            b2str(start_y)+","+b2str(num_x)+","+b2str(num_y)+","+
1527                            b2str(min_x)+","+b2str(min_y)+","+b2str(dx)+","+
1528                            b2str(dy)+")")
1529
1530    def field(self):
1531        """  Returns the fieldname. """
1532        return self.client.send_si(self.handle, "field()")
1533
1534    def filename(self):
1535        """  Returns the filename. """
1536        return self.client.send_si(self.handle, "filename()")
1537
1538    def start_x(self):
1539        """  Returns the X index of the matrix in the file """
1540        return self.client.send_si(self.handle, "startX()")
1541
1542    def start_y(self):
1543        """  Returns the Y index of the matrix in the file """
1544        return self.client.send_si(self.handle, "startY()")
1545
1546class EditableMatrix(Matrix):
1547    """ A matrix in kst, which is editable from python.
1548
1549    This matrix in kst can be created from 2D float64 numpy array,
1550    (with ''load()'') or edited point by point (with ''setValue()'').
1551
1552    :param np_array: initialize the matrix in kst to this 2D numpy array.
1553
1554    To create an editable matrix from the num py array np::
1555
1556      import pykst as kst
1557      client = kst.Client()
1558      m = client.new_editable_matrix(np)
1559
1560    """
1561    def __init__(self, client, np_array=None, name="", new=True):
1562        Matrix.__init__(self, client)
1563
1564        if new:
1565            self.client.send("newEditableMatrix()")
1566            if np_array is not None:
1567                assert np_array.dtype == np.float64
1568                nx = np_array.shape[0]
1569                ny = np_array.shape[1]
1570
1571                with tempfile.NamedTemporaryFile(delete=False) as f:
1572                    f.close()
1573                    atexit.register(clean_tmp_file, f)
1574                    np_array.tofile(f.name)
1575                    self.client.send("load(" + f.name + ","+b2str(nx)+","+b2str(ny)+")")
1576
1577            self.handle = self.client.send("endEdit()")
1578            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1579
1580            self.set_name(name)
1581        else:
1582            self.handle = name
1583
1584    def load(self, np_array):
1585        """  sets the values of the matrix in kst to that of the float64
1586        2D np array """
1587
1588        assert np_array.dtype == np.float64
1589        nx = np_array.shape[0]
1590        ny = np_array.shape[1]
1591
1592        with tempfile.NamedTemporaryFile(delete=False) as f:
1593            f.close()
1594            atexit.register(clean_tmp_file, f)
1595            np_array.tofile(f.name)
1596            retval = self.client.send_si(self.handle, "load(" + f.name + ","+b2str(nx)+","+
1597                                         b2str(ny)+")")
1598
1599        return retval
1600
1601
1602class Relation(Object):
1603    """ Convenience class. You should not use it directly."""
1604    def __init__(self, client):
1605        Object.__init__(self, client)
1606
1607    def max_x(self):
1608        """  Returns the max X value of the curve or image. """
1609        return self.client.send_si(self.handle, "maxX()")
1610
1611    def min_x(self):
1612        """  Returns the min X value of the curve or image. """
1613        return self.client.send_si(self.handle, "minX()")
1614
1615    def max_y(self):
1616        """  Returns the max Y value of the curve or image. """
1617        return self.client.send_si(self.handle, "maxY()")
1618
1619    def min_y(self):
1620        """  Returns the min Y value of the curve or image. """
1621        return self.client.send_si(self.handle, "minY()")
1622
1623    def show_edit_dialog(self):
1624        """  shows the edit dialog for the curve or image. """
1625        return self.client.send_si(self.handle, "showEditDialog()")
1626
1627class Curve(Relation):
1628    """ A Curve inside kst.
1629
1630    This class represents a string you would create via
1631    "Create>Curve" from the menubar inside kst.  The parameters of this
1632    function mirror the parameters within "Create>Curve".
1633
1634    :param x_vector: The vector which specifies the X coordinates of each point.
1635    :param x_vector: The vector which specifies the Y coordinates of each point.
1636
1637    Use the convenience function in client to create a curve in kst session
1638    "client" of vectors v1 and v2::
1639
1640      c1 = client.new_curve(v1, v2)
1641
1642    """
1643    def __init__(self, client, x_vector, y_vector, name="", new=True):
1644        Relation.__init__(self, client)
1645
1646        if new:
1647            self.client.send("newCurve()")
1648            self.client.send("setXVector("+x_vector.handle+")")
1649            self.client.send("setYVector("+y_vector.handle+")")
1650            self.handle = self.client.send("endEdit()")
1651            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1652            self.set_name(name)
1653        else:
1654            self.handle = name
1655
1656    def set_y_error(self, vector, vectorminus=0):
1657        """ Set the Y Error flags for the curve.
1658
1659        The error bars are symetric if vectorminus is not set.
1660        """
1661        self.client.send("beginEdit("+self.handle+")")
1662
1663        self.client.send("setYError("+vector.handle+")")
1664        if vectorminus != 0:
1665            self.client.send("setYMinusError("+vectorminus.handle+")")
1666        else:
1667            self.client.send("setYMinusError("+vector.handle+")")
1668
1669        self.client.send("endEdit()")
1670
1671    def set_x_error(self, vector, vectorminus=0):
1672        """ Set the X Error flags for the curve.
1673
1674        The error bars are symetric if vectorminus is not set.
1675        """
1676        self.client.send("beginEdit("+self.handle+")")
1677
1678        self.client.send("setXError("+vector.handle+")")
1679        if vectorminus != 0:
1680            self.client.send("setXMinusError("+vectorminus.handle+")")
1681        else:
1682            self.client.send("setXMinusError("+vector.handle+")")
1683
1684        self.client.send("endEdit()")
1685
1686    def set_color(self, color):
1687        """ Set the color of the points and lines.
1688
1689        Colors are given by a name such as ``red`` or a hex number such
1690        as ``#FF0000``.
1691        """
1692        self.client.send_si(self.handle, "setColor("+color+")")
1693
1694    def set_head_color(self, color):
1695        """ Set the color of the Head marker, if any.
1696
1697        Colors are given by a name such as ``red`` or a hex number such
1698        as ``#FF0000``.
1699        """
1700        self.client.send_si(self.handle, "setHeadColor("+color+")")
1701
1702    def set_bar_fill_color(self, color):
1703        """ Set the fill color of the histogram bars, if any.
1704
1705        Colors are given by a name such as ``red`` or a hex number such
1706        as ``#FF0000``.
1707        """
1708        self.client.send_si(self.handle, "setBarFillColor("+color+")")
1709
1710    def set_has_points(self, has=True):
1711        """ Set whether individual points are drawn on the curve """
1712        if has:
1713            self.client.send_si(self.handle, "setHasPoints(True)")
1714        else:
1715            self.client.send_si(self.handle, "setHasPoints(False)")
1716
1717    def set_has_bars(self, has=True):
1718        """ Set whether histogram bars are drawn. """
1719        if has:
1720            self.client.send_si(self.handle, "setHasBars(True)")
1721        else:
1722            self.client.send_si(self.handle, "setHasBars(False)")
1723
1724    def set_has_lines(self, has=True):
1725        """ Set whether lines are drawn. """
1726        if has:
1727            self.client.send_si(self.handle, "setHasLines(True)")
1728        else:
1729            self.client.send_si(self.handle, "setHasLines(False)")
1730
1731    def set_has_head(self, has=True):
1732        """ Set whether a point at the head of the line is drawn """
1733        if has:
1734            self.client.send_si(self.handle, "setHasHead(True)")
1735        else:
1736            self.client.send_si(self.handle, "setHasHead(False)")
1737
1738    def set_line_width(self, x):
1739        """ Sets the width of the curve's line. """
1740        self.client.send_si(self.handle, "setLineWidth("+b2str(x)+")")
1741
1742    def set_point_size(self, x):
1743        """ Sets the size of points, if they are drawn. """
1744        self.client.send_si(self.handle, "setPointSize("+b2str(x)+")")
1745
1746    def set_point_density(self, density):
1747        """ Sets the point density.
1748
1749        When show_points is true, this option can be used to only show a
1750        subset of the points, for example, to use point types to discriminate
1751        between different curves..  This does not effect 'lines', where every
1752        point is always connected.
1753
1754        density can be from 0 (all points) to 4.
1755        """
1756        self.client.send_si(self.handle, "setPointDensity("+b2str(density)+")")
1757
1758    def set_point_type(self, point_type):
1759        """ Sets the point type.
1760
1761        The available point types are::
1762
1763         0:  X                       1: open square
1764         2:  open circle,           3: filled circle
1765         4:  downward open triangle  5: upward open triangle
1766         6:  filled square           7: +
1767         8:  *                       9: downward filled triangle
1768         10: upward filled triangle 11: open diamond
1769         12: filled diamond
1770
1771        """
1772        self.client.send_si(self.handle, "setPointType("+b2str(point_type)+")")
1773
1774    def set_head_type(self, x):
1775        """ Sets the head point type.  See set_point_type for details."""
1776        self.client.send_si(self.handle, "setHeadType("+b2str(x)+")")
1777
1778    def set_line_style(self, lineStyle):
1779        """ Sets the line type.
1780
1781        0 is SolidLine, 1 is DashLine, 2 is DotLine, 3 is DashDotLine,
1782        and 4 isDashDotDotLine,
1783        """
1784        self.client.send_si(self.handle, "setLineStyle("+b2str(lineStyle)+")")
1785
1786
1787    def color(self):
1788        """ Returns the curve color. """
1789        return self.client.send_si(self.handle, "color()")
1790
1791    def head_color(self):
1792        """ Returns the curve head color. """
1793        return self.client.send_si(self.handle, "headColor()")
1794
1795    def bar_fill_color(self):
1796        """ Returns the bar fill color. """
1797        return self.client.send_si(self.handle, "barFillColor()")
1798
1799    def has_points(self):
1800        """ Returns True if the line has points. """
1801        return self.client.send_si(self.handle, "hasPoints()") == "True"
1802
1803    def has_lines(self):
1804        """ Returns True if the line has lines. """
1805        return self.client.send_si(self.handle, "hasLines()") == "True"
1806
1807    def has_bars(self):
1808        """ Returns True if the line has historgram bars. """
1809        return self.client.send_si(self.handle, "hasBars()") == "True"
1810
1811    def has_head(self):
1812        """ Returns True if the last point has a special marker. """
1813        return self.client.send_si(self.handle, "hasHead()") == "True"
1814
1815    def line_width(self):
1816        """ Returns the width of the line. """
1817        return self.client.send_si(self.handle, "lineWidth()")
1818
1819    def point_size(self):
1820        """ Returns the size of the points. """
1821        return self.client.send_si(self.handle, "pointSize()")
1822
1823    def point_type(self):
1824        """ Returns index of the point type.  See set_point_type. """
1825        return self.client.send_si(self.handle, "pointType()")
1826
1827    def head_type(self):
1828        """ Returns index of the head point type.  See set_point_type. """
1829        return self.client.send_si(self.handle, "headType()")
1830
1831    def line_style(self):
1832        """ Returns the index of the line style.  See set_line_style. """
1833        return self.client.send_si(self.handle, "lineStyle()")
1834
1835    def point_density(self):
1836        """ Returns the density of points shown.  see set_point_density.  """
1837        return self.client.send_si(self.handle, "pointDensity()")
1838
1839    def x_vector(self):
1840        """ Returns the x vector of the curve.
1841
1842        FIXME: should figure out what kind of vector this is and return that.
1843        """
1844        vec = VectorBase(self.client)
1845        vec.handle = self.client.send_si(self.handle, "xVector()")
1846        return vec
1847
1848    def y_vector(self):
1849        """ Returns the y vector of the curve.
1850
1851        FIXME: should figure out what kind of vector this is and return that.
1852        """
1853        vec = VectorBase(self.client)
1854        vec.handle = self.client.send_si(self.handle, "yVector()")
1855        return vec
1856
1857    def x_error_vector(self):
1858        """ Returns the +x error vector of the curve.
1859
1860        FIXME: should figure out what kind of vector this is and return that.
1861        """
1862        vec = VectorBase(self.client)
1863        vec.handle = self.client.send_si(self.handle, "xErrorVector()")
1864        return vec
1865
1866    def y_error_vector(self):
1867        """ Returns the +y error vector of the curve.
1868
1869        FIXME: should figure out what kind of vector this is and return that.
1870        """
1871        vec = VectorBase(self.client)
1872        vec.handle = self.client.send_si(self.handle, "yErrorVector()")
1873        return vec
1874
1875    def x_minus_error_vector(self):
1876        """ Returns the -x error vector of the curve.
1877
1878        FIXME: should figure out what kind of vector this is and return that.
1879        """
1880        vec = VectorBase(self.client)
1881        vec.handle = self.client.send_si(self.handle, "xMinusErrorVector()")
1882        return vec
1883
1884    def y_minus_error_vector(self):
1885        """ Returns the -y error vector of the curve.
1886
1887        FIXME: should figure out what kind of vector this is and return that.
1888        """
1889        vec = VectorBase(self.client)
1890        vec.handle = self.client.send_si(self.handle, "yMinusErrorVector()")
1891        return vec
1892
1893class Image(Relation):
1894    """ An image inside kst.
1895
1896    This class represents an image you would create via
1897    "Create>Image" from the menubar inside kst.  The parameters of this
1898    function mirror the parameters within "Create>Curve".
1899
1900    :param matrix: The matrix which defines the image.
1901
1902    Use the convenience function in client to create an image in kst session
1903    "client" of Matrix m::
1904
1905      i1 = client.new_image(m)
1906
1907    """
1908    def __init__(self, client, matrix, name="", new=True):
1909        Relation.__init__(self, client)
1910
1911        if new:
1912            self.client.send("newImage()")
1913            self.client.send("setMatrix("+matrix.handle+")")
1914            self.handle = self.client.send("endEdit()")
1915            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1916            self.set_name(name)
1917
1918        else:
1919            self.handle = name
1920
1921    def set_matrix(self, matrix):
1922        """ change the matrix which is the source of the image. """
1923        self.client.send_si(self.handle, "setMatrix("+matrix.handle+")")
1924
1925    def set_palette(self, palette):
1926        """ set the palette, selected by index.
1927
1928        The available palettes are::
1929
1930          0: Grey
1931          1:  Red
1932          2:  Spectrum
1933          3:  EOS-A
1934          4:  EOS-B
1935          5:  8 colors
1936          6:  Cyclical Spectrum
1937
1938        Note: this is not the same order as the dialog.
1939        """
1940        self.client.send_si(self.handle, "setPalette("+b2str(palette)+")")
1941
1942    def set_range(self, zmin, zmax):
1943        """ sets the z range of the color map."""
1944        self.client.send_si(self.handle, "setFixedColorRange("+
1945                            b2str(zmin)+","+b2str(zmax)+")")
1946
1947    def set_auto_range(self, saturated=0):
1948        """ Automatically set the z range of the color map
1949
1950        :param saturated: The colormap range is set so that this fraction
1951                          of the points in the matrix are saturated.
1952
1953        Equal numbers of points are saturated at both ends of the color map.
1954        """
1955        self.client.send_si(self.handle, "setAutoColorRange("+b2str(saturated) + ")")
1956
1957    def max_z(self):
1958        """  Returns the max Z value of the curve or image. """
1959        return self.client.send_si(self.handle, "maxZ()")
1960
1961    def min_z(self):
1962        """  Returns the max Z value of the curve or image. """
1963        return self.client.send_si(self.handle, "minZ()")
1964
1965# Equation ############################################################
1966class Equation(Object):
1967    """ An equation inside kst.
1968
1969      :param xvector: the x vector of the equation
1970      :param equation: the equation
1971
1972      Vectors inside kst are refered to as [vectorname] or [scalarname].
1973    """
1974    def __init__(self, client, xvector, equation, interpolate=True, name="", new=True):
1975        Object.__init__(self, client)
1976
1977        if new:
1978            self.client.send("newEquation()")
1979
1980            self.client.send("setEquation(" + equation + ")")
1981            self.client.send("setInputVector(X,"+xvector.handle+")")
1982            self.client.send("interpolateVectors("+b2str(interpolate)+")")
1983            self.handle = self.client.send("endEdit()")
1984            self.handle.remove(0, self.handle.indexOf("ing ")+4)
1985            self.set_name(name)
1986        else:
1987            self.handle = name
1988
1989    def y(self):
1990        """ a vector containing the equation  """
1991        vec = VectorBase(self.client)
1992        vec.handle = self.client.send_si(self.handle, "outputVector(O)")
1993        return vec
1994
1995    def x(self):
1996        """ a vector containing the x vector  """
1997        vec = VectorBase(self.client)
1998        vec.handle = self.client.send_si(self.handle, "outputVector(XO)")
1999        return vec
2000
2001    def set_x(self, xvector):
2002        """ set the x vector of an existing equation.  xvector is a kst vector.  """
2003        self.client.send_si(self.handle, "setInputVector(X,"+xvector.handle+")")
2004
2005    def set_equation(self, equation):
2006        """ set the equation of an existing equation  """
2007        self.client.send_si(self.handle, "setEquation(" + equation + ")")
2008
2009    def set_inpterpolate(self, interpolate):
2010        """ set whether all vectors are interpolated to the highest resolution vector. """
2011        self.client.send_si(self.handle, "interpolateVectors(" + b2str(interpolate) + ")")
2012
2013# Histogram ############################################################
2014class Histogram(Object):
2015    """ A Histogram inside kst.
2016
2017      :param vector: the vector to take the histogram of
2018      :param bin_min: the low end of the lowest bin
2019      :param bin_max: the high end of the highest bin
2020      :param num_bins: the number of bins
2021      :param normalization: see below
2022      :param auto_bin: if True, set xmin and xmax based on the vector
2023
2024      The normalization types are::
2025
2026       0: Number in the bin     1: Percent in the bin
2027       2: Fraction in the bin   3: Peak is normalized to 1.0
2028
2029    """
2030    def __init__(self, client, vector, bin_min, bin_max, num_bins,
2031                 normalization=0, auto_bin=False,
2032                 name="", new=True):
2033        Object.__init__(self, client)
2034
2035        if new:
2036            self.client.send("newHistogram()")
2037
2038            self.client.send("change(" + vector.handle + "," +
2039                             b2str(bin_min) + "," +
2040                             b2str(bin_max) + "," +
2041                             b2str(num_bins) + "," +
2042                             b2str(normalization) + "," +
2043                             b2str(auto_bin) + ")")
2044
2045            self.handle = self.client.send("endEdit()")
2046            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2047            self.set_name(name)
2048        else:
2049            self.handle = name
2050
2051    def y(self):
2052        """ a vector containing the histogram values  """
2053        vec = VectorBase(self.client)
2054        vec.handle = self.client.send_si(self.handle, "outputVector(H)")
2055        return vec
2056
2057    def x(self):
2058        """ a vector containing the bin centers  """
2059        vec = VectorBase(self.client)
2060        vec.handle = self.client.send_si(self.handle, "outputVector(B)")
2061        return vec
2062
2063    def change(self, vector, bin_min, bin_max, num_bins,
2064               normalization=0, auto_bin=False):
2065        """ Change Histogram parameters.
2066
2067        :param vector: the vector to take the histogram of
2068        :param bin_min: the low end of the lowest bin
2069        :param bin_max: the high end of the highest bin
2070        :param num_bins: the number of bins
2071        :param normalization: See :class:`Histogram`
2072        :param auto_bin: if True, set xmin and xmax based on the vector
2073
2074        """
2075        self.client.send_si(self.handle, "change(" +
2076                            vector.handle + "," +
2077                            b2str(bin_min) + "," +
2078                            b2str(bin_max) + "," +
2079                            b2str(num_bins) + "," +
2080                            b2str(normalization) + "," +
2081                            b2str(auto_bin) + ")")
2082
2083    def bin_min(self):
2084        """ the low end of the lowest bin """
2085        retval = self.client.send_si(self.handle, "xMin()")
2086        return retval
2087
2088    def bin_max(self):
2089        """ the high end of the lowest bin """
2090        retval = self.client.send_si(self.handle, "xMax()")
2091        return retval
2092
2093    def num_bins(self):
2094        """ the number of bins """
2095        retval = self.client.send_si(self.handle, "nBins()")
2096        return retval
2097
2098    def normalization(self):
2099        """ how the bins are normalized
2100
2101        See :class:`Histogram`
2102
2103        """
2104        retval = self.client.send_si(self.handle, "normalizationType()")
2105        return retval
2106
2107    def auto_bin(self):
2108        """ if True, xmin and xmax are set based on the vector """
2109        retval = self.client.send_si(self.handle, "autoBin()")
2110        return retval
2111
2112# Spectrum ############################################################
2113class Spectrum(Object):
2114    """ An spectrum inside kst.
2115
2116      :param vector: the vector to take the spectrum of
2117      :param sample_rate: the sample rate of the vector
2118      :param interleaved_average: average spectra of length fft_length
2119      :param fft_length: the fft is 2^fft_length long if interleaved_average is true.
2120      :param apodize: if true, apodize the vector first
2121      :param remove_mean: if true, remove mean first
2122      :param vector_unints: units of the input vector - for labels.
2123      :param rate_units: the units of the sample rate - for labels.
2124      :param apodize_function: index of the apodization function - see apodize_function()
2125      :param sigma: only used if gausian apodization is selected.
2126      :param output_type: index for the output type - see output_type()
2127
2128      The apodize function is::
2129
2130       0: default          1: Bartlett
2131       2: Window           3: Connes
2132       4: Cosine           5: Gaussian
2133       6: Hamming          7: Hann
2134       8: Welch            9: Uniform
2135
2136      The output type is::
2137
2138       0: Amplitude Spectral Density  1: Power Spectral Density
2139       2: AmplitudeSpectrum           3: Power Spectrum
2140
2141
2142    """
2143    def __init__(self, client,
2144                 vector,
2145                 sample_rate=1.0,
2146                 interleaved_average=False,
2147                 fft_length=10,
2148                 apodize=True,
2149                 remove_mean=True,
2150                 vector_units="",
2151                 rate_units="Hz",
2152                 apodize_function=0,
2153                 sigma=1.0,
2154                 output_type=0,
2155                 name="", new=True):
2156
2157        Object.__init__(self, client)
2158
2159        if new:
2160            self.client.send("newSpectrum()")
2161
2162            self.client.send("change(" + vector.handle + "," +
2163                             b2str(sample_rate) + "," +
2164                             b2str(interleaved_average) + "," +
2165                             b2str(fft_length) + "," +
2166                             b2str(apodize) + "," +
2167                             b2str(remove_mean) + "," +
2168                             vector_units + "," +
2169                             rate_units + "," +
2170                             b2str(apodize_function) + "," +
2171                             b2str(sigma) + "," +
2172                             b2str(output_type) + "," + ")")
2173
2174            self.handle = self.client.send("endEdit()")
2175            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2176            self.set_name(name)
2177        else:
2178            self.handle = name
2179
2180    def y(self):
2181        """ a vector containing the spectrum  """
2182        vec = VectorBase(self.client)
2183        vec.handle = self.client.send_si(self.handle, "outputVector(S)")
2184        return vec
2185
2186    def x(self):
2187        """ a vector containing the frequency bins  """
2188        vec = VectorBase(self.client)
2189        vec.handle = self.client.send_si(self.handle, "outputVector(F)")
2190        return vec
2191
2192    def set_vector(self, xvector):
2193        """ set the input vector """
2194        self.client.send_si(self.handle, "setInputVector(I,"+xvector.handle+")")
2195
2196    def interleaved_average(self):
2197        """ average spectra of length fft_length() """
2198        retval = self.client.send_si(self.handle, "interleavedAverage()")
2199        return retval
2200
2201    def sample_rate(self):
2202        """ the sample rate assumed for the spectra. """
2203        retval = self.client.send_si(self.handle, "sampleRate()")
2204        return retval
2205
2206    def fft_length(self):
2207        """ ffts are 2^fft_length() long if interleaved_average is set """
2208        retval = self.client.send_si(self.handle, "fftLength()")
2209        return retval
2210
2211    def apodize(self):
2212        """ apodize before taking spectra, if set """
2213        retval = self.client.send_si(self.handle, "apodize()")
2214        return retval
2215
2216    def remove_mean(self):
2217        """ remove mean before taking spectra, if set """
2218        retval = self.client.send_si(self.handle, "removeMean()")
2219        return retval
2220
2221    def vector_units(self):
2222        """ the units of the input vector.  For labels """
2223        retval = self.client.send_si(self.handle, "vectorUnits()")
2224        return retval
2225
2226    def rate_units(self):
2227        """ the units of the sample rate.  For labels """
2228        retval = self.client.send_si(self.handle, "rateUnits()")
2229        return retval
2230
2231    def apodize_function(self):
2232        """ the index of the apodize function.
2233
2234        The apodize funcition is::
2235
2236         0: default          1: Bartlett
2237         2: Window           3: Connes
2238         4: Cosine           5: Gaussian
2239         6: Hamming          7: Hann
2240         8: Welch            9: Uniform
2241
2242        """
2243        retval = self.client.send_si(self.handle, "apodizeFunctionIndex()")
2244        return retval
2245
2246    def gaussian_sigma(self):
2247        """ the width, if apodize_funcion_index() is 5 (gaussian). """
2248        retval = self.client.send_si(self.handle, "gaussianSigma()")
2249        return retval
2250
2251    def output_type(self):
2252        """ the index of the spectrum output type.
2253
2254        The output type is::
2255
2256         0: Amplitude Spectral Density  1: Power Spectral Density
2257         2: AmplitudeSpectrum           3: Power Spectrum
2258
2259        """
2260
2261        retval = self.client.send_si(self.handle, "outputTypeIndex()")
2262        return retval
2263
2264
2265# Cross Spectrum ########################################################
2266class CrossSpectrum(Object):
2267    """ a cross spectrum plugin inside kst.
2268
2269    Takes two equal sized vectors and calculates their cross spectrum.
2270
2271      :param V1: First kst vector
2272      :param V2: Second kst vector.  Must be the same size as V1
2273      :param fft_size: the fft will be on subvectors of length 2^fft_size
2274      :param sample_rate: the sample rate of the vectors
2275
2276    """
2277    def __init__(self, client, V1, V2, fft_size, sample_rate, name="", new=True):
2278        Object.__init__(self, client)
2279
2280        if new:
2281            self.client.send("newPlugin(Cross Spectrum)")
2282
2283            self.client.send("setInputVector(Vector In One,"+V1.handle+")")
2284            self.client.send("setInputVector(Vector In Two,"+V2.handle+")")
2285
2286            if isinstance(fft_size, Scalar):
2287                self.client.send("setInputScalar(Scalar In FFT,"+fft_size.handle+")")
2288            else:
2289                tmpscalar = self.client.new_generated_scalar(fft_size)
2290                self.client.send("setInputScalar(Scalar In FFT,"+tmpscalar.handle+")")
2291
2292            if isinstance(sample_rate, Scalar):
2293                self.client.send("setInputScalar(Scalar In Sample Rate,"+sample_rate.handle+")")
2294            else:
2295                tmpscalar2 = self.client.new_generated_scalar(sample_rate)
2296                self.client.send("setInputScalar(Scalar In Sample Rate,"+tmpscalar2.handle+")")
2297
2298            self.handle = self.client.send("endEdit()")
2299            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2300            self.set_name(name)
2301        else:
2302            self.handle = name
2303
2304    def x(self):
2305        """ a vector containing the frequency bins of the fft  """
2306        vec = VectorBase(self.client)
2307        vec.handle = self.client.send_si(self.handle, "outputVector(Frequency)")
2308        return vec
2309
2310
2311    def y(self):
2312        """ a vector containing the real part if the cross spectrum  """
2313        vec = VectorBase(self.client)
2314        vec.handle = self.client.send_si(self.handle, "outputVector(Real)")
2315        return vec
2316
2317    def yi(self):
2318        """ a vector containing the imaginary part if the cross spectrum  """
2319        vec = VectorBase(self.client)
2320        vec.handle = self.client.send_si(self.handle, "outputVector(Imaginary)")
2321        return vec
2322
2323# FILTER ################################################################
2324class Filter(Object):
2325    """ This is a class which provides some methods common to all filters """
2326    def __init__(self, client):
2327        Object.__init__(self, client)
2328
2329    def output(self):
2330        """ a vector containing the output of the filter  """
2331        vec = VectorBase(self.client)
2332        vec.handle = self.client.send_si(self.handle, "outputVector(Y)")
2333        return vec
2334
2335# SUM FILTER ############################################################
2336class SumFilter(Filter):
2337    """ a cumulative sum filter inside kst
2338
2339    The output is the cumulative sum of the input vector
2340    """
2341    def __init__(self, client, yvector, step_dX, name="", new=True):
2342        Filter.__init__(self, client)
2343
2344        if new:
2345            self.client.send("newPlugin(Cumulative Sum)")
2346            self.client.send("setInputVector(Vector In,"+yvector.handle+")")
2347            self.client.send("setInputScalar(Scale Scalar,"+step_dX.handle+")")
2348            self.handle = self.client.send("endEdit()")
2349            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2350            self.set_name(name)
2351        else:
2352            self.handle = name
2353
2354    def output_sum(self):
2355        """ a vector containing the output of the filter  """
2356        vec = VectorBase(self.client)
2357        vec.handle = self.client.send_si(self.handle, "outputVector(sum(Y)dX)")
2358        return vec
2359
2360
2361# FLAG FILTER ############################################################
2362class FlagFilter(Filter):
2363    """ a flagged vector inside kst
2364
2365    The output is the input when flag == 0, or NaN if flag is non-0.
2366    """
2367    def __init__(self, client, yvector, flag, mask="0xffffff", valid_is_zero=True,
2368                 name="", new=True):
2369        Filter.__init__(self, client)
2370
2371        if new:
2372            self.client.send("newPlugin(Flag Filter)")
2373
2374            self.client.send("setInputVector(Y Vector,"+yvector.handle+")")
2375            self.client.send("setInputVector(Flag Vector,"+flag.handle+")")
2376            self.client.send("setProperty(Mask,"+mask+")")
2377            if valid_is_zero:
2378                self.client.send("setProperty(ValidIsZero,true)")
2379            else:
2380                self.client.send("setProperty(ValidIsZero,false)")
2381
2382            self.handle = self.client.send("endEdit()")
2383            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2384            self.set_name(name)
2385        else:
2386            self.handle = name
2387
2388
2389# FIT ###################################################################
2390class Fit(Object):
2391    """ This is a class which provides some methods common to all fits """
2392    def __init__(self, client):
2393        Object.__init__(self, client)
2394
2395    def parameters(self):
2396        """ a vector containing the Parameters of the fit  """
2397        vec = VectorBase(self.client)
2398        vec.handle = self.client.send_si(self.handle, "outputVector(Parameters Vector)")
2399        return vec
2400
2401    def fit(self):
2402        """ a vector containing the fit  """
2403        vec = VectorBase(self.client)
2404        vec.handle = self.client.send_si(self.handle, "outputVector(Fit)")
2405        return vec
2406
2407    def residuals(self):
2408        """ a vector containing the Parameters of the fit  """
2409        vec = VectorBase(self.client)
2410        vec.handle = self.client.send_si(self.handle, "outputVector(Residuals)")
2411        return vec
2412
2413    def covariance(self):
2414        """ a vector containing the Covariance of the fit  """
2415        vec = VectorBase(self.client)
2416        vec.handle = self.client.send_si(self.handle, "outputVector(Covariance)")
2417        return vec
2418
2419    def reduced_chi2(self):
2420        """ a scalar containing the Parameters of the fit  """
2421        X = Scalar(self.client)
2422        X.handle = self.client.send_si(self.handle, "outputScalar(chi^2/nu)")
2423        return X
2424
2425
2426# LINEAR FIT ############################################################
2427class LinearFit(Fit):
2428    """ A linear fit inside kst.
2429
2430    If weightvector is 0, then the fit is unweighted.
2431    """
2432    def __init__(self, client, xvector, yvector, weightvector=0, name="", new=True):
2433        Fit.__init__(self, client)
2434
2435        if new:
2436            if weightvector == 0:
2437                self.client.send("newPlugin(Linear Fit)")
2438            else:
2439                self.client.send("newPlugin(Linear Weighted Fit)")
2440                self.client.send("setInputVector(Weights Vector,"+weightvector.handle+")")
2441
2442            self.client.send("setInputVector(X Vector,"+xvector.handle+")")
2443            self.client.send("setInputVector(Y Vector,"+yvector.handle+")")
2444            self.handle = self.client.send("endEdit()")
2445            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2446            self.set_name(name)
2447        else:
2448            self.handle = name
2449
2450    def slope(self):
2451        """ The slope of the fit.  """
2452        vec = VectorBase(self.client)
2453        vec.handle = self.client.send_si(self.handle, "outputVector(Parameters Vector)")
2454        return vec.value(1)
2455
2456    def intercept(self):
2457        """ The intercept of the fit.  """
2458        vec = VectorBase(self.client)
2459        vec.handle = self.client.send_si(self.handle, "outputVector(Parameters Vector)")
2460        return vec.value(0)
2461
2462# POLYNOMIAL FIT ############################################################
2463class PolynomialFit(Fit):
2464    """ A Polynomial fit inside kst.
2465
2466       :param order: The order of the fit
2467    """
2468    def __init__(self, client, order, xvector, yvector, weightvector=0, name="", new=True):
2469        Fit.__init__(self, client)
2470
2471        if new:
2472            if weightvector == 0:
2473                self.client.send("newPlugin(Polynomial Fit)")
2474            else:
2475                self.client.send("newPlugin(Polynomial Weighted Fit)")
2476                self.client.send("setInputVector(Weights Vector,"+weightvector.handle+")")
2477
2478            self.client.send("setInputVector(X Vector,"+xvector.handle+")")
2479            self.client.send("setInputVector(Y Vector,"+yvector.handle+")")
2480            self.client.send("setInputScalar(Order Scalar,"+order.handle+")")
2481            self.handle = self.client.send("endEdit()")
2482            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2483            self.set_name(name)
2484        else:
2485            self.handle = name
2486
2487
2488
2489# View Items ################################################################
2490class ViewItem(NamedObject):
2491    """ Convenience class. You should not use it directly."""
2492    def __init__(self, client):
2493        NamedObject.__init__(self, client)
2494        #self.client = client
2495
2496    def set_h_margin(self, margin):
2497        self.client.send_si(self.handle,
2498                            "setLayoutHorizontalMargin("+b2str(margin)+")")
2499
2500    def set_v_margin(self, margin):
2501        self.client.send_si(self.handle,
2502                            "setLayoutVerticalMargin("+b2str(margin)+")")
2503
2504    def set_h_space(self, space):
2505        self.client.send_si(self.handle,
2506                            "setLayoutHorizontalSpacing("+b2str(space)+")")
2507
2508    def set_v_space(self, space):
2509        self.client.send_si(self.handle,
2510                            "setLayoutVerticalSpacing("+b2str(space)+")")
2511
2512    def set_fill_color(self, color):
2513        """ Set the fill/background color.
2514
2515        Colors are given by a name such as ``red`` or a hex number such
2516        as ``#FF0000``.
2517
2518        """
2519        self.client.send_si(self.handle, b2str("setFillColor("+b2str(color)+")"))
2520
2521    def set_fill_style(self, style):
2522        """ Set the background fill style.
2523
2524        This is equivalent to setting the index of Apperance>Fill>Style within
2525        a view item dialog in kst.::
2526
2527         0:  NoBrush          1:  SolidPattern
2528         2:  Dense1Pattern    3:  Dense2Pattern
2529         4:  Dense3Pattern    5:  Dense4Pattern
2530         6:  Dense5Pattern    7:  Dense6Pattern
2531         8:  Dense7Pattern    9:  HorPattern
2532         11: VerPattern       12: CrossPattern,
2533         13: BDiagPattern     14: FDiagPattern.
2534
2535        """
2536        self.client.send_si(self.handle,
2537                            "setIndexOfFillStyle("+b2str(style)+")")
2538
2539    def set_stroke_style(self, style):
2540        """ Set the stroke style of lines for the item.
2541
2542        This is equivalent to setting the index of Apperance>Stroke>Style
2543        within a view item dialog in kst::
2544
2545         0: SolidLine       1: DashLine
2546         2: DotLine         3: DashDotLine
2547         4: DashDotDotLine  5: CustomDashLine
2548
2549        """
2550        self.client.send_si(self.handle, "setIndexOfStrokeStyle("+b2str(style)+")")
2551
2552    def set_stroke_width(self, width):
2553        """ Set the width of lines for the item. """
2554        self.client.send_si(self.handle, "setStrokeWidth("+b2str(width)+")")
2555
2556    def set_stroke_brush_color(self, color):
2557        """ Set the color for lines for the item.
2558
2559        Colors are given by a name such as ``red`` or a hex number
2560        such as ``#FF0000``.
2561        """
2562        self.client.send_si(self.handle, "setStrokeBrushColor("+b2str(color)+")")
2563
2564    def set_stroke_brush_style(self, style):
2565        """ Set the brush style for lines for the item.
2566
2567        This is equivalent to setting the index of Apperance>Stroke>Brush Style
2568        within a view item dialog in kst.
2569
2570        This sets the brush type for lines in the item, and not for the fill,
2571        so values other than ``1`` (SolidPattern) only make sense for wide lines
2572        and are rarely used::
2573
2574         0:  NoBrush          1:  SolidPattern
2575         2:  Dense1Pattern    3:  Dense2Pattern
2576         4:  Dense3Pattern    5:  Dense4Pattern
2577         6:  Dense5Pattern    7:  Dense6Pattern
2578         8:  Dense7Pattern    9:  HorPattern
2579         11: VerPattern       12: CrossPattern,
2580         13: BDiagPattern     14: FDiagPattern.
2581
2582        """
2583        self.client.send_si(self.handle,
2584                            "setIndexOfStrokeBrushStyle("+b2str(style)+")")
2585
2586    def set_stroke_join_style(self, style):
2587        """ Set the style by which lines are joined in the item.
2588
2589        This is equivalent to setting the index of Apperance>Stroke>Join Style
2590        within a view item dialog in kst.
2591
2592        0 is MiterJoin, 1 is BevelJoin, 2 is RoundJoin,
2593        and 3 is SvgMiterJoin.
2594        """
2595        self.client.send_si(self.handle,
2596                            "setIndexOfStrokeJoinStyle("+b2str(style)+")")
2597
2598    def set_stroke_cap_style(self, style):
2599        """ Set the cap style for the ends of lines in the item.
2600
2601        This is equivalent to setting the index of Apperance>Stroke>Cap Style
2602        within a view item dialog in kst.
2603
2604        0 is FlatCap, 1 is SquareCap, and 2 is RoundCap.
2605        """
2606        self.client.send_si(self.handle,
2607                            "setIndexOfStrokeCapStyle("+b2str(style)+")")
2608
2609    def set_fixed_aspect_ratio(self, fixed=True):
2610        """ if True, fix the aspect ratio of the item to its current value.
2611
2612        This is equivalent to checking Dimensions>Fix aspect ratio within a
2613        view item dialog in kst.
2614        """
2615        if fixed:
2616            self.client.send_si(self.handle, b2str("lockAspectRatio(True)"))
2617        else:
2618            self.client.send_si(self.handle, b2str("lockAspectRatio(False)"))
2619
2620    def position(self):
2621        return_message = str(self.client.send_si(self.handle, "position()"))
2622
2623        ret = literal_eval(return_message)
2624
2625        return ret
2626
2627    def dimensions(self):
2628        return_message = str(self.client.send_si(self.handle, "dimensions()"))
2629
2630        ret = literal_eval(return_message)
2631
2632        return ret
2633
2634    def set_pos(self, pos):
2635        """ Set the center position of the item.
2636
2637        :param pos: a 2 element tuple ``(x, y)`` specifying the position.
2638                    The Top Left of the parent is (0, 0).
2639                    The Bottom Right of the parent is (1, 1)
2640
2641        """
2642        x, y = pos
2643
2644        self.client.send("beginEdit("+self.handle+")")
2645        self.client.send("setPos("+b2str(x)+","+b2str(y)+")")
2646        #self.client.send("setPosX("+b2str(x)+")")
2647        #self.client.send("setPosY("+b2str(y)+")")
2648        self.client.send("endEdit()")
2649
2650    def set_size(self, size):
2651        """ Set the size of the item.
2652
2653        :param size: a 2 element tuple ``(w, h)`` specifying the size.
2654
2655        Elements go from 0 to 1.  If the aspect ratio is fixed, then ``h``
2656        is ignored.
2657
2658        This is equivalent to setting Dimensions>Position within a view
2659        item dialog in kst.
2660
2661        """
2662        w, h = size
2663        self.client.send("beginEdit("+self.handle+")")
2664        self.client.send("setSize("+b2str(w)+","+b2str(h)+")")
2665        self.client.send("endEdit()")
2666
2667    def set_lock_pos_to_data(self, lock=True):
2668        """
2669        if lock is True, and the item is in a plot, then the position of the item
2670        will be locked to the data coordinates in the plot.  The item will move with
2671        zooming and scrolling.
2672
2673        If lock is False, or the item is not in a plot, then the item will be fixed
2674        to the geometry of the window, and zooming/scrolling will not change its
2675        position.
2676
2677        """
2678        if lock:
2679            self.client.send_si(self.handle, "setLockPosToData(True)")
2680        else:
2681            self.client.send_si(self.handle, "setLockPosToData(False)")
2682
2683    def set_parent_auto(self):
2684        """
2685        Set the parent of the viewitem to an existing view item which fully contains it.
2686        Once reparented, moving/resizing the parent will also move/resize the child.
2687
2688        By default view items created by pyKst are parented by the toplevel view unless
2689        this method is called, or if the item is moved/resized in the GUI.
2690        """
2691
2692        self.client.send_si(self.handle, "updateParent()")
2693
2694    def set_parent_toplevel(self):
2695        """
2696        Set the parent of the viewitem to the toplevel view.
2697
2698        By default view items created by pyKst are parented by the toplevel view unless
2699        set_parent_auto() is called, or if the item is moved/resized in the GUI.
2700        """
2701
2702        self.client.send_si(self.handle, "parentTopLevel()")
2703
2704    def subplot(self, *args):
2705        """
2706        Set the item position according to the given grid definition.
2707
2708        Typical call signature::
2709
2710          subplot(nrows, ncols, plot_number)
2711
2712        Where *nrows* and *ncols* are used to notionally split the figure
2713        into ``nrows * ncols`` sub-axes, and *plot_number* is used to identify
2714        the particular subplot that this function is to create within the notional
2715        grid. *plot_number* starts at 1, increments across rows first and has a
2716        maximum of ``nrows * ncols``.
2717
2718        In the case when *nrows*, *ncols* and *plot_number* are all less than 10,
2719        a convenience exists, such that the a 3 digit number can be given instead,
2720        where the hundreds represent *nrows*, the tens represent *ncols* and the
2721        units represent *plot_number*. For instance::
2722
2723          subplot(211)
2724
2725        place the plot in the top grid location (i.e. the
2726        first) in a 2 row by 1 column notional grid (no grid actually exists,
2727        but conceptually this is how the returned subplot has been positioned).
2728
2729
2730        """
2731
2732        w = 0
2733        h = 0
2734        x = 0
2735        y = 0
2736        n = 0
2737
2738        if len(args) == 1:
2739            h = args[0]/100
2740            w = (args[0]%100)/10
2741            n = args[0]%10
2742        elif len(args) == 3:
2743            h = args[0]
2744            w = args[1]
2745            n = args[2]
2746        else:
2747            w = h = n = 1
2748
2749        x = (n-1)%w
2750        y = (n-1)/w
2751
2752        size = (1.0/w, 1.0/h)
2753        pos = (x/float(w)+0.5/w, y/float(h)+0.5/h)
2754
2755        self.set_pos(pos)
2756        self.set_size(size)
2757
2758    def set_rotation(self, rot):
2759        """ Set the rotation of the item.
2760
2761        This is equivalent to setting Dimensions>Rotation within a view item dialog.
2762
2763        """
2764        self.client.send_si(self.handle, b2str("setRotation("+b2str(rot)+")"))
2765
2766    def remove(self):
2767        """ This removes the object from Kst. """
2768        self.client.send("eliminate("+self.handle+")")
2769
2770
2771# LABELS ######################################################################
2772class Label(ViewItem):
2773    r"""
2774    A label inside kst.
2775
2776    :param text: the text of the label.  Supports scalars, equations, and a
2777                 LaTeX subset.
2778    :param pos: a 2 element tuple ``(x, y)`` specifying the position.
2779                (0, 0) is top left.  (1, 1) is bottom right.
2780    :param rot: rotation of the label in degrees.
2781    :param font_size: size of the label in points, when the printed at the
2782                     reference size.
2783    :param font_color: Colors are given by a name such as ``red`` or a
2784                      hex number such as ``#FF0000``.
2785    :param font_family: The font family.  eg, TimeNewRoman.
2786
2787    Scalars and scalar equations can be displayed live in labels.
2788    When the scalar is updated, the label is updated.
2789
2790
2791    The format is::
2792
2793        Scalar:         [scalarname]         eg [GYRO1:Mean(X4)]
2794        Vector Element: [vectorName[index]]  eg [GYRO1 (V2)[4]]
2795        Equation:       [=equation]          eg [=[GYRO1:Mean(X4)]/[GYRO1:Sigma (X4)]]
2796
2797
2798    These numerical fields can be formatted by appending a C printf format embedded
2799    in { } immediately after the field. For example::
2800
2801        [GYRO1:Mean(X4)]{%4.2f}
2802
2803    Labels in kst support a derrivitive subset of LaTeX. For example, to display
2804    the equation for the area of a circle, you could set the label to ``A=2\pir^2``.
2805    Unlike LaTeX, it is not necessary to enter math mode using ``$``. Also,
2806    unlike LaTeX, variables are not automatically displayed in italic font.
2807    If desired, this must be done explicitly using ``\\textit{}``.
2808
2809    Greek letters: \\\\name or \\\\Name. eg: ``\\alpha``
2810
2811    Other symbols: ``\\approx, \\cdot, \\ge, \\geq, \\inf, \\approx, \\cdot,
2812    \\ge, \\geq, \\inf, \\int, \\le, \\leq, \\ne, \\n, \\partial, \\prod, \\pm,
2813    \\sum, \\sqrt``
2814
2815    Font effects: ``\\textcolor{colorname}{colored text}, \\textbf{bold text},
2816    \\textit{italicized text}, \\underline{underlined text},
2817    \\overline{overlined text}.``
2818
2819    Other:``x^y``, ``x_y``, ``\\t``, ``\\n``, ``\\[``
2820
2821    This class represents a label you would create via "Create>Annotations>Label"
2822    from the menubar inside kst.
2823
2824    Use the convenience function in Client to create a label "Test Label" in kst::
2825
2826      import pykst as kst
2827      client = kst.Client()
2828      L = client.new_label("Test Label", (0.25, 0.25), font_size=18)
2829
2830    """
2831    def __init__(self, client, text, pos=(0.5, 0.5), rot=0, font_size=12,
2832                 bold=False, italic=False, font_color="black",
2833                 font_family="Serif", name="", new=True):
2834        ViewItem.__init__(self, client)
2835
2836        if new:
2837            self.client.send("newLabel()")
2838            self.handle = self.client.send("endEdit()")
2839            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2840
2841            self.set_text(text)
2842            self.set_label_font_size(font_size)
2843            self.set_pos(pos)
2844            self.set_fixed_aspect_ratio(True)
2845            self.set_rotation(rot)
2846            self.set_font_color(font_color)
2847            self.set_font_family(font_family)
2848
2849            self.set_font_bold(bold)
2850            self.set_font_italic(italic)
2851            self.set_name(name)
2852        else:
2853            self.handle = name
2854
2855    def set_text(self, text):
2856        r""" Set text displayed by the label.
2857
2858        Scalars and scalar equations can be displayed live in labels.
2859        When the scalar is updated, the label is updated.
2860        The format is::
2861
2862          Scalar:         [scalarname]         eg [GYRO1:Mean(X4)]
2863          Vector Element: [vectorName[index]]  eg [GYRO1 (V2)[4]]
2864          Equation:       [=equation]          eg [=[GYRO1:Mean(X4)]/[GYRO1:Sigma (X4)]]
2865
2866        Labels in kst support a derrivitive subset of LaTeX. For example,
2867        to display the equation for the area of a circle, you could set the
2868        label to ``A=2\pir^2``. Unlike LaTeX, it is not necessary to enter
2869        math mode using ``$``. Also, unlike LaTeX, variables are not
2870        automatically displayed in italic font.  If desired, this must be done
2871        explicitly using ``\\textit{}``.
2872
2873        Greek letters: \\\\name or \\\\Name. eg: ``\\alpha``
2874
2875        Other symbols: ``\\approx, \\cdot, \\ge, \\geq, \\inf, \\approx, \\cdot,
2876        \\ge, \\geq, \\inf, \\int, \\le, \\leq, \\ne, \\n, \\partial, \\prod, \\pm,
2877        \\sum, \\sqrt``
2878
2879        Font effects: ``\\textcolor{colorname}{colored text}, \\textbf{bold text},
2880        \\textit{italicized text}, \\underline{underlined text},
2881        \\overline{overlined text}.``
2882
2883        Other:``x^y``, ``x_y``, ``\\t``, ``\\n``, ``\\[``
2884        """
2885        self.client.send_si(self.handle, b2str("setLabel("+b2str(text)+")"))
2886
2887    def set_label_font_size(self, size):
2888        """ size of the label in points, when the printed at the reference size."""
2889        self.client.send_si(self.handle, b2str("setFontSize("+b2str(size)+")"))
2890
2891    def set_font_bold(self, bold=True):
2892        """ . . . """
2893        if bold:
2894            self.client.send_si(self.handle, b2str("checkLabelBold()"))
2895        else:
2896            self.client.send_si(self.handle, b2str("uncheckLabelBold()"))
2897
2898    def set_font_italic(self, italic=True):
2899        """ . . . """
2900        if italic:
2901            self.client.send_si(self.handle, b2str("checkLabelItalic()"))
2902        else:
2903            self.client.send_si(self.handle, b2str("uncheckLabelItalic()"))
2904
2905    def set_font_color(self, color):
2906        """ Colors are given by a name such as ``red`` or a hex number such
2907        as ``#FF0000`` """
2908        self.client.send_si(self.handle, b2str("setLabelColor("+b2str(color)+")"))
2909
2910    def set_font_family(self, family):
2911        """ set the font family.  eg, TimeNewRoman. """
2912        self.client.send_si(self.handle, b2str("setFontFamily("+b2str(family)+")"))
2913
2914
2915class Legend(ViewItem):
2916    """ A legend in a plot in kst.
2917
2918    : param plot: a plot in kst.
2919    Use the convenience function in Client to create a legend in kst::
2920
2921      import pykst as kst
2922      client = kst.Client()
2923     ...
2924      P1 = client.new_plot()
2925      L1 = client.new_legend(P1)
2926
2927    """
2928    def __init__(self, client, plot, name="", new=True):
2929        ViewItem.__init__(self, client)
2930
2931        if new:
2932            self.client.send("newLegend("+plot.name()+")")
2933            self.handle = self.client.send("endEdit()")
2934            self.handle.remove(0, self.handle.indexOf("ing ")+4)
2935        else:
2936            self.handle = name
2937
2938    def set_font_size(self, size):
2939        """ size of the label in points, when the printed at the reference size."""
2940        self.client.send_si(self.handle, b2str("setFontSize("+b2str(size)+")"))
2941
2942    def set_font_bold(self, bold=True):
2943        """ . . . """
2944        if bold:
2945            self.client.send_si(self.handle, b2str("checkLabelBold()"))
2946        else:
2947            self.client.send_si(self.handle, b2str("uncheckLabelBold()"))
2948
2949    def set_font_italic(self, italic=True):
2950        """ . . . """
2951        if italic:
2952            self.client.send_si(self.handle, b2str("checkLabelItalic()"))
2953        else:
2954            self.client.send_si(self.handle, b2str("uncheckLabelItalic()"))
2955
2956    def set_font_color(self, color):
2957        """ Colors are given by a name such as ``red`` or a hex number such
2958        as ``#FF0000`` """
2959        self.client.send_si(self.handle, b2str("setLegendColor("+b2str(color)+")"))
2960
2961    def set_font_family(self, family):
2962        """ set the font family.  eg, TimeNewRoman. """
2963        self.client.send_si(self.handle, b2str("setFontFamily("+b2str(family)+")"))
2964
2965
2966class Box(ViewItem):
2967    """ A floating box inside kst.
2968
2969    :param pos: a 2 element tuple ``(x, y)`` specifying the position.
2970                ``(0, 0)`` is top left.  ``(1, 1)`` is bottom right.
2971    :param size: a 2 element tuple ``(w, h)`` specifying the size.
2972                ``(1, 1)`` is the size of the window.
2973    :param rotation: rotation of the label in degrees.
2974    :param fill_color: the background color.
2975    :param fill_style: the background fill style.  See set_fill_style.
2976    :param stroke_style: see set_stroke_style
2977    :param stroke_width: the pen width for the box outline.
2978    :param stroke_brush_color: the box outline color
2979    :param stroke_brush_style: see set_stroke_brush_style
2980    :param stroke_join_style: see set_stroke_join_style
2981    :param stroke_cap_style: see set_stroke_cap_style
2982    :param fix_aspect: if true, the box will have a fixed aspect ratio.
2983
2984    Colors are given by a name such as ``red`` or a hex number such
2985    as ``#FF0000``.
2986
2987    This class represents a box you would create via "Create>Annotations>Box"
2988    from the menubar inside kst.
2989
2990    Use the convenience function in Client to create a box in kst::
2991
2992      import pykst as kst
2993      client = kst.Client()
2994      ...
2995      B = client.new_box((0.25, 0.25), (0.2, 0.1), fill_color="blue")
2996
2997    """
2998    def __init__(self, client, pos=(0.1, 0.1), size=(0.1, 0.1), rot=0,
2999                 fill_color="white", fill_style=1, stroke_style=1, stroke_width=1,
3000                 stroke_brush_color="black", stroke_brush_style=1,
3001                 stroke_join_style=1, stroke_cap_style=1, fix_aspect=False,
3002                 name="", new=True):
3003        ViewItem.__init__(self, client)
3004
3005        if new:
3006            self.client.send("newBox()")
3007            self.handle = self.client.send("endEdit()")
3008            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3009
3010            self.set_pos(pos)
3011            self.set_size(size)
3012
3013            self.set_fixed_aspect_ratio(fix_aspect)
3014            self.set_rotation(rot)
3015
3016            self.set_stroke_brush_color(stroke_brush_color)
3017            self.set_fill_color(fill_color)
3018            self.set_fill_style(fill_style)
3019            self.set_stroke_style(stroke_style)
3020            self.set_stroke_width(stroke_width)
3021            self.set_stroke_brush_color(stroke_brush_color)
3022            self.set_stroke_brush_style(stroke_brush_style)
3023            self.set_stroke_join_style(stroke_join_style)
3024            self.set_stroke_cap_style(stroke_cap_style)
3025            self.set_name(name)
3026        else:
3027            self.handle = name
3028
3029
3030class Circle(ViewItem):
3031    """ A floating circle inside kst.
3032
3033    :param pos: a 2 element tuple ``(x, y)`` specifying the position.
3034                ``(0, 0)`` is top left.  ``(1, 1)`` is bottom right.
3035    :param diameter: the diameter of the circle.  1 is the width of the window.
3036    :param fill_color: the background color.
3037    :param fill_style: the background fill style.  See set_fill_style.
3038    :param stroke_style: see set_stroke_style
3039    :param stroke_width: the pen width for the circle outline.
3040    :param stroke_brush_color: the circle outline color
3041    :param stroke_brush_style: see set_stroke_brush_style
3042
3043    Colors are given by a name such as ``red`` or a hex number such
3044    as ``#FF0000``.
3045
3046    This class represents a circle you would create via
3047    "Create>Annotations>Circle" from the menubar inside kst.
3048
3049    Use the convenience function in Client to create a circle in kst::
3050
3051      import pykst as kst
3052      client = kst.Client()
3053      ...
3054      Cr = client.new_circle((0.5, 0.5), 0.2, fill_color="red")
3055
3056    """
3057    def __init__(self, client, pos=(0.1, 0.1), diameter=0.1,
3058                 fill_color="white", fill_style=1, stroke_style=1,
3059                 stroke_width=1, stroke_brush_color="grey", stroke_brush_style=1,
3060                 name="", new=True):
3061        ViewItem.__init__(self, client)
3062
3063        if new:
3064            self.client.send("newCircle()")
3065            self.handle = self.client.send("endEdit()")
3066            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3067
3068            self.set_pos(pos)
3069            self.set_diameter(diameter)
3070
3071            self.set_stroke_brush_color(stroke_brush_color)
3072            self.set_fill_color(fill_color)
3073            self.set_fill_style(fill_style)
3074            self.set_stroke_style(stroke_style)
3075            self.set_stroke_width(stroke_width)
3076            self.set_stroke_brush_color(stroke_brush_color)
3077            self.set_stroke_brush_style(stroke_brush_style)
3078            self.set_name(name)
3079        else:
3080            self.handle = name
3081
3082
3083    def set_diameter(self, diameter):
3084        """ set the diamter of the circle.
3085
3086        The width of the window is 1.0.
3087        """
3088        self.client.send_si(self.handle, "setSize("+b2str(diameter)+","+b2str(diameter)+")")
3089
3090class Ellipse(ViewItem):
3091    """ A floating ellipse inside kst.
3092
3093    :param pos: a 2 element tuple ``(x, y)`` specifying the position.
3094                ``(0, 0)`` is top left.  ``(1, 1)`` is bottom right.
3095    :param size: a 2 element tuple ``(w, h)`` specifying the size.
3096                ``(1, 1)`` is the size of the window.
3097    :param fill_color: the background color.
3098    :param fill_style: the background fill style.  See set_fill_style.
3099    :param stroke_style: see set_stroke_style
3100    :param stroke_width: the pen width for the ellipse outline.
3101    :param stroke_brush_color: the ellipse outline color
3102    :param stroke_brush_style: see set_stroke_brush_style
3103
3104    Colors are given by a name such as ``red`` or a hex number such
3105    as ``#FF0000``.
3106
3107    This class represents an ellipse you would create via
3108    "Create>Annotations>Ellipse" from the menubar inside kst.
3109
3110    Use the convenience function in Client to create an Ellipse in kst::
3111
3112      import pykst as kst
3113      client = kst.Client()
3114      ...
3115      E = client.new_ellipse((0.25, 0.25), (0.2, 0.1), fill_color="green")
3116
3117    """
3118    def __init__(self, client, pos=(0.1, 0.1), size=(0.1, 0.1),
3119                 rot=0, fill_color="white", fill_style=1, stroke_style=1,
3120                 stroke_width=1, stroke_brush_color="black", stroke_brush_style=1,
3121                 fix_aspect=False, name="", new=True):
3122        ViewItem.__init__(self, client)
3123
3124        if new:
3125            self.client.send("newEllipse()")
3126            self.handle = self.client.send("endEdit()")
3127            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3128
3129            self.set_pos(pos)
3130            self.set_size(size)
3131            if fix_aspect:
3132                self.set_fixed_aspect_ratio(True)
3133            else:
3134                self.set_fixed_aspect_ratio(False)
3135
3136            self.set_rotation(rot)
3137
3138            self.set_stroke_brush_color(stroke_brush_color)
3139            self.set_fill_color(fill_color)
3140            self.set_fill_style(fill_style)
3141            self.set_stroke_style(stroke_style)
3142            self.set_stroke_width(stroke_width)
3143            self.set_stroke_brush_color(stroke_brush_color)
3144            self.set_stroke_brush_style(stroke_brush_style)
3145            self.set_name(name)
3146        else:
3147            self.handle = name
3148
3149
3150class Line(ViewItem):
3151    """ A floating line inside kst.
3152
3153    :param start: a 2 element tuple ``(x, y)`` specifying the position of the
3154                  start of the line.
3155                  ``(0, 0)`` is top left of the window, and ``(1, 1)`` is bottom right.
3156    :param end: a 2 element tuple ``(x, y)`` specifying the position of the
3157                end of the line.
3158                ``(0, 0)`` is top left of the window, and ``(1, 1)`` is bottom right.
3159    :param length: The length of the line.  1 is the width of the window.
3160    :param rot: rotation of the line in degrees.
3161    :param stroke_style: see set_stroke_style
3162    :param stroke_width: the pen width for the ellipse outline.
3163    :param stroke_brush_color: the ellipse outline color
3164    :param stroke_brush_style: see set_stroke_brush_style
3165    :param stroke_cap_style: see set_stroke_cap_style
3166
3167    Colors are given by a name such as ``red`` or a hex number such
3168    as ``#FF0000``.
3169
3170    This class represents a line you would create via "Create>Annotations>Line"
3171    from the menubar inside kst.
3172
3173    Colors are given by a name such as ``red`` or a hex number such as ``#FF0000``".
3174
3175    Use the convenience function in Client to create a line in kst::
3176
3177      import pykst as kst
3178      client = kst.Client()
3179      ...
3180      Ln = client.new_line((0.25, 0.25), (0.5, 0.5))
3181
3182    """
3183    def __init__(self, client, start=(0, 0), end=(1, 1),
3184                 stroke_style=1, stroke_width=1, stroke_brush_color="black",
3185                 stroke_brush_style=1, stroke_cap_style=1, name="", new=True):
3186        ViewItem.__init__(self, client)
3187
3188        if new:
3189            self.client.send("newLine()")
3190            self.handle = self.client.send("endEdit()")
3191
3192            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3193
3194            self.set_endpoints(start, end)
3195
3196            self.set_stroke_brush_color(stroke_brush_color)
3197            self.set_stroke_style(stroke_style)
3198            self.set_stroke_width(stroke_width)
3199            self.set_stroke_brush_color(stroke_brush_color)
3200            self.set_stroke_brush_style(stroke_brush_style)
3201            self.set_stroke_cap_style(stroke_cap_style)
3202            self.set_name(name)
3203        else:
3204            self.handle = name
3205
3206
3207    def set_length(self, length):
3208        """ set the length of the line.
3209
3210        The length, between 0 and 1, is as a fraction of the width of the parent item.
3211        """
3212        self.client.send_si(self.handle, "setSize("+b2str(length)+","+b2str(length)+")")
3213
3214    def set_endpoints(self, start=(0, 0), end=(1, 1)):
3215        """ set the endpoints of the line.
3216
3217        If lock_pos_to_data has been set True, and the item parent is a plot, then
3218        the coordinates are in terms the data's coordinates.  Otherwise, the coordinates,
3219        between 0 and 1, are relative to the dimensions of the parent object.
3220        """
3221        x1, y1 = start
3222        x2, y2 = end
3223        self.client.send_si(self.handle, "setLineEndpoints("+b2str(x1)+","+b2str(y1)+","+
3224                            b2str(x2)+","+b2str(y2)+")")
3225
3226class Arrow(ViewItem):
3227    """ A floating arrow inside kst.
3228
3229    :param pos: a 2 element tuple ``(x, y)`` specifying the position of the
3230                center of the line.
3231                ``(0, 0)`` is top left.  ``(1, 1)`` is bottom right.
3232    :param length: The length of the line.  1 is the width of the window.
3233    :param rot: rotation of the line in degrees.
3234    :param arror_at_start: if True, draw an arrow at the start of the line.
3235    :param arrow_at_end: if True, draw an arrow at the end of the line.
3236    :param arrow_size: the size of the arrow.
3237    :param stroke_style: see set_stroke_style.
3238    :param stroke_width: the pen width for the ellipse outline.
3239    :param stroke_brush_color: the ellipse outline color
3240    :param stroke_brush_style: see set_stroke_brush_style
3241    :param stroke_cap_style: see set_stroke_cap_style
3242
3243    Colors are given by a name such as ``red`` or a hex number such
3244    as ``#FF0000``.
3245
3246    This class represents an arrow you would create via
3247    "Create>Annotations>Arrow" from the menubar inside kst.
3248
3249    Use the convenience function in Client to create an arrow in kst::
3250
3251      import pykst as kst
3252      client = kst.Client()
3253      ...
3254      Ln = client.new_arrow((0.25, 0.25), 0.2, rot=15, arror_at_start=True)
3255
3256    """
3257    def __init__(self, client, start=(0, 0), end=(1, 1),
3258                 arror_at_start=False, arrow_at_end=True, arrow_size=12.0,
3259                 stroke_style=1, stroke_width=1, stroke_brush_color="black",
3260                 stroke_brush_style=1, stroke_cap_style=1, name="", new=True):
3261        ViewItem.__init__(self, client)
3262
3263        if new:
3264            self.client.send("newArrow()")
3265            self.handle = self.client.send("endEdit()")
3266            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3267
3268            self.set_endpoints(start, end)
3269            #self.set_pos(pos)
3270            #self.set_length(length)
3271            #self.set_rotation(rot)
3272
3273            self.set_stroke_brush_color(stroke_brush_color)
3274            self.set_stroke_style(stroke_style)
3275            self.set_stroke_width(stroke_width)
3276            self.set_stroke_brush_color(stroke_brush_color)
3277            self.set_stroke_brush_style(stroke_brush_style)
3278            self.set_stroke_cap_style(stroke_cap_style)
3279            self.set_arrow_at_start(arror_at_start)
3280            self.set_arrow_at_end(arrow_at_end)
3281            self.set_arrow_size(arrow_size)
3282            self.set_name(name)
3283        else:
3284            self.handle = name
3285
3286    def set_arrow_at_start(self, arrow=True):
3287        """ Set whether an arrow head is shown at the start of the line """
3288        if arrow:
3289            self.client.send_si(self.handle, b2str("arrowAtStart(True)"))
3290        else:
3291            self.client.send_si(self.handle, b2str("arrowAtStart(False)"))
3292
3293    def set_arrow_at_end(self, arrow=True):
3294        """ Set whether an arrow head is shown at the end of the line """
3295        if arrow:
3296            self.client.send_si(self.handle, b2str("arrowAtEnd(True)"))
3297        else:
3298            self.client.send_si(self.handle, b2str("arrowAtEnd(False)"))
3299
3300    def set_arrow_size(self, arrow_size):
3301        self.client.send_si(self.handle, b2str("arrowHeadScale("+b2str(arrow_size)+")"))
3302
3303    def set_length(self, length):
3304        """ set the length of the line.
3305
3306        The width of the window is 1.0.
3307        """
3308        self.client.send_si(self.handle, "setSize("+b2str(length)+","+b2str(length)+")")
3309
3310    def set_endpoints(self, start=(0, 0), end=(1, 1)):
3311        """ set the endpoints of the arrow.
3312
3313        If lock_pos_to_data has been set True, and the item parent is a plot, then the
3314        coordinates are in terms the data's coordinates.  Otherwise, the coordinates,
3315        between 0 and 1, are relative to the dimensions of the parent object.
3316        """
3317        x1, y1 = start
3318        x2, y2 = end
3319        self.client.send_si(self.handle, "setLineEndpoints("+b2str(x1)+","+b2str(y1)+","+
3320                            b2str(x2)+","+b2str(y2)+")")
3321
3322
3323class Picture(ViewItem):
3324    """ A floating image inside kst.
3325
3326    :param filename: the file which holds the image to be shown.
3327    :param pos: a 2 element tuple ``(x, y)`` specifying the position of the
3328                center of the picture.
3329                ``(0, 0)`` is top left.  ``(1, 1)`` is bottom right.
3330    :param width: The width of the picture.  1 is the width of the window.
3331    :param rot: rotation of the picture in degrees.
3332
3333    This class represents a picture you would create via
3334    "Create>Annotations>Picture" from the menubar inside kst.
3335
3336    Use the convenience function in Client to create a picture in kst::
3337
3338      import pykst as kst
3339      client = kst.Client()
3340      ...
3341      pic = client.new_picture("image.jpg", (0.25, 0.25), 0.2)
3342
3343    BUG: the aspect ratio of the picture is wrong.
3344    """
3345    def __init__(self, client, filename, pos=(0.1, 0.1), width=0.1, rot=0,
3346                 name="", new=True):
3347        ViewItem.__init__(self, client)
3348
3349        if new:
3350            self.client.send("newPicture("+b2str(filename)+")")
3351            self.handle = self.client.send("endEdit()")
3352
3353            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3354
3355            self.set_pos(pos)
3356            self.set_width(width)
3357            self.set_fixed_aspect_ratio(True)
3358            self.set_rotation(rot)
3359            self.set_name(name)
3360        else:
3361            self.handle = name
3362
3363    def set_width(self, width):
3364        """ set the width of the picture.
3365
3366        The width of the window is 1.0.
3367        """
3368        self.client.send_si(self.handle, "setSize("+b2str(width)+")")
3369
3370
3371    def set_picture(self, pic):
3372        """ BUG: aspect ratio is not changed. There is no parellel for this
3373        function within the kst GUI. """
3374        self.client.send_si(self.handle, b2str("setPicture("+b2str(pic)+")"))
3375
3376
3377class SVG(ViewItem):
3378    """ A floating svg image inside kst.
3379
3380    :param filename: the file which holds the svg image to be shown.
3381    :param pos: a 2 element tuple ``(x, y)`` specifying the position of the
3382                center of the picture.
3383                ``(0, 0)`` is top left.  ``(1, 1)`` is bottom right.
3384    :param width: The width of the picture.  1 is the width of the window.
3385    :param rot: rotation of the picture in degrees.
3386
3387    This class represents a picture you would create via
3388    "Create>Annotations>SVG" from the menubar inside kst.
3389
3390    Use the convenience function in Client to create an SVG picture in kst::
3391
3392      import pykst as kst
3393      client = kst.Client()
3394      ...
3395      svg1 = client.new_SVG("image.svg", (0.25, 0.25), 0.2)
3396
3397    """
3398    def __init__(self, client, filename, pos=(0.1, 0.1), width=0.1, rot=0,
3399                 name="", new=True):
3400        ViewItem.__init__(self, client)
3401
3402        if new:
3403            self.client.send("newSvgItem("+b2str(filename)+")")
3404            self.handle = self.client.send("endEdit()")
3405
3406            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3407
3408            self.set_pos(pos)
3409            self.set_width(width)
3410            self.set_fixed_aspect_ratio(True)
3411            self.set_rotation(rot)
3412            self.set_name(name)
3413        else:
3414            self.handle = name
3415
3416    def set_width(self, width):
3417        """ set the width of the picture.
3418
3419        The width of the window is 1.0.
3420        """
3421        self.client.send_si(self.handle, "setSize("+b2str(width)+")")
3422
3423
3424class Plot(ViewItem):
3425    """ A plot inside kst.
3426
3427    :param pos: a 2 element tuple ``(x, y)`` specifying the position.
3428                ``(0, 0)`` is top left.  ``(1, 1)`` is bottom right.
3429    :param size: a 2 element tuple ``(w, h)`` specifying the size.
3430                ``(1, 1)`` is the size of the window.
3431    :param font_size: font size for labels in the plot.  kst default if 0.
3432    :param rotation: rotation of the label in degrees.
3433    :param columns: auto-place the plot, reformatting into this many columns.
3434    :param fill_color: the background color.
3435    :param fill_style: the background fill style.  See set_fill_style.
3436    :param stroke_style: see set_stroke_style
3437    :param stroke_width: the pen width for the plot outline.
3438    :param stroke_brush_color: the plot outline color
3439    :param stroke_brush_style: see set_stroke_brush_style
3440    :param stroke_join_style: see set_stroke_join_style
3441    :param stroke_cap_style: see set_stroke_cap_style
3442    :param fix_aspect: if true, the plot will have a fixed aspect ratio.
3443    :param auto_postion: if True (the default) the plot will be auto-placed.  Ignored if pos is set.
3444
3445    Colors are given by a name such as ``red`` or a hex number such
3446    as ``#FF0000``.
3447
3448    This class represents a Plot you would create via
3449    "Create>Annotations>Plot" from the menubar inside kst.
3450
3451    To create an plot in kst and plot a curve ``curve1``::
3452
3453      import pykst as kst
3454      client = kst.Client()
3455      ...
3456      P1 = client.new_plot((0.25, 0.25), (0.5, 0.5))
3457      P1.add(curve1)
3458
3459    """
3460    def __init__(self, client, pos=(0, 0), size=(0, 0), rot=0,
3461                 font_size=0,
3462                 columns=0,
3463                 fill_color="white", fill_style=1, stroke_style=1, stroke_width=1,
3464                 stroke_brush_color="black", stroke_brush_style=1,
3465                 stroke_join_style=1, stroke_cap_style=1, fix_aspect=False,
3466                 auto_position=True,
3467                 name="", new=True):
3468        ViewItem.__init__(self, client)
3469
3470        if size != (0, 0):
3471            auto_position = False
3472
3473        if new:
3474            self.client.send("newPlot()")
3475            if columns > 0:
3476                self.client.send("addToCurrentView(Columns,"+b2str(columns)+")")
3477            elif auto_position:
3478                self.client.send("addToCurrentView(Auto,2)")
3479            else:
3480                self.client.send("addToCurrentView(Protect,2)")
3481            self.handle = self.client.send("endEdit()")
3482
3483            self.handle.remove(0, self.handle.indexOf("ing ")+4)
3484            if size != (0, 0):
3485                self.set_size(size)
3486                self.set_pos(pos)
3487
3488            self.set_global_font(font_size=font_size)
3489            self.set_fixed_aspect_ratio(fix_aspect)
3490            self.set_rotation(rot)
3491
3492            self.set_stroke_brush_color(stroke_brush_color)
3493            self.set_fill_color(fill_color)
3494            self.set_fill_style(fill_style)
3495            self.set_stroke_style(stroke_style)
3496            self.set_stroke_width(stroke_width)
3497            self.set_stroke_brush_color(stroke_brush_color)
3498            self.set_stroke_brush_style(stroke_brush_style)
3499            self.set_stroke_join_style(stroke_join_style)
3500            self.set_stroke_cap_style(stroke_cap_style)
3501            self.set_name(name)
3502        else:
3503            self.handle = name
3504
3505
3506    def add(self, relation):
3507        """ Add a curve or an image to the plot. """
3508        self.client.send_si(self.handle, "addRelation(" + relation.handle + ")")
3509
3510    def set_x_range(self, x0, x1):
3511        """ Set X zoom range from x0 to x1 """
3512        self.client.send_si(self.handle, "setXRange("+b2str(x0)+","+b2str(x1)+")")
3513
3514    def set_y_range(self, y0, y1):
3515        """ Set Y zoom range from y0 to y1 """
3516        self.client.send_si(self.handle, "setYRange("+b2str(y0)+","+b2str(y1)+")")
3517
3518    def set_x_auto(self):
3519        """ Set X zoom range to autoscale """
3520        self.client.send_si(self.handle, "setXAuto()")
3521
3522    def set_y_auto(self):
3523        """ Set Y zoom range to autoscale """
3524        self.client.send_si(self.handle, "setPlotYAuto()")
3525
3526    def set_x_auto_border(self):
3527        """ Set X zoom range to autoscale with a small border """
3528        self.client.send_si(self.handle, "setPlotXAutoBorder()")
3529
3530    def set_y_auto_border(self):
3531        """ Set Y zoom range to autoscale with a small border """
3532        self.client.send_si(self.handle, "setYAutoBorder()")
3533
3534    def set_x_no_spike(self):
3535        """ Set X zoom range to spike insensitive autoscale """
3536        self.client.send_si(self.handle, "setXNoSpike()")
3537
3538    def set_y_no_spike(self):
3539        """ Set Y zoom range to spike insensitive autoscale """
3540        self.client.send_si(self.handle, "setYNoSpike()")
3541
3542    def set_x_ac(self, r):
3543        """ Set X zoom range to fixed range, centered around the mean.
3544
3545        Similar to AC coupling on an oscilloscope.
3546        """
3547        self.client.send_si(self.handle, "setXAC("+b2str(r)+")")
3548
3549    def set_y_ac(self, r):
3550        """ Set Y zoom range to fixed range, centered around the mean.
3551
3552        Similar to AC coupling on an oscilloscope.
3553        """
3554        self.client.send_si(self.handle, "setYAC("+b2str(r)+")")
3555
3556    def set_global_font(self, family="", font_size=0, bold=False, italic=False):
3557        """ Set the global plot font.
3558
3559        By default, the axis labels all use this, unless they have been set
3560        to use their own.
3561
3562        If the parameter 'family' is empty, the font family will be unchanged.
3563        If the parameter 'font_size' is 0, the font size will be unchanged.
3564        The font will be bold if parameter 'bold' is set to 'bold' or 'True'.
3565        The font will be italic if parameter 'italic' is set to 'italic'
3566        or 'True'.
3567        """
3568        self.client.send_si(self.handle, "setGlobalFont("+family+","+
3569                            b2str(font_size)+","+b2str(bold)+","+b2str(italic)+")")
3570
3571    def set_top_label(self, label=""):
3572        """ Set the plot top label """
3573        self.client.send_si(self.handle, "setTopLabel("+label+")")
3574
3575    def set_bottom_label(self, label=""):
3576        """ Set the plot bottom label """
3577        self.client.send_si(self.handle, "setBottomLabel("+label+")")
3578
3579    def set_left_label(self, label=""):
3580        """ Set the plot left label """
3581        self.client.send_si(self.handle, "setLeftLabel("+label+")")
3582
3583    def set_right_label(self, label=""):
3584        """ Set the plot right label """
3585        self.client.send_si(self.handle, "setRightLabel("+label+")")
3586
3587    def set_top_label_auto(self):
3588        """ Set the top label to auto generated. """
3589        self.client.send_si(self.handle, "setTopLabelAuto()")
3590
3591    def set_bottom_label_auto(self):
3592        """ Set the bottom label to auto generated. """
3593        self.client.send_si(self.handle, "setBottomLabelAuto()")
3594
3595    def set_left_label_auto(self):
3596        """ Set the left label to auto generated. """
3597        self.client.send_si(self.handle, "setLeftLabelAuto()")
3598
3599    def set_right_label_auto(self):
3600        """ Set the right label to auto generated. """
3601        self.client.send_si(self.handle, "setRightLabelAuto()")
3602
3603    def normalize_x_to_y(self):
3604        """ Adjust the X zoom range so X and Y have the same scale
3605        per unit (square pixels) """
3606        self.client.send_si(self.handle, "normalizeXtoY()")
3607
3608    def set_log_x(self, log_mode=True):
3609        """ Set X axis to log mode. """
3610        self.client.send_si(self.handle, "setLogX("+b2str(log_mode) + ")")
3611
3612    def set_log_y(self, log_mode=True):
3613        """ Set Y axis to log mode. """
3614        self.client.send_si(self.handle, "setLogY("+b2str(log_mode) + ")")
3615
3616    def set_y_axis_reversed(self, axis_reversed=True):
3617        """ set the Y axis to decreasing from bottom to top. """
3618        if axis_reversed:
3619            self.client.send_si(self.handle, "setYAxisReversed()")
3620        else:
3621            self.client.send_si(self.handle, "setYAxisNotReversed()")
3622
3623    def set_x_axis_reversed(self, reversed=True):
3624        """ set the X axis to decreasing from left to right. """
3625        if reversed:
3626            self.client.send_si(self.handle, "setXAxisReversed()")
3627        else:
3628            self.client.send_si(self.handle, "setXAxisNotReversed()")
3629
3630    def set_x_axis_interpretation(self, interp="ctime"):
3631        """ Interpret the x axis as time
3632
3633        :param interp: interpret the time as follows
3634
3635        interp can be::
3636
3637          ctime: Standard unix C time
3638          year:  Decimal year
3639          jd:    Julian Date
3640          mjd:   Modified Julian Date
3641          excel: Time as used by MS Excel
3642
3643        """
3644        self.client.send_si(self.handle, "setXAxisInterpretation("+interp+")")
3645
3646    def clear_x_axis_interpretation(self):
3647        """ do not intepret the x axis as time """
3648        self.client.send_si(self.handle, "clearXAxisInterpretation()")
3649
3650    def set_x_axis_display(self, display="yyyy/MM/dd h:mm:ss ap"):
3651        """ if the x axis has been interpreted as time, set the display.
3652
3653        Display Types::
3654
3655          year:              display the decimal year
3656          qttextdtehhmmss:   <Qt Text Date> HH:MM:SS.SS
3657          qtlocaldatehhmmss: <Qt Local Date> HH:MM:SS.SS
3658          jd:                Julian Date
3659          mjd:               Modified Julian Date
3660          All others:        custom format
3661
3662        The custom format is defined as::
3663
3664          d         the day as number without a leading zero (1 to 31)
3665          dd        the day as number with a leading zero (01 to 31)
3666          ddd       the abbreviated localized day name (e.g. 'Mon' to 'Sun').
3667                    Uses the system locale to localize the name, i.e. QLocale::system().
3668          dddd      the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
3669                    Uses the system locale to localize the name, i.e. QLocale::system().
3670          M         the month as number without a leading zero (1-12)
3671          MM        the month as number with a leading zero (01-12)
3672          MMM       the abbreviated localized month name (e.g. 'Jan' to 'Dec').
3673                    Uses the system locale to localize the name, i.e. QLocale::system().
3674          MMMM      the long localized month name (e.g. 'January' to 'December').
3675                    Uses the system locale to localize the name, i.e. QLocale::system().
3676          yy        the year as two digit number (00-99)
3677          yyyy      the year as four digit number
3678          h         the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
3679          hh        the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
3680          H         the hour without a leading zero (0 to 23, even with AM/PM display)
3681          HH        the hour with a leading zero (00 to 23, even with AM/PM display)
3682          m         the minute without a leading zero (0 to 59)
3683          mm        the minute with a leading zero (00 to 59)
3684          s         the second without a leading zero (0 to 59)
3685          ss        the second with a leading zero (00 to 59)
3686          z         the milliseconds without leading zeroes (0 to 999)
3687          zzz       the milliseconds with leading zeroes (000 to 999)
3688          AP or A   use AM/PM display. A/AP will be replaced by either "AM" or "PM".
3689          ap or a   use am/pm display. a/ap will be replaced by either "am" or "pm".
3690          t         the timezone (for example "CEST")
3691
3692           """
3693
3694        self.client.send_si(self.handle, "setXAxisDisplay("+display+")")
3695
3696
3697class Button(ViewItem):
3698    """ This represents a button inside a View. When the button is pressed, it sends a
3699    message via a socket.
3700
3701    socket is a QtNetwork.QLocalSocket that is not connected to anything. The message
3702    "clicked" will be sent when the button is pressed. See the bonjourMonde example. """
3703    def __init__(self, client, text, socket, posX=0.1, posY=0.1, sizeX=0.1, sizeY=0.1, rot=0):
3704        ViewItem.__init__(self, client)
3705        self.client.send("newButton()")
3706        self.client.send("setPos("+b2str(posX)+","+b2str(posY)+")")
3707        self.client.send("setSize("+b2str(sizeX)+","+b2str(sizeY)+")")
3708        self.client.send("setText("+b2str(text)+")")
3709        self.client.send("setRotation("+b2str(rot)+")")
3710        self.handle = self.client.send("endEdit()")
3711
3712        self.handle.remove(0, self.handle.indexOf("ing ")+4)
3713        socket.connectToServer(client.server_name)
3714        socket.waitForConnected(300)
3715        socket.write(b2str("attachTo("+self.handle+")"))
3716
3717    def set_text(self, text):
3718        """ Sets the text of the button. """
3719        self.client.send("beginEdit("+self.handle+")")
3720        self.client.send("setText("+b2str(text)+")")
3721        self.client.send("endEdit()")
3722
3723
3724
3725
3726
3727class LineEdit(ViewItem):
3728    """ This represents a line edit inside a View. When the lineedit's value is changed,
3729    it sends a message via a socket.
3730
3731    socket is a QtNetwork.QLocalSocket that is not connected to anything. The message
3732    "valueSet:VAL" where VAL is some text will be sent when the text is changed.
3733    See the ksNspire example. """
3734    def __init__(self, client, text, socket, posX=0.1, posY=0.1, sizeX=0.1, sizeY=0.1, rot=0):
3735        ViewItem.__init__(self, client)
3736        self.client.send("newLineEdit()")
3737        self.client.send("setPos("+b2str(posX)+","+b2str(posY)+")")
3738        self.client.send("setSize("+b2str(sizeX)+","+b2str(sizeY)+")")
3739        self.client.send("setText("+b2str(text)+")")
3740        self.client.send("setRotation("+b2str(rot)+")")
3741        self.handle = self.client.send("endEdit()")
3742
3743        self.handle.remove(0, self.handle.indexOf("ing ")+4)
3744        socket.connectToServer(b2str(client.server_name))
3745        socket.waitForConnected(300)
3746        socket.write(b2str("attachTo("+self.handle+")"))
3747
3748    def set_text(self, text):
3749        """ Sets the text of the line edit. """
3750        self.client.send("beginEdit("+self.handle+")")
3751        self.client.send("setText("+b2str(text)+")")
3752        self.client.send("endEdit()")
3753