I’m using LetsPlot to graph a line (electrocardiog...
# datascience
c
I’m using LetsPlot to graph a line (electrocardiogram) plus a scatterplot of detected R peaks. This helps visualize whether the R peak detection algorithm is working correctly. The ECG line looks great. The problem is that the R peak scatterplot is behaving strangely. About half the points appear on top of the line graph as expected, but then some points cluster at the end of the graph in the top right corner.
This is the current implementation, where time is a Kotlinx Instant and y is a Float.
Copy code
val X = "Time"
val Y = "y"
val rawDataframe: Map<String, List<Any>> = buildMap<String, List<Any>> {
    put(X, rawData.map { it.x })
    put(Y, rawData.map { it.y })
}

val detectionDataframe: Map<String, List<Any>> = buildMap<String, List<Any>> {
    put(X, detection.map { it.x })
    put(Y, detection.map { it.y })
}

val plot = letsPlot() + geomLine(rawDataframe, color = "blue") {
    x = X
    y = Y
} + geomPoint(detectionDataframe, color = "red") {
    x = X
    y = Y
} + ggtitle(
    title
) + ylab(
    yAxisLabel
) + scaleXDateTime() + ggsize(
    IMAGE_PIXELS_WIDTH,
    IMAGE_PIXELS_HEIGHT
)
a
@Igor Alshannikov
i
time is a Kotlinx Instant and y is a Float.
Kotlinx Instant is not currently supported. Please try to convert all 'Instant' values to Double - milliseconds since Unix epoch.
c
Thank you for the reply. Using
toEpochMilliseconds
makes it work better. I’m seeing two weird things though. It seems the x axis labels are repeating (minute is always 2). And the Y axis doesn’t line up with the data even though the coordinates should be along the line.
This is the LetsPlot output
message has been deleted
And this is the JFreeChart output, which is effectively what I expect
(Ignoring the colors being swapped).
The peak detection does have a warmup period, so no points for the first several peaks is expected. And the peak detection can be off slightly so a handful of points not quite on the peak are also expected.
i
Perhaps some data-point are filtered by builtin 'sampling'. Try to add
sampling = samplingNone
parameter to the
geomLine()
layer. Another thought:
scaleXTime()
might be a better fit for ECG than
scaleXDateTime()
See docs: https://lets-plot.org/kotlin/plot-api/jetbrains.letsPlot.scale/scale-x-time.html Example notebook: https://nbviewer.org/github/JetBrains/lets-plot-kotlin/blob/master/docs/examples/jupyter-notebooks/scale_time.ipynb
c
sampling = samplingNone
resolves the issue with the points being wrong, so that’s a big help.
I think
scaleXDateTime
is probably what I want. Being able to see the actual wall time is very helpful because I sometimes need to manually correlate the data from multiple sources. being able to say “here’s what happened at noon” is a lot easier than “here’s what happened at time index 52 minutes.”
I think I finally got the time axis to print correctly. I used a lowercase
m
in the format and switching to uppercase
M
seems to be the right parameter.
👍 1