Exemple #1
0
def body_edge_table():
    """
    Extract rows for a particular body from the merge table.
    Useful for debugging, or for warming up the merge graph cache.
    """
    global logger
    global MERGE_TABLE

    data = request.json
    user = data.get("user", "unknown")
    body_id = data["body-id"]
    server = data["server"] + ':' + str(data["port"])
    uuid = data["uuid"]
    segmentation_instance = data["segmentation-instance"]
    find_missing_edges = data.get("find-missing-edges", True)

    body_logger = PrefixedLogger(logger, f"User {user}: Body {body_id}: ")

    instance_info = DvidInstanceInfo(server, uuid, segmentation_instance)

    body_logger.info("Recevied body-edge-table request")

    try:
        session = default_dvid_session(appname='cleave-server', user=user)
        _mutid, _supervoxels, edges, scores = MERGE_GRAPH.extract_edges(*instance_info, body_id, find_missing_edges, session=session, logger=body_logger)
    except requests.HTTPError as ex:
        status_name = str(HTTPStatus(ex.response.status_code)).split('.')[1]
        if ex.response.status_code == HTTPStatus.NOT_FOUND:
            msg = f"Body not found: {body_id}"
        else:
            msg = f"Received error from DVID: {status_name}"
        body_logger.error(msg)
        return msg, ex.response.status_code

    response = StringIO()
    table = pd.DataFrame(edges, columns=['id_a', 'id_b'])
    table['score'] = scores
    table.to_csv(response, index=False, header=True)
    return response.getvalue()
Exemple #2
0
 def session_id(_):
     time.sleep(0.01)
     return id(default_dvid_session())
Exemple #3
0
def _run_cleave(data):
    """
    Helper function that actually performs the cleave,
    and can be run in a separate process.
    Must not use any flask functions.
    """
    global logger
    global MERGE_TABLE

    user = data.get("user", "unknown")
    method = data.get("method", DEFAULT_METHOD)
    body_id = data["body-id"]
    seeds = { int(k): v for k,v in data["seeds"].items() }
    server = data["server"] + ':' + str(data["port"])
    uuid = data["uuid"]
    segmentation_instance = data["segmentation-instance"]
    find_missing_edges = data.get("find-missing-edges", True)

    body_logger = PrefixedLogger(logger, f"User {user}: Body {body_id}: ")

    instance_info = DvidInstanceInfo(server, uuid, segmentation_instance)

    # Remove empty seed classes (if any)
    for label in list(seeds.keys()):
        if len(seeds[label]) == 0:
            del seeds[label]

    cleave_response = copy.copy(data)
    cleave_response["seeds"] = dict(sorted((k, sorted(v)) for (k,v) in data["seeds"].items()))
    cleave_response["assignments"] = {}
    cleave_response["warnings"] = []
    cleave_response["info"] = []

    if not data["seeds"]:
        msg = "Request contained no seeds!"
        body_logger.error(msg)
        body_logger.info(f"Responding with error PRECONDITION_FAILED.")
        cleave_response.setdefault("errors", []).append(msg)
        return cleave_response, HTTPStatus.PRECONDITION_FAILED # code 412

    # Extract this body's edges from the complete merge graph
    with Timer() as timer:
        try:
            session = default_dvid_session(appname='cleave-server', user=user)
            mutid, supervoxels, edges, scores = MERGE_GRAPH.extract_edges(*instance_info, body_id, find_missing_edges, session=session, logger=body_logger)
        except requests.HTTPError as ex:
            status_name = str(HTTPStatus(ex.response.status_code)).split('.')[1]
            if ex.response.status_code == HTTPStatus.NOT_FOUND:
                msg = f"Body not found: {body_id}"
            else:
                msg = f"Received error from DVID: {status_name}"
            body_logger.error(msg)
            body_logger.info(f"Responding with error {status_name}.")
            cleave_response.setdefault("errors", []).append(msg)
            return cleave_response, ex.response.status_code

    body_logger.info(f"Extracting body graph (mutid={mutid}) took {timer.timedelta}")

    unexpected_seeds = set(chain(*seeds.values())) - set(supervoxels)
    if unexpected_seeds:
        msg = f"Request contained seeds that do not belong to body: {sorted(unexpected_seeds)}"
        body_logger.error(msg)
        body_logger.info("Responding with error PRECONDITION_FAILED.")
        cleave_response.setdefault("errors", []).append(msg)
        return cleave_response, HTTPStatus.PRECONDITION_FAILED # code 412

    try:
        # Perform the cleave computation
        with Timer() as timer:
            results = cleave(edges, scores, seeds, supervoxels, method=method)
    except InvalidCleaveMethodError as ex:
        body_logger.error(str(ex))
        body_logger.info("Responding with error BAD_REQUEST.")
        cleave_response.setdefault("errors", []).append(str(ex))
        return cleave_response, HTTPStatus.BAD_REQUEST # code 400
        
    body_logger.info(f"Computing cleave took {timer.timedelta}")

    # Convert assignments to JSON
    df = pd.DataFrame({'node': supervoxels, 'label': results.output_labels})
    df.sort_values('node', inplace=True)
    for label, group in df.groupby('label'):
        cleave_response["assignments"][str(label)] = group['node'].tolist()

    if results.disconnected_components:
        msg = (f"Cleave result contains non-contiguous objects for seeds: "
               f"{sorted(results.disconnected_components)}")
        body_logger.warning(msg)
        cleave_response["info"].append(msg)

    if results.contains_unlabeled_components:
        num_unlabeled = len(cleave_response["assignments"]["0"])
        msg = f"Cleave result is not complete. {num_unlabeled} supervoxels remain unassigned."
        body_logger.error(msg)
        body_logger.warning(msg)
        cleave_response["warnings"].append(msg)

    body_logger.info("Sending cleave results")
    return ( cleave_response, HTTPStatus.OK )