Creating an XY graph in labview which would store previous values - arrays

Link to the vi: see xy_plot_problem_withcase
In the attached vi (xy_plot_problem_updated.vi) I am able to get 3 individual values x, y and z in an array, element 0 being x, element 1 being y and element 2 being z.
These three values come for every iteration of the outer while loop. I would like to store all generated x values into one array and same with y and z so I can use the final arrays to generate one final graph.
The outer while loop runs 30 times and I would like to record the 30 different values generated at index 0 in a separate array. I tried using a shift register, build array etc but its just replacing element 1 (of the new array) with the newest element generated (They are not getting accumulated).
I have encountered this problem while designing for a system which records 3 different readings for every 5 degree increase in temperature. I want to be able to plot the acquired values against the current temperature. Hence, the outer while loop is actually a case statement which gets triggered every time the temperature goes up by 5 degrees.
I have also attached the main VI too alongside (final.vi).
Any help appreciated!!
Thanks in advance!!!

In your final.vi you have a while loop, you should move everything in the case into the while loop. My advise for you would be to look at the LabVIEW fundamentals on data flow and on shift registers.
In your code you were resetting the shift register in the while loop every iteration.
Try to clean up your code and use the executing highlighting function (the light bulb).

Related

How to write to arrays using loops in PureData?

I'm writing random numbers in an array using loops in Pure Data. For some reason in loop one Pure Data starts writing from index 1 instead of 0 and finishes on index 0 after the loop, this is not what I want. In loop two I found a solution using an extra [f] and [bang], Pure Data does the expected, starting from index 0. In both cases console prints the data in the same order (numbers are random, the order is the same), just the graph, reflecting the array, is different.
Does anyone know why the first case fails and the second works? My guess is that its related to the flow of data into the left and right inlets of [tabwrite].
loop one
Code
Console
Graph (1.151 is on index 1 instead of index 0)
loop two
Code
Console
Graph (1.742 is correct on index 0)
Message order.
You have a fanning output on the [f] object. Use a trigger [t b f] (short for [trigger bang float]) to make the order explicit. If you see an atom with multiple connections on one output, that's a red flag! Always use trigger objects, because without them the order in which you made the connections will be the order in which the messages will be sent. That's not visible in the patch, so it should be avoided!
Read more about message order in the documentation of Pd
There is another issue in your patch. Consider this case: If NotasPor0it is 8 and the counter is at 6, then NotasPor0it is changed to 4, the select object [sel] will never trigger the reset function of the counter idiom and continue to count... To avoid this issue, you could use a 'larger as' [>] symbol, or solve it with modulo (%) as seen in the screenshot.

Excel function to filter an array where a step change has occurred

I am trying to filter an array to only include those values that are not within a set distance of a change in that array.
Here's my example:
The input array increases monotonically in steps. I want to zero out any of the input values from N rows above to N rows below any point where the value changes. Cell $B$2 holds this "window" value.
For example, cell A9 (value 11) is different from cell A8 (value 5), so I want to zero out values that come from any cells from A7 to A11 inclusive. That is from -N to +N relative the cell where the change occurs, where N=2.
I can achieve the required output with non-array functions, using intermediate calculation columns, but since I am processing a large number of columns it would save greatly on spreadsheet real-estate if I could construct a single array formula that operates on the range A4:A25, and uses cell B1 for the size of N. I am using the current Excel Beta, so I have access to LET and LAMBDA if needed.
I have tried various combinations, using SEQUENCE, but I run into the issue that LET (or indeed any array functions) seems to fail if they contain two SEQUENCE statements.
I am continuing to work on this, but if anyone wants to have a try, I would be most grateful!
UPDATE: This formula does the trick, but needs to be copied down:
=A4*IF(AVERAGE(OFFSET(A4,-($B$1+1),0,2*($B$1+1),1))<>A4,0,1)
So, while the suggestion of #JvdV was not exactly what I was after, a hat-tip to them for the idea of offsetting the whole column up and down, which led to this:
=LET(input,A4:A25,up,OFFSET(input,-1*(B1+1),0),down,OFFSET(input,B1,0),input*IF(IFERROR(up*down,0)>0,IF(up=down,1,0),1))

Add Random Number to List only if it's different than others

I'm designing a game in Scratch. The game is suppose to have a Spaceship travel through space, avoiding asteroids. These asteroids start at a fixed X position on the right side of the screen and go to the left, horizontally until they hit a fixed X position and they'll disappear. The asteroids will start in groups between 2-6 (it's a random number generated), and each set is about 1 second apart.
Assuming the game throws out up to 6 asteroids at once, I want to make sure each asteroid is distant from the next. I tried using two variables and comparing the distance, but this did not work. I can put the group of asteroids Y spawning position into a list. So say for instance in my list, I have:
0, 100, 5, 30, -20
As you can see, there are two items in that list that are close together. What I'm trying to do, is prevent this, so the third item would be something else, like -50, for instance, and then if a six item is generated, ensure it's also distant.
Can someone pseudocode how to achieve something like this? It doesn't matter what programming language it's in, I can probably translate the general idea into Scratch.
There is a way to do this without a trial-and-error loop.
Instead of picking random positions, pick random distances, then scale them to fit the screen.
Roughly, the approach is as follows.
The lists below represent the distances between neighboring asteroids (ordered by Y coordinate), as well as distances between the outermost asteroids and the edges of the screen.
For example, if a group contains 6 asteroids, then you need lists of 7 elements each.
Create a list L1 of minimal distances. Obviously, these are all fixed values.
Create a list L2 of random numbers. Take them from some arbitrary, fixed range with a positive lower bound, e.g. [1..100].
Calculate the total 'slack' = height of screen minus sum(L1).
Calculate a multiplication factor = slack divided by sum(L2).
Multiply every element of L2 with the multiplication factor.
Add every value from L1 to the value in L2 at the same index.
L2 now contains a list of distances that:
obey the minimal distances specified in L1
together equal the height of the screen
The final step is to position every asteroid relative to its neightbor, based on the distances in L2.
Note: if step 3 gives a negative number, then obviously there is not enough room on screen for all asteroids. What's worse, a naive 'trial-and-error' algorithm would then result in an infinite loop. The solution is of course to fix your parameters; you cannot fit 6 asteroids in 360 pixels with a minimal distance of 100.
To do this, you need to do through each previous entry in the array, compare that value to the new value, and if any element is too close change the value. This process needs to repeat until a suitable number is found. If this number is less then some minimum distance, then a variable tooClose is set to yes and the value will be reset. At the begining of the loop tooClose is set to yes so that at least one random number will be generated. Then, at the beginning of the loop, the value is randomized, and tooClose is set to no, then, I loop through all the previous entries with the value i, comparing each element and setting tooClose to yes if it is too close. The comparison between numbers is done with a subtraction, followed by an absolute value, which will ensure the result is positive, giving the difference between the two numbers as a positive value.
Here is a screenshot of the code:
And here is the project:
https://scratch.mit.edu/projects/408196031/

Storing and replacing values in array continuously

I'm trying to read amplitude from a waveform and shine a green, yellow or red light depending on the amplitude of the signal. I'm fairly new to labVIEW and couldnt get my idea that wouldve worked with any other programming language I know to work. What I'm trying to do is take the value of the signal and for everytime it updates I'll store the value of the amplitude into an index of a large array. With each measurement being stored in the n+1 index of the array.
After a certain amount of data points I want to start over and replace values in the array (I use the formula node with the modulus for this). By keeping a finite amount of indexes to check for max value I restrict my amplitude check to a certain time period.
However my problem is that whenever I use the replace array subset to insert a new value into index n, all the other index points get erased. Rendering it pretty much useless. I was thinking its the Initialize array causing problems but I just cant seem to wrap my head around what to do here.
I tried creating just basic arrays in the front panel, but those either are control or indicator arrays and can't seem to be both written and read from, its either control (read but not write) or indicate(write but not read)?. Maybe its just not possible to do what I had in mind in an eloquent way in LabVIEW. If its not possible to do this with arrays in LabVIEW I will look for a different way to do it.
I'm pretty sure I got most of the rest of the code down except for an unfinished part here and there. Its just my issue with the arrays not working as I want them too.
I expected the array to retain its previously inputted data for index n-1 when index n is inputted. And only to be replaced once the index has come back to that specific point.
Instead its like a new array is initialized every time a new index is input.
download link for the VI
What you want to do:
Transport the content of the modified array into the next iteration of the WHILE loop.
What happens:
On each iteration, the content of the array is the same. It is the content of the initial array you created outside.
To solve this, right-click the orange square on the left border of the loop, and make it a "shift register". The symbol changes, and a similar symbol appears on the right border. Now, wire the modified array to the symbol on the right. What flows out into that symbol on the right, comes in from the left symbol on the next iteration.
Edit:
I have optimized your code a little. There is a modulo function, and an IF clause can handle ranges. ..3 means "values lower or equal 3". The next case is "Default", the next "7..". Unfortunately, this only works for integers. Otherwise, one would use nested IF clauses with the < comparator or similar.

replacing r variables with multiple or different values

I have a dataframe (raw) that can have one variable (iv1) with NA's in it. I want to replace the NA with different random values from the distribution of existing scores within (iv1), not one single value. the sample size (n) can be anything - 100 to 1000.
I save the distribution to a new data frame (dbmi) because I want to keep raw and dbmi separate, and calculate the mean and SD of the existing values of iv1 within dbmi. The following code works but replaces all of the NA's with just one value. I think I need to set up a for loop? Some kind of loop that finds the next occurrence of an NA and runs the new 'rnorm' value and sticks it in and goes to the next and does it again etc etc but I cant figure out how to do that. Any help?
dbmi<-raw
attach(dbmi)
rawmean<-mean(dbmi$iv1,na.rm=TRUE)
rawsd<-sd(dbmi$iv1,na.rm=TRUE)
for (i in 1:n){
dbmi$iv1[is.na(dbmi$iv1)]<-rnorm(1,rawmean,rawsd)
}
I actually solved my own problem. I set up the variable locations [i] that had the NA's into a variable called 'pull', then I just created a new stream into a variable called 'new' I used this code to substitute.
dbmi<-raw
attach(dbmi)
rawmean<-mean(dbmi$iv1,na.rm=TRUE)
rawsd<-sd(dbmi$iv1,na.rm=TRUE)
new<-rnorm(num,rawmean,rawsd)
for (i in 1:n){
dbmi$iv1[pull]<-new
}

Resources