Fixed fit internals
This commit is contained in:
parent
60bddaa50c
commit
53aad7f6a4
@ -20,16 +20,16 @@ import hep.dataforge.plots.PlotFrame
|
|||||||
import hep.dataforge.plots.XYFunctionPlot
|
import hep.dataforge.plots.XYFunctionPlot
|
||||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||||
import hep.dataforge.stat.fit.ParamSet
|
import hep.dataforge.stat.fit.ParamSet
|
||||||
import inr.numass.models.LossCalculator
|
import inr.numass.models.misc.LossCalculator
|
||||||
import org.apache.commons.math3.analysis.UnivariateFunction
|
import org.apache.commons.math3.analysis.UnivariateFunction
|
||||||
import org.apache.commons.math3.analysis.solvers.BisectionSolver
|
import org.apache.commons.math3.analysis.solvers.BisectionSolver
|
||||||
|
|
||||||
ParamSet params = new ParamSet()
|
ParamSet params = new ParamSet()
|
||||||
.setParValue("exPos", 12.76)
|
.setParValue("exPos", 12.76)
|
||||||
.setParValue("ionPos", 13.95)
|
.setParValue("ionPos", 13.95)
|
||||||
.setParValue("exW", 1.2)
|
.setParValue("exW", 1.2)
|
||||||
.setParValue("ionW", 13.5)
|
.setParValue("ionW", 13.5)
|
||||||
.setParValue("exIonRatio", 4.55)
|
.setParValue("exIonRatio", 4.55)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ UnivariateIntegrator integrator = NumassContext.defaultIntegrator;
|
|||||||
|
|
||||||
double border = 13.6;
|
double border = 13.6;
|
||||||
|
|
||||||
UnivariateFunction ratioFunction = {e->integrator.integrate(0, e, scatterFunction) / integrator.integrate(e, 100, scatterFunction)}
|
UnivariateFunction ratioFunction = { e -> integrator.integrate(0, e, scatterFunction) / integrator.integrate(e, 100, scatterFunction) }
|
||||||
|
|
||||||
double ratio = ratioFunction.value(border);
|
double ratio = ratioFunction.value(border);
|
||||||
println "The true excitation to ionization ratio with border energy $border is $ratio";
|
println "The true excitation to ionization ratio with border energy $border is $ratio";
|
||||||
@ -54,35 +54,35 @@ double resolution = 1.5d;
|
|||||||
|
|
||||||
def X = 0.527;
|
def X = 0.527;
|
||||||
|
|
||||||
LossCalculator calculator = new LossCalculator();
|
LossCalculator calculator = LossCalculator.INSTANCE;
|
||||||
|
|
||||||
List<Double> lossProbs = calculator.getGunLossProbabilities(X);
|
List<Double> lossProbs = calculator.getGunLossProbabilities(X);
|
||||||
|
|
||||||
UnivariateFunction newScatterFunction = { double d ->
|
UnivariateFunction newScatterFunction = { double d ->
|
||||||
double res = scatterFunction.value(d);
|
double res = scatterFunction.value(d);
|
||||||
for(i = 1; i < lossProbs.size(); i++){
|
for (i = 1; i < lossProbs.size(); i++) {
|
||||||
res += lossProbs.get(i) * calculator.getLossValue(i, d, 0);
|
res += lossProbs.get(i) * calculator.getLossValue(i, d, 0);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UnivariateFunction resolutionValue = {double e ->
|
UnivariateFunction resolutionValue = { double e ->
|
||||||
if (e <= 0d) {
|
if (e <= 0d) {
|
||||||
return 0d;
|
return 0d;
|
||||||
} else if (e >= resolution) {
|
} else if (e >= resolution) {
|
||||||
return 1d;
|
return 1d;
|
||||||
} else {
|
} else {
|
||||||
return e/resolution;
|
return e / resolution;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
UnivariateFunction integral = {double u ->
|
UnivariateFunction integral = { double u ->
|
||||||
if(u <= 0d){
|
if (u <= 0d) {
|
||||||
return 0d;
|
return 0d;
|
||||||
} else {
|
} else {
|
||||||
UnivariateFunction integrand = {double e -> resolutionValue.value(u-e) * newScatterFunction.value(e)};
|
UnivariateFunction integrand = { double e -> resolutionValue.value(u - e) * newScatterFunction.value(e) };
|
||||||
return integrator.integrate(0d, u, integrand)
|
return integrator.integrate(0d, u, integrand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,9 +92,9 @@ frame.add(XYFunctionPlot.plotFunction("integral", integral, 0, 100, 800));
|
|||||||
|
|
||||||
BisectionSolver solver = new BisectionSolver(1e-3);
|
BisectionSolver solver = new BisectionSolver(1e-3);
|
||||||
|
|
||||||
UnivariateFunction integralShifted = {u ->
|
UnivariateFunction integralShifted = { u ->
|
||||||
def integr = integral.value(u);
|
def integr = integral.value(u);
|
||||||
return integr/(1-integr) - ratio;
|
return integr / (1 - integr) - ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
double integralBorder = solver.solve(400, integralShifted, 10d, 20d);
|
double integralBorder = solver.solve(400, integralShifted, 10d, 20d);
|
||||||
@ -104,6 +104,6 @@ println "The integral border is $integralBorder";
|
|||||||
double newBorder = 14.43
|
double newBorder = 14.43
|
||||||
double integralValue = integral.value(newBorder);
|
double integralValue = integral.value(newBorder);
|
||||||
|
|
||||||
double err = Math.abs(integralValue/(1-integralValue)/ratio - 1d)
|
double err = Math.abs(integralValue / (1 - integralValue) / ratio - 1d)
|
||||||
|
|
||||||
println "The relative error ic case of using $newBorder instead of real one is $err";
|
println "The relative error ic case of using $newBorder instead of real one is $err";
|
@ -8,7 +8,6 @@ package inr.numass.scripts
|
|||||||
|
|
||||||
import hep.dataforge.maths.integration.GaussRuleIntegrator
|
import hep.dataforge.maths.integration.GaussRuleIntegrator
|
||||||
import hep.dataforge.maths.integration.UnivariateIntegrator
|
import hep.dataforge.maths.integration.UnivariateIntegrator
|
||||||
import inr.numass.models.LossCalculator
|
|
||||||
import org.apache.commons.math3.analysis.UnivariateFunction
|
import org.apache.commons.math3.analysis.UnivariateFunction
|
||||||
|
|
||||||
UnivariateIntegrator integrator = new GaussRuleIntegrator(400);
|
UnivariateIntegrator integrator = new GaussRuleIntegrator(400);
|
||||||
|
@ -6,9 +6,10 @@
|
|||||||
|
|
||||||
package inr.numass.scripts
|
package inr.numass.scripts
|
||||||
|
|
||||||
import inr.numass.models.LossCalculator
|
import inr.numass.models.misc.LossCalculator
|
||||||
|
|
||||||
LossCalculator loss = LossCalculator.instance()
|
|
||||||
|
LossCalculator loss = LossCalculator.INSTANCE
|
||||||
|
|
||||||
def X = 0.36
|
def X = 0.36
|
||||||
|
|
||||||
|
@ -15,12 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package inr.numass.scripts
|
package inr.numass.scripts
|
||||||
|
|
||||||
import hep.dataforge.stat.fit.FitManager
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.stat.fit.FitState
|
import hep.dataforge.io.FittingIOUtils
|
||||||
import hep.dataforge.stat.fit.MINUITPlugin
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.stat.fit.ParamSet
|
import hep.dataforge.stat.fit.*
|
||||||
import hep.dataforge.stat.models.XYModel
|
import hep.dataforge.stat.models.XYModel
|
||||||
import hep.dataforge.tables.ListTable
|
|
||||||
import inr.numass.data.SpectrumAdapter
|
import inr.numass.data.SpectrumAdapter
|
||||||
import inr.numass.data.SpectrumGenerator
|
import inr.numass.data.SpectrumGenerator
|
||||||
import inr.numass.models.BetaSpectrum
|
import inr.numass.models.BetaSpectrum
|
||||||
@ -30,7 +29,6 @@ import inr.numass.models.ResolutionFunction
|
|||||||
import inr.numass.utils.DataModelUtils
|
import inr.numass.utils.DataModelUtils
|
||||||
import org.apache.commons.math3.analysis.BivariateFunction
|
import org.apache.commons.math3.analysis.BivariateFunction
|
||||||
|
|
||||||
import static hep.dataforge.context.Global.out
|
|
||||||
import static java.util.Locale.setDefault
|
import static java.util.Locale.setDefault
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,7 +39,8 @@ import static java.util.Locale.setDefault
|
|||||||
setDefault(Locale.US);
|
setDefault(Locale.US);
|
||||||
new MINUITPlugin().startGlobal();
|
new MINUITPlugin().startGlobal();
|
||||||
|
|
||||||
FitManager fm = new FitManager();
|
FitManager fm = Global.INSTANCE.get(FitManager)
|
||||||
|
|
||||||
|
|
||||||
BivariateFunction resolution = new ResolutionFunction(8.3e-5);
|
BivariateFunction resolution = new ResolutionFunction(8.3e-5);
|
||||||
|
|
||||||
@ -49,16 +48,16 @@ ModularSpectrum beta = new ModularSpectrum(new BetaSpectrum(), resolution, 13490
|
|||||||
beta.setCaching(false);
|
beta.setCaching(false);
|
||||||
|
|
||||||
NBkgSpectrum spectrum = new NBkgSpectrum(beta);
|
NBkgSpectrum spectrum = new NBkgSpectrum(beta);
|
||||||
XYModel model = new XYModel("tritium", spectrum, new SpectrumAdapter());
|
XYModel model = new XYModel(Meta.empty(), new SpectrumAdapter(Meta.empty()), spectrum);
|
||||||
|
|
||||||
ParamSet allPars = new ParamSet();
|
ParamSet allPars = new ParamSet();
|
||||||
|
|
||||||
|
|
||||||
allPars.setPar("N", 6e5, 10, 0, Double.POSITIVE_INFINITY);
|
allPars.setPar("N", 6e5, 10, 0, Double.POSITIVE_INFINITY);
|
||||||
|
|
||||||
allPars.setPar("bkg", 2d, 0.1 );
|
allPars.setPar("bkg", 2d, 0.1);
|
||||||
|
|
||||||
allPars.setPar("E0", 18575.0, 0.05 );
|
allPars.setPar("E0", 18575.0, 0.05);
|
||||||
|
|
||||||
allPars.setPar("mnu2", 0, 1);
|
allPars.setPar("mnu2", 0, 1);
|
||||||
|
|
||||||
@ -74,7 +73,7 @@ allPars.setPar("trap", 0, 0.01, 0d, Double.POSITIVE_INFINITY);
|
|||||||
|
|
||||||
SpectrumGenerator generator = new SpectrumGenerator(model, allPars, 12316);
|
SpectrumGenerator generator = new SpectrumGenerator(model, allPars, 12316);
|
||||||
|
|
||||||
ListTable data = generator.generateData(DataModelUtils.getUniformSpectrumConfiguration(14000d, 18200, 1e6, 60));
|
def data = generator.generateData(DataModelUtils.getUniformSpectrumConfiguration(14000d, 18200, 1e6, 60));
|
||||||
|
|
||||||
// data = data.filter("X", Value.of(15510.0), Value.of(18610.0));
|
// data = data.filter("X", Value.of(15510.0), Value.of(18610.0));
|
||||||
allPars.setParValue("U2", 0);
|
allPars.setParValue("U2", 0);
|
||||||
@ -87,14 +86,14 @@ FitState state = new FitState(data, model, allPars);
|
|||||||
// 1-delta*(E-U);
|
// 1-delta*(E-U);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
resolution.setTailFunction(ResolutionFunction.getRealTail())
|
//resolution.setTailFunction(ResolutionFunction.getRealTail())
|
||||||
|
|
||||||
//PlotFrame frame = JFreeChartFrame.drawFrame("Transmission function", null);
|
//PlotFrame frame = JFreeChartFrame.drawFrame("Transmission function", null);
|
||||||
//frame.add(new PlottableFunction("transmission",null, {U -> resolution.value(18500,U)},13500,18505,500));
|
//frame.add(new PlottableFunction("transmission",null, {U -> resolution.value(18500,U)},13500,18505,500));
|
||||||
|
|
||||||
FitState res = fm.runTask(state, "QOW", FitTask.TASK_RUN, "N", "bkg", "E0", "U2", "trap");
|
def res = fm.runStage(state, "QOW", FitStage.TASK_RUN, "N", "bkg", "E0", "U2", "trap");
|
||||||
|
|
||||||
|
|
||||||
|
res.printState(new PrintWriter(System.out))
|
||||||
|
|
||||||
res.print(out());
|
FittingIOUtils.printResiduals(new PrintWriter(System.out), res.optState().get())
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import hep.dataforge.maths.integration.GaussRuleIntegrator;
|
|||||||
import hep.dataforge.maths.integration.UnivariateIntegrator;
|
import hep.dataforge.maths.integration.UnivariateIntegrator;
|
||||||
import hep.dataforge.stat.parametric.AbstractParametricFunction;
|
import hep.dataforge.stat.parametric.AbstractParametricFunction;
|
||||||
import hep.dataforge.values.Values;
|
import hep.dataforge.values.Values;
|
||||||
|
import inr.numass.models.misc.LossCalculator;
|
||||||
import org.apache.commons.math3.analysis.BivariateFunction;
|
import org.apache.commons.math3.analysis.BivariateFunction;
|
||||||
import org.apache.commons.math3.analysis.UnivariateFunction;
|
import org.apache.commons.math3.analysis.UnivariateFunction;
|
||||||
|
|
||||||
@ -59,11 +60,9 @@ public class EmpiricalLossSpectrum extends AbstractParametricFunction {
|
|||||||
final double shift = set.getDouble("shift");
|
final double shift = set.getDouble("shift");
|
||||||
|
|
||||||
//FIXME тут толщины усреднены по длине источника, а надо брать чистого Пуассона
|
//FIXME тут толщины усреднены по длине источника, а надо брать чистого Пуассона
|
||||||
final List<Double> probs = LossCalculator.instance().getGunLossProbabilities(X);
|
final List<Double> probs = LossCalculator.INSTANCE.getGunLossProbabilities(X);
|
||||||
final double noLossProb = probs.get(0);
|
final double noLossProb = probs.get(0);
|
||||||
final BivariateFunction lossFunction = (Ei, Ef) -> {
|
final BivariateFunction lossFunction = (Ei, Ef) -> LossCalculator.INSTANCE.getLossValue(probs, Ei, Ef);
|
||||||
return LossCalculator.instance().getLossValue(probs, Ei, Ef);
|
|
||||||
};
|
|
||||||
UnivariateFunction integrand = (double x) -> transmission.value(x) * lossFunction.value(x, U - shift);
|
UnivariateFunction integrand = (double x) -> transmission.value(x) * lossFunction.value(x, U - shift);
|
||||||
return noLossProb * transmission.value(U - shift) + integrator.integrate(U, eMax, integrand);
|
return noLossProb * transmission.value(U - shift) + integrator.integrate(U, eMax, integrand);
|
||||||
}
|
}
|
||||||
|
@ -1,442 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Alexander Nozik.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package inr.numass.models;
|
|
||||||
|
|
||||||
import hep.dataforge.maths.functions.FunctionCaching;
|
|
||||||
import hep.dataforge.maths.integration.GaussRuleIntegrator;
|
|
||||||
import hep.dataforge.maths.integration.UnivariateIntegrator;
|
|
||||||
import hep.dataforge.plots.PlotFrame;
|
|
||||||
import hep.dataforge.plots.XYFunctionPlot;
|
|
||||||
import hep.dataforge.utils.Misc;
|
|
||||||
import hep.dataforge.values.Values;
|
|
||||||
import org.apache.commons.math3.analysis.BivariateFunction;
|
|
||||||
import org.apache.commons.math3.analysis.UnivariateFunction;
|
|
||||||
import org.apache.commons.math3.exception.OutOfRangeException;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static java.lang.Math.exp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Вычисление произвольного порядка функции рассеяния. Не учитывается
|
|
||||||
* зависимость сечения от энергии электрона
|
|
||||||
*
|
|
||||||
* @author Darksnake
|
|
||||||
*/
|
|
||||||
public class LossCalculator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* порог по вероятности, до которого вычисляются компоненты функции потерь
|
|
||||||
*/
|
|
||||||
public final static double SCATTERING_PROBABILITY_THRESHOLD = 1e-3;
|
|
||||||
|
|
||||||
private static final LossCalculator instance = new LossCalculator();
|
|
||||||
private static final UnivariateIntegrator integrator = new GaussRuleIntegrator(100);
|
|
||||||
private static final Map<Double, List<Double>> lossProbCache = Misc.getLRUCache(100);
|
|
||||||
private final Map<Integer, UnivariateFunction> cache = new HashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private LossCalculator() {
|
|
||||||
cache.put(1, getSingleScatterFunction());
|
|
||||||
// immutable.put(2, getDoubleScatterFunction());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UnivariateFunction getSingleScatterFunction() {
|
|
||||||
final double A1 = 0.204;
|
|
||||||
final double A2 = 0.0556;
|
|
||||||
final double b = 14.0;
|
|
||||||
final double pos1 = 12.6;
|
|
||||||
final double pos2 = 14.3;
|
|
||||||
final double w1 = 1.85;
|
|
||||||
final double w2 = 12.5;
|
|
||||||
|
|
||||||
return (double eps) -> {
|
|
||||||
if (eps <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (eps <= b) {
|
|
||||||
double z = eps - pos1;
|
|
||||||
return A1 * exp(-2 * z * z / w1 / w1);
|
|
||||||
} else {
|
|
||||||
double z = 4 * (eps - pos2) * (eps - pos2);
|
|
||||||
return A2 / (1 + z / w2 / w2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A generic loss function for numass experiment in "Lobashev"
|
|
||||||
* parameterization
|
|
||||||
*
|
|
||||||
* @param exPos
|
|
||||||
* @param ionPos
|
|
||||||
* @param exW
|
|
||||||
* @param ionW
|
|
||||||
* @param exIonRatio
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static UnivariateFunction getSingleScatterFunction(
|
|
||||||
final double exPos,
|
|
||||||
final double ionPos,
|
|
||||||
final double exW,
|
|
||||||
final double ionW,
|
|
||||||
final double exIonRatio) {
|
|
||||||
UnivariateFunction func = (double eps) -> {
|
|
||||||
if (eps <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
double z1 = eps - exPos;
|
|
||||||
double ex = exIonRatio * exp(-2 * z1 * z1 / exW / exW);
|
|
||||||
|
|
||||||
double z = 4 * (eps - ionPos) * (eps - ionPos);
|
|
||||||
double ion = 1 / (1 + z / ionW / ionW);
|
|
||||||
|
|
||||||
double res;
|
|
||||||
if (eps < exPos) {
|
|
||||||
res = ex;
|
|
||||||
} else {
|
|
||||||
res = Math.max(ex, ion);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
double cutoff = 25d;
|
|
||||||
//caclulating lorentz integral analythically
|
|
||||||
double tailNorm = (Math.atan((ionPos - cutoff) * 2d / ionW) + 0.5 * Math.PI) * ionW / 2d;
|
|
||||||
final double norm = integrator.integrate(0d, cutoff, func) + tailNorm;
|
|
||||||
return (e) -> func.value(e) / norm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UnivariateFunction getSingleScatterFunction(Values set) {
|
|
||||||
|
|
||||||
final double exPos = set.getDouble("exPos");
|
|
||||||
final double ionPos = set.getDouble("ionPos");
|
|
||||||
final double exW = set.getDouble("exW");
|
|
||||||
final double ionW = set.getDouble("ionW");
|
|
||||||
final double exIonRatio = set.getDouble("exIonRatio");
|
|
||||||
|
|
||||||
return getSingleScatterFunction(exPos, ionPos, exW, ionW, exIonRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BivariateFunction getTrapFunction() {
|
|
||||||
return (double Ei, double Ef) -> {
|
|
||||||
double eps = Ei - Ef;
|
|
||||||
if (eps > 10) {
|
|
||||||
return 1.86e-04 * exp(-eps / 25.0) + 5.5e-05;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Синглетон, так как кэши функций потреь можно вычислять один раз
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static LossCalculator instance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void plotScatter(PlotFrame frame, Values set) {
|
|
||||||
//"X", "shift", "exPos", "ionPos", "exW", "ionW", "exIonRatio"
|
|
||||||
|
|
||||||
// JFreeChartFrame frame = JFreeChartFrame.drawFrame("Differential scattering crosssection", null);
|
|
||||||
double X = set.getDouble("X");
|
|
||||||
|
|
||||||
final double exPos = set.getDouble("exPos");
|
|
||||||
|
|
||||||
final double ionPos = set.getDouble("ionPos");
|
|
||||||
|
|
||||||
final double exW = set.getDouble("exW");
|
|
||||||
|
|
||||||
final double ionW = set.getDouble("ionW");
|
|
||||||
|
|
||||||
final double exIonRatio = set.getDouble("exIonRatio");
|
|
||||||
|
|
||||||
UnivariateFunction scatterFunction = getSingleScatterFunction(exPos, ionPos, exW, ionW, exIonRatio);
|
|
||||||
|
|
||||||
if (set.getNames().contains("X")) {
|
|
||||||
final LossCalculator loss = LossCalculator.instance;
|
|
||||||
final List<Double> probs = loss.getGunLossProbabilities(set.getDouble("X"));
|
|
||||||
UnivariateFunction single = (double e) -> probs.get(1) * scatterFunction.value(e);
|
|
||||||
frame.add(XYFunctionPlot.Companion.plot("Single scattering", 0, 100, 1000, single::value));
|
|
||||||
|
|
||||||
for (int i = 2; i < probs.size(); i++) {
|
|
||||||
final int j = i;
|
|
||||||
UnivariateFunction scatter = (double e) -> probs.get(j) * loss.getLossValue(j, e, 0d);
|
|
||||||
frame.add(XYFunctionPlot.Companion.plot(j + " scattering", 0, 100, 1000, scatter::value));
|
|
||||||
}
|
|
||||||
|
|
||||||
UnivariateFunction total = (eps) -> {
|
|
||||||
if (probs.size() == 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
double sum = probs.get(1) * scatterFunction.value(eps);
|
|
||||||
for (int i = 2; i < probs.size(); i++) {
|
|
||||||
sum += probs.get(i) * loss.getLossValue(i, eps, 0);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
};
|
|
||||||
|
|
||||||
frame.add(XYFunctionPlot.Companion.plot("Total loss", 0, 100, 1000, total::value));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
frame.add(XYFunctionPlot.Companion.plot("Differential crosssection", 0, 100, 2000, scatterFunction::value));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Double> getGunLossProbabilities(double X) {
|
|
||||||
List<Double> res = new ArrayList<>();
|
|
||||||
double prob;
|
|
||||||
if (X > 0) {
|
|
||||||
prob = Math.exp(-X);
|
|
||||||
} else {
|
|
||||||
// если x ==0, то выживает только нулевой член, первый равен 1
|
|
||||||
res.add(1d);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
res.add(prob);
|
|
||||||
|
|
||||||
int n = 0;
|
|
||||||
while (prob > SCATTERING_PROBABILITY_THRESHOLD) {
|
|
||||||
/*
|
|
||||||
* prob(n) = prob(n-1)*X/n;
|
|
||||||
*/
|
|
||||||
n++;
|
|
||||||
prob *= X / n;
|
|
||||||
res.add(prob);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getGunZeroLossProb(double X) {
|
|
||||||
return Math.exp(-X);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ленивое рекурсивное вычисление функции потерь через предыдущие
|
|
||||||
*
|
|
||||||
* @param order
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private UnivariateFunction getLoss(int order) {
|
|
||||||
if (order <= 0) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
if (cache.containsKey(order)) {
|
|
||||||
return cache.get(order);
|
|
||||||
} else {
|
|
||||||
synchronized (this) {
|
|
||||||
cache.computeIfAbsent(order, (i) -> {
|
|
||||||
LoggerFactory.getLogger(getClass())
|
|
||||||
.debug("Scatter immutable of order {} not found. Updating", i);
|
|
||||||
return getNextLoss(getMargin(i), getLoss(i - 1));
|
|
||||||
});
|
|
||||||
return cache.get(order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BivariateFunction getLossFunction(int order) {
|
|
||||||
assert order > 0;
|
|
||||||
return (double Ei, double Ef) -> getLossValue(order, Ei, Ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Double> getLossProbDerivs(double X) {
|
|
||||||
List<Double> res = new ArrayList<>();
|
|
||||||
List<Double> probs = getLossProbabilities(X);
|
|
||||||
|
|
||||||
double delta = Math.exp(-X);
|
|
||||||
res.add((delta - probs.get(0)) / X);
|
|
||||||
for (int i = 1; i < probs.size(); i++) {
|
|
||||||
delta *= X / i;
|
|
||||||
res.add((delta - probs.get(i)) / X);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* рекурсивно вычисляем все вероятности, котрорые выше порога
|
|
||||||
* <p>
|
|
||||||
* дисер, стр.48
|
|
||||||
* </p>
|
|
||||||
* @param X
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public List<Double> getLossProbabilities(double X) {
|
|
||||||
return lossProbCache.computeIfAbsent(X, x -> {
|
|
||||||
List<Double> res = new ArrayList<>();
|
|
||||||
double prob;
|
|
||||||
if (x > 0) {
|
|
||||||
prob = 1 / x * (1 - Math.exp(-x));
|
|
||||||
} else {
|
|
||||||
// если x ==0, то выживает только нулевой член, первый равен нулю
|
|
||||||
res.add(1d);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
res.add(prob);
|
|
||||||
|
|
||||||
while (prob > SCATTERING_PROBABILITY_THRESHOLD) {
|
|
||||||
/*
|
|
||||||
* prob(n) = prob(n-1)-1/n! * X^n * exp(-X);
|
|
||||||
*/
|
|
||||||
double delta = Math.exp(-x);
|
|
||||||
for (int i = 1; i < res.size() + 1; i++) {
|
|
||||||
delta *= x / i;
|
|
||||||
}
|
|
||||||
prob -= delta / x;
|
|
||||||
res.add(prob);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getLossProbability(int order, double X) {
|
|
||||||
if (order == 0) {
|
|
||||||
if (X > 0) {
|
|
||||||
return 1 / X * (1 - Math.exp(-X));
|
|
||||||
} else {
|
|
||||||
return 1d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<Double> probs = getLossProbabilities(X);
|
|
||||||
if (order >= probs.size()) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return probs.get(order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getLossValue(int order, double Ei, double Ef) {
|
|
||||||
if (Ei - Ef < 5d) {
|
|
||||||
return 0;
|
|
||||||
} else if (Ei - Ef >= getMargin(order)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return getLoss(order).value(Ei - Ef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* функция потерь с произвольными вероятностями рассеяния
|
|
||||||
*
|
|
||||||
* @param probs
|
|
||||||
* @param Ei
|
|
||||||
* @param Ef
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public double getLossValue(List<Double> probs, double Ei, double Ef) {
|
|
||||||
double sum = 0;
|
|
||||||
for (int i = 1; i < probs.size(); i++) {
|
|
||||||
sum += probs.get(i) * getLossValue(i, Ei, Ef);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* граница интегрирования
|
|
||||||
*
|
|
||||||
* @param order
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private double getMargin(int order) {
|
|
||||||
return 80 + order * 50d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* генерирует кэшированную функцию свертки loss со спектром однократных
|
|
||||||
* потерь
|
|
||||||
*
|
|
||||||
* @param loss
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private UnivariateFunction getNextLoss(double margin, UnivariateFunction loss) {
|
|
||||||
UnivariateFunction res = (final double x) -> {
|
|
||||||
UnivariateFunction integrand = (double y) -> {
|
|
||||||
try {
|
|
||||||
return loss.value(x - y) * getSingleScatterFunction().value(y);
|
|
||||||
} catch (OutOfRangeException ex) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return integrator.integrate(5d, margin, integrand);
|
|
||||||
};
|
|
||||||
|
|
||||||
return FunctionCaching.cacheUnivariateFunction(0, margin, 200, res);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public BivariateFunction getTotalLossBivariateFunction(final double X) {
|
|
||||||
return (double Ei, double Ef) -> getTotalLossValue(X, Ei, Ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Значение полной производной функции потерь с учетом всех неисчезающих
|
|
||||||
* порядков
|
|
||||||
*
|
|
||||||
* @param X
|
|
||||||
* @param Ei
|
|
||||||
* @param Ef
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public double getTotalLossDeriv(double X, double Ei, double Ef) {
|
|
||||||
List<Double> probs = getLossProbDerivs(X);
|
|
||||||
|
|
||||||
double sum = 0;
|
|
||||||
for (int i = 1; i < probs.size(); i++) {
|
|
||||||
sum += probs.get(i) * getLossValue(i, Ei, Ef);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BivariateFunction getTotalLossDerivBivariateFunction(final double X) {
|
|
||||||
return (double Ei, double Ef) -> getTotalLossDeriv(X, Ei, Ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Значение полной функции потерь с учетом всех неисчезающих порядков
|
|
||||||
*
|
|
||||||
* @param X
|
|
||||||
* @param Ei
|
|
||||||
* @param Ef
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public double getTotalLossValue(double X, double Ei, double Ef) {
|
|
||||||
if (X == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
List<Double> probs = getLossProbabilities(X);
|
|
||||||
|
|
||||||
double sum = 0;
|
|
||||||
for (int i = 1; i < probs.size(); i++) {
|
|
||||||
sum += probs.get(i) * getLossValue(i, Ei, Ef);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import hep.dataforge.stat.parametric.AbstractParametricFunction;
|
|||||||
import hep.dataforge.stat.parametric.ParametricFunction;
|
import hep.dataforge.stat.parametric.ParametricFunction;
|
||||||
import hep.dataforge.values.ValueProvider;
|
import hep.dataforge.values.ValueProvider;
|
||||||
import hep.dataforge.values.Values;
|
import hep.dataforge.values.Values;
|
||||||
|
import inr.numass.models.misc.LossCalculator;
|
||||||
import org.apache.commons.math3.analysis.BivariateFunction;
|
import org.apache.commons.math3.analysis.BivariateFunction;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ import java.util.List;
|
|||||||
public class ModularSpectrum extends AbstractParametricFunction {
|
public class ModularSpectrum extends AbstractParametricFunction {
|
||||||
|
|
||||||
private static final String[] list = {"X", "trap"};
|
private static final String[] list = {"X", "trap"};
|
||||||
private LossCalculator calculator;
|
private LossCalculator calculator = LossCalculator.INSTANCE;
|
||||||
List<NamedSpectrumCaching> cacheList;
|
List<NamedSpectrumCaching> cacheList;
|
||||||
NamedSpectrumCaching trappingCache;
|
NamedSpectrumCaching trappingCache;
|
||||||
BivariateFunction resolution;
|
BivariateFunction resolution;
|
||||||
@ -61,7 +62,6 @@ public class ModularSpectrum extends AbstractParametricFunction {
|
|||||||
this.cacheMin = cacheMin;
|
this.cacheMin = cacheMin;
|
||||||
this.cacheMax = cacheMax;
|
this.cacheMax = cacheMax;
|
||||||
this.resolution = resolution;
|
this.resolution = resolution;
|
||||||
this.calculator = LossCalculator.instance();
|
|
||||||
this.sourceSpectrum = source;
|
this.sourceSpectrum = source;
|
||||||
setupCache();
|
setupCache();
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ public class ModularSpectrum extends AbstractParametricFunction {
|
|||||||
|
|
||||||
//обновляем кэши для трэппинга и упругого прохождения
|
//обновляем кэши для трэппинга и упругого прохождения
|
||||||
//Using external trappingCache function if provided
|
//Using external trappingCache function if provided
|
||||||
BivariateFunction trapFunc = trappingFunction != null ? trappingFunction : LossCalculator.getTrapFunction();
|
BivariateFunction trapFunc = trappingFunction != null ? trappingFunction : calculator.getTrapFunction();
|
||||||
BivariateFunction trapRes = new LossResConvolution(trapFunc, resolution);
|
BivariateFunction trapRes = new LossResConvolution(trapFunc, resolution);
|
||||||
|
|
||||||
ParametricFunction elasticSpectrum = new TransmissionConvolution(sourceSpectrum, resolution, sourceSpectrum);
|
ParametricFunction elasticSpectrum = new TransmissionConvolution(sourceSpectrum, resolution, sourceSpectrum);
|
||||||
|
@ -21,6 +21,7 @@ import hep.dataforge.stat.parametric.AbstractParametricFunction;
|
|||||||
import hep.dataforge.stat.parametric.ParametricFunction;
|
import hep.dataforge.stat.parametric.ParametricFunction;
|
||||||
import hep.dataforge.values.ValueProvider;
|
import hep.dataforge.values.ValueProvider;
|
||||||
import hep.dataforge.values.Values;
|
import hep.dataforge.values.Values;
|
||||||
|
import inr.numass.models.misc.LossCalculator;
|
||||||
import inr.numass.utils.NumassIntegrator;
|
import inr.numass.utils.NumassIntegrator;
|
||||||
import org.apache.commons.math3.analysis.BivariateFunction;
|
import org.apache.commons.math3.analysis.BivariateFunction;
|
||||||
import org.apache.commons.math3.analysis.UnivariateFunction;
|
import org.apache.commons.math3.analysis.UnivariateFunction;
|
||||||
@ -40,7 +41,7 @@ public class VariableLossSpectrum extends AbstractParametricFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static VariableLossSpectrum withData(final UnivariateFunction transmission, double eMax) {
|
public static VariableLossSpectrum withData(final UnivariateFunction transmission, double eMax) {
|
||||||
return new VariableLossSpectrum(new AbstractParametricFunction(new String[0]) {
|
return new VariableLossSpectrum(new AbstractParametricFunction() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double derivValue(String parName, double x, Values set) {
|
public double derivValue(String parName, double x, Values set) {
|
||||||
@ -82,7 +83,7 @@ public class VariableLossSpectrum extends AbstractParametricFunction {
|
|||||||
double X = set.getDouble("X");
|
double X = set.getDouble("X");
|
||||||
final double shift = set.getDouble("shift");
|
final double shift = set.getDouble("shift");
|
||||||
|
|
||||||
final LossCalculator loss = LossCalculator.instance();
|
final LossCalculator loss = LossCalculator.INSTANCE;
|
||||||
|
|
||||||
final List<Double> probs = loss.getGunLossProbabilities(X);
|
final List<Double> probs = loss.getGunLossProbabilities(X);
|
||||||
final double noLossProb = probs.get(0);
|
final double noLossProb = probs.get(0);
|
||||||
@ -126,7 +127,7 @@ public class VariableLossSpectrum extends AbstractParametricFunction {
|
|||||||
final double exW,
|
final double exW,
|
||||||
final double ionW,
|
final double ionW,
|
||||||
final double exIonRatio) {
|
final double exIonRatio) {
|
||||||
return LossCalculator.getSingleScatterFunction(exPos, ionPos, exW, ionW, exIonRatio);
|
return LossCalculator.INSTANCE.getSingleScatterFunction(exPos, ionPos, exW, ionW, exIonRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,7 +23,7 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||||
import hep.dataforge.providers.Provides
|
import hep.dataforge.providers.Provides
|
||||||
import hep.dataforge.providers.ProvidesNames
|
import hep.dataforge.providers.ProvidesNames
|
||||||
import hep.dataforge.stat.models.ModelManager
|
import hep.dataforge.stat.models.ModelLibrary
|
||||||
import hep.dataforge.stat.models.WeightedXYModel
|
import hep.dataforge.stat.models.WeightedXYModel
|
||||||
import hep.dataforge.stat.models.XYModel
|
import hep.dataforge.stat.models.XYModel
|
||||||
import hep.dataforge.tables.Adapters
|
import hep.dataforge.tables.Adapters
|
||||||
@ -53,7 +53,7 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
// StorageManager.buildFrom(context);
|
// StorageManager.buildFrom(context);
|
||||||
super.attach(context)
|
super.attach(context)
|
||||||
//TODO Replace by local providers
|
//TODO Replace by local providers
|
||||||
loadModels(context[ModelManager::class.java])
|
loadModels(context[ModelLibrary::class.java])
|
||||||
loadMath(FunctionLibrary.buildFrom(context))
|
loadMath(FunctionLibrary.buildFrom(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,9 +116,9 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
/**
|
/**
|
||||||
* Load all numass model factories
|
* Load all numass model factories
|
||||||
*
|
*
|
||||||
* @param manager
|
* @param library
|
||||||
*/
|
*/
|
||||||
private fun loadModels(manager: ModelManager) {
|
private fun loadModels(library: ModelLibrary) {
|
||||||
|
|
||||||
// manager.addModel("modularbeta", (context, an) -> {
|
// manager.addModel("modularbeta", (context, an) -> {
|
||||||
// double A = an.getDouble("resolution", 8.3e-5);//8.3e-5
|
// double A = an.getDouble("resolution", 8.3e-5);//8.3e-5
|
||||||
@ -131,7 +131,7 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
// return new XYModel(spectrum, getAdapter(an));
|
// return new XYModel(spectrum, getAdapter(an));
|
||||||
// });
|
// });
|
||||||
|
|
||||||
manager.addModel("scatter") { context, meta ->
|
library.addModel("scatter") { context, meta ->
|
||||||
val A = meta.getDouble("resolution", 8.3e-5)//8.3e-5
|
val A = meta.getDouble("resolution", 8.3e-5)//8.3e-5
|
||||||
val from = meta.getDouble("from", 0.0)
|
val from = meta.getDouble("from", 0.0)
|
||||||
val to = meta.getDouble("to", 0.0)
|
val to = meta.getDouble("to", 0.0)
|
||||||
@ -148,7 +148,7 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
XYModel(meta, getAdapter(meta), spectrum)
|
XYModel(meta, getAdapter(meta), spectrum)
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.addModel("scatter-empiric") { context, meta ->
|
library.addModel("scatter-empiric") { context, meta ->
|
||||||
val eGun = meta.getDouble("eGun", 19005.0)
|
val eGun = meta.getDouble("eGun", 19005.0)
|
||||||
|
|
||||||
val interpolator = buildInterpolator(context, meta, eGun)
|
val interpolator = buildInterpolator(context, meta, eGun)
|
||||||
@ -161,7 +161,7 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
WeightedXYModel(meta, getAdapter(meta), spectrum) { dp -> weightReductionFactor }
|
WeightedXYModel(meta, getAdapter(meta), spectrum) { dp -> weightReductionFactor }
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.addModel("scatter-empiric-variable") { context, meta ->
|
library.addModel("scatter-empiric-variable") { context, meta ->
|
||||||
val eGun = meta.getDouble("eGun", 19005.0)
|
val eGun = meta.getDouble("eGun", 19005.0)
|
||||||
|
|
||||||
//builder transmisssion with given data, annotation and smoothing
|
//builder transmisssion with given data, annotation and smoothing
|
||||||
@ -183,7 +183,7 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
WeightedXYModel(meta, getAdapter(meta), spectrum) { dp -> weightReductionFactor }
|
WeightedXYModel(meta, getAdapter(meta), spectrum) { dp -> weightReductionFactor }
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.addModel("scatter-analytic-variable") { context, meta ->
|
library.addModel("scatter-analytic-variable") { context, meta ->
|
||||||
val eGun = meta.getDouble("eGun", 19005.0)
|
val eGun = meta.getDouble("eGun", 19005.0)
|
||||||
|
|
||||||
val loss = VariableLossSpectrum.withGun(eGun + 5)
|
val loss = VariableLossSpectrum.withGun(eGun + 5)
|
||||||
@ -200,7 +200,7 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
XYModel(meta, getAdapter(meta), spectrum)
|
XYModel(meta, getAdapter(meta), spectrum)
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.addModel("scatter-empiric-experimental") { context, meta ->
|
library.addModel("scatter-empiric-experimental") { context, meta ->
|
||||||
val eGun = meta.getDouble("eGun", 19005.0)
|
val eGun = meta.getDouble("eGun", 19005.0)
|
||||||
|
|
||||||
//builder transmisssion with given data, annotation and smoothing
|
//builder transmisssion with given data, annotation and smoothing
|
||||||
@ -217,14 +217,14 @@ class NumassPlugin : BasicPlugin() {
|
|||||||
WeightedXYModel(meta, getAdapter(meta), spectrum) { dp -> weightReductionFactor }
|
WeightedXYModel(meta, getAdapter(meta), spectrum) { dp -> weightReductionFactor }
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.addModel("sterile") { context, meta ->
|
library.addModel("sterile") { context, meta ->
|
||||||
val sp = SterileNeutrinoSpectrum(context, meta)
|
val sp = SterileNeutrinoSpectrum(context, meta)
|
||||||
val spectrum = NBkgSpectrum(sp)
|
val spectrum = NBkgSpectrum(sp)
|
||||||
|
|
||||||
XYModel(meta, getAdapter(meta), spectrum)
|
XYModel(meta, getAdapter(meta), spectrum)
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.addModel("gun") { context, meta ->
|
library.addModel("gun") { context, meta ->
|
||||||
val gsp = GunSpectrum()
|
val gsp = GunSpectrum()
|
||||||
|
|
||||||
val tritiumBackground = meta.getDouble("tritiumBkg", 0.0)
|
val tritiumBackground = meta.getDouble("tritiumBkg", 0.0)
|
||||||
|
@ -3,7 +3,6 @@ package inr.numass.models
|
|||||||
import hep.dataforge.maths.integration.UnivariateIntegrator
|
import hep.dataforge.maths.integration.UnivariateIntegrator
|
||||||
import hep.dataforge.names.Names
|
import hep.dataforge.names.Names
|
||||||
import hep.dataforge.stat.models.Model
|
import hep.dataforge.stat.models.Model
|
||||||
import hep.dataforge.stat.models.ModelDescriptor
|
|
||||||
import hep.dataforge.stat.models.ModelFactory
|
import hep.dataforge.stat.models.ModelFactory
|
||||||
import hep.dataforge.stat.parametric.AbstractParametricFunction
|
import hep.dataforge.stat.parametric.AbstractParametricFunction
|
||||||
import hep.dataforge.stat.parametric.ParametricFunction
|
import hep.dataforge.stat.parametric.ParametricFunction
|
||||||
@ -14,8 +13,8 @@ import inr.numass.utils.NumassIntegrator
|
|||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
|
|
||||||
fun model(name: String, descriptor: ModelDescriptor? = null, factory: ContextMetaFactory<Model>): ModelFactory {
|
fun model(name: String,factory: ContextMetaFactory<Model>): ModelFactory {
|
||||||
return ModelFactory.build(name, descriptor, factory);
|
return ModelFactory.build(name, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// spectra operations
|
// spectra operations
|
||||||
|
@ -21,6 +21,10 @@ import hep.dataforge.plots.PlotFrame
|
|||||||
import hep.dataforge.plots.XYFunctionPlot
|
import hep.dataforge.plots.XYFunctionPlot
|
||||||
import hep.dataforge.utils.Misc
|
import hep.dataforge.utils.Misc
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
|
import kotlinx.coroutines.experimental.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.experimental.Deferred
|
||||||
|
import kotlinx.coroutines.experimental.async
|
||||||
|
import kotlinx.coroutines.experimental.runBlocking
|
||||||
import org.apache.commons.math3.analysis.BivariateFunction
|
import org.apache.commons.math3.analysis.BivariateFunction
|
||||||
import org.apache.commons.math3.analysis.UnivariateFunction
|
import org.apache.commons.math3.analysis.UnivariateFunction
|
||||||
import org.apache.commons.math3.exception.OutOfRangeException
|
import org.apache.commons.math3.exception.OutOfRangeException
|
||||||
@ -35,9 +39,7 @@ import java.util.*
|
|||||||
* @author Darksnake
|
* @author Darksnake
|
||||||
*/
|
*/
|
||||||
object LossCalculator {
|
object LossCalculator {
|
||||||
private val cache = HashMap<Int, UnivariateFunction>().also {
|
private val cache = HashMap<Int, Deferred<UnivariateFunction>>()
|
||||||
it[1] = singleScatterFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun getGunLossProbabilities(X: Double): List<Double> {
|
fun getGunLossProbabilities(X: Double): List<Double> {
|
||||||
@ -65,8 +67,23 @@ object LossCalculator {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGunZeroLossProb(X: Double): Double {
|
fun getGunZeroLossProb(x: Double): Double {
|
||||||
return Math.exp(-X)
|
return Math.exp(-x)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getCachedSpectrum(order: Int): Deferred<UnivariateFunction> {
|
||||||
|
return when {
|
||||||
|
order <= 0 -> error("Non-positive loss cache order")
|
||||||
|
order == 1 -> CompletableDeferred(singleScatterFunction)
|
||||||
|
else -> cache.getOrPut(order) {
|
||||||
|
async {
|
||||||
|
LoggerFactory.getLogger(javaClass)
|
||||||
|
.debug("Scatter cache of order {} not found. Updating", order)
|
||||||
|
getNextLoss(getMargin(order), getCachedSpectrum(order - 1).await())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,22 +92,8 @@ object LossCalculator {
|
|||||||
* @param order
|
* @param order
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private fun getLoss(order: Int): UnivariateFunction? {
|
private fun getLoss(order: Int): UnivariateFunction {
|
||||||
if (order <= 0) {
|
return runBlocking { getCachedSpectrum(order).await() }
|
||||||
throw IllegalArgumentException()
|
|
||||||
}
|
|
||||||
return if (cache.containsKey(order)) {
|
|
||||||
cache[order]
|
|
||||||
} else {
|
|
||||||
synchronized(this) {
|
|
||||||
cache.getOrPut(order) {
|
|
||||||
LoggerFactory.getLogger(javaClass)
|
|
||||||
.debug("Scatter cache of order {} not found. Updating", order)
|
|
||||||
getNextLoss(getMargin(order), getLoss(order - 1))
|
|
||||||
}
|
|
||||||
return cache[order]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLossFunction(order: Int): BivariateFunction {
|
fun getLossFunction(order: Int): BivariateFunction {
|
||||||
@ -122,32 +125,30 @@ object LossCalculator {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun getLossProbabilities(x: Double): List<Double> {
|
fun getLossProbabilities(x: Double): List<Double> {
|
||||||
return (lossProbCache).getOrPut(x) {
|
val res = ArrayList<Double>()
|
||||||
val res = ArrayList<Double>()
|
var prob: Double
|
||||||
var prob: Double
|
if (x > 0) {
|
||||||
if (x > 0) {
|
prob = 1 / x * (1 - Math.exp(-x))
|
||||||
prob = 1 / x * (1 - Math.exp(-x))
|
} else {
|
||||||
} else {
|
// если x ==0, то выживает только нулевой член, первый равен нулю
|
||||||
// если x ==0, то выживает только нулевой член, первый равен нулю
|
res.add(1.0)
|
||||||
res.add(1.0)
|
return res
|
||||||
return@getOrPut res
|
|
||||||
}
|
|
||||||
res.add(prob)
|
|
||||||
|
|
||||||
while (prob > SCATTERING_PROBABILITY_THRESHOLD) {
|
|
||||||
/*
|
|
||||||
* prob(n) = prob(n-1)-1/n! * X^n * exp(-X);
|
|
||||||
*/
|
|
||||||
var delta = Math.exp(-x)
|
|
||||||
for (i in 1 until res.size + 1) {
|
|
||||||
delta *= x / i
|
|
||||||
}
|
|
||||||
prob -= delta / x
|
|
||||||
res.add(prob)
|
|
||||||
}
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
res.add(prob)
|
||||||
|
|
||||||
|
while (prob > SCATTERING_PROBABILITY_THRESHOLD) {
|
||||||
|
/*
|
||||||
|
* prob(n) = prob(n-1)-1/n! * X^n * exp(-X);
|
||||||
|
*/
|
||||||
|
var delta = Math.exp(-x)
|
||||||
|
for (i in 1 until res.size + 1) {
|
||||||
|
delta *= x / i
|
||||||
|
}
|
||||||
|
prob -= delta / x
|
||||||
|
res.add(prob)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLossProbability(order: Int, X: Double): Double {
|
fun getLossProbability(order: Int, X: Double): Double {
|
||||||
@ -167,12 +168,10 @@ object LossCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getLossValue(order: Int, Ei: Double, Ef: Double): Double {
|
fun getLossValue(order: Int, Ei: Double, Ef: Double): Double {
|
||||||
return if (Ei - Ef < 5.0) {
|
return when {
|
||||||
0.0
|
Ei - Ef < 5.0 -> 0.0
|
||||||
} else if (Ei - Ef >= getMargin(order)) {
|
Ei - Ef >= getMargin(order) -> 0.0
|
||||||
0.0
|
else -> getLoss(order).value(Ei - Ef)
|
||||||
} else {
|
|
||||||
getLoss(order)!!.value(Ei - Ef)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,11 +260,11 @@ object LossCalculator {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun getTotalLossValue(x: Double, Ei: Double, Ef: Double): Double {
|
fun getTotalLossValue(x: Double, Ei: Double, Ef: Double): Double {
|
||||||
if (x == 0.0) {
|
return if (x == 0.0) {
|
||||||
return 0.0
|
0.0
|
||||||
} else {
|
} else {
|
||||||
val probs = getLossProbabilities(x)
|
val probs = getLossProbabilities(x)
|
||||||
return (0 until probs.size).sumByDouble { i ->
|
(1 until probs.size).sumByDouble { i ->
|
||||||
probs[i] * getLossValue(i, Ei, Ef)
|
probs[i] * getLossValue(i, Ei, Ef)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import hep.dataforge.maths.functions.FunctionLibrary
|
|||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.stat.parametric.AbstractParametricBiFunction
|
import hep.dataforge.stat.parametric.AbstractParametricBiFunction
|
||||||
import hep.dataforge.values.Values
|
import hep.dataforge.values.Values
|
||||||
import inr.numass.models.LossCalculator
|
import inr.numass.models.misc.LossCalculator
|
||||||
import inr.numass.utils.ExpressionUtils
|
import inr.numass.utils.ExpressionUtils
|
||||||
import org.apache.commons.math3.analysis.BivariateFunction
|
import org.apache.commons.math3.analysis.BivariateFunction
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@ -20,7 +20,6 @@ import java.util.*
|
|||||||
* @author [Alexander Nozik](mailto:altavir@gmail.com)
|
* @author [Alexander Nozik](mailto:altavir@gmail.com)
|
||||||
*/
|
*/
|
||||||
class NumassTransmission(context: Context, meta: Meta) : AbstractParametricBiFunction(list) {
|
class NumassTransmission(context: Context, meta: Meta) : AbstractParametricBiFunction(list) {
|
||||||
private val calculator: LossCalculator = LossCalculator.instance()
|
|
||||||
private val trapFunc: BivariateFunction
|
private val trapFunc: BivariateFunction
|
||||||
//private val lossCache = HashMap<Double, UnivariateFunction>()
|
//private val lossCache = HashMap<Double, UnivariateFunction>()
|
||||||
|
|
||||||
@ -55,13 +54,13 @@ class NumassTransmission(context: Context, meta: Meta) : AbstractParametricBiFun
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun p0(eIn: Double, set: Values): Double {
|
fun p0(eIn: Double, set: Values): Double {
|
||||||
return LossCalculator.instance().getLossProbability(0, getX(eIn, set))
|
return LossCalculator.getLossProbability(0, getX(eIn, set))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun derivValue(parName: String, eIn: Double, eOut: Double, set: Values): Double {
|
override fun derivValue(parName: String, eIn: Double, eOut: Double, set: Values): Double {
|
||||||
return when (parName) {
|
return when (parName) {
|
||||||
"trap" -> trapFunc.value(eIn, eOut)
|
"trap" -> trapFunc.value(eIn, eOut)
|
||||||
"X" -> calculator.getTotalLossDeriv(getX(eIn, set), eIn, eOut)
|
"X" -> LossCalculator.getTotalLossDeriv(getX(eIn, set), eIn, eOut)
|
||||||
else -> super.derivValue(parName, eIn, eOut, set)
|
else -> super.derivValue(parName, eIn, eOut, set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +73,7 @@ class NumassTransmission(context: Context, meta: Meta) : AbstractParametricBiFun
|
|||||||
//calculate X taking into account its energy dependence
|
//calculate X taking into account its energy dependence
|
||||||
val X = getX(eIn, set)
|
val X = getX(eIn, set)
|
||||||
// loss part
|
// loss part
|
||||||
val loss = calculator.getTotalLossValue(X, eIn, eOut)
|
val loss = LossCalculator.getTotalLossValue(X, eIn, eOut)
|
||||||
// double loss;
|
// double loss;
|
||||||
//
|
//
|
||||||
// if(eIn-eOut >= 300){
|
// if(eIn-eOut >= 300){
|
||||||
|
@ -31,10 +31,11 @@ import hep.dataforge.stat.fit.FitStage
|
|||||||
import hep.dataforge.stat.fit.FitState
|
import hep.dataforge.stat.fit.FitState
|
||||||
import hep.dataforge.stat.fit.ParamSet
|
import hep.dataforge.stat.fit.ParamSet
|
||||||
import hep.dataforge.stat.models.XYModel
|
import hep.dataforge.stat.models.XYModel
|
||||||
import hep.dataforge.tables.Adapters
|
import hep.dataforge.tables.Adapters.X_AXIS
|
||||||
import hep.dataforge.tables.ListTable
|
import hep.dataforge.values.ValueMap
|
||||||
import inr.numass.NumassPlugin
|
import inr.numass.NumassPlugin
|
||||||
import inr.numass.data.SpectrumAdapter
|
import inr.numass.data.SpectrumAdapter
|
||||||
|
import inr.numass.data.SpectrumGenerator
|
||||||
import inr.numass.models.NBkgSpectrum
|
import inr.numass.models.NBkgSpectrum
|
||||||
import inr.numass.models.sterile.SterileNeutrinoSpectrum
|
import inr.numass.models.sterile.SterileNeutrinoSpectrum
|
||||||
import kotlinx.coroutines.experimental.launch
|
import kotlinx.coroutines.experimental.launch
|
||||||
@ -98,14 +99,20 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
val x = (14000.0..18400.0).step(100.0).toList()
|
val x = (14000.0..18400.0).step(100.0).toList()
|
||||||
|
|
||||||
val table = ListTable.Builder(Adapters.getFormat(adapter)).apply {
|
|
||||||
x.forEach { u ->
|
|
||||||
row(adapter.buildSpectrumDataPoint(u, t * spectrum.value(u, params).toLong(), t.toDouble()))
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
|
|
||||||
val model = XYModel(Meta.empty(), adapter, spectrum)
|
val model = XYModel(Meta.empty(), adapter, spectrum)
|
||||||
val state = FitState(table, model, params)
|
|
||||||
|
val generator = SpectrumGenerator(model, paramsMod, 12316);
|
||||||
|
val configuration = x.map { ValueMap.ofPairs(X_AXIS to it, "time" to t) }
|
||||||
|
val data = generator.generateData(configuration);
|
||||||
|
|
||||||
|
// val table = ListTable.Builder(Adapters.getFormat(adapter)).apply {
|
||||||
|
// x.forEach { u ->
|
||||||
|
// row(adapter.buildSpectrumDataPoint(u, t * spectrum.value(u, paramsMod).toLong(), t.toDouble()))
|
||||||
|
// }
|
||||||
|
// }.build()
|
||||||
|
|
||||||
|
|
||||||
|
val state = FitState(data, model, params)
|
||||||
val res = fm.runStage(state, "QOW", FitStage.TASK_RUN, "N", "E0","bkg")
|
val res = fm.runStage(state, "QOW", FitStage.TASK_RUN, "N", "E0","bkg")
|
||||||
|
|
||||||
res.printState(PrintWriter(System.out))
|
res.printState(PrintWriter(System.out))
|
||||||
|
@ -12,14 +12,14 @@ fun main(args: Array<String>) {
|
|||||||
val point = ProtoNumassPoint.readFile(file)
|
val point = ProtoNumassPoint.readFile(file)
|
||||||
point.plotAmplitudeSpectrum()
|
point.plotAmplitudeSpectrum()
|
||||||
|
|
||||||
point.blocks.filter { it.channel == 0 }.firstOrNull()?.let {
|
point.blocks.firstOrNull { it.channel == 0 }?.let {
|
||||||
it.plotAmplitudeSpectrum(plotName = "0") {
|
it.plotAmplitudeSpectrum(plotName = "0") {
|
||||||
"title" to "pixel 0"
|
"title" to "pixel 0"
|
||||||
"binning" to 50
|
"binning" to 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
point.blocks.filter { it.channel == 4 }.firstOrNull()?.let {
|
point.blocks.firstOrNull { it.channel == 4 }?.let {
|
||||||
it.plotAmplitudeSpectrum(plotName = "4") {
|
it.plotAmplitudeSpectrum(plotName = "4") {
|
||||||
"title" to "pixel 4"
|
"title" to "pixel 4"
|
||||||
"binning" to 50
|
"binning" to 50
|
||||||
|
Loading…
Reference in New Issue
Block a user