Exemple #1
0
def triangle_normals(vlist):
    nt = len(vlist)//3
    from numpy import array, int32
    ta = array(range(3*nt), int32).reshape((nt,3))
    from chimerax.surface import calculate_vertex_normals
    na = calculate_vertex_normals(vlist, ta)
    return na
Exemple #2
0
def spherical_surface(
    session,
    radius_function,
    move=None,  # a Place instance to rotate and translate surface
    theta_steps=100,
    phi_steps=50,
    positive_color=(255, 100, 100, 255),  # red, green, blue, alpha, 0-255 
    negative_color=(100, 100, 255, 255)):

    # Compute vertices and vertex colors
    vertices = []
    colors = []
    for t in range(theta_steps):
        theta = (t / theta_steps) * 2 * pi
        ct, st = cos(theta), sin(theta)
        for p in range(phi_steps):
            phi = (p / (phi_steps - 1)) * pi
            cp, sp = cos(phi), sin(phi)
            r = radius_function(theta, phi)
            xyz = (r * sp * ct, r * sp * st, r * cp)
            vertices.append(xyz)
            color = positive_color if r >= 0 else negative_color
            colors.append(color)

    # Compute triangles, triples of vertex indices
    triangles = []
    for t in range(theta_steps):
        for p in range(phi_steps - 1):
            i = t * phi_steps + p
            t1 = (t + 1) % theta_steps
            i1 = t1 * phi_steps + p
            triangles.append((i, i + 1, i1 + 1))
            triangles.append((i, i1 + 1, i1))

    # Create numpy arrays
    from numpy import array, float32, uint8, int32
    va = array(vertices, float32)
    ca = array(colors, uint8)
    ta = array(triangles, int32)

    # Rotate and translate vertices to a new location.
    if move is not None:
        move.transform_points(va, in_place=True)

    # Compute average vertex normal vectors
    from chimerax.surface import calculate_vertex_normals
    na = calculate_vertex_normals(va, ta)

    # Create ChimeraX surface model
    from chimerax.core.models import Surface
    s = Surface('surface', session)
    s.set_geometry(va, na, ta)
    s.vertex_colors = ca
    session.models.add([s])

    return s
Exemple #3
0
 def _update_geometry(self):
     from chimerax.shape.shape import cylinder_geometry
     varray, tarray = cylinder_geometry(
         self.radius, self.thickness, max(2, int(self.thickness / 3 + 0.5)),
         max(40, int(20.0 * self.radius + 0.5)), True)
     from chimerax.geometry import translation, vector_rotation
     varray = (translation(self.plane.origin) * vector_rotation(
         (0, 0, 1), self.plane.normal)).transform_points(varray)
     from chimerax.surface import calculate_vertex_normals
     narray = calculate_vertex_normals(varray, tarray)
     self.set_geometry(varray, narray, tarray)
Exemple #4
0
def triangles_model(session,
                    points,
                    triangles,
                    name='vtk polygons',
                    color=(180, 180, 180, 255)):
    from chimerax.core.models import Surface
    m = Surface(name, session)
    from chimerax import surface
    normals = surface.calculate_vertex_normals(points, triangles)
    m.set_geometry(points, normals, triangles)
    m.color = color
    return m
Exemple #5
0
def slab_surface(va, ta, na, pad, sharp_edges=False):

    nv = len(va)
    nt = len(ta)

    from chimerax.surface import boundary_edges
    edges = boundary_edges(ta)
    ne = len(edges)
    if sharp_edges:
        nv2 = 4 * nv
        nt2 = 2 * nt + 6 * ne
    else:
        nv2 = 2 * nv
        nt2 = 2 * nt + 2 * ne
    from numpy import zeros
    varray = zeros((nv2, 3), va.dtype)
    narray = zeros((nv2, 3), na.dtype)
    tarray = zeros((nt2, 3), ta.dtype)

    # Two copies of vertices offset along normals by padding values.
    varray[:nv, :] = va + pad[1] * na
    varray[nv:2 * nv, :] = va + pad[0] * na
    narray[:nv, :] = na
    narray[nv:2 * nv, :] = -na

    if sharp_edges:
        # TODO: Copy just edge vertices instead of all vertices when making
        #       sharp edges.
        e = edges[:, 0]
        varray[2 * nv:3 * nv, :] = varray[:nv, :]
        varray[3 * nv:, :] = varray[nv:2 * nv, :]

    tarray[:nt, :] = ta
    # Reverse triangle orientation for inner face.
    tarray[nt:2 * nt, 0] = ta[:, 0] + len(va)
    tarray[nt:2 * nt, 1] = ta[:, 2] + len(va)
    tarray[nt:2 * nt, 2] = ta[:, 1] + len(va)

    # Stitch faces with band of triangles, two per boundary edge.
    if sharp_edges:
        band_triangles(tarray[2 * nt:, :], edges, 0, 2 * nv)
        band_triangles(tarray[2 * nt + 2 * ne:, :], edges, 2 * nv, 3 * nv)
        band_triangles(tarray[2 * nt + 4 * ne:, :], edges, 3 * nv, nv)
        # Set band normals.
        tband = tarray[2 * nt + 2 * ne:2 * nt + 4 * ne, :]
        from chimerax.surface import calculate_vertex_normals
        narray[2 * nv:, :] = calculate_vertex_normals(varray,
                                                      tband)[2 * nv:, :]
    else:
        band_triangles(tarray[2 * nt:, :], edges, 0, nv)

    return varray, narray, tarray
Exemple #6
0
def new_object(session, object_name, vertices, normals, texcoords, faces,
               voffset):

    if _need_vertex_split(faces):
        # Texture coordinates or normals do not match vertices order.
        # Need to make additional vertices if a vertex has different texture
        # coordinates or normals in different faces.
        vertices, normals, texcoords, triangles = _split_vertices(
            vertices, normals, texcoords, faces)
    else:
        triangles = faces

    if len(vertices) == 0:
        raise OBJError('OBJ file has no vertices')
    if len(normals) > 0 and len(normals) != len(vertices):
        raise OBJError(
            'OBJ file has different number of normals (%d) and vertices (%d)' %
            (len(normals), len(vertices)))
    if len(texcoords) > 0 and len(texcoords) != len(vertices):
        raise OBJError(
            'OBJ file has different number of texture coordinates (%d) and vertices (%d)'
            % (len(texcoords), len(vertices)))

    from chimerax.core.models import Surface
    #    model = Surface(object_name, session)
    #    model.SESSION_SAVE_DRAWING = True
    #    model.clip_cap = True
    model = WavefrontOBJ(object_name, session)

    from numpy import array, float32, int32, uint8
    if texcoords:
        model.texture_coordinates = array(texcoords, float32)
    ta = array(triangles, int32)
    if voffset > 0:
        ta -= voffset
    ta -= 1  # OBJ first vertex index is 1 while model first vertex index is 0
    va = array(vertices, float32)
    if normals:
        na = array(normals, float32)
    else:
        # na = None
        from chimerax.surface import calculate_vertex_normals
        na = calculate_vertex_normals(va, ta)
    model.set_geometry(va, na, ta)
    model.color = array((170, 170, 170, 255), uint8)
    return model
Exemple #7
0
def meshes_as_models(session, meshes, buf_arrays):

    mesh_models = []
    ba = buf_arrays
    from numpy import int32
    from chimerax.core.models import Surface
    for m in meshes:
        if 'primitives' not in m:
            raise glTFError('glTF mesh has no "primitives": %s' % str(j))
        pdlist = []
        for pi, p in enumerate(m['primitives']):
            if 'mode' in p and p['mode'] != GLTF_TRIANGLES:
                raise glTFError(
                    'glTF reader only handles triangles, got mode %d' %
                    p['mode'])
            if 'indices' not in p:
                raise glTFError('glTF missing "indices" in primitive %s' %
                                str(p))
            ta = ba[p['indices']]
            if len(ta.shape) == 1:
                ta = ta.reshape((len(ta) // 3, 3))
            ta = ta.astype(int32, copy=False)
            if 'attributes' not in p:
                raise glTFError('glTF missing "attributes" in primitive %s' %
                                str(p))
            pa = p['attributes']
            if 'POSITION' not in pa:
                raise glTFError(
                    'glTF missing "POSITION" attribute in primitive %s' %
                    str(p))
            va = ba[pa['POSITION']]
            if 'NORMAL' in pa:
                na = ba[pa['NORMAL']]
            else:
                from chimerax import surface
                na = surface.calculate_vertex_normals(va, ta)
            if 'COLOR_0' in pa:
                vc = ba[pa['COLOR_0']]
            else:
                vc = None
            pd = Surface('p%d' % pi, session)
            set_geometry(pd, va, na, vc, ta)
            pdlist.append(pd)
        mesh_models.append(pdlist)

    return mesh_models
Exemple #8
0
def create_mesh(session, c, transform, rgba, name):

    varray, tarray = mesh_geometry(c)
    if len(tarray) == 0:
        return None

    transform.transform_points(varray, in_place=True)

    from chimerax.core.models import Surface
    s = Surface(name, session)
    s.SESSION_SAVE_DRAWING = True
    s.clip_cap = True  # Cap surface when clipped
    from chimerax.surface import calculate_vertex_normals
    narray = calculate_vertex_normals(varray, tarray)
    s.set_geometry(varray, narray, tarray)
    rgba8 = [int(r * 255) for r in rgba]
    s.color = rgba8

    return s
def load_surface(session,
                 tensor_file,
                 sc=2.09,
                 theta_steps=100,
                 phi_steps=50,
                 positive_color=(255, 100, 100, 255),
                 negative_color=(100, 100, 255, 255),
                 marker_pos_color=(100, 255, 100, 255),
                 marker_neg_color=(255, 255, 100, 255)):

    Delta, Eta, Euler, Pos, Marker = load_tensor(tensor_file)

    from chimerax.core.models import Surface
    from chimerax.surface import calculate_vertex_normals, combine_geometry_vntc

    geom = list()

    for k, (delta, eta, euler, pos,
            marker) in enumerate(zip(Delta, Eta, Euler, Pos, Marker)):
        if marker == 1:
            pc = marker_pos_color
            nc = marker_neg_color
        else:
            pc = positive_color
            nc = negative_color
        xyz,tri,colors=spherical_surface(\
                                         delta=delta,eta=eta,euler=euler,pos=pos,\
                                         sc=sc,theta_steps=theta_steps,\
                                         phi_steps=phi_steps,\
                                         positive_color=pc,\
                                         negative_color=nc)

        norm_vecs = calculate_vertex_normals(xyz, tri)

        geom.append((xyz, norm_vecs, tri, colors))

    xyz, norm_vecs, tri, colors = combine_geometry_vntc(geom)
    s = Surface('surface', session)
    s.set_geometry(xyz, norm_vecs, tri)
    s.vertex_colors = colors
    session.models.add([s])

    return s
Exemple #10
0
def _show_surface(session, varray, tarray, color, mesh,
                  center, rotation, qrotation, coordinate_system,
                  slab, model_id, shape_name, edge_mask = None, sharp_slab = False):
        
    if center is not None or rotation is not None or qrotation is not None:
        from chimerax.geometry import Place, translation
        tf = Place()
        if rotation is not None:
            tf = rotation * tf
        if qrotation is not None:
            tf = qrotation * tf
        if center is not None:
            from chimerax.core.commands import Center
            if isinstance(center, Center):
                center = center.scene_coordinates()
            tf = translation(center) * tf
        varray = tf.transform_points(varray)
        
    from chimerax.surface import calculate_vertex_normals
    narray = calculate_vertex_normals(varray, tarray)
    
    if slab is not None:
        from chimerax.mask.depthmask import slab_surface
        varray, narray, tarray = slab_surface(varray, tarray, narray, slab,
                                              sharp_edges = sharp_slab)

    s = _surface_model(session, model_id, shape_name, coordinate_system)
    s.set_geometry(varray, narray, tarray)
    if color is not None:
        s.color = color
    if mesh:
        s.display_style = s.Mesh
    if edge_mask is not None:
        s.edge_mask = edge_mask    # Hide spokes of hexagons.
    _add_surface(s)

    return s
Exemple #11
0
def calculate_segmentation_surfaces(seg,
                                    where=None,
                                    each=None,
                                    region='all',
                                    step=None,
                                    color=None):
    # Warn if number of surfaces is large.
    if where is None and each is None:
        max_seg_id = _maximum_segment_id(seg)
        if max_seg_id > 100:
            from chimerax.core.errors import UserError
            raise UserError(
                'Segmentation %s (#%s) has %d segments (> 100).'
                ' To create surface for each segment use "each segment" option.'
                % (seg.name, seg.id_string, max_seg_id))

    # Compute surfaces
    conditions = (where if where else []) + ([each] if each else [])
    group, attribute_name = _which_segments(seg, conditions)
    matrix = seg.matrix(step=step, subregion=region)
    from . import segmentation_surfaces
    surfs = segmentation_surfaces(matrix, group)

    # Transform vertices from index to scene units and compute normals.
    geom = []
    tf = seg.matrix_indices_to_xyz_transform(step=step, subregion=region)
    for region_id, va, ta in surfs:
        tf.transform_points(va, in_place=True)
        from chimerax.surface import calculate_vertex_normals
        na = calculate_vertex_normals(va, ta)
        geom.append((region_id, va, na, ta))

    # Determine surface coloring.
    if color is None:
        attr = None if attribute_name == 'segment' else attribute_name
        colors = _attribute_colors(seg, attr).attribute_rgba

    # Create one or more surface models
    from chimerax.core.models import Surface
    from chimerax.surface import combine_geometry_xvnt
    segsurfs = []
    if each is None and len(geom) > 1:
        # Combine multiple surfaces into one.
        va, na, ta = combine_geometry_xvnt(geom)
        name = '%s %d %ss' % (seg.name, len(geom), attribute_name)
        s = Surface(name, seg.session)
        s.clip_cap = True  # Cap surface when clipped
        s.set_geometry(va, na, ta)
        if color is None:
            color_counts = [(colors[region_id], len(sva))
                            for region_id, sva, sna, sta in geom]
            s.vertex_colors = _vertex_colors(len(va), color_counts)
        else:
            s.color = color
        segsurfs.append(s)
    else:
        # Create multiple surface models
        for region_id, va, na, ta in geom:
            name = '%s %s %d' % (seg.name, attribute_name, region_id)
            s = Surface(name, seg.session)
            s.clip_cap = True  # Cap surface when clipped
            s.set_geometry(va, na, ta)
            s.color = colors[region_id] if color is None else color
            segsurfs.append(s)

    return segsurfs