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.
- Gang Xu asked 4 years ago
- last edited 4 years ago
- You must login to post comments
Hi there,
-
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.
-
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
- Yura Khariton answered 4 years ago
- last edited 4 years ago
-
Thanks for the advice.
- You must login to post comments
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();
}
}
- Gang Xu answered 4 years ago
- last edited 4 years ago
- You must login to post comments
Please login first to submit.