Search in sources :

Example 1 with HeartRateUtils

use of nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils in project Gadgetbridge by Freeyourgadget.

the class AbstractChartFragment method refresh.

public DefaultChartsData<LineData> refresh(GBDevice gbDevice, List<? extends ActivitySample> samples) {
    // Calendar cal = GregorianCalendar.getInstance();
    // cal.clear();
    TimestampTranslation tsTranslation = new TimestampTranslation();
    // Date date;
    // String dateStringFrom = "";
    // String dateStringTo = "";
    // ArrayList<String> xLabels = null;
    LOG.info("" + getTitle() + ": number of samples:" + samples.size());
    LineData lineData;
    if (samples.size() > 1) {
        boolean annotate = true;
        boolean use_steps_as_movement;
        int last_type = ActivityKind.TYPE_UNKNOWN;
        int numEntries = samples.size();
        List<Entry> activityEntries = new ArrayList<>(numEntries);
        List<Entry> deepSleepEntries = new ArrayList<>(numEntries);
        List<Entry> lightSleepEntries = new ArrayList<>(numEntries);
        List<Entry> notWornEntries = new ArrayList<>(numEntries);
        boolean hr = supportsHeartrate(gbDevice);
        List<Entry> heartrateEntries = hr ? new ArrayList<Entry>(numEntries) : null;
        // this is kinda inefficient...
        List<Integer> colors = new ArrayList<>(numEntries);
        int lastHrSampleIndex = -1;
        HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
        for (int i = 0; i < numEntries; i++) {
            ActivitySample sample = samples.get(i);
            int type = sample.getKind();
            int ts = tsTranslation.shorten(sample.getTimestamp());
            // System.out.println(ts);
            // ts = i;
            // determine start and end dates
            // if (i == 0) {
            // cal.setTimeInMillis(ts * 1000L); // make sure it's converted to long
            // date = cal.getTime();
            // dateStringFrom = dateFormat.format(date);
            // } else if (i == samples.size() - 1) {
            // cal.setTimeInMillis(ts * 1000L); // same here
            // date = cal.getTime();
            // dateStringTo = dateFormat.format(date);
            // }
            float movement = sample.getIntensity();
            float value = movement;
            switch(type) {
                case ActivityKind.TYPE_DEEP_SLEEP:
                    if (last_type != type) {
                        // FIXME: this is ugly but it works (repeated in each case)
                        deepSleepEntries.add(createLineEntry(0, ts - 1));
                        lightSleepEntries.add(createLineEntry(0, ts));
                        notWornEntries.add(createLineEntry(0, ts));
                        activityEntries.add(createLineEntry(0, ts));
                    }
                    deepSleepEntries.add(createLineEntry(value + SleepUtils.Y_VALUE_DEEP_SLEEP, ts));
                    break;
                case ActivityKind.TYPE_LIGHT_SLEEP:
                    if (last_type != type) {
                        lightSleepEntries.add(createLineEntry(0, ts - 1));
                        deepSleepEntries.add(createLineEntry(0, ts));
                        notWornEntries.add(createLineEntry(0, ts));
                        activityEntries.add(createLineEntry(0, ts));
                    }
                    lightSleepEntries.add(createLineEntry(value, ts));
                    break;
                case ActivityKind.TYPE_NOT_WORN:
                    if (last_type != type) {
                        notWornEntries.add(createLineEntry(0, ts - 1));
                        lightSleepEntries.add(createLineEntry(0, ts));
                        deepSleepEntries.add(createLineEntry(0, ts));
                        activityEntries.add(createLineEntry(0, ts));
                    }
                    // a small value, just to show something on the graphs
                    notWornEntries.add(createLineEntry(SleepUtils.Y_VALUE_DEEP_SLEEP, ts));
                    break;
                default:
                    // value = ((float) movement) / movement_divisor;
                    if (last_type != type) {
                        activityEntries.add(createLineEntry(0, ts - 1));
                        lightSleepEntries.add(createLineEntry(0, ts));
                        notWornEntries.add(createLineEntry(0, ts));
                        deepSleepEntries.add(createLineEntry(0, ts));
                    }
                    activityEntries.add(createLineEntry(value, ts));
            }
            if (hr && sample.getKind() != ActivityKind.TYPE_NOT_WORN && heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
                if (lastHrSampleIndex > -1 && ts - lastHrSampleIndex > 1800 * HeartRateUtils.MAX_HR_MEASUREMENTS_GAP_MINUTES) {
                    heartrateEntries.add(createLineEntry(0, lastHrSampleIndex + 1));
                    heartrateEntries.add(createLineEntry(0, ts - 1));
                }
                heartrateEntries.add(createLineEntry(sample.getHeartRate(), ts));
                lastHrSampleIndex = ts;
            }
            String xLabel = "";
            if (annotate) {
            // cal.setTimeInMillis((ts + tsOffset) * 1000L);
            // date = cal.getTime();
            // String dateString = annotationDateFormat.format(date);
            // xLabel = dateString;
            // if (last_type != type) {
            // if (isSleep(last_type) && !isSleep(type)) {
            // // woken up
            // LimitLine line = new LimitLine(i, dateString);
            // line.enableDashedLine(8, 8, 0);
            // line.setTextColor(Color.WHITE);
            // line.setTextSize(15);
            // chart.getXAxis().addLimitLine(line);
            // } else if (!isSleep(last_type) && isSleep(type)) {
            // // fallen asleep
            // LimitLine line = new LimitLine(i, dateString);
            // line.enableDashedLine(8, 8, 0);
            // line.setTextSize(15);
            // line.setTextColor(Color.WHITE);
            // chart.getXAxis().addLimitLine(line);
            // }
            // }
            }
            last_type = type;
        }
        List<ILineDataSet> lineDataSets = new ArrayList<>();
        LineDataSet activitySet = createDataSet(activityEntries, akActivity.color, "Activity");
        lineDataSets.add(activitySet);
        LineDataSet deepSleepSet = createDataSet(deepSleepEntries, akDeepSleep.color, "Deep Sleep");
        lineDataSets.add(deepSleepSet);
        LineDataSet lightSleepSet = createDataSet(lightSleepEntries, akLightSleep.color, "Light Sleep");
        lineDataSets.add(lightSleepSet);
        LineDataSet notWornSet = createDataSet(notWornEntries, akNotWorn.color, "Not worn");
        lineDataSets.add(notWornSet);
        if (hr && heartrateEntries.size() > 0) {
            LineDataSet heartrateSet = createHeartrateSet(heartrateEntries, "Heart Rate");
            lineDataSets.add(heartrateSet);
        }
        lineData = new LineData(lineDataSets);
    // chart.setDescription(getString(R.string.sleep_activity_date_range, dateStringFrom, dateStringTo));
    // chart.setDescriptionPosition(?, ?);
    } else {
        lineData = new LineData();
    }
    ValueFormatter xValueFormatter = new SampleXLabelFormatter(tsTranslation);
    return new DefaultChartsData(lineData, xValueFormatter);
}
Also used : AbstractActivitySample(nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample) ActivitySample(nodomain.freeyourgadget.gadgetbridge.model.ActivitySample) ILineDataSet(com.github.mikephil.charting.interfaces.datasets.ILineDataSet) LineDataSet(com.github.mikephil.charting.data.LineDataSet) HeartRateUtils(nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils) ArrayList(java.util.ArrayList) LineData(com.github.mikephil.charting.data.LineData) Entry(com.github.mikephil.charting.data.Entry) ILineDataSet(com.github.mikephil.charting.interfaces.datasets.ILineDataSet) ValueFormatter(com.github.mikephil.charting.formatter.ValueFormatter)

Example 2 with HeartRateUtils

use of nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils in project Gadgetbridge by Freeyourgadget.

the class GPXExporter method findClosestSensibleActivityPoint.

@Nullable
private ActivityPoint findClosestSensibleActivityPoint(Date time, List<ActivityPoint> trackPoints) {
    ActivityPoint closestPointItem = null;
    HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
    // minimum distance is 2min
    long lowestDifference = 60 * 2 * 1000;
    for (ActivityPoint pointItem : trackPoints) {
        int hrItem = pointItem.getHeartRate();
        if (heartRateUtilsInstance.isValidHeartRateValue(hrItem)) {
            Date timeItem = pointItem.getTime();
            if (timeItem.after(time) || timeItem.equals(time)) {
                // we assume that the given trackPoints are sorted in time ascending order (oldest first)
                break;
            }
            long difference = time.getTime() - timeItem.getTime();
            if (difference < lowestDifference) {
                lowestDifference = difference;
                closestPointItem = pointItem;
            }
        }
    }
    return closestPointItem;
}
Also used : HeartRateUtils(nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils) ActivityPoint(nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint) ActivityPoint(nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint) Date(java.util.Date) Nullable(androidx.annotation.Nullable)

Example 3 with HeartRateUtils

use of nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils in project Gadgetbridge by Freeyourgadget.

the class SleepChartFragment method calculateHrData.

private Triple<Float, Integer, Integer> calculateHrData(List<? extends ActivitySample> samples) {
    if (samples.toArray().length < 1) {
        return Triple.of(0f, 0, 0);
    }
    List<Integer> heartRateValues = new ArrayList<>();
    HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
    for (ActivitySample sample : samples) {
        if (sample.getKind() == ActivityKind.TYPE_LIGHT_SLEEP || sample.getKind() == ActivityKind.TYPE_DEEP_SLEEP) {
            int heartRate = sample.getHeartRate();
            if (heartRateUtilsInstance.isValidHeartRateValue(heartRate)) {
                heartRateValues.add(heartRate);
            }
        }
    }
    if (heartRateValues.toArray().length < 1) {
        return Triple.of(0f, 0, 0);
    }
    int min = Collections.min(heartRateValues);
    int max = Collections.max(heartRateValues);
    int count = heartRateValues.toArray().length;
    float sum = calculateSumOfInts(heartRateValues);
    float average = sum / count;
    return Triple.of(average, min, max);
}
Also used : ActivitySample(nodomain.freeyourgadget.gadgetbridge.model.ActivitySample) HeartRateUtils(nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils) ArrayList(java.util.ArrayList)

Example 4 with HeartRateUtils

use of nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils in project Gadgetbridge by Freeyourgadget.

the class StepAnalysis method calculateStepSessions.

public List<ActivitySession> calculateStepSessions(List<? extends ActivitySample> samples) {
    LOG.debug("get all samples activitysessions: " + samples.toArray().length);
    List<ActivitySession> result = new ArrayList<>();
    ActivityUser activityUser = new ActivityUser();
    final int MIN_SESSION_LENGTH = 60 * GBApplication.getPrefs().getInt("chart_list_min_session_length", 5);
    final int MAX_IDLE_PHASE_LENGTH = 60 * GBApplication.getPrefs().getInt("chart_list_max_idle_phase_length", 5);
    final int MIN_STEPS_PER_MINUTE = GBApplication.getPrefs().getInt("chart_list_min_steps_per_minute", 40);
    int stepLengthCm = activityUser.getStepLengthCm();
    final double STEP_LENGTH_M = stepLengthCm * 0.01;
    final double MIN_SESSION_INTENSITY = Math.max(0, Math.min(1, MIN_STEPS_PER_MINUTE * 0.01));
    totalDailySteps = 0;
    ActivitySample previousSample = null;
    Date sessionStart = null;
    Date sessionEnd;
    // steps that we count
    int activeSteps = 0;
    // steps during time when we maybe take a rest but then restart
    int stepsBetweenActivePeriods = 0;
    int durationSinceLastActiveStep = 0;
    int activityKind;
    List<Integer> heartRateSum = new ArrayList<>();
    List<Integer> heartRateBetweenActivePeriodsSum = new ArrayList<>();
    float activeIntensity = 0;
    float intensityBetweenActivePeriods = 0;
    HeartRateUtils heartRateUtilsInstance = HeartRateUtils.getInstance();
    for (ActivitySample sample : samples) {
        int steps = sample.getSteps();
        if (steps > 0) {
            totalDailySteps += steps;
        }
        if (// anything but sleep counts
        sample.getKind() != ActivityKind.TYPE_SLEEP && !(sample instanceof TrailingActivitySample)) {
            if (sessionStart == null) {
                sessionStart = getDateFromSample(sample);
                activeSteps = sample.getSteps();
                activeIntensity = sample.getIntensity();
                heartRateSum = new ArrayList<>();
                if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
                    heartRateSum.add(sample.getHeartRate());
                }
                durationSinceLastActiveStep = 0;
                stepsBetweenActivePeriods = 0;
                heartRateBetweenActivePeriodsSum = new ArrayList<>();
                previousSample = null;
            }
            if (previousSample != null) {
                int durationSinceLastSample = sample.getTimestamp() - previousSample.getTimestamp();
                if (// either some steps
                sample.getSteps() > MIN_STEPS_PER_MINUTE || (sample.getIntensity() > MIN_SESSION_INTENSITY && sample.getSteps() > 0)) {
                    // or some intensity plus at least one step
                    activeSteps += sample.getSteps() + stepsBetweenActivePeriods;
                    activeIntensity += sample.getIntensity() + intensityBetweenActivePeriods;
                    if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
                        heartRateSum.add(sample.getHeartRate());
                    }
                    heartRateSum.addAll(heartRateBetweenActivePeriodsSum);
                    heartRateBetweenActivePeriodsSum = new ArrayList<>();
                    stepsBetweenActivePeriods = 0;
                    intensityBetweenActivePeriods = 0;
                    durationSinceLastActiveStep = 0;
                } else {
                    // short break data to remember, we will add it to the rest later, if break not too long
                    stepsBetweenActivePeriods += sample.getSteps();
                    if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
                        heartRateBetweenActivePeriodsSum.add(sample.getHeartRate());
                    }
                    durationSinceLastActiveStep += durationSinceLastSample;
                    intensityBetweenActivePeriods += sample.getIntensity();
                }
                if (durationSinceLastActiveStep >= MAX_IDLE_PHASE_LENGTH) {
                    // break too long, we split here
                    int current = sample.getTimestamp();
                    int starting = (int) (sessionStart.getTime() / 1000);
                    int session_length = current - starting - durationSinceLastActiveStep;
                    if (session_length >= MIN_SESSION_LENGTH) {
                        // valid activity session
                        int heartRateAverage = heartRateSum.toArray().length > 0 ? calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length : 0;
                        float distance = (float) (activeSteps * STEP_LENGTH_M);
                        sessionEnd = new Date((sample.getTimestamp() - durationSinceLastActiveStep) * 1000L);
                        activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
                        ActivitySession activitySession = new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind);
                        // activitySession.setSessionType(ActivitySession.SESSION_ONGOING);
                        result.add(activitySession);
                    }
                    sessionStart = null;
                }
            }
            previousSample = sample;
        }
    }
    if (sessionStart != null && previousSample != null) {
        int current = previousSample.getTimestamp();
        int starting = (int) (sessionStart.getTime() / 1000);
        int session_length = current - starting - durationSinceLastActiveStep;
        if (session_length >= MIN_SESSION_LENGTH) {
            int heartRateAverage = heartRateSum.toArray().length > 0 ? calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length : 0;
            float distance = (float) (activeSteps * STEP_LENGTH_M);
            sessionEnd = getDateFromSample(previousSample);
            activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
            ActivitySession ongoingActivity = new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind);
            ongoingActivity.setSessionType(ActivitySession.SESSION_ONGOING);
            result.add(ongoingActivity);
        }
    }
    return result;
}
Also used : ActivitySample(nodomain.freeyourgadget.gadgetbridge.model.ActivitySample) HeartRateUtils(nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils) ArrayList(java.util.ArrayList) Date(java.util.Date) ActivityUser(nodomain.freeyourgadget.gadgetbridge.model.ActivityUser) ActivitySession(nodomain.freeyourgadget.gadgetbridge.model.ActivitySession)

Aggregations

HeartRateUtils (nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils)4 ArrayList (java.util.ArrayList)3 ActivitySample (nodomain.freeyourgadget.gadgetbridge.model.ActivitySample)3 Date (java.util.Date)2 Nullable (androidx.annotation.Nullable)1 Entry (com.github.mikephil.charting.data.Entry)1 LineData (com.github.mikephil.charting.data.LineData)1 LineDataSet (com.github.mikephil.charting.data.LineDataSet)1 ValueFormatter (com.github.mikephil.charting.formatter.ValueFormatter)1 ILineDataSet (com.github.mikephil.charting.interfaces.datasets.ILineDataSet)1 AbstractActivitySample (nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample)1 ActivityPoint (nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint)1 ActivitySession (nodomain.freeyourgadget.gadgetbridge.model.ActivitySession)1 ActivityUser (nodomain.freeyourgadget.gadgetbridge.model.ActivityUser)1