Skip to content

API Usage

Aditya Chinchure edited this page Aug 28, 2020 · 3 revisions

Once you have set up the infrastructure, you can start using LEAP.

Unlike the usual HTTP-based API, LEAP's API is a way to code your own algorithms to run it in a federated manner. You can use the API in two ways:

1. Predefined functions:

If the function you want to use is already defined in the Leap API, you can import it and use it directly. The following is an example of using a predefined function for count ("COUNT_ALGO").

Below we have a simple example on how to count the number of patients on each hospital site that are older than 50 and have a bmi of less than 25.

import sys
sys.path.append("../")
import api.leap as leap
import api.leap_fn as leap_fn
import api.register.user.registration as user_reg
from proto import computation_msgs_pb2

def predef_count_selector():
    leap_predef = leap_fn.PredefinedFunction(computation_msgs_pb2.AlgoCodes.COUNT_ALGO)
    selector = {"type": "default", "filter": "[age] > 50 and [bmi] < 25", "useLocalData": False}
    leap_predef.selector = selector
    return leap_predef

def distributed(sites, auth_token):
    leap_fn = predef_count_selector()
    dist_leap = leap.DistributedLeap(leap_fn, "127.0.0.1:50000", auth_token)
    print(dist_leap.get_result(sites))

if __name__ == "__main__":
    user_reg.register_user("TestUser2", "1234561", "127.0.0.1:50000")
    auth_res = user_reg.authenticate_user("TestUser", "123456", "127.0.0.1:50000")
    distributed([1], auth_res.token)

2. Writing your own algorithm

To create an algorithm, that counts the number of patients on each site you need to write the 8 abstract functions of Leap. For example:

import pdb
import json
import inspect
import numpy as np

# Sum a particular column

def map_fns():

    def map_fn1(data, state):
        COUNT_SENSITIVITY = 1
        epsilon = privacy_params["epsilon"]
        delta = privacy_params["delta"]


        if delta == 0:
            noise = np.random.laplace(loc = 0, scale = COUNT_SENSITIVITY/float(epsilon), size = (1,1))
        else:
            sigma = (COUNT_SENSITIVITY/(epsilon))*np.sqrt(2*np.log(1.25/delta))
            noise = np.random.normal(0.0, sigma, 1)

        count = len(data) + noise.item()
        result = {
            "count": count
        }
        return json.dumps(result)

    return [map_fn1]

def agg_fns():

    def agg_fn1(map_results):
        s = 0
        for result in map_results:
            result = json.loads(result)
            s += result["count"]
        return s
    return [agg_fn1]

def update_fns():

    def update_fn1(agg_result, state):
        state["i"] += 1
        return state

    return [update_fn1]

# Returns which map/agg fn to run
def choice_fn(state):
    return 0

def dataprep_fn(data):
    return data

def stop_fn(agg_result, state):
    return state["i"] == 1

def postprocessing_fn(agg_result, state):
    return agg_result

def init_state_fn():
    state = {
        "i": 0,
    }
    return state

Now just send those functions over to Leap and get the result:

def distributed(sites, auth_token):
    udf_count = leap_fn.UDF()
    selector = {"type": "default", "filter": "[age] > 50 and [bmi] < 25", "useLocalData": False}
    udf_count.selector = selector
    udf_count.map_fns = map_fns
    udf_count.update_fns = update_fns
    udf_count.agg_fns = agg_fns
    udf_count.choice_fn = choice_fn
    udf_count.stop_fn = stop_fn
    udf_count.dataprep_fn = dataprep_fn
    udf_count.postprocessing_fn = postprocessing_fn
    udf_count.init_state_fn = init_state_fn
    dist_leap = leap.DistributedLeap(udf_count, "127.0.0.1:50000", auth_token)
    print(dist_leap.get_result(sites))

if __name__ == "__main__":
    user_reg.register_user("TestUser2", "1234561", "127.0.0.1:50000")
    auth_res = user_reg.authenticate_user("TestUser", "123456", "127.0.0.1:50000")
    distributed([1], auth_res.token)