Skip to content
Snippets Groups Projects
Verified Commit ad944546 authored by Frank Sauerburger's avatar Frank Sauerburger
Browse files

Implement rebin

parent 4c7bff5e
No related branches found
No related tags found
2 merge requests!10Resolve "Restructure Graph code",!9Draft: Resolve "Add React interface"
Pipeline #7187 passed
......@@ -97,3 +97,51 @@ export const sumStat = (yields, process_names, bin_index=null) => (
bin_index
})
)
/**
* Rebin a single series of values.
*
* @param series Array of bin contents
* @param old_edges Bin boundaries of the original series array. Should
* have one more value than series.
* @param new_edges Bin boundaries of the target series.
* @param pre Callback that maps values before summing them. Should
* be identify for the yields, and the square for
* statistical uncetainties.
* @param post Callback that maps values after summing them to undo
* the effect of pre. Should be identify for the yields,
* and the square root for statistical uncetainties.
*/
export const rebin = (
series,
old_edges,
new_edges,
pre = (x) => x,
post = (x) => x,
) => {
if (series.length != old_edges.length + 1) {
throw new Error("Incompatible number of values and edges")
}
new_edges.forEach(e => {
if (old_edges.indexOf(e) < 0) {
throw new Error("New edges are not a subset of old edges")
}
})
const ref_edges = [old_edges[0] - 1, ...old_edges]
const target_index = series.map((value, i) => {
const low_edge = ref_edges[i];
const bins_to_the_left = new_edges.map((x, i) => [x, i]).filter(d => d[0] <= low_edge).map(d => d[1]).reverse()
if (bins_to_the_left.length > 0) {
return bins_to_the_left[0] + 1
}
return 0
})
const range = Array(new_edges.length + 1).fill(0).map((x, i) => i)
const result = range.map(i =>
series.filter((v, j) => target_index[j] == i).map(x => pre(x)).reduce((a, b) => a + b, 0)
)
return result.map(x => post(x))
}
export const preprocessData = ( ) => 0
import { use, assert, expect } from 'chai';
import chaiAlmost from 'chai-almost';
import { sumBase, sumStat } from "../src/helpers/uhepp.js";
import { sumBase, sumStat, rebin } from "../src/helpers/uhepp.js";
use(chaiAlmost())
const toy_yield = {
"process_a": {
"base": [ 0, 1, 2, 3, 4, 5],
"stat": [0.1, 0.1, 0.1, 0.1, 0.1]
},
"process_b": {
"base": [10, 12, 14, 16, 18, 20],
"stat": [1.0, 1.2, 1.4, 1.6, 1.8, 2.0]
},
"process_c": {
"base": [ 4, 4, -5, -5, -6, 5],
"stat": [ 0.4, 0.4, 0.5, 0.5, 0.6, 0.6]
}
}
describe("sumBase", () => {
const toy_yield = {
"process_a": {
"base": [ 0, 1, 2, 3, 4, 5],
"stat": [0.1, 0.1, 0.1, 0.1, 0.1]
},
"process_b": {
"base": [10, 12, 14, 16, 18, 20],
"stat": [1.0, 1.2, 1.4, 1.6, 1.8, 2.0]
},
"process_c": {
"base": [ 4, 4, -5, -5, -6, 5],
"stat": [ 0.4, 0.4, 0.5, 0.5, 0.6, 0.6]
}
}
it("should return 0 if the yield object is empty", () => {
const sum = sumBase({}, ["process_a", "process_b"])
assert.equal(sum, 0);
......@@ -72,6 +72,21 @@ describe("sumBase", () => {
});
describe("sumStat", () => {
const toy_yield = {
"process_a": {
"base": [ 0, 1, 2, 3, 4, 5],
"stat": [0.1, 0.1, 0.1, 0.1, 0.1]
},
"process_b": {
"base": [10, 12, 14, 16, 18, 20],
"stat": [1.0, 1.2, 1.4, 1.6, 1.8, 2.0]
},
"process_c": {
"base": [ 4, 4, -5, -5, -6, 5],
"stat": [ 0.4, 0.4, 0.5, 0.5, 0.6, 0.6]
}
}
it("should return 0 if the yield object is empty", () => {
const sum = sumStat({}, ["process_a", "process_b"])
assert.equal(sum, 0);
......@@ -122,3 +137,52 @@ describe("sumStat", () => {
assert.equal(sum, 0);
})
});
describe("rebin", () => {
const toy_series = [-3, 1, 2, 4, 8, 16, 32, 64]
const old_edges = [0, 10, 20, 30, 40, 50, 60]
it("should return the original values if both edges are identical", () => {
const rebinned = rebin(toy_series, old_edges, old_edges)
assert.deepEqual(rebinned, toy_series)
})
it("should raise an exception if the new edges are not a subset", () => {
assert.throws(
() => rebin(toy_series, old_edges, [0, 5, 15, 60]),
/subset/
)
})
it("should sum the entries of merged bins", () => {
const new_edges = [0, 20, 50, 60]
const rebinned = rebin(toy_series, old_edges, new_edges)
assert.deepEqual(rebinned, [-3, 3, 28, 32, 64])
})
it("should sum all entries for a single bin output", () => {
const new_edges = [0, 60]
const rebinned = rebin(toy_series, old_edges, new_edges)
assert.deepEqual(rebinned, [-3, 63, 64])
})
it("should discard bins outside new edges", () => {
const new_edges = [10, 30, 50]
const rebinned = rebin(toy_series, old_edges, new_edges)
assert.deepEqual(rebinned, [-2, 6, 24, 96])
})
it("should raise an exception if the input lengths are incompatible", () => {
const new_edges = [10, 30, 50]
assert.throws(
() => rebin(toy_series, new_edges, new_edges),
/number/
)
})
it("should apply pre and post to merged bin values", () => {
const new_edges = [0, 20, 50, 60]
const rebinned = rebin(
toy_series,
old_edges,
new_edges,
(x) => x + 1,
(x) => x * x,
)
assert.deepEqual(rebinned, [4, 25, 31*31, 33*33, 65*65])
})
})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment