Hi Elias
This is almost certainly really badly coded :)
I have a large spectral spread in which I’m using the differential between slices to look for ‘peaks’ and then finding the ‘width’ of the falloff around each peak. Not sure if it’ll make much sense!
- region usings
using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Collections.Generic;
using VVVV.PluginInterfaces.V1;
using VVVV.PluginInterfaces.V2;
using VVVV.Utils.VColor;
using VVVV.Utils.VMath;
using VVVV.Core.Logging;
- endregion usings
namespace VVVV.Nodes
{
#region PluginInfo
[PluginInfo(Name = "led_val_to_frame_data", Category = "Value", Help = "Basic template with one value in/out", Tags = "")](PluginInfo(Name = "led_val_to_frame_data", Category = "Value", Help = "Basic template with one value in/out", Tags = ""))
#endregion PluginInfo
public class Valueled_val_to_frame_dataNode : IPluginEvaluate
{
#region fields & pins
[Input("LED spread in", DefaultValue = 1.0)](Input("LED spread in", DefaultValue = 1.0))
public ISpread<double> FInput;
[Input("width to frame number multiplier", DefaultValue = 1.0)](Input("width to frame number multiplier", DefaultValue = 1.0))
public ISpread<double> widthFrameMult;
[Input("num of leds per arc", DefaultValue = 1, IsSingle = true)](Input("num of leds per arc", DefaultValue = 1, IsSingle = true))
public ISpread<int> ledCount;
[Input("peak minimum threshold", DefaultValue = 0, IsSingle = true)](Input("peak minimum threshold", DefaultValue = 0, IsSingle = true))
public ISpread<double> peakMin;
[Input("find highest peaks", DefaultValue = 0, IsSingle = true)](Input("find highest peaks", DefaultValue = 0, IsSingle = true))
public ISpread<bool> sortPeaks;
[Output("Peaks Heights")](Output("Peaks Heights"))
public ISpread<double> justPeaks;
[Output("Width on side L")](Output("Width on side L"))
public ISpread<double> justWidthsOutL;
[Output("Width on side R")](Output("Width on side R"))
public ISpread<double> justWidthsOutR;
[Output("Peak Centre")](Output("Peak Centre"))
public ISpread<double> peakCentre;
//[Output("Dip Height")](Output("Dip Height"))
//public ISpread<double> dipHeight;
[Output("Peaks count per Arc")](Output("Peaks count per Arc"))
public ISpread<int> peakCount;
[Import()](Import())
public ILogger FLogger;
#endregion fields & pins
//called when data for any output pin is requested
public int mapWidth(double width, double factor)
{
return (int)Math.Max(Math.Min(width * factor, 1023),0);
}
// function to initialise array with values
static void InitIntArray(int[]() arr)
{
for (int i = 0; i < arr.Length; i++)
{
arr[i](i) = -1;
}
}
static void InitDoubleArray(double[]() arr)
{
for (int i = 0; i < arr.Length; i++)
{
arr[i](i) = -1;
}
}
// oject to hold accumulated output data. Reset each arc iter
class Peak
{
public Peak(double height, double centre, int widthL, int widthR)
{
Height = height;
Centre = centre;
WidthL = widthL;
WidthR = widthR;
}
public double Height { get; set; }
public double Centre { get; set; }
public double WidthL { get; set; }
public double WidthR { get; set; }
}
public void Evaluate(int SpreadMax)
{
int diffCount = ledCount[0](0)-1;
int arcCount = SpreadMax/ledCount[0](0);
int outputSliceCount = SpreadMax - arcCount;
justPeaks.SliceCount = arcCount * 3; //
justWidthsOutL.SliceCount = arcCount * 3; //
justWidthsOutR.SliceCount = arcCount * 3; //
peakCentre.SliceCount = arcCount * 3; //
peakCount.SliceCount = arcCount;
//double[]() diffArray = new double[outputSliceCount](outputSliceCount);
//double[]() dipHeight = new double[SpreadMax](SpreadMax);
double[]() diffArray = new double[outputSliceCount](outputSliceCount);
double[]() dipHeight = new double[SpreadMax+arcCount](SpreadMax+arcCount);
List<Peak> peaks = new List<Peak>();
bool foundPeak = false;
for (int i = 0; i<arcCount; i++) //loop through arcs
{
int j=0; // index of current led
peaks.Add(new Peak(0, 0, 0, 0)); // add 3 peaks so we don't need to check count before sorting later
peaks.Add(new Peak(0, 0, 0, 0));
peaks.Add(new Peak(0, 0, 0, 0));
for (j=0; j<diffCount; j++) //loop through leds in arc
{
int IndexIn = i*ledCount[0](0) + j;
int IndexOut = i*diffCount + j;
dipHeight[IndexOut](IndexOut) = 0;
diffArray[IndexOut](IndexOut) = FInput[IndexIn+1](IndexIn+1) - FInput[IndexIn](IndexIn);
// id the first in arc
if(j == 0)
{
if(diffArray[IndexOut](IndexOut) < 0)
{
foundPeak = true;
peaks.Add(new Peak(FInput[IndexIn](IndexIn), j*0.00523560, 0, 0)); //0.00523560 is to normalise peak centre slice index (1/192)
}
}
//is this the last in an arc
else if(j == diffCount-1)
{
if(diffArray[| (diffArray[IndexOut](IndexOut](| (diffArray[IndexOut](IndexOut) > 0 ) < 0 && diffArray[IndexOut-1](IndexOut-1) >0) )
{
foundPeak = true;
peaks.Add(new Peak(FInput[IndexIn](IndexIn), j*0.00523560, 0, 0));
}
}
//then it's the rest
else
{
if(diffArray[IndexOut-1](IndexOut-1) >= 0 && diffArray[IndexOut](IndexOut) < 0) //diff[i-1](i-1) is being taken from the last frame so might cause issues
{
foundPeak = true;
peaks.Add(new Peak(FInput[IndexIn](IndexIn), j*0.00523560, 0, 0));
}
// find dips (troughs)
dipHeight[i](i) = 0;
if(diffArray[IndexOut-1](IndexOut-1) <= 0 && diffArray[IndexOut](IndexOut) > 0) //diff[i-1](i-1) is being taken from the last frame so might cause issues
{
dipHeight[IndexOut](IndexOut) = FInput[IndexIn](IndexIn);
}
}
//find widths
if(foundPeak)
{
//double currentVal = peakHeight[IndexOut](IndexOut);
double currentHeight = peaks.Last().Height;
double changingHeight = currentHeight;
double previousHeight = currentHeight;
int k = 0;
// find index of half decay point on RIGHT side
while( k<192 )
{
if(dipHeight[IndexOut+k](IndexOut+k) > 0.01 || IndexOut+k == diffCount-1)
{
double temp = changingHeight/(currentHeight/2);
temp = Math.Pow(temp, 1.75);
temp *=k;
k = (int)temp;
break;
}
previousHeight = changingHeight;
changingHeight = FInput[IndexIn+k+1](IndexIn+k+1);
if(changingHeight < (currentHeight/2))
{
break;
}
k++;
}
double subSampleShift = (previousHeight-(currentHeight/2)) / (previousHeight-changingHeight);
peaks.Last().WidthR = mapWidth(k+subSampleShift, widthFrameMult[i](i));
changingHeight = currentHeight;
k = 0;
// find index of half decay point on LEFT side
while( k<192 )
{
if(dipHeight[IndexOut+k](IndexOut+k) > 0.01 || IndexOut+k == 0)
{
double temp = changingHeight/(currentHeight/2);
temp = Math.Pow(temp, 1.75);
temp *= k;
k = (int)temp;
break;
}
previousHeight = changingHeight;
changingHeight = FInput[IndexIn+k-1](IndexIn+k-1);
if( changingHeight < (currentHeight/2) )
{
break;
}
k--;
}
subSampleShift = (previousHeight-(currentHeight/2)) / (previousHeight-changingHeight);
peaks.Last().WidthL = mapWidth(-(k-subSampleShift), widthFrameMult[i](i));
}
foundPeak = false;
}
int listSize = peaks.Count;
peakCount[i](i) = listSize - 3; //take off the 3 dummies we added
if(sortPeaks[0](0))
{
peaks = peaks.OrderBy(x => x.Height).ToList(); //sort by height to find biggest peaks
}
for (int l=1; l<4; l++)
{
int offset = 3 * i;
justPeaks[l+offset](l+offset) = peaks[listSize-l](listSize-l).Height;
peakCentre[l+offset](l+offset) = peaks[listSize-l](listSize-l).Centre;
justWidthsOutL[l+offset](l+offset) = peaks[listSize-l](listSize-l).WidthL;
justWidthsOutR[l+offset](l+offset) = peaks[listSize-l](listSize-l).WidthR;
}
peaks.Clear(); // clear list (so list calcs only happen per arc)
}
}
}
}