예제 #1
0
def uuid_index(request):
    status_code = Constant.HTTP_SUCCESS_STATUS_CODE
    status = Constant.STATUS_SUCCESS
    message = ''

    if validate_http_request_method(request, 'POST', True) == False:
        return create_json_response(
            400,
            'error',
            message=
            'Bad request 1! This API endpoint only handles POST request.')

    body_unicode = request.body.decode('utf-8')

    # validate if the request body is in JSON format
    try:
        # { "uuid": "33d84b2a-9e39-11eb-a8b3-0242ac130003" }
        body = json.loads(body_unicode)
    except Exception as e:
        logger.error(str(e))
        return create_json_response(
            400,
            'error',
            message=
            'Bad request! The request data have to be in a valid JSON format.')

    uuid = Uuid.objects.filter(uuid=body['uuid'])

    logger.info('checking UUID availaliy')

    # UUID is valid
    if uuid.count() == 0:
        try:
            uuid = Uuid(uuid=body['uuid'])
            uuid.save()
        except Exception as e:
            return create_json_response(status_code, 'error', message=str(e))

        status = 'success'
        message = 'The UUID is vaild.'
    else:
        # UUID is invalid
        status = 'error'
        message = 'The UUID already existed.'

    return create_json_response(status_code, status, message=message)
예제 #2
0
def stress_index(request):
    # success HTTP status code as default value
    status_code = Constant.HTTP_SUCCESS_STATUS_CODE
    sample_rate = Constant.SAMPLE_RATE
    mode = Constant.HRV_MODE
    diff = 0
    message = ''
    dataframe = None
    hr_threshold = Constant.HR_THRESHOLD
    base_data_length = get_base_line_size(Constant.FREQUENCY)
    hrv_threshold = Constant.HRV_THRESHOLD
    pnn50_threshold = Constant.PNN50_THRESHOLD
    status = Constant.STATUS_SUCCESS
    status_basic = Constant.STATUS_SUCCESS
    status_sliding = Constant.STATUS_SUCCESS
    data = {}
    isJobCreated = False

    if validate_http_request_method(request, 'POST', True) == False:
        return create_json_response(
            400,
            'error',
            message=
            'Bad request 2! This API endpoint only handles POST request.')

    try:
        # Handle the request from the client-end
        body_unicode = request.body.decode('utf-8')

        # Convert the json into a dataframe
        body = json.loads(body_unicode)

        # Convert the json into a dataframe for further processing
        dataframe = pd.DataFrame.from_dict(body)

        device_code = dataframe['Device'].iloc[0]
        uuid = dataframe['uuid'].iloc[0]
        user_id = dataframe['User_ID'].iloc[0]

        request_model = Request()
        request_model.device = device_code
        request_model.hr = round(dataframe['HR'].astype(int).mean(axis=0), 2)
        request_model.time = 0
        request_model.timedate = 0
        request_model.uuid = uuid
        request_model.ppg = round(dataframe['PPG'].astype(float).mean(axis=0),
                                  2)
        request_model.user_id = user_id
        request_model.save()

        if not isJobCreated:
            create_job(uuid, device_code, Constant.FREQUENCY, hr_threshold,
                       hrv_threshold, base_data_length)
            isJobCreated = True

    except Exception as e:
        return create_json_response(500,
                                    'error',
                                    data={'raw_request_body': request.data},
                                    message=str(e))

    # @todo: validate the mode value, the mode parameter should be optional
    mode = request.GET.get('mode')

    # Get the first value of the device column (as the device code value will never change from a same device)
    device_code = dataframe['Device'].iloc[0]

    # Get the first value of the uuid column (as the device code value will never change from a same experiment)
    uuid = dataframe['uuid'].iloc[0]
    filtered_response = Response.objects.filter(device_code=device_code,
                                                uuid=uuid)

    # Calculate the average hear rate based on HR column
    hr_mean = round(dataframe['HR'].astype(float).mean(axis=0), 2)
    # Calculate the HRV RMSSD value from the base data (first n mins, e.g. 5)
    hrv_rmssd_mean = list(filtered_response[1:base_data_length].aggregate(
        Avg('hrv_rmssd')).values())[0]
    base_hr_mean = list(filtered_response[1:base_data_length].aggregate(
        Avg('hr_mean')).values())[0]
    pnn50_mean = list(filtered_response[1:base_data_length].aggregate(
        Avg('hrv_pnn50')).values())[0]

    logger.info("================================================")
    logger.info(hrv_rmssd_mean)
    logger.info(base_hr_mean)
    logger.info(pnn50_mean)
    logger.info("================================================")

    if mode == 'hr':
        # compare the mean value with recent request
        if filtered_response.count() > 0:
            # extract the recent mean
            diff = hr_mean - base_hr_mean

        # if the changes is bigger than the pre-defined threshold
        if diff >= hr_threshold:
            status = 'warning'
            message = 'HRV RMSSD has been changed significantly. You probably under stress.'

        data = {
            'mode': mode,
            'device': device_code,
            'uuid': uuid,
            'HR_MEAN': hr_mean
        }
    elif mode == 'hrv':
        # logger.info('==================')
        # logger.info(dataframe['PPG'])
        # logger.info(type(dataframe['PPG']))
        # logger.info(dataframe.dtypes)
        # logger.info(dataframe['PPG'].astype(float).div(1000000).to_numpy())
        # logger.info(type(dataframe['PPG'].astype(float).div(1000000)))
        # logger.info('==================')
        normalized_ppg_data = get_normalized_ppg_data(dataframe)

        # Compute HRV indices
        try:
            hrv_indices = calculate_hrv(normalized_ppg_data, sample_rate)
        except ValueError:
            status = 'error'
            message = 'Please wear the polarOH1 properly.'
            data = {
                'mode': mode,
                'device': device_code,
                'uuid': uuid,
                'hr_mean': hr_mean
            }
            data['message'] = message
            return create_json_response(status_code,
                                        status,
                                        data,
                                        message=message)

        # Convert HRV output into json format
        result = hrv_indices.to_json()
        parsed = json.loads(result)

        stress_info = detect_stress(filtered_response, base_data_length,
                                    parsed, hrv_threshold, hrv_rmssd_mean,
                                    hr_mean, base_hr_mean, hr_threshold,
                                    pnn50_threshold, pnn50_mean)
        status = stress_info['status']
        status_basic = stress_info['status_basic']
        status_sliding = stress_info['status_sliding']
        message = stress_info['message']

        data = {
            'mode': mode,
            'device': device_code,
            'uuid': uuid,
            'hr_mean': hr_mean,
            'HRV': parsed
        }

    # add message into the data dict
    data['message'] = message

    # Store response into Mysql database
    store_response(device_code, uuid, mode, status_basic, status_sliding,
                   hr_mean, parsed['HRV_pNN50']['0'], parsed['HRV_RMSSD']['0'],
                   data)
    return create_json_response(status_code, status, data, message=message)
예제 #3
0
def report_add_label_index(request):
    if validate_http_request_method(request, 'POST', True) == False:
        return create_json_response(
            400,
            'error',
            message=
            'Bad request 4! This API endpoint only handles POST request.')

    device_code = request.POST.get('device_code')
    uuid = request.POST.get('uuid')
    event_short_hand = request.POST.get('label_short_hand')
    event_label_name = request.POST.get('event_label_name')
    event_label_value = request.POST.get('event_label_value')

    if not event_label_name or not event_label_value or not event_short_hand:
        return create_json_response(
            500,
            'error',
            message=
            'Bad request! You have to identify device code and uuid to render the page correctly.'
        )

    try:
        event_label_model = EventLabel()
        event_label_model.uuid = uuid
        event_label_model.device_code = device_code
        event_label_model.name = event_label_name
        event_label_model.short_hand = event_short_hand
        event_label_model.value = event_label_value
        event_label_model.save()
    except Exception as e:
        logger.info(e)

    return redirect('/report?device_code=' + device_code + '&' + 'uuid=' +
                    uuid)


# @csrf_exempt
# def ml_index(request):
#     status_code = 200
#     status = 'success'

#     uuid = request.GET.get('uuid')
#     device_code = request.GET.get('device_code')

#     # Read data from database
#     # Filter the data with device code and uuid
#     filtered_response = Response.objects.filter(device_code=device_code, uuid=uuid)

#     # Convert data to dataframe
#     df = pd.DataFrame(list(filtered_response.values()))

#     # Initialize empty dataframe with column names
#     dataframe_hrv = pd.DataFrame()

#     # Process data with sklearn ML algorithms
#     df = df.reset_index(drop=True)

#     # Transform response body data
#     for index, row in df['response_body'].iteritems():
#         data = json.loads(json.dumps(row))
#         tmp_df = pd.json_normalize(data)

#         dataframe_hrv = dataframe_hrv.append(tmp_df)

#     logger.info(dataframe_hrv.columns)

#     # Append stress column into the dataframe by heart rate
#     dataframe_hrv['stress'] = dataframe_hrv.apply(lambda row: stress_classifier(row), axis=1)

#     logger.info(dataframe_hrv.shape)

#     # 'HRV.HRV_ULF.0', 'HRV.HRV_VLF.0', are removed because all the values are None
#     selected_X_columns = ['HRV.HRV_S.0',
#        'HRV.HRV_AI.0', 'HRV.HRV_Ca.0', 'HRV.HRV_Cd.0', 'HRV.HRV_GI.0',
#        'HRV.HRV_HF.0', 'HRV.HRV_LF.0', 'HRV.HRV_PI.0', 'HRV.HRV_SI.0',
#        'HRV.HRV_C1a.0', 'HRV.HRV_C1d.0', 'HRV.HRV_C2a.0', 'HRV.HRV_C2d.0',
#        'HRV.HRV_CSI.0', 'HRV.HRV_CVI.0', 'HRV.HRV_HFn.0', 'HRV.HRV_HTI.0',
#        'HRV.HRV_LFn.0', 'HRV.HRV_PAS.0', 'HRV.HRV_PIP.0', 'HRV.HRV_PSS.0',
#        'HRV.HRV_SD1.0', 'HRV.HRV_SD2.0', 'HRV.HRV_VHF.0',
#        'HRV.HRV_ApEn.0', 'HRV.HRV_CVNN.0', 'HRV.HRV_CVSD.0',
#        'HRV.HRV_IALS.0', 'HRV.HRV_LFHF.0', 'HRV.HRV_LnHF.0', 'HRV.HRV_SD1a.0',
#        'HRV.HRV_SD1d.0', 'HRV.HRV_SD2a.0', 'HRV.HRV_SD2d.0', 'HRV.HRV_SDNN.0',
#        'HRV.HRV_SDSD.0', 'HRV.HRV_TINN.0', 'HRV.HRV_IQRNN.0',
#        'HRV.HRV_MCVNN.0', 'HRV.HRV_MadNN.0', 'HRV.HRV_RMSSD.0',
#        'HRV.HRV_SDNNa.0', 'HRV.HRV_SDNNd.0', 'HRV.HRV_pNN20.0',
#        'HRV.HRV_pNN50.0', 'HRV.HRV_MeanNN.0', 'HRV.HRV_SD1SD2.0',
#        'HRV.HRV_SampEn.0', 'HRV.HRV_MedianNN.0', 'HRV.HRV_CSI_Modified.0'
#     ]

#     for column_name in selected_X_columns:
#         logger.info(dataframe_hrv[column_name])
#         dataframe_hrv[column_name] = dataframe_hrv[column_name].apply(round_floats)

#     X = dataframe_hrv[selected_X_columns]
#     y = dataframe_hrv['stress']

#     # tpot_classifer = do_tpot(generations=10, population_size=20, X=X, y=y)

#     prediction = random_forest_classfier(X=X, y=y, test_size=0.2, random_state=0, debug=True)

#     logger.info(prediction)

#     return create_json_response(status_code, status, data, message = filtered_response.count())
예제 #4
0
def report_index(request):
    if validate_http_request_method(request, 'GET', True) == False:
        return create_json_response(
            400,
            'error',
            message='Bad request! This API endpoint only handles GET request.')

    # The API needs two params to display the diagram and information about the experiment
    # device_code, uuid
    device_code = request.GET.get('device_code')
    uuid = request.GET.get('uuid')
    x_axis_start = int(request.GET.get('x-axis-start', '0'))
    x_axis_end = int(request.GET.get('x-axis-end', "1"))

    start = ''
    end = ''
    experiment_length = ''
    row_number = 1
    base_data_length = get_base_line_size(Constant.FREQUENCY)
    frequency = Constant.FREQUENCY
    outlier_threshold = 3
    x_axis_labels = []

    if not device_code or not uuid:
        return create_json_response(
            500,
            'error',
            message=
            'Bad request! You have to identify device code and uuid to render the page correctly.'
        )

    responses = Response.objects.filter(device_code=device_code, uuid=uuid)
    requests = Request.objects.filter(device=device_code, uuid=uuid)
    jobs = Job.objects.filter(device=device_code, uuid=uuid)
    requests_df = pd.DataFrame(requests.values())

    # Calculate the HRV RMSSD value from the base data (first n mins, e.g. 5)
    hrv_rmssd_mean = list(responses[1:base_data_length].aggregate(
        Avg('hrv_rmssd')).values())[0]
    records = responses.count()

    if not records:
        return render(request, 'error.html', {})

    if records:
        if x_axis_end == 1:
            x_axis_end = records

        start = responses.first().created_at
        end = responses.last().created_at
        # experiment_length = get_time_diff(int(start.strftime('%s')), int(end.strftime('%s')))
        rows = responses.values()
        detected_stress_x_basic = []
        detected_stress_y_basic = []
        detected_stress_x_sliding = []
        detected_stress_y_sliding = []
        event_labels_short_hand = []
        event_labels_value = []

        # Preprocess the value

        for row in rows:
            current_row_number = row_number - 1
            # Data smoothing, Remove outliers
            if float(rows[current_row_number]
                     ['hrv_rmssd']) > hrv_rmssd_mean * outlier_threshold:
                rows[current_row_number]['hrv_rmssd'] = hrv_rmssd_mean

            # Add row number column
            rows[current_row_number]['row_number'] = row_number

            # Create detected points
            if rows[current_row_number]['status_basic'] == 'warning' or rows[
                    current_row_number]['status_basic'] == 'basic_warning':
                detected_stress_x_basic.append(
                    rows[current_row_number]['row_number'])
                detected_stress_y_basic.append(
                    rows[current_row_number]['hrv_rmssd'])

            # Create detected points generated by sliding window algorithm
            if rows[current_row_number]['status_sliding'] == 'sliding_warning':
                detected_stress_x_sliding.append(
                    rows[current_row_number]['row_number'])
                detected_stress_y_sliding.append(
                    rows[current_row_number]['hrv_rmssd'])

            row_number += 1

        df = pd.DataFrame(rows)
        df['row_number'] = df['row_number'].astype(int)
        df['hrv_rmssd'] = df['hrv_rmssd'].astype(float)

        # fig, ax = plt.subplots()
        # df.plot(x='row_number', y='hrv_rmssd').line()
        # filePath = "./demoapp/static/images/" + device_code + "/" + uuid + "/"
        # mkDir(filePath)
        # fig.saveFig(filePath + 'line_chart.png')
        generate_csv(rows, device_code, uuid, 'response')

    event_labels = EventLabel.objects.filter(device_code=device_code,
                                             uuid=uuid)
    if event_labels.count() > 0:
        for label in event_labels:
            event_labels_short_hand.append(label.short_hand)
            event_labels_value.append(int(label.value))

    x_axis_labels = df['row_number'].tolist()[x_axis_start:x_axis_end]
    x_axis_labels.insert(0, 0)

    return render(
        request, "report.html", {
            'device_code':
            device_code,
            'uuid':
            uuid,
            'records':
            records,
            'frequency':
            jobs.first().frequency,
            'hr_threhold':
            jobs.first().hr_threshold,
            'baseline_size':
            jobs.first().baseline_size,
            'hrv_threshold':
            jobs.first().hrv_threshold,
            'start':
            start,
            'end':
            end,
            'ppg_data':
            requests_df['ppg'].tolist()[x_axis_start:x_axis_end],
            'data':
            df['hrv_rmssd'].tolist()[x_axis_start:x_axis_end],
            'hr':
            df['hr_mean'].tolist()[x_axis_start:x_axis_end],
            'labels':
            x_axis_labels,
            'detected_stress_x_basic':
            detected_stress_x_basic,
            'detected_stress_y_basic':
            detected_stress_y_basic,
            'detected_stress_x_sliding':
            detected_stress_x_sliding,
            'detected_stress_y_sliding':
            detected_stress_y_sliding,
            'stress_labels':
            event_labels.values('short_hand',
                                'name').order_by('short_hand').distinct(),
            'event_labels_short_hand':
            event_labels_short_hand,
            'event_labels_value':
            event_labels_value
        })
예제 #5
0
def process(request):
    uuid = request.POST.get('uuid')
    frequency = int(request.POST.get('frequency'))

    # success HTTP status code as default value
    status_code = Constant.HTTP_SUCCESS_STATUS_CODE
    sample_rate = Constant.SAMPLE_RATE
    mode = Constant.HRV_MODE
    message = ''
    dataframe = None
    hr_threshold = Constant.HR_THRESHOLD
    base_data_length = get_base_line_size(frequency)
    hrv_threshold = Constant.HRV_THRESHOLD
    pnn50_threshold = Constant.PNN50_THRESHOLD
    status = Constant.STATUS_SUCCESS
    status_basic = Constant.STATUS_SUCCESS
    status_sliding = Constant.STATUS_SUCCESS
    data = {}
    secondStorage = 0
    isSend = False
    isJobCreated = False

    if validate_http_request_method(request, 'POST', True) == False:
        return create_json_response(
            400,
            'error',
            message=
            'Bad request 3! This API endpoint only handles POST request.')

    # device_code = request.POST.get('device_code')
    uuid_model = Uuid(uuid=uuid)
    uuid_model.save()

    ppg_raw_file = request.FILES['ppg_raw']

    decoded_file = ppg_raw_file.read().decode('utf-8').splitlines()
    reader = csv.DictReader(decoded_file)
    dataframe = pd.DataFrame()

    for row in reader:
        device_code = row['Device']
        if not isJobCreated:
            create_job(uuid, device_code, frequency, hr_threshold,
                       hrv_threshold, base_data_length)
            isJobCreated = True

        dataframe = dataframe.append(row, ignore_index=True)

        # Get the second of the time
        second = int(row['Time'].split(':')[2])

        if second is not secondStorage:
            secondStorage = second
            isSend = False

        # Per frequency to process HRV
        if (second + 1) % frequency == 0 and not isSend:
            request_model = Request()
            request_model.device = dataframe['Device'].iloc[0]
            request_model.hr = round(dataframe['HR'].astype(int).mean(axis=0),
                                     2)
            request_model.time = 0
            request_model.timedate = 0
            request_model.uuid = uuid
            request_model.ppg = round(
                dataframe['PPG'].astype(float).mean(axis=0), 2)
            request_model.save()

            normalized_ppg_data = get_normalized_ppg_data(dataframe)
            filtered_response = Response.objects.filter(
                device_code=device_code, uuid=uuid)

            # Calculate the average hear rate based on HR column
            hr_mean = round(dataframe['HR'].astype(float).mean(axis=0), 2)

            # Compute HRV indices
            try:
                hrv_indices = calculate_hrv(normalized_ppg_data, sample_rate)
            except ValueError:
                status = 'error'
                message = 'Please wear the polarOH1 properly.'
                data = {
                    'mode': mode,
                    'device': device_code,
                    'uuid': uuid,
                    'hr_mean': hr_mean
                }
                data['message'] = message
                return create_json_response(status_code,
                                            status,
                                            data,
                                            message=message)

            # Convert HRV output into json format
            result = hrv_indices.to_json()
            parsed = json.loads(result)

            data = {
                'mode': mode,
                'device': device_code,
                'uuid': uuid,
                'hr_mean': hr_mean,
                'HRV': parsed
            }

            # add message into the data dict
            data['message'] = message

            if filtered_response.count() > 0:
                # Calculate the HRV RMSSD value from the base data (first n mins, e.g. 5)
                hrv_rmssd_mean = list(
                    filtered_response[1:base_data_length].aggregate(
                        Avg('hrv_rmssd')).values())[0]
                base_hr_mean = list(
                    filtered_response[1:base_data_length].aggregate(
                        Avg('hr_mean')).values())[0]
                pnn50_mean = list(
                    filtered_response[1:base_data_length].aggregate(
                        Avg('hrv_pnn50')).values())[0]

                logger.info("================================================")
                logger.info(hrv_rmssd_mean)
                logger.info(base_hr_mean)
                logger.info(pnn50_mean)
                logger.info("================================================")

                stress_info = detect_stress(filtered_response,
                                            base_data_length, parsed,
                                            hrv_threshold, hrv_rmssd_mean,
                                            hr_mean, base_hr_mean,
                                            hr_threshold, pnn50_threshold,
                                            pnn50_mean)
                status = stress_info['status']
                status_basic = stress_info['status_basic']
                status_sliding = stress_info['status_sliding']
                message = stress_info['message']

            # Store response into Mysql database
            store_response(device_code, uuid, mode, status_basic,
                           status_sliding, hr_mean, parsed['HRV_pNN50']['0'],
                           parsed['HRV_RMSSD']['0'], data)
            # Reset dataframe
            dataframe = pd.DataFrame()
            isSend = True

    return redirect('/report?device_code=' + device_code + '&' + 'uuid=' +
                    uuid)