def estimate_scale_correction(morphology: Morphology,
                              soma_depth: float,
                              soma_marker_z: float,
                              cut_thickness: Optional[float] = 350):
    """
        Estimate a scale factor to correct the reconstructed morphology
        for slice shrinkage

        Prior to reconstruction, the slice shrinks due to evaporation.
        This is most notable in the z axis, which is the slice thickness.

        To correct for shrinkage we compare soma depth within the slice
        obtained soon after cutting the slice to the fixed_soma_depth obtained
        during the reconstruction. Then the scale correction is estimated as:
        scale  = soma_depth / fixed_soma_depth.
        This is sensible as long as the z span of the corrected reconstruction
        is contained  within the slice thickness. Thus we also estimate
        the maximum scale correction as:
        scale_max  = cut_thickness / z_span,
        and take the smaller of scale and scale_max


        Parameters
        ----------
        morphology: Morphology object
        soma_depth: recorded depth of the soma when it was sliced
        soma_marker_z: soma marker z value from revised marker file
                       (z is on the slice surface for the marker file)
        cut_thickness: thickness of the cut slice

        Returns
        -------
        scale factor correction

    """
    soma_morph_z = morphology.get_soma()['z']
    fixed_depth = np.abs(soma_morph_z - soma_marker_z)
    scale = soma_depth / fixed_depth

    node_z = [node['z'] for node in morphology.nodes()]
    z_range = np.max(node_z) - np.min(node_z)
    scale_max = cut_thickness / z_range

    if scale > scale_max:
        scale = scale_max
        warnings.warn(f"Shrinkage scale correction factor: {scale} "
                      f"exceeded the max allowed value: {scale_max}. "
                      f"Will correct for shrinkage using the maximum value."
                      )

    return scale
def morphology_png_to_s3(bucket: str, key: str, morphology: Morphology):

    tmp_path = key.split("/")[-1]

    nodes = morphology.nodes()
    x = [node['x'] for node in nodes]
    y = [node['y'] for node in nodes]
    z = [node['z'] for node in nodes]

    fig, ax = plt.subplots(1, 2)
    ax[0].scatter(x, y, s=0.1)
    ax[0].set_title('x-y view')
    ax[1].scatter(z, y, s=0.1)
    ax[1].set_title('z-y view')
    fig.suptitle(tmp_path[:-4], fontsize=16)
    fig.savefig(tmp_path)

    s3.upload_file(Filename=tmp_path, Bucket=bucket, Key=key)
    os.remove(tmp_path)
    return key
Example #3
0
    def transform_morphology(
        self,
        morphology: Morphology,
        clone: bool = False,
        scale_radius: bool = True,
    ) -> Morphology:
        """
            Apply this transform to all nodes in a morphology.

            Parameters
            ----------
            morphology: a Morphology loaded from an swc file
            clone: make a new object if True
            scale_radius: apply radius scaling if True

            Returns
            -------
            A Morphology
        """
        if clone:
            morphology = morphology.clone()

        if scale_radius:
            scaling_factor = self._get_scaling_factor()
        else:
            scaling_factor = 1

        for node in morphology.nodes():
            coordinates = np.array((node['x'], node['y'], node['z']),
                                   dtype=float)
            new_coordinates = self.transform(coordinates)
            node['x'] = new_coordinates[0]
            node['y'] = new_coordinates[1]
            node['z'] = new_coordinates[2]
            # approximate with uniform scaling in each dimension
            node['radius'] *= scaling_factor

        return morphology