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);
}
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;
}
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);
}
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;
}
Aggregations