Exemplo n.º 1
0
def test_fetch_synapses(client):
    nc = NC(type='ExR.*', regex=True, rois=['EB'])
    sc = SC(rois=['FB', 'LAL(R)'], primary_only=True)
    syn_df = fetch_synapses(nc, sc)
    assert set(syn_df['roi']) == {'FB', 'LAL(R)'}

    neuron_df, _count_df = fetch_neurons(nc)
    syn_df = syn_df.merge(neuron_df[['bodyId', 'type']],
                          'left',
                          on='bodyId',
                          suffixes=['_syn', '_body'])
    assert syn_df['type_body'].isnull().sum() == 0
    assert syn_df['type_body'].apply(lambda s: s.startswith('ExR')).all()
Exemplo n.º 2
0
    def get_pre_synaptic_positions(self, skid):
        # Fetch neuron with given body id
        neuron_criteria = NeuronCriteria(bodyId=skid)
        # Fetch all presynapses
        synapse_criteria = SynapseCriteria(type='pre')

        connectors = fetch_synapses(neuron_criteria, synapse_criteria)
        connectors.index = self._synapse_ids(connectors)
        connectors.index.name = 'connector_id'

        x = connectors["x"].to_numpy()
        y = connectors["y"].to_numpy()
        z = connectors["z"].to_numpy()
        pos_array, ids = np.vstack([z, y, x]).T, connectors.index.to_numpy()
        return [tuple(np.round(p).astype(np.uint64)) for p in pos_array], ids
def measure_tbar_mito_distances(seg_src,
                                mito_src,
                                body,
                                *,
                                search_configs=DEFAULT_SEARCH_CONFIGS,
                                npclient=None,
                                tbars=None,
                                valid_mitos=None):
    """
    Search for the closest mito to each tbar in a list of tbars
    (or any set of points, really).

    FIXME: Rename this function.  It works for more than just tbars.

    Args:
        seg_src:
            (server, uuid, instance) OR a flyemflows VolumeService
            Labelmap instance for the neuron segmentation.
        mito_src:
            (server, uuid, instance) OR a flyemflows VolumeService
            Labelmap instance for the mitochondria "supervoxel"
            segmentation -- not just the "masks".
        body:
            The body ID of interest, on which the tbars reside.
        search_configs:
            A list ``SearchConfig`` tuples.
            For each tbar, this function tries to locate a mitochondria within
            he given search radius, using data downloaded from the given scale.
            If the search fails and no mito can be found, the function tries
            again using the next search criteria in the list.
            The radius should always be specified in scale-0 units,
            regardless of the scale at which you want to perform the analysis.
            Additionally, the data will be downloaded at the specified scale,
            then downsampled (with continuity preserving downsampling) to a lower scale for analysis.
            Notes:
                - Scale 4 is too low-res.  Stick with scale-3 or better.
                - Higher radius is more expensive, but some of that expense is
                  recouped because all points that fall within the radius are
                  analyzed at once.  See _measure_tbar_mito_distances()
                  implementation for details.
            dilation_radius_s0:
                If dilation_radius_s0 is non-zero, the segmentation will be "repaired" to close
                gaps, using a procedure involving a dilation of the given radius.
            dilation_exclusion_buffer_s0:
                We want to close small gaps in the segmentation, but only if we think
                they're really a gap in the actual segmentation, not if they are merely
                fingers of the same branch that are actually connected outside of our
                analysis volume. The dilation procedure tends to form such spurious
                connections near the volume border, so this parameter can be used to
                exclude a buffer (inner halo) near the border from dilation repairs.
        npclient:
            ``neuprint.Client`` to use when fetching the list of tbars that belong
            to the given body, unless you provide your own tbar points in the next
            argument.
        tbars:
            A DataFrame of tbar coordinates at least with columns ``['x', 'y', 'z']``.
        valid_mitos:
            If provided, only the listed mito IDs will be considered valid as search targets.
    Returns:
        DataFrame of tbar coordinates, mito distances, and mito coordinates.
        Points for which no nearby mito could be found (after trying all the given search_configs)
        will be marked with `done=False` in the results.
    """
    assert search_configs[-1].is_final, "Last search config should be marked is_final"
    assert all([not cfg.is_final for cfg in search_configs[:-1]]), \
        "Only the last search config should be marked is_final (no others)."

    # Fetch tbars
    if tbars is None:
        tbars = fetch_synapses(body, SC(type='pre', primary_only=True), client=npclient)

    tbars = initialize_results(body, tbars)

    if valid_mitos is None or len(valid_mitos) == 0:
        valid_mito_mapper = None
    else:
        valid_mitos = np.asarray(valid_mitos, dtype=np.uint64)
        valid_mito_mapper = LabelMapper(valid_mitos, valid_mitos)

    with tqdm_proxy(total=len(tbars)) as progress:
        for row in tbars.itertuples():
            # can't use row.done -- itertuples might be out-of-sync
            done = tbars['done'].loc[row.Index]
            if done:
                continue

            loop_logger = None
            for cfg in search_configs:
                prefix = (f"({row.x}, {row.y}, {row.z}) [ds={cfg.download_scale} "
                          f"as={cfg.analysis_scale} r={cfg.radius_s0:4} dil={cfg.dilation_radius_s0:2}] ")
                loop_logger = PrefixedLogger(logger, prefix)

                prev_num_done = tbars['done'].sum()
                _measure_tbar_mito_distances(
                    seg_src, mito_src, body, tbars, row.Index, cfg, valid_mito_mapper, loop_logger)
                num_done = tbars['done'].sum()

                progress.update(num_done - prev_num_done)
                done = tbars['done'].loc[row.Index]
                if done:
                    break

                if not cfg.is_final:
                    loop_logger.info("Search failed for primary tbar. Trying next search config!")

            if not done:
                loop_logger.warning(f"Failed to find a nearby mito for tbar at point {(row.x, row.y, row.z)}")
                progress.update(1)

    failed = np.isinf(tbars['mito-distance'])
    succeeded = ~failed
    logger.info(f"Found mitos for {succeeded.sum()} tbars, failed for {failed.sum()} tbars")

    return tbars
    # tbars = fetch_synapses(body, SC(primary_only=True)).sort_values([*'xyz']).reset_index(drop=True)
    # #selections = (tbars[[*'xyz']] == (12773, 26869, 15604)).all(axis=1)
    # selections = (tbars[[*'xyz']] == (9117, 20980, 27398)).all(axis=1)
    # tbars = tbars.loc[selections]

    # EXPORT_DEBUG_VOLUMES = True
    # #body = 1005308608
    # body = 2178626284
    # #tbars = fetch_synapses(body, SC(type='pre', primary_only=True))
    # tbars = fetch_label('emdata4:8900', '3159', 'synapses', body, format='pandas')[[*'xyz', 'conf', 'kind']]
    # #selections = (tbars[[*'xyz']] == (25435,26339,21900)).all(axis=1)
    # #tbars = tbars.loc[selections]

    EXPORT_DEBUG_VOLUMES = True
    body = 300972942
    tbars = fetch_synapses(body, SC(primary_only=True)).sort_values([*'xyz']).reset_index(drop=True)
    # Many of these fall on the same hopeless segment(s).
    # They should mostly be skipped.
    selections = [
        (13333, 21208, 9755),
        (17800, 28214, 4821),
        (17817, 28222, 4629),
        (17821, 28225, 4640),
        (17823, 28225, 4646),
        (17832, 28212, 4659),
        (17832, 28213, 4676),
        (17905, 28250, 6020),
        (17910, 28253, 6004),
        (17919, 28251, 6003),
        (17921, 28258, 6000),
        (17923, 28255, 6000),
                      type='FB4Y',
                      cropped=False,
                      inputRois=['EB'],
                      min_roi_inputs=100,
                      min_pre=400)
''' inputRois: Only neurons which have inputs in EVERY one of the given ROIs will be matched (``regex`` cannot apply)
    min_roi_inputs: How many input (post) synapses a neuron must have in each ROI to satisfy criteria (only if 'inputRois' provided)
    min_pre: Exclude neurons that don't have at least this many t-bars (outputs) overall, regardless of how many t-bars exist in any particular ROI
'''

# Define synapse filter (i.e. which filters by roi, type, confidence)
ellipsoid_synapses = synapse_criteria = SC(rois='EB', primary_only=True)
'''i.e. get only synapses are found in the ellipsoid body (EB)'''

# Get synapses (from neuron)
synapses = fetch_synapses(fanshapedNeurons, ellipsoid_synapses)

# Plot the synapse positions in a 2D projection
fig, ax = plt.subplots(1, 1)
fig.set_figwidth(7)
fig.set_figheight(8)
ax.scatter(synapses['x'], synapses['z'], s=3)
ax.invert_yaxis()
plt.grid()
plt.box(False)
plt.show()

# ------------------------------------------
# Synapse connections
# ------------------------------------------
''' Fetch all synapse-synapse connections from a set of neurons. Provide a NeuronCriteria for the source
            but the mito masks are stored at 16nm resolution, use mito_scale_offset=1.
        npclient:
            ``neuprint.Client`` to use when fetching the list of tbars that belong
            to the given body, unless you provide your own tbar points in the next
            argument.
        tbars:
            A DataFrame of tbar coordinates at least with columns ``['x', 'y', 'z']``.
    Returns:
        DataFrame of tbar coordinates, mito distances, and mito coordinates.
        Points for which no nearby mito could be found (after trying all the given search_configs)
        will be marked with `done=False` in the results.
    """
    # Fetch tbars
    if tbars is None:
        tbars = fetch_synapses(body,
                               SC(type='pre', primary_only=True),
                               client=npclient)
    else:
        tbars = tbars.copy()

    tbars['body'] = body
    tbars['mito-distance'] = np.inf
    tbars['done'] = False
    tbars['mito-x'] = 0
    tbars['mito-y'] = 0
    tbars['mito-z'] = 0

    with tqdm_proxy(total=len(tbars)) as progress:
        for row in tbars.itertuples():
            if row.done:
                continue