WIP porting model from legacy

This commit is contained in:
Alexander Nozik 2021-04-12 15:10:37 +03:00
parent c6beaf3f83
commit f4d26197d9
18 changed files with 1341 additions and 3 deletions

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -0,0 +1,48 @@
/*
* 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 hep.dataforge.stat.parametric
import hep.dataforge.exceptions.NameNotFoundException
abstract class AbstractParametric : AbstractNamedSet {
constructor(names: NameList?) : super(names) {}
constructor(list: Array<String?>?) : super(list) {}
constructor(set: NameSetContainer?) : super(set) {}
/**
* Provide default value for parameter with name `name`. Throws
* NameNotFound if no default found for given parameter.
*
* @param name
* @return
*/
protected fun getDefaultParameter(name: String?): Double {
throw NameNotFoundException(name)
}
/**
* Extract value from input vector using default value if required parameter
* not found
*
* @param name
* @param set
* @return
*/
protected fun getParameter(name: String?, set: Values): Double {
//FIXME add default value
return set.getDouble(name)
}
}

View File

@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.stat.parametric
import hep.dataforge.exceptions.NotDefinedException
abstract class AbstractParametricBiFunction : AbstractParametric, ParametricBiFunction {
constructor(names: NameList?) : super(names) {}
constructor(list: Array<String?>?) : super(list) {}
constructor(set: NameSetContainer?) : super(set) {}
fun derivValue(parName: String?, x: Double, y: Double, set: Values?): Double {
return if (!getNames().contains(parName)) {
0
} else {
throw NotDefinedException()
}
}
}

View File

@ -0,0 +1,34 @@
/*
* 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 hep.dataforge.stat.parametric
import hep.dataforge.names.NameList
typealias NameList = List<String>
/**
*
*
* Abstract AbstractNamedSpectrum class.
*
* @author Alexander Nozik
* @version $Id: $Id
*/
abstract class AbstractParametricFunction : AbstractParametric, ParametricFunction {
constructor(names: NameList?) : super(names) {}
constructor(vararg list: String?) : super(list) {}
constructor(set: NameSetContainer?) : super(set) {}
}

View File

@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.stat.parametric
import hep.dataforge.names.NameList
abstract class AbstractParametricValue : AbstractParametric, ParametricValue {
constructor(names: NameList?) : super(names) {}
constructor(list: Array<String?>?) : super(list) {}
constructor(set: NameSetContainer?) : super(set) {}
}

View File

@ -0,0 +1,108 @@
/*
* 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 hep.dataforge.stat.parametric
import hep.dataforge.stat.fit.Param
/**
*
* DerivativeCalculator class.
*
* @author Alexander Nozik
* @version $Id: $Id
*/
object DerivativeCalculator {
private const val numPoints = 3
/**
* Calculates finite differences derivative via 3 points differentiator.
*
* @param function a [hep.dataforge.stat.parametric.ParametricValue] object.
* @param point a [hep.dataforge.stat.fit.ParamSet] object.
* @param parName a [String] object.
* @return a double.
*/
fun calculateDerivative(function: ParametricValue?, point: ParamSet, parName: String?): Double {
val projection: UnivariateFunction = ParametricUtils.getNamedProjection(function, parName, point)
val par: Param = point.getByName(parName)
val diff =
FiniteDifferencesDifferentiator(numPoints, par.getErr() / 2.0, par.getLowerBound(), par.getUpperBound())
val derivative: UnivariateDifferentiableFunction = diff.differentiate(projection)
val x = DerivativeStructure(1, 1, 0, point.getDouble(parName))
val y: DerivativeStructure = derivative.value(x)
return y.getPartialDerivative(1)
}
/**
* Calculates finite differences derivative via 3 points differentiator.
*
* @param function a [org.apache.commons.math3.analysis.UnivariateFunction] object.
* @param point a double.
* @param step a double.
* @return a double.
*/
fun calculateDerivative(function: UnivariateFunction?, point: Double, step: Double): Double {
val diff = FiniteDifferencesDifferentiator(numPoints, step)
val derivative: UnivariateDifferentiableFunction = diff.differentiate(function)
val x = DerivativeStructure(1, 1, 0, point)
val y: DerivativeStructure = derivative.value(x)
return y.getPartialDerivative(1)
}
/**
*
* providesValidDerivative.
*
* @param function a [hep.dataforge.stat.parametric.ParametricValue] object.
* @param point a [hep.dataforge.stat.fit.ParamSet] object.
* @param tolerance a double.
* @param parName a [String] object.
* @return a boolean.
*/
fun providesValidDerivative(
function: ParametricValue,
point: ParamSet,
tolerance: Double,
parName: String?
): Boolean {
if (!function.providesDeriv(parName)) {
return false
}
val calculatedDeriv = calculateDerivative(function, point, parName)
val providedDeriv: Double = function.derivValue(parName, point)
return safeRelativeDifference(calculatedDeriv, providedDeriv) <= tolerance
}
/**
* Returns safe from (no devision by zero) relative difference between two
* input values
*
* @param val1
* @param val2
* @return
*/
private fun safeRelativeDifference(val1: Double, val2: Double): Double {
if (Precision.equals(val1, val2, Precision.EPSILON)) {
return 0
}
val average: Double = Math.abs(val1 + val2) / 2
return if (average > Precision.EPSILON) {
Math.abs(val1 - val2) / average
} else {
Double.POSITIVE_INFINITY
}
}
}

View File

@ -0,0 +1,75 @@
/*
* 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 ru.inr.mass.models
import hep.dataforge.names.NamesUtils.combineNamesWithEquals
import hep.dataforge.stat.parametric.AbstractParametricFunction
import hep.dataforge.stat.parametric.ParametricFunction
import hep.dataforge.utils.MultiCounter
import hep.dataforge.values.ValueProvider
import hep.dataforge.values.Values
import space.kscience.kmath.expressions.Symbol
typealias Values = Map<Symbol, Double>
/**
*
* @author Darksnake
*/
open class NBkgSpectrum(private val source: ParametricFunction) : AbstractParametricFunction(*combineNamesWithEquals(source.namesAsArray(), *list)) {
override fun derivValue(parName: String, x: Double, set: Values): Double {
return when (parName) {
"N" -> source.value(x, set)
"bkg" -> 1.0
else -> getN(set) * source.derivValue(parName, x, set)
}
}
private fun getBkg(set: ValueProvider): Double {
return set.getDouble("bkg")
}
private fun getN(set: ValueProvider): Double {
return set.getDouble("N")
}
override fun providesDeriv(name: String): Boolean {
return when (name) {
"N","bkg" -> true
else -> this.source.providesDeriv(name)
}
}
override fun value(x: Double, set: Values): Double {
this.counter.increase("value")
return getN(set) * source.value(x, set) + getBkg(set)
}
override fun getDefaultParameter(name: String): Double {
return when (name) {
"bkg" -> 0.0
"N" -> 1.0
else -> super.getDefaultParameter(name)
}
}
companion object {
private val list = arrayOf("N", "bkg")
}
}

View File

@ -0,0 +1,225 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.models.sterile
import hep.dataforge.exceptions.NotDefinedException
import hep.dataforge.stat.parametric.AbstractParametricBiFunction
import hep.dataforge.stat.parametric.AbstractParametricFunction
import hep.dataforge.stat.parametric.ParametricFunction
import hep.dataforge.values.Values
import java.lang.Math.*
/**
* A bi-function for beta-spectrum calculation taking energy and final state as
* input.
*
*
* dissertation p.33
*
*
* @author [Alexander Nozik](mailto:altavir@gmail.com)
*/
class NumassBeta : AbstractParametricBiFunction(list) {
/**
* Beta spectrum derivative
*
* @param n parameter number
* @param E0
* @param mnu2
* @param E
* @return
* @throws NotDefinedException
*/
@Throws(NotDefinedException::class)
private fun derivRoot(n: Int, E0: Double, mnu2: Double, E: Double): Double {
val D = E0 - E//E0-E
if (D == 0.0) {
return 0.0
}
return if (mnu2 >= 0) {
if (E >= E0 - sqrt(mnu2)) {
0.0
} else {
val bare = sqrt(D * D - mnu2)
when (n) {
0 -> factor(E) * (2.0 * D * D - mnu2) / bare
1 -> -factor(E) * 0.5 * D / bare
else -> 0.0
}
}
} else {
val mu = sqrt(-0.66 * mnu2)
if (E >= E0 + mu) {
0.0
} else {
val root = sqrt(Math.max(D * D - mnu2, 0.0))
val exp = exp(-1 - D / mu)
when (n) {
0 -> factor(E) * (D * (D + mu * exp) / root + root * (1 - exp))
1 -> factor(E) * (-(D + mu * exp) / root * 0.5 - root * exp * (1 + D / mu) / 3.0 / mu)
else -> 0.0
}
}
}
}
/**
* Derivative of spectrum with sterile neutrinos
*
* @param name
* @param E
* @param E0
* @param pars
* @return
* @throws NotDefinedException
*/
@Throws(NotDefinedException::class)
private fun derivRootsterile(name: String, E: Double, E0: Double, pars: Values): Double {
val mnu2 = getParameter("mnu2", pars)
val mst2 = getParameter("msterile2", pars)
val u2 = getParameter("U2", pars)
return when (name) {
"E0" -> {
if (u2 == 0.0) {
derivRoot(0, E0, mnu2, E)
} else {
u2 * derivRoot(0, E0, mst2, E) + (1 - u2) * derivRoot(0, E0, mnu2, E)
}
}
"mnu2" -> (1 - u2) * derivRoot(1, E0, mnu2, E)
"msterile2" -> {
if (u2 == 0.0) {
0.0
} else {
u2 * derivRoot(1, E0, mst2, E)
}
}
"U2" -> root(E0, mst2, E) - root(E0, mnu2, E)
else -> 0.0
}
}
/**
* The part independent of neutrino mass. Includes global normalization
* constant, momentum and Fermi correction
*
* @param E
* @return
*/
private fun factor(E: Double): Double {
val me = 0.511006E6
val eTot = E + me
val pe = sqrt(E * (E + 2.0 * me))
val ve = pe / eTot
val yfactor = 2.0 * 2.0 * 1.0 / 137.039 * Math.PI
val y = yfactor / ve
val fn = y / abs(1.0 - exp(-y))
val fermi = fn * (1.002037 - 0.001427 * ve)
val res = fermi * pe * eTot
return K * res
}
override fun providesDeriv(name: String): Boolean {
return true
}
/**
* Bare beta spectrum with Mainz negative mass correction
*
* @param E0
* @param mnu2
* @param E
* @return
*/
private fun root(E0: Double, mnu2: Double, E: Double): Double {
//bare beta-spectrum
val delta = E0 - E
val bare = factor(E) * delta * sqrt(Math.max(delta * delta - mnu2, 0.0))
return when {
mnu2 >= 0 -> Math.max(bare, 0.0)
delta == 0.0 -> 0.0
delta + 0.812 * sqrt(-mnu2) <= 0 -> 0.0 //sqrt(0.66)
else -> {
val aux = sqrt(-mnu2 * 0.66) / delta
Math.max(bare * (1 + aux * exp(-1 - 1 / aux)), 0.0)
}
}
}
/**
* beta-spectrum with sterile neutrinos
*
* @param E
* @param E0
* @param pars
* @return
*/
private fun rootsterile(E: Double, E0: Double, pars: Values): Double {
val mnu2 = getParameter("mnu2", pars)
val mst2 = getParameter("msterile2", pars)
val u2 = getParameter("U2", pars)
return if (u2 == 0.0) {
root(E0, mnu2, E)
} else {
u2 * root(E0, mst2, E) + (1 - u2) * root(E0, mnu2, E)
}
// P(rootsterile)+ (1-P)root
}
override fun getDefaultParameter(name: String): Double {
return when (name) {
"mnu2", "U2", "msterile2" -> 0.0
else -> super.getDefaultParameter(name)
}
}
override fun derivValue(parName: String, fs: Double, eIn: Double, pars: Values): Double {
val e0 = getParameter("E0", pars)
return derivRootsterile(parName, eIn, e0 - fs, pars)
}
override fun value(fs: Double, eIn: Double, pars: Values): Double {
val e0 = getParameter("E0", pars)
return rootsterile(eIn, e0 - fs, pars)
}
/**
* Get univariate spectrum with given final state
*/
fun getSpectrum(fs: Double = 0.0): ParametricFunction {
return BetaSpectrum(fs);
}
inner class BetaSpectrum(val fs: Double) : AbstractParametricFunction(*list) {
override fun providesDeriv(name: String): Boolean {
return this@NumassBeta.providesDeriv(name)
}
override fun derivValue(parName: String, x: Double, set: Values): Double {
return this@NumassBeta.derivValue(parName, fs, x, set)
}
override fun value(x: Double, set: Values): Double {
return this@NumassBeta.value(fs, x, set)
}
}
companion object {
private const val K = 1E-23
private val list = arrayOf("E0", "mnu2", "msterile2", "U2")
}
}

View File

@ -0,0 +1,87 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.models.sterile
import hep.dataforge.context.Context
import hep.dataforge.maths.functions.FunctionLibrary
import hep.dataforge.meta.Meta
import hep.dataforge.stat.parametric.AbstractParametricBiFunction
import hep.dataforge.values.Values
import inr.numass.models.ResolutionFunction
import inr.numass.utils.ExpressionUtils
import org.apache.commons.math3.analysis.BivariateFunction
import java.lang.Math.sqrt
import java.util.*
/**
* @author [Alexander Nozik](mailto:altavir@gmail.com)
*/
class NumassResolution(context: Context, meta: Meta) : AbstractParametricBiFunction(list) {
private val resA: Double = meta.getDouble("A", 8.3e-5)
private val resB = meta.getDouble("B", 0.0)
private val tailFunction: BivariateFunction = 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()
}
override fun derivValue(parName: String, x: Double, y: Double, set: Values): Double {
return 0.0
}
private fun getValueFast(E: Double, U: Double): Double {
val delta = resA * E
return when {
E - U < 0 -> 0.0
E - U > delta -> tailFunction.value(E, U)
else -> (E - U) / delta
}
}
override fun providesDeriv(name: String): Boolean {
return true
}
override fun value(E: Double, U: Double, set: Values): Double {
assert(resA > 0)
if (resB <= 0) {
return this.getValueFast(E, U)
}
assert(resB > 0)
val delta = resA * E
return when {
E - U < 0 -> 0.0
E - U > delta -> tailFunction.value(E, U)
else -> (1 - sqrt(1 - (E - U) / E * resB)) / (1 - sqrt(1 - resA * resB))
}
}
companion object {
private val list = arrayOf<String>() //leaving
}
}

View File

@ -0,0 +1,86 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.models.sterile
import hep.dataforge.context.Context
import hep.dataforge.maths.functions.FunctionLibrary
import hep.dataforge.meta.Meta
import hep.dataforge.stat.parametric.AbstractParametricBiFunction
import hep.dataforge.values.Values
import inr.numass.models.misc.LossCalculator
import inr.numass.utils.ExpressionUtils
import org.apache.commons.math3.analysis.BivariateFunction
import org.slf4j.LoggerFactory
import java.util.*
/**
* @author [Alexander Nozik](mailto:altavir@gmail.com)
*/
class NumassTransmission(context: Context, meta: Meta) : AbstractParametricBiFunction(list) {
private val trapFunc: BivariateFunction
//private val lossCache = HashMap<Double, UnivariateFunction>()
private val adjustX: Boolean = meta.getBoolean("adjustX", false)
init {
if (meta.hasValue("trapping")) {
val trapFuncStr = meta.getString("trapping")
trapFunc = if (trapFuncStr.startsWith("function::")) {
FunctionLibrary.buildFrom(context).buildBivariateFunction(trapFuncStr.substring(10))
} else {
BivariateFunction { Ei: Double, Ef: Double ->
val binding = HashMap<String, Any>()
binding["Ei"] = Ei
binding["Ef"] = Ef
ExpressionUtils.function(trapFuncStr, binding)
}
}
} else {
LoggerFactory.getLogger(javaClass).warn("Trapping function not defined. Using default")
trapFunc = FunctionLibrary.buildFrom(context).buildBivariateFunction("numass.trap.nominal")
}
}
override fun derivValue(parName: String, eIn: Double, eOut: Double, set: Values): Double {
return when (parName) {
"trap" -> trapFunc.value(eIn, eOut)
"X" -> LossCalculator.getTotalLossDeriv(set, eIn, eOut)
else -> super.derivValue(parName, eIn, eOut, set)
}
}
override fun providesDeriv(name: String): Boolean {
return true
}
override fun value(eIn: Double, eOut: Double, set: Values): Double {
// loss part
val loss = LossCalculator.getTotalLossValue(set, eIn, eOut)
// double loss;
//
// if(eIn-eOut >= 300){
// loss = 0;
// } else {
// UnivariateFunction lossFunction = this.lossCache.computeIfAbsent(X, theX ->
// FunctionCaching.cacheUnivariateFunction(0, 300, 400, x -> calculator.getTotalLossValue(theX, eIn, eIn - x))
// );
//
// loss = lossFunction.value(eIn - eOut);
// }
//trapping part
val trap = getParameter("trap", set) * trapFunc.value(eIn, eOut)
return loss + trap
}
companion object {
private val list = arrayOf("trap", "X")
}
}

View File

@ -0,0 +1,40 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.stat.parametric
import hep.dataforge.exceptions.NotDefinedException
/**
*
* @author Alexander Nozik
*/
interface ParametricBiFunction : NameSetContainer {
fun derivValue(parName: String?, x: Double, y: Double, set: Values?): Double
fun value(x: Double, y: Double, set: Values?): Double
fun providesDeriv(name: String?): Boolean
fun derivative(parName: String?): ParametricBiFunction? {
return if (providesDeriv(parName)) {
object : ParametricBiFunction {
override fun derivValue(parName: String?, x: Double, y: Double, set: Values?): Double {
throw NotDefinedException()
}
override fun value(x: Double, y: Double, set: Values?): Double {
return this@ParametricBiFunction.derivValue(parName, x, y, set)
}
override fun providesDeriv(name: String?): Boolean {
return !names.contains(name)
}
val names: NameList
get() = this@ParametricBiFunction.getNames()
}
} else {
throw NotDefinedException()
}
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.models.sterile
import hep.dataforge.names.NameList
import hep.dataforge.stat.parametric.ParametricBiFunction
import hep.dataforge.values.Values
class ParametricBiFunctionCache(val function: ParametricBiFunction): ParametricBiFunction {
override fun derivValue(parName: String?, x: Double, y: Double, set: Values?): Double {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun getNames(): NameList {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun value(x: Double, y: Double, set: Values?): Double {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun providesDeriv(name: String?): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}

View File

@ -0,0 +1,58 @@
/*
* 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 hep.dataforge.stat.parametric
import hep.dataforge.exceptions.NotDefinedException
/**
*
*
* NamedSpectrum interface.
*
* @author Alexander Nozik
* @version $Id: $Id
*/
interface ParametricFunction : NameSetContainer {
fun derivValue(parName: String?, x: Double, set: Values?): Double
fun value(x: Double, set: Values?): Double
fun providesDeriv(name: String?): Boolean
fun derivative(parName: String?): ParametricFunction? {
return if (providesDeriv(parName)) {
object : ParametricFunction {
override fun derivValue(parName: String?, x: Double, set: Values?): Double {
return if (names.contains(parName)) {
throw NotDefinedException()
} else {
0
}
}
override fun value(x: Double, set: Values?): Double {
return this@ParametricFunction.derivValue(parName, x, set)
}
override fun providesDeriv(name: String?): Boolean {
return !names.contains(name)
}
val names: NameList
get() = this@ParametricFunction.getNames()
}
} else {
throw NotDefinedException()
}
}
}

View File

@ -0,0 +1,130 @@
/*
* 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 hep.dataforge.stat.parametric
import hep.dataforge.exceptions.NotDefinedException
/**
* Универсальная обертка, которая объединяет именованную и обычную функцию.
*
* @author Alexander Nozik
* @version $Id: $Id
*/
class ParametricMultiFunctionWrapper : hep.dataforge.stat.parametric.ParametricValue, MultiFunction {
private val multiFunc: MultiFunction?
private val nFunc: hep.dataforge.stat.parametric.ParametricValue?
private val names: NameList
constructor(names: NameList, multiFunc: MultiFunction?) {
this.names = names
nFunc = null
this.multiFunc = multiFunc
}
constructor(nFunc: hep.dataforge.stat.parametric.ParametricValue) {
names = nFunc.getNames()
this.nFunc = nFunc
multiFunc = null
}
/**
* {@inheritDoc}
*/
override fun derivValue(parName: String?, pars: Values): Double {
return if (nFunc != null) {
nFunc.derivValue(parName, pars)
} else {
require(pars.getNames().contains(names.asArray())) { "Wrong parameter set." }
require(names.contains(parName)) { "Wrong derivative parameter name." }
multiFunc.derivValue(getNumberByName(parName),
MathUtils.getDoubleArray(pars, getNames().asArray()))
}
}
/**
* {@inheritDoc}
*/
@Throws(NotDefinedException::class)
fun derivValue(n: Int, vector: DoubleArray?): Double {
return if (multiFunc != null) {
multiFunc.derivValue(n, vector)
} else {
val set = NamedVector(names.asArray(), vector)
nFunc!!.derivValue(names.asArray().get(n), set)
}
}
val dimension: Int
get() = getNames().size()
/**
* {@inheritDoc}
*/
fun getNames(): NameList {
return names
}
private fun getNumberByName(name: String?): Int {
return getNames().asList().indexOf(name)
}
/**
* {@inheritDoc}
*
*
* Подразумевается, что аналитически заданы все(!) производные
*/
fun providesDeriv(n: Int): Boolean {
return if (nFunc != null && nFunc.providesDeriv(getNames().asArray().get(n))) {
true
} else multiFunc != null && multiFunc.providesDeriv(n)
}
/**
* {@inheritDoc}
*/
override fun providesDeriv(name: String?): Boolean {
return if (nFunc != null) {
nFunc.providesDeriv(name)
} else {
multiFunc.providesDeriv(getNumberByName(name))
}
}
/**
* {@inheritDoc}
*/
override fun value(pars: Values): Double {
return if (nFunc != null) {
nFunc.value(pars)
} else {
require(pars.getNames().contains(names.asArray())) { "Wrong parameter set." }
this.value(MathUtils.getDoubleArray(pars, getNames().asArray()))
}
}
/**
* {@inheritDoc}
*/
override fun value(vector: DoubleArray?): Double {
return if (multiFunc != null) {
multiFunc.value(vector)
} else {
val set = NamedVector(names.asArray(), vector)
nFunc!!.value(set)
}
}
}

View File

@ -0,0 +1,151 @@
/*
* 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 hep.dataforge.stat.parametric
import hep.dataforge.exceptions.NameNotFoundException
/**
*
* ParametricUtils class.
*
* @author Alexander Nozik
* @version $Id: $Id
*/
object ParametricUtils {
/**
* Создает одномерное сечение многомерной именованной функции
*
* @param nFunc - исходная именованная функция
* @param parName - имя параметра, по которому делается сечение
* @param pars - Точка, вкоторой вычеслено сечение
* @return a [UniFunction] object.
*/
fun getNamedProjection(nFunc: ParametricValue, parName: String?, pars: Values?): UniFunction {
return object : UniFunction() {
var curPars: NamedVector = NamedVector(pars)
@Throws(NotDefinedException::class)
fun derivValue(x: Double): Double {
curPars.setValue(parName, x)
return nFunc.derivValue(parName, curPars)
}
fun providesDeriv(): Boolean {
return nFunc.providesDeriv(parName)
}
fun value(x: Double): Double {
curPars.setValue(parName, x)
return nFunc.value(curPars)
}
}
}
/**
*
* getNamedProjectionDerivative.
*
* @param nFunc a [hep.dataforge.stat.parametric.ParametricValue] object.
* @param parName a [String] object.
* @param derivativeName a [String] object.
* @param pars
* @return a [org.apache.commons.math3.analysis.UnivariateFunction] object.
*/
fun getNamedProjectionDerivative(
nFunc: ParametricValue,
parName: String?, derivativeName: String?, pars: Values?
): UnivariateFunction {
return object : UnivariateFunction() {
var curPars: NamedVector = NamedVector(pars)
fun value(x: Double): Double {
curPars.setValue(parName, x)
return nFunc.derivValue(derivativeName, curPars)
}
}
}
/**
* Функция, которая запоминает исходную точку, и при нехватке параметров
* берет значения оттуда.
*
* @param func a [hep.dataforge.stat.parametric.ParametricValue] object.
* @param initPars
* @param freePars - Описывает, каким параметрам можно будет изменяться.
* Если null, то разрешено изменение всех параметров.
* @return a [hep.dataforge.stat.parametric.ParametricValue] object.
*/
fun getNamedSubFunction(func: ParametricValue, initPars: Values, vararg freePars: String?): ParametricValue {
require(initPars.getNames().contains(func.namesAsArray())) { "InitPars does not cover all of func parameters." }
val names: NameList
if (freePars.size > 0) {
names = NameList(freePars)
} else {
names = initPars.getNames()
}
return object : AbstractParametricValue(names) {
private val allPars: NamedVector = NamedVector(initPars)
private val f: ParametricValue = func
override fun derivValue(derivParName: String?, pars: Values): Double {
if (!pars.getNames().contains(this.namesAsArray())) {
throw NameNotFoundException()
}
for (name in this.getNames()) {
allPars.setValue(name, pars.getDouble(name))
}
return f.derivValue(derivParName, allPars)
}
override fun providesDeriv(name: String?): Boolean {
return f.providesDeriv(name) && this.getNames().contains(name)
}
override fun value(pars: Values): Double {
if (!pars.getNames().contains(this.namesAsArray())) {
throw NameNotFoundException()
}
for (name in this.getNames()) {
allPars.setValue(name, pars.getDouble(name))
}
return f.value(allPars)
}
}
}
fun getSpectrumDerivativeFunction(name: String?, s: ParametricFunction, pars: Values?): UnivariateFunction {
return UnivariateFunction { x: Double -> s.derivValue(name, x, pars) }
}
fun getSpectrumFunction(s: ParametricFunction, pars: Values?): UnivariateFunction {
return UnivariateFunction { x: Double -> s.value(x, pars) }
}
fun getSpectrumPointFunction(s: ParametricFunction, x: Double): ParametricValue {
return object : AbstractParametricValue(s) {
@Throws(NotDefinedException::class, NamingException::class)
override fun derivValue(derivParName: String?, pars: Values?): Double {
return s.derivValue(derivParName, x, pars)
}
override fun providesDeriv(name: String?): Boolean {
return s.providesDeriv(name)
}
@Throws(NamingException::class)
override fun value(pars: Values?): Double {
return s.value(x, pars)
}
}
}
}

View File

@ -0,0 +1,52 @@
/*
* 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 hep.dataforge.stat.parametric
import hep.dataforge.exceptions.NotDefinedException
/**
* A function mapping parameter set to real value
*
* @author Alexander Nozik
*/
interface ParametricValue : NameSetContainer {
/**
* Value
* @param pars
* @return
*/
fun value(pars: Values?): Double
/**
* Partial derivative value for given parameter
* @param derivParName
* @param pars
* @return
*/
fun derivValue(derivParName: String?, pars: Values?): Double {
throw NotDefinedException()
}
/**
* Returns true if this object provides explicit analytical value derivative for given parameter
*
* @param name a [String] object.
* @return a boolean.
*/
fun providesDeriv(name: String?): Boolean {
return false
}
}

View File

@ -0,0 +1,169 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.models.sterile
import hep.dataforge.context.Context
import hep.dataforge.description.NodeDef
import hep.dataforge.description.NodeDefs
import hep.dataforge.description.ValueDef
import hep.dataforge.description.ValueDefs
import hep.dataforge.exceptions.NotDefinedException
import hep.dataforge.maths.integration.UnivariateIntegrator
import hep.dataforge.meta.Meta
import hep.dataforge.stat.parametric.AbstractParametricBiFunction
import hep.dataforge.stat.parametric.AbstractParametricFunction
import hep.dataforge.stat.parametric.ParametricBiFunction
import hep.dataforge.values.ValueType.BOOLEAN
import hep.dataforge.values.Values
import inr.numass.getFSS
import inr.numass.models.FSS
import inr.numass.models.misc.LossCalculator
import inr.numass.utils.NumassIntegrator
/**
* Compact all-in-one model for sterile neutrino spectrum
*
* @author Alexander Nozik
*/
@NodeDefs(
NodeDef(key = "resolution"),
NodeDef(key = "transmission")
)
@ValueDefs(
ValueDef(key = "fssFile", info = "The name for external FSS file. By default internal FSS file is used"),
ValueDef(key = "useFSS", type = arrayOf(BOOLEAN))
)
/**
* @param source variables:Eo offset,Ein; parameters: "mnu2", "msterile2", "U2"
* @param transmission variables:Ein,Eout; parameters: "A"
* @param resolution variables:Eout,U; parameters: "X", "trap"
*/
class SterileNeutrinoSpectrum @JvmOverloads constructor(
context: Context,
configuration: Meta,
val source: ParametricBiFunction = NumassBeta(),
val transmission: ParametricBiFunction = NumassTransmission(context, configuration.getMetaOrEmpty("transmission")),
val resolution: ParametricBiFunction = NumassResolution(context, configuration.getMeta("resolution", Meta.empty()))
) : AbstractParametricFunction(*list) {
/**
* auxiliary function for trans-res convolution
*/
private val transRes: ParametricBiFunction = TransRes()
private val fss: FSS? = getFSS(context, configuration)
// private boolean useMC;
private val fast: Boolean = configuration.getBoolean("fast", true)
override fun derivValue(parName: String, u: Double, set: Values): Double {
return when (parName) {
"U2", "msterile2", "mnu2", "E0" -> integrate(u, source.derivative(parName), transRes, set)
"X", "trap" -> integrate(u, source, transRes.derivative(parName), set)
else -> throw NotDefinedException()
}
}
override fun value(u: Double, set: Values): Double {
return integrate(u, source, transRes, set)
}
override fun providesDeriv(name: String): Boolean {
return source.providesDeriv(name) && transmission.providesDeriv(name) && resolution.providesDeriv(name)
}
/**
* Direct Gauss-Legendre integration
*
* @param u
* @param sourceFunction
* @param transResFunction
* @param set
* @return
*/
private fun integrate(
u: Double,
sourceFunction: ParametricBiFunction,
transResFunction: ParametricBiFunction,
set: Values): Double {
val eMax = set.getDouble("E0") + 5.0
if (u >= eMax) {
return 0.0
}
val integrator: UnivariateIntegrator<*> = if (fast) {
when {
eMax - u < 300 -> NumassIntegrator.getFastInterator()
eMax - u > 2000 -> NumassIntegrator.getHighDensityIntegrator()
else -> NumassIntegrator.getDefaultIntegrator()
}
} else {
NumassIntegrator.getHighDensityIntegrator()
}
return integrator.integrate(u, eMax) { eIn -> sumByFSS(eIn, sourceFunction, set) * transResFunction.value(eIn, u, set) }
}
private fun sumByFSS(eIn: Double, sourceFunction: ParametricBiFunction, set: Values): Double {
return if (fss == null) {
sourceFunction.value(0.0, eIn, set)
} else {
(0 until fss.size()).sumByDouble { fss.getP(it) * sourceFunction.value(fss.getE(it), eIn, set) }
}
}
private inner class TransRes : AbstractParametricBiFunction(arrayOf("X", "trap")) {
override fun providesDeriv(name: String): Boolean {
return true
}
override fun derivValue(parName: String, eIn: Double, u: Double, set: Values): Double {
return when (parName) {
"X" -> throw NotDefinedException()//TODO implement p0 derivative
"trap" -> lossRes(transmission.derivative(parName), eIn, u, set)
else -> super.derivValue(parName, eIn, u, set)
}
}
override fun value(eIn: Double, u: Double, set: Values): Double {
val p0 = LossCalculator.p0(set, eIn)
return p0 * resolution.value(eIn, u, set) + lossRes(transmission, eIn, u, set)
}
private fun lossRes(transFunc: ParametricBiFunction, eIn: Double, u: Double, set: Values): Double {
val integrand = { eOut: Double -> transFunc.value(eIn, eOut, set) * resolution.value(eOut, u, set) }
val border = u + 30
val firstPart = NumassIntegrator.getFastInterator().integrate(u, Math.min(eIn, border), integrand)
val secondPart: Double = if (eIn > border) {
if (fast) {
NumassIntegrator.getDefaultIntegrator().integrate(border, eIn, integrand)
} else {
NumassIntegrator.getHighDensityIntegrator().integrate(border, eIn, integrand)
}
} else {
0.0
}
return firstPart + secondPart
}
}
companion object {
private val list = arrayOf("X", "trap", "E0", "mnu2", "msterile2", "U2")
}
}

View File

@ -6,8 +6,8 @@ pluginManagement {
gradlePluginPortal() gradlePluginPortal()
} }
val toolsVersion = "0.9.3" val toolsVersion = "0.9.5-dev"
val kotlinVersion = "1.4.32" val kotlinVersion = "1.5.0-M2"
plugins { plugins {
id("ru.mipt.npm.gradle.project") version toolsVersion id("ru.mipt.npm.gradle.project") version toolsVersion