1

I would like to apologise in advance for how wordy this problem is: I have experience with MATLAB but am relatively new to Python, and as such I am unable to express this problem in code where it would be more appropriate than describing using words.

I have a measured spectrum which consists of contributions from two components: A and B.

The absorbance at a given value of x is therefore:

Abs(x) ~ c*[(f*A(x))+((1-f)*B(x)],

where f is the fraction of A in the mixture, and c is proportional to the total concentration of A and B. The absorbance is only approximate because of noise in the measured spectrum.

Absorbance of individual components

Absorbance of mixture with noise

The question I have is how best to deconvolute the measured spectrum (over the entire range of x values) by determining the relative contribution of each component, and calculate the concentration of A + B - i.e., determine the combination of values for c and f in the equation above which give the best fit.

As a novice, a method which should work but which is inefficient would be to choose values of f at different intervals (say, 0 to 1 in 0.1 intervals) and find the value of c which gives the smallest sum of residuals squared, R^2 for each f. The combination which gives the best fit could then be used as an initial guess to optimise f to a chosen number of significant figures. I imagine however, that this approach would be time-intensive when running for loops with >thousands of spectra at a time.

Does Python contain any functionality which would allow for this deconvolution to be done more efficiently than the process described above, either in part or in whole?

Thanks in advance.

sglander
  • 21
  • 3
  • I don't know [SciPy](https://scipy.org/) myself, but that's where you will find what you need (like, e.g., [scipy.optimize.least_squares](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html)) – Walter Tross Jul 20 '20 at 21:13
  • 1
    Thanks, this is exactly what I need. Part of my problem was that everything I saw required a function as input rather than two data sets for optimisation, however now I realise that I can simply define the function in terms of the two data sets. – sglander Jul 21 '20 at 00:22
  • Instead of adding the solution to the top of your post, you can leave the question properly stated as such, and write your own answer. This would be more useful for StackOverflow users, and I would upvote both, question and answer. Note also that "in Python" is redundant in the title, because you have the tag. – Walter Tross Jul 21 '20 at 07:06
  • 1
    Thanks, I've added the answer and edited my question as you advised. – sglander Jul 31 '20 at 22:04

1 Answers1

1

Maybe not the best way to solve the problem, although the results are satisfactory and now knowing the general method I can tweak the code in future.

# Determine concentration and fraction of A in mixture by minimising the sum 
# of the square residuals for measured spectrum - sum of spectra A + B
from scipy.optimize import minimize
def objective(x)
    return sum(spec-(x1*((x2*spec_A)+((1-x2)*spec_B))))**2

# Initial guess for parameters
x0=[max(spec)/(0.5*max(spec_A+spec_B)),0.5]

sol=minimize(objective,x0,method='SLSQP')
sglander
  • 21
  • 3