Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pycalibration
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Model registry
Analyze
Contributor 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
calibration
pycalibration
Commits
5e57e05c
Commit
5e57e05c
authored
9 months ago
by
Egor Sobolev
Browse files
Options
Downloads
Patches
Plain Diff
Remove addon abstraction
parent
624b8c9d
No related branches found
No related tags found
1 merge request
!986
[AGIPD] Feat: lit-pixel counter
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/cal_tools/agipdlib.py
+24
-18
24 additions, 18 deletions
src/cal_tools/agipdlib.py
src/cal_tools/litpx_counter.py
+42
-60
42 additions, 60 deletions
src/cal_tools/litpx_counter.py
with
66 additions
and
78 deletions
src/cal_tools/agipdlib.py
+
24
−
18
View file @
5e57e05c
...
@@ -28,7 +28,7 @@ from cal_tools.agipdutils import (
...
@@ -28,7 +28,7 @@ from cal_tools.agipdutils import (
melt_snowy_pixels
,
melt_snowy_pixels
,
)
)
from
cal_tools.enums
import
AgipdGainMode
,
BadPixels
,
SnowResolution
from
cal_tools.enums
import
AgipdGainMode
,
BadPixels
,
SnowResolution
from
cal_tools.litpx_counter
import
AnalysisAddon
,
LitPixelCounter
from
cal_tools.litpx_counter
import
LitPixelCounter
from
logging
import
warning
from
logging
import
warning
...
@@ -73,7 +73,7 @@ class AgipdCtrl:
...
@@ -73,7 +73,7 @@ class AgipdCtrl:
else
:
else
:
raise
ValueError
(
f
"
No raw images found for
{
self
.
image_src
}
"
)
raise
ValueError
(
f
"
No raw images found for
{
self
.
image_src
}
"
)
return
ncell
return
ncell
def
get_num_cells
(
self
)
->
int
:
def
get_num_cells
(
self
)
->
int
:
"""
Read number of memory cells from fast data.
"""
"""
Read number of memory cells from fast data.
"""
...
@@ -84,7 +84,7 @@ class AgipdCtrl:
...
@@ -84,7 +84,7 @@ class AgipdCtrl:
# the function returns wrong value.
# the function returns wrong value.
ncell
=
self
.
_get_num_cells_instr
()
ncell
=
self
.
_get_num_cells_instr
()
return
ncell
return
ncell
def
_get_acq_rate_ctrl
(
self
)
->
Optional
[
float
]:
def
_get_acq_rate_ctrl
(
self
)
->
Optional
[
float
]:
"""
Get acquisition (repetition) rate from CONTROL source.
"""
"""
Get acquisition (repetition) rate from CONTROL source.
"""
...
@@ -588,6 +588,7 @@ class AgipdCorrections:
...
@@ -588,6 +588,7 @@ class AgipdCorrections:
# Output parameters
# Output parameters
self
.
compress_fields
=
[
'
gain
'
,
'
mask
'
]
self
.
compress_fields
=
[
'
gain
'
,
'
mask
'
]
self
.
recast_image_fields
=
{}
self
.
recast_image_fields
=
{}
self
.
write_extra_data
=
[]
# Shared variables for data and constants
# Shared variables for data and constants
self
.
shared_dict
=
[]
self
.
shared_dict
=
[]
...
@@ -777,12 +778,13 @@ class AgipdCorrections:
...
@@ -777,12 +778,13 @@ class AgipdCorrections:
instrument_channels
.
append
(
f
"
{
agipd_base
}
/image
"
)
instrument_channels
.
append
(
f
"
{
agipd_base
}
/image
"
)
# backward compatibility END
# backward compatibility END
addons
=
[]
# resolve names for extra source
for
name
,
elem
in
data_dict
.
items
():
extra_sources
=
[]
if
isinstance
(
elem
,
AnalysisAddon
):
for
name
in
self
.
write_extra_data
:
src_name
=
elem
.
source_name
(
karabo_id
,
det_channel
)
processor
=
data_dict
[
name
]
addons
.
append
((
elem
,
src_name
))
src_name
=
processor
.
source_name
(
karabo_id
,
det_channel
)
instrument_channels
.
append
(
f
"
{
src_name
}
/
{
elem
.
channel
}
"
)
extra_sources
.
append
((
processor
,
src_name
))
instrument_channels
.
append
(
f
"
{
src_name
}
/
{
processor
.
channel
}
"
)
with
DataFile
.
from_details
(
out_folder
,
agg
,
runno
,
seqno
)
as
outfile
:
with
DataFile
.
from_details
(
out_folder
,
agg
,
runno
,
seqno
)
as
outfile
:
outfile
.
create_metadata
(
outfile
.
create_metadata
(
...
@@ -823,13 +825,13 @@ class AgipdCorrections:
...
@@ -823,13 +825,13 @@ class AgipdCorrections:
field
,
shape
=
arr
.
shape
,
dtype
=
arr
.
dtype
,
**
kw
field
,
shape
=
arr
.
shape
,
dtype
=
arr
.
dtype
,
**
kw
)
)
# create
addon
sources
# create
extra
sources
required_
addon_
data
=
[]
required_data
=
[]
for
addon
,
src_name
in
addon
s
:
for
processor
,
src_name
in
extra_source
s
:
src
=
outfile
.
create_instrument_source
(
src_name
)
src
=
outfile
.
create_instrument_source
(
src_name
)
addon
.
set_num_images
(
n_img
)
processor
.
set_num_images
(
n_img
)
addon
.
create_schema
(
src
,
trains
,
count
)
processor
.
create_schema
(
src
,
trains
,
count
)
required_
addon_
data
.
append
((
addon
,
src
))
required_data
.
append
((
processor
,
src
))
# Write the corrected data
# Write the corrected data
for
field
in
image_fields
:
for
field
in
image_fields
:
...
@@ -840,9 +842,9 @@ class AgipdCorrections:
...
@@ -840,9 +842,9 @@ class AgipdCorrections:
else
:
else
:
image_grp
[
field
][:]
=
data_dict
[
field
][:
n_img
]
image_grp
[
field
][:]
=
data_dict
[
field
][:
n_img
]
# write
addon
data
# write
extra
data
for
addon
,
src
in
required_
addon_
data
:
for
processor
,
src
in
required_data
:
addon
.
write
(
src
)
processor
.
write
(
src
)
def
_write_compressed_frames
(
self
,
dataset
,
arr
):
def
_write_compressed_frames
(
self
,
dataset
,
arr
):
"""
Compress gain/mask frames in multiple threads, and save their data
"""
Compress gain/mask frames in multiple threads, and save their data
...
@@ -1493,6 +1495,7 @@ class AgipdCorrections:
...
@@ -1493,6 +1495,7 @@ class AgipdCorrections:
:param shape: Shape of expected data (nImg, x, y)
:param shape: Shape of expected data (nImg, x, y)
:param n_cores_files: Number of files, handled in parallel
:param n_cores_files: Number of files, handled in parallel
"""
"""
self
.
write_extra_data
=
[]
self
.
shared_dict
=
[]
self
.
shared_dict
=
[]
for
i
in
range
(
n_cores_files
):
for
i
in
range
(
n_cores_files
):
self
.
shared_dict
.
append
({})
self
.
shared_dict
.
append
({})
...
@@ -1521,6 +1524,9 @@ class AgipdCorrections:
...
@@ -1521,6 +1524,9 @@ class AgipdCorrections:
self
.
shared_dict
[
i
][
"
litpx_counter
"
]
=
LitPixelCounter
(
self
.
shared_dict
[
i
][
"
litpx_counter
"
]
=
LitPixelCounter
(
self
.
shared_dict
[
i
],
threshold
=
self
.
litpx_threshold
)
self
.
shared_dict
[
i
],
threshold
=
self
.
litpx_threshold
)
if
self
.
corr_bools
.
get
(
"
count_lit_pixels
"
):
self
.
write_extra_data
.
append
(
"
litpx_counter
"
)
if
self
.
corr_bools
.
get
(
"
round_photons
"
):
if
self
.
corr_bools
.
get
(
"
round_photons
"
):
self
.
shared_hist_preround
=
sharedmem
.
empty
(
len
(
self
.
hist_bins_preround
)
-
1
,
dtype
=
"
i8
"
)
self
.
shared_hist_preround
=
sharedmem
.
empty
(
len
(
self
.
hist_bins_preround
)
-
1
,
dtype
=
"
i8
"
)
self
.
shared_hist_postround
=
sharedmem
.
empty
(
len
(
self
.
hist_bins_postround
)
-
1
,
dtype
=
"
i8
"
)
self
.
shared_hist_postround
=
sharedmem
.
empty
(
len
(
self
.
hist_bins_postround
)
-
1
,
dtype
=
"
i8
"
)
...
...
This diff is collapsed.
Click to expand it.
src/cal_tools/litpx_counter.py
+
42
−
60
View file @
5e57e05c
...
@@ -2,16 +2,30 @@ import numpy as np
...
@@ -2,16 +2,30 @@ import numpy as np
import
sharedmem
import
sharedmem
class
AnalysisAddon
:
class
LitPixelCounter
:
"""
Base class for analysis addons
"""
"""
Lit-pixel counter: counts pixels with a signal above a threshold.
"""
channel
=
"
data
"
channel
=
"
litpx
"
output_fields
=
[
output_fields
=
[
"
cellId
"
,
"
pulseId
"
,
"
trainId
"
]
"
cellId
"
,
"
pulseId
"
,
"
trainId
"
,
"
litPixels
"
,
"
unmaskedPixels
"
,
"
totalIntensity
"
]
required_data
=
[
required_data
=
[
"
cellId
"
,
"
pulseId
"
,
"
trainId
"
]
"
data
"
,
"
mask
"
,
"
cellId
"
,
"
pulseId
"
,
"
trainId
"
]
def
__init__
(
self
,
data
):
def
__init__
(
self
,
data
,
threshold
=
0.7
):
"""
Initialize the instance of lit-pixel analysis addon.
Parameters
----------
data: dict
Dictionary with image data. It must include the fields:
`data`, `mask`, `cellId`, `pulseId`, `trainId`
threshold: float
The pixel intensity value, which if exceeded means
that the pixel is illuminated.
"""
required_data
=
set
(
self
.
required_data
)
|
{
"
pulseId
"
}
required_data
=
set
(
self
.
required_data
)
|
{
"
pulseId
"
}
for
name
in
required_data
:
for
name
in
required_data
:
if
name
not
in
data
:
if
name
not
in
data
:
...
@@ -21,6 +35,19 @@ class AnalysisAddon:
...
@@ -21,6 +35,19 @@ class AnalysisAddon:
self
.
max_images
=
data
[
"
pulseId
"
].
shape
[
0
]
self
.
max_images
=
data
[
"
pulseId
"
].
shape
[
0
]
self
.
num_images
=
self
.
max_images
self
.
num_images
=
self
.
max_images
# specific members
self
.
image
=
data
[
"
data
"
]
self
.
mask
=
data
[
"
mask
"
]
self
.
threshold
=
threshold
self
.
num_unmasked_px
=
sharedmem
.
full
(
self
.
max_images
,
0
,
int
)
self
.
num_lit_px
=
sharedmem
.
full
(
self
.
max_images
,
0
,
int
)
self
.
total_intensity
=
sharedmem
.
full
(
self
.
max_images
,
0
,
int
)
self
.
data
[
"
litPixels
"
]
=
self
.
num_lit_px
self
.
data
[
"
unmaskedPixels
"
]
=
self
.
num_unmasked_px
self
.
data
[
"
totalIntensity
"
]
=
self
.
total_intensity
def
set_num_images
(
self
,
num_images
):
def
set_num_images
(
self
,
num_images
):
"""
Sets the actual number of images in data.
"""
Sets the actual number of images in data.
...
@@ -39,7 +66,14 @@ class AnalysisAddon:
...
@@ -39,7 +66,14 @@ class AnalysisAddon:
chunk: slice, sequence or array
chunk: slice, sequence or array
The indices of images in `data` to process
The indices of images in `data` to process
"""
"""
raise
NotImplementedError
ix
=
range
(
*
chunk
.
indices
(
self
.
num_images
))
for
i
in
ix
:
mask
=
self
.
mask
[
i
]
==
0
self
.
total_intensity
[
i
]
=
np
.
sum
(
self
.
image
[
i
],
initial
=
0
,
where
=
mask
)
self
.
num_lit_px
[
i
]
=
np
.
sum
(
self
.
image
[
i
]
>
self
.
threshold
,
initial
=
0
,
where
=
mask
)
self
.
num_unmasked_px
[
i
]
=
np
.
sum
(
mask
)
def
source_name
(
self
,
karabo_id
,
channel
):
def
source_name
(
self
,
karabo_id
,
channel
):
"""
Returns the source name.
"""
Returns the source name.
...
@@ -56,7 +90,7 @@ class AnalysisAddon:
...
@@ -56,7 +90,7 @@ class AnalysisAddon:
source_name: str
source_name: str
The source name for EXDF files
The source name for EXDF files
"""
"""
return
f
"
{
karabo_id
}
/
DANA
/
{
channel
}
"
return
f
"
{
karabo_id
}
/
LITPX
/
{
channel
}
"
def
create_schema
(
self
,
source
,
file_trains
=
None
,
count
=
None
):
def
create_schema
(
self
,
source
,
file_trains
=
None
,
count
=
None
):
"""
Creates the indices and keys in the source.
"""
Creates the indices and keys in the source.
...
@@ -106,55 +140,3 @@ class AnalysisAddon:
...
@@ -106,55 +140,3 @@ class AnalysisAddon:
channel
=
source
[
self
.
channel
]
channel
=
source
[
self
.
channel
]
for
key
in
self
.
output_fields
:
for
key
in
self
.
output_fields
:
channel
[
key
][:]
=
self
.
data
[
key
][:
self
.
num_images
]
channel
[
key
][:]
=
self
.
data
[
key
][:
self
.
num_images
]
class
LitPixelCounter
(
AnalysisAddon
):
"""
Lit-pixel counter analysis addon.
"""
channel
=
"
litpx
"
output_fields
=
[
"
cellId
"
,
"
pulseId
"
,
"
trainId
"
,
"
litPixels
"
,
"
unmaskedPixels
"
,
"
totalIntensity
"
]
required_data
=
[
"
data
"
,
"
mask
"
,
"
cellId
"
,
"
pulseId
"
,
"
trainId
"
]
def
__init__
(
self
,
data
,
threshold
=
0.8
):
"""
Initialize the instance of lit-pixel analysis addon.
Parameters
----------
data: dict
Dictionary with image data. It must include the fields:
`data`, `mask`, `cellId`, `pulseId`, `trainId`
threshold: float
The pixel intensity value, which if exceeded means
that the pixel is illuminated.
"""
super
().
__init__
(
data
)
self
.
image
=
data
[
"
data
"
]
self
.
mask
=
data
[
"
mask
"
]
self
.
threshold
=
threshold
self
.
num_unmasked_px
=
sharedmem
.
full
(
self
.
max_images
,
0
,
int
)
self
.
num_lit_px
=
sharedmem
.
full
(
self
.
max_images
,
0
,
int
)
self
.
total_intensity
=
sharedmem
.
full
(
self
.
max_images
,
0
,
int
)
self
.
data
[
"
litPixels
"
]
=
self
.
num_lit_px
self
.
data
[
"
unmaskedPixels
"
]
=
self
.
num_unmasked_px
self
.
data
[
"
totalIntensity
"
]
=
self
.
total_intensity
def
process
(
self
,
chunk
):
ix
=
range
(
*
chunk
.
indices
(
self
.
num_images
))
for
i
in
ix
:
mask
=
self
.
mask
[
i
]
==
0
self
.
total_intensity
[
i
]
=
np
.
sum
(
self
.
image
[
i
],
initial
=
0
,
where
=
mask
)
self
.
num_lit_px
[
i
]
=
np
.
sum
(
self
.
image
[
i
]
>
self
.
threshold
,
initial
=
0
,
where
=
mask
)
self
.
num_unmasked_px
[
i
]
=
np
.
sum
(
mask
)
def
source_name
(
self
,
karabo_id
,
channel
):
return
f
"
{
karabo_id
}
/LITPX/
{
channel
}
"
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