Extract neighbourhood of first maximum in pulse train

I have a dataset of an evenly spaced pulse train, formatted as $(t, a(t))$ where of course $t$ is time and $a$ is the amplitude.

I would like to extract, from this dataset, the first (or, in general, the $n$-th) pulse and its neighbourhood, to fit it with a Gaussian/Lorentzian.

• I could do it manually, ListPlot-ing the whole dataset and roughly choosing the subset I need;
• I could "brute force" it and write a long set of rules to achieve my goal.

Is there a neater way to do it?

EDIT:

As requested, here's my code so far. After importing the data, I define a function xPulse which, assuming the pulse is not right at the beginning of the file, takes $t$ elements of the list, where $t$ is the period up to a multiplying constant, defined at the beginning. This way I'm sure that (if the pulse is not right at the start of the dataset) I only get the $n$-th pulse:

xPulse[x_]:= Module[{y = t*(x - 1) + 1}, data[[y ;; y + t, 2]]]


I then fit the result

fit = Normal@NonlinearModelFit[xPulse[1], {Exp[-((x - s)^2/(2*m^2))] + n, {s > 0, m > 0}}, {s, m, n}, x, MaxIterations -> 5000]


This is what I got so far, but the approach assumes the knowledge in advance of the repetition rate (whose measurement should become a part of the notebook in the future), as well as not working correctly if the first point is part of a pulse nor taking account of the time scale.

EDIT2:

Here's a plot of the pulse train:

• Can you post an example of what exactly you mean by neighborhood. Also, please post the code you have tried. Jun 26, 2017 at 13:50
• Are the pulses equally spaced? Please share some sample data, in addition to what @AnjanKumar mentioned as well. Jun 26, 2017 at 14:23
• Added what I have so far. I didn't add sample data as just one pulse takes up to 1000 points. By neighbourhood I simply mean a subset of $t$ elements containing one pulse only, preferably positioned in the centre of the subset
– Enzo
Jun 26, 2017 at 16:22
• Can you display a plot of an example pulse train? The key is to discriminate pulse from not-pulse. After that, the problem is easy. Jun 26, 2017 at 16:34
• @MikeY done. The discrimination is pretty evident.
– Enzo
Jun 26, 2017 at 16:42

some made up data similar to yours:

pulse := 20 Table[
Sin[2 Pi x/50] + RandomVariate[NormalDistribution[0, .1]], {x, 0,
50}]
data = Table[
Sin[x] + RandomVariate[NormalDistribution[0, .1]], {x, 1000}] +
Total@Table[SparseArray[ (Range[i + #, 50 + i + #] &@
RandomInteger[20]) -> pulse, {1000}], {i, 1, 950, 150}];
ListPlot[data, Joined -> True, PlotRange -> All]


find the lead edge of each pulse by threshold detection:

threshold = 10;
pulses = First /@
SequencePosition[data, {x_ /; x < threshold, y_ /; y >= threshold}]


{5, 167, 322, 475, 610, 755, 905}

look at neighborhood of each pulse.

ListPlot[data[[Max[1, # - 20] ;; Min[# + 80, Length@data]]],
Joined -> True, PlotRange -> All] & /@ pulses


• Thanks, this is a very neat approach. What if I wanted to have the peak (in my case) or the centre (in yours) of the pulse in the centre of the subset, so I have the same number of points both left and right of my pulse? I'm assuming I'll have to change those $20$ and $80$ values in the ListPlot, where you are selecting the interval. But hardcoding values can be counterproductive, as a pulse can be wider (hence requiring more points) or narrower.
– Enzo
Jun 27, 2017 at 9:37
• I found the function FindPeaks which, however, doesn't give the same results as your approach (in fact, FindPeaks gives 300 more elements that expected, as your code confirms. Is FindPeaks[data,0,0,threshold] wrong? If I set a blurring parameter it gives either a 1-element array, with a low blurring parameter, or random values increasing the blurring...
– Enzo
Jun 27, 2017 at 10:44
• Your original data looks so clean I don't see a need to try to do something more complicated than simple threshold detection. You might find each peak, then calculated the midpoints between them and call that the neighborhood without hard coding anything. Jun 27, 2017 at 18:38
• I found a way to do that (simply calculating the mean value of the position difference between consecutive peaks, so I have the period of the train expressed in points number). I'll just use that to make sure the peak is centred. The other issue is that the time axis always starts from 0, instead of the actual time. But I guess that's easy to work around. Thank you very much. I should look into a way to fit the entire train without extracting every single peak, maybe, and a way to calculate the pulse width, but that's material for another question, I assume.
– Enzo
Jun 28, 2017 at 10:20