def handle_rollback(table_id): if table_id in ["fly_v26", "fly_v31"]: raise cg_exceptions.InternalServerError( "Rollback not supported for this chunkedgraph table.") current_app.table_id = table_id user_id = str(g.auth_user["id"]) current_app.user_id = user_id target_user_id = request.args["user_id"] # Call ChunkedGraph cg = app_utils.get_cg(table_id) user_operations = all_user_operations(table_id) operation_ids = user_operations["operation_id"] timestamps = user_operations["timestamp"] operations = list(zip(operation_ids, timestamps)) operations.sort(key=lambda op: op[1]) for operation in operations: operation_id = operation[0] try: ret = cg.undo_operation(user_id=target_user_id, operation_id=operation_id) except cg_exceptions.LockingError as e: raise cg_exceptions.InternalServerError( "Could not acquire root lock for undo operation.") except (cg_exceptions.PreconditionError, cg_exceptions.PostconditionError) as e: raise cg_exceptions.BadRequest(str(e)) if ret.new_lvl2_ids.size > 0: trigger_remesh(table_id, ret.new_lvl2_ids, is_priority=False) return user_operations
def handle_redo(table_id): if table_id in ["fly_v26", "fly_v31"]: raise cg_exceptions.InternalServerError( "Redo not supported for this chunkedgraph table.") current_app.table_id = table_id data = json.loads(request.data) is_priority = request.args.get('priority', True, type=str2bool) user_id = str(g.auth_user["id"]) current_app.user_id = user_id current_app.logger.debug(data) # Call ChunkedGraph cg = app_utils.get_cg(table_id) operation_id = np.uint64(data["operation_id"]) try: ret = cg.redo(user_id=user_id, operation_id=operation_id) except cg_exceptions.LockingError as e: raise cg_exceptions.InternalServerError( "Could not acquire root lock for redo operation.") except (cg_exceptions.PreconditionError, cg_exceptions.PostconditionError) as e: raise cg_exceptions.BadRequest(str(e)) current_app.logger.debug(("after redo:", ret.new_root_ids)) current_app.logger.debug(("lvl2_nodes:", ret.new_lvl2_ids)) if ret.new_lvl2_ids.size > 0: trigger_remesh(table_id, ret.new_lvl2_ids, is_priority=is_priority) return ret
def oldest_timestamp(table_id): current_app.table_id = table_id user_id = str(g.auth_user["id"]) current_app.user_id = user_id cg = app_utils.get_cg(table_id) try: earliest_timestamp = cg.get_earliest_timestamp() except cg_exceptions.PreconditionError: raise cg_exceptions.InternalServerError("No timestamp available") return earliest_timestamp
def handle_split(table_id): current_app.table_id = table_id data = json.loads(request.data) is_priority = request.args.get('priority', True, type=str2bool) user_id = str(g.auth_user["id"]) current_app.user_id = user_id current_app.logger.debug(data) # Call ChunkedGraph cg = app_utils.get_cg(table_id) data_dict = {} for k in ["sources", "sinks"]: data_dict[k] = collections.defaultdict(list) for node in data[k]: node_id = node[0] x, y, z = node[1:] coordinate = np.array([x, y, z]) / cg.segmentation_resolution atomic_id = cg.get_atomic_id_from_coord( coordinate[0], coordinate[1], coordinate[2], parent_id=np.uint64(node_id), ) if atomic_id is None: raise cg_exceptions.BadRequest( f"Could not determine supervoxel ID for coordinates " f"{coordinate}.") data_dict[k]["id"].append(atomic_id) data_dict[k]["coord"].append(coordinate) current_app.logger.debug(data_dict) try: ret = cg.remove_edges( user_id=user_id, source_ids=data_dict["sources"]["id"], sink_ids=data_dict["sinks"]["id"], source_coords=data_dict["sources"]["coord"], sink_coords=data_dict["sinks"]["coord"], mincut=True, ) except cg_exceptions.LockingError as e: raise cg_exceptions.InternalServerError( "Could not acquire root lock for split operation.") except cg_exceptions.PreconditionError as e: raise cg_exceptions.BadRequest(str(e)) if ret.new_root_ids is None: raise cg_exceptions.InternalServerError( "Could not split selected segment groups.") current_app.logger.debug(("after split:", ret.new_root_ids)) current_app.logger.debug(("lvl2_nodes:", ret.new_lvl2_ids)) if len(ret.new_lvl2_ids) > 0: trigger_remesh(table_id, ret.new_lvl2_ids, is_priority=is_priority) return ret
def handle_merge(table_id): current_app.table_id = table_id nodes = json.loads(request.data) is_priority = request.args.get('priority', True, type=str2bool) user_id = str(g.auth_user["id"]) current_app.user_id = user_id current_app.logger.debug(nodes) assert len(nodes) == 2 # Call ChunkedGraph cg = app_utils.get_cg(table_id) atomic_edge = [] coords = [] for node in nodes: node_id = node[0] x, y, z = node[1:] coordinate = np.array([x, y, z]) / cg.segmentation_resolution atomic_id = cg.get_atomic_id_from_coord(coordinate[0], coordinate[1], coordinate[2], parent_id=np.uint64(node_id)) if atomic_id is None: raise cg_exceptions.BadRequest( f"Could not determine supervoxel ID for coordinates " f"{coordinate}.") coords.append(coordinate) atomic_edge.append(atomic_id) # Protection from long range mergers chunk_coord_delta = cg.get_chunk_coordinates( atomic_edge[0]) - cg.get_chunk_coordinates(atomic_edge[1]) if np.any(np.abs(chunk_coord_delta) > 3): raise cg_exceptions.BadRequest( "Chebyshev distance between merge points exceeded allowed maximum " "(3 chunks).") try: ret = cg.add_edges( user_id=user_id, atomic_edges=np.array(atomic_edge, dtype=np.uint64), source_coord=coords[:1], sink_coord=coords[1:], ) except cg_exceptions.LockingError as e: raise cg_exceptions.InternalServerError( "Could not acquire root lock for merge operation.") except cg_exceptions.PreconditionError as e: raise cg_exceptions.BadRequest(str(e)) if ret.new_root_ids is None: raise cg_exceptions.InternalServerError("Could not merge selected " "supervoxel.") current_app.logger.debug(("lvl2_nodes:", ret.new_lvl2_ids)) if len(ret.new_lvl2_ids) > 0: trigger_remesh(table_id, ret.new_lvl2_ids, is_priority=is_priority) return ret
def handle_split(table_id): current_app.request_type = "split" data = json.loads(request.data) user_id = str(request.remote_addr) current_app.logger.debug(data) # Call ChunkedGraph cg = app_utils.get_cg(table_id) data_dict = {} for k in ["sources", "sinks"]: data_dict[k] = collections.defaultdict(list) for node in data[k]: node_id = node[0] x, y, z = node[1:] x /= 2 y /= 2 coordinate = np.array([x, y, z]) current_app.logger.debug(("before", coordinate)) if not cg.is_in_bounds(coordinate): coordinate /= cg.segmentation_resolution coordinate[0] *= 2 coordinate[1] *= 2 current_app.logger.debug(("after", coordinate)) atomic_id = cg.get_atomic_id_from_coord(coordinate[0], coordinate[1], coordinate[2], parent_id=np.uint64( node_id)) if atomic_id is None: raise cg_exceptions.BadRequest( f"Could not determine supervoxel ID for coordinates " f"{coordinate}.") data_dict[k]["id"].append(atomic_id) data_dict[k]["coord"].append(coordinate) current_app.logger.debug(data_dict) lvl2_nodes = [] try: ret = cg.remove_edges(user_id=user_id, source_ids=data_dict["sources"]["id"], sink_ids=data_dict["sinks"]["id"], source_coords=data_dict["sources"]["coord"], sink_coords=data_dict["sinks"]["coord"], mincut=True, return_new_lvl2_nodes=True, remesh_preview=False) if len(ret) == 2: new_roots, lvl2_nodes = ret else: new_roots = ret except cg_exceptions.LockingError as e: raise cg_exceptions.InternalServerError( "Could not acquire root lock for split operation.") except cg_exceptions.PreconditionError as e: raise cg_exceptions.BadRequest(str(e)) if new_roots is None: raise cg_exceptions.InternalServerError( "Could not split selected segment groups." ) current_app.logger.debug(("after split:", new_roots)) t = threading.Thread(target=meshing_app_blueprint._mesh_lvl2_nodes, args=(cg.get_serialized_info(), lvl2_nodes)) t.start() # Return binary return app_utils.tobinary(new_roots)
def handle_merge(table_id): current_app.request_type = "merge" nodes = json.loads(request.data) user_id = str(request.remote_addr) current_app.logger.debug(nodes) assert len(nodes) == 2 # Call ChunkedGraph cg = app_utils.get_cg(table_id) atomic_edge = [] coords = [] for node in nodes: node_id = node[0] x, y, z = node[1:] x /= 2 y /= 2 coordinate = np.array([x, y, z]) if not cg.is_in_bounds(coordinate): coordinate /= cg.segmentation_resolution coordinate[0] *= 2 coordinate[1] *= 2 atomic_id = cg.get_atomic_id_from_coord(coordinate[0], coordinate[1], coordinate[2], parent_id=np.uint64(node_id)) if atomic_id is None: raise cg_exceptions.BadRequest( f"Could not determine supervoxel ID for coordinates " f"{coordinate}." ) coords.append(coordinate) atomic_edge.append(atomic_id) # Protection from long range mergers chunk_coord_delta = cg.get_chunk_coordinates(atomic_edge[0]) - \ cg.get_chunk_coordinates(atomic_edge[1]) if np.any(np.abs(chunk_coord_delta) > 3): raise cg_exceptions.BadRequest( "Chebyshev distance between merge points exceeded allowed maximum " "(3 chunks).") lvl2_nodes = [] try: ret = cg.add_edges(user_id=user_id, atomic_edges=np.array(atomic_edge, dtype=np.uint64), source_coord=coords[:1], sink_coord=coords[1:], return_new_lvl2_nodes=True, remesh_preview=False) if len(ret) == 2: new_root, lvl2_nodes = ret else: new_root = ret except cg_exceptions.LockingError as e: raise cg_exceptions.InternalServerError( "Could not acquire root lock for merge operation.") except cg_exceptions.PreconditionError as e: raise cg_exceptions.BadRequest(str(e)) if new_root is None: raise cg_exceptions.InternalServerError( "Could not merge selected supervoxel.") t = threading.Thread(target=meshing_app_blueprint._mesh_lvl2_nodes, args=(cg.get_serialized_info(), lvl2_nodes)) t.start() # Return binary return app_utils.tobinary(new_root)