/// <summary> /// Copies the current parameters for the fit element with the provided index into the provided array. /// </summary> /// <param name="idxFitEle">Index of the fit element.</param> /// <param name="parameters">Provided array to copy the current parameters to. Must have same size as NumberOfParameters for the given fit element.</param> public void GetParameters(int idxFitEle, double[] parameters) { CachedFitElementInfo info = _cachedFitElementInfo[idxFitEle]; // copy of the parameter to the temporary array for (int i = 0; i < info.Parameters.Length; i++) { int idx = info.ParameterMapping[i]; parameters[i] = idx >= 0 ? _cachedVaryingParameters[idx] : _constantParameters[-1 - idx]; } }
/// <summary> /// Calculates the jacobian values, i.e. the derivatives of the fitting values with respect to the parameters. /// </summary> /// <param name="parameter">The parameter used to calculate the values.</param> /// <param name="outputValues">You must provide an array to hold the calculated values. Size of the array must be /// at least <see cref="NumberOfData" />*<see cref="FitElement.NumberOfParameters" />.</param> /// <param name="adata">Currently ignored.</param> /// <remarks>The values of the fit elements are stored in the order from element_0 to element_n*m. If there is more /// than one used dependent variable per fit element, the output values are stored in interleaved order. The derivatives /// on one fitting value are stored in successive order. /// </remarks> public void EvaluateFitJacobian(double[] parameter, double[] outputValues, object adata) { outputValues.Initialize(); // make sure every element contains zero int outputValuesPointer = 0; for (int ele = 0; ele < _cachedFitElementInfo.Length; ele++) { CachedFitElementInfo info = _cachedFitElementInfo[ele]; FitElement fitEle = _fitEnsemble[ele]; // make sure, that the dimension of the DYs is ok if (info.DYs == null || info.DYs.Length != fitEle.NumberOfDependentVariables || info.DYs[0].Length != fitEle.NumberOfParameters) { info.DYs = LinearAlgebra.JaggedArrayMath.GetMatrixArray(fitEle.NumberOfDependentVariables, fitEle.NumberOfParameters); } // copy of the parameter to the temporary array for (int i = 0; i < info.Parameters.Length; i++) { int idx = info.ParameterMapping[i]; info.Parameters[i] = idx >= 0 ? parameter[idx] : _constantParameters[-1 - idx]; } IAscendingIntegerCollection validRows = info.ValidRows; int numValidRows = validRows.Count; // Evaluate the function for all points for (int i = 0; i < numValidRows; ++i) { for (int k = info.Xs.Length - 1; k >= 0; k--) { info.Xs[k] = fitEle.IndependentVariables(k)[validRows[i]]; } ((IFitFunctionWithGradient)fitEle.FitFunction).EvaluateGradient(info.Xs, info.Parameters, info.DYs); // copy the evaluation result to the output array (interleaved) for (int k = 0; k < info.DependentVariablesInUse.Length; ++k) { for (int l = 0; l < info.Parameters.Length; ++l) { int idx = info.ParameterMapping[l]; if (idx >= 0) { outputValues[outputValuesPointer + idx] += info.DYs[info.DependentVariablesInUse[k]][l]; } } outputValuesPointer += parameter.Length; // increase output pointer only by the varying (!) number of parameters } } } }
/// <summary> /// Calculates the fitting values. /// </summary> /// <param name="parameter">The parameter used to calculate the values.</param> /// <param name="outputValues">You must provide an array to hold the calculated values. Size of the array must be /// at least <see cref="NumberOfData" />.</param> /// <param name="calculateUnusedDependentVariablesAlso">If <c>true</c>, the unused dependent variables are also calculated (and plotted).</param> /// <remarks>The values of the fit elements are stored in the order from element_0 to element_n. If there is more /// than one used dependent variable per fit element, the output values are stored in interleaved order. /// </remarks> public void EvaluateFitValues(double[] parameter, double[] outputValues, bool calculateUnusedDependentVariablesAlso) { int outputValuesPointer = 0; for (int ele = 0; ele < _cachedFitElementInfo.Length; ele++) { CachedFitElementInfo info = _cachedFitElementInfo[ele]; FitElement fitEle = _fitEnsemble[ele]; // copy of the parameter to the temporary array for (int i = 0; i < info.Parameters.Length; i++) { int idx = info.ParameterMapping[i]; info.Parameters[i] = idx >= 0 ? parameter[idx] : _constantParameters[-1 - idx]; } IAscendingIntegerCollection validRows = info.ValidRows; int numValidRows = validRows.Count; // Evaluate the function for all points for (int i = 0; i < numValidRows; ++i) { for (int k = info.Xs.Length - 1; k >= 0; k--) { info.Xs[k] = fitEle.IndependentVariables(k)[validRows[i]]; } fitEle.FitFunction.Evaluate(info.Xs, info.Parameters, info.Ys); if (calculateUnusedDependentVariablesAlso) { // copy the evaluation result to the output array (interleaved) for (int k = 0; k < fitEle.NumberOfDependentVariables; ++k) { outputValues[outputValuesPointer++] = info.Ys[k]; } } else { // copy the evaluation result to the output array (interleaved) for (int k = 0; k < info.DependentVariablesInUse.Length; ++k) { outputValues[outputValuesPointer++] = info.Ys[info.DependentVariablesInUse[k]]; } } } } }
/// <summary> /// Stores the dependent values of all elements in an array. The data /// are stored from FitElement_0 to FitElement_n. For FitElements with more than one dependent /// variable in use, the data are stored interleaved. /// </summary> /// <param name="values">The array used to store the values.</param> public void GetDependentValues(double[] values) { int outputValuesPointer = 0; for (int ele = 0; ele < _cachedFitElementInfo.Length; ele++) { CachedFitElementInfo info = _cachedFitElementInfo[ele]; FitElement fitEle = _fitEnsemble[ele]; IAscendingIntegerCollection validRows = info.ValidRows; int numValidRows = validRows.Count; // Evaluate the function for all points for (int i = 0; i < numValidRows; ++i) { for (int j = 0; j < info.DependentVariablesInUse.Length; ++j) { values[outputValuesPointer++] = fitEle.DependentVariables(info.DependentVariablesInUse[j])[validRows[i]]; } } } }
/// <summary> /// Internal function to set up the cached data for the fitting procedure. /// </summary> /// <param name="paraSet">The set of parameters (the information which parameters are fixed is mainly used here).</param> private void CalculateCachedData(ParameterSet paraSet) { // Preparation: Store the parameter names by name and index, and store // all parameter values in _constantParameters System.Collections.Hashtable paraNames = new System.Collections.Hashtable(); System.Collections.Hashtable varyingParaNames = new System.Collections.Hashtable(); _constantParameters = new double[paraSet.Count]; int numberOfVaryingParameters = 0; for (int i = 0; i < paraSet.Count; ++i) { paraNames.Add(paraSet[i].Name, i); _constantParameters[i] = paraSet[i].Parameter; if (paraSet[i].Vary) ++numberOfVaryingParameters; } _cachedVaryingParameters = new double[numberOfVaryingParameters]; for (int i = 0, k = 0; i < paraSet.Count; ++i) { if (paraSet[i].Vary) { varyingParaNames.Add(paraSet[i].Name, k); _cachedVaryingParameters[k++] = paraSet[i].Parameter; } } _cachedNumberOfData = 0; _cachedFitElementInfo = new CachedFitElementInfo[_fitEnsemble.Count]; for (int i = 0; i < _fitEnsemble.Count; i++) { CachedFitElementInfo info = new CachedFitElementInfo(); _cachedFitElementInfo[i] = info; FitElement fitEle = _fitEnsemble[i]; info.ValidRows = fitEle.CalculateValidNumericRows(); info.Xs = new double[fitEle.NumberOfIndependentVariables]; info.Parameters = new double[fitEle.NumberOfParameters]; info.Ys = new double[fitEle.NumberOfDependentVariables]; // Calculate the number of used variables int numVariablesUsed = 0; for (int j = 0; j < fitEle.NumberOfDependentVariables; ++j) { if (fitEle.DependentVariables(j) != null) ++numVariablesUsed; } info.DependentVariablesInUse = new int[numVariablesUsed]; for (int j = 0, used = 0; j < fitEle.NumberOfDependentVariables; ++j) { if (fitEle.DependentVariables(j) != null) info.DependentVariablesInUse[used++] = j; } // calculate the total number of data points _cachedNumberOfData += numVariablesUsed * info.ValidRows.Count; // now create the parameter mapping info.ParameterMapping = new int[fitEle.NumberOfParameters]; for (int j = 0; j < info.ParameterMapping.Length; ++j) { if (!paraNames.Contains(fitEle.ParameterName(j))) throw new ArgumentException(string.Format("ParameterSet does not contain parameter {0}, which is used by function[{1}]", fitEle.ParameterName(j), i)); int idx = (int)paraNames[fitEle.ParameterName(j)]; if (paraSet[idx].Vary) { info.ParameterMapping[j] = (int)varyingParaNames[fitEle.ParameterName(j)]; } else { info.ParameterMapping[j] = -idx - 1; } } } _cachedDependentValues = new double[_cachedNumberOfData]; GetDependentValues(_cachedDependentValues); if (this.HasToUseWeights()) { _cachedWeights = new double[_cachedNumberOfData]; GetWeights(_cachedWeights); } else _cachedWeights = null; }
/// <summary> /// Internal function to set up the cached data for the fitting procedure. /// </summary> /// <param name="paraSet">The set of parameters (the information which parameters are fixed is mainly used here).</param> private void CalculateCachedData(ParameterSet paraSet) { // Preparation: Store the parameter names by name and index, and store // all parameter values in _constantParameters var paraNames = new System.Collections.Hashtable(); var varyingParaNames = new System.Collections.Hashtable(); _constantParameters = new double[paraSet.Count]; int numberOfVaryingParameters = 0; for (int i = 0; i < paraSet.Count; ++i) { paraNames.Add(paraSet[i].Name, i); _constantParameters[i] = paraSet[i].Parameter; if (paraSet[i].Vary) { ++numberOfVaryingParameters; } } _cachedVaryingParameters = new double[numberOfVaryingParameters]; for (int i = 0, k = 0; i < paraSet.Count; ++i) { if (paraSet[i].Vary) { varyingParaNames.Add(paraSet[i].Name, k); _cachedVaryingParameters[k++] = paraSet[i].Parameter; } } _cachedNumberOfData = 0; _cachedFitElementInfo = new CachedFitElementInfo[_fitEnsemble.Count]; for (int i = 0; i < _fitEnsemble.Count; i++) { var info = new CachedFitElementInfo(); _cachedFitElementInfo[i] = info; FitElement fitEle = _fitEnsemble[i]; info.ValidRows = fitEle.CalculateValidNumericRows(); info.Xs = new double[fitEle.NumberOfIndependentVariables]; info.Parameters = new double[fitEle.NumberOfParameters]; info.Ys = new double[fitEle.NumberOfDependentVariables]; // Calculate the number of used variables int numVariablesUsed = 0; for (int j = 0; j < fitEle.NumberOfDependentVariables; ++j) { if (fitEle.DependentVariables(j) != null) { ++numVariablesUsed; } } info.DependentVariablesInUse = new int[numVariablesUsed]; for (int j = 0, used = 0; j < fitEle.NumberOfDependentVariables; ++j) { if (fitEle.DependentVariables(j) != null) { info.DependentVariablesInUse[used++] = j; } } // calculate the total number of data points _cachedNumberOfData += numVariablesUsed * info.ValidRows.Count; // now create the parameter mapping info.ParameterMapping = new int[fitEle.NumberOfParameters]; for (int j = 0; j < info.ParameterMapping.Length; ++j) { if (!paraNames.Contains(fitEle.ParameterName(j))) { throw new ArgumentException(string.Format("ParameterSet does not contain parameter {0}, which is used by function[{1}]", fitEle.ParameterName(j), i)); } int idx = (int)paraNames[fitEle.ParameterName(j)]; if (paraSet[idx].Vary) { info.ParameterMapping[j] = (int)varyingParaNames[fitEle.ParameterName(j)]; } else { info.ParameterMapping[j] = -idx - 1; } } } _cachedDependentValues = new double[_cachedNumberOfData]; GetDependentValues(_cachedDependentValues); if (HasToUseWeights()) { _cachedWeights = new double[_cachedNumberOfData]; GetWeights(_cachedWeights); } else { _cachedWeights = null; } }