SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and iOS Chart & Android Chart Components

Answered
0
0

Hello,

I have two questions about how to get axes or annotations by ID.

First, I trying to update the VisibleRange for X axis in the internalUpdate function in the UniformHeatmapSeriesTooltip. When I use getAxisById, my ECG data series is gone from the chart. But it works if I use getDefault() instead (axis Id not defined). So I kind of confused.

private class CustomHeatmapTooltip extends UniformHeatmapSeriesTooltip {

        public CustomHeatmapTooltip(Context context, UniformHeatmapSeriesInfo heatmapInfo) {
            super(context, heatmapInfo);
        }
        @Override
        protected void internalUpdate(UniformHeatmapSeriesInfo heatmapInfo) {
            ecgSurface.getXAxes().getAxisById("ecgx").setVisibleRange(new DateRange(startDate, stopDate));
        }
}

Second, I have one vertical line annotation and multiple text annotations. Every time I render the heatmap, I want to remove the text annotations and add some new text annotations as needed, without touching the vertical line annotation. Is there a way to only remove the text annotations?

Thanks a lot.

Version
3.1.0.4341
  • You must to post comments
Best Answer
0
0

Hi there,

  1. Well, as I see you set custom id for xAxis, but I don’t see that you set XAxisId for ecgSeries. If you change one id you also need to change another or as alternative you need to provide axis with default id, so during rendering ecgSeries can find XAxis with id that matches its XAxisId value. For more information please take a look on this tutorial from documentation.

  2. We don’t have such API, but you can easily add this functionality on your own. For example iterate over annotations collection and check its type and remove desired annotations. Or you can create seperate list for storing TextAnnotations to remove. Then when time comes remove them from chart’s annotation collection and clear this list with annotations to remove.

Best regards,
Yura

  • Gang Xu
    Thanks for the advice.
  • You must to post comments
0
0

About the first question, I’m wondering if this is a bug. Cause all I changed is set axis with an id, and the data series won’t render.

And throw out an error.

java.lang.UnsupportedOperationException: AxisCollection.getAxisById(‘DefaultAxisId’) returned no axis with ID=DefaultAxisId. Please check you have added an axis with this Id to the AxisCollection
at com.scichart.charting.model.AxisCollection.getAxisById(SourceFile:120)
at com.scichart.charting.visuals.axes.rangeCalculators.RangeCalculationHelper2DBase.getWindowedYRange(SourceFile:209)
at com.scichart.charting.visuals.axes.rangeCalculators.RangeCalculationHelper2DBase.updateMaximumRange(SourceFile:180)
at com.scichart.charting.visuals.axes.rangeCalculators.RangeCalculatorHelperBase.getMaximumRange(SourceFile:83)
at com.scichart.charting.visuals.axes.AxisBase.getMaximumRange(SourceFile:1115)
at com.scichart.charting.viewportManagers.ViewportManagerBase.onApplyAutoRange(SourceFile:218)
at com.scichart.charting.viewportManagers.ViewportManagerBase.tryPerformAutoRange(SourceFile:205)
at com.scichart.charting.visuals.rendering.RenderSurfaceRenderer.a(SourceFile:238)
at com.scichart.charting.visuals.rendering.RenderSurfaceRenderer.a(SourceFile:204)
at com.scichart.charting.visuals.rendering.RenderSurfaceRenderer.a(SourceFile:142)
at com.scichart.charting.visuals.rendering.RenderSurfaceRenderer.onDraw(SourceFile:131)
at com.scichart.drawing.opengl.GLTextureView$b.onDraw(SourceFile:213)
at com.scichart.drawing.opengl.MyGLRenderer.b(SourceFile:270)
at com.scichart.drawing.opengl.ao.b(SourceFile:94)
at com.scichart.drawing.opengl.ap.handleMessage(SourceFile:52)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at com.scichart.drawing.opengl.ao.run(SourceFile:76)

If I comment out the line withAxisId(‘ecgx’), and getDefault X Axes in the button callback function, everything works fine.

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.Switch;

import com.scichart.charting.model.dataSeries.IXyDataSeries;
import com.scichart.charting.model.dataSeries.UniformHeatmapDataSeries;
import com.scichart.charting.visuals.SciChartSurface;
import com.scichart.charting.visuals.axes.AutoRange;
import com.scichart.charting.visuals.axes.AxisAlignment;
import com.scichart.charting.visuals.axes.IAxis;
import com.scichart.charting.visuals.axes.NumericAxis;
import com.scichart.charting.visuals.renderableSeries.ColorMap;
import com.scichart.charting.visuals.renderableSeries.FastUniformHeatmapRenderableSeries;
import com.scichart.charting.visuals.renderableSeries.IRenderableSeries;
import com.scichart.data.model.DoubleRange;
import com.scichart.drawing.utility.ColorUtil;
import com.scichart.extensions.builders.SciChartBuilder;

import java.util.Collections;
import java.util.Random;

import static com.scichart.drawing.utility.ColorUtil.rgb;

public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {

    // SciChart
    private LinearLayout sciChartLayout;
    private SciChartSurface ecgSurface;
    private SciChartSurface heatmapSurface;
    private IXyDataSeries<Double, Double> ecgData;
    private IRenderableSeries ecgSeries;
    private static final int SAMPLE_RATE = 200;
    private int HEATMAP_WIDTH_MINUTE = 5;
    private double HEATMAP_COLUMN_WIDTH_SECOND = 0.25;
    private static final double HEATMAP_YLIM1 = -0.5;
    private static final double HEATMAP_YLIM2 = 1.5;
    private static final double HEATMAP_CLIM1 = -0.2;
    private static final double HEATMAP_CLIM2 = 0.8;
    private int MATRIX_COLUMNS = (int)(HEATMAP_WIDTH_MINUTE *60/ HEATMAP_COLUMN_WIDTH_SECOND);
    private int MATRIX_ROWS = (int)(HEATMAP_YLIM2 - HEATMAP_YLIM1)*SAMPLE_RATE;
    private UniformHeatmapDataSeries<Double, Double, Double> heatmapDataSeries;

    private Switch mSwitchECGEnabled;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sciChartLicense();
        createSciChart();
        initECMSciChart();


        mSwitchECGEnabled = findViewById(R.id.streamSwitch);
        mSwitchECGEnabled.setOnCheckedChangeListener(this);
    }

    public void sciChartLicense () {
        // SciChart License
        try {
            com.scichart.charting.visuals.SciChartSurface.setRuntimeLicenseKey("");
        } catch (Exception e) {
            Log.e("SciChart", "Error when setting the license", e);
        }
    }

    private void createSciChart() {
        // setup SciChart
        sciChartLayout = (LinearLayout) findViewById(R.id.sciChart_layout);
        ecgSurface = new SciChartSurface(this);
        heatmapSurface = new SciChartSurface(this);
        sciChartLayout.addView(ecgSurface);
        sciChartLayout.addView(heatmapSurface);

        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
        ecgSurface.setLayoutParams(layoutParams);
        ecgSurface.setTheme(R.style.SciChart_SciChartv4DarkStyle);
        heatmapSurface.setLayoutParams(layoutParams);
        heatmapSurface.setTheme(R.style.SciChart_SciChartv4DarkStyle);

        // Initialize the SciChartBuilder
        SciChartBuilder.init(this);
        // Obtain the SciChartBuilder instance
        final SciChartBuilder sciChartBuilder = SciChartBuilder.instance();

        // first chart
        IAxis xAxis = sciChartBuilder.newNumericAxis()
                .withAxisId("ecgx")
                .withAutoRangeMode(AutoRange.Never)
                .withAxisTitleMargin(10)
                .build();
        IAxis yAxis = sciChartBuilder.newNumericAxis()
                .withAutoRangeMode(AutoRange.Always)
                .withAxisAlignment(AxisAlignment.Left)
                .build();

        // Add the X axis to the XAxes collection of the surface
        Collections.addAll(ecgSurface.getXAxes(), xAxis);
        Collections.addAll(ecgSurface.getYAxes(), yAxis);

        // ecg data
        ecgData = sciChartBuilder.newXyDataSeries(Double.class, Double.class)
                .build();
        ecgSeries = sciChartBuilder.newLineSeries()
                .withDataSeries(ecgData)
                .withPaletteProvider(new DimTracePaletteProvider())
                .withStrokeStyle(ColorUtil.Green, 2f, true)
                .build();
        Collections.addAll(ecgSurface.getRenderableSeries(), ecgSeries);

        // second chart
        NumericAxis xAxis2 = sciChartBuilder.newNumericAxis()
                .withVisibleRange(0d, 300d)
                .build();

        NumericAxis yAxis2 = sciChartBuilder.newNumericAxis()
                .withAxisAlignment(AxisAlignment.Left)
                .withVisibleRange(-0.5,1.5)
                .withAxisTitleMargin(10)
                .build();

        heatmapDataSeries = new UniformHeatmapDataSeries<>(Double.class, Double.class, Double.class, MATRIX_COLUMNS, MATRIX_ROWS);
        heatmapDataSeries.setStartX(0d);
        heatmapDataSeries.setStepX(0.25d);
        heatmapDataSeries.setStartY(-0.5);
        heatmapDataSeries.setStepY(1d/(double)SAMPLE_RATE);

        // Create a ColorMap Legend
        int[] colorRGBArray = new int[]{
                rgb(0,0,131),
                rgb(0,0,255),
                rgb(0,255,255),
                rgb(255,255,0),
                rgb(255,0,0),
                rgb(128,0,0)};
        float[] colorZValueArray = determineColorMapValues(0, 1);
        ColorMap colorMap = new ColorMap(colorRGBArray, colorZValueArray);

        FastUniformHeatmapRenderableSeries heatmapRenderableSeries = sciChartBuilder.newUniformHeatmap()
                .withColorMap(colorMap)
                .withMinimum(HEATMAP_CLIM1)
                .withMaximum(HEATMAP_CLIM2)
                .withDataSeries(heatmapDataSeries)
                .withPaletteProvider(new TransparentNanUniformHeatMapProvider())
                .build();

        Collections.addAll(heatmapSurface.getXAxes(), xAxis2);
        Collections.addAll(heatmapSurface.getYAxes(), yAxis2);
        Collections.addAll(heatmapSurface.getRenderableSeries(), heatmapRenderableSeries);
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            for (int i = 0; i < 10000; i++) {
                double time = (double)i/SAMPLE_RATE;
                ecgData.append(time, Math.sin(time * 10));
            }
            // update visible range
            ecgSurface.getXAxes().getAxisById("ecgx").setVisibleRange(new DoubleRange(10d, 20d));
//            ecgSurface.getXAxes().getDefault().setVisibleRange(new DoubleRange(10d, 20d));

            for (int i = 0; i < MATRIX_COLUMNS; i++) {
                for (int j = 0; j < MATRIX_ROWS; j++) {
                    final int min = -1;
                    final int max = 1;
                    final int random = new Random().nextInt((max - min) + 1) + min;
                    heatmapDataSeries.updateZAt(i, j, (double) random);
                }
            }
        }
        else {
        }
    }

    public float[] determineColorMapValues(double clim1, double clim2) {

        double intervalC = (clim2 - clim1)/5.0;
        float[] returnValues = new float[6];
        for (int i = 0; i < 6; i++) {
            returnValues[i] = (float) (clim1 + i*intervalC);
        }
        return returnValues;
    }

    public void initECMSciChart() {
        // initialize chart with NaN
        for (int i = 0; i < MATRIX_COLUMNS; i++) {
            for (int j = 0; j < MATRIX_ROWS; j++) {
                heatmapDataSeries.updateZAt(i, j, Double.NaN);
            }
        }
        heatmapDataSeries.setStartX(0d);
        heatmapSurface.zoomExtentsX();
    }
}
  • You must to post comments
Showing 2 results
Your Answer

Please first to submit.