'Explains to the plot how to interpret the data set by :meth:`set_plot_data`. Its arguments
are indices (must be less than the size of an example) into the dataset (each one
specifies a column). Additionally, it accepts a list of colors (when color is a discrete
attribute), a value specifying how many different symbols are needed to display the data and
information whether or not positional data is discrete.
.. note:: This function does not add items to the legend automatically.
You will have to add them yourself with :meth:`.OWLegend.add_item`.
:param x_index: Index (column) of the x coordinate.
:type int
:param y_index: Index (column) of the y coordinate.
:type int
:param z_index: Index (column) of the z coordinate.
:type int
:param color_index: Index (column) of the color attribute.
:type int
:param symbol_index: Index (column) of the symbol attribute.
:type int
:param size_index: Index (column) of the size attribute.
:type int
:param label_index: Index (column) of the label attribute.
:type int
:param colors: List of colors used for symbols. When color is a discrete attribute,
this list should be empty. You should make sure the number of colors in this list
equals the number of unique values in the color attribute.
:type list of QColor
:param num_symbols_used: Specifies the number of unique values in the symbol attribute.
Must be -1 if all points are to use the same symbol.
:type int
:param x_discrete: Specifies whether or not x coordinate is discrete.
:type bool
:param y_discrete: Specifies whether or not y coordinate is discrete.
:type bool
:param z_discrete: Specifies whether or not z coordinate is discrete.
:type bool'

def set_features(self, x_index, y_index, z_index, color_index, symbol_index, size_index, label_index, colors, num_symbols_used, x_discrete, y_discrete, z_discrete):

    if (self.data == None):
        print 'Error:    set_plot_data    has    not    been    called    yet!'
        return
    start = time.time()
    self.makeCurrent()
    self.x_index = x_index
    self.y_index = y_index
    self.z_index = z_index
    self.color_index = color_index
    self.symbol_index = symbol_index
    self.size_index = size_index
    self.colors = colors
    self.num_symbols_used = num_symbols_used
    self.x_discrete = x_discrete
    self.y_discrete = y_discrete
    self.z_discrete = z_discrete
    self.label_index = label_index
    if (self.num_examples > (10 * 1000)):
        self.use_2d_symbols = True
    if self._use_opengl_3:
        self.generating_program.bind()
        self.generating_program.setUniformValue('x_index', x_index)
        self.generating_program.setUniformValue('y_index', y_index)
        self.generating_program.setUniformValue('z_index', z_index)
        self.generating_program.setUniformValue('x_discrete', x_discrete)
        self.generating_program.setUniformValue('y_discrete', y_discrete)
        self.generating_program.setUniformValue('z_discrete', z_discrete)
        self.generating_program.setUniformValue('color_index', color_index)
        self.generating_program.setUniformValue('symbol_index', symbol_index)
        self.generating_program.setUniformValue('size_index', size_index)
        self.generating_program.setUniformValue('use_2d_symbols', self.use_2d_symbols)
        self.generating_program.setUniformValue('example_size', self.example_size)
        self.generating_program.setUniformValue('num_colors', len(colors))
        self.generating_program.setUniformValue('num_symbols_used', num_symbols_used)
        glUniform3fv(glGetUniformLocation(self.generating_program.programId(), 'colors'), len(colors), numpy.array(colors, 'f').ravel())
        glUniform1iv(glGetUniformLocation(self.generating_program.programId(), 'symbols_sizes'), (len(Symbol) * 2), numpy.array(self.symbols_sizes, dtype='i'))
        glUniform1iv(glGetUniformLocation(self.generating_program.programId(), 'symbols_indices'), (len(Symbol) * 2), numpy.array(self.symbols_indices, dtype='i'))
        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_BUFFER, self.symbol_buffer)
        self.generating_program.setUniformValue('symbol_buffer', 0)
        glActiveTexture(GL_TEXTURE1)
        glBindTexture(GL_TEXTURE_BUFFER, self.data_buffer)
        self.generating_program.setUniformValue('data_buffer', 1)
        qid = glGenQueries(1)
        glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, qid)
        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, self.feedback_bid)
        glEnable(GL_RASTERIZER_DISCARD)
        glBeginTransformFeedback(GL_TRIANGLES)
        glBindVertexArray(self.dummy_vao)
        glDrawArrays(GL_POINTS, 0, self.num_examples)
        glEndTransformFeedback()
        glDisable(GL_RASTERIZER_DISCARD)
        glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
        self.num_primitives_generated = glGetQueryObjectuiv(qid, GL_QUERY_RESULT)
        glBindVertexArray(0)
        self._feedback_generated = True
        print ('Num    generated    primitives:    ' + str(self.num_primitives_generated))
        self.generating_program.release()
        glActiveTexture(GL_TEXTURE0)
        print (('Generation    took    ' + str((time.time() - start))) + '    seconds')
    else:
        orangeqt.Plot3D.update_data(self, x_index, y_index, z_index, color_index, symbol_index, size_index, label_index, colors, num_symbols_used, x_discrete, y_discrete, z_discrete, self.use_2d_symbols)
        print (('Data    processing    took    ' + str((time.time() - start))) + '    seconds')
    self.update()
