Changeset 8412:67227a0d4c6d in orange


Ignore:
Timestamp:
07/22/11 00:14:23 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
9a3a3a972624c1794f0f31a8c0a7f7767f318e08
Message:

owscatterplot3d: several bugfixes, discrete attributes, plot report

Location:
orange/OrangeWidgets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Prototypes/OWScatterPlot3D.py

    r8404 r8412  
    1111import numpy 
    1212 
    13 TooltipKind = enum('NONE', 'VISIBLE', 'ALL') # Which attributes should be displayed? 
     13TooltipKind = enum('NONE', 'VISIBLE', 'ALL') # Which attributes should be displayed in tooltips? 
    1414 
    1515class OWScatterPlot3D(OWWidget): 
    16     settingsList = ['plot.show_legend'] 
     16    settingsList = ['plot.show_legend', 'plot.symbol_size', 'plot.show_x_axis_title', 'plot.show_y_axis_title', 
     17                    'plot.show_z_axis_title', 'plot.show_legend', 'plot.face_symbols', 'plot.filled_symbols', 
     18                    'plot.transparency', 'plot.show_grid', 'plot.pitch', 'plot.yaw', 'plot.use_ortho', 
     19                    'auto_send_selection', 'auto_send_selection_update'] 
    1720    contextHandlers = {"": DomainContextHandler("", ["xAttr", "yAttr", "zAttr"])} 
    18   
     21    jitter_sizes = [0.0, 0.1, 0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 30, 40, 50] 
     22 
    1923    def __init__(self, parent=None, signalManager=None, name="Scatter Plot 3D"): 
    2024        OWWidget.__init__(self, parent, signalManager, name, True) 
     
    3438        self.symbol_scale = 5 
    3539        self.alpha_value = 255 
     40 
     41        self.loadSettings() 
    3642 
    3743        self.tabs = OWGUI.tabWidget(self.controlArea) 
     
    8591        box = OWGUI.widgetBox(self.settings_tab, 'Point properties') 
    8692        OWGUI.hSlider(box, self, "plot.symbol_scale", label="Symbol scale", 
    87             minValue=1, maxValue=10, 
     93            minValue=1, maxValue=5, 
    8894            tooltip="Scale symbol size", 
    89             callback=self.on_checkbox_update 
     95            callback=self.on_checkbox_update, 
    9096            ) 
    9197 
     
    96102        OWGUI.rubber(box) 
    97103 
     104        self.jitter_size = 0 
     105        self.jitter_continuous = False 
     106        box = OWGUI.widgetBox(self.settings_tab, "Jittering Options") 
     107        self.jitter_size_combo = OWGUI.comboBox(box, self, 'jitter_size', label='Jittering size (% of size)'+'  ', 
     108            orientation='horizontal', 
     109            callback=self.on_checkbox_update, 
     110            items=self.jitter_sizes, 
     111            sendSelectedValue=1, 
     112            valueType=float) 
     113        OWGUI.checkBox(box, self, 'jitter_continuous', 'Jitter continuous attributes', 
     114            callback=self.on_checkbox_update, 
     115            tooltip='Does jittering apply also on continuous attributes?') 
     116 
    98117        box = OWGUI.widgetBox(self.settings_tab, 'General settings') 
    99118        OWGUI.checkBox(box, self, 'plot.show_x_axis_title',   'X axis title',   callback=self.on_checkbox_update) 
     
    101120        OWGUI.checkBox(box, self, 'plot.show_z_axis_title',   'Z axis title',   callback=self.on_checkbox_update) 
    102121        OWGUI.checkBox(box, self, 'plot.show_legend',         'Show legend',    callback=self.on_checkbox_update) 
    103         OWGUI.checkBox(box, self, 'plot.ortho',               'Use ortho',      callback=self.on_checkbox_update) 
     122        OWGUI.checkBox(box, self, 'plot.use_ortho',           'Use ortho',      callback=self.on_checkbox_update) 
    104123        OWGUI.checkBox(box, self, 'plot.filled_symbols',      'Filled symbols', callback=self.on_checkbox_update) 
    105124        OWGUI.checkBox(box, self, 'plot.face_symbols',        'Face symbols',   callback=self.on_checkbox_update) 
    106         OWGUI.checkBox(box, self, 'plot.grid',                'Show grid',      callback=self.on_checkbox_update) 
     125        OWGUI.checkBox(box, self, 'plot.show_grid',           'Show grid',      callback=self.on_checkbox_update) 
    107126        OWGUI.rubber(box) 
    108127 
     
    244263 
    245264    def set_subset_data(self, data=None): 
    246         self.subsetData = data 
     265        self.subsetData = data # TODO: what should scatterplot do with this? 
    247266 
    248267    def handleNewSignals(self): 
    249268        self.update_plot() 
    250269        self.send_selections() 
     270 
     271    def saveSettings(self): 
     272        OWWidget.saveSettings(self) 
     273 
     274    def sendReport(self): 
     275        self.startReport('%s [%s - %s - %s]' % (self.windowTitle(), self.attr_name[self.x_attr], 
     276                                                self.attr_name[self.y_attr], self.attr_name[self.z_attr])) 
     277        self.reportSettings('Visualized attributes', 
     278                            [('X', self.attr_name[self.x_attr]), 
     279                             ('Y', self.attr_name[self.y_attr]), 
     280                             ('Z', self.attr_name[self.z_attr]), 
     281                             self.color_attr and ('Color', self.attr_name[self.color_attr]), 
     282                             self.label_attr and ('Label', self.attr_name[self.label_attr]), 
     283                             self.shape_attr and ('Shape', self.attr_name[self.shape_attr]), 
     284                             self.size_attr  and ('Size', self.attr_name[self.size_attr])]) 
     285        self.reportSettings('Settings', 
     286                            [('Symbol size', self.plot.symbol_scale), 
     287                             ('Transparency', self.plot.transparency), 
     288                             #("Jittering", self.graph.jitterSize), 
     289                             #("Jitter continuous attributes", OWGUI.YesNo[self.graph.jitterContinuous])]) 
     290                             ]) 
     291        self.reportSection('Plot') 
     292        self.reportImage(self.plot.save_to_file_direct, QSize(400, 400)) 
    251293 
    252294    def send_selections(self): 
     
    347389        self.plot.set_z_axis_title(self.axis_candidate_attrs[self.z_attr].name) 
    348390 
     391        def create_discrete_map(attr_index): 
     392            keys = range(len(self.axis_candidate_attrs[attr_index].values)) 
     393            values = self.axis_candidate_attrs[attr_index].values 
     394            map = {} 
     395            for key, value in zip(keys, values): 
     396                map[key] = value 
     397            return map 
     398 
     399        if self.axis_candidate_attrs[self.x_attr].varType == orange.VarTypes.Discrete: 
     400            self.plot.set_x_axis_map(create_discrete_map(self.x_attr)) 
     401        if self.axis_candidate_attrs[self.y_attr].varType == orange.VarTypes.Discrete: 
     402            self.plot.set_y_axis_map(create_discrete_map(self.y_attr)) 
     403        if self.axis_candidate_attrs[self.z_attr].varType == orange.VarTypes.Discrete: 
     404            self.plot.set_z_axis_map(create_discrete_map(self.z_attr)) 
     405 
    349406    def get_axis_data(self, x_ind, y_ind, z_ind): 
    350407        array = self.data_array 
  • orange/OrangeWidgets/owplot3d.py

    r8411 r8412  
    66        Determines whether to display the legend or not. 
    77 
    8     .. attribute:: ortho 
     8    .. attribute:: use_ortho 
    99        If False, perspective projection is used instead. 
    1010 
     
    3737        Removes everything from the graph. 
    3838""" 
     39 
     40# TODO: docs! 
    3941 
    4042from PyQt4.QtCore import * 
     
    280282        QtOpenGL.QGLWidget.__init__(self, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers), parent) 
    281283 
    282         self.activateZooming = lambda: None 
     284        void = lambda: None 
     285        self.activateZooming = void 
     286        self.activateRectangleSelection = void 
     287        self.activatePolygonSelection = void 
     288        self.activatePanning = void 
     289        self.activateSelection = void 
    283290 
    284291        self.commands = [] 
     
    319326        self.vaos = [] 
    320327 
    321         self.ortho = False 
     328        self.use_ortho = False 
    322329        self.show_legend = True 
    323330        self.legend = Legend(self) 
     
    327334        self.symbol_scale = 1. 
    328335        self.transparency = 255 
    329         self.grid = True 
     336        self.show_grid = True 
    330337        self.scale = numpy.array([1., 1., 1.]) 
    331338        self.additional_scale = [0, 0, 0] 
     
    348355 
    349356        self.mouseover_callback = None 
     357 
     358        self.x_axis_map = None 
     359        self.y_axis_map = None 
     360        self.z_axis_map = None 
    350361 
    351362    def __del__(self): 
     
    371382            uniform float symbol_scale; 
    372383            uniform float transparency; 
     384            uniform float view_edge; 
    373385 
    374386            uniform vec3 scale; 
     
    421433                pos = abs(pos); 
    422434                float manhattan_distance = max(max(pos.x, pos.y), pos.z)+5.; 
    423                 var_color = vec4(color.rgb, pow(min(1, 10. / manhattan_distance), 5)); 
     435                float a = min(pow(min(1, view_edge / manhattan_distance), 5), transparency); 
     436                var_color = vec4(color.rgb, a); 
    424437              } 
    425438            } 
     
    448461        self.symbol_shader_symbol_scale = self.symbol_shader.uniformLocation('symbol_scale') 
    449462        self.symbol_shader_transparency = self.symbol_shader.uniformLocation('transparency') 
     463        self.symbol_shader_view_edge    = self.symbol_shader.uniformLocation('view_edge') 
    450464        self.symbol_shader_scale        = self.symbol_shader.uniformLocation('scale') 
    451465        self.symbol_shader_translation  = self.symbol_shader.uniformLocation('translation') 
     
    465479        glClearColor(1, 1, 1, 1) 
    466480        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
     481 
     482        if len(self.commands) == 0: 
     483            return 
     484 
    467485        glMatrixMode(GL_PROJECTION) 
    468486        glLoadIdentity() 
    469487        width, height = self.width(), self.height() 
    470         if self.ortho: 
     488        if self.use_ortho: 
    471489            glOrtho(-width / self.ortho_scale, 
    472490                     width / self.ortho_scale, 
     
    486504            0, 0, 0, 
    487505            0, 1, 0) 
     506 
    488507        self.draw_grid_and_axes() 
    489508 
     
    500519                self.symbol_shader.setUniformValue(self.symbol_shader_tooltip_mode, False) 
    501520                self.symbol_shader.setUniformValue(self.symbol_shader_face_symbols, self.face_symbols) 
    502                 # TODO: line below crashes this thing on windows (weird stuff!) 
    503                 self.symbol_shader.setUniformValue(self.symbol_shader_symbol_scale, self.symbol_scale) 
    504                 self.symbol_shader.setUniformValue(self.symbol_shader_transparency, self.transparency) 
     521                self.symbol_shader.setUniformValue(self.symbol_shader_view_edge,    float(self.view_cube_edge)) 
     522                self.symbol_shader.setUniformValue(self.symbol_shader_symbol_scale, float(self.symbol_scale)) 
     523                self.symbol_shader.setUniformValue(self.symbol_shader_transparency, self.transparency / 255.) 
    505524                self.symbol_shader.setUniformValue(self.symbol_shader_scale,        *scale) 
    506525 
     
    520539                else: 
    521540                    glBindVertexArray(outline_vao_id) 
    522                     glDrawElements(GL_LINES, outline_vao_id.num_indices, GL_UNSIGNED_INT, 0) 
     541                    glDrawElements(GL_LINES, outline_vao_id.num_indices, GL_UNSIGNED_INT, c_void_p(0)) 
    523542                    glBindVertexArray(0) 
    524543                self.symbol_shader.release() 
     
    618637            glEnd() 
    619638 
    620         def draw_values(axis, coord_index, normal, sub=10): 
     639        def draw_discrete_axis_values(axis, coord_index, normal, axis_map): 
     640            start, end = axis 
     641            scale = (max(0, self.scale[coord_index] + self.additional_scale[coord_index])) 
     642            scale *= self.initial_scale[coord_index] 
     643            start_value = (start[coord_index] / scale) + self.initial_center[coord_index] 
     644            end_value =   (end[coord_index] / scale)   + self.initial_center[coord_index] 
     645            length = end_value - start_value 
     646            offset = normal*0.8 
     647            for key in axis_map.keys(): 
     648                if start_value <= key <= end_value: 
     649                    position = start + (end-start)*((key-start_value) / length) 
     650                    position += offset 
     651                    self.renderText(position[0], 
     652                                    position[1], 
     653                                    position[2], 
     654                                    axis_map[key], font=self.labels_font) 
     655 
     656        def draw_values(axis, coord_index, normal, axis_map, sub=10): 
     657            if axis_map != None: 
     658                draw_discrete_axis_values(axis, coord_index, normal, axis_map) 
     659                return 
    621660            glColor4f(0.1, 0.1, 0.1, 1) 
    622661            glLineWidth(1) 
     
    691730                  self.axis_plane_xy_back, self.axis_plane_yz_right] 
    692731        visible_planes = map(plane_visible, planes) 
    693         if self.grid: 
     732        if self.show_grid: 
    694733            draw_axis_plane(self.axis_plane_xz) 
    695734            for visible, plane in zip(visible_planes, planes): 
     
    702741        if visible_planes[0]: 
    703742            draw_axis(self.x_axis) 
    704             draw_values(self.x_axis, 0, numpy.array([0, 0, -1])) 
     743            draw_values(self.x_axis, 0, numpy.array([0, 0, -1]), self.x_axis_map) 
    705744            if self.show_x_axis_title: 
    706745                draw_axis_title(self.x_axis, self.x_axis_title, numpy.array([0, 0, -1])) 
    707746        elif visible_planes[2]: 
    708747            draw_axis(self.x_axis + self.unit_z) 
    709             draw_values(self.x_axis + self.unit_z, 0, numpy.array([0, 0, 1])) 
     748            draw_values(self.x_axis + self.unit_z, 0, numpy.array([0, 0, 1]), self.x_axis_map) 
    710749            if self.show_x_axis_title: 
    711750                draw_axis_title(self.x_axis + self.unit_z, 
     
    714753        if visible_planes[1]: 
    715754            draw_axis(self.z_axis) 
    716             draw_values(self.z_axis, 2, numpy.array([-1, 0, 0])) 
     755            draw_values(self.z_axis, 2, numpy.array([-1, 0, 0]), self.z_axis_map) 
    717756            if self.show_z_axis_title: 
    718757                draw_axis_title(self.z_axis, self.z_axis_title, numpy.array([-1, 0, 0])) 
    719758        elif visible_planes[3]: 
    720759            draw_axis(self.z_axis + self.unit_x) 
    721             draw_values(self.z_axis + self.unit_x, 2, numpy.array([1, 0, 0])) 
     760            draw_values(self.z_axis + self.unit_x, 2, numpy.array([1, 0, 0]), self.z_axis_map) 
    722761            if self.show_z_axis_title: 
    723762                draw_axis_title(self.z_axis + self.unit_x, self.z_axis_title, numpy.array([1, 0, 0])) 
     
    740779        normal = normals[rightmost_visible] 
    741780        draw_axis(axis) 
    742         draw_values(axis, 1, normal) 
     781        draw_values(axis, 1, normal, self.y_axis_map) 
    743782        if self.show_y_axis_title: 
    744783            draw_axis_title(axis, self.y_axis_title, normal) 
     
    847886        vertex_buffer_id = glGenBuffers(1) 
    848887        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id) 
     888        glBufferData(GL_ARRAY_BUFFER, numpy.array(vertices, 'f'), GL_STATIC_DRAW) 
    849889 
    850890        vertex_size = (4+3+4)*4 
     
    856896        glEnableVertexAttribArray(2) 
    857897 
    858         # It's important to keep a reference to vertices around, 
    859         # data uploaded to GPU seem to get corrupted otherwise. 
    860         #vertex_buffer_id.vertices = numpy.array(vertices, 'f') 
    861         glBufferData(GL_ARRAY_BUFFER, numpy.array(vertices, 'f'), GL_STATIC_DRAW) 
    862             #ArrayDatatype.arrayByteCount(vertex_buffer.vertices), 
    863             #ArrayDatatype.voidDataPointer(vertex_buffer.vertices), GL_STATIC_DRAW) 
    864  
    865898        glBindVertexArray(0) 
    866899        glBindBuffer(GL_ARRAY_BUFFER, 0) 
     
    871904        index_buffer_id = glGenBuffers(1) 
    872905        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id) 
    873         #index_buffer.indices = numpy.array(outline_indices, 'I') 
    874906        glBufferData(GL_ELEMENT_ARRAY_BUFFER, numpy.array(outline_indices, 'I'), GL_STATIC_DRAW) 
    875             #ArrayDatatype.arrayByteCount(index_buffer.indices), 
    876             #ArrayDatatype.voidDataPointer(index_buffer.indices), GL_STATIC_DRAW) 
    877907 
    878908        outline_vao_id = GLuint(0) 
     
    892922        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 
    893923        glBindBuffer(GL_ARRAY_BUFFER, 0) 
    894          
     924 
    895925        vao_id.num_vertices = len(vertices) / (vertex_size / 4) 
    896926        outline_vao_id.num_indices = vao_id.num_vertices * 2 / 3 
    897         #self.vertex_buffers.append(vertex_buffer) 
    898         #self.index_buffers.append(index_buffer) 
    899         #self.vaos.append(vao) 
    900         #self.vaos.append(vao_outline) 
     927        self.vertex_buffers.append(vertex_buffer_id) 
     928        self.index_buffers.append(index_buffer_id) 
     929        self.vaos.append(vao_id) 
     930        self.vaos.append(outline_vao_id) 
    901931        self.commands.append(("scatter", [vao_id, outline_vao_id, (X,Y,Z), labels])) 
     932        self.updateGL() 
     933 
     934    def set_x_axis_map(self, map): 
     935        self.x_axis_map = map 
     936        self.updateGL() 
     937 
     938    def set_y_axis_map(self, map): 
     939        self.y_axis_map = map 
     940        self.updateGL() 
     941 
     942    def set_z_axis_map(self, map): 
     943        self.z_axis_map = map 
    902944        self.updateGL() 
    903945 
     
    906948        size_dlg.exec_() 
    907949 
    908     def save_to_file_direct(self, file_name): 
     950    def save_to_file_direct(self, file_name, size=None): 
    909951        img = self.grabFrameBuffer() 
     952        if size != None: 
     953            img = img.scaled(size) 
    910954        return img.save(file_name) 
    911955 
     
    917961 
    918962        projection = QMatrix4x4() 
    919         if self.ortho: 
     963        if self.use_ortho: 
    920964            projection.ortho(-width / self.ortho_scale, width / self.ortho_scale, 
    921965                             -height / self.ortho_scale, height / self.ortho_scale, 
     
    11081152        self.legend.clear() 
    11091153        self.x_axis_title = self.y_axis_title = self.z_axis_title = '' 
     1154        self.x_axis_map = self.y_axis_map = self.z_axis_map = None 
    11101155        self.updateGL() 
    11111156 
Note: See TracChangeset for help on using the changeset viewer.