Industrial Data Science
in C# and .NET:
Simple. Fast. Reliable.
 
 

ILNumerics - Technical Computing

Modern High Performance Tools for Technical

Computing and Visualization in Industry and Science

Live Debug Data Plotting in C#

ILNumerics Array Visualizer is an interactive, graphical debug tool for Visual Studio. During your debug session it connects to the Visual Studio debug engine and allows immediate insight into the data of your C# program. Arbitrary array data is plotted in various, interactive chart styles: as 1D and 2D line plots, scatter plots, bar plots, as 3D surface plots, and images. Easily describe the data via arbitrary expressions. Export data in a large number of external formats, including charts, HDF5 and Microsoft Excel. Follow your data with each debug step to quickly find bugs in the algorithm.

Visualizing Debug Data - 3 Simple Steps

1. When halted in your Visual Studio debug session go to the Visual Studio View menu:    

VIEW -> Other Windows -> ILNumerics Array Visualizer

2. Enter the name of an array variable from your current debug scope into the expression text area of the Array Visualizer.

3. (Optional) Choose a plotting type from the list of available 2D and 3D plots.

4. (Optional) Apply further configurations to the plot.

 

Plotting Array Expressions in C#

Let's start by creating a very simple C# program:

The content of the variable A at the current statement is plotted by entering A into the Array Visualizer and pressing [Enter].

    Here, the content is shown as text. Click on the Line Plot Tab  at the top of the Array Visualizer tool window to show the data as line plot. Note how the plot is linked to the variable: pressing F10 modifies A in the next statement. The change is immediately reflected by the plot.

    Get Interactive

    No matter, how you interact with the data in your debug session – changes will show up immediately in the array visualizer. Let's set the 3rd element of A to the value 10 in the immediate window. See how the plot reflects the changes:

    Ad-hoc visualizations of any vector data are possible by entering code creating an array containing the desired elements. In order to plot some values, taken from constants, variables, other arrays or functions:

    new double[]{ 1.2, A[3]+1, -Math.Tan(-2.223), r, B }

     

    Supported Array Expressions in C#

    In C# the ILNumerics Array Visualizer plots arbitrary expressions yielding the following array types:

    • ILNumerics arrays: Array<T>, InArray<T>, ...
    • 1D System.Array: double[], float[], int[], ILNumerics.complex(), ...
    • Multidimensional System.Array: double[,,], int[,], byte[,,,], ILNumerics.complex(,), ...
    • On-the-fly expressions evaluating to arrays: new int[] {1,2,3,4,5}fft(A)[r(0,end/2-1)], ...
    • Arrays of structs ('records', user defined types)

    All primitve numeric element types are supported:

    Floating point data types double float

    ILNumerics .complex

    ILNumerics .fcomplex

           
    Integral data types int long short sbyte uint ulong ushort byte
    Character char              

     

    Expression entered in the Array Visualizer are evaluated in the context of the current debug stack frame. Your program must be halted in debug mode. Any valid C# code can be used as expression for the Array Visualizer, including variables, function calls etc. from assembly modules currently referenced from your project. 

    Users of the ILNumerics Computing Engine can utilize any function from ILMath, from any referenced toolbox, combining several Array<T> variables, subarray expressions, accessing HDF5 data, and so on...

    N-D Array Plotting Example

    Handling matrices and arrays with more dimensions works in the same way. Next, we create and visualize a two dimensional .NET System.Array:

    Plot Types 

    Next to the simple text output the 2D matrix D can be visualized by means of the following chart types:

    XY-Line Plot Scatter Plot Rows Plot
    Surface Plot ImageSC Plot Bar Plot

    Read more about the available plot types in ILNumerics Array Visualizer.

    Using Array Descriptors in C# 

    In the previous sections of this manual, the data to plot were represented as simple, dense array variables. However, many technical applications implement more complex data storage scenarios. In most situations, the interesting data are stored within recordsets, or structs of more complex data types. 

    Example: a data type definition for storing 3D measurement data.

     

    Here, 5 data elements of type double are stored for each measurement: the X,Y, and Z coordinates as the position of the measurement and two arbitrary data values. Data1 and Data2 might be used to store the actual value measured or some error range / confidence information computed for the measurement or any other useful value.

    In real world applications data structures like this are very popular. Working with them can be cumbersome, however, especially when the number of measurements grows high. Developers often enough end up inspecting individual fields of every single measurement, utilizing data tips in Visual Studio:

    Now, the ILNumerics Array Visualizer can simplify things greatly. Use the following expression with the Array Visualizer: 

    myData[0].Data1

    I.e.: reference the first struct element by index 0 and the struct member you are interested in. 

    Just enter the path to the interesting field (here: 'myData[0].Data1')  into the expression text box and hit Enter. Choose a useful plotting type and inspect all Data1 values from all Measurements at once! In this example we selected 'Line Plot' as output type. Just as well, we could have made use of bar plots or others...

    Combining multiple members

    With a little help of our flexible array descriptor syntax we can combine arbitrary elements of the structure array to create even more useful plots. Let's modify the expression to 'myData' to reference the array itself and press Enter: 

    The Array Visualizer recognizes that we try to plot data from the struct array myData. It activated the array descriptor mode and filled in the length of the array (9) and the strides of individual elements for us (40b). Now, since struct arrays can have arbitrary member types, we are asked to enter a valid type for visualizing the data. Enter double as element type:

      

    What we see now is the visualization of the first struct member X of all array elements. We can enhance the plot by adding Y and Z. In order to archieve this, recall the memory layout of the struct array: 

    By now we have extracted the vector of X values from the memory by picking the first double from each struct object, skipping over 40 bytes to get to the next X value. We may see this extraction as creating the following matrix row:

    Extracting more data than X corresponds to having more rows in the matrix:

    This requires a slight modification to the array descriptor only:

     

    This time and by using the scattered data plot the 3D positions of the measurements are made clearly visible. (We show the X-Y positions only here, since we look straight onto the X-Y plane. If there were any useful Z values we would visualize them by switching to the 3D view and rotating the plot with the mouse.)

    Another useful view is given by the bar plot tab. It shows the X, Y and Z coordinates as separated groups: 

    Now we could easily add both, Data1 and Data2 as new rows to the matrix - this is left to the reader as exercise.

    Member Selection - Working with Offsets

    Any member from the struct can be selected for plotting in the Array Visualizer individually. In order to plot both data members only we must jump over preceding elements and start the extraction matrix at the first (in terms of memory address) data member. In our example this corresponds to the starting address of the Data1 member of the 1st struct array element, 0x02DE28BC. This address is 3 x 8 = 24 bytes higher than the start of X1. We can use the array descriptor to enter the offset manually. Note that we also adjusted the lenght of the first dimension (2) to extract Data1 and the subsequent Data2 member:

    Alternatively, we could leave the work of computing the required offset to the Array Visualizer. We start all over by clearing the Array Visualizer expression window (CTRL+A or CTRL+Enter) and entering the direct path to the first Data1 member:

      ->[Enter]

    Note how the offset of 24 bytes has been figured out automatically. From here, it is easy to add the additional dimension to get the exact same plotting result as in the example above:

    Replacing the Memory Window in C#

    You may have encountered that the Visual Studio Debug Memory Window does not work as expected in all Situations in C#. Older versions of Visual Studio did not support memory display in C# at all. While more recent versions have improved, they still expose some problems in this matter. The Array Visualizer is able to display any accessible memory in any shape / type one may possibly needs. Therefore, it can be used as a nice replacement for the Debug Memory Tool Window, too. 

    For example, we can use a simple line plot in order to get an overview over the bytes assembling the execution assembly: 

    Or, use the text view in order to create a table of bytes nicely arranged and formatted: 

    By varying the element type, the number of rows and columns and, potentially, by working with modified strides one can create highly efficient 'memory watch views'. Such output again is automatically refreshing on data changes.  You may also try the ImageSC plot for similar purposes.

     

    Read more about array descriptors in the array descriptor tutorial (mixed languages).