B4J Library [B4X] [XUI] xGraph Class and b4xlib

klaus

Expert
Licensed User
The xGraph Class and B4XLib allows graphic analysis of signals.
It works on all three products: B4A, B4i and B4J.

The graph holds a given number of curves (10 by default) with a given number of samples (10000 by default) these values can be defined in the Designer.
All curves have the same number of samples with the same X signal.

What can be done:
- Draw up to 4 curves on the same graph.
- Show values when moving the cursor on the graph.
- Zooming, either with the cursor or setting in the code.
- Different scale modes.
- Different methods on curves.
-- Copy a curve to another location.
-- Add a value to a curve.
-- Multiply a curve by a value.
-- Add two curves and save the result in another curve.
-- Multiply two curves and save the result in another curve.
-- Calculate the integral of a curve and save the result in another curve.
-- Calculate the derivative of a curve and save the result in another curve.

Attached the xGraphDemo.zip file contains three demo program using the xGraph.b4xlib library,
the xGraph.b4xlib library file, the xGraph.bas file and the xGraph.xml file.

The xGraph library needs the XUI, iXUI, or jXUI libraries.
The xGraphDemo programs need the XUI Views.b4xlib library.

EDIT: 2020.06.23 Version 1.3
Added GraphWithMissingData and MissingDataValue properties
Updated the Tag property according to Erels recommandation:
Added two cursors with display of the curvevalues.
Added a Touch event which return
Added a CursorPositionChanged event returning the CursoorIndex and XIndex.
Added these properties XIndexBegin, XIndexEnd. GraphLeft, GraphTop, GraphWidth and GraphHeight
Version 1.2 2020.02.23
Set CurveColor to Public

EDIT: 2019.12.14 Version 1.1
Amended bug reported HERE

upload_2019-8-18_20-47-1.gif


1592918602205.png

xGraph

Author:
Klaus CHRISTL (klaus)
Version: 1.3
  • xGraph
    • Functions:
      • AddCursor (Color As Int)
        Adds a cursor with the given color by touching the graph
      • CalcAddValue (CurveIndex As Int, Value As Double, ZoomedPartOnly As Boolean)
        Adds a value to the given cuve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcDerivative (SourceIndex As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Calculates the derivative of the source curve and copies the result in the destination curve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcDevide2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Devides two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) / Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcIntegral (SourceIndex As Int, DestinationIndex As Int, InitilalCondition As Double, ZoomedPartOnly As Boolean)
        Calculates the integral of the source curve and copies the result in the destination curve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcMeanValue (CurveIndex As Int, ZoomedPartOnly As Boolean) As Double
        Returns the mean value of the given curve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcMultiplyByValue (CurveIndex As Int, Value As Double, ZoomedPartOnly As Boolean)
        Multiplies the curve by the given value
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcMutiply2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Multiplies two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) * Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcSubtract2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Substracts two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) - Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcSum2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Adds two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) + Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CopyCurve (SourceIndex As Int, DestinationIndex As Int)
        Copies the curve with SourceIndex to the DestinationIndex curve.
      • DrawGraph
        Draws a graph
      • GetScaleAuto (CurveIndex As Int) As ScaleValues
        Gets the automatic scale for the given curve
      • GetScaleManu (CurveIndex As Int) As ScaleValues
        Gets the manual scale for the given curve
      • NumberFormat3 (Number As Double, MaxDigits As Int) As String
        Formats numbers with a fixed number of digits and scientific notation
      • RemoveCursor (Index As Int)
        Removes one or both cursors.
        Set 0 or 1 as cursor index to delete one cursor.
        Set 2 to delete both cursors.
        When you remove cursor(0) cursor(1) becomes cursor(0), it is removed from the list.
        If there is only one Cursor, then any index value will remove the cursor.
      • SetCursor (XIndex As Int, CursorIndex As Int, Color As Int)
        Sets one of the two cursors.
        XIndex = sample index, in the curve array.
        CursorIndex = 0 or 1, index of the cursor.
      • SetCurveName (CurveIndex As Int, Name As String, UpdateGraph As Boolean)
        Sets the a new name for the curve with the given index
        UpdateGraph = True redraws the graph
      • SetCurveUnit (CurveIndex As Int, Unit As String, UpdateGraph As Boolean)
        Sets a new unit for the curve with the given index
        UpdateGraph = True redraws the graph
      • SetSameScale (SameScaleCurveIndex As Int)
        Sets the scale of curve SameScaleCurveIndex for all curves
      • SetScaleManu (CurveIndex As Int, MinVal As Double, MaxVal As Double)
        Sets a manual scale for a given curve
      • SetZoomIndexes (BeginIndex As Int, EndIndex As Int)
        Sets the begin and end indexes for zoom diaplay
      • SetZoomMode
        Sets the zooming mode
        The user selects with the curor the left limit and then the right limit
    • Properties:
      • AutomaticYScales
        Gets or sets the automatic scales mode
        True displays automatic Y sacales for all curves
        False displays the manual scales
      • CurvesToDisplay
        Gets or sets the curves to display
      • DisplayCurveIndex
        Gets or sets the DisplayCurveIndex property
        True displays the curve index before the curve name
        Example: 3 : Speed
      • DisplayCurveUnit
        Gets or sets the DisplayCurveUnit property
        True displays the curve unit after the curve name
        Example: Speed [m/s]
      • DrawCursorValues
        gets or sets the DrawCursorValues property
        Displays the values of the cuves at the cursor position
      • GraphColor
        Gets or sets the graph background color
      • GraphHeight
        Gets the GraphHeight property
        The height of the Graph in pixels
      • GraphWidth
        Gets the GraphWidth property
        The width of the Graph in pixels
      • GraphWithMissingData
        Gets or sets the GraphWithMissingDat property
        Manages curves with missing data, it is necessary to enter the MissingDataValue in place.
      • GridColor
        Gets or sets the graph grid color
      • GridFrameColor
        Gets or sets the graph grid frame color
      • Height
        Gets or sets the Height property
      • Left
        Gets or sets the Left property
      • MissingDataValue
        Gets or sets the MissingDataValue property
        Used when GraphWithMissingData = True, the missing data must be replaced by this value
      • NbMaxCurves
        Gets or sets the max number of curves
      • NbMaxSamples
        Gets or sets the max number of samples
      • NbSamples
        Gets or sets the current number of samples
      • NbXIntervals
        Gets or sets the number of x axis intervals
      • NbYIntervals
        Gets or sets the number of y axis intervals
      • OuterFrame
        Gets or sets the graph outer frame property
        True = draws an outer frame around the graph
      • OuterFrameColor
        Gets or sets the graph outer frame color
      • ScaleXValues
        Gets or sets the ScaleValues property
        it is a string with the different scale values separated by an exclamation mark.
        it must begin with 1! and end with !10
        Example: the default property 1!2!2.5!5!10
        These values can be selected in the Designer: 1!2!2.5!5!10|1!1.2!1.5!1.8!2!2.5!3!4!5!6!7!8!9!10
      • ScaleYValues
        Gets or sets the ScaleValues property
        used for automatic scales
        it is a string with the different scale values separated by the exclamation mark.
        it must begin with 1! and end with !10
        Example: the default property 1!2!2.5!5!10
        These values can be selected in the Designer: 1!2!2.5!5!10|1!1.2!1.5!1.8!2!2.5!3!4!5!6!7!8!9!10
      • Snapshot
        Returns a B4XBitmap object of the graph (read only)
      • Title
        Gets or sets the graph title
      • Top
        Gets or sets the Top property
      • Width
        Gets or sets the Width property
      • XAxisName
        Gets or sets the x axis name
      • XAxisUnit
        Gets or sets the x axis uni
      • XIndexBegin
        Gets the XIndexBegin property
        Index of the first visible item
      • XIndexEnd
        Gets the XIndexBegin property
        Index of the last visible item
 

Attachments

Last edited:

rgarnett1955

Active Member
Licensed User
Can it be used to display real-time data (Dynamic Graph) ?
You can you xGraph for displaying realtime data that has a slow sample rate i.e >= 0.5 sample per second. I use it for plotting mains power voltage frequency etc at an update rate of 2 seconds. I make the x axis range -2 Hours and reverse the data.The latest data is then shown at the right hand side of the graph. The CPU load with 3600 samples is negligible.

The reason I used xGraph was that it had an inbuilt cursor and was simple to use. It also provides for multiple y axis ranges on the same graph space. It does exactly what I need.

The first code snippet is the initialisation. I have left the test data in, but you could initialise the arrays to whatever you like.

B4X:
Private Sub InitGraphX1
    Private i As Int
 
    xGraph1.CurveYName(0) = "Voltage RMS"
    xGraph1.SetScaleManu(0, 220, 270)
    xGraph1.CurveYName(1) = "Frequency Hz"
    xGraph1.SetScaleManu(1, 48.5, 51.5)
 
    xGraph1.CurvesToDisplay.Initialize2(Array As Int(0, 1))
 
    Private x0 = -120 * 30 As Int
    Samples = NWServ.NO_SAMPLES
    xGraph1.NbSamples = Samples + 1
    For i = 0 To Samples
        xGraph1.CurveX(i) = (i + x0) / 30
        xGraph1.CurveY(0, i) = 1 * SinD(i * 0.1) + 247
        xGraph1.CurveY(1, i) = 0.1 * CosD(i * 0.1)
    Next
    xGraph1.DrawGraph
End Sub
This next snippet is all you need to do to update the graph with realtime data.

B4X:
    ptrOut = ptrIn

   For i = 0 To Main.Samples - 1
       If ptrOut = NO_SAMPLES Then
           ptrOut = 0
       End If
      
       Main.xGraph1.CurveY(0, i) = arrayVrms(ptrOut)
       Main.xGraph1.CurveY(1, i) = arrayFreq(ptrOut)
      
       Main.xGraph2.CurveY(0, i) = arraySupplykW(ptrOut)
       Main.xGraph2.CurveY(1, i) = arraySolarkW(ptrOut)
       Main.xGraph2.CurveY(2, i) = arrayQuality(ptrOut)
       Main.xGraph2.CurveY(3, i) = arrayLoadkW(ptrOut)
       ptrOut = ptrOut + 1
   Next
   Main.xGraph1.DrawGraph
   Main.xGraph2.DrawGraph
h
Too easy!!

In this code NO_SAMPLES is a constant of 3600. (2 hours of 2 second data)

I have uploaded the project so you can see the layout for the graphs.

Best regards

Rob

PS I had a seniors moment and got the code for right hand origin wrong. I have updated it, but I haven't bothered changing the zip file because the Layout is still the same.
 

Attachments

Last edited:

rgarnett1955

Active Member
Licensed User
The xGraph Class and B4XLib allows graphic analysis of signals.

The graph holds a given number of curves (10 by default) with a given number of samples (10000 by default) these values can be defined in the Designer.
All curves have the same number of samples with the same X signal.

What can be done:
- Draw up to 4 curves on the same graph.
- Show values when moving the cursor on the graph.
- Zooming, either with the cursor or setting in the code.
- Different scale modes.
- Different methods on curves.
-- Copy a curve to another location.
-- Add a value to a curve.
-- Multiply a curve by a value.
-- Add two curves and save the result in another curve.
-- Multiply two curves and save the result in another curve.
-- Calculate the integral of a curve and save the result in another curve.
-- Calculate the derivative of a curve and save the result in another curve.

Attached the xGraphDemo.zip file contains three demo program using the xGraph.b4xlib library,
the xGraph.b4xlib library file, the xGraph.bas file and the xGraph.xml file.

The xGraph library needs the XUI, iXUI, or jXUI libraries.
The xGraphDemo programs need the XUI Views.b4xlib library.

EDIT: 2019.12.14 Version 1.1
Amended bug reported HERE

View attachment 83217

xGraph

Author: Klaus CHRISTL (klaus)
Version: 1.1
  • xGraph
    • Functions:
      • CalcAddValue (CurveIndex As Int, Value As Double, ZoomedPartOnly As Boolean)
        Adds a value to the given cuve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcDerivative (SourceIndex As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Calculates the derivative of the source curve and copies the result in the destination curve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcDevide2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Devides two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) / Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcIntegral (SourceIndex As Int, DestinationIndex As Int, InitilalCondition As Double, ZoomedPartOnly As Boolean)
        Calculates the integral of the source curve and copies the result in the destination curve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcMeanValue (CurveIndex As Int, ZoomedPartOnly As Boolean) As Double
        Returns the mean value of the given curve
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcMultiplyByValue (CurveIndex As Int, Value As Double, ZoomedPartOnly As Boolean)
        Multiplies the curve by the given value
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcMutiply2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Multiplies two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) * Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcSubtract2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Substracts two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) - Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CalcSum2Curves (SourceIndex1 As Int, SourceIndex2 As Int, DestinationIndex As Int, ZoomedPartOnly As Boolean)
        Adds two curves and copies the result in the destination curve
        Curve(DestinationIndex) = Curve(SourceIndex1) + Curve(SourceIndex2)
        ZoomedPartOnly = True calculates only the zoomed part if the curve is zoomed
      • CopyCurve (SourceIndex As Int, DestinationIndex As Int)
        Copies the curve with SourceIndex to the DestinationIndex curve.
      • DrawGraph
        Draws a graph
      • GetScaleAuto (CurveIndex As Int) As ScaleValues
        Gets the automatic scale for the given curve
      • GetScaleManu (CurveIndex As Int) As ScaleValues
        Gets the manual scale for the given curve
      • NumberFormat3 (Number As Double, MaxDigits As Int) As String
        Formats numbers with a fixed number of digits and scientific notation
      • SetCurveName (CurveIndex As Int, Name As String, UpdateGraph As Boolean)
        Sets the a new name for the curve with the given index
        UpdateGraph = True redraws the graph
      • SetCurveUnit (CurveIndex As Int, Unit As String, UpdateGraph As Boolean)
        Sets a new unit for the curve with the given index
        UpdateGraph = True redraws the graph
      • SetSameScale (SameScaleCurveIndex As Int)
        Sets the scale of curve SameScaleCurveIndex for all curves
      • SetScaleManu (CurveIndex As Int, MinVal As Double, MaxVal As Double)
        Sets a manual scale for a given curve
      • SetZoomIndexes (BeginIndex As Int, EndIndex As Int)
        Sets the begin and end indexes for zoom diaplay
      • SetZoomMode
        Sets the zooming mode
        The user selects with the curor the left limit and then the right limit
    • Properties:
      • AutomaticYScales
        Gets or sets the automatic scales mode
        True displays automatic Y sacales for all curves
        False displays the manual scales
      • CurvesToDisplay
        Gets or sets the curves to display
      • DisplayCurveIndex
        Gets or sets the DisplayCurveIndex property
        True displays the curve index before the curve name
        Example: 3 : Speed
      • DisplayCurveUnit
        Gets or sets the DisplayCurveUnit property
        True displays the curve unit after the curve name
        Example: Speed [m/s]
      • GraphColor
        Gets or sets the graph background color
      • GridColor
        Gets or sets the graph grid color
      • GridFrameColor
        Gets or sets the graph grid frame color
      • NbMaxCurves
        Gets or sets the max number of curves
      • NbMaxSamples
        Gets or sets the max number of samples
      • NbSamples
        Gets or sets the current number of samples
      • NbXIntervals
        Gets or sets the number of x axis intervals
      • NbYIntervals
        Gets or sets the number of y axis intervals
      • OuterFrame
        Gets or sets the graph outer frame property
        True = draws an outer frame around the graph
      • OuterFrameColor
        Gets or sets the graph outer frame color
      • ScaleXValues
        Gets or sets the ScaleValues property
        it is a string with the different scale values separated by an exclamation mark.
        it must begin with 1! and end with !10
        Example: the default property 1!2!2.5!5!10
        These values can be selected in the Designer: 1!2!2.5!5!10|1!1.2!1.5!1.8!2!2.5!3!4!5!6!7!8!9!10
      • ScaleYValues
        Gets or sets the ScaleValues property
        used for automatic scales
        it is a string with the different scale values separated by the exclamation mark.
        it must begin with 1! and end with !10
        Example: the default property 1!2!2.5!5!10
        These values can be selected in the Designer: 1!2!2.5!5!10|1!1.2!1.5!1.8!2!2.5!3!4!5!6!7!8!9!10
      • Snapshot
        Returns a B4XBitmap object of the graph (read only)
      • Title
        Gets or sets the graph title
      • XAxisName
        Gets or sets the x axis name
      • XAxisUnit
        Gets or sets the x axis uni
Hi Klause

If you ever get a chance do you think that you could add the following feature to xGraph, (probably applies to xChart as well):

- Do not plot values that are set to "not a number" (NaN) Matlab does this and its handy for prefilling a graph buffer before valid data is received or when a displayed calc goes bad. Gaps in the trace a better than trying to plot infinity or - infinity.

Best regards

Rob
 

klaus

Expert
Licensed User
I could add two new properties GraphWithMissingSamples and MissingSampleValue.

GraphWithMissingSamples, when set to True, tests for missing samples. When set to False avoids wasting time to check for missing sample values.
Two different DrawCurves routines.

MissingSampleValue = a specific value representing a missing sample. Default value = 1000000000

It would look like this:

upload_2019-12-16_15-36-45.png
 

klaus

Expert
Licensed User
No, not currently.
The xGraph object can contain up to 10 curves.
But only 4 out of the 10 can be displayed at the same time.
The colors for these 4 curves are defined internaly.
Then it depends on what color to change?
One color for each of the 10 curves or the colors for the 4 visible curves.
 

mahyara

Member
Thanks for your reply, I wanted to change the scale, curve colors or editing the legend I mean instead of "0:" which comes before curve name like Temperature not 0:Temperature, generally I meant some graphical modifications.
 

klaus

Expert
Licensed User
You can disable the curve number with:
B4X:
xGraph1.DisplayCurveIndex = False
If you use the xGraph.bas module you can set the CurveColor array as Public like this:
B4X:
Public CurveColor(4) As Int
I will set it to Public in the next update.

...generally I meant some graphical modifications
What kind of graphical modifications?
 

mahyara

Member
You can disable the curve number with:
B4X:
xGraph1.DisplayCurveIndex = False
If you use the xGraph.bas module you can set the CurveColor array as Public like this:
B4X:
Public CurveColor(4) As Int
I will set it to Public in the next update.


What kind of graphical modifications?
Thanks for the hints they were great and improved my plot. Just sometimes even on your example, when I zoom the window also becomes half width as shown on the attachment. Is it normal or me again making mistakes? and is there a touch focus type i mean with two fingers getting near each other zooming in and when fingers getting far zooming out?
 

Attachments

mahyara

Member
I used BAS and could do changes I wanted to do just I dont know how to change Width (ratio of curve to graph: distance shown with arrow to maximize area used for curve)
 

Attachments

klaus

Expert
Licensed User
Just sometimes even on your example, when I zoom the window also becomes half width as shown ...
This is normal and it's due to the automatic scale.
Depending on the difference between the first and last value and a given scale the number of divisions changes.
And, as I want to keep the with of the divisions constant, the length of the graph is different.
Many years ago I had written a graphic analysis program in VB. The graphs could be saved as images and transfered to Word with square beeing either 1cm or 5mm.
and is there a touch focus type i mean with two fingers getting near
No, and the zoom function works only on the X axis.
 

mahyara

Member
This is normal and it's due to the automatic scale.
Depending on the difference between the first and last value and a given scale the number of divisions changes.
And, as I want to keep the with of the divisions constant, the length of the graph is different.
Many years ago I had written a graphic analysis program in VB. The graphs could be saved as images and transfered to Word with square beeing either 1cm or 5mm.

No, and the zoom function works only on the X axis.
How about this: how can I decrease this gap between graph panel (minimizing the distance shown as Width in upper photo I posted)
 

mahyara

Member
It would need to redesign the drawing function.
Whatever I did I could not make it in a way that whenever I zoom the window is not scaled again (decreasing graph size) do you have any example to give me so that I know how to resolve this problem.
 
Top