# Fitting a free parameter by matching a an array with another array

I have the following problem that I can't figure out how to solve. I have two measured signals, (data1 and data1), and their measured sum (datasummeasured). I have a theoretical description of how the two signals should be summed, but the equation has one free parameter that I need to determine by matching the measured summ with the calculated summ from the two measured single signals.

I can't use any of the regular fitting routines, because the equation I have is not used to describe the function shape of the data, but how two separate sets of data can be summed up to generate a third. In the example below I would like to fit the calculated sum data to the measured sum data by changing the parameter called "orthogonality".

SignalSum[S1_ , S2_, Ortogonality_] :=
N[Sqrt[(S1 ^2 + S2 ^2) + 2 S1 S2 Cos[Ortogonality]]];
data1 = {{1., 0.63}, {0.5, 0.85}, {0., 1.02}, {-0.5, 0.97}, {-1., 0.87}, {-1.5, 0.77}, {-2., 0.75}, {-2.5, 0.72}, {-3., 0.66}, {-3.5, 0.48}, {-4., 0.36}};
data2 = {{1., 0.61}, {0.5, 0.79}, {0., 1.02}, {-0.5, 1.09}, {-1., 1.07}, {-1.5, 0.93}, {-2., 0.77}, {-2.5, 0.63}, {-3., 0.47}, {-3.5, 0.38}, {-4., 0.27}};

datasummeasured = {{1., 0.72}, {0.5, 0.93}, {0., 1.15}, {-0.5, 1.17}, {-1., 1.15}, {-1.5, 1.02}, {-2., 0.9}, {-2.5, 0.83}, {-3., 0.74}, {-3.5, 0.56}, {-4., 0.41}};

ortogonality = 1.5; (*I would like to make this parameter variable and obtain it by matching the measured sum data with the calculated sum data*)
signalsumm =
Table[{data1[[i, 1]],
SignalSum[data1[[i, 2]], data2[[i, 2]], ortogonality]}, {i, 1,
Length[data1]}];

ListPlot[{data1, data2, datasummeasured}, PlotRange -> All,
Joined -> False,
PlotLegends -> {"Singal 1", "Singal 2", "Measured summ"},
Frame -> True,  PlotLabel -> "Measured signals"]

ListPlot[{datasummeasured, signalsumm}, PlotRange -> All,
Joined -> False, PlotLegends -> {"Measured summ", "Calculated Sum"},
Frame -> True,  PlotLabel -> "Measured vs. Calculated sum"]

$$$$


For convenience, let's redefine your summing function so it takes the two lists at once, rather than point-wise:

ClearAll[signalSum2]
signalSum2[S1_List, S2_List, Ortogonality_] :=
Sqrt[(S1[[All, 2]]^2 + S2[[All, 2]]^2) + 2 S1[[All, 2]] S2[[All, 2]] Cos[Ortogonality]]


Let's then construct a sum of square deviations between the calculated sum (as a function of orthogonality) and the measured one, and minimize that sum of squares to obtain the optimal value of the orthogonality parameter:

sumOfSquares = Total@(datasummeasured[[All, 2]] - signalSum2[data1, data2, orth])^2;
bestfit = NMinimize[{sumOfSquares, 0 <= orth <= 2 Pi}, orth]

(* Out: {2.3202*^-24, {orth -> 4.4061}}*)


Let's plot the results and compare them to the measured values:

ListPlot[
{
datasummeasured,
Transpose[{datasummeasured[[All, 1]], signalSum2[data1, data2, orth /. Last@bestfit]}]
},
PlotStyle -> {Black, Directive[PointSize[0.02], Opacity[0.5, Red]]},
PlotLegends -> {"measured", "calculated"}
]


Note that there are multiple similar minima for the orthogonality parameter; for instance, the results are not much different for $$\text{orthogonality} = 1.87$$. I have constrained the value of the parameter to $$[0,2\pi]$$ because it is the argument of a cosine and therefore periodic, but perhaps you could constrain it further from insight into your physical system.

• Thank you @MarcoB! I was not aware that you could define functions to go over specific parts of a list :) it is a great trick Commented Jul 21, 2023 at 9:55