/*-
* Copyright (c) 2015 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package uk.ac.diamond.scisoft.analysis.fitting.functions;
import org.eclipse.dawnsci.analysis.api.fitting.functions.IParameter;
import org.eclipse.january.dataset.DoubleDataset;
/**
* Class to provide a Fano resonance profile
*/
public class Fano extends AFunction {
private static final String NAME = "Fano";
private static final String DESC = "A Fano resonance profile."
+ "\n y(x) = sigma [ q w / 2 + (x-r) ]^2 / [ w^2/4 + (x-r)^2 ]"
+ "\nwhere r is resonant energy, the phase of the scattering amplitude"
+ "\nchanges by pi within 2*w of the resonant energy,"
+ "\nsigma is the resonant cross-section,"
+ "\nand q is the Fano parameter that measure the ratio of resonant scattering"
+ "\nto direct (background) scattering.";
private static final String[] PARAM_NAMES = new String[] {"r", "w", "sigma", "q"};
private static final double[] PARAMS = new double[] {0, 1, 2, 1};
public Fano() {
this(PARAMS);
}
/**
* Constructor which takes the four parameters required, which are
*
* <pre>
* r - resonant energy
* w - line width
* sigma - cross-section
* q - Fano parameter
* </pre>
*
* @param params
*/
public Fano(double... params) {
super(PARAMS.length);
if (params.length != PARAMS.length) {
throw new IllegalArgumentException("A Fano profile requires 4 parameters, and it has been given " + params.length);
}
setParameterValues(params);
}
public Fano(IParameter... params) {
super(PARAMS.length);
if (params.length != PARAMS.length) {
throw new IllegalArgumentException("A Fano profile requires 4 parameters, and it has been given " + params.length);
}
setParameters(params);
}
@Override
protected void setNames() {
setNames(NAME, DESC, PARAM_NAMES);
}
private transient double r, d, sigma, q;
protected void calcCachedParameters() {
r = getParameterValue(0);
d = getParameterValue(1) / 2.;
sigma = getParameterValue(2);
q = getParameterValue(3);
setDirty(false);
}
@Override
public double val(double... values) {
if (isDirty())
calcCachedParameters();
double arg = (values[0] - r) / d;
double num = q + arg;
return sigma * num * num /(1 + arg * arg);
}
@Override
public void fillWithValues(DoubleDataset data, CoordinatesIterator it) {
if (isDirty())
calcCachedParameters();
it.reset();
double[] coords = it.getCoordinates();
int i = 0;
double[] buffer = data.getData();
while (it.hasNext()) {
double arg = (coords[0] - r) / d;
double num = q + arg;
buffer[i++] = sigma * num * num /(1 + arg * arg);
}
}
}