Example #1
0
    def __init__(self, data_source_filename, parent=None, exit_on_close=True):
        self.in_filename = data_source_filename
        #todo check the file exists
        in_file = VOAOutFile(self.in_filename)

        self.exit_on_close = exit_on_close
        self.uifile = os.path.join(
            os.path.realpath(os.path.dirname(sys.argv[0])),
            "voaP2PPlotgui.glade")
        self.wTree = gtk.Builder()
        self.wTree.add_from_file(self.uifile)

        self.get_objects("dialog", "type_combobox", "group_combobox",
                         "tz_spinbutton", "cmap_combobox")
        self.parent = parent
        self.dialog.set_transient_for(self.parent)
        self.dialog.set_title(_("Plot Control"))

        if in_file.get_number_of_groups() >= 2:
            self.plot_type_d[5] = _('3D: MUF')

        self.populate_combo(self.type_combobox, self.plot_type_d, 'value')
        model = self.type_combobox.get_model()
        iter = model.get_iter_first()
        while iter:
            if model.get_value(iter, 0) == '2':  # reliability
                self.type_combobox.set_active_iter(iter)
                break
            iter = model.iter_next(iter)

        self.populate_combo(self.cmap_combobox, self.cmap_d, 'value')
        model = self.cmap_combobox.get_model()
        iter = model.get_iter_first()
        while iter:
            if model.get_value(iter, 0) == 'jet':
                self.cmap_combobox.set_active_iter(iter)
                break
            iter = model.iter_next(iter)

        d = {
            0: _('All Plots'),
        }
        l = in_file.get_group_titles()
        d.update(zip(range(1, len(l) + 1), l))
        self.populate_combo(self.group_combobox, d, 'key')

        event_dic = {
            "on_dialog_destroy": self.quit_application,
            "on_cancel_button_clicked": self.quit_application,
            "on_ok_button_clicked": self.run_plot
        }
        self.wTree.connect_signals(event_dic)
        self.dialog.connect('delete_event', self.quit_application)
        self.dialog.run()
Example #2
0
    def __init__(self, data_source_filename, parent = None, exit_on_close = True):
        self.in_filename = data_source_filename
        #todo check the file exists
        in_file = VOAOutFile(self.in_filename)

        self.exit_on_close = exit_on_close
        self.uifile = os.path.join(os.path.realpath(os.path.dirname(sys.argv[0])), "voaP2PPlotgui.glade")
        self.wTree = gtk.Builder()
        self.wTree.add_from_file(self.uifile)

        self.get_objects("dialog", "type_combobox", "group_combobox", 
                                "tz_spinbutton", "cmap_combobox")
        self.parent = parent
        self.dialog.set_transient_for(self.parent)
        self.dialog.set_title(_("Plot Control")) 

        if in_file.get_number_of_groups() >= 2:
            self.plot_type_d[5] = _('3D: MUF')

        self.populate_combo(self.type_combobox, self.plot_type_d, 'value')
        model = self.type_combobox.get_model()
        iter = model.get_iter_first()
        while iter:
            if model.get_value(iter, 0) == '2': # reliability
                self.type_combobox.set_active_iter(iter)
                break
            iter = model.iter_next(iter)

        self.populate_combo(self.cmap_combobox, self.cmap_d, 'value')
        model = self.cmap_combobox.get_model()
        iter = model.get_iter_first()
        while iter:
            if model.get_value(iter, 0) == 'jet':
                self.cmap_combobox.set_active_iter(iter)
                break
            iter = model.iter_next(iter)

        d = { 0 : _('All Plots'),}
        l = in_file.get_group_titles()
        d.update(zip(range(1, len(l)+1), l))
        self.populate_combo(self.group_combobox, d, 'key')
                
        event_dic = { "on_dialog_destroy" : self.quit_application, 
                      "on_cancel_button_clicked" : self.quit_application,
                      "on_ok_button_clicked" : self.run_plot}
        self.wTree.connect_signals(event_dic)
        self.dialog.connect('delete_event', self.quit_application)
        self.dialog.run()
Example #3
0
    def __init__(self, data_file, 
                data_type = 2,
                color_map = 'jet',
                plot_label = "",
                time_zone = 0, 
                plot_max_freq = 30.0,
                run_quietly = False,
                save_file = '',
                parent = None):

        self.data_type = data_type
        self.data_file = VOAOutFile(data_file, \
                        time_zone=time_zone, \
                        data_type=self.data_type)

        self.image_defs = self.IMG_TYPE_DICT[self.data_type]
        
        #color_map = eval('P.cm.' + color_map)
    
        num_grp = self.data_file.get_number_of_groups()
        if num_grp < 2:
            md = Gtk.MessageDialog(parent, \
                Gtk.DialogFlags.MODAL,\
                Gtk.MessageType.ERROR, \
                Gtk.ButtonsType.CANCEL, \
                "There must be 2 groups or more")
            md.run()
            md.destroy()
            return
        plot_groups = range(0, num_grp)

        self.subplots = []
        number_of_subplots = len(plot_groups)
        
        matplotlib.rcParams['axes.edgecolor'] = 'gray'
        matplotlib.rcParams['axes.facecolor'] = 'white'
        matplotlib.rcParams['axes.grid'] = True
        matplotlib.rcParams['figure.facecolor'] = 'white'
        matplotlib.rcParams['legend.fancybox'] = True
        matplotlib.rcParams['legend.shadow'] = True
        matplotlib.rcParams['figure.subplot.hspace'] = 0.45
        matplotlib.rcParams['figure.subplot.wspace'] = 0.35
        matplotlib.rcParams['figure.subplot.right'] = 0.85
        colorbar_fontsize = 12
               
        self.main_title_fontsize = 24
        matplotlib.rcParams['legend.fontsize'] = 12
        matplotlib.rcParams['axes.labelsize'] = 12
        matplotlib.rcParams['axes.titlesize'] = 10
        matplotlib.rcParams['xtick.labelsize'] = 10
        matplotlib.rcParams['ytick.labelsize'] = 10
        self.x_axes_ticks = np.arange(0, 25, 2)

        self.fig = Figure()
        ax = Axes3D(self.fig)
        
        X = np.arange(0, 25)
        Y = np.arange(0, len(plot_groups))
        X, Y = np.meshgrid(X, Y)

        data_buffer = [] # hold the Z data sets


        for chan_grp in plot_groups:
            (group_name, group_info, fot, muf, hpf, image_buffer) = \
                self.data_file.get_group_data(chan_grp)
            # Copy the element at [0] to the tail of the array 
            #to 'wrap-around' the values at 24hrs.
            np.resize(muf, len(muf)+1)
            muf[-1] = muf[0]
            data_buffer.append(muf)

        Z = np.vstack((tuple(data_buffer)))

	# set up the titles and labels
        ax.set_xticks(np.arange(0, 25, 2))

        if (plot_max_freq==self.AUTOSCALE) :
            z_max = math.ceil(max(muf) / 5.0) * 5.0
            z_max = min(plot_max_freq, 30.0)
            z_max = max(plot_max_freq, 5.0)
        else :
            z_max = math.ceil(plot_max_freq / 5.0) * 5.0
        z_ticks = [2, 5]
        for z_tick_value in np.arange(10, z_max+1, 5):
            z_ticks.append(z_tick_value) 
        #ax.set_yticks(z_ticks)

	#label axes
        tz_sign = '+' if (time_zone >= 0) else ''
        self.x_label = ax.set_xlabel('Time (UTC%s%s)' % (tz_sign, time_zone))
        self.y_label = ax.set_ylabel('Group')
        self.z_label = ax.set_zlabel('Frequency (MHz)')

	#do the plot
        ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=color_map)
        canvas = FigureCanvasGTK3Agg(self.fig)
        canvas.show()
        Axes3D.mouse_init(ax)
        VOAPlotWindow('pythonProp - ' + self.image_defs['title'], \
                        canvas, \
                        parent)
        return
Example #4
0
class VOA3DPlot:
    """Program to plot .out files produced by voacap in 3D"""
    
    AUTOSCALE = -1.0
    
    IMG_TYPE_DICT  = { 0:{'title':'', \
                            'min':0, \
                            'max':1, \
                            'y_labels':(0), \
                            'formatter':'defaultFormat'}, \
            1:{'title':'MUF Days (%)', \
                'min':0, \
                'max':1, \
                'y_labels':(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),\
                'formatter':'percent_format'}, \
            2:{'title':'Circuit Reliability (%)', \
                'min':0, \
                'max':1, \
                'y_labels':(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),\
                'formatter':'percent_format'}, \
            3:{'title':'SNR at Receiver (dB)', \
                'min':20, \
                'max':70, \
                'y_labels':(20, 30, 40, 50, 60, 70), \
                'formatter':'SNR_format'}, \
            4:{'title':'Signal Strength at Receiver (dBW)', \
                'min':-151, \
                'max':-43, \
                'y_labels':(-151, -145, -139, -133, -127, -121,-115, -109, \
                    -103, -93, -83, -73, -63, -53, -43), \
                'formatter':'SDBW_format'} }
    
    mono_font = {'family' : 'monospace'}
    #default_font = {'family' : 'sans-serif'}
      
    def __init__(self, data_file, 
                data_type = 2,
                color_map = 'jet',
                plot_label = "",
                time_zone = 0, 
                plot_max_freq = 30.0,
                run_quietly = False,
                save_file = '',
                parent = None):

        self.data_type = data_type
        self.data_file = VOAOutFile(data_file, \
                        time_zone=time_zone, \
                        data_type=self.data_type)

        self.image_defs = self.IMG_TYPE_DICT[self.data_type]
        
        #color_map = eval('P.cm.' + color_map)
    
        num_grp = self.data_file.get_number_of_groups()
        if num_grp < 2:
            md = Gtk.MessageDialog(parent, \
                Gtk.DialogFlags.MODAL,\
                Gtk.MessageType.ERROR, \
                Gtk.ButtonsType.CANCEL, \
                "There must be 2 groups or more")
            md.run()
            md.destroy()
            return
        plot_groups = range(0, num_grp)

        self.subplots = []
        number_of_subplots = len(plot_groups)
        
        matplotlib.rcParams['axes.edgecolor'] = 'gray'
        matplotlib.rcParams['axes.facecolor'] = 'white'
        matplotlib.rcParams['axes.grid'] = True
        matplotlib.rcParams['figure.facecolor'] = 'white'
        matplotlib.rcParams['legend.fancybox'] = True
        matplotlib.rcParams['legend.shadow'] = True
        matplotlib.rcParams['figure.subplot.hspace'] = 0.45
        matplotlib.rcParams['figure.subplot.wspace'] = 0.35
        matplotlib.rcParams['figure.subplot.right'] = 0.85
        colorbar_fontsize = 12
               
        self.main_title_fontsize = 24
        matplotlib.rcParams['legend.fontsize'] = 12
        matplotlib.rcParams['axes.labelsize'] = 12
        matplotlib.rcParams['axes.titlesize'] = 10
        matplotlib.rcParams['xtick.labelsize'] = 10
        matplotlib.rcParams['ytick.labelsize'] = 10
        self.x_axes_ticks = np.arange(0, 25, 2)

        self.fig = Figure()
        ax = Axes3D(self.fig)
        
        X = np.arange(0, 25)
        Y = np.arange(0, len(plot_groups))
        X, Y = np.meshgrid(X, Y)

        data_buffer = [] # hold the Z data sets


        for chan_grp in plot_groups:
            (group_name, group_info, fot, muf, hpf, image_buffer) = \
                self.data_file.get_group_data(chan_grp)
            # Copy the element at [0] to the tail of the array 
            #to 'wrap-around' the values at 24hrs.
            np.resize(muf, len(muf)+1)
            muf[-1] = muf[0]
            data_buffer.append(muf)

        Z = np.vstack((tuple(data_buffer)))

	# set up the titles and labels
        ax.set_xticks(np.arange(0, 25, 2))

        if (plot_max_freq==self.AUTOSCALE) :
            z_max = math.ceil(max(muf) / 5.0) * 5.0
            z_max = min(plot_max_freq, 30.0)
            z_max = max(plot_max_freq, 5.0)
        else :
            z_max = math.ceil(plot_max_freq / 5.0) * 5.0
        z_ticks = [2, 5]
        for z_tick_value in np.arange(10, z_max+1, 5):
            z_ticks.append(z_tick_value) 
        #ax.set_yticks(z_ticks)

	#label axes
        tz_sign = '+' if (time_zone >= 0) else ''
        self.x_label = ax.set_xlabel('Time (UTC%s%s)' % (tz_sign, time_zone))
        self.y_label = ax.set_ylabel('Group')
        self.z_label = ax.set_zlabel('Frequency (MHz)')

	#do the plot
        ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=color_map)
        canvas = FigureCanvasGTK3Agg(self.fig)
        canvas.show()
        Axes3D.mouse_init(ax)
        VOAPlotWindow('pythonProp - ' + self.image_defs['title'], \
                        canvas, \
                        parent)
        return
Example #5
0
    def __init__(self, data_source_filename, parent=None, exit_on_close=True, datadir=""):
        self.datadir = datadir
        self.in_filename = data_source_filename
        # todo check the file exists
        in_file = VOAOutFile(self.in_filename)

        self.exit_on_close = exit_on_close
        # self.uifile = os.path.join(os.path.realpath(os.path.dirname(sys.argv[0])), "voaP2PPlotgui.ui")
        self.parent = parent
        if self.parent:
            self.ui_file = os.path.join(self.datadir, "ui", "voaP2PPlotDialog.ui")
        else:
            self.ui_file = os.path.join(self.datadir, "ui", "voaP2PPlotWindow.ui")
        # self.wTree = Gtk.Builder.new_from_file(self.ui_file)

        self.wTree = Gtk.Builder()
        self.wTree.add_from_file(self.ui_file)

        self.get_objects("dialog", "type_combobox", "group_combobox", "tz_spinbutton", "cmap_combobox")
        if self.parent:
            self.dialog.set_transient_for(self.parent)

        self.dialog.set_title(_("Plot Control"))

        if in_file.get_number_of_groups() >= 2:
            self.plot_type_d[5] = _("3D: MUF")

        self.populate_combo(self.type_combobox, self.plot_type_d, "value")
        model = self.type_combobox.get_model()
        iter = model.get_iter_first()
        while iter:
            if model.get_value(iter, 0) == "2":  # reliability
                self.type_combobox.set_active_iter(iter)
                break
            iter = model.iter_next(iter)

        self.populate_combo(self.cmap_combobox, self.cmap_d, "value")
        model = self.cmap_combobox.get_model()
        iter = model.get_iter_first()
        while iter:
            if model.get_value(iter, 0) == "jet":
                self.cmap_combobox.set_active_iter(iter)
                break
            iter = model.iter_next(iter)

        d = {0: _("All Plots")}
        l = in_file.get_group_titles()
        d.update(zip(range(1, len(l) + 1), l))
        self.populate_combo(self.group_combobox, d, "key")

        event_dic = {
            "on_dialog_destroy": self.quit_application,
            "on_cancel_button_clicked": self.quit_application,
            "on_ok_button_clicked": self.run_plot,
        }
        self.wTree.connect_signals(event_dic)
        self.dialog.connect("delete_event", self.quit_application)
        if self.parent:
            self.dialog.run()
        else:
            self.dialog.show_all()
            Gtk.main()
Example #6
0
    def __init__(self,
                 data_file,
                 data_type=2,
                 color_map='jet',
                 plot_label="",
                 time_zone=0,
                 plot_max_freq=30.0,
                 run_quietly=False,
                 save_file='',
                 parent=None,
                 interactive=True):

        self.data_type = data_type
        self.data_file = VOAOutFile(data_file, \
                        time_zone=time_zone, \
                        data_type=self.data_type)

        self.image_defs = self.IMG_TYPE_DICT[self.data_type]

        color_map = eval('P.cm.' + color_map)

        num_grp = self.data_file.get_number_of_groups()
        if num_grp < 2:
            md = gtk.MessageDialog(parent, \
                gtk.DIALOG_MODAL,\
                gtk.MESSAGE_ERROR, \
                gtk.BUTTONS_CANCEL, \
                "There must be 2 groups or more")
            md.run()
            md.destroy()
            return
        plot_groups = range(0, num_grp)

        self.subplots = []
        number_of_subplots = len(plot_groups)

        matplotlib.rcParams['axes.edgecolor'] = 'gray'
        matplotlib.rcParams['axes.facecolor'] = 'white'
        matplotlib.rcParams['axes.grid'] = True
        matplotlib.rcParams['figure.facecolor'] = 'white'
        matplotlib.rcParams['legend.fancybox'] = True
        matplotlib.rcParams['legend.shadow'] = True
        matplotlib.rcParams['figure.subplot.hspace'] = 0.45
        matplotlib.rcParams['figure.subplot.wspace'] = 0.35
        matplotlib.rcParams['figure.subplot.right'] = 0.85
        colorbar_fontsize = 12

        self.main_title_fontsize = 24
        matplotlib.rcParams['legend.fontsize'] = 12
        matplotlib.rcParams['axes.labelsize'] = 12
        matplotlib.rcParams['axes.titlesize'] = 10
        matplotlib.rcParams['xtick.labelsize'] = 10
        matplotlib.rcParams['ytick.labelsize'] = 10
        self.x_axes_ticks = P.arange(0, 25, 2)

        self.fig = plt.figure()
        ax = Axes3D(self.fig)

        X = P.arange(0, 25)
        Y = P.arange(0, len(plot_groups))
        X, Y = np.meshgrid(X, Y)

        data_buffer = []  # hold the Z data sets

        for chan_grp in plot_groups:
            (group_name, group_info, fot, muf, hpf, image_buffer) = \
                self.data_file.get_group_data(chan_grp)
            # Copy the element at [0] to the tail of the array
            #to 'wrap-around' the values at 24hrs.
            np.resize(muf, len(muf) + 1)
            muf[-1] = muf[0]
            data_buffer.append(muf)

        Z = np.vstack((tuple(data_buffer)))

        # set up the titles and labels
        ax.set_xticks(P.arange(0, 25, 2))

        if (plot_max_freq == self.AUTOSCALE):
            z_max = math.ceil(max(muf) / 5.0) * 5.0
            z_max = min(plot_max_freq, 30.0)
            z_max = max(plot_max_freq, 5.0)
        else:
            z_max = math.ceil(plot_max_freq / 5.0) * 5.0
        z_ticks = [2, 5]
        for z_tick_value in P.arange(10, z_max + 1, 5):
            z_ticks.append(z_tick_value)
        #ax.set_yticks(z_ticks)

#label axes
        tz_sign = '+' if (time_zone >= 0) else ''
        self.x_label = ax.set_xlabel('Time (UTC%s%s)' % (tz_sign, time_zone))
        self.y_label = ax.set_ylabel('Group')
        self.z_label = ax.set_zlabel('Frequency (MHz)')

        #do the plot
        ax.plot_surface(X,
                        Y,
                        Z,
                        rstride=1,
                        cstride=1,
                        cmap=plt.get_cmap('jet'))
        if interactive:
            plt.show()
        else:
            canvas = FigureCanvasGTKAgg(self.fig)
            canvas.show()
            VOAPlotWindow('pythonProp - ' + self.image_defs['title'], \
                        canvas, \
                        parent)
        return
Example #7
0
class VOA3DPlot:
    """Program to plot .out files produced by voacap in 3D"""

    AUTOSCALE = -1.0

    IMG_TYPE_DICT  = { 0:{'title':'', \
                            'min':0, \
                            'max':1, \
                            'y_labels':(0), \
                            'formatter':'defaultFormat'}, \
            1:{'title':'MUF Days (%)', \
                'min':0, \
                'max':1, \
                'y_labels':(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),\
                'formatter':'percent_format'}, \
            2:{'title':'Circuit Reliability (%)', \
                'min':0, \
                'max':1, \
                'y_labels':(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),\
                'formatter':'percent_format'}, \
            3:{'title':'SNR at Receiver (dB)', \
                'min':20, \
                'max':70, \
                'y_labels':(20, 30, 40, 50, 60, 70), \
                'formatter':'SNR_format'}, \
            4:{'title':'Signal Strength at Receiver (dBW)', \
                'min':-151, \
                'max':-43, \
                'y_labels':(-151, -145, -139, -133, -127, -121,-115, -109, \
                    -103, -93, -83, -73, -63, -53, -43), \
                'formatter':'SDBW_format'} }

    mono_font = {'family': 'monospace'}

    #default_font = {'family' : 'sans-serif'}

    def __init__(self,
                 data_file,
                 data_type=2,
                 color_map='jet',
                 plot_label="",
                 time_zone=0,
                 plot_max_freq=30.0,
                 run_quietly=False,
                 save_file='',
                 parent=None,
                 interactive=True):

        self.data_type = data_type
        self.data_file = VOAOutFile(data_file, \
                        time_zone=time_zone, \
                        data_type=self.data_type)

        self.image_defs = self.IMG_TYPE_DICT[self.data_type]

        color_map = eval('P.cm.' + color_map)

        num_grp = self.data_file.get_number_of_groups()
        if num_grp < 2:
            md = gtk.MessageDialog(parent, \
                gtk.DIALOG_MODAL,\
                gtk.MESSAGE_ERROR, \
                gtk.BUTTONS_CANCEL, \
                "There must be 2 groups or more")
            md.run()
            md.destroy()
            return
        plot_groups = range(0, num_grp)

        self.subplots = []
        number_of_subplots = len(plot_groups)

        matplotlib.rcParams['axes.edgecolor'] = 'gray'
        matplotlib.rcParams['axes.facecolor'] = 'white'
        matplotlib.rcParams['axes.grid'] = True
        matplotlib.rcParams['figure.facecolor'] = 'white'
        matplotlib.rcParams['legend.fancybox'] = True
        matplotlib.rcParams['legend.shadow'] = True
        matplotlib.rcParams['figure.subplot.hspace'] = 0.45
        matplotlib.rcParams['figure.subplot.wspace'] = 0.35
        matplotlib.rcParams['figure.subplot.right'] = 0.85
        colorbar_fontsize = 12

        self.main_title_fontsize = 24
        matplotlib.rcParams['legend.fontsize'] = 12
        matplotlib.rcParams['axes.labelsize'] = 12
        matplotlib.rcParams['axes.titlesize'] = 10
        matplotlib.rcParams['xtick.labelsize'] = 10
        matplotlib.rcParams['ytick.labelsize'] = 10
        self.x_axes_ticks = P.arange(0, 25, 2)

        self.fig = plt.figure()
        ax = Axes3D(self.fig)

        X = P.arange(0, 25)
        Y = P.arange(0, len(plot_groups))
        X, Y = np.meshgrid(X, Y)

        data_buffer = []  # hold the Z data sets

        for chan_grp in plot_groups:
            (group_name, group_info, fot, muf, hpf, image_buffer) = \
                self.data_file.get_group_data(chan_grp)
            # Copy the element at [0] to the tail of the array
            #to 'wrap-around' the values at 24hrs.
            np.resize(muf, len(muf) + 1)
            muf[-1] = muf[0]
            data_buffer.append(muf)

        Z = np.vstack((tuple(data_buffer)))

        # set up the titles and labels
        ax.set_xticks(P.arange(0, 25, 2))

        if (plot_max_freq == self.AUTOSCALE):
            z_max = math.ceil(max(muf) / 5.0) * 5.0
            z_max = min(plot_max_freq, 30.0)
            z_max = max(plot_max_freq, 5.0)
        else:
            z_max = math.ceil(plot_max_freq / 5.0) * 5.0
        z_ticks = [2, 5]
        for z_tick_value in P.arange(10, z_max + 1, 5):
            z_ticks.append(z_tick_value)
        #ax.set_yticks(z_ticks)

#label axes
        tz_sign = '+' if (time_zone >= 0) else ''
        self.x_label = ax.set_xlabel('Time (UTC%s%s)' % (tz_sign, time_zone))
        self.y_label = ax.set_ylabel('Group')
        self.z_label = ax.set_zlabel('Frequency (MHz)')

        #do the plot
        ax.plot_surface(X,
                        Y,
                        Z,
                        rstride=1,
                        cstride=1,
                        cmap=plt.get_cmap('jet'))
        if interactive:
            plt.show()
        else:
            canvas = FigureCanvasGTKAgg(self.fig)
            canvas.show()
            VOAPlotWindow('pythonProp - ' + self.image_defs['title'], \
                        canvas, \
                        parent)
        return