def employees(self) -> List[dict]:
        r = requests.get(f"{self._baseUrl}/employees")
        if r.status_code != 200:
            raise ApiError(f"Endpoint responded with an error: {r.status_code}")
        else:
            response = r.json()
            if 'data' not in response:
                raise ApiError("Unexpected response contents for /employees")

            data = response['data']
            return data
Beispiel #2
0
    def wrapper(self, url, *args, **kwargs):
        kwargs['headers'] = {
            'Authorization': 'Token {}'.format(self._token),
            'Content-Type': 'application/json'
        }
        kwargs['verify'] = self._verify

        url = self._base_url + url

        try:
            response = func(self, url, *args, **kwargs)
        except requests.RequestException as e:
            raise ApiConnectionError('Connection to Management Console failed',
                                     e)

        if response.status_code >= 400:
            try:
                message = response.json().get('message', '')
            except JSONDecodeError:
                message = response.text

            if response.status_code == 401:
                raise ApiUnauthorizedError(message)

            raise ApiError(message)

        return response
Beispiel #3
0
def send_message():
    from models import Patient, Doctor, Message
    from errors import ApiError, ErrorCodes
    from tools import ok

    request_body = request.json
    patient_id = request_body["patient_id"]
    doctor_id = request_body["doctor_id"]
    from_patient = request_body["from_patient"]
    message_text = request_body["message_text"]

    patient = db.session.query(Patient).filter(
        Patient.id == patient_id).first()
    doctor = db.session.query(Doctor).filter(Doctor.id == doctor_id).first()

    if not patient or not doctor:
        return ApiError(
            status_code=ErrorCodes.BAD_REQUEST,
            message="Patient or doctor does not exist. Unable to send message"
        ).to_json()

    message = Message()
    message.date_sent = int(time.time())
    message.from_patient = from_patient
    message.message_text = message_text
    message.doctor_id = doctor_id
    message.patient_id = patient_id

    patient.messages.append(message)
    db.session.commit()

    return ok(message.to_json())
Beispiel #4
0
    def get_providers(self) -> tuple:
        url = urllib.parse.urljoin(self.__base_url, 'providers')
        response = requests.get(url, auth=self.__auth, timeout=20)
        if response.status_code != HTTPStatus.OK:
            raise ApiError(f"failed to query for providers {response}")

        payload = json.loads(response.content.decode('utf-8'))
        return tuple(self._to_provider(item) for item in payload)
Beispiel #5
0
def get_patient_data_in_time_window(last_name, first_name):
    from models import Patient, ActivityType, HeartRate, Steps
    from sqlalchemy import func
    from errors import ApiError, ErrorCodes
    from tools import ok

    start_unix_time = request.args.get("start")
    end_unix_time = request.args.get("end")

    if not start_unix_time or not end_unix_time:
        return ApiError(
            status_code=ErrorCodes.BAD_REQUEST,
            message=
            "Must include unix timestamps in query parameters start and end."
        ).to_json()

    try:
        start_unix_time = int(start_unix_time)
        end_unix_time = int(end_unix_time)
    except ValueError:
        return ApiError(
            status_code=ErrorCodes.BAD_REQUEST,
            message="Unix timestamps given in start and end must be integers"
        ).to_json()
    finally:
        patient = db.session.query(Patient).filter(
            func.lower(Patient.last_name) == func.lower(last_name) and
            func.lower(Patient.first_name) == func.lower(first_name)).first()

        activity_measures = patient.activity_type_measures.filter(
            (ActivityType.unix_timestamp >= start_unix_time)
            & (ActivityType.unix_timestamp <= end_unix_time)).all()
        heart_rates = patient.heart_rate_measures.filter(
            (HeartRate.unix_timestamp >= start_unix_time)
            & (HeartRate.unix_timestamp <= end_unix_time)).all()
        steps = patient.step_measures.filter(
            (Steps.unix_timestamp >= start_unix_time)
            & (Steps.unix_timestamp <= end_unix_time)).all()

        patient.activity_type_measures = activity_measures
        patient.heart_rate_measures = heart_rates
        patient.step_measures = steps
        return ok(patient.to_json())
Beispiel #6
0
    def get(self, only_current: bool = True) -> tuple:
        url_end = "notifications?only_current=" + 'true' if only_current else 'false'
        url = urllib.parse.urljoin(self.__base_url, url_end)
        r = requests.get(url, auth=self.__auth, timeout=5)
        if r.status_code != HTTPStatus.OK:
            raise ApiError(f"failed to query for notifications {r}")

        payload = json.loads(r.content.decode('utf-8'))
        return tuple(
            NotificationsRepo._to_notification(item) for item in payload)
Beispiel #7
0
    def create(self, notif: Notification) -> uuid:
        url = urllib.parse.urljoin(self.__base_url, 'notifications')
        data = NotificationsRepo._from_notification(notif)
        r = requests.post(url, auth=self.__auth, json=data, timeout=20)
        if r.status_code != HTTPStatus.CREATED:
            raise ApiError(f"error while storing notification {r.content}")

        if 'Location' in r.headers:
            location = r.headers.get('Location')
            return location.split('/')[-1]

        return
Beispiel #8
0
 def get_response(self, url):
     count = 0
     while True:
         try:
             response = requests.get(url)
             if response.status_code == 200:
                 break
             else:
                 raise
         except:
             if count > 5:
                 raise ApiError("Too many API failures %s" % url)
             time.sleep(10 * count)
             count += 1
             continue
     return response
Beispiel #9
0
 def _get_json(self, *args, **kwargs):
     r = self._get(*args, **kwargs)
     try:
         return r.json()
     except JSONDecodeError as e:
         raise ApiError('Response is not a json: {}. {}'.format(r.text, e))
Beispiel #10
0
 def _create(self, *args, **kwargs):
     r = self._post(*args, **kwargs)
     try:
         return r.json()['id']
     except JSONDecodeError as e:
         raise ApiError('Response is not a json: {}. {}'.format(r.text, e))
Beispiel #11
0
def compute_health_metrics_in_time_window(patient_id):
    from models import HeartRate
    from errors import ApiError, ErrorCodes
    from tools import ok

    start_unix_time = request.args.get("start")
    end_unix_time = request.args.get("end")

    if not start_unix_time or not end_unix_time:
        return ApiError(
            status_code=ErrorCodes.BAD_REQUEST,
            message=
            "Must include unix timestamps in query parameters start and end."
        ).to_json()

    try:
        start_unix_time = int(start_unix_time)
        end_unix_time = int(end_unix_time)
    except ValueError:
        return ApiError(
            status_code=ErrorCodes.BAD_REQUEST,
            message="Unix timestamps given in start and end must be integers"
        ).to_json()
    finally:
        payload = dict()

        # Produce a list of RR intervals based on time window
        rr_list = db.session.query(HeartRate).filter(
            (HeartRate.patient_id == patient_id)
            & (HeartRate.unix_timestamp >= start_unix_time)
            & (HeartRate.unix_timestamp <= end_unix_time)).with_entities(
                HeartRate.rr).all()
        rrs = [rr for rr_sublist in rr_list for rr in rr_sublist]

        if len(rrs) < 1:
            return ApiError(
                status_code=ErrorCodes.BAD_REQUEST,
                message="Insufficient RR intervals in time window {} to {}".
                format(start_unix_time, end_unix_time)).to_json()

        time_domain_measures = dict()
        non_linear_measures = dict()
        non_linear_measures["poincare"] = dict()

        def time_domain_worker():
            [ann, sdnn, p_nn50, p_nn20, r_mssd] = timeDomain(rrs)
            time_domain_measures["ann"] = ann
            time_domain_measures["sdnn"] = sdnn
            time_domain_measures["pnn50"] = p_nn50
            time_domain_measures["pnn20"] = p_nn20
            time_domain_measures["rmssd"] = r_mssd

        def sample_entropy_worker():
            try:
                r = 0.2 * np.std(rrs)
                non_linear_measures["sample_entropy"] = sampEn(rrs, 2, r)
            except ValueError:
                non_linear_measures["sample_entropy"] = 0.0

        def dfa_worker():
            non_linear_measures["dfa"] = dict()

            if len(rrs) > 0:
                upper_scale_limit = min(1000, len(rrs))
                [scales, f, alpha] = scalingExponent(rrs, 5, upper_scale_limit,
                                                     20, 1, 2)

                non_linear_measures["dfa"]["scales"] = scales.tolist()
                non_linear_measures["dfa"][
                    "fluctuation_coefficients"] = f.tolist()
                non_linear_measures["dfa"]["alpha"] = alpha

        def poincare_coefficient():
            coefficient = correlation_coef(rrs)
            non_linear_measures["poincare"][
                "correlation_coefficient"] = coefficient

        def eclipse_fitting():
            standard_deviations = eclipse_fitting_methods(rrs)
            non_linear_measures["poincare"]["standard_deviations"] = dict()
            non_linear_measures["poincare"]["standard_deviations"][
                "sd1"] = standard_deviations["SD1"]
            non_linear_measures["poincare"]["standard_deviations"][
                "sd2"] = standard_deviations["SD2"]
            non_linear_measures["poincare"]["rr1"] = rrs[:-1]
            non_linear_measures["poincare"]["rr2"] = rrs[1:]

        t1 = Thread(target=time_domain_worker)
        t2 = Thread(target=sample_entropy_worker)
        t3 = Thread(target=dfa_worker)
        t4 = Thread(target=poincare_coefficient)
        t5 = Thread(target=eclipse_fitting)
        threads = [t1, t2, t3, t4, t5]
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        t5.start()

        for thread in threads:
            thread.join()

        payload["time_domain_measures"] = time_domain_measures
        payload["non_linear_measures"] = non_linear_measures

        return ok(payload)
Beispiel #12
0
 def delete(self, notif_uuid: uuid) -> bool:
     url = urllib.parse.urljoin(self.__base_url,
                                f"notifications/{notif_uuid}")
     r = requests.delete(url, auth=self.__auth, timeout=20)
     if r.status_code != HTTPStatus.NO_CONTENT:
         raise ApiError(f"error while deleting notification {r.content}")