1

I'm trying to build a heatmap in LightningChart that covers a fixed 24 hours time span in 15 minutes intervals. For the sake of conveinience, that interval is inclusive, so if I'm reading a midnight-to-midnight interval, I expect to have the data for both midnights, making for an effective range of 24¼ hours over 97 samples.

My problem is that, when using the datetime tick strategy, having an axis interval covering more than exactly 24 hours causes it to use the FormattingDay format, which uses a tick hierarchy of great: ISOWeek, major: DayOfMonth, minor: Hour, which is very inconveinient to read in this sort of situation.

from Sunday August 21 to Monday August 22 from Monday August 22 to Tuesday August 23

On the left is when the great tick (ISO week, every monday) shows up in the middle of the axis (from Sunday August 21 to Monday August 22), and on the right is when only a major tick is visible (from Monday August 22 to Tuesday August 23). Both of these I find very confusing to read and not at all what I want the axis to look like. The use of months would actually be preferable, as ISO weeks aren't exactly a common layman time representation.

Is there a way to force a specific tick hierarchy to be used to label axes? Either great: Month, major: DayOfMonth, minor: Hour or great: DayOfMonth, major: Hour, minor: Minute would be good, but the default of great: ISOWeek is unusable to me.

VLRoyrenn
  • 596
  • 5
  • 11

2 Answers2

0

That seems very inconvenient indeed.

Maybe in your case it would be actually easier to manually place each tick along the Y axis?

You can create custom ticks like this:

const tick = Axis.addCustomTick(UIElementBuilders.AxisTick)

Here's an example that you can reference for styling the ticks: https://www.arction.com/lightningchart-js-interactive-examples/edit/lcjs-example-0011-customTicksScrolling.html

In any case this is an important form of feedback, unfortunately there are a number of cases where the current DateTime ticks don't deliver.

Niilo Keinänen
  • 2,187
  • 1
  • 7
  • 12
  • Yeah, I was hoping I could avoid using manual tick placement, that maybe I just wasn't looking at the right place. I haven't found any template/recipe for custom datetime axis generation, either, and I can't copy it from the source of DateTimeTickStrategy, so I would have preferred to stick to the stock components where possible. – VLRoyrenn Aug 26 '22 at 18:35
  • 1
    Understandable... We'll be working towards improving this kind of use cases in the future. – Niilo Keinänen Aug 29 '22 at 09:19
0

Not a perfect solution, but a suitable workaround for the time being: I ended up just using the axis range extremums to detect when the value to be formatted is a great tick beyond what the axis should display (ticks pointing to the "start of the current week"/"start of next week" outside the chart have a value of midnight the previous Monday), and clamp it to the axis range, so they can just be formatted as dates.

myChart.getDefaultAxisY().setTickStrategy("DateTime", (ticks) => {
    // If the axis range covers more than exactly 24h, LightningCharts uses FormattingDay instead of FormattingHour.
    // That means one great tick at the start of every monday (2022-W33) but not the start every day (that's major ticks) or every month (August 1st is a regular major tick)

    // This still makes for a great tick at the start of every Monday, but clamps the date to match what's inside the axis,
    // and formats it like a date, so the "context" dates at both ends of the axis behave more or less like they do with FormattingHour.
    return ticks.setFormattingDay(
        (val, range, loc) => {
            let adjustedVal;

            if (range.getInnerStart() < range.getInnerEnd()) {
                adjustedVal = Math.min(Math.max(range.getInnerStart(), val), range.getInnerEnd())
            } else {
                adjustedVal = Math.min(Math.max(range.getInnerEnd(), val), range.getInnerStart())
            }
            
            let formattedDate = new Date(adjustedVal);
            return formattedDate.toLocaleDateString(loc);
        },
        { month: 'long', day: '2-digit' }, // Midnight every day
        { hour: '2-digit', minute: '2-digit' } // Every hour
    );

    // return ticks.setFormattingDay(
    //     { month: 'long', day: '2-digit' }, // Midnight every ISO start of week (Monday)
    //     { month: 'long', day: '2-digit' }, // Midnight every day
    //     { hour: '2-digit', minute: '2-digit' }, // Every hour
    // );
});

enter image description here

VLRoyrenn
  • 596
  • 5
  • 11