refactor numass resolution

This commit is contained in:
Alexander Nozik 2021-05-29 20:38:35 +03:00
parent 57e3439220
commit d41ff5fefc
8 changed files with 513 additions and 315 deletions

View File

@ -136,9 +136,7 @@ class ListTable @JvmOverloads constructor(override val format: TableFormat, poin
* @throws NamingException * @throws NamingException
*/ */
@Throws(NamingException::class) @Throws(NamingException::class)
fun row(vararg values: Any): Builder { fun row(vararg values: Any): Builder = row(ValueMap.of(format.namesAsArray(), *values))
return row(ValueMap.of(format.namesAsArray(), *values))
}
fun row(values: ValueProvider): Builder { fun row(values: ValueProvider): Builder {
val names = format.namesAsArray() val names = format.namesAsArray()
@ -146,17 +144,12 @@ class ListTable @JvmOverloads constructor(override val format: TableFormat, poin
return row(ValueMap(map)) return row(ValueMap(map))
} }
fun row(vararg values: NamedValue): Builder { fun row(vararg values: NamedValue): Builder = row(ValueMap.of(*values))
return row(ValueMap.of(*values))
}
fun row(vararg values: Pair<String, Any>): Builder { fun row(vararg values: Pair<String, Any>): Builder =
return row(ValueMap.of(values.map { NamedValue.of(it.first, it.second) })) row(ValueMap.of(values.map { NamedValue.of(it.first, it.second) }))
}
fun row(map: Map<String, Any>): Builder { fun row(map: Map<String, Any>): Builder = row(ValueMap.ofMap(map))
return row(ValueMap.ofMap(map))
}
fun rows(points: Iterable<Values>): Builder { fun rows(points: Iterable<Values>): Builder {
for (point in points) { for (point in points) {
@ -170,16 +163,12 @@ class ListTable @JvmOverloads constructor(override val format: TableFormat, poin
return this return this
} }
fun build(): Table { fun build(): ListTable = ListTable(format, points)
return ListTable(format, points)
}
/** /**
* Build table without points name check * Build table without points name check
*/ */
fun buildUnsafe(): Table { fun buildUnsafe(): Table = ListTable(format, points, true)
return ListTable(format, points, true)
}
} }
companion object { companion object {

View File

@ -52,8 +52,6 @@ interface Table : NavigableValuesSource, MetaMorph {
*/ */
fun getColumn(name: String): Column fun getColumn(name: String): Column
@JvmDefault
override fun toMeta(): Meta { override fun toMeta(): Meta {
val res = MetaBuilder("table") val res = MetaBuilder("table")
res.putNode("format", format.toMeta()) res.putNode("format", format.toMeta())

View File

@ -1,77 +0,0 @@
package inr.numass.scripts
import hep.dataforge.context.Context
import hep.dataforge.context.Global
import hep.dataforge.grind.GrindShell
import hep.dataforge.grind.helpers.PlotHelper
import hep.dataforge.stat.fit.ParamSet
import inr.numass.NumassPlugin
import inr.numass.models.sterile.NumassResolution
import inr.numass.models.sterile.SterileNeutrinoSpectrum
import static hep.dataforge.grind.Grind.buildMeta
Context ctx = Global.instance()
ctx.getPlugins().load(FXPlotManager)
ctx.getPlugins().load(NumassPlugin.class)
GrindShell shell = new GrindShell(ctx)
shell.eval {
PlotHelper plot = plots
ParamSet params = new ParamSet(buildMeta {
N(value: 2.7e+06, err: 30, lower: 0)
bkg(value: 5.0, err: 0.1)
E0(value: 18575.0, err: 0.1)
mnu2(value: 0, err: 0.01)
msterile2(value: 1000**2, err: 1)
U2(value: 0.0, err: 1e-3)
X(value: 0.0, err: 0.01, lower: 0)
trap(value: 1.0, err: 0.05)
})
def meta1 = buildMeta {
resolution(width: 8.3e-5, tail: "(0.99797 - 3.05346E-7*D - 5.45738E-10 * D**2 - 6.36105E-14 * D**3)")
}
def meta2 = buildMeta {
resolution(width: 8.3e-5, tail: "(0.99797 - 3.05346E-7*D - 5.45738E-10 * D**2 - 6.36105E-14 * D**3)*(1-5e-3*sqrt(E/1000))")
}
def resolution1 = new NumassResolution(
ctx,
meta1.getMeta("resolution")
)
def resolution2 = new NumassResolution(
ctx,
meta2.getMeta("resolution")
)
plot.plot(frame: "resolution", from: 13500, to: 19000) { x ->
resolution1.value(x, 14000, params)
}
plot.plot(frame: "resolution", from: 13500, to: 19000) { x ->
resolution2.value(x, 14000, params)
}
def spectrum1 = new SterileNeutrinoSpectrum(ctx, meta1)
def spectrum2 = new SterileNeutrinoSpectrum(ctx, meta2)
def x = []
def y1 = []
def y2 = []
(13500..19000).step(100).each {
x << it
y1 << spectrum1.value(it, params)
y2 << spectrum2.value(it, params)
}
plot.plot(x, y1, "spectrum1", "spectrum")
plot.plot(x, y2, "spectrum2", "spectrum")
}

View File

@ -26,7 +26,9 @@ import hep.dataforge.values.Values
* *
* @author Darksnake * @author Darksnake
*/ */
open class NBkgSpectrum(private val source: ParametricFunction) : AbstractParametricFunction(*combineNamesWithEquals(source.namesAsArray(), *list)) { open class NBkgSpectrum(
private val source: ParametricFunction,
) : AbstractParametricFunction(*combineNamesWithEquals(source.namesAsArray(), *list)) {
var counter = MultiCounter(this.javaClass.name) var counter = MultiCounter(this.javaClass.name)

View File

@ -13,40 +13,16 @@ import hep.dataforge.values.Values
import inr.numass.models.ResolutionFunction import inr.numass.models.ResolutionFunction
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 java.lang.Math.sqrt import kotlin.math.sqrt
import java.util.*
/** /**
* @author [Alexander Nozik](mailto:altavir@gmail.com) * @author [Alexander Nozik](mailto:altavir@gmail.com)
*/ */
class NumassResolution(context: Context, meta: Meta) : AbstractParametricBiFunction(list) { class NumassResolution(
val resA: Double = 8.3e-5,
private val resA: Double = meta.getDouble("A", 8.3e-5) val resB: Double = 0.0,
private val resB = meta.getDouble("B", 0.0) val tailFunction: BivariateFunction = ResolutionFunction.getConstantTail(),
private val tailFunction: BivariateFunction = when { ) : AbstractParametricBiFunction(list) {
meta.hasValue("tail") -> {
val tailFunctionStr = meta.getString("tail")
if (tailFunctionStr.startsWith("function::")) {
FunctionLibrary.buildFrom(context).buildBivariateFunction(tailFunctionStr.substring(10))
} else {
BivariateFunction { E, U ->
val binding = HashMap<String, Any>()
binding["E"] = E
binding["U"] = U
binding["D"] = E - U
ExpressionUtils.function(tailFunctionStr, binding)
}
}
}
meta.hasValue("tailAlpha") -> {
//add polynomial function here
val alpha = meta.getDouble("tailAlpha")
val beta = meta.getDouble("tailBeta", 0.0)
BivariateFunction { E: Double, U: Double -> 1 - (E - U) * (alpha + E / 1000.0 * beta) / 1000.0 }
}
else -> ResolutionFunction.getConstantTail()
}
override fun derivValue(parName: String, x: Double, y: Double, set: Values): Double { override fun derivValue(parName: String, x: Double, y: Double, set: Values): Double {
return 0.0 return 0.0
@ -82,6 +58,35 @@ class NumassResolution(context: Context, meta: Meta) : AbstractParametricBiFunct
companion object { companion object {
private val list = arrayOf<String>() //leaving private val list = arrayOf<String>() //leaving
internal fun fromMeta(context: Context, meta: Meta) = NumassResolution(
meta.getDouble("A", 8.3e-5),
meta.getDouble("B", 0.0),
when {
meta.hasValue("tail") -> {
val tailFunctionStr = meta.getString("tail")
if (tailFunctionStr.startsWith("function::")) {
FunctionLibrary.buildFrom(context).buildBivariateFunction(tailFunctionStr.substring(10))
} else {
BivariateFunction { E, U ->
val binding = HashMap<String, Any>()
binding["E"] = E
binding["U"] = U
binding["D"] = E - U
ExpressionUtils.function(tailFunctionStr, binding)
}
}
}
meta.hasValue("tailAlpha") -> {
//add polynomial function here
val alpha = meta.getDouble("tailAlpha")
val beta = meta.getDouble("tailBeta", 0.0)
BivariateFunction { E: Double, U: Double -> 1 - (E - U) * (alpha + E / 1000.0 * beta) / 1000.0 }
}
else -> ResolutionFunction.getConstantTail()
}
)
} }
} }

View File

@ -48,7 +48,7 @@ class SterileNeutrinoSpectrum @JvmOverloads constructor(
configuration: Meta, configuration: Meta,
val source: ParametricBiFunction = NumassBeta(), val source: ParametricBiFunction = NumassBeta(),
val transmission: ParametricBiFunction = NumassTransmission(context, configuration.getMetaOrEmpty("transmission")), val transmission: ParametricBiFunction = NumassTransmission(context, configuration.getMetaOrEmpty("transmission")),
val resolution: ParametricBiFunction = NumassResolution(context, configuration.getMeta("resolution", Meta.empty())) val resolution: ParametricBiFunction = NumassResolution.fromMeta(context, configuration.getMeta("resolution", Meta.empty()))
) : AbstractParametricFunction(*list) { ) : AbstractParametricFunction(*list) {

View File

@ -0,0 +1,155 @@
/*
* Copyright 2018 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.scripts.models
import hep.dataforge.buildContext
import hep.dataforge.configure
import hep.dataforge.fx.FXPlugin
import hep.dataforge.fx.output.FXOutputManager
import hep.dataforge.meta.Meta
import hep.dataforge.plots.Plot
import hep.dataforge.plots.data.DataPlot
import hep.dataforge.plots.jfreechart.JFreeChartPlugin
import hep.dataforge.plots.output.plotFrame
import hep.dataforge.plots.plotFunction
import hep.dataforge.stat.fit.FitManager
import hep.dataforge.stat.fit.FitStage
import hep.dataforge.stat.fit.FitState
import hep.dataforge.stat.fit.ParamSet
import hep.dataforge.stat.models.XYModel
import hep.dataforge.step
import hep.dataforge.tables.Adapters.X_AXIS
import hep.dataforge.tables.Table
import hep.dataforge.values.ValueMap
import inr.numass.NumassPlugin
import inr.numass.data.SpectrumAdapter
import inr.numass.data.SpectrumGenerator
import inr.numass.models.NBkgSpectrum
import inr.numass.models.sterile.NumassResolution
import inr.numass.models.sterile.SterileNeutrinoSpectrum
import org.apache.commons.math3.analysis.interpolation.SplineInterpolator
import java.io.PrintWriter
private fun getCustomResolution(): NumassResolution {
val correctionDataString = """
10 0.376892
12 0.1615868
13 0.1009648
14 0.0677539
15 0.0487972
16 0.037275
17 0.02958922
18 0.02511696
19 0.02247986
""".trimIndent()
val correctionData = correctionDataString.lines().map { line ->
val (u, cor) = line.split("\t")
u.toDouble() * 1000 to cor.toDouble()
}
val correctionInterpolation = SplineInterpolator().interpolate(
correctionData.map { it.first }.toDoubleArray(),
correctionData.map { it.second }.toDoubleArray()
)
return NumassResolution(tailFunction = { e, _ -> 1.0 - correctionInterpolation.value(e) })
}
private fun XYModel.plot(name: String, params: ParamSet): Plot {
val x = (14000.0..19000.0).step(100.0).toList()
val y = x.map { spectrum.value(it, params) }
return DataPlot.plot(name, x.toDoubleArray(), y.toDoubleArray())
}
fun main() {
val context = buildContext(
"NUMASS",
NumassPlugin::class.java,
FXPlugin::class.java,
JFreeChartPlugin::class.java
) {
output = FXOutputManager()
}
val params = ParamSet().apply {
setPar("N", 8e5, 6.0, 0.0, Double.POSITIVE_INFINITY)
setPar("bkg", 2.0, 0.03)
setPar("E0", 18575.0, 1.0)
setPar("mnu2", 0.0, 1.0)
setParValue("msterile2", (1000 * 1000).toDouble())
setPar("U2", 0.0, 1e-3)
setPar("X", 0.0, 0.01)
setPar("trap", 1.0, 0.01)
}
val customResolution = getCustomResolution()
context.plotFrame("fit", stage = "resolution") {
plots.configure {
"showLine" to true
"showSymbol" to false
"showErrors" to false
"thickness" to 2.0
}
plots.setType<DataPlot>()
plotFunction("custom", 14000.0, 18000.0, 1000) { x ->
customResolution.value(x, 14100.0, params)
}
val basicResolution = NumassResolution()
plotFunction("basic", 14000.0, 18000.0, 1000) { x ->
basicResolution.value(x, 14100.0, params)
}
}
val dataSpectrum = NBkgSpectrum(SterileNeutrinoSpectrum(context, Meta.empty(), resolution = customResolution))
val t = 30 * 50 // time in seconds per point
val adapter = SpectrumAdapter(Meta.empty())
val fm = context.getOrLoad(FitManager::class.java)
val x = (14000.0..18500.0).step(100.0).toList()
val dataModel = XYModel(Meta.empty(), adapter, dataSpectrum)
val generator = SpectrumGenerator(dataModel, params, 12316)
val configuration = x.map { ValueMap.ofPairs(X_AXIS to it, "time" to t) }
val data: Table = generator.generateData(configuration)
val modelSpectrum = NBkgSpectrum(SterileNeutrinoSpectrum(context, Meta.empty(), resolution = NumassResolution()))
val fitModel = XYModel(Meta.empty(), adapter, modelSpectrum)
context.plotFrame("fit", stage = "plots") {
plots.configure {
"showLine" to true
"showSymbol" to false
"showErrors" to false
"thickness" to 4.0
}
plots.setType<DataPlot>()
+dataModel.plot("Data", params)
+fitModel.plot("Fit-start", params)
}
val state = FitState(data, fitModel, params)
val res = fm.runStage(state, "QOW", FitStage.TASK_RUN, "N", "E0", "bkg", "trap")
res.printState(PrintWriter(System.out))
val resU2 = fm.runStage(res.optState().get(), "QOW", FitStage.TASK_RUN, "N", "E0", "bkg", "trap", "U2")
resU2.printState(PrintWriter(System.out))
}