Example #1
0
    def accessible_surface(self,
                           radius,
                           nump=100,
                           superradius=200,
                           include_edges=True,
                           view_mesh=False,
                           savefig=None,
                           write_cmm_file=None,
                           verbose=False,
                           chimera_bin='chimera'):
        """
        Calculates a mesh surface around the model (distance equal to input
        **radius**) and checks if each point of this mesh could be replaced by
        an object (i.e. a protein) of a given **radius**

        Outer part of the model can be excluded from the estimation of
        accessible surface, as the occupancy outside the model is unknown (see
        superradius option).

        :param radius: radius of the object we want to fit in the model.
        :param None write_cmm_file: path to file in which to write cmm with the
           colored meshed (red inaccessible points, green accessible points)
        :param 100 nump: number of points to draw around a given particle. This
           number also sets the number of points drawn around edges, as each
           point occupies a given surface (see maths below). *Note that this
           number is considerably lowered by the occupancy of edges, depending
           of the angle formed by the edges surrounding a given particle, only
           10% to 50% of the ``nump`` will be drawn in fact.*
        :param True include_edges: if False, edges will not be included in the
           calculation of the accessible surface, only particles. Note that
           statistics on particles (like last item returned) will not change,
           and computation time will be significantly decreased.
        :param False view_mesh: launches chimera to display the mesh around the
           model
        :param None savefig: path where to save chimera image
        :param 'chimera' chimera_bin: path to chimera binary to use
        :param False verbose: prints stats about the surface
        :param 200 superradius: radius of an object used to exclude outer
           surface of the model. Superradius must be higher than radius.

        This function will first define a mesh around the chromatin,
        representing all possible position of the center of the object we want
        to fit. This mesh will be at a distance of *radius* from the chromatin
        strand. All dots in the mesh represents an equal area (*a*), the whole
        surface of the chromatin strand being: :math:`A=n \\times a` (*n* being
        the total number of dots in the mesh).

        The mesh consists of spheres around particles of the model, and
        cylinders around edges joining particles (no overlap is allowed between
        sphere and cylinders or cylinder and cylinder when they are
        consecutive).

        If we want that all dots of the mesh representing the surface of the
        chromatin, corresponds to an equal area (:math:`a`)

        .. math::

          a = \\frac{4\pi r^2}{s} = \\frac{2\pi r N_{(d)}}{c}

        with:

        * :math:`r` radius of the object to fit (as the input parameter **radius**)
        * :math:`s` number of points in sphere
        * :math:`c` number of points in circle (as the input parameter **nump**)
        * :math:`N_{(d)}` number of circles in an edge of length :math:`d`

        According to this, when the distance between two particles is equal
        to :math:`2r` (:math:`N=2r`), we would have :math:`s=c`.

        As :

        .. math::

          2\pi r = \sqrt{4\pi r^2} \\times \sqrt{\pi}

        It is fair to state the number of dots represented along a circle as:

        .. math::

          c = \sqrt{s} \\times \sqrt{\pi}

        Thus the number of circles in an edge of length :math:`d` must be:

        .. math::

          N_{(d)}=\\frac{s}{\sqrt{s}\sqrt{\pi}}\\times\\frac{d}{2r}

        :returns: a list of *1-* the number of dots in the mesh that could be
           occupied by an object of the given radius *2-* the total number of
           dots in the mesh *3-* the estimated area of the mesh (in square
           micrometers) *4-* the area of the mesh of a virtually straight strand
           of chromatin defined as
           :math:`contour\\times 2\pi r + 4\pi r^2` (also in
           micrometers) *5-* a list of number of (accessibles, inaccessible) for
           each particle (percentage burried can be infered afterwards by
           accessible/(accessible+inaccessible) )

        """

        points, dots, superdots, points2dots = build_mesh(
            self['x'], self['y'], self['z'], len(self), nump, radius,
            superradius, include_edges)

        # calculates the number of inaccessible peaces of surface
        if superradius:
            radius2 = (superradius - 4)**2
            outdot = []
            for x2, y2, z2 in superdots:
                for j, (x1, y1, z1) in enumerate(points):
                    if fast_square_distance(x1, y1, z1, x2, y2, z2) < radius2:
                        outdot.append(False)
                        break
                else:
                    outdot.append(True)
                    continue
                points.insert(0, points.pop(j))
        else:
            outdot = [False] * len(superdots)

        # calculates the number of inaccessible peaces of surface
        radius2 = (radius - 2)**2
        grey = (0.6, 0.6, 0.6)
        red = (1, 0, 0)
        green = (0, 1, 0)
        colors = []
        for i, (x2, y2, z2) in enumerate(dots):
            if outdot[i]:
                colors.append(grey)
                continue
            for j, (x1, y1, z1) in enumerate(points):
                if fast_square_distance(x1, y1, z1, x2, y2, z2) < radius2:
                    colors.append(red)
                    break
            else:
                colors.append(green)
                continue
            points.insert(0, points.pop(j))
        possibles = colors.count(green)

        acc_parts = []
        for p in sorted(points2dots.keys()):
            acc = 0
            ina = 0
            for dot in points2dots[p]:
                if colors[dot] == green:
                    acc += 1
                elif colors[dot] == red:
                    ina += 1
            acc_parts.append((p + 1, acc, ina))

        # some stats
        dot_area = 4 * pi * (float(radius) / 1000)**2 / nump
        area = (possibles * dot_area)
        total = (self.contour() / 1000 * 2 * pi * float(radius) / 1000 +
                 4 * pi * (float(radius) / 1000)**2)
        if verbose:
            print((' Accessible surface: %s micrometers^2' +
                   '(%s accessible times %s micrometers)') %
                  (round(area, 2), possibles, dot_area))
            print('    (%s accessible dots of %s total times %s micrometers)' %
                  (possibles, outdot.count(False), round(dot_area, 5)))
            print('  - %s%% of the contour mesh' % (round(
                (float(possibles) / outdot.count(False)) * 100, 2)))
            print('  - %s%% of a virtual straight chromatin (%s microm^2)' %
                  (round((area / total) * 100, 2), round(total, 2)))

        # write cmm file
        if savefig:
            view_mesh = True
        if write_cmm_file or view_mesh:
            out = '<marker_set name=\"2\">\n'
            form = ('<marker id=\"%s\" x=\"%s\" y=\"%s\" z=\"%s\"' +
                    ' r=\"%s\" g=\"%s\" b=\"%s\" ' + 'radius=\"7\"/>\n')
            for k_2, thing in enumerate(dots):
                out += form % (1 + k_2, thing[0], thing[1], thing[2],
                               colors[k_2][0], colors[k_2][1], colors[k_2][2])
            if superradius:
                for k_3, thing in enumerate(superdots):
                    out += form % (1 + k_3 + k_2 + 1, thing[0], thing[1],
                                   thing[2], 0.1, 0.1, 0.1)
            out += '</marker_set>\n'
            if view_mesh:
                out_f = open('/tmp/tmp_mesh.cmm', 'w')
                out_f.write(out)
                out_f.close()
            if write_cmm_file:
                out_f = open(write_cmm_file, 'w')
                out_f.write(out)
                out_f.close()
        if view_mesh:
            chimera_cmd = [
                'focus', 'bonddisplay never #1',
                'shape tube #1 radius 15 bandLength 300 segmentSubdivisions 1 followBonds on',
                '~show #1', 'set bg_color white', 'windowsize 800 600',
                'clip yon -500', 'set subdivision 1', 'set depth_cue',
                'set dc_color black', 'set dc_start 0.5', 'set dc_end 1',
                'scale 0.8'
            ]
            if savefig:
                if savefig.endswith('.png'):
                    chimera_cmd += ['copy file %s png' % (savefig)]
                elif savefig[-4:] in ('.mov', 'webm'):
                    chimera_cmd += [
                        'movie record supersample 1', 'turn y 3 120',
                        'wait 120', 'movie stop',
                        'movie encode output %s' % savefig
                    ]
            self.write_cmm('/tmp/')
            chimera_view([
                '/tmp/tmp_mesh.cmm',
                '/tmp/model.%s.cmm' % (self['rand_init'])
            ],
                         chimera_bin=chimera_bin,
                         align=False,
                         savefig=savefig,
                         chimera_cmd=chimera_cmd)

        return (possibles, outdot.count(False), area, total, acc_parts)
Example #2
0
    def accessible_surface(self, radius, nump=100, superradius=200,
                           include_edges=True, view_mesh=False, savefig=None,
                           write_cmm_file=None, verbose=False,
                           chimera_bin='chimera'):
        """
        Calculates a mesh surface around the model (distance equal to input
        **radius**) and checks if each point of this mesh could be replaced by
        an object (i.e. a protein) of a given **radius**

        Outer part of the model can be excluded from the estimation of
        accessible surface, as the occupancy outside the model is unkown (see
        superradius option).

        :param radius: radius of the object we want to fit in the model.
        :param None write_cmm_file: path to file in which to write cmm with the
           colored meshed (red inaccessible points, green accessible points)
        :param 100 nump: number of points to draw around a given particle. This
           number also sets the number of points drawn around edges, as each
           point occupies a given surface (see maths below). *Note that this
           number is considerably lowered by the occupancy of edges, depending
           of the angle formed by the edges surrounding a given particle, only
           10% to 50% of the ``nump`` will be drawn in fact.*
        :param True include_edges: if False, edges will not be included in the
           calculation of the accessible surface, only particles. Note that
           statistics on particles (like last item returned) will not change,
           and computation time will be significantly decreased.
        :param False view_mesh: launches chimera to display the mesh around the
           model
        :param None savefig: path where to save chimera image
        :param 'chimera' chimera_bin: path to chimera binary to use
        :param False verbose: prints stats about the surface
        :param 200 superradius: radius of an object used to exclude outer
           surface of the model. Superradius must be higher than radius.

        This function will first define a mesh around the chromatin,
        representing all possible position of the center of the object we want
        to fit. This mesh will be at a distance of *radius* from the chromatin
        strand. All dots in the mesh represents an equal area (*a*), the whole
        surface of the chromatin strand being: :math:`A=n \\times a` (*n* being
        the total number of dots in the mesh).

        The mesh consists of spheres around particles of the model, and
        cylinders around edges joining particles (no overlap is allowed between
        sphere and cylinders or cylinder and cylinder when they are
        consecutive).
        
        If we want that all dots of the mesh representing the surface of the
        chromatin, corresponds to an equal area (:math:`a`)

        .. math::

          a = \\frac{4\pi r^2}{s} = \\frac{2\pi r N_{(d)}}{c}

        with:

        * :math:`r` radius of the object to fit (as the input parameter **radius**)
        * :math:`s` number of points in sphere
        * :math:`c` number of points in circle (as the input parameter **nump**)
        * :math:`N_{(d)}` number of circles in an edge of length :math:`d`

        According to this, when the distance between two particles is equal
        to :math:`2r` (:math:`N=2r`), we would have :math:`s=c`.

        As :

        .. math::

          2\pi r = \sqrt{4\pi r^2} \\times \sqrt{\pi}
        
        It is fair to state the number of dots represented along a circle as:

        .. math::

          c = \sqrt{s} \\times \sqrt{\pi}

        Thus the number of circles in an edge of length :math:`d` must be:

        .. math::

          N_{(d)}=\\frac{s}{\sqrt{s}\sqrt{\pi}}\\times\\frac{d}{2r}

        :returns: a list of *1-* the number of dots in the mesh that could be
           occupied by an object of the given radius *2-* the total number of
           dots in the mesh *3-* the estimated area of the mesh (in square
           micrometers) *4-* the area of the mesh of a virtually straight strand
           of chromatin defined as 
           :math:`contour\\times 2\pi r + 4\pi r^2` (also in
           micrometers) *5-* a list of number of (accessibles, inaccessible) for
           each particle (percentage burried can be infered afterwards by
           accessible/(accessible+inaccessible) )

        """

        points, dots, superdots, points2dots = build_mesh(
            self['x'], self['y'], self['z'], len(self), nump, radius,
            superradius, include_edges)
        
        # calculates the number of inaccessible peaces of surface
        if superradius:
            radius2 = (superradius - 4)**2
            outdot  = []
            for x2, y2, z2 in superdots:
                for j, (x1, y1, z1) in enumerate(points):
                    if fast_square_distance(x1, y1, z1, x2, y2, z2) < radius2:
                        outdot.append(False)
                        break
                else:
                    outdot.append(True)
                    continue
                points.insert(0, points.pop(j))
        else:
            outdot = [False] * len(superdots)

        # calculates the number of inaccessible peaces of surface
        radius2 = (radius - 2)**2
        grey    = (0.6, 0.6, 0.6)
        red     = (1, 0, 0)
        green   = (0, 1, 0)
        colors  = []
        for i, (x2, y2, z2) in enumerate(dots):
            if outdot[i]:
                colors.append(grey)
                continue
            for j, (x1, y1, z1) in enumerate(points):
                if fast_square_distance(x1, y1, z1, x2, y2, z2) < radius2:
                    colors.append(red)
                    break
            else:
                colors.append(green)
                continue
            points.insert(0, points.pop(j))
        possibles = colors.count(green)

        acc_parts = []
        for p in sorted(points2dots.keys()):
            acc = 0
            ina = 0
            for dot in points2dots[p]:
                if colors[dot]==green:
                    acc += 1
                elif colors[dot]==red:
                    ina += 1
            acc_parts.append((p + 1, acc, ina))

        # some stats
        dot_area = 4 * pi * (float(radius) / 1000)**2 / nump
        area = (possibles * dot_area)
        total = (self.contour() / 1000 * 2 * pi * float(radius) / 1000 + 4 * pi
                 * (float(radius) / 1000)**2)
        if verbose:
            print (' Accessible surface: %s micrometers^2' +
                   '(%s accessible times %s micrometers)') % (
                round(area, 2), possibles, dot_area)
            print '    (%s accessible dots of %s total times %s micrometers)' % (
                possibles, outdot.count(False), round(dot_area, 5))
            print '  - %s%% of the contour mesh' % (
                round((float(possibles)/outdot.count(False))*100, 2))
            print '  - %s%% of a virtual straight chromatin (%s microm^2)' % (
                round((area/total)*100, 2), round(total, 2))

        # write cmm file
        if savefig:
            view_mesh = True
        if write_cmm_file or view_mesh:
            out = '<marker_set name=\"2\">\n'
            form = ('<marker id=\"%s\" x=\"%s\" y=\"%s\" z=\"%s\"' +
                    ' r=\"%s\" g=\"%s\" b=\"%s\" ' +
                    'radius=\"7\"/>\n')
            for k_2, thing in enumerate(dots):
                out += form % (1 + k_2, thing[0], thing[1], thing[2],
                                colors[k_2][0], colors[k_2][1], colors[k_2][2])
            if superradius:
                for k_3, thing in enumerate(superdots):
                    out += form % (1 + k_3 + k_2 + 1,
                                   thing[0], thing[1], thing[2],
                                    0.1, 0.1, 0.1)
            out += '</marker_set>\n'
            if view_mesh:
                out_f = open('/tmp/tmp_mesh.cmm', 'w')
                out_f.write(out)
                out_f.close()
            if write_cmm_file:
                out_f = open(write_cmm_file, 'w')
                out_f.write(out)
                out_f.close()
        if view_mesh:
            chimera_cmd = [
                'focus',
                'bonddisplay never #1',
                'shape tube #1 radius 15 bandLength 300 segmentSubdivisions 1 followBonds on',
                '~show #1',
                'set bg_color white', 'windowsize 800 600',
                'clip yon -500', 'set subdivision 1', 'set depth_cue',
                'set dc_color black', 'set dc_start 0.5', 'set dc_end 1',
                'scale 0.8']
            if savefig:
                if savefig.endswith('.png'):
                    chimera_cmd += ['copy file %s png' % (savefig)]
                elif savefig[-4:] in ('.mov', 'webm'):
                    chimera_cmd += [
                        'movie record supersample 1', 'turn y 3 120',
                        'wait 120', 'movie stop',
                        'movie encode output %s' % savefig]
            self.write_cmm('/tmp/')
            chimera_view(['/tmp/tmp_mesh.cmm',
                          '/tmp/model.%s.cmm' % (self['rand_init'])],
                         chimera_bin=chimera_bin, align=False,
                         savefig=savefig, chimera_cmd=chimera_cmd)

        return (possibles, outdot.count(False), area, total, acc_parts)