ChimeraX Recipes

Colored axes, coverslip and timestamp

Shayne Quinn asked about axis colored outline boxes for lightsheet microscopy data, showing a cover slip as a gray rectangle, and showing a time stamp, on the ChimeraX mailing list. These tasks can be done with the shape, marker, and 2dlabel ChimeraX commands and the Python code just simplifies specifying the positions to align axes and coverslip slab with already opened 3d image data. Below is Python code defining 3 ChimeraX commands to show those things. Opening the Python code in ChimeraX defines the commands.

open lightsheet.py

And here is an example use of the 3 commands.

open cell15.am
outline #1
coverslip #1 thickness 2
timestamp

There are additional options to these commands to set axis thickness, colors (name or red,green,blue,opacity), and timestamp position that you can see in the Python code. Here are examples of these options.

  outline #1 edgeRadius .5
  coverslip #1 color lightblue
  coverslip #1 color 90,90,90,30
  timestamp xpos .5 ypos .9 color yellow

Here is the Python code lightsheet.py

    #
    # Shayne Quinn asked about axis colored outline boxes for lightsheet data,
    # showing a cover slip as a gray rectangle, and showing a time stamp, on
    # the ChimeraX mailing list:
    #
    # https://www.rbvi.ucsf.edu/pipermail/chimerax-users/2022-October/004467.html
    #
    def colored_volume_outline(session, volume, edge_radius = None):

        # First create a box outline around the volume with the shape command.
        xyz_min, xyz_max = volume.xyz_bounds()
        xsize,ysize,zsize = [x2-x1 for x1,x2 in zip(xyz_min, xyz_max)]
        xmid,ymid,zmid = [0.5*(x1+x2) for x1,x2 in zip(xyz_min, xyz_max)]
        shape_cmd = f'shape rectangle width {xsize} height {ysize} slab {zsize} center {xmid},{ymid},{zmid} widthdivisions 1 heightdivisions 1 mesh true'
        from chimerax.core.commands import run
        s = run(session, shape_cmd)

        # Eliminate the diagonal lines in the outline box
        run(session, f'surface squaremesh {s.atomspec}')

        # Convert the outline box to a fake molecule with atoms and bonds.
        if edge_radius is None:
            edge_radius = max(volume.data.step)  # Use grid spacing for edge radius.
        m = run(session, f'marker fromMesh {s.atomspec} edgeRadius {edge_radius}')
        run(session, f'rename {m.atomspec} "Colored axes"')

        # Close the outline.
        run(session, f'close {s.atomspec}')

        # Color the bonds.
        red, green, blue = (255,0,0,255), (0,255,0,255), (0,0,255,255) # RGBA values
        axis_colors = {0: blue, 1: green, 2: red}
        for b in m.bonds:
            a1,a2 = b.atoms
            from numpy import absolute
            axis = absolute(a2.coord - a1.coord).argmax()
            b.color = axis_colors[axis]

        return m

    def cover_slip(session, volume, thickness = 1, color = (180,180,180,80)):

        # First create a rectangular with the shape command near the z=0 face of the volume.
        xyz_min, xyz_max = volume.xyz_bounds()
        xyz_max[2] = thickness
        xsize,ysize,zsize = [x2-x1 for x1,x2 in zip(xyz_min, xyz_max)]
        xmid,ymid,zmid = [0.5*(x1+x2) for x1,x2 in zip(xyz_min, xyz_max)]
        from chimerax.core.colors import hex_color
        shape_cmd = f'shape rectangle width {xsize} height {ysize} slab {zsize} center {xmid},{ymid},{zmid} color {hex_color(color)} name coverslip'
        from chimerax.core.commands import run
        s = run(session, shape_cmd)
        return s

    def time_stamp(session, xpos = .1, ypos = .05, color = None):
        from datetime import datetime
        date = datetime.now().ctime()
        from chimerax.core.commands import run
        label = run(session, f'2dlabel text "{date}" xpos {xpos} ypos {ypos}')
        return label

    def register_command(session):
        from chimerax.core.commands import CmdDesc, register, FloatArg, Color8Arg
        from chimerax.map import MapArg
        desc = CmdDesc(required=[('volume', MapArg)],
                       keyword=[('edge_radius', FloatArg)],
                       synopsis='Show red,blue,green colored volume outline box')
        register('outline', desc, colored_volume_outline, logger=session.logger)

        desc = CmdDesc(required=[('volume', MapArg)],
                       keyword=[('thickness', FloatArg),
                                ('color', Color8Arg)],
                       synopsis='Show rectangular box at base of map')
        register('coverslip', desc, cover_slip, logger=session.logger)

        desc = CmdDesc(keyword=[('xpos', FloatArg),
                                ('ypos', FloatArg),
                                ('color', Color8Arg)],
                       synopsis='Show timestamp label')
        register('timestamp', desc, time_stamp, logger=session.logger)

    register_command(session)

Tom Goddard, October 20, 2022