LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How do I Index an n-dimensional array?

Solved!
Go to solution

 

Hello,

 

If I wanted to scan a sensor around a volume in 3 dimensions, X, Y and Z (lets say 10mm by 10mm by 10mm, in 1mm steps), and take a measurement at each point, then I would write some some code that looked like this:

nested_loops.JPG

 

Does anyone have any ideas as to how I could go about programming this for N dimensions? For example, at each point of the scan above I may wish to take a measurement at four different frequencies, which would make a four dimensional scan.

 

I want to allow the user to create there own scan of N dimensions, preferably without giving the software a maximum possible number of dimensions by hard coding in a load of nested for loops as above.

 

Thanks,

 

Christian

0 Kudos
Message 1 of 9
(4,372 Views)

Sometimes it's just better to hardcode it... if that can't or shouldn't be done you can do this:

 

To do this, I normally flatten my N dimensional array into a two dimensional array, where one dimension is a run number and the other dimensions are the parameters (assuming all numeric parameters).

 

i.e.

 

run number 1 : 1Hz, 10Hz, 1Hz, 10Hz

run number 2 : 2Hz, 10Hz, 1Hz, 10Hz

run number 1 : 1Hz, 20Hz, 1Hz, 10Hz

etc...

 

And to do this we can use recursion.

 

So to run the scan, you simply have a 1 dimensional for loop that plugs in all the parameters and then collects the data. The data can be in another array where the index corresponds to the index in the parameters array.

 

My example can be sped up by preinitializing the results in array, maybe using a data value reverence, and then using the replace element in line, in cases of large result arrays. Look at the code in the example.vi and then the recursion.vi.

 

Also check the execution properties in the recursion vi.

 

Hope that helps!

Download All
0 Kudos
Message 2 of 9
(4,353 Views)

My first thought is that you can't write a VI to process an arbitrary array because the controls and indicators need to have a defined data type.  Perhaps you can rethink your data structure to make it more flexible.  Maybe a 1D array of cluster with X,Y,Z,measurement type, measurement.

 

Example_VI_FP.png

Jim
You're entirely bonkers. But I'll tell you a secret. All the best people are. ~ Alice
For he does not know what will happen; So who can tell him when it will occur? Eccl. 8:7

0 Kudos
Message 3 of 9
(4,334 Views)
Solution
Accepted by topic author crnbaker

Given the number of times I have mentioned this recently I will nominate 'Cartesian Product' for the most common operation performed without knowing its name.  I use it a lot when taking data because it is common to scan over many different paramters.

 

Check out for instance this post:

http://forums.ni.com/t5/LabVIEW/3-loops-incrementing/m-p/1439422#M552998

 

The lower snippet is a subVI I use to find the indices for a given iteration with a given number of elements in each list.  I usually build a 2D array which holds the individual values for the scan parameters (assuming they are all the same data type).  Each row contains the points to be scanned for one parameter.  A separate 1D array holds the number of points in each scan  which is used in the subVI to find the proper indices.  The 2D array will be padded if the scans have different lengths, but these points will not be indexed so no need to worry about them.  Once I have the found the indices for a given iteration, I simply pick those columns out as I iterate over the rows of the 2D array.  (I'll try to find an example to post).

 

You may argue that the padded 2D array is not the most efficient, but when you consider that each point is a separate measurement, you will probably run out of patience in the lab long before you run out of memory in the array.

Message 4 of 9
(4,326 Views)

Here is a quick example:

 

ScanWithCartesianProduct.png

 

Download the attached SubVI first if you try to use the snippet, mostly intended as a visual aid.

Message 5 of 9
(4,315 Views)

Thanks everyone for your replies. I wanted to avoid storing dimension values in the format:

 

Dimension 1: 1 1 1 1 2 2 2 2

Dimension 2: 1 1 2 2 1 1 2 2

Dimension 3: 1 2 1 2 1 2 1 2

rather than simply:

 

Dimension 1: 1 2

Dimension 2: 1 2

Dimension 3: 1 2

 

because I'm potentially working with large size dimensions (and also this software is using an engine that is used for 1 to 3 dimesional applications elsewhere, and already has an FGV for storing and indexing dimension values in this manner). But luckily I've come up with a way to index through N dimensions stored in the second format above. It does it using a for loop which goes through each of the N dimensions, incrementing it to its next value only if the dimension above it has reached its last point, and resetting its position only if the dimension itself has reached its last point. Since the final dimension (dimenson N) has no dimension above it, it will always increment to it's next value (unless it is already at its last value, in which case it will reset to its first). I'll try to post some sort of generalised version of the VI when I get into the lab tomorrow.

 

Thanks again, I think Cartesian Product is going to come in useful elsewhere anyway.

 

Christian.

0 Kudos
Message 6 of 9
(4,278 Views)

For the record, the example I posted does store the values in the second format you describe (with zero padding if the dimensions are of unequal lengths).  The subVI uses math instead of an odometer approach to index the arrays is the only difference with yours.

Message 7 of 9
(4,264 Views)

I see, I got the wrong idea and thought that the cartesian product VI converted the data from one format to the other (and therefore still used up as much memory). I haven't had a proper look at your example yet as I got my (probably less efficient) code working before you posted. Will check it out later and probably implement it, since it's probably much more easily documentable than mine if not more effiecent.

 

Thanks,

Christian.

0 Kudos
Message 8 of 9
(4,251 Views)

Yes, your method is exactly what I need. I really wish I'd waited a bit longer before trying to solve it myself now.

0 Kudos
Message 9 of 9
(4,238 Views)