package cz.cuni.lf1.lge.ThunderSTORM.estimators;
import cz.cuni.lf1.lge.ThunderSTORM.estimators.PSF.BiplaneEllipticGaussianPSF;
import cz.cuni.lf1.lge.ThunderSTORM.estimators.PSF.MoleculeDescriptor;
import cz.cuni.lf1.lge.ThunderSTORM.estimators.PSF.PSFModel;
import org.apache.commons.math3.analysis.MultivariateFunction;
import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
import org.apache.commons.math3.analysis.MultivariateVectorFunction;
import java.util.Arrays;
public class LsqMleBiplaneFunctions implements ILsqFunctions, IMleFunctions {
BiplaneEllipticGaussianPSF psfModel;
SubImage plane1;
SubImage plane2;
public LsqMleBiplaneFunctions(PSFModel psfModel, SubImage plane1, SubImage plane2) {
assert (psfModel != null);
assert (plane1 != null);
assert (plane2 != null);
if (!(psfModel instanceof BiplaneEllipticGaussianPSF)) {
throw new ClassCastException("Can't use this PSF model!");
}
this.psfModel = (BiplaneEllipticGaussianPSF) psfModel;
this.plane1 = plane1;
this.plane2 = plane2;
}
@Override
public double[] getInitialParams() {
return psfModel.getInitialParams(plane1, plane2);
}
@Override
public MultivariateVectorFunction getValueFunction() {
return psfModel.getValueFunction(plane1.xgrid, plane1.ygrid, plane2.xgrid, plane2.ygrid);
}
@Override
public MultivariateFunction getLikelihoodFunction() {
return psfModel.getLikelihoodFunction(plane1.xgrid, plane1.ygrid, plane1.values, plane2.xgrid, plane2.ygrid, plane2.values);
}
@Override
public MultivariateMatrixFunction getJacobianFunction() {
return psfModel.getJacobianFunction(plane1.xgrid, plane1.ygrid, plane2.xgrid, plane2.ygrid);
}
@Override
public double[] calcWeights(boolean useWeighting) {
double[] weights = new double[plane1.values.length + plane2.values.length];
if(!useWeighting){
Arrays.fill(weights, 1);
} else {
double minWeight = 1.0 / Math.max(plane1.getMax(), plane2.getMax());
double maxWeight = 1000 * minWeight;
int index = 0;
for (int i = 0; i < plane1.values.length; i++, index++) {
double weight = 1 / plane1.values[i];
if (Double.isInfinite(weight) || Double.isNaN(weight) || weight > maxWeight) {
weight = maxWeight;
}
weights[index] = weight;
}
for (int i = 0; i < plane2.values.length; i++, index++) {
double weight = 1 / plane2.values[i];
if (Double.isInfinite(weight) || Double.isNaN(weight) || weight > maxWeight) {
weight = maxWeight;
}
weights[index] = weight;
}
}
return weights;
}
@Override
public double[] getObservations() {
double[] observations = new double[plane1.values.length + plane2.values.length];
int index = 0;
for (int i = 0; i < plane1.values.length; i++, index++) {
observations[index] = plane1.values[i];
}
for (int i = 0; i < plane2.values.length; i++, index++) {
observations[index] = plane2.values[i];
}
return observations;
}
@Override
public MoleculeDescriptor.Units getImageUnits() {
return plane1.units;
}
}