/*-
* Copyright (c) 2013 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.IOperator;
import org.eclipse.dawnsci.analysis.api.fitting.functions.IParameter;
import org.eclipse.dawnsci.analysis.dataset.impl.Signal;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.DatasetFactory;
import org.eclipse.january.dataset.DatasetUtils;
import org.eclipse.january.dataset.DoubleDataset;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.Slice;
/**
* Convolve two functions where the second function is the kernel
*/
public class Convolve extends ABinaryOperator implements IOperator {
private static final String NAME = "Convolve";
private static final String DESC = "Convolve one function with a kernel";
public Convolve() {
super();
name = NAME;
description = DESC;
}
@Override
protected void setNames() {
setNames(NAME, DESC);
}
@Override
public double val(double... values) {
DoubleDataset v = calculateValues(DatasetFactory.createFromObject(values.length, Dataset.ARRAYFLOAT64, values, 1));
return v.getAbs(0);
}
@Override
public void fillWithValues(DoubleDataset data, CoordinatesIterator it) {
if (fa == null || fb == null)
return;
IDataset[] values = it.getValues();
DoubleDataset da = (DoubleDataset) DatasetUtils.cast(fa.calculateValues(values), Dataset.FLOAT64);
Dataset db = DatasetUtils.cast(fb.calculateValues(values), Dataset.FLOAT64);
data.setSlice(calcConvolution(da, db));
}
private static Dataset calcConvolution(DoubleDataset signal, Dataset kernel) {
int l = signal.getSize();
DoubleDataset padded = DatasetFactory.zeros(DoubleDataset.class, 2*l - 1);
int hl = l/2;
padded.setSlice(signal.getAbs(0), new Slice(0, hl));
padded.setSlice(signal, new Slice(hl, hl + l));
padded.setSlice(signal.getAbs(l - 1), new Slice(hl + l, null));
kernel.idivide(kernel.sum());
return Signal.convolveForOverlap(padded, kernel, null);
}
@Override
public void fillWithPartialDerivativeValues(IParameter parameter, DoubleDataset data, CoordinatesIterator it) {
if (fa == null || fb == null)
return;
final IDataset[] values = it.getValues();
DoubleDataset da = (DoubleDataset) DatasetUtils.cast(fa.calculatePartialDerivativeValues(parameter, values), Dataset.FLOAT64);
Dataset db = DatasetUtils.cast(fb.calculateValues(values), Dataset.FLOAT64);
data.setSlice(calcConvolution(da, db));
da = (DoubleDataset) DatasetUtils.cast(fa.calculateValues(values), Dataset.FLOAT64);
db = DatasetUtils.cast(fb.calculatePartialDerivativeValues(parameter, values), Dataset.FLOAT64);
data.iadd(calcConvolution(da, db));
}
}