Closed west-rynes closed 3 months ago
Hello,
As you can see below, the code to transform a numpy array to a full C-Style C Array (which ImPlot expects) is quite complex
Concerning non contiguous arrays: I would advise you to use ascontiguousarray before calling implot, since I think it would be too complex to let the code handle another special case. However, I could raise a readable exception if if the received array is detected as not contiguous.
Concerning the stride option: I'm out of time to study this more in detail now. I'll give it a more complete look next week.
Cheers
Since it is a lot of work. Perhaps for other users in the future there would be some info in the documentation to indicate that contiguous should only be used.
That is what I have been doing. I just figured some people may not understand why their plotting is not working so I thought I’d submit an issue.
Don’t worry about the stride option. I just subsample the numpy array and then use the as contiguous numpy function.
I didn’t want to cause any significant work. Thank you for looking at it.
Ok. Two modifications were applied.
Doesn't the offset
param simply depend on index from the user side? I have been able to use the offset
param successfully for some plotting widgets, didn't experience any issues with it before. It's very useful for making "scrolling" graphs and such by offsetting an array like a circular buffer.
@Aman-Anas: Thanks for your remark and reactivity!
Indeed offset does not depend on the size of the type as long as stride is not used.
See extract from ImPlot code below:
template <typename T>
IMPLOT_INLINE T IndexData(const T* data, int idx, int count, int offset, int stride) {
const int s = ((offset == 0) << 0) | ((stride == sizeof(T)) << 1);
switch (s) {
case 3 : return data[idx];
case 2 : return data[(offset + idx) % count];
case 1 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((idx) ) * stride);
case 0 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((offset + idx) % count) * stride);
default: return T(0);
}
}
When stride is disabled, we only fall into case 2 and case 3 (which are OK). Case 0 and 1 do pointer arithmetic that depend on the size (IMHO (const unsigned char*)data + (size_t)((idx) ) * stride
is a valid pointer iif stride is a multiple of sizeof(T))`
See commit https://github.com/pthom/imgui_bundle/commit/4316732046e53aabfbd6352bf10e1bd9b142f685 that restores the offset.
I noticed two potential issues: (or am just missing things)
1) It appears that the wrapping of the implot functions that take numpy arrays expect contiguous data. Would it be possible to enhance the wrapping to handle non-contiguous data. I believe the numpy C api allows that with a flag NPY_ARRAY_C_CONTIGUOUS. This may help users who may not be aware that they need to currently alway supply contiguous data.
2) The
stride
option in the plot functions does not seem to work as expected.Sample code illustrating behavior:
Example output
The red line with the
stride
option mangles the data:The orange curve with a sliced numpy array which then non-contiguous reads incorrectly:
Thanks as aways for this great imgui wrapper bundle and the helloimgui ease of use library.