streamlinesocial / highcharts-regression

Linear and non-linear regression support for highcharts
MIT License
73 stars 64 forks source link

Works on one chart in Angular, but not the other! #110

Closed cosmoKenney closed 2 years ago

cosmoKenney commented 2 years ago

I have a polynomial regression line on one of my charts, but I cannot for the life of me get it to work on a different chart. It is almost exactly the same configuration. But the regression just doesn't show up. No errors in the console, nothing.

Is there a way to toggle a verbose debugging mode or something?

I've taken the configuration (options) from the non-working chart and set up a fiddle here: http://jsfiddle.net/yv8pbx56/4/ The regression works perfectly in the fiddle. But in my angular project I get no regression line. Just the scatter plot shows.

I must have everything imported correctly including the regression plugin since the chart in showing up. So how can I find out if the regression plugin is working and just confused or what?

My angular component code:

import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
import { RiskApiService } from "@core/services";
import * as Highcharts from "highcharts";
import { IHighChartsSeriesData } from "@app/interfaces/IHighChartsSeriesData";
import * as HC_Regression from 'highcharts-regression';

@Component({
    selector: 'cl-trend',
    templateUrl: './trend.component.html',
    styleUrls: ['./trend.component.scss']
})
export class TrendComponent implements OnInit
{
    //public Names: BehaviorSubject<IRiskName[]> = new BehaviorSubject<IRiskName[]>([]);
    public TrendChartOptions: Highcharts.Options = this.get_trend_chart_options([], false);
    public highcharts = Highcharts;
    public updateTrendFlag: boolean = false;

    constructor(
        private _changeDetector: ChangeDetectorRef,
        private _api: RiskApiService
    )
    {
        HC_Regression(Highcharts);
    }

    ngOnInit(): void
    {
    }

    private _riskId: string;
    @Input()
    public set RiskId(riskId: string)
    {
        if (this._riskId !== riskId)
        {
            this._riskId = riskId;
            setTimeout(async () => this.init(), 1);
        }
    }
    public get RiskId()
    {
        return this._riskId;
    }

    private _expanded: boolean = false;
    @Input()
    public set Expanded(expanded: boolean)
    {
        if (this._expanded !== expanded)
        {
            this._expanded = expanded;
            setTimeout(async () => this.init(), 1);
        }
    }

    private async init()
    {
        const mods = await this._api.XmodGraph(this._riskId); //  this is cached, so no problem calling it many times 
        let index: number = 0;
        let seriesData: IHighChartsSeriesData[];
        if (mods && mods.length > 0)
        {
            seriesData = (this._expanded ? mods.slice(-30) : mods.slice(-10)).map((v, i, crs) =>
            {
                return { name: v.XmodIncepYear.toString(), x: index++, y: v.XmodFactor, color: undefined };
            });
            this.TrendChartOptions = this.get_trend_chart_options(seriesData, this._expanded);
            this.updateTrendFlag = true;
            this._changeDetector.detectChanges(); // tried this as a last ditch
        }
    }

    private get_trend_chart_options(seriesData: IHighChartsSeriesData[], expanded: boolean): Highcharts.Options
    {
        seriesData = seriesData || [];
        const max = Math.max.apply(Math, seriesData.map((o) => o.y));
        const avgLast3 = seriesData.slice(0, 3).reduce((pv, m) => pv + m.y, 0) / 3;
        const avgAll = seriesData.reduce((pv, m) => pv + m.y, 0) / seriesData.length;

        return {
            credits: { enabled: false },
            chart: {
                zoomType: "xy",
                type: 'scatter',
                width: expanded ? 817 : 286,
                height: 151,
                spacingLeft: 5,
                spacingTop: 10,
                spacingBottom: 15,
                spacingRight: 10,
                borderWidth: 0
            },
            title: { text: null, },
            xAxis: {
                type: 'category',
                labels: {
                    style: {
                        fontSize: '8pt',
                        fontFamily: "Verdana",
                        color: "#0F4F8C"
                    },
                    rotation: -90,
                    step: 1
                },
                tickInterval: 1,
                showLastLabel: true
            },
            yAxis: {
                min: 0,
                max: max + 10,
                tickInterval: max / 6,
                allowDecimals: false,
                title: { text: null },
                labels: {
                    formatter: function ()
                    {
                        return ('000' + parseFloat('' + this.value).toFixed()).slice(-3);
                    },
                    style: {
                        fontSize: "8pt",
                        fontFamily: "Verdana",
                        color: "#0F4F8C"
                    }
                }
            },
            legend: { enabled: false },
            plotOptions: {
                scatter: { dataLabels: { color: "#0F4F8C" } },
                series: {
                    borderWidth: 0,
                    color: "#336699",
                    dataLabels: { enabled: false, allowOverlap: true }
                }
            },
            tooltip: {
                formatter: function ()
                {
                    const y = ('000' + parseFloat('' + this.point.y).toFixed()).slice(-3)
                    return `<span>${this.series.name}</span><br><span>${this.point.name}</span>: <b>${y}</b><br/>`;
                }
            },
            series: [
                ({
                    regression: (seriesData.length > 2),
                    //type: 'line',
                    zIndex: 1,
                    name: 'X-Mod',
                    id: "mods",
                    lineWidth: 0,
                    marker: {
                        enabled: true,
                        symbol: "circle",
                        radius: 6
                    },
                    regressionSettings: {
                        name: 'Trend',
                        visible: (seriesData.length > 2),
                        type: 'polynomial',
                        color: avgLast3 > avgAll ? "#D50D0D" : "#1D681B",
                        order: 4,
                        lineWidth: 2,
                        index: 2,
                        //regressionSeriesOptions: { dataLabels: { enabled: false } }
                    },
                    data: seriesData
                } as any)
            ]
        };
    }
}
cosmoKenney commented 2 years ago

This issue is not due to configuration or references to the packages. It has to do with changing the data after initial display. Opening another issue that is more relevant to the actual problem.

phpepe commented 2 years ago

Can you share a snippet on JsFiddle or simillar?

On Wed, Jun 29, 2022 at 9:10 PM Ken Hadden @.***> wrote:

I have a poly nomial regression line on one of my charts, but I cannot for the life of me get it to work on a different chart. It is almost exactly the same configuration. But the regression just doesn't show up. No errors in the console, nothing.

Is there a way to toggle a verbose debugging mode or something?

— Reply to this email directly, view it on GitHub https://github.com/streamlinesocial/highcharts-regression/issues/110, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAP5GLTGCXXGGICPANHN7BLVRTQV5ANCNFSM52HQIIKQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

cosmoKenney commented 2 years ago

@phpepe Sorry, all the relevant code is in the original post. I don't have any time to setup a fiddle. However, I did post this issue with a fiddle. The problem occurs when I change the data after the chart has been initialized: https://github.com/streamlinesocial/highcharts-regression/issues/111

It's been almost six months since I worked on this. And if I recall correctly I had to do some dirty hacks to get it to work. I never did get it working properly.