I've started implementing some
changes in how GtkDatabox handles input data, along the lines of
my earlier posting. Would like some feedback on the interface,
and on whether worthwhile or not. It can be done in a completely
backwards compatible way.
GOALS: 1. more flexible / robust data handling (handle non-float data, growing arrays, ring buffers, matrices where the data is a particular row or column). 2. be backwards compatible with existing scheme 3. minimize or eliminate data copying / memory allocations PROPOSAL: instead of passing a (gfloat *) pointer and a length: pass a (void *) pointer, a starting offset, a stride number, and the number (length) of samples to process, as well as the size of the allocated buffer, which may be less than the length when dealing with a ring buffer. The idea is to treat the data as coming from a matrix of floats/doubles/ints. If gtkdatabox is told to go beyond the available number of rows of data, then wrap around to the beginning (i.e. treat as ring buffer). In the simple case, the matrix has one column of floats, in which case it's just like what we have now. API CHANGES For complete backwards compatibility, keep the current convenience allocators: gtk_databox_lines_new(len, X, Y, color, size); but add something like these: gtk_databox_lines_new_full(allocatedlength, length, X, xstart, xstride, G_TYPE_INT, Y, ystart, ystride, G_TYPE_DOUBLE, color, size); gtk_databox_graph_data_update(graph, allocatedlength, length, X, xstart, xstride, G_TYPE_INT, Y, ystart, ystride, G_TYPE_DOUBLE); where xstart/ystart are almost always 0, and xstride and ystride are usually 1 (or at least equal to ncols if the data is in a matrix). WHAT FILES/FUNCTIONS WOULD CHANGE 1. gtkdatabox_xyc_graph.c and gtkdatabox_xyyc_graph.c 2. gtk_databox_value(s)_to_pixel*() 3. Also, each of the graphs' *_real_draw() functions need minor changes. FOR SIMPLE LINEAR ARRAYS: Where for a linear array like our current ones: X and Y are the starts of their arrays, length and allocated length are usually the same, xstart/ystart are 0 xstride/ystride are 1 Note if you want to plot only a subset of the array, can alter xstart/length, no need to reallocate, or memory copy. FOR MATRIX DATA: But if the data comes from a matrix with, say 2 columns, 10 rows: A00 A01 A10 A11 A20 A21 A30 A31 .. A90 A91 and we want the plot the first column as X, the second as Y: Then X could point to A00, Y could point to A01 xstart is 0, ystart is 0, since we want to start with the first row. xstride and ystride are 2 since there are two columns and length and allocated length are 9, since X will have a maximum of 10 elements, and we want to plot all 10 elements. FOR REAL TIME DATA: Most people use ring-buffers for data collection here. With the proposed data handling, it should be easy to scroll data. No memory copies. A0 A1 A2 A3 A4 A5 ... A9 if we are plotting 5 elements, and the newest data in the ring buffer was on A2 (and it's wrapped around already), then pass it the following: X = A0 xstart = A2-5 = A8 length = 5 allocated length = 10 (it will know to wrap around to the beginning because xstart + length is past the allocated length. xstride = 1 ALTERNATIVES: GArrays have been proposed as an alternative. Problems wtih GArrays: 1. It's hard to implement in a backwards compatible manner. 2. Most users of gtkdatabox, I'd guess, are not doing their data analysis using glib structures like GArrays. So if your data is already in some format in memory, you'd have to copy it into a GArray for GtkDatabox 3. Also, there's nothing magical about GArray. All it does (I assume) is internally call realloc() if adding an element increases things beyond the allocated storage. That's just not hard to do with the existing float arrays method. But I don't want to waste a lot of time. I have no real need for this myself. I can get rid of the xstart/xstride/etc, and leave the type field, and add support for G_TYPE_FLOAT/G_TYPE_DOUBLE/G_TYPE_INT. That's rather easier. If the consensus is this is all too complicated, I'll stop. Sincerely, -- Amish |