# How to perturb data along a midline?

Consider the following data, which can be obtained here

ListLinePlot[data, Frame -> True]


I want to perturb the previous data around a defined midline, which can be, for example, either points of inflection or the midpoint between two consecutive local minima or maxima, as sketched

sig = Sign[data[[2]] - data[[1]]]; pts = {1};
For[i = 1, i < Length@data, i++,
If[Sign[data[[i + 1]] - data[[i]]] != sig,
sig = -sig; pts = Append[pts, i]]];
AppendTo[pts, 2000];
ptsm = Floor@
Table[Mean[{pts[[i]], pts[[i + 1]]}], {i, Length@pts - 1}];
Show[ListLinePlot[data, Frame -> True],
ListPlot[Transpose[{ptsm, data[[ptsm]]}], PlotStyle -> Red]]


My goal is to, given a parameter scale, rescale the previous data around the points in red, to get something like

where the local minimisers and maximisers should remain the same, and the perturbation level should scale with the local concavity or convexity. Is there any easy way of achieving this?

For an example, I will take the following positions of inflexion points:

inf={161, 505, 952, 1107, 1216, 1358, 1529, 1723, 1867, 1898};


Then we define a linear interpolation between these points (plus the start and end point):

int[x_] =
Interpolation[
Sort[{#, data[[#]]} & /@ ({1, inf, Length[data]} // Flatten)],
InterpolationOrder -> 1][x];


and I define a function of the original data:

fun[x_] = Interpolation[data][x];


Now we multiply the difference between the linear interpolation and the original curve by some perturbation factor:

Manipulate[
Plot[{fun[x] - lam (int[x] - fun[x]), fun[x]}, {x, 1, 2000},
PlotRange -> {0, 500}]
, {lam, 0, 2}]


• What is the function fun? Mar 6, 2023 at 17:12
• Sorry, this is an interpolation of the original data. I fixed it. Mar 6, 2023 at 17:17
• Wonderful answer. Just wondering, it seems that such a "perturbation" scales with the values on the y-axis, as one would expect. Could we somehow normalize the factor lam to scale only based on local behavior? I am particularly concerned about the huge amplification between ~600 and ~800, compared to other regions. Naturally, this is a bit vague, and you already pretty much answered my question, but, any thoughts? Mar 6, 2023 at 17:28
• I used InterpolationOrder->1. You may play with this, e.g. using InterpolationOrder->6. It does not actual scale with the height , but with the difference between a linear and a curved segment. Another approach would be to add a scaled version of "x(1-x))" to the curve segments. Mar 6, 2023 at 19:24