Rate in a graph

Hello,
i have made a programm that loads csv files and make plots in processing IDE…I would like to know how can i calculate the rate of the results with code in java for processing i3.t The plots are sinusoidal so i want to find how many times the maximum values show up.

Can you elaborate more on your code and the data you have so we can get a better idea of what you’re trying to do?

Just to leave you with something useful, you can use the following snippet to calculate occurrences in a list. If you can find the max of your values, you can plug it in instead:

import java.util.*;

void setup() {
  size(200, 200);
  
  ArrayList<Integer> sampleList = new ArrayList<Integer>();
  sampleList.add(1);
  sampleList.add(1);
  sampleList.add(4);
  sampleList.add(1);
  
  println(Collections.frequency(sampleList, 1));
}
1 Like

Finding the local minima and maxima of a curve can be quite easy. If you have an array of values, and you want to find a maximum, you can iterate over the array and subtract the current value from the previous value in the array. Keep track of the result. If the result in the next iteration has a different sign than the previous result, then the curve “changed direction” and you’re at an extremum.

Since you have physicist in your name, you could relate this to the derivative of the curve. A known property of the derivative is that it changes sign when the function goes through an extremum. The derivative is defined as df/dx = lim(h -> 0) (f(x)-f(x+h))/h. Here, h cannot go to zero as it is limited by the sample size of the curve. But that’s fine as we’re not interested in the actual value of the derivative, but only when it changes sign. So it is sufficient to calculate f(x)-f(x+h), where f(x) is the previous value (of the iteration) in the array and f(x+h) the current.

Major drawback: noise. If you have a slowly varying signal, and a noise component with a significant amplitude and frequency higher than the signal, the noise will induce local peaks. Therefore, you always have to verify if the result makes sense. If necessary you can introduce a smoothing algorithm.

If you need more rigorous methods, you could try curve fitting algorithms or Fourier transform algorithms, but those are outside my area of expertise.

2 Likes

Can you provide me an example code that to this:

Finding the local minima and maxima of a curve can be quite easy. If you have an array of values, and you want to find a maximum, you can iterate over the array and subtract the current value from the previous value in the array. Keep track of the result. If the result in the next iteration has a different sign than the previous result, then the curve “changed direction” and you’re at an extremum.

Create a sample array and then literally translate each phrase of the description from @colouredmirrorball into a line of code – a for loop, subtraction, a variable that stores the previous value, and an if statement. The results are as described.

//                                  *                 *            *
float[] myArray = new float[]{0, 1, 2, 1, 0, -1, -2, -3, -1, 1, 3, 5, 3};
float lastChange = 0;

// you can iterate over the array
for(int i=1; i<myArray.length; i++){
  // and subtract the current value from the previous value in the array.
  float newChange = myArray[i] - myArray[i-1];
  // If the result in the next iteration has a different sign than the previous result,
  if(newChange * lastChange < 0){
    // then the curve “changed direction” and you’re at an extremum.
    println(i-1, ":", myArray[i-1], "is an extremum");
  }
  // Keep track of the result.
  lastChange = newChange;
}

// output:
//  2 :  2.0 is an extremum
//  7 : -3.0 is an extremum
// 11 :  5.0 is an extremum
1 Like

Slightly modified version of jeremydouglass solution.

for(int i=1; i<myArray.length-1; i++){
  if( (myArray[i] - myArray[i-1]) * (myArray[i] - myArray[i+1]) > 0){
    println(i, ":", myArray[i], "is an extremum");
  }
}

// output:
//  2 :  2.0 is an extremum
//  7 : -3.0 is an extremum
// 11 :  5.0 is an extremum

To give a better answer we need to know more about the data. Perhaps you can shows us some sample data. If you want to calculate rates of change then we need to know the interval between data values (if it is constant) and how the interval compares to the period of the sinusoidal source.

1 Like

@jeremydouglass @quark your code finds many max values and i want just the only one max… I guess i have to check if i>i+1 and in the same time must i>i-1.

That was not clear from the original question!

float[] myArray = new float[]{0, 1, 2, 1, 0, -1, -2, -3, -1, 1, 3, 5, 3};
float max = myArray[0];
int maxPos = 0;

for (int i=1; i < myArray.length; i++) {
  if ( myArray[i] > max) {
    max = myArray[i];
    maxPos = i;
  }
}
println("Found max value (" + myArray[maxPos] + ") at position " + maxPos);

Output:
Found max value (5.0) at position 11

Thank you @quark , this really works. But what happens if i want to load a csv file with two values (x,y)? First i have to load y values into an array, second i have to find the max of the array and finally i want to find which is the corresponding x that y is max.

Have you written the code to read the data from the CSV file

it is simple:

void setup() {
Table table=loadTable(“data.csv”, “header”);
table.setColumnType(“x”, Table.FLOAT);
table.setColumnType(“y”, Table.FLOAT);
for (int row = 0; row < table.getRowCount(); row++) {
float y = table.getFloat(row, “y”);
float x= table.getFloat(row, “x”);
}
}

That’s funny, before you said many maximum values.

If you just want the max, Processing has a built-in for that: max().

float[] myArray = new float[]{0, 1, 2, 1, 0, -1, -2, -3, -1, 1, 2, 1, 2};
float myMax = max(myArray);
println(myMax);

To count identical occurrences of one max value (not multiple local max values), you can also do the counting while finding your own max with a single loop. Expanded from @quark’s code above:

float[] myArray = new float[]{0, 1, 2, 1, 0, -1, -2, -3, -1, 1, 2, 0, 2};
float max = myArray[0];
int maxPos = 0;
int maxCount = 0;

for (int i=1; i < myArray.length; i++) {
  if ( myArray[i] > max) {
    max = myArray[i];
    maxPos = i;
    maxCount = 1;
  } else if (myArray[i] == max) {
    maxCount++;
  }
}
println("Found max value (" + myArray[maxPos] + ") starting at position " + maxPos + " and occuring x" + maxCount);
void setup() {
  Table table=loadTable("data.csv", "header");
  table.setColumnType("x", Table.FLOAT);
  table.setColumnType("y", Table.FLOAT);
  float maxY = table.getFloat(0, "y");
  float posX= table.getFloat(0, "x");
  for (int row = 1; row < table.getRowCount(); row++) {
    float y = table.getFloat(row, "y");
    float x= table.getFloat(row, "x");
    if (y > maxY) {
      maxY = y;
      posX = x;
    }
  }
  println("The maximum value of y (" + maxY + ") @ x = " + posX);
}
2 Likes

Thank so much @quark :smile::sweat_smile::wink: , that was what i mean… I was just stuck…

If you read back over this discussion you will also realise that you would have got the answer more quickly and with less head-scratching from forum members if you had phrased the question more accurately and gave more information about the data and how it was stored.

Glad to have helped. :smile:

2 Likes

thanks to @quark ++
you got the same answer again, you did not trust me on:

i know but it doesn’t matter because everything was useful for me for different reasons. :smile::thinking::blush:

I did trusted you but for my project your way mas not convenient for me. You really helped me in other ways, for example with the filtering and the detection of peaks…Thank you so much :wink::smile: :