Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Roel Aaij
k40gen
Commits
6c54ce72
Commit
6c54ce72
authored
Feb 27, 2019
by
Roel Aaij
Browse files
Fix generation of values and coincidences. Tests work.
parent
c9b7f6f5
Changes
14
Hide whitespace changes
Inline
Side-by-side
CMakeLists.txt
View file @
6c54ce72
...
...
@@ -113,7 +113,6 @@ endif()
set
(
generate_SOURCES
src/generate/generate.cpp
src/generate/storage.cpp
src/generate/generate_scalar.cpp
)
if
(
USE_AVX2
)
...
...
lib/generate/generate_common.h
View file @
6c54ce72
...
...
@@ -74,14 +74,17 @@ public:
return
1.0e9
f
/
m_rates
[
0
];
}
size_t
n_expect
(
const
long
interval
)
const
{
float
total_rate
=
std
::
accumulate
(
begin
(
m_rates
),
end
(
m_rates
),
0.
f
);
size_t
n_expect
(
const
long
interval
,
bool
include_l0
)
const
{
using
namespace
Constants
;
float
l0_rate
=
include_l0
?
m_rates
[
0
]
:
0.
f
;
float
l1_rate
=
std
::
accumulate
(
std
::
next
(
begin
(
m_rates
)),
end
(
m_rates
),
0.
f
);
// Fudge with 30% extra space to avoid reallocating
double
n_per_pmt
=
1.3
*
total_rate
*
(
double
)(
interval
)
/
1e9
;
if
(
n_per_pmt
>
std
::
numeric_limits
<
float
>::
max
())
{
double
n_per_pmt
=
1.3
*
(
l0_rate
+
3.
f
*
l1_rate
)
*
(
double
)(
interval
)
/
1e9
;
auto
n_pmts
=
n_dom
*
n_mod
*
n_pmt
;
if
(
n_per_pmt
>
std
::
numeric_limits
<
float
>::
max
()
/
n_pmts
)
{
throw
std
::
domain_error
{
"rate of "
+
std
::
to_string
(
n_per_pmt
)
+
" is too large"
};
}
return
std
::
lround
(
Constants
::
n_dom
*
Constants
::
n_mod
*
(
float
)
n_per_pmt
);
return
std
::
lround
(
n_pmts
*
(
float
)
n_per_pmt
);
}
};
...
...
@@ -112,8 +115,8 @@ unsigned int random_index(const Container& buffer, const double random) {
}
}
std
::
tuple
<
s
td
::
array
<
unsigned
int
,
4
>
,
size_t
>
fill_coincidences
(
storage_t
&
times
,
size_t
idx
,
std
::
tuple
<
s
ize_t
,
size_t
>
fill_coincidences
(
storage_t
&
times
,
pmts_t
&
pmts
,
size_t
idx
,
const
long
time_start
,
const
long
time_end
,
Generators
&
gens
);
...
...
lib/generate/storage.h
View file @
6c54ce72
...
...
@@ -15,23 +15,15 @@
*/
#pragma once
#ifdef HAVE_CUDA
#include
<thrust/host_vector.h>
#include
<thrust/system/cuda/experimental/pinned_allocator.h>
#else
#include
<vector>
#endif
#include
"aligned_allocator.h"
namespace
storage
{
extern
int
n_per_mod
;
}
#ifdef HAVE_CUDA
using
storage_t
=
thrust
::
host_vector
<
long
,
thrust
::
cuda
::
experimental
::
pinned_allocator
<
int
>>
;
#ifdef USE_AVX2
#include
<Vc/Allocator>
using
storage_t
=
std
::
vector
<
long
,
Vc
::
Allocator
<
long
>>
;
using
pmts_t
=
std
::
vector
<
int
,
Vc
::
Allocator
<
int
>>
;
#else
using
storage_t
=
std
::
vector
<
long
,
aligned_allocator
<
long
>>
;
using
storage_t
=
std
::
vector
<
long
>
;
using
pmts_t
=
std
::
vector
<
int
>
;
#endif
using
queue_t
=
std
::
vector
<
std
::
tuple
<
storage_t
,
storage_t
>>
;
src/generate/generate.cpp
View file @
6c54ce72
...
...
@@ -27,7 +27,6 @@
namespace
{
using
std
::
cout
;
using
std
::
endl
;
using
std
::
pair
;
using
std
::
vector
;
using
std
::
array
;
...
...
@@ -75,8 +74,8 @@ float cross_prob(const float ct) {
return
std
::
exp
(
ct
*
(
Constants
::
p2
+
ct
*
(
Constants
::
p3
+
ct
*
Constants
::
p4
)));
}
std
::
tuple
<
array
<
unsigned
int
,
4
>
,
size_t
>
fill_coincidences
(
storage_t
&
times
,
size_t
idx
,
std
::
tuple
<
size_t
,
size_t
>
fill_coincidences
(
storage_t
&
times
,
pmts_t
&
pmts
,
size_t
idx
,
const
long
time_start
,
const
long
time_end
,
Generators
&
gen
)
{
const
auto
&
prob1D
=
gen
.
prob1D
;
...
...
@@ -85,21 +84,23 @@ fill_coincidences(storage_t& times, size_t idx,
auto
&
mt
=
gen
.
mt
;
auto
&
flat
=
gen
.
flat
;
array
<
unsigned
int
,
4
>
pmts
;
std
::
fill
(
begin
(
pmts
),
end
(
pmts
),
0
)
;
if
(
gen
.
coincidence_rate
<
0.001
)
{
return
{
pmts
,
0
};
return
{
0
,
0
};
}
pmts
.
clear
();
// Fill coincidences
size_t
n
=
0
;
for
(
long
t1
=
time_start
;
t1
<
time_end
;
t1
+=
gen
.
coincidence
(
mt
))
{
++
n
;
// generate two-fold coincidence
const
unsigned
int
pmt1
=
random_index
(
prob1D
,
flat
(
mt
));
const
unsigned
int
pmt2
=
random_index
(
prob2D
[
pmt1
],
flat
(
mt
));
pmts
[
n
++
]
=
pmt1
;
pmts
[
n
++
]
=
pmt2
;
pmts
.
emplace_back
(
pmt1
)
;
pmts
.
emplace_back
(
pmt2
)
;
std
::
normal_distribution
<
double
>
gauss
(
t1
,
0.5
);
times
[
++
idx
]
=
std
::
lround
(
gauss
(
mt
));
...
...
@@ -117,28 +118,28 @@ fill_coincidences(storage_t& times, size_t idx,
probND
[
pmtN
]
=
0.0
;
pmtN
=
random_index
(
probND
,
flat
(
mt
));
pmts
[
n
++
]
=
pmtN
;
pmts
.
emplace_back
(
pmtN
)
;
times
[
++
idx
]
=
std
::
lround
(
gauss
(
mt
));
}
}
}
catch
(
const
std
::
domain_error
&
)
{}
}
return
{
pmts
,
n
};
return
{
pmts
.
size
()
,
n
};
}
std
::
tuple
<
storage_t
,
storage_t
>
generate
(
const
long
start
,
const
long
end
,
Generators
&
gens
,
bool
use_avx2
)
{
#ifdef USE_AVX2
if
(
use_avx2
)
{
std
::
cout
<<
"Generating AVX2
"
<<
std
::
endl
;
std
::
cout
<<
"Generating AVX2
\n
"
;
return
generate_avx2
(
start
,
end
,
gens
);
}
else
{
std
::
cout
<<
"Generating scalar
"
<<
std
::
endl
;
std
::
cout
<<
"Generating scalar
\n
"
;
return
generate_scalar
(
start
,
end
,
gens
);
}
#else
std
::
cout
<<
"Generating scalar
"
<<
std
::
endl
;
std
::
cout
<<
"Generating scalar
\n
"
;
return
generate_scalar
(
start
,
end
,
gens
);
#endif
}
src/generate/generate_avx2.cpp
View file @
6c54ce72
...
...
@@ -15,6 +15,7 @@
*/
#include
<cassert>
#include
<tuple>
#include
<functional>
#include
<Vc/Vc>
#include
<instrset.h>
...
...
@@ -58,6 +59,45 @@ inline int_v scan_AVX(int_v x) {
return
x
;
}
auto
int_v_to_long_v
(
const
int_v
&
in
)
->
pair
<
long_v
,
long_v
>
{
return
{
Vc
::
AvxIntrinsics
::
cvtepi32_epi64
(
Vc
::
AVX
::
lo128
(
in
.
data
())),
Vc
::
AvxIntrinsics
::
cvtepi32_epi64
(
Vc
::
AVX
::
hi128
(
in
.
data
()))};
};
void
fill_values_avx2
(
long
idx_start
,
long
idx_end
,
storage_t
&
values
,
Ranvec1
&
random
,
int
dom
,
int
mod
,
std
::
function
<
int_v
(
size_t
)
>
pmt_fun
)
{
// fill values
size_t
n
=
0
;
const
long
value_end
=
idx_end
+
(
2
*
long_v
::
size
()
-
(
idx_end
%
2
*
long_v
::
size
()));
for
(
long
vidx
=
idx_start
;
vidx
<
value_end
;
vidx
+=
2
*
long_v
::
size
())
{
int_v
pmt1
=
pmt_fun
(
n
++
);
int_v
pmt2
=
pmt_fun
(
n
++
);
auto
u1
=
float_v
{
random
.
random8f
()};
auto
u2
=
float_v
{
random
.
random8f
()}
*
Constants
::
two_pi
;
auto
fact
=
sqrt
(
-
2.0
f
*
log
(
u1
));
float_v
z0
,
z1
;
sincos
(
u2
,
&
z0
,
&
z1
);
z0
=
fact
*
tot_sigma
*
z0
+
tot_mean
;
z1
=
fact
*
tot_sigma
*
z1
+
tot_mean
;
auto
val0
=
simd_cast
<
int_v
>
(
z0
)
|
(
pmt1
<<
8
)
|
((
100
*
(
dom
+
1
)
+
mod
+
1
)
<<
13
);
auto
[
val0_first
,
val0_second
]
=
int_v_to_long_v
(
val0
);
val0_first
.
store
(
&
values
[
vidx
]);
val0_second
.
store
(
&
values
[
vidx
+
long_v
::
size
()]);
auto
val1
=
simd_cast
<
int_v
>
(
z1
)
|
(
pmt2
<<
8
)
|
((
100
*
(
dom
+
1
)
+
mod
+
1
)
<<
13
);
auto
[
val1_first
,
val1_second
]
=
int_v_to_long_v
(
val1
);
val1_first
.
store
(
&
values
[
vidx
+
2
*
long_v
::
size
()]);
val1_second
.
store
(
&
values
[
vidx
+
3
*
long_v
::
size
()]);
}
}
std
::
tuple
<
storage_t
,
storage_t
>
generate_avx2
(
const
long
time_start
,
const
long
time_end
,
Generators
&
gens
)
{
...
...
@@ -67,27 +107,22 @@ std::tuple<storage_t, storage_t> generate_avx2(const long time_start, const long
// Assume times.size() is multiple of 8 here
// assert(storage::n_hits % 16 == 0);
const
size_t
n_expect
=
gens
.
n_expect
(
time_end
-
time_start
);
const
size_t
n_expect
=
gens
.
n_expect
(
time_end
-
time_start
,
true
);
const
size_t
n_expect_pmts
=
gens
.
n_expect
(
time_end
-
time_start
,
false
);
const
float
tau_l0
=
gens
.
tau_l0
();
size_t
storage_size
=
n_expect
+
long_v
::
size
()
-
n_expect
%
long_v
::
size
();
storage_t
times
;
times
.
resize
(
storage_size
);
storage_t
values
;
values
.
resize
(
storage_size
+
2
*
long_v
::
size
());
auto
int_v_to_long_v
=
[]
(
const
int_v
&
in
)
->
pair
<
long_v
,
long_v
>
{
return
{
Vc
::
AvxIntrinsics
::
cvtepi32_epi64
(
Vc
::
AVX
::
lo128
(
in
.
data
())),
Vc
::
AvxIntrinsics
::
cvtepi32_epi64
(
Vc
::
AVX
::
hi128
(
in
.
data
()))};
};
pmts_t
pmts
(
n_expect_pmts
+
long_v
::
size
()
-
n_expect_pmts
%
long_v
::
size
(),
0
);
size_t
idx
=
0
;
// First generate some data
for
(
int
dom
=
0
;
dom
<
Constants
::
n_dom
;
++
dom
)
{
for
(
int
mod
=
0
;
mod
<
Constants
::
n_mod
;
++
mod
)
{
size_t
mod_start
=
idx
;
for
(
int
pmt
=
0
;
pmt
<
Constants
::
n_pmt
;
++
pmt
)
{
size_t
pmt_start
=
idx
;
long_v
offset
;
offset
.
data
()
=
_mm256_set1_epi64x
(
time_start
);
long
last
=
time_start
;
...
...
@@ -121,38 +156,20 @@ std::tuple<storage_t, storage_t> generate_avx2(const long time_start, const long
// When filling, fill the past and current indices
idx
+=
2
*
long_v
::
size
();
}
}
// Coincidences
auto
[
pmts
,
n_coincidence
]
=
fill_coincidences
(
times
,
idx
,
time_start
,
time_end
,
gens
);
idx
+=
n_coincidence
;
// fill values
const
size_t
value_end
=
idx
+
(
2
*
long_v
::
size
()
-
(
idx
%
2
*
long_v
::
size
()));
for
(
size_t
vidx
=
mod_start
;
vidx
<
value_end
;
vidx
+=
2
*
long_v
::
size
())
{
int_v
pmt1
{
random
.
random8i
(
0
,
31
)};
int_v
pmt2
{
random
.
random8i
(
0
,
31
)};
fill_values_avx2
(
pmt_start
,
idx
,
values
,
random
,
dom
,
mod
,
[
pmt
](
size_t
)
{
return
int_v
(
pmt
);
});
auto
u1
=
float_v
{
random
.
random8f
()};
auto
u2
=
float_v
{
random
.
random8f
()}
*
Constants
::
two_pi
;
auto
fact
=
sqrt
(
-
2.0
f
*
log
(
u1
));
float_v
z0
,
z1
;
sincos
(
u2
,
&
z0
,
&
z1
);
z0
=
fact
*
tot_sigma
*
z0
+
tot_mean
;
z1
=
fact
*
tot_sigma
*
z1
+
tot_mean
;
auto
val0
=
simd_cast
<
int_v
>
(
z0
)
|
(
pmt1
<<
8
)
|
((
100
*
(
dom
+
1
)
+
mod
+
1
)
<<
13
);
auto
[
val0_first
,
val0_second
]
=
int_v_to_long_v
(
val0
);
}
val0_first
.
store
(
&
values
[
vidx
]);
val0_second
.
store
(
&
values
[
vidx
+
long_v
::
size
()]);
// Coincidences
auto
[
n_times
,
_
]
=
fill_coincidences
(
times
,
pmts
,
idx
,
time_start
,
time_end
,
gens
);
fill_values_avx2
(
idx
,
idx
+
n_times
,
values
,
random
,
dom
,
mod
,
[
&
pmts
](
size_t
n
)
{
return
int_v
(
pmts
.
data
()
+
n
*
int_v
::
size
());
});
idx
+=
n_times
;
auto
val1
=
simd_cast
<
int_v
>
(
z1
)
|
(
pmt2
<<
8
)
|
((
100
*
(
dom
+
1
)
+
mod
+
1
)
<<
13
);
auto
[
val1_first
,
val1_second
]
=
int_v_to_long_v
(
val1
);
val1_first
.
store
(
&
values
[
vidx
+
2
*
long_v
::
size
()]);
val1_second
.
store
(
&
values
[
vidx
+
3
*
long_v
::
size
()]);
}
}
}
times
.
resize
(
idx
);
...
...
src/generate/generate_scalar.cpp
View file @
6c54ce72
...
...
@@ -16,6 +16,8 @@
#include
<cassert>
#include
<stdexcept>
#include
<vector>
#include
<functional>
#include
<iostream>
#include
<tuple>
#include
<optional>
...
...
@@ -28,9 +30,7 @@ namespace {
const
float
tot_mean
=
Constants
::
tot_mean
;
const
float
tot_sigma
=
Constants
::
tot_sigma
;
using
namespace
storage
;
using
std
::
cout
;
using
std
::
endl
;
using
std
::
array
;
}
...
...
@@ -43,26 +43,15 @@ float GenScalar::dot_product(const std::array<float, 3>& left, const std::array<
}
void
fill_values_scalar
(
long
idx_start
,
long
idx_end
,
storage_t
&
values
,
Generators
&
gens
,
int
dom
,
int
mod
,
const
std
::
optional
<
array
<
unsigned
int
,
4
>>&
pmts
)
{
std
::
function
<
unsigned
int
(
size_t
)
>
pmt_fun
)
{
// fill values
std
::
uniform_int_distribution
<
long
>
flat_pmt
(
0
,
31
);
auto
&
mt
=
gens
.
mt
;
auto
&
flat
=
gens
.
flat
;
if
(
pmts
)
{
assert
((
idx_end
-
idx_start
)
<
pmts
->
size
());
}
size_t
n
=
0
;
for
(
long
vidx
=
idx_start
;
vidx
<
idx_end
;
vidx
+=
2
)
{
unsigned
int
pmt1
=
0
,
pmt2
=
0
;
if
(
pmts
)
{
pmt1
=
(
*
pmts
)[
n
++
];
pmt2
=
(
*
pmts
)[
n
++
];
}
else
{
pmt1
=
flat_pmt
(
mt
);
pmt2
=
flat_pmt
(
mt
);
}
auto
pmt1
=
pmt_fun
(
n
++
);
auto
pmt2
=
pmt_fun
(
n
++
);
auto
u1
=
flat
(
mt
);
auto
u2
=
flat
(
mt
)
*
Constants
::
two_pi
;
...
...
@@ -88,36 +77,39 @@ std::tuple<storage_t, storage_t> generate_scalar(const long time_start, const lo
auto
&
mt
=
gens
.
mt
;
auto
&
flat
=
gens
.
flat
;
const
size_t
n_expect
=
gens
.
n_expect
(
time_end
-
time_start
);
const
size_t
n_expect
=
gens
.
n_expect
(
time_end
-
time_start
,
true
);
const
float
tau_l0
=
gens
.
tau_l0
();
storage_t
times
;
times
.
resize
(
n_expect
);
storage_t
values
;
values
.
resize
(
n_expect
+
1
);
const
size_t
n_expect_pmts
=
gens
.
n_expect
(
time_end
-
time_start
,
false
);
pmts_t
pmts
(
n_expect_pmts
,
0
);
size_t
idx
=
0
;
// First generate some data
for
(
int
dom
=
0
;
dom
<
Constants
::
n_dom
;
++
dom
)
{
for
(
int
mod
=
0
;
mod
<
Constants
::
n_mod
;
++
mod
)
{
size_t
mod_start
=
idx
;
for
(
int
pmt
=
0
;
pmt
<
Constants
::
n_pmt
;
++
pmt
)
{
long
last
=
time_start
;
while
(
last
<
time_end
&&
idx
<
times
.
size
()
-
2
)
{
// Generate times
float
r
=
-
1.
f
*
tau_l0
*
log
(
flat
(
mt
));
last
+=
static_cast
<
long
>
(
r
+
0.5
);
times
[
idx
++
]
=
last
;
}
size_t
pmt_start
=
idx
;
long
last
=
time_start
;
while
(
last
<
time_end
&&
idx
<
times
.
size
()
-
2
)
{
// Generate times
float
r
=
-
1.
f
*
tau_l0
*
log
(
flat
(
mt
));
last
+=
static_cast
<
long
>
(
r
+
0.5
);
times
[
idx
++
]
=
last
;
}
fill_values_scalar
(
pmt_start
,
idx
,
values
,
gens
,
dom
,
mod
,
[
pmt
](
size_t
)
{
return
pmt
;
});
}
fill_values_scalar
(
mod_start
,
idx
,
values
,
gens
,
dom
,
mod
,
{});
// Coincidences
auto
[
pmts
,
n_coincidence
]
=
fill_coincidences
(
times
,
idx
,
time_start
,
time_end
,
gens
);
idx
+=
n_coincidence
;
fill_values_scalar
(
mod_start
,
idx
,
values
,
gens
,
dom
,
mod
,
pmts
);
auto
[
n_times
,
_
]
=
fill_coincidences
(
times
,
pmts
,
idx
,
time_start
,
time_end
,
gens
);
fill_values_scalar
(
idx
,
idx
+
n_times
,
values
,
gens
,
dom
,
mod
,
[
&
pmts
](
size_t
n
)
{
assert
(
n
<
pmts
.
size
());
return
pmts
[
n
];
});
idx
+=
n_times
;
}
}
times
.
resize
(
idx
);
...
...
src/generate/storage.cpp
deleted
100644 → 0
View file @
c9b7f6f5
/*
* Copyright 2018-2019 NWO-I
*
* 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.
*/
#include
"storage.h"
int
storage
::
n_per_mod
=
21760
;
src/k40gen/bindings.cpp
View file @
6c54ce72
...
...
@@ -37,10 +37,10 @@ generate_k40(const long time_start, const long time_end, Generators& gens, bool
// factory for lambda's to shift and mask the values back into their
// components.
auto
shift_mask_fact
=
[
&
values
]
(
const
size_t
shift
,
const
long
mask
)
{
return
[
&
values
,
shift
,
mask
]
(
const
auto
val
)
{
return
(
val
>>
shift
)
&
mask
;
};
auto
shift_mask_fact
=
[]
(
const
size_t
shift
,
const
long
mask
)
{
return
[
shift
,
mask
]
(
const
auto
val
)
{
return
(
val
>>
shift
)
&
mask
;
};
};
// column in the output array
...
...
tests/CMakeLists.txt
View file @
6c54ce72
...
...
@@ -59,6 +59,8 @@ if (ROOT_FOUND)
generate
test_functions
${
ROOT_LIBRARIES
}
)
add_test
(
TestK40ROOT test_k40gen_root
)
endif
()
find_package
(
Python3 COMPONENTS Interpreter
)
...
...
tests/include/test_functions.h
View file @
6c54ce72
#pragma once
#include
<array>
#include
<unordered_map>
#include
<tuple>
template
<
std
::
size_t
N
>
...
...
@@ -15,5 +14,4 @@ struct get_n {
std
::
pair
<
double
,
double
>
generate_l0
(
float
l0_rate
,
long
dt
,
bool
use_avx2
);
std
::
tuple
<
double
,
double
,
std
::
unordered_map
<
size_t
,
double
>>
coincidence_rate
(
std
::
array
<
float
,
4
>
rates
);
std
::
tuple
<
double
,
double
>
coincidence_rate
(
std
::
array
<
float
,
4
>
rates
);
tests/lib/coincidences.cpp
View file @
6c54ce72
...
...
@@ -9,29 +9,26 @@
using
namespace
std
;
tuple
<
double
,
double
,
unordered_map
<
size_t
,
double
>
>
tuple
<
double
,
double
>
coincidence_rate
(
array
<
float
,
4
>
rates
)
{
Generators
gens
{
1052
,
9523
,
rates
};
auto
l1_rate
=
std
::
accumulate
(
std
::
next
(
begin
(
rates
)),
end
(
rates
),
0.
);
long
dt
=
std
::
lround
(
1e9
);
long
dt
=
std
::
lround
(
1e7
);
const
size_t
n_expect
=
gens
.
n_expect
(
dt
);
storage_t
times
;
times
.
resize
(
n_expect
);
storage_t
values
;
values
.
resize
(
n_expect
);
storage_t
times
;
times
.
resize
(
3
*
l1_rate
);
storage_t
values
;
values
.
resize
(
3
*
l1_rate
);
pmts_t
pmts
(
3
*
l1_rate
);
long
time_start
=
0
,
time_end
=
0
;
double
av
=
0.
;
const
int
n_iter
=
10000
;
unordered_map
<
size_t
,
double
>
count
;
const
int
n_iter
=
5000
;
for
(
int
i
=
0
;
i
<
n_iter
;
++
i
)
{
time_end
+=
dt
;
auto
[
pmts
,
n_coincidence
]
=
fill_coincidences
(
times
,
0ul
,
time_start
,
time_end
,
gens
);
count
[
n_coincidence
]
+=
1
/
double
{
n_iter
};
av
+=
n_coincidence
/
double
{
n_iter
};
auto
[
n_times
,
n_coincidences
]
=
fill_coincidences
(
times
,
pmts
,
0ul
,
time_start
,
time_end
,
gens
);
av
+=
n_coincidences
/
double
{
n_iter
};
time_start
=
time_end
;
}
return
{
gens
.
coincidence_rate
,
av
,
count
};
return
{
gens
.
coincidence_rate
,
av
};
}
tests/lib/generate.cpp
View file @
6c54ce72
...
...
@@ -18,7 +18,7 @@ pair<double, double> generate_l0(float l0_rate, long dt, bool use_avx2) {
double
av
=
0.
;
const
size_t
n_times
=
times
.
size
();
for
(
size_t
i
=
0
;
i
<
n_times
-
1
;
++
i
)
{
if
(((
values
[
i
+
1
])
>>
13
)
==
(
values
[
i
]
>>
13
))
{
if
(((
values
[
i
+
1
])
>>
8
)
==
(
values
[
i
]
>>
8
))
{
av
+=
static_cast
<
double
>
(
times
[
i
+
1
]
-
times
[
i
])
/
n_times
;
}
}
...
...
tests/src/test_coincidences.cpp
View file @
6c54ce72
...
...
@@ -8,11 +8,11 @@ using namespace std;
TEST_CASE
(
"Coincidences make sense"
,
"[coincidence]"
)
{
auto
check_coincidence
=
[](
array
<
float
,
4
>
rates
)
{
const
auto
[
rate
,
av
,
counts
]
=
coincidence_rate
(
rates
);
const
auto
[
rate
,
av
]
=
coincidence_rate
(
rates
);
auto
conf_rate
=
std
::
accumulate
(
std
::
next
(
begin
(
rates
)),
end
(
rates
),
0.
);
REQUIRE
(
rate
==
conf_rate
);
if
(
rate
!=
0.
)
{
REQUIRE
(
std
::
abs
(
rate
-
av
)
/
rate
<
1
e-3
);
REQUIRE
(
std
::
abs
(
rate
-
av
)
/
rate
<
2
e-3
);
}
};
...
...
tests/src/test_rates_root.cpp
View file @
6c54ce72
#include
<numeric>
#include
<iostream>
#include
<array>
#include
<iomanip>
#include
<generate.h>
#include
<storage.h>
...
...
@@ -14,12 +15,19 @@
#include
<TCanvas.h>
#include
<TROOT.h>
#define CATCH_CONFIG_RUNNER
#include
"catch2/catch.hpp"
using
namespace
std
;
int
main
()
{
int
main
(
int
argc
,
char
*
argv
[]
)
{
gROOT
->
SetBatch
();
return
Catch
::
Session
().
run
(
argc
,
argv
);
}
TEST_CASE
(
"Rates makes sense [ROOT]"
,
"[rates_ROOT]"
)
{
map
<
bool
,
unique_ptr
<
TH1I
>>
histos
;
array
<
float
,
4
>
rates
{
7000.
,
0.
,
0.
,
0.
};
...
...
@@ -31,15 +39,14 @@ int main() {
Generators
gens
{
1052
,
9523
,
rates
};
long
dt
=
std
::
lround
(
1e
6
);
long
dt
=
std
::
lround
(
1e
7
);
long
time_start
=
0
,
time_end
=
time_start
+
dt
;
auto
[
times
,
values
]
=
generate
(
time_start
,
time_end
,
gens
,
use_avx2
);
const
size_t
n_times
=
times
.
size
();
for
(
size_t
i
=
0
;
i
<
n_times
-
1
;
++
i
)
{
if
(((
values
[
i
+
1
])
>>
13
)
==
(
values
[
i
]
>>
13
))
{
if
(((
values
[
i
+
1
])
>>
8
)
==
(
values
[
i
]
>>
8
))
{
time_histo
->
Fill
(
times
[
i
+
1
]
-
times
[
i
]);
}
}
...
...
@@ -47,7 +54,7 @@ int main() {
time_histo
->
GetBinCenter
(
1
+
time_histo
->
GetNbinsX
())};
auto
fit
=
time_histo
->
Fit
(
&
expo
,
"RS"
);
// parameter is negative
cout
<<
std
::
fabs
(
rates
[
0
]
+
(
fit
->
Parameter
(
1
)
*
1e9
))
/
rates
[
0
]
<<
endl
;
REQUIRE
(
std
::
fabs
(
rates
[
0
]
+
(
fit
->
Parameter
(
1
)
*
1e9
))
/
rates
[
0
]
<
1e-3
)
;
}
TCanvas
canvas
{
"canvas"
,
"canvas"
,
600
,
800
};
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment