So I have an external C function that returns a pointer to an array. I'm trying to figure out how to convert the pointer to something that can be be displayed on the screen using the latest version of LabView (2019, assume I have all the toolkits).
The C function signature imports fine and is designed to display 16 bit images.
STATUS DemoImage(unsigned short** ptr, int64* rows, int64* columns, int64 image_idx)
with ptr eventually filling a pointer containing the memory location to 16 bit image. rows, columns work as expected.
Whats the name of the controllers that convert the data type to something that can be displayed? I'd also appreciate answers that only address how to display a 8 bit images as I can convert them in my own library if worst, comes to worst.
There is a vi.lib VI not on the palette that you can use: GetValueByPointer.
Detailed walkthrough
For the step-by-step explanation, see this NI document.
2D arrays are represented as an array of arrays. Since an array is really a pointer, a 2D array is a pointer to an array of pointers, where each pointer points to the individual rows of the array. So in order to dereference a 2D Array, you must first dereference the individual pointers to each row, and then dereference in individual elements in each row. The following snippet shows an example of this:
Download examples
For a download with examples, see this one instead, section 4.d.
Returning values by reference (pass by ref)
Function:void ReturningValuesByReference_2DArrayOfIntegers (int rows, int cols, int ***newArray);
VI:Returning Values By Reference 2D Array Of Integers Complete.vi
Related
Preamble
On another question I understood that python constructors routines does not make a copy of the provided numpy array only if the data-type of the array is the same for all the entries. In case the constructor is fed with a structured numpy array with different types on columns, it makes a copy.
Implementation reference
df_dict = {}
for i in range(5):
obj = Object(1000000)
arr = obj.getNpArr()
print(arr[:10])
df_dict[i] = pandas.DataFrame.from_records(arr)
print("The DataFrames are :")
for i in range(5):
print(df_dict[i].head(10))
In this case Object(N) constructs an instance of Object which internally allocates and initializes a 2D array of shape (N,3), with dtypes 'f8','i4','i4' on each row. Object manages the life of these data, deallocating it on destruction. The function Object.getNpArr() returns a np.recarray pointing to the internal data and it has the above mentioned dtype. Importantly, the returned array does not own the data, it is just a view.
Problem
The DataFrame printed at the end show corrupted data (with respect to the printed array inside the first loop). I am not expecting such behaviour, since the array fed to the pandas construction function is copied (I separately checked this behaviour).
I have not many ideas about the cause and solutions to avoid data corruption. The only guess I can make is:
the constructor starts allocating the memory for its own data, which takes long because of the big size, and then copies
before/during the allocation/copy, the GIL is released and it is taken back to the for loop
for loop proceed before the copy of the array is completed, going to the next iteration
at the next iteration the obj name is moved to the new Object and the memory is deallocated, which causes data corruption in the copy of the DataFrame at the previous iteration, which is probably still running.
If this is really the cause of the issue, how can I find a workaround? Is there a way to let the GIL go through only when the copy of the array is effectively done?
Or, if my guess is wrong, what is the cause of the data corruption?
I'm going through a Fortran code, and one bit has me a little puzzled.
There is a subroutine, say
SUBROUTINE SSUB(X,...)
REAL*8 X(0:N1,1:N2,0:N3-1),...
...
RETURN
END
Which is called in another subroutine by:
CALL SSUB(W(0,1,0,1),...)
where W is a 'working array'. It appears that a specific value from W is passed to the X, however, X is dimensioned as an array. What's going on?
This is non-uncommon idiom for getting the subroutine to work on a (rectangular in N-dimensions) subset of the original array.
All parameters in Fortran (at least before Fortran 90) are passed by reference, so the actual array argument is resolved as a location in memory. Choose a location inside the space allocated for the whole array, and the subroutine manipulates only part of the array.
Biggest issue: you have to be aware of how the array is laid out in memory and how Fortran's array indexing scheme works. Fortran uses column major array ordering which is the opposite convention from c. Consider an array that is 5x5 in size (and index both directions from 0 to make the comparison with c easier). In both languages 0,0 is the first element in memory. In c the next element in memory is [0][1] but in Fortran it is (1,0). This affects which indexes you drop when choosing a subspace: if the original array is A(i,j,k,l), and the subroutine works on a three dimensional subspace (as in your example), in c it works on Aprime[i=constant][j][k][l], but in Fortran in works on Aprime(i,j,k,l=constant).
The other risk is wrap around. The dimensions of the (sub)array in the subroutine have to match those in the calling routine, or strange, strange things will happen (think about it). So if A is declared of size (0:4,0:5,0:6,0:7), and we call with element A(0,1,0,1), the receiving routine is free to start the index of each dimension where ever it likes, but must make the sizes (4,5,6) or else; but that means that the last element in the j direction actually wraps around! The thing to do about this is not use the last element. Making sure that that happens is the programmers job, and is a pain in the butt. Take care. Lots of care.
in fortran variables are passed by address.
So W(0,1,0,1) is value and address. so basically you pass subarray starting at W(0,1,0,1).
This is called "sequence association". In this case, what appears to be a scaler, an element of an array (actual argument in caller) is associated with an array (implicitly the first element), the dummy argument in the subroutine . Thereafter the elements of the arrays are associated by storage order, known as "sequence". This was done in Fortran 77 and earlier for various reasons, here apparently for a workspace array -- perhaps the programmer was doing their own memory management. This is retained in Fortran >=90 for backwards compatibility, but IMO, doesn't belong in new code.
Definition:
As defined here, CGGetDisplaysWithPoint takes 4 parameters:
A CGPoint object
An int32 representing the maximum number of displays returned
A mutable array passed by reference, which will be filled with the displayIDs found.
An int32 representing the matching display count
Syntax:
CGError CGGetDisplaysWithPoint(CGPoint point, uint32_t maxDisplays, CGDirectDisplayID *displays, uint32_t *matchingDisplayCount);
This is fine and I can get this function working however I am quite confused as to how I should deal with the maxDisplays parameter?
As I understand it, if I set maxDisplays to 5 then if someone has 6 displays, there is a 1/6 chance that a randomly selected pixel will find no displays?
So do we just set maxDisplays to something unrealistic, like 99, and release the array afterwards? What's the point in this argument?
The point of the argument is to prevent the function from writing past the end of your array. You have to tell it the capacity of the array. Note that the displays parameter is neither a Cocoa nor Core Foundation mutable array object. It's a C-style array. It's "mutable" in the sense that it's not "const", but it's not an object that manages its own storage. You are responsible for managing that storage and must communicate its capacity to any function that is intended to store data in it (or otherwise guarantee that such function won't overrun it).
So, your question should really be how to decide on the capacity of the array. There are two basic approaches:
1) Call the function passing NULL for the displays parameter and any arbitrary value (best to use 0) for maxDisplays. As documented, when displays is NULL, maxDisplays is ignored and the function outputs via matchingDisplayCount the number of displays whose bounds contain the given point. Then, allocate an array with (at least) that many elements to use to receive the display IDs and call the function again, passing that array for displays and its capacity for maxDisplays.
2) Use an array with capacity of 32. It's not explicitly documented but it's implicit in the API that that's the maximum number of supported displays. A display ID can be converted to an OpenGL display mask using CGDisplayIDToOpenGLDisplayMask(). The type CGOpenGLDisplayMask is used to hold OpenGL display masks. It is defined as uint32_t, a 32-bit value. Therefore, there can be at most 32 active displays.
This technique is used in some Apple docs, like here, here, here, and here. That last one even makes a direct connection between the number of bits in CGOpenGLDisplayMask and the maximum number of displays.
This isn't really a question about how to do something, more just to satisfy my curiosity.
According to this, Labview stores arrays in memory as a series of int32s describing the size of each dimension followed by the actual data. So, e.g., a 2-d array of size 3x5 would be stored as
0: 3
4: 5
8: data starts here
Now suppose you have an array of int32s. How would labview tell the difference between the actual data and the array size information? In the example above, for instance, how does labview know it's a 3x5 array and not a 1-d array of length 3 and then just ignore the remaining elements? Sorry if there is something obvious that I am missing.
If you look at the LabVIEW KB Article How LabVIEW stores data in memory, you'll see that every data-type is stored with type information. For an array it first stores an I32 for each dimension, followed by the flattenend data.
The actual data-type is stored in it's type-descriptor, it consists of a list of the different contained type descriptors. For an array the minimum is two:
The array
The data in the array
The array's type descriptor is
<nn> xx40 <k> <k dims> <k elems> <element type descriptor>
where nn is the total data-packet size
xx40 is the array datatype
k is the total number of dimensions
For the contained I32 the type descriptor is:
0004 xx03 xx
0004 is the length of the type descriptor
03 is the I32 type identifier
However it's has been changed between LabVIEW 7 and 8. Relying on the type descriptor is something you shouldn't mess with yourself. Let LabVIEW handle this.
When references to data are passed around in LabVIEW internally, the data type is always passed around, too. Data is passed around as void pointers and the type is passed along with them. So any time LabVIEW sees your array, it'll also see that the type is a 2d array of int32s. (I work on the LabVIEW team at National Instruments)
I want to make a bit array or bit vector of items I have in an array so that I can create a binary fingerprint to compare to an object's fingerprint.
Here is an example:
Base fingerprint...
All "available" colors
colorsArray[blue, red, white, green, orange];
Make this into a binary array (or whatever)
This is the result = masterPrint[1,1,1,1,1];
Now I have a separate object that has the colors red and blue in it (object[red,blue])
This object's fingerprint is object's print = [1,1,0,0,0];
Compare two prints, master print [1,1,1,1,1] and object print [1,1,0,0,0];
Result is two matches 40%
How can I accomplish this? Thank you
Better option is CFMutableBitVector
CFBitVector and its derived mutable type, CFMutableBitVector, manage ordered collections of bit values, which are either 0 or 1.
CFBitVector creates static bit vectors and CFMutableBitVector creates dynamic bit vectors.
See the class reference here