How to speed up Voigt profile fits?Compiling the VoigtDistribution PDFGetting lengths of sublists that sum to more than oneHow to Output Chi-Squared Statistics when using NonLinearModelFitModule in numerical model for NonlinearModelFit is slow and leaks memoryOptimizing code containing an infinite sumP-Values are inconsistent when using DistributionFitTest repeatedlyStill more problems with Fitting, please helpNon-linear curve fit problemCurve fitting using an asymmetrical sigmoid functionFitting a Voigt distribution - never finishesFitting data to an empirical distribution, finding best fit

Existence of subset with given Hausdorff dimension

Are all passive ability checks floors for active ability checks?

Dice rolling probability game

SOQL: Populate a Literal List in WHERE IN Clause

Instead of Universal Basic Income, why not Universal Basic NEEDS?

Why doesn't using two cd commands in bash script execute the second command?

Employee lack of ownership

Life insurance that covers only simultaneous/dual deaths

Do I need life insurance if I can cover my own funeral costs?

Why do Australian milk farmers need to protest supermarkets' milk price?

Why one should not leave fingerprints on bulbs and plugs?

Co-worker team leader wants to inject his friend's awful software into our development. What should I say to our common boss?

The difference between「N分で」and「後N分で」

A sequence that has integer values for prime indexes only:

Do the common programs (for example: "ls", "cat") in Linux and BSD come from the same source code?

Have researchers managed to "reverse time"? If so, what does that mean for physics?

Is there a data structure that only stores hash codes and not the actual objects?

How to deal with taxi scam when on vacation?

Brexit - No Deal Rejection

Time travel from stationary position?

Happy pi day, everyone!

How do anti-virus programs start at Windows boot?

Why is the President allowed to veto a cancellation of emergency powers?

If I can solve Sudoku can I solve Travelling Salesman Problem(TSP)? If yes, how?



How to speed up Voigt profile fits?


Compiling the VoigtDistribution PDFGetting lengths of sublists that sum to more than oneHow to Output Chi-Squared Statistics when using NonLinearModelFitModule in numerical model for NonlinearModelFit is slow and leaks memoryOptimizing code containing an infinite sumP-Values are inconsistent when using DistributionFitTest repeatedlyStill more problems with Fitting, please helpNon-linear curve fit problemCurve fitting using an asymmetrical sigmoid functionFitting a Voigt distribution - never finishesFitting data to an empirical distribution, finding best fit













6












$begingroup$


Voigt profile fits in Mathematica seem terribly slow. For an example data set with 81 points a corresponding fitting procedures for Voigt fits is >1000 times slower than for Gaussian or Lorentzian profile. How can Voigt profile fits be speed up?



Here is what I do. First we define the Voigt and Gaussian profile. As Mathematica often complains about δ and σ being <0, I use Abs instead of constraining the model as this proved faster. In addition I use the compile command to make the function even faster.



voigtprofile = Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,0, ν0,_Real, 0, ν, _Real, 0, A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]];
gaussian[σ_, A_, ν0_, ν_] := Return[A PDF[NormalDistribution[ν0, σ], ν]];


Then I create noisy example data sets with a bit of noise:



noisyDataV = #, 
voigtprofile[0.15, 0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@ Range[-2, 2, 0.05];
noisyDataG = #, gaussian[0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@
Range[-2, 2, 0.05];


And we use NonlinearModelFit to fit the data with excellent start parameters:



tv = AbsoluteTiming[vfit = NonlinearModelFit[noisyDataV, 
voigtprofile[δ, σ,
A, ν0, ν], δ, 0.15, σ, 0.1, A,
1, ν0, 0, ν];]
tg = AbsoluteTiming[gfit = NonlinearModelFit[noisyDataG,
gaussian[σ,
A, ν0, ν], σ, 0.1, A, 1, ν0,
0, ν];]


And if we compare the required time for fit:



tv[[1]]/tg[[1]]


I get values between 1000 and 6000, which is terrible. In addition, selecting a fit Method e.g. NMinimize or other does at best yield the same result.



As this minimal example is just a very simple example, times scale up to unbearable long times for more realistic scenarios with real data.
I'm glad for any hint on how to speed this simple example up.










share|improve this question









New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$







  • 4




    $begingroup$
    Have you seen this?
    $endgroup$
    – J. M. is slightly pensive
    15 hours ago















6












$begingroup$


Voigt profile fits in Mathematica seem terribly slow. For an example data set with 81 points a corresponding fitting procedures for Voigt fits is >1000 times slower than for Gaussian or Lorentzian profile. How can Voigt profile fits be speed up?



Here is what I do. First we define the Voigt and Gaussian profile. As Mathematica often complains about δ and σ being <0, I use Abs instead of constraining the model as this proved faster. In addition I use the compile command to make the function even faster.



voigtprofile = Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,0, ν0,_Real, 0, ν, _Real, 0, A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]];
gaussian[σ_, A_, ν0_, ν_] := Return[A PDF[NormalDistribution[ν0, σ], ν]];


Then I create noisy example data sets with a bit of noise:



noisyDataV = #, 
voigtprofile[0.15, 0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@ Range[-2, 2, 0.05];
noisyDataG = #, gaussian[0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@
Range[-2, 2, 0.05];


And we use NonlinearModelFit to fit the data with excellent start parameters:



tv = AbsoluteTiming[vfit = NonlinearModelFit[noisyDataV, 
voigtprofile[δ, σ,
A, ν0, ν], δ, 0.15, σ, 0.1, A,
1, ν0, 0, ν];]
tg = AbsoluteTiming[gfit = NonlinearModelFit[noisyDataG,
gaussian[σ,
A, ν0, ν], σ, 0.1, A, 1, ν0,
0, ν];]


And if we compare the required time for fit:



tv[[1]]/tg[[1]]


I get values between 1000 and 6000, which is terrible. In addition, selecting a fit Method e.g. NMinimize or other does at best yield the same result.



As this minimal example is just a very simple example, times scale up to unbearable long times for more realistic scenarios with real data.
I'm glad for any hint on how to speed this simple example up.










share|improve this question









New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$







  • 4




    $begingroup$
    Have you seen this?
    $endgroup$
    – J. M. is slightly pensive
    15 hours ago













6












6








6


1



$begingroup$


Voigt profile fits in Mathematica seem terribly slow. For an example data set with 81 points a corresponding fitting procedures for Voigt fits is >1000 times slower than for Gaussian or Lorentzian profile. How can Voigt profile fits be speed up?



Here is what I do. First we define the Voigt and Gaussian profile. As Mathematica often complains about δ and σ being <0, I use Abs instead of constraining the model as this proved faster. In addition I use the compile command to make the function even faster.



voigtprofile = Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,0, ν0,_Real, 0, ν, _Real, 0, A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]];
gaussian[σ_, A_, ν0_, ν_] := Return[A PDF[NormalDistribution[ν0, σ], ν]];


Then I create noisy example data sets with a bit of noise:



noisyDataV = #, 
voigtprofile[0.15, 0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@ Range[-2, 2, 0.05];
noisyDataG = #, gaussian[0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@
Range[-2, 2, 0.05];


And we use NonlinearModelFit to fit the data with excellent start parameters:



tv = AbsoluteTiming[vfit = NonlinearModelFit[noisyDataV, 
voigtprofile[δ, σ,
A, ν0, ν], δ, 0.15, σ, 0.1, A,
1, ν0, 0, ν];]
tg = AbsoluteTiming[gfit = NonlinearModelFit[noisyDataG,
gaussian[σ,
A, ν0, ν], σ, 0.1, A, 1, ν0,
0, ν];]


And if we compare the required time for fit:



tv[[1]]/tg[[1]]


I get values between 1000 and 6000, which is terrible. In addition, selecting a fit Method e.g. NMinimize or other does at best yield the same result.



As this minimal example is just a very simple example, times scale up to unbearable long times for more realistic scenarios with real data.
I'm glad for any hint on how to speed this simple example up.










share|improve this question









New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$




Voigt profile fits in Mathematica seem terribly slow. For an example data set with 81 points a corresponding fitting procedures for Voigt fits is >1000 times slower than for Gaussian or Lorentzian profile. How can Voigt profile fits be speed up?



Here is what I do. First we define the Voigt and Gaussian profile. As Mathematica often complains about δ and σ being <0, I use Abs instead of constraining the model as this proved faster. In addition I use the compile command to make the function even faster.



voigtprofile = Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,0, ν0,_Real, 0, ν, _Real, 0, A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]];
gaussian[σ_, A_, ν0_, ν_] := Return[A PDF[NormalDistribution[ν0, σ], ν]];


Then I create noisy example data sets with a bit of noise:



noisyDataV = #, 
voigtprofile[0.15, 0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@ Range[-2, 2, 0.05];
noisyDataG = #, gaussian[0.1, 1, 0, #] + RandomReal[-0.1, 0.1] & /@
Range[-2, 2, 0.05];


And we use NonlinearModelFit to fit the data with excellent start parameters:



tv = AbsoluteTiming[vfit = NonlinearModelFit[noisyDataV, 
voigtprofile[δ, σ,
A, ν0, ν], δ, 0.15, σ, 0.1, A,
1, ν0, 0, ν];]
tg = AbsoluteTiming[gfit = NonlinearModelFit[noisyDataG,
gaussian[σ,
A, ν0, ν], σ, 0.1, A, 1, ν0,
0, ν];]


And if we compare the required time for fit:



tv[[1]]/tg[[1]]


I get values between 1000 and 6000, which is terrible. In addition, selecting a fit Method e.g. NMinimize or other does at best yield the same result.



As this minimal example is just a very simple example, times scale up to unbearable long times for more realistic scenarios with real data.
I'm glad for any hint on how to speed this simple example up.







performance-tuning fitting nonlinear






share|improve this question









New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 15 hours ago









Johu

3,7031037




3,7031037






New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 15 hours ago









Adrian BeckertAdrian Beckert

613




613




New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







  • 4




    $begingroup$
    Have you seen this?
    $endgroup$
    – J. M. is slightly pensive
    15 hours ago












  • 4




    $begingroup$
    Have you seen this?
    $endgroup$
    – J. M. is slightly pensive
    15 hours ago







4




4




$begingroup$
Have you seen this?
$endgroup$
– J. M. is slightly pensive
15 hours ago




$begingroup$
Have you seen this?
$endgroup$
– J. M. is slightly pensive
15 hours ago










2 Answers
2






active

oldest

votes


















3












$begingroup$

Thanks to J. M. for the suggestion. Instead of using the computationally intensive VoigtDistribution, we can use the Pseudo-Voigt numeric approximation from this post which exhibits very low errors compared to the analytical Voigt (see here or references in here) and speeds up the fitting procedure by approximately a factor of 100 or more.



pseudoVoigtProfile = With[n = 24, τ = 12, With[d = N[Range[n] π/τ],b = N[Exp[-(Range[n] π/τ)^2]], s = N[PadRight[, n, -1, 1]], sq = N[Sqrt[2]],sp = N[Sqrt[2 π]], 
Compile[δ, _Real, σ, _Real, x, _Real,
Module[z = (x + I δ)/(σ sq), e,
e = Exp[I τ z];
Re[(I (1 -e)/(τ z) + (2 I z/τ)b.((e s -1)/((d + z) (d - z))))]/(σ sp)],
RuntimeAttributes -> Listable]]];


and fit it to the noisy test data



tpv = AbsoluteTiming[pvfit = NonlinearModelFit[noisyDataV, 
pseudoVoigtProfile[δ, σ, ν - ν0], δ, 0.15, σ, 0.1, A, 1, ν0, 0, ν];]


which leads to a ratio tpv/tg ~ 10 on my computer.



Note: Although the Pseudo-Voigt profile is a numerical approximation it will do the job for most daily life applications where the noise on the e.g. optical spectrum is at least an order of magnitude larger than the numeric error of the approximation.






share|improve this answer










New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$












  • $begingroup$
    As Voigt is Gaussian convolved by Lorentzian another approach regularly used in spectrometry is to work in Fourier space: see sites.math.washington.edu/~morrow/papers/GVmathThesis2010.pdf for instance (sorry I do not have all the details in mind for a complete answer here)
    $endgroup$
    – Picaud Vincent
    12 hours ago






  • 1




    $begingroup$
    The compiled implementation you got from my answer is a genuine implementation of the Voigt profile, nothing "pseudo" about it.
    $endgroup$
    – J. M. is slightly pensive
    12 hours ago


















2












$begingroup$

You can use CompilePrint to check what Compile actually did:



Needs["CompiledFunctionTools`"];
voigtprofile1 =
Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,
0, ν0, _Real, 0, ν, _Real, 0,
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
];
CompilePrint[voigtprofile1]

Out[26]= "5 arguments
7 Real registers
Underflow checking off
Overflow checking off
Integer overflow checking on
RuntimeAttributes ->
R0 = A1
R1 = A2
R2 = A3
R3 = A4
R4 = A5
Result = R6
1 R5 = MainEvaluate[ Function[δ, σ, A, ν0, ν,
PDF[VoigtDistribution[Abs[δ], Abs[σ]], ν - ν0]][ R0, R1, R2, R3, R4]]
2 R6 = R2 * R5
3 Return"


As you can see, all the function really does is call MainEvaluate and then multiply two numbers together. Basically, you haven't compiled anything.



Instead, evaluate the PDF inside of the Compile to get a symbolic expression that is compilable:



voigtprofile2 = Compile[
δ, _Real, 0, σ, _Real, 0, A, _Real, 0, ν0, _Real, 0, ν, _Real, 0,
Evaluate[
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
],
CompilationOptions -> "ExpressionOptimization" -> True,
RuntimeAttributes -> Listable
];


This should be significantly faster.






share|improve this answer











$endgroup$








  • 1




    $begingroup$
    The problem with your voigtprofile2 is that Erfc[] only works for real arguments within a compiled function, so it gets wrapped in MainEvaluate. That was one reason why I wrote the routine in the thread I linked to in the comments.
    $endgroup$
    – J. M. is slightly pensive
    11 hours ago






  • 1




    $begingroup$
    Ok, that's handy to know. That's a specific problem of VoigtDistribution I didn't anticipate. I still wanted to point out the importance of using CompilePrint, though.
    $endgroup$
    – Sjoerd Smit
    11 hours ago










Your Answer





StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
);
);
, "mathjax-editing");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "387"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);






Adrian Beckert is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f193317%2fhow-to-speed-up-voigt-profile-fits%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









3












$begingroup$

Thanks to J. M. for the suggestion. Instead of using the computationally intensive VoigtDistribution, we can use the Pseudo-Voigt numeric approximation from this post which exhibits very low errors compared to the analytical Voigt (see here or references in here) and speeds up the fitting procedure by approximately a factor of 100 or more.



pseudoVoigtProfile = With[n = 24, τ = 12, With[d = N[Range[n] π/τ],b = N[Exp[-(Range[n] π/τ)^2]], s = N[PadRight[, n, -1, 1]], sq = N[Sqrt[2]],sp = N[Sqrt[2 π]], 
Compile[δ, _Real, σ, _Real, x, _Real,
Module[z = (x + I δ)/(σ sq), e,
e = Exp[I τ z];
Re[(I (1 -e)/(τ z) + (2 I z/τ)b.((e s -1)/((d + z) (d - z))))]/(σ sp)],
RuntimeAttributes -> Listable]]];


and fit it to the noisy test data



tpv = AbsoluteTiming[pvfit = NonlinearModelFit[noisyDataV, 
pseudoVoigtProfile[δ, σ, ν - ν0], δ, 0.15, σ, 0.1, A, 1, ν0, 0, ν];]


which leads to a ratio tpv/tg ~ 10 on my computer.



Note: Although the Pseudo-Voigt profile is a numerical approximation it will do the job for most daily life applications where the noise on the e.g. optical spectrum is at least an order of magnitude larger than the numeric error of the approximation.






share|improve this answer










New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$












  • $begingroup$
    As Voigt is Gaussian convolved by Lorentzian another approach regularly used in spectrometry is to work in Fourier space: see sites.math.washington.edu/~morrow/papers/GVmathThesis2010.pdf for instance (sorry I do not have all the details in mind for a complete answer here)
    $endgroup$
    – Picaud Vincent
    12 hours ago






  • 1




    $begingroup$
    The compiled implementation you got from my answer is a genuine implementation of the Voigt profile, nothing "pseudo" about it.
    $endgroup$
    – J. M. is slightly pensive
    12 hours ago















3












$begingroup$

Thanks to J. M. for the suggestion. Instead of using the computationally intensive VoigtDistribution, we can use the Pseudo-Voigt numeric approximation from this post which exhibits very low errors compared to the analytical Voigt (see here or references in here) and speeds up the fitting procedure by approximately a factor of 100 or more.



pseudoVoigtProfile = With[n = 24, τ = 12, With[d = N[Range[n] π/τ],b = N[Exp[-(Range[n] π/τ)^2]], s = N[PadRight[, n, -1, 1]], sq = N[Sqrt[2]],sp = N[Sqrt[2 π]], 
Compile[δ, _Real, σ, _Real, x, _Real,
Module[z = (x + I δ)/(σ sq), e,
e = Exp[I τ z];
Re[(I (1 -e)/(τ z) + (2 I z/τ)b.((e s -1)/((d + z) (d - z))))]/(σ sp)],
RuntimeAttributes -> Listable]]];


and fit it to the noisy test data



tpv = AbsoluteTiming[pvfit = NonlinearModelFit[noisyDataV, 
pseudoVoigtProfile[δ, σ, ν - ν0], δ, 0.15, σ, 0.1, A, 1, ν0, 0, ν];]


which leads to a ratio tpv/tg ~ 10 on my computer.



Note: Although the Pseudo-Voigt profile is a numerical approximation it will do the job for most daily life applications where the noise on the e.g. optical spectrum is at least an order of magnitude larger than the numeric error of the approximation.






share|improve this answer










New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$












  • $begingroup$
    As Voigt is Gaussian convolved by Lorentzian another approach regularly used in spectrometry is to work in Fourier space: see sites.math.washington.edu/~morrow/papers/GVmathThesis2010.pdf for instance (sorry I do not have all the details in mind for a complete answer here)
    $endgroup$
    – Picaud Vincent
    12 hours ago






  • 1




    $begingroup$
    The compiled implementation you got from my answer is a genuine implementation of the Voigt profile, nothing "pseudo" about it.
    $endgroup$
    – J. M. is slightly pensive
    12 hours ago













3












3








3





$begingroup$

Thanks to J. M. for the suggestion. Instead of using the computationally intensive VoigtDistribution, we can use the Pseudo-Voigt numeric approximation from this post which exhibits very low errors compared to the analytical Voigt (see here or references in here) and speeds up the fitting procedure by approximately a factor of 100 or more.



pseudoVoigtProfile = With[n = 24, τ = 12, With[d = N[Range[n] π/τ],b = N[Exp[-(Range[n] π/τ)^2]], s = N[PadRight[, n, -1, 1]], sq = N[Sqrt[2]],sp = N[Sqrt[2 π]], 
Compile[δ, _Real, σ, _Real, x, _Real,
Module[z = (x + I δ)/(σ sq), e,
e = Exp[I τ z];
Re[(I (1 -e)/(τ z) + (2 I z/τ)b.((e s -1)/((d + z) (d - z))))]/(σ sp)],
RuntimeAttributes -> Listable]]];


and fit it to the noisy test data



tpv = AbsoluteTiming[pvfit = NonlinearModelFit[noisyDataV, 
pseudoVoigtProfile[δ, σ, ν - ν0], δ, 0.15, σ, 0.1, A, 1, ν0, 0, ν];]


which leads to a ratio tpv/tg ~ 10 on my computer.



Note: Although the Pseudo-Voigt profile is a numerical approximation it will do the job for most daily life applications where the noise on the e.g. optical spectrum is at least an order of magnitude larger than the numeric error of the approximation.






share|improve this answer










New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$



Thanks to J. M. for the suggestion. Instead of using the computationally intensive VoigtDistribution, we can use the Pseudo-Voigt numeric approximation from this post which exhibits very low errors compared to the analytical Voigt (see here or references in here) and speeds up the fitting procedure by approximately a factor of 100 or more.



pseudoVoigtProfile = With[n = 24, τ = 12, With[d = N[Range[n] π/τ],b = N[Exp[-(Range[n] π/τ)^2]], s = N[PadRight[, n, -1, 1]], sq = N[Sqrt[2]],sp = N[Sqrt[2 π]], 
Compile[δ, _Real, σ, _Real, x, _Real,
Module[z = (x + I δ)/(σ sq), e,
e = Exp[I τ z];
Re[(I (1 -e)/(τ z) + (2 I z/τ)b.((e s -1)/((d + z) (d - z))))]/(σ sp)],
RuntimeAttributes -> Listable]]];


and fit it to the noisy test data



tpv = AbsoluteTiming[pvfit = NonlinearModelFit[noisyDataV, 
pseudoVoigtProfile[δ, σ, ν - ν0], δ, 0.15, σ, 0.1, A, 1, ν0, 0, ν];]


which leads to a ratio tpv/tg ~ 10 on my computer.



Note: Although the Pseudo-Voigt profile is a numerical approximation it will do the job for most daily life applications where the noise on the e.g. optical spectrum is at least an order of magnitude larger than the numeric error of the approximation.







share|improve this answer










New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this answer



share|improve this answer








edited 9 hours ago









MarcoB

37.5k556113




37.5k556113






New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









answered 13 hours ago









Adrian BeckertAdrian Beckert

613




613




New contributor




Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Adrian Beckert is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











  • $begingroup$
    As Voigt is Gaussian convolved by Lorentzian another approach regularly used in spectrometry is to work in Fourier space: see sites.math.washington.edu/~morrow/papers/GVmathThesis2010.pdf for instance (sorry I do not have all the details in mind for a complete answer here)
    $endgroup$
    – Picaud Vincent
    12 hours ago






  • 1




    $begingroup$
    The compiled implementation you got from my answer is a genuine implementation of the Voigt profile, nothing "pseudo" about it.
    $endgroup$
    – J. M. is slightly pensive
    12 hours ago
















  • $begingroup$
    As Voigt is Gaussian convolved by Lorentzian another approach regularly used in spectrometry is to work in Fourier space: see sites.math.washington.edu/~morrow/papers/GVmathThesis2010.pdf for instance (sorry I do not have all the details in mind for a complete answer here)
    $endgroup$
    – Picaud Vincent
    12 hours ago






  • 1




    $begingroup$
    The compiled implementation you got from my answer is a genuine implementation of the Voigt profile, nothing "pseudo" about it.
    $endgroup$
    – J. M. is slightly pensive
    12 hours ago















$begingroup$
As Voigt is Gaussian convolved by Lorentzian another approach regularly used in spectrometry is to work in Fourier space: see sites.math.washington.edu/~morrow/papers/GVmathThesis2010.pdf for instance (sorry I do not have all the details in mind for a complete answer here)
$endgroup$
– Picaud Vincent
12 hours ago




$begingroup$
As Voigt is Gaussian convolved by Lorentzian another approach regularly used in spectrometry is to work in Fourier space: see sites.math.washington.edu/~morrow/papers/GVmathThesis2010.pdf for instance (sorry I do not have all the details in mind for a complete answer here)
$endgroup$
– Picaud Vincent
12 hours ago




1




1




$begingroup$
The compiled implementation you got from my answer is a genuine implementation of the Voigt profile, nothing "pseudo" about it.
$endgroup$
– J. M. is slightly pensive
12 hours ago




$begingroup$
The compiled implementation you got from my answer is a genuine implementation of the Voigt profile, nothing "pseudo" about it.
$endgroup$
– J. M. is slightly pensive
12 hours ago











2












$begingroup$

You can use CompilePrint to check what Compile actually did:



Needs["CompiledFunctionTools`"];
voigtprofile1 =
Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,
0, ν0, _Real, 0, ν, _Real, 0,
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
];
CompilePrint[voigtprofile1]

Out[26]= "5 arguments
7 Real registers
Underflow checking off
Overflow checking off
Integer overflow checking on
RuntimeAttributes ->
R0 = A1
R1 = A2
R2 = A3
R3 = A4
R4 = A5
Result = R6
1 R5 = MainEvaluate[ Function[δ, σ, A, ν0, ν,
PDF[VoigtDistribution[Abs[δ], Abs[σ]], ν - ν0]][ R0, R1, R2, R3, R4]]
2 R6 = R2 * R5
3 Return"


As you can see, all the function really does is call MainEvaluate and then multiply two numbers together. Basically, you haven't compiled anything.



Instead, evaluate the PDF inside of the Compile to get a symbolic expression that is compilable:



voigtprofile2 = Compile[
δ, _Real, 0, σ, _Real, 0, A, _Real, 0, ν0, _Real, 0, ν, _Real, 0,
Evaluate[
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
],
CompilationOptions -> "ExpressionOptimization" -> True,
RuntimeAttributes -> Listable
];


This should be significantly faster.






share|improve this answer











$endgroup$








  • 1




    $begingroup$
    The problem with your voigtprofile2 is that Erfc[] only works for real arguments within a compiled function, so it gets wrapped in MainEvaluate. That was one reason why I wrote the routine in the thread I linked to in the comments.
    $endgroup$
    – J. M. is slightly pensive
    11 hours ago






  • 1




    $begingroup$
    Ok, that's handy to know. That's a specific problem of VoigtDistribution I didn't anticipate. I still wanted to point out the importance of using CompilePrint, though.
    $endgroup$
    – Sjoerd Smit
    11 hours ago















2












$begingroup$

You can use CompilePrint to check what Compile actually did:



Needs["CompiledFunctionTools`"];
voigtprofile1 =
Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,
0, ν0, _Real, 0, ν, _Real, 0,
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
];
CompilePrint[voigtprofile1]

Out[26]= "5 arguments
7 Real registers
Underflow checking off
Overflow checking off
Integer overflow checking on
RuntimeAttributes ->
R0 = A1
R1 = A2
R2 = A3
R3 = A4
R4 = A5
Result = R6
1 R5 = MainEvaluate[ Function[δ, σ, A, ν0, ν,
PDF[VoigtDistribution[Abs[δ], Abs[σ]], ν - ν0]][ R0, R1, R2, R3, R4]]
2 R6 = R2 * R5
3 Return"


As you can see, all the function really does is call MainEvaluate and then multiply two numbers together. Basically, you haven't compiled anything.



Instead, evaluate the PDF inside of the Compile to get a symbolic expression that is compilable:



voigtprofile2 = Compile[
δ, _Real, 0, σ, _Real, 0, A, _Real, 0, ν0, _Real, 0, ν, _Real, 0,
Evaluate[
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
],
CompilationOptions -> "ExpressionOptimization" -> True,
RuntimeAttributes -> Listable
];


This should be significantly faster.






share|improve this answer











$endgroup$








  • 1




    $begingroup$
    The problem with your voigtprofile2 is that Erfc[] only works for real arguments within a compiled function, so it gets wrapped in MainEvaluate. That was one reason why I wrote the routine in the thread I linked to in the comments.
    $endgroup$
    – J. M. is slightly pensive
    11 hours ago






  • 1




    $begingroup$
    Ok, that's handy to know. That's a specific problem of VoigtDistribution I didn't anticipate. I still wanted to point out the importance of using CompilePrint, though.
    $endgroup$
    – Sjoerd Smit
    11 hours ago













2












2








2





$begingroup$

You can use CompilePrint to check what Compile actually did:



Needs["CompiledFunctionTools`"];
voigtprofile1 =
Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,
0, ν0, _Real, 0, ν, _Real, 0,
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
];
CompilePrint[voigtprofile1]

Out[26]= "5 arguments
7 Real registers
Underflow checking off
Overflow checking off
Integer overflow checking on
RuntimeAttributes ->
R0 = A1
R1 = A2
R2 = A3
R3 = A4
R4 = A5
Result = R6
1 R5 = MainEvaluate[ Function[δ, σ, A, ν0, ν,
PDF[VoigtDistribution[Abs[δ], Abs[σ]], ν - ν0]][ R0, R1, R2, R3, R4]]
2 R6 = R2 * R5
3 Return"


As you can see, all the function really does is call MainEvaluate and then multiply two numbers together. Basically, you haven't compiled anything.



Instead, evaluate the PDF inside of the Compile to get a symbolic expression that is compilable:



voigtprofile2 = Compile[
δ, _Real, 0, σ, _Real, 0, A, _Real, 0, ν0, _Real, 0, ν, _Real, 0,
Evaluate[
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
],
CompilationOptions -> "ExpressionOptimization" -> True,
RuntimeAttributes -> Listable
];


This should be significantly faster.






share|improve this answer











$endgroup$



You can use CompilePrint to check what Compile actually did:



Needs["CompiledFunctionTools`"];
voigtprofile1 =
Compile[δ, _Real, 0, σ, _Real, 0, A, _Real,
0, ν0, _Real, 0, ν, _Real, 0,
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
];
CompilePrint[voigtprofile1]

Out[26]= "5 arguments
7 Real registers
Underflow checking off
Overflow checking off
Integer overflow checking on
RuntimeAttributes ->
R0 = A1
R1 = A2
R2 = A3
R3 = A4
R4 = A5
Result = R6
1 R5 = MainEvaluate[ Function[δ, σ, A, ν0, ν,
PDF[VoigtDistribution[Abs[δ], Abs[σ]], ν - ν0]][ R0, R1, R2, R3, R4]]
2 R6 = R2 * R5
3 Return"


As you can see, all the function really does is call MainEvaluate and then multiply two numbers together. Basically, you haven't compiled anything.



Instead, evaluate the PDF inside of the Compile to get a symbolic expression that is compilable:



voigtprofile2 = Compile[
δ, _Real, 0, σ, _Real, 0, A, _Real, 0, ν0, _Real, 0, ν, _Real, 0,
Evaluate[
A PDF[VoigtDistribution[Abs@δ, Abs@σ], ν - ν0]
],
CompilationOptions -> "ExpressionOptimization" -> True,
RuntimeAttributes -> Listable
];


This should be significantly faster.







share|improve this answer














share|improve this answer



share|improve this answer








edited 9 hours ago









MarcoB

37.5k556113




37.5k556113










answered 11 hours ago









Sjoerd SmitSjoerd Smit

4,055815




4,055815







  • 1




    $begingroup$
    The problem with your voigtprofile2 is that Erfc[] only works for real arguments within a compiled function, so it gets wrapped in MainEvaluate. That was one reason why I wrote the routine in the thread I linked to in the comments.
    $endgroup$
    – J. M. is slightly pensive
    11 hours ago






  • 1




    $begingroup$
    Ok, that's handy to know. That's a specific problem of VoigtDistribution I didn't anticipate. I still wanted to point out the importance of using CompilePrint, though.
    $endgroup$
    – Sjoerd Smit
    11 hours ago












  • 1




    $begingroup$
    The problem with your voigtprofile2 is that Erfc[] only works for real arguments within a compiled function, so it gets wrapped in MainEvaluate. That was one reason why I wrote the routine in the thread I linked to in the comments.
    $endgroup$
    – J. M. is slightly pensive
    11 hours ago






  • 1




    $begingroup$
    Ok, that's handy to know. That's a specific problem of VoigtDistribution I didn't anticipate. I still wanted to point out the importance of using CompilePrint, though.
    $endgroup$
    – Sjoerd Smit
    11 hours ago







1




1




$begingroup$
The problem with your voigtprofile2 is that Erfc[] only works for real arguments within a compiled function, so it gets wrapped in MainEvaluate. That was one reason why I wrote the routine in the thread I linked to in the comments.
$endgroup$
– J. M. is slightly pensive
11 hours ago




$begingroup$
The problem with your voigtprofile2 is that Erfc[] only works for real arguments within a compiled function, so it gets wrapped in MainEvaluate. That was one reason why I wrote the routine in the thread I linked to in the comments.
$endgroup$
– J. M. is slightly pensive
11 hours ago




1




1




$begingroup$
Ok, that's handy to know. That's a specific problem of VoigtDistribution I didn't anticipate. I still wanted to point out the importance of using CompilePrint, though.
$endgroup$
– Sjoerd Smit
11 hours ago




$begingroup$
Ok, that's handy to know. That's a specific problem of VoigtDistribution I didn't anticipate. I still wanted to point out the importance of using CompilePrint, though.
$endgroup$
– Sjoerd Smit
11 hours ago










Adrian Beckert is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















Adrian Beckert is a new contributor. Be nice, and check out our Code of Conduct.












Adrian Beckert is a new contributor. Be nice, and check out our Code of Conduct.











Adrian Beckert is a new contributor. Be nice, and check out our Code of Conduct.














Thanks for contributing an answer to Mathematica Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f193317%2fhow-to-speed-up-voigt-profile-fits%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How should I use the fbox command correctly to avoid producing a Bad Box message?How to put a long piece of text in a box?How to specify height and width of fboxIs there an arrayrulecolor-like command to change the rule color of fbox?What is the command to highlight bad boxes in pdf?Why does fbox sometimes place the box *over* the graphic image?how to put the text in the boxHow to create command for a box where text inside the box can automatically adjust?how can I make an fbox like command with certain color, shape and width of border?how to use fbox in align modeFbox increase the spacing between the box and it content (inner margin)how to change the box height of an equationWhat is the use of the hbox in a newcommand command?

152 Atala Notae | Nexus externi | Tabula navigationis"Discovery Circumstances: Numbered Minor Planets"2000152Small-Body Database

Doxepinum Nexus interni Notae | Tabula navigationis3158DB01142WHOa682390"Structural Analysis of the Histamine H1 Receptor""Transdermal and Topical Drug Administration in the Treatment of Pain""Antidepressants as antipruritic agents: A review"