Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
ToolBox
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
SCS
ToolBox
Commits
b64c9318
Commit
b64c9318
authored
3 years ago
by
Cammille Carinan
Browse files
Options
Downloads
Patches
Plain Diff
Add hRIXS class and centroid/integral methods
parent
a8629280
No related branches found
No related tags found
1 merge request
!170
hRIXS functions
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/toolbox_scs/detectors/hrixs.py
+198
-0
198 additions, 0 deletions
src/toolbox_scs/detectors/hrixs.py
with
198 additions
and
0 deletions
src/toolbox_scs/detectors/hrixs.py
+
198
−
0
View file @
b64c9318
from
functools
import
lru_cache
import
numpy
as
np
from
scipy.optimize
import
curve_fit
from
scipy.signal
import
fftconvolve
import
toolbox_scs
as
tb
__all__
=
[
'
find_curvature
'
,
...
...
@@ -142,3 +146,197 @@ def gauss1d(x, height, x0, sigma, offset):
def
to_fwhm
(
sigma
):
return
abs
(
sigma
*
FWHM_COEFF
)
# -----------------------------------------------------------------------------
# Centroid
THRESHOLD
=
510
# pixel counts above which a hit candidate is assumed
CURVE_A
=
2.19042931e-02
# curvature parameters as determined elsewhere
CURVE_B
=
-
3.02191568e-07
def
centroid
(
image
,
threshold
=
THRESHOLD
,
curvature
=
(
CURVE_A
,
CURVE_B
)):
gs
=
2
base
=
image
.
mean
()
cp
=
np
.
argwhere
(
image
[
gs
//
2
:
-
gs
//
2
,
gs
//
2
:
-
gs
//
2
]
>
threshold
)
+
np
.
array
([
gs
//
2
,
gs
//
2
])
if
len
(
cp
)
>
100000
:
raise
RuntimeError
(
'
Threshold too low or acquisition time too long
'
)
res
=
[]
for
cy
,
cx
in
cp
:
spot
=
image
[
cy
-
gs
//
2
:
cy
+
gs
//
2
+
1
,
cx
-
gs
//
2
:
cx
+
gs
//
2
+
1
]
-
base
spot
[
spot
<
0
]
=
0
if
(
spot
>
image
[
cy
,
cx
]).
sum
()
==
0
:
mx
=
np
.
average
(
np
.
arange
(
cx
-
gs
//
2
,
cx
+
gs
//
2
+
1
),
weights
=
spot
.
sum
(
axis
=
0
))
my
=
np
.
average
(
np
.
arange
(
cy
-
gs
//
2
,
cy
+
gs
//
2
+
1
),
weights
=
spot
.
sum
(
axis
=
1
))
my
-=
(
curvature
[
0
]
+
curvature
[
1
]
*
mx
)
*
mx
res
.
append
((
my
,
mx
))
return
res
def
decentroid
(
res
):
res
=
np
.
array
(
res
)
ret
=
np
.
zeros
(
shape
=
(
res
.
max
(
axis
=
0
)
+
1
).
astype
(
int
))
for
cy
,
cx
in
res
:
if
cx
>
0
and
cy
>
0
:
ret
[
int
(
cy
),
int
(
cx
)]
+=
1
return
ret
# -----------------------------------------------------------------------------
# Integral
FACTOR
=
3
RANGE
=
[
300
,
400
]
BINS
=
abs
(
np
.
subtract
(
*
RANGE
))
*
FACTOR
def
parabola
(
x
,
a
,
b
,
c
=
0
):
return
(
a
*
x
+
b
)
*
x
+
c
def
integrate
(
image
,
factor
=
FACTOR
,
range
=
RANGE
,
curvature
=
(
CURVE_A
,
CURVE_B
),
):
image
=
image
-
image
.
mean
()
x
=
np
.
arange
(
image
.
shape
[
1
])[
None
,
:]
y
=
np
.
arange
(
image
.
shape
[
0
])[:,
None
]
ys
=
factor
*
(
y
-
parabola
(
x
,
curvature
[
1
],
curvature
[
0
]))
ysf
=
np
.
floor
(
ys
)
rang
=
(
factor
*
range
[
0
],
factor
*
range
[
1
])
bins
=
rang
[
1
]
-
rang
[
0
]
lhy
,
lhx
=
np
.
histogram
(
ysf
.
ravel
(),
bins
=
bins
,
weights
=
((
ys
-
ysf
)
*
image
).
ravel
(),
range
=
rang
)
rhy
,
rhx
=
np
.
histogram
((
ysf
+
1
).
ravel
(),
bins
=
bins
,
weights
=
(((
ysf
+
1
)
-
ys
)
*
image
).
ravel
(),
range
=
rang
)
lvy
,
lvx
=
np
.
histogram
(
ysf
.
ravel
(),
bins
=
bins
,
weights
=
(
ys
-
ysf
).
ravel
(),
range
=
rang
)
rvy
,
rvx
=
np
.
histogram
((
ysf
+
1
).
ravel
(),
bins
=
bins
,
weights
=
((
ysf
+
1
)
-
ys
).
ravel
(),
range
=
rang
)
return
(
lhy
+
rhy
)
/
(
lvy
+
rvy
)
# -----------------------------------------------------------------------------
# hRIXS class
class
hRIXS
:
# run
PROPOSAL
=
2769
# image range
X_RANGE
=
np
.
s_
[
1300
:
-
100
]
Y_RANGE
=
np
.
s_
[:]
# centroid
THRESHOLD
=
THRESHOLD
# pixel counts above which a hit candidate is assumed
CURVE_A
=
CURVE_A
# curvature parameters as determined elsewhere
CURVE_B
=
CURVE_B
# integral
FACTOR
=
FACTOR
RANGE
=
RANGE
BINS
=
abs
(
np
.
subtract
(
*
RANGE
))
*
FACTOR
METHOD
=
'
centroid
'
# ['centroid', 'integral']
@classmethod
def
set_params
(
cls
,
**
params
):
for
key
,
value
in
params
.
items
():
setattr
(
cls
,
key
.
upper
(),
value
)
def
__set_params
(
self
,
**
params
):
self
.
__class__
.
set_params
(
**
params
)
self
.
refresh
()
@classmethod
def
get_params
(
cls
,
*
params
):
if
not
params
:
params
=
(
'
proposal
'
,
'
x_range
'
,
'
y_range
'
,
'
threshold
'
,
'
curve_a
'
,
'
curve_b
'
,
'
factor
'
,
'
range
'
,
'
bins
'
,
'
method
'
)
return
{
param
:
getattr
(
cls
,
param
.
upper
())
for
param
in
params
}
def
refresh
(
self
):
cls
=
self
.
__class__
for
cached
in
[
'
_centroid
'
,
'
_integral
'
]:
getattr
(
cls
,
cached
).
fget
.
cache_clear
()
def
__init__
(
self
,
images
,
norm
=
None
):
self
.
images
=
images
self
.
norm
=
norm
# class/instance method compatibility
self
.
set_params
=
self
.
__set_params
@classmethod
def
from_run
(
cls
,
runNB
,
proposal
=
None
,
first_wrong
=
False
):
if
proposal
is
None
:
proposal
=
cls
.
PROPOSAL
run
,
data
=
tb
.
load
(
proposal
,
runNB
=
runNB
,
fields
=
[
'
hRIXS_det
'
,
'
SCS_slowTrain
'
])
# Get slow train data
mnemo
=
tb
.
mnemonics
[
'
SCS_slowTrain
'
][
0
]
slow_train
=
run
[
mnemo
[
'
source
'
],
mnemo
[
'
key
'
]].
ndarray
().
sum
()
return
cls
(
images
=
data
[
'
hRIXS_det
'
][
1
if
first_wrong
else
0
:].
data
,
norm
=
slow_train
)
@property
@lru_cache
()
def
_centroid
(
self
):
return
sum
((
centroid
(
image
[
self
.
Y_RANGE
,
self
.
X_RANGE
].
T
,
threshold
=
self
.
THRESHOLD
,
curvature
=
(
self
.
CURVE_A
,
self
.
CURVE_B
),
)
for
image
in
self
.
images
),
[])
def
_centroid_spectrum
(
self
,
bins
=
None
,
range
=
None
,
normalize
=
True
):
if
bins
is
None
:
bins
=
self
.
BINS
if
range
is
None
:
range
=
self
.
RANGE
r
=
np
.
array
(
self
.
_centroid
)
hy
,
hx
=
np
.
histogram
(
r
[:,
0
],
bins
=
bins
,
range
=
range
)
if
normalize
and
self
.
norm
is
not
None
:
hy
=
hy
/
self
.
norm
return
(
hx
[:
-
1
]
+
hx
[
1
:])
/
2
,
hy
@property
@lru_cache
()
def
_integral
(
self
):
return
sum
((
integrate
(
image
[
self
.
Y_RANGE
,
self
.
X_RANGE
].
T
,
factor
=
self
.
FACTOR
,
range
=
self
.
RANGE
,
curvature
=
(
self
.
CURVE_A
,
self
.
CURVE_B
))
for
image
in
self
.
images
))
def
_integral_spectrum
(
self
,
normalize
=
True
):
values
=
self
.
_integral
if
normalize
and
self
.
norm
is
not
None
:
values
=
values
/
self
.
norm
return
np
.
arange
(
values
.
size
),
values
@property
def
corrected
(
self
):
return
decentroid
(
self
.
_centroid
)
def
spectrum
(
self
,
normalize
=
True
):
spec_func
=
(
self
.
_centroid_spectrum
if
self
.
METHOD
.
lower
()
==
'
centroid
'
else
self
.
_integral_spectrum
)
return
spec_func
(
normalize
=
normalize
)
def
__sub__
(
self
,
other
):
px
,
py
=
self
.
spectrum
()
mx
,
my
=
other
.
spectrum
()
return
(
px
+
mx
)
/
2
,
py
-
my
def
__add__
(
self
,
other
):
ix
,
iy
=
self
.
spectrum
(
normalize
=
False
)
jx
,
jy
=
other
.
spectrum
(
normalize
=
False
)
i_n
=
self
.
norm
or
0
j_n
=
other
.
norm
or
0
norm
=
((
i_n
+
j_n
)
or
1
)
return
ix
,
(
iy
+
jy
)
/
norm
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment