예제 #1
0
파일: viewer.py 프로젝트: snilek/sfepy
    def build_mlab_pipeline(self, file_source=None, is_3d=False,
                            layout='rowcol',
                            scalar_mode='iso_surface',
                            vector_mode='arrows_norm',
                            rel_scaling=None, clamping=False,
                            ranges=None, is_scalar_bar=False,
                            is_wireframe=False, opacity=None,
                            subdomains_args=None,
                            rel_text_width=None,
                            filter_names=None, group_names=None,
                            only_names=None,
                            domain_specific=None, **kwargs):
        """Sets self.source, self.is_3d_data """
        opacities = get_opacities(opacity)

        file_source = get_default(file_source, self.file_source,
                                  'file_source not set!')
        filter_names = get_default(filter_names, [])
        domain_specific = get_default(domain_specific, {})

        if subdomains_args is not None:
            is_subdomains = True
            file_source.setup_mat_id(subdomains_args['mat_id_name'],
                                     subdomains_args['single_color'])

        else:
            is_subdomains = False

        self.source = source = self.file_source()
        data_ranges = get_data_ranges(source, return_only=True)

        # Hack to prevent mayavi switching to point scalar on source
        # change.
        if len(source._point_scalars_list):
            source.point_scalars_name = ''

        bbox = file_source.get_bounding_box()
        dx = 1.1 * (bbox[1,:] - bbox[0,:])

        float_eps = nm.finfo(nm.float64).eps
        self.is_3d_data = abs(dx[2]) > (10.0 * float_eps)

        p_names, c_names = self.get_data_names(source, detailed=True)
        names = p_names + c_names
        if only_names is None:
            names = [ii for ii in names if ii[2] not in filter_names]

        else:
            # Use order of only_names.
            _names = []
            aux = [ii[2] for ii in names]
            for name in only_names:
                try:
                    ii = aux.index(name)
                except ValueError:
                    output('ignoring nonexistent name: %s' % name)
                    continue
                _names.append(names[ii])

            if len(_names) != len(only_names):
                output('warning: some names were not found!')
            if not len(_names):
                raise ValueError('no names were found! (%s not in %s)'
                                 % (only_names, [name[2] for name in names]))
            names = _names

        if group_names is not None:
            ndict = {}
            for name in names:
                ndict[name[2]] = name

            repeat = []
            _names = []
            aux = set(name[2] for name in names)
            for group in group_names:
                aux.difference_update(group)
                repeat.append(len(group))
                for name in group:
                    _names.append(ndict[name])

            repeat.extend([1] * len(aux))
            n_pos = len(repeat)

            names = _names
            n_data = len(names)

        else:
            n_pos = n_data = len(names)
            repeat = [1] * n_data

        def _make_iterator(repeat, n_row, n_col):
            ii = 0
            for ij, iric in enumerate(cycle((n_row, n_col))):
                ir, ic = iric
                if ij < len(repeat):
                    for ik in xrange(repeat[ij]):
                        yield ii, ir, ic
                        ii += 1

        n_row, n_col = get_position_counts(n_pos, layout)
        if layout[:3] == 'col':
            iterator = _make_iterator(repeat, n_col, n_row)
        else:
            iterator = _make_iterator(repeat, n_row, n_col)

        max_label_width = nm.max([len(ii[2]) for ii in names] + [5]) + 2

        if c_names:
            ctp = mlab.pipeline.cell_to_point_data(source)

        else:
            ctp = None

        self.scalar_bars = []

        for ii, ir, ic in iterator:
            if layout[:3] == 'col':
                ir, ic = ic, ir
            if ii == n_data: break
            family, kind, name = names[ii]
            data_range = data_ranges[name]

            is_magnitude = False
            position = nm.array([dx[0] * ic, dx[1] * (n_row - ir - 1), 0])
            output(family, kind, name, 'at', position)
            output('range: %.2e %.2e l2 norm range: %.2e %.2e' % data_range[3:])

            if name in domain_specific:
                if ctp is None:
                    ctp = mlab.pipeline.cell_to_point_data(source)

                ds = domain_specific[name]
                out = ds(source, ctp, bbox, position, family, kind, name)
                if len(out) == 4:
                    kind, name, active, bars = out
                    self.scalar_bars.extend(bars)

                else:
                    kind, name, active = out

            elif kind == 'scalars':
                if family == 'point':
                    active = mlab.pipeline.set_active_attribute(source)

                else:
                    if is_3d and ('iso_surface' in scalar_mode):
                        active = mlab.pipeline.set_active_attribute(ctp)

                    else:
                        active = mlab.pipeline.set_active_attribute(source)

                setattr(active, '%s_%s_name' % (family, kind), name)

                if is_3d:
                    if 'cut_plane' in scalar_mode:
                        op = opacities['scalar_cut_plane']
                        add_scalar_cut_plane(active, position, [1, 0, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active, position, [0, 1, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active, position, [0, 0, 1],
                                             opacity=op)
                    if 'iso_surface' in scalar_mode:
                        active.point_scalars_name = name
                        add_iso_surface(active, position,
                                        opacity=opacities['iso_surface'])
                else:
                    add_surf(active, position, opacity=opacities['surface'])

            elif kind == 'vectors':
                if family == 'point':
                    active = mlab.pipeline.set_active_attribute(source)
                else:
                    active = mlab.pipeline.set_active_attribute(ctp)
                active.point_vectors_name = name

                if (ranges is not None) and (name in ranges):
                    sf = get_glyphs_scale_factor(ranges[name],
                                                 rel_scaling, bbox)
                else:
                    sf = None

                if 'arrows' in vector_mode:
                    glyphs = add_glyphs(active, position, bbox,
                                        rel_scaling=rel_scaling,
                                        clamping=clamping)
                    if sf is not None:
                        glyphs.glyph.glyph.scale_factor = sf

                if 'warp' in vector_mode:
                    active = mlab.pipeline.warp_vector(active)
                    active.filter.scale_factor = rel_scaling

                if 'norm' in vector_mode:
                    active = mlab.pipeline.extract_vector_norm(active)
                    if 'arrows' in vector_mode:
                        op = opacities['arrows_surface']
                    else:
                        op = opacities['surface']
                    add_surf(active, position, opacity=op)

                if is_3d:
                    if 'cut_plane' in vector_mode:
                        op = opacities['vector_cut_plane']
                        for normal in [[1, 0, 0], [0, 1, 0], [0, 0, 1]]:
                            vcp = add_vector_cut_plane(active,
                                                       position, normal, bbox,
                                                       rel_scaling=rel_scaling,
                                                       clamping=clamping,
                                                       opacity=op)
                            if sf is not None:
                                vcp.glyph.glyph.scale_factor = sf

            elif kind == 'tensors':
                if family == 'point':
                    active = mlab.pipeline.set_active_attribute(source)
                else:
                    active = mlab.pipeline.set_active_attribute(ctp)
                active.point_tensors_name = name

                active = mlab.pipeline.extract_tensor_components(active)
                is_magnitude = True
                if is_3d:
                    if 'cut_plane' in scalar_mode:
                        op = opacities['scalar_cut_plane']
                        add_scalar_cut_plane(active, position, [1, 0, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active, position, [0, 1, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active, position, [0, 0, 1],
                                             opacity=op)
                    if 'iso_surface' in scalar_mode:
                        add_iso_surface(active, position,
                                        opacity=opacities['iso_surface'])
                else:
                    add_surf(active, position, opacity=opacities['surface'])

            else:
                raise ValueError('bad kind! (%s)' % kind)

            if (ranges is not None) and (name in ranges):
                mm = active.children[0]
                if (kind == 'scalars') or (kind == 'tensors'):
                    lm = mm.scalar_lut_manager

                else: # kind == 'vectors':
                    lm = mm.vector_lut_manager

                lm.use_default_range = False
                lm.data_range = ranges[name]

            if is_subdomains:
                add_subdomains_surface(source, position, **subdomains_args)

            if is_wireframe:
                surf = add_surf(source, position,
                                opacity=opacities['wireframe'])
                surf.actor.property.representation = 'wireframe'
                surf.actor.mapper.scalar_visibility = False

            if is_scalar_bar:
                mm = active.children[0]
                if (kind == 'scalars') or (kind == 'tensors'):
                    lm = mm.scalar_lut_manager

                else: # kind == 'vectors':
                    lm = mm.vector_lut_manager

                self.scalar_bars.append((family, name, lm))

            if rel_text_width > (10 * float_eps):
                position[2] = 0.5 * dx[2]
                if is_magnitude:
                    name = '|%s|' % name
                add_text(active, position, name,
                         float(rel_text_width * len(name))
                         / float(max_label_width), color=self.fgcolor)

        if not names:
            # No data, so just show the mesh.
            surf = add_surf(source, (0.0, 0.0, 0.0),
                            opacity=opacities['surface'])
            surf.actor.property.color = (0.8, 0.8, 0.8)

            if is_subdomains:
                add_subdomains_surface(source, (0.0, 0.0, 0.0),
                                       **subdomains_args)

            if is_wireframe:
                surf = add_surf(source, (0.0, 0.0, 0.0),
                                opacity=opacities['wireframe'])
                surf.actor.property.representation = 'wireframe'
                surf.actor.mapper.scalar_visibility = False
예제 #2
0
    def build_mlab_pipeline(self,
                            file_source=None,
                            is_3d=False,
                            layout='rowcol',
                            scalar_mode='iso_surface',
                            vector_mode='arrows_norm',
                            rel_scaling=None,
                            clamping=False,
                            ranges=None,
                            is_scalar_bar=False,
                            is_wireframe=False,
                            opacity=None,
                            subdomains_args=None,
                            rel_text_width=None,
                            filter_names=None,
                            group_names=None,
                            only_names=None,
                            domain_specific=None,
                            **kwargs):
        """Sets self.source, self.is_3d_data """
        opacities = get_opacities(opacity)

        file_source = get_default(file_source, self.file_source,
                                  'file_source not set!')
        filter_names = get_default(filter_names, [])
        domain_specific = get_default(domain_specific, {})

        if subdomains_args is not None:
            is_subdomains = True
            file_source.setup_mat_id(subdomains_args['mat_id_name'],
                                     subdomains_args['single_color'])

        else:
            is_subdomains = False

        self.source = source = self.file_source()
        data_ranges = get_data_ranges(source, return_only=True)

        # Hack to prevent mayavi switching to point scalar on source
        # change.
        if len(source._point_scalars_list):
            source.point_scalars_name = ''

        bbox = file_source.get_bounding_box()
        bx = bbox[1, :] - bbox[0, :]
        dx = 1.1 * bx

        float_eps = nm.finfo(nm.float64).eps
        self.is_3d_data = abs(dx[2]) > (10.0 * float_eps)

        p_names, c_names = self.get_data_names(source, detailed=True)
        names = p_names + c_names
        if only_names is None:
            names = [ii for ii in names if ii[2] not in filter_names]

        else:
            # Use order of only_names.
            _names = []
            aux = [ii[2] for ii in names]
            for name in only_names:
                try:
                    ii = aux.index(name)
                except ValueError:
                    output('ignoring nonexistent name: %s' % name)
                    continue
                _names.append(names[ii])

            if len(_names) != len(only_names):
                output('warning: some names were not found!')
            if not len(_names):
                raise ValueError('no names were found! (%s not in %s)' %
                                 (only_names, [name[2] for name in names]))
            names = _names

        if group_names is not None:
            ndict = {}
            for name in names:
                ndict[name[2]] = name

            repeat = []
            _names = []
            aux = set(name[2] for name in names)
            for group in group_names:
                aux.difference_update(group)
                repeat.append(len(group))
                for name in group:
                    _names.append(ndict[name])

            repeat.extend([1] * len(aux))
            n_pos = len(repeat)

            names = _names
            n_data = len(names)

        else:
            n_pos = n_data = len(names)
            repeat = [1] * n_data

        def _make_iterator(repeat, n_row, n_col):
            ii = 0
            for ij, iric in enumerate(cycle((n_row, n_col))):
                ir, ic = iric
                if ij < len(repeat):
                    for ik in range(repeat[ij]):
                        yield ii, ir, ic
                        ii += 1

        n_row, n_col = get_position_counts(n_pos, layout)
        if layout[:3] == 'col':
            iterator = _make_iterator(repeat, n_col, n_row)
        else:
            iterator = _make_iterator(repeat, n_row, n_col)

        max_label_width = nm.max([len(ii[2]) for ii in names] + [5]) + 2

        # Scene dimensions.
        wx = dx * (nm.array([n_col, n_row, 0])) - 0.1 * bx

        if c_names:
            ctp = mlab.pipeline.cell_to_point_data(source)

        else:
            ctp = None

        self.scalar_bars = []

        for ii, ir, ic in iterator:
            if layout[:3] == 'col':
                ir, ic = ic, ir
            if ii == n_data: break
            family, kind, name = names[ii]
            data_range = data_ranges[name]

            is_magnitude = False
            position = nm.array([
                dx[0] * ic - 0.5 * wx[0],
                dx[1] * (n_row - ir - 1) - 0.5 * wx[1], 0
            ])
            output(family, kind, name, 'at', position)
            output('range: %.2e %.2e l2 norm range: %.2e %.2e' %
                   data_range[3:])

            if name in domain_specific:
                if ctp is None:
                    ctp = mlab.pipeline.cell_to_point_data(source)

                ds = domain_specific[name]
                out = ds(source, ctp, bbox, position, family, kind, name)
                if len(out) == 4:
                    kind, name, active, bars = out
                    self.scalar_bars.extend(bars)

                else:
                    kind, name, active = out

            elif kind == 'scalars':
                if family == 'point':
                    active = mlab.pipeline.set_active_attribute(source)

                else:
                    if is_3d and ('iso_surface' in scalar_mode):
                        active = mlab.pipeline.set_active_attribute(ctp)

                    else:
                        active = mlab.pipeline.set_active_attribute(source)

                setattr(active, '%s_%s_name' % (family, kind), name)

                if is_3d:
                    if 'cut_plane' in scalar_mode:
                        op = opacities['scalar_cut_plane']
                        add_scalar_cut_plane(active,
                                             position, [1, 0, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active,
                                             position, [0, 1, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active,
                                             position, [0, 0, 1],
                                             opacity=op)
                    if 'iso_surface' in scalar_mode:
                        active.point_scalars_name = name
                        add_iso_surface(active,
                                        position,
                                        opacity=opacities['iso_surface'])
                else:
                    add_surf(active, position, opacity=opacities['surface'])

            elif kind == 'vectors':
                if family == 'point':
                    active = mlab.pipeline.set_active_attribute(source)
                else:
                    active = mlab.pipeline.set_active_attribute(ctp)
                active.point_vectors_name = name

                if (ranges is not None) and (name in ranges):
                    sf = get_glyphs_scale_factor(ranges[name], rel_scaling,
                                                 bbox)
                else:
                    sf = None

                if 'arrows' in vector_mode:
                    glyphs = add_glyphs(active,
                                        position,
                                        bbox,
                                        rel_scaling=rel_scaling,
                                        clamping=clamping)
                    if sf is not None:
                        glyphs.glyph.glyph.scale_factor = sf

                if 'warp' in vector_mode:
                    active = mlab.pipeline.warp_vector(active)
                    active.filter.scale_factor = rel_scaling

                if 'norm' in vector_mode:
                    active = mlab.pipeline.extract_vector_norm(active)
                    if 'arrows' in vector_mode:
                        op = opacities['arrows_surface']
                    else:
                        op = opacities['surface']
                    add_surf(active, position, opacity=op)

                if is_3d:
                    if 'cut_plane' in vector_mode:
                        op = opacities['vector_cut_plane']
                        for normal in [[1, 0, 0], [0, 1, 0], [0, 0, 1]]:
                            vcp = add_vector_cut_plane(active,
                                                       position,
                                                       normal,
                                                       bbox,
                                                       rel_scaling=rel_scaling,
                                                       clamping=clamping,
                                                       opacity=op)
                            if sf is not None:
                                vcp.glyph.glyph.scale_factor = sf

            elif kind == 'tensors':
                if family == 'point':
                    active = mlab.pipeline.set_active_attribute(source)
                else:
                    active = mlab.pipeline.set_active_attribute(ctp)
                active.point_tensors_name = name

                active = mlab.pipeline.extract_tensor_components(active)
                is_magnitude = True
                if is_3d:
                    if 'cut_plane' in scalar_mode:
                        op = opacities['scalar_cut_plane']
                        add_scalar_cut_plane(active,
                                             position, [1, 0, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active,
                                             position, [0, 1, 0],
                                             opacity=op)
                        add_scalar_cut_plane(active,
                                             position, [0, 0, 1],
                                             opacity=op)
                    if 'iso_surface' in scalar_mode:
                        add_iso_surface(active,
                                        position,
                                        opacity=opacities['iso_surface'])
                else:
                    add_surf(active, position, opacity=opacities['surface'])

            else:
                raise ValueError('bad kind! (%s)' % kind)

            if (ranges is not None) and (name in ranges):
                mm = active.children[0]
                if (kind == 'scalars') or (kind == 'tensors'):
                    lm = mm.scalar_lut_manager

                else:  # kind == 'vectors':
                    lm = mm.vector_lut_manager

                lm.use_default_range = False
                lm.data_range = ranges[name]

            if is_subdomains:
                add_subdomains_surface(source, position, **subdomains_args)

            if is_wireframe:
                surf = add_surf(source,
                                position,
                                opacity=opacities['wireframe'])
                surf.actor.property.representation = 'wireframe'
                surf.actor.mapper.scalar_visibility = False

            if is_scalar_bar:
                mm = active.children[0]
                if (kind == 'scalars') or (kind == 'tensors'):
                    lm = mm.scalar_lut_manager

                else:  # kind == 'vectors':
                    lm = mm.vector_lut_manager

                self.scalar_bars.append((family, name, lm))

            if rel_text_width > (10 * float_eps):
                position[2] = 0.5 * dx[2]
                if is_magnitude:
                    name = '|%s|' % name
                add_text(active,
                         position,
                         name,
                         float(rel_text_width * len(name)) /
                         float(max_label_width),
                         color=self.fgcolor)

        if not names:
            # No data, so just show the mesh.
            surf = add_surf(source, (0.0, 0.0, 0.0),
                            opacity=opacities['surface'])
            surf.actor.property.color = (0.8, 0.8, 0.8)

            if is_subdomains:
                add_subdomains_surface(source, (0.0, 0.0, 0.0),
                                       **subdomains_args)

            if is_wireframe:
                surf = add_surf(source, (0.0, 0.0, 0.0),
                                opacity=opacities['wireframe'])
                surf.actor.property.representation = 'wireframe'
                surf.actor.mapper.scalar_visibility = False

        set_colormap(source, self.colormap)