2
$\begingroup$

I'm quite new to Mathematica. I've used Matlab in the past but it was a long time ago.

I'm working on developing a Dark Room Light meter and need to fit some curves. But, ideally, I need to fit all the curves in a single 2 variable surface.

I couldn't upload the picture, so I leave a link to it: Plot Each curve corresponds to a Printing Range that would be the -y- axis, while the exposure would be the -x- axis and the Density (darkness of the print) will be the -z- axis. The variables of the function will be x and y and the result should be the Density.

One approach would be taking individual values of each curve at different points and try to fit a 2 variable function. But since I see that it's quite easy to fit a function for each curve, I would like to approach the two variable function from the curve fitting of each plot.

Separating each plot is not an issue since I can even do it in Photoshop before feeding it to Mathematica.

Thanks in advance for you help.

$\endgroup$
  • $\begingroup$ Do you have the data you want to fit (ie, a list of data points)? Please post any Mathematica code or data you have -- it makes it a lot easier for people to help you. And have you looked at NonlinearModelFit? $\endgroup$ – aardvark2012 Oct 9 '17 at 9:48
  • $\begingroup$ I have plots from paper manufacturers, not data points. I've posted a picture of the plots given by one manufacturer. For the moment, I don't have any code to post, sorry. It's in a link since I could not upload the file directly. I almost know how to fit each separate curve, but I don't know how to fit them all on a surface. $\endgroup$ – Ivan Vazquez Oct 9 '17 at 10:18
  • $\begingroup$ In the context of computer graphics, this operation is called "lofting" or "skinning". $\endgroup$ – J. M. will be back soon Mar 25 '18 at 17:36
3
$\begingroup$

I suppose that you can import the data points of each curve into Mathematica somehow, so that you obtain a matrix curves such as I tried to emulated below.

tlist = Table[t, {t, 0, 5., 0.1}];
nlist = Range[5];
curves = Table[ Map[t \[Function] {t, 1/Exp[1 + Exp[-n (t - (1 + 1/n))]]}, tlist], {n, nlist}];
ListLinePlot[curves, PlotLegends -> nlist,  AxesLabel -> {"LogE", "Density"}]

enter image description here

Here, nlist is a list of parameters; each entry corresponds to one entry in curves. I create 3-dimensional data by merging nlist and curves as follows; afterwards I use Interpolation to do, well, the interpolation.

data = Join[
   Table[ConstantArray[{N[n]}, Length[tlist]], {n, nlist}],
   curves,
   3
   ];
f = Interpolation[Flatten[data, 1]];

Now, we can plot that as a surface. I also show how the 2-d curves are embedded into $\mathbb{R}^3$. I hope this helps.

Show[
 Plot3D[f[n, t], {n, 1, 5}, {t, Min[tlist], Max[tlist]}, 
  AxesLabel -> {"n", "LogE"}],
 Graphics3D[{Thick, Line[data]}]
 ]

enter image description here

$\endgroup$
  • $\begingroup$ Thank you very much, Henrik! That's almost what I need. The only missing thing is how to get a 2 variable function that represents this surface. $\endgroup$ – Ivan Vazquez Oct 9 '17 at 15:18
  • $\begingroup$ You're welcome. The function f constructed above should be what you are looking for. All the data is packed into an InterpolationFunction object and hidden from the user. You can use f as any other pure function; e.g., you can also evaluate derivatives of it. See the documentation of Interpolation for more details. You can also find various options for the interpolation, there. $\endgroup$ – Henrik Schumacher Oct 9 '17 at 15:32
  • $\begingroup$ Thank you very much again for your response. I almost understand what I need to do. The only problem with this approach is that I cannot get the expression of the InterpolatingFunction and I need to get it in order to include it in my C# code. I cannot use Mathematica API since it's running on a Raspberry Pi and I want to keep it as simple as possible. $\endgroup$ – Ivan Vazquez Oct 10 '17 at 8:39
  • $\begingroup$ Ah, I see. Maybe these will help: mathematica.stackexchange.com/questions/59944 or mathematica.stackexchange.com/questions/105459 $\endgroup$ – Henrik Schumacher Oct 10 '17 at 9:45
  • $\begingroup$ Thank you very much, Henrik. You have helped me a lot. I'm now on the way to get a proper function. I really, really, appreciate your help. $\endgroup$ – Ivan Vazquez Oct 10 '17 at 10:34
0
$\begingroup$

Preparation

Since you did not supply the curves to fit, we firstly generate several curves:

curves1 = Table[{2 i, 2 j, Sin[2 i + 2 j]}, {i, 0, 2}, {j, 0, 6, 0.5}];
curves2 = Table[{2 i + 1, 2 j + 1, Sin[2 i + 2 j + 2]}, {i, 0, 2}, {j, 0, 6, 0.5}];
Graphics3D[{Red, Thick, Line[curves1], Blue, Line[curves2]}, Boxed -> False]

enter image description here

Solution

If you just want to visualize a surface to fit all these curves, BSplineSurface is enough:

bsSurface = BSplineSurface[Flatten[{curves1, curves2}, 1]];
Graphics3D[{Red, Thick, Line[curves1], Blue, Thick, Line[curves2],
    Opacity[0.6], Gray, EdgeForm[], bsSurface}, Boxed -> False]

enter image description here

However if you want to interpolate the data of all the curves, i.e. curves1 and curves2, Interpolation works for such purpose. Interpolation can fit multidimensional functions:

interpolateFunciton = Interpolation[{{#1, #2}, #3} & @@@ Flatten[{curves1, curves2}, 2]];

Validation

Validate our interpolateFunciton at the point with coordinate {3.5, 3.5, ?}, which does not belong to either curves1 or curves2:

pt = {#1, #2, interpolateFunciton[#1, #2]} & @@ {3.5, 3.5};
Graphics3D[{Red, Thick, Line[curves1], Blue, Thick, Line[curves2], 
    Opacity[0.6], Gray, EdgeForm[], bsSurface, PointSize[.02], 
    Black, Point[pt]}, Boxed -> False]

enter image description here

En, the black point almost lies within the interpolated surface.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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