Consider the following data, which can be obtained here

ListLinePlot[data, Frame -> True]

enter image description here

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]]

enter image description here

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

enter image description here

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?


1 Answer 1


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_] = 
    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:

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

enter image description here

  • $\begingroup$ What is the function fun? $\endgroup$
    – sam wolfe
    Mar 6, 2023 at 17:12
  • $\begingroup$ Sorry, this is an interpolation of the original data. I fixed it. $\endgroup$ Mar 6, 2023 at 17:17
  • $\begingroup$ 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? $\endgroup$
    – sam wolfe
    Mar 6, 2023 at 17:28
  • 2
    $\begingroup$ 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. $\endgroup$ Mar 6, 2023 at 19:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.