#pragma rtGlobals=1 // Use modern global access method. #pragma version =1.0 //initial release //Jan Ilavsky, ilavsky@aps.anl.gov //date: August 27, 2009 // Total non-negative least square method // reference: http://www.caam.rice.edu/~zhang/reports/tr0408.ps // (Michael Merritt and Yin Zhang, Technical Report TR04-08, Department of Computational and Applied Mathematics, Rice University, Houston, Texas 77005, U.S.A., May, 2004) // this method solves problems, which can be described as : // B = A x Model, where B is measured data (with uncertainities), A is n x m matrix and Model is what we are looking for. // Note, B has associated x-data in Wave BdataBinning // Model has associated X-data in Wave ModeldataBinning // none of the binning needs to be linear. // ApproachParameter is "step" - needs to be smaller than 1, usually 0.6 is good. Reasonable range seems to be 0.3 - 0.99 // limit MaxNumIterations to sensible number... Depends on complexity of problem... Function TNNLS(AmatrixInput,ModelWaveOutput, ModelDataBinning,BvectorInput, BdataBinning, UncertainitiesInput, ApproachParameter, MaxNumIterations) wave AmatrixInput,ModelWaveOutput,ModelDataBinning,BvectorInput, BdataBinning, UncertainitiesInput variable ApproachParameter, MaxNumIterations //Amatrix is n x m matrix relating ModelData to BVector(measured data). //create working space string OldDf=GetDataFolder(1) NewDataFolder/O/S root:Packages NewDataFolder/O/S root:Packages:NNLS //create local copies of input waves Duplicate/O AmatrixInput, AmatrixInputE, AmatrixOrig Duplicate/O BvectorInput, BvectorInputE //note this code defaults to use uncertainities. If these are not available, set following parameter to 0 and modify the code variable useUncertainitiesInput=1 if(useUncertainitiesInput) AmatrixInputE = AmatrixInput[p][q] / UncertainitiesInput[p] MatrixOp/O BvectorInputE = BvectorInput / UncertainitiesInput endif //create local meaningful waves to work with which account for the errors used. Duplicate/O AmatrixInputE, Amatrix Duplicate/O ModelWaveInput, ModelWave Duplicate/O BvectorInputE, BVector, BvectorOrig, CurrentResultB Duplicate/O UncertainitiesInput, Uncertainities //create some parameters, which the user may actually use after the run to find what happened. variable/g NumberIterations, Chisquare //first we will need some variables variable i,j //we will need these multiple times, precalcualting may save time. Amatrix[][] = AmatrixInputE[p][q] * BdataBinning[p] MatrixOp/O AmatrixT=Amatrix^t MatrixOp/O BVector = BvectorOrig * BdataBinning //starting conditions redimension/D ModelWave //we will start with reliably small positive number. Assume 1e-32 is such, but this may fail in some cases... ModelWave = 1e-32 //working waves & variables variable numIter=0 variable lasterr=1e3 variable err=0 variable alphaStar, temp1, temp2 //here the iterations start... Do //start of NNLS Interior point gradient method itself. Following steps designation relates to the original paper... //step 1 MatrixOp/O Qk = AmatrixT x Amatrix x ModelWave - AmatrixT x BVector MatrixOp/O Dk = ModelWave / (AmatrixT x Amatrix x ModelWave) MatrixOp/O Pk = - Dk * Qk //step 2 MatrixOp/O AkSTAR= (pk^t x AmatrixT x Amatrix x Pk) temp1 = AkSTAR[0] MatrixOp/O AkSTAR= - (pk^t x Qk) temp2 = AkSTAR[0] alphaStar = temp2 / temp1 redimension/N=(numpnts(ModelWave)) AkSTAR AkSTAR = alphaStar //above is ideal step to make//below is limiting the step so we do not get negative values... MatrixOP/O AlphaWv = - ModelWave/Pk //this is maximum alpha, which we can make, if pk is negative For(i=0;i1 && numIter