Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Bliss
bliss
Commits
157148f8
Commit
157148f8
authored
Dec 01, 2020
by
Perceval Guillou
Browse files
introduce scan simulation tools
parent
bb2a3b61
Pipeline
#47062
passed with stages
in 109 minutes and 29 seconds
Changes
6
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
bliss/common/image_tools.py
View file @
157148f8
...
...
@@ -31,49 +31,81 @@ def file_to_array(fpath):
ext
=
fpath
[
fpath
.
rfind
(
"."
)
+
1
:]
if
ext
==
"edf"
:
arry
=
_fabio_file_to_array
(
fpath
)
size
=
arry
.
shape
[
1
],
arry
.
shape
[
0
]
mode
=
_find_array_mode
(
arry
.
shape
,
arry
.
dtype
)
else
:
pil
=
Image
.
open
(
fpath
)
if
pil
.
mode
==
"LA"
:
pil
=
pil
.
convert
(
"L"
)
elif
pil
.
mode
==
"I;16B"
:
pil
=
pil
.
convert
(
"I"
)
pil
=
_file_to_pil
(
fpath
)
arry
=
pil_to_array
(
pil
)
return
arry
mode
=
pil
.
mode
size
=
pil
.
size
data
=
pil
.
tostring
()
arry
=
buffer_to_array
(
mode
,
size
,
data
)
def
file_to_pil
(
fpath
):
ext
=
fpath
[
fpath
.
rfind
(
"."
)
+
1
:]
if
ext
==
"edf"
:
arry
=
_fabio_file_to_array
(
fpath
)
pil
=
array_to_pil
(
arry
)
else
:
pil
=
_file_to_pil
(
fpath
)
return
(
mode
,
size
,
arry
)
return
pil
def
file_to_buffer
(
fpath
):
ext
=
fpath
[
fpath
.
rfind
(
"."
)
+
1
:]
if
ext
==
"edf"
:
arry
=
_fabio_file_to_array
(
fpath
)
data
=
arry
.
tostring
()
# tobytes() ?
size
=
arry
.
shape
[
1
],
arry
.
shape
[
0
]
mode
=
_find_array_mode
(
arry
.
shape
,
arry
.
dtype
)
return
array_to_buffer
(
arry
)
else
:
pil
=
Image
.
open
(
fpath
)
if
pil
.
mode
==
"LA"
:
pil
=
pil
.
convert
(
"L"
)
elif
pil
.
mode
==
"I;16B"
:
pil
=
pil
.
convert
(
"I"
)
elif
pil
.
mode
==
"P"
:
pil
=
pil
.
convert
(
"RGB"
)
pil
=
_file_to_pil
(
fpath
)
return
pil_to_buffer
(
pil
)
def
array_to_file
(
arry
,
fpath
,
mode
=
None
):
ext
=
fpath
[
fpath
.
rfind
(
"."
)
+
1
:]
if
ext
==
"edf"
:
_fabio_array_to_file
(
arry
,
fpath
)
else
:
if
mode
is
None
:
mode
=
_find_array_mode
(
arry
.
shape
,
arry
.
dtype
)
pil
=
Image
.
fromarray
(
arry
,
mode
)
pil
.
save
(
fpath
)
mode
=
pil
.
mode
size
=
pil
.
size
data
=
pil
.
tostring
()
def
array_to_pil
(
arry
,
mode
=
None
):
if
mode
is
None
:
mode
=
_find_array_mode
(
arry
.
shape
,
arry
.
dtype
)
return
Image
.
fromarray
(
arry
,
mode
)
def
array_to_buffer
(
arry
,
mode
=
None
):
if
mode
is
None
:
mode
=
_find_array_mode
(
arry
.
shape
,
arry
.
dtype
)
size
=
arry
.
shape
[
1
],
arry
.
shape
[
0
]
data
=
arry
.
tostring
()
return
(
mode
,
size
,
data
)
def
pil_to_file
(
pil
,
fpath
):
pil
.
save
(
fpath
)
def
pil_to_array
(
pil
):
return
buffer_to_array
(
*
pil_to_buffer
(
pil
))
def
pil_to_buffer
(
pil
):
if
hasattr
(
pil
,
"tostring"
):
data
=
pil
.
tostring
()
# PIL
else
:
data
=
pil
.
tobytes
()
# PILOW
return
(
pil
.
mode
,
pil
.
size
,
data
)
def
buffer_to_file
(
mode
,
size
,
data
,
fpath
):
arry
=
buffer_to_array
(
mode
,
size
,
data
)
array_to_file
(
arry
,
fpath
)
def
buffer_to_array
(
mode
,
size
,
data
):
w
,
h
=
size
if
mode
==
"RGB"
:
...
...
@@ -84,30 +116,9 @@ def buffer_to_array(mode, size, data):
return
np
.
frombuffer
(
data
,
NUMPY_MODES
[
mode
]).
reshape
((
h
,
w
))
def
pil_to_array
(
pil_img
):
w
,
h
=
pil_img
.
size
mode
=
pil_img
.
mode
data
=
pil_img
.
tostring
()
if
mode
==
"RGB"
:
arry
=
np
.
frombuffer
(
data
,
NUMPY_MODES
[
mode
]).
reshape
((
h
,
w
,
3
))
elif
mode
==
"RGBA"
:
arry
=
np
.
frombuffer
(
data
,
NUMPY_MODES
[
mode
]).
reshape
((
h
,
w
,
4
))
else
:
arry
=
np
.
frombuffer
(
data
,
NUMPY_MODES
[
mode
]).
reshape
((
h
,
w
))
return
arry
def
array_to_file
(
arry
,
fpath
,
mode
=
None
):
if
mode
is
None
:
mode
=
_find_array_mode
(
arry
.
shape
,
arry
.
dtype
)
pil
=
Image
.
fromarray
(
arry
,
mode
)
ext
=
fpath
[
fpath
.
rfind
(
"."
)
+
1
:]
if
ext
==
"edf"
:
_fabio_array_to_file
(
arry
,
fpath
)
else
:
pil
.
save
(
fpath
)
def
buffer_to_pil
(
mode
,
size
,
data
):
arry
=
buffer_to_array
(
mode
,
size
,
data
)
return
array_to_pil
(
arry
)
def
_fabio_array_to_file
(
arry
,
fpath
):
...
...
@@ -148,47 +159,37 @@ def _find_array_mode(shape, dtype):
)
# ------ ARRAY CREATION -----------------------
def
empty_array
(
size
,
mode
):
w
,
h
=
size
if
mode
==
"RGBA"
:
shape
=
(
h
,
w
,
4
)
elif
mode
==
"RGB"
:
shape
=
(
h
,
w
,
3
)
else
:
shape
=
(
h
,
w
)
return
np
.
empty
(
shape
,
NUMPY_MODES
[
mode
])
def
_file_to_pil
(
fpath
,
raw
=
False
):
pil
=
Image
.
open
(
fpath
)
if
not
raw
:
if
pil
.
mode
==
"LA"
:
pil
=
pil
.
convert
(
"L"
)
elif
pil
.
mode
==
"I;16B"
:
pil
=
pil
.
convert
(
"I"
)
elif
pil
.
mode
==
"P"
:
pil
=
pil
.
convert
(
"RGB"
)
return
pil
def
zero_array
(
size
,
mode
):
w
,
h
=
size
if
mode
==
"RGBA"
:
shape
=
(
h
,
w
,
4
)
elif
mode
==
"RGB"
:
shape
=
(
h
,
w
,
3
)
else
:
shape
=
(
h
,
w
)
return
np
.
zeros
(
shape
,
NUMPY_MODES
[
mode
])
# ------ ARRAY CREATION -----------------------
def
gauss2d
(
w
,
h
,
A
=
100
,
sx
=
10
,
sy
=
10
,
cx
=
0
,
cy
=
0
):
def
gauss2d
(
w
,
h
,
A
=
100
,
sx
=
10
,
sy
=
10
,
cx
=
None
,
cy
=
None
):
""" Create a 2D Gaussian array
- w: image width
- h: image height
- A: Gaussian amplitude (max)
- sx: Gaussian sigma along x axis
- sx: Gaussian sigma along y axis
- cx: Gaussian
position
along x axis (centr
ed
by default)
- cy: Gaussian
position
along y axis (centr
ed
by default)
- cx: Gaussian
center
along x axis (
image
cent
e
r by default)
- cy: Gaussian
center
along y axis (
image
cent
e
r by default)
"""
if
cx
is
None
:
cx
=
w
/
2
cx
+=
w
/
2
cy
+
=
h
/
2
if
cy
is
None
:
cy
=
h
/
2
x
=
np
.
linspace
(
0
,
w
-
1
,
w
)
y
=
np
.
linspace
(
0
,
h
-
1
,
h
)
...
...
@@ -199,79 +200,65 @@ def gauss2d(w, h, A=100, sx=10, sy=10, cx=0, cy=0):
)
# ------ DRAW IN ARRAY ------------------------
def
DrawArc
(
arry
,
value
=
1
,
cx
=
0
,
cy
=
0
,
r1
=
100
,
r2
=
120
,
a1
=
0
,
a2
=
180
):
# check input args
if
r1
<
0
or
r2
<
0
:
raise
ValueError
(
"radius must be a positive number !"
)
if
a1
<
0
or
a2
<
0
or
a1
>
360
or
a2
>
360
:
raise
ValueError
(
"angles must be in [0, 360] degree !"
)
h
,
w
=
arry
.
shape
cx
=
w
/
2
+
cx
cy
=
h
/
2
+
cy
y
,
x
=
np
.
ogrid
[:
h
,
:
w
]
# take the region between the 2 radius
rmini
=
min
(
r1
,
r2
)
rmaxi
=
max
(
r1
,
r2
)
a
=
(
x
-
cx
)
**
2
+
(
y
-
cy
)
**
2
<=
rmaxi
**
2
b
=
(
x
-
cx
)
**
2
+
(
y
-
cy
)
**
2
>=
rmini
**
2
# take the region between the 2 angles
# Numpy handles y/x where x[i] == 0 => inf and np.arctan(inf) ==> pi/2
def
arcmask
(
w
,
h
,
cx
,
cy
,
r1
,
r2
,
a1
,
a2
):
x
=
np
.
linspace
(
0
,
w
-
1
,
w
)
y
=
np
.
linspace
(
0
,
h
-
1
,
h
)
x
,
y
=
np
.
meshgrid
(
x
,
y
)
amini
=
min
(
a1
,
a2
)
amaxi
=
max
(
a1
,
a
2
)
radius
=
(
x
-
cx
)
**
2
+
(
y
-
cy
)
**
2
c1
=
(
radius
>=
r1
**
2
)
*
(
radius
<=
r2
**
2
)
z
=
(
y
-
cy
)
/
(
x
-
cx
)
angles
=
(
np
.
arctan2
((
y
-
cy
),
(
x
-
cx
))
/
DEG2RAD
)
%
360
c2
=
(
angles
>=
a1
)
*
(
angles
<=
a2
)
if
amini
<
180
and
amaxi
>
180
:
c
=
np
.
arctan2
(
y
-
cy
,
x
-
cx
)
>=
(
amini
*
DEG2RAD
)
d
=
np
.
arctan2
(
y
-
cy
,
x
-
cx
)
<=
(
180
*
DEG2RAD
)
return
c1
*
c2
amaxi
-=
360
e
=
np
.
arctan2
(
y
-
cy
,
x
-
cx
)
>=
(
-
180
*
DEG2RAD
)
f
=
np
.
arctan2
(
y
-
cy
,
x
-
cx
)
<=
(
amaxi
*
DEG2RAD
)
mask1
=
a
*
b
*
c
*
d
mask2
=
a
*
b
*
e
*
f
# ------ DRAW IN ARRAY ------------------------
def
draw_rect
(
arry
,
x
,
y
,
w
,
h
,
fill_value
=
0
):
arry
[
y
:
y
+
h
,
x
:
x
+
w
]
=
fill_value
return
arry
notmask1
=
~
mask1
notmask2
=
~
mask2
return
arry
*
(
notmask1
+
notmask2
)
+
value
*
(
mask1
+
mask2
)
def
draw_arc
(
arry
,
cx
,
cy
,
r1
,
r2
,
a1
,
a2
,
fill_value
=
0
):
else
:
"""" draw circular arc """
if
amini
>=
180
:
amini
-=
360
amaxi
-=
360
h
,
w
=
arry
.
shape
[
0
:
2
]
mask
=
arcmask
(
w
,
h
,
cx
,
cy
,
r1
,
r2
,
a1
,
a2
)
return
np
.
where
(
mask
,
fill_value
,
arry
)
# where True in mask use fill_value else arry
c
=
np
.
arctan2
(
y
-
cy
,
x
-
cx
)
>=
(
amini
*
DEG2RAD
)
d
=
np
.
arctan2
(
y
-
cy
,
x
-
cx
)
<=
(
amaxi
*
DEG2RAD
)
mask
=
a
*
b
*
c
*
d
# ------ BUILD SPECIAL IMAGES ------------------
notmask
=
~
mask
return
arry
*
notmask
+
mask
*
value
def
test_image
(
w
=
800
,
h
=
600
):
arry
=
np
.
ones
((
h
,
w
))
arry
=
draw_rect
(
arry
,
int
(
w
*
0.1
),
int
(
h
*
0.1
),
int
(
w
*
0.1
),
int
(
h
*
0.1
),
fill_value
=
0
)
arry
=
draw_rect
(
arry
,
int
(
w
*
0.5
),
int
(
h
*
0.1
),
int
(
w
*
0.15
),
int
(
h
*
0.15
),
fill_value
=
50
)
arry
=
draw_rect
(
arry
,
int
(
w
*
0.1
),
int
(
h
*
0.5
),
int
(
w
*
0.2
),
int
(
h
*
0.2
),
fill_value
=
100
)
arry
=
draw_rect
(
arry
,
int
(
w
*
0.5
),
int
(
h
*
0.5
),
int
(
w
*
0.25
),
int
(
h
*
0.25
),
fill_value
=
150
)
# ------ BUILD SPECIAL IMAGES ------------------
return
arry
.
astype
(
"uint8"
)
def
create_beam_images
(
fdir
,
nframes
=
100
,
nframes
=
10
,
w
=
800
,
h
=
600
,
amp
=
1000.
,
centre
=
(
0
,
0
),
centre
=
(
None
,
None
),
sigma
=
(
100
,
100
),
noise
=
0.1
,
):
...
...
@@ -283,23 +270,28 @@ def create_beam_images(
- w: image width
- h: image height
- amp: maximum intensity of the Gaussian beam
- centre: position (cx, cy) of the Gaussian beam (
centred on
image center by default)
- centre: position (cx, cy) of the Gaussian beam (image center by default)
- sigma: sigma values (sx, sy) of the Gaussian beam
- noise: noise level in perecentage of the Gaussian amplitude (%)
"""
amp
=
min
(
amp
,
2
**
31
)
# centre by default
cx
,
cy
=
centre
if
cx
is
None
:
cx
=
w
/
2
if
cy
is
None
:
cy
=
h
/
2
# generate random Gaussian parameters (centred + jitter)
A
=
np
.
random
.
default_rng
().
normal
(
amp
,
5
,
size
=
nframes
)
sx
=
np
.
random
.
default_rng
().
normal
(
sigma
[
0
],
1
,
size
=
nframes
)
sy
=
np
.
random
.
default_rng
().
normal
(
sigma
[
1
],
1
,
size
=
nframes
)
x0
=
np
.
random
.
default_rng
().
normal
(
c
entre
[
0
]
,
2
,
size
=
nframes
)
y0
=
np
.
random
.
default_rng
().
normal
(
c
entre
[
1
]
,
2
,
size
=
nframes
)
x0
=
np
.
random
.
default_rng
().
normal
(
c
x
,
2
,
size
=
nframes
)
y0
=
np
.
random
.
default_rng
().
normal
(
c
y
,
2
,
size
=
nframes
)
# generate beam images
frames
=
[]
for
i
in
range
(
nframes
):
bg
=
np
.
random
.
default_rng
().
normal
(
amp
*
noise
,
10
,
size
=
(
h
,
w
))
arry
=
gauss2d
(
w
,
h
,
A
[
i
],
sx
[
i
],
sy
[
i
],
x0
[
i
],
y0
[
i
])
+
bg
...
...
@@ -311,28 +303,51 @@ def create_beam_images(
# convert to uint32
arry
=
arry
.
astype
(
"uint32"
)
# save as image file (edf)
fpath
=
f
"
{
fdir
}
/frame_
{
i
:
04
d
}
.edf"
array_to_file
(
arry
,
fpath
)
frames
.
append
(
arry
)
return
frames
def
create_ring_image
(
fpath
,
w
=
800
,
h
=
600
,
cx
=
0
,
cy
=
0
,
r1
=
100
,
r2
=
120
,
a1
=
0
,
a2
=
180
):
"""" create arc """
# ----- PLOT IMAGE ----------------------
cx
=
w
/
2
+
cx
cy
=
h
/
2
+
cy
x
=
np
.
linspace
(
0
,
w
-
1
,
w
)
y
=
np
.
linspace
(
0
,
h
-
1
,
h
)
x
,
y
=
np
.
meshgrid
(
x
,
y
)
def
get_image_display
(
interactive
=
True
,
dtmin
=
0.001
,
defsize
=
(
800
,
600
)):
""" Plot 2D array as an image (static or live update) """
import
matplotlib.pyplot
as
plt
class
Display
:
def
__init__
(
self
,
interactive
=
True
,
dtmin
=
0.001
,
defsize
=
(
800
,
600
)):
self
.
_interactive
=
interactive
self
.
_dtmin
=
dtmin
if
interactive
:
plt
.
ion
()
else
:
plt
.
ioff
()
self
.
plot
=
plt
.
imshow
(
np
.
zeros
((
defsize
[
1
],
defsize
[
0
])))
plt
.
pause
(
self
.
_dtmin
)
def
__del__
(
self
):
plt
.
close
()
plt
.
ioff
()
def
show
(
self
,
arry
):
try
:
plt
.
cla
()
# clear axes
# plt.clf() # clear figure
except
Exception
:
pass
self
.
plot
=
plt
.
imshow
(
arry
)
plt
.
pause
(
self
.
_dtmin
)
a
=
(
x
-
cx
)
**
2
+
(
y
-
cy
)
**
2
>=
r2
**
2
b
=
(
x
-
cx
)
**
2
+
(
y
-
cy
)
**
2
<=
r1
**
2
c
=
y
>=
h
/
2
r
=
(
a
+
b
+
c
)
*
1
r
=
r
.
astype
(
"uint32"
)
if
not
self
.
_interactive
:
plt
.
show
()
array_to_file
(
r
,
fpath
)
def
close
(
self
):
plt
.
close
()
plt
.
ioff
()
return
r
return
Display
(
interactive
,
dtmin
,
defsize
)
bliss/common/scans/simulation.py
0 → 100644
View file @
157148f8
This diff is collapsed.
Click to expand it.
tests/controllers_sw/test_lima_image.py
View file @
157148f8
...
...
@@ -13,46 +13,7 @@ from bliss.controllers.lima.limatools import (
from
bliss.data.lima_image
import
image_from_server
from
bliss.shell.formatters.table
import
IncrementalTable
# ------ Utility function to PLOT 2D ARRAY AS AN IMAGE (LIVE PREVIEW) --------
def
get_image_display
(
interactive
=
True
,
dtmin
=
0.001
,
defsize
=
(
800
,
600
)):
import
matplotlib.pyplot
as
plt
class
Display
:
def
__init__
(
self
,
interactive
=
True
,
dtmin
=
0.001
,
defsize
=
(
800
,
600
)):
self
.
_interactive
=
interactive
self
.
_dtmin
=
dtmin
if
interactive
:
plt
.
ion
()
else
:
plt
.
ioff
()
self
.
plot
=
plt
.
imshow
(
numpy
.
zeros
((
defsize
[
1
],
defsize
[
0
])))
plt
.
pause
(
self
.
_dtmin
)
def
__del__
(
self
):
plt
.
close
()
plt
.
ioff
()
def
show
(
self
,
arry
):
try
:
plt
.
cla
()
# clear axes
# plt.clf() # clear figure
except
Exception
:
pass
self
.
plot
=
plt
.
imshow
(
arry
)
if
self
.
_interactive
:
plt
.
pause
(
self
.
_dtmin
)
else
:
plt
.
show
()
def
close
(
self
):
plt
.
close
()
plt
.
ioff
()
return
Display
(
interactive
,
dtmin
,
defsize
)
from
bliss.common.image_tools
import
get_image_display
# --- Notes about rect vs roi ------------
...
...
tests/controllers_sw/test_lima_simulator.py
View file @
157148f8
...
...
@@ -1153,8 +1153,8 @@ def test_roi_collection(default_session, lima_simulator, tmp_path):
# === check saved image files ======
for
idx
in
range
(
frames
):
fpath
=
os
.
path
.
join
(
imgdir
,
f
"test_rois_
{
idx
:
04
d
}
.edf"
)
mode
,
size
,
img
=
file_to_array
(
fpath
)
print
(
"img info"
,
mode
,
siz
e
,
img
.
dtype
)
img
=
file_to_array
(
fpath
)
print
(
"img info"
,
img
.
shap
e
,
img
.
dtype
)
# img.dtype = defdtype
plt
.
imshow
(
img
)
plt
.
show
()
...
...
tests/images/bliss_logo.png
0 → 100644
View file @
157148f8
9.01 KB
tests/scans/test_zap_scan.py
0 → 100644
View file @
157148f8
# -*- coding: utf-8 -*-
#
# This file is part of the bliss project
#
# Copyright (c) 2015-2020 Beamline Control Unit, ESRF
# Distributed under the GNU LGPLv3. See LICENSE for more info.
import
os
from
bliss.common.scans.simulation
import
simu_l2scan
,
simu_mesh
def
test_zap
(
session
,
images_directory
):
img_path
=
os
.
path
.
join
(
str
(
images_directory
),
"bliss_logo.png"
)
fast_motor
=
session
.
config
.
get
(
"roby"
)
slow_motor
=
session
.
config
.
get
(
"robz"
)
cnt
=
session
.
config
.
get
(
"diode"
)
simu_l2scan
(
fast_motor
,
0
,
3
,
3
,
slow_motor
,
0
,
1
,
1
,
0.01
,
cnt
,
backnforth
=
False
,
scale
=
0.1
,
imshow
=
False
,
simdatapath
=
img_path
,
)
def
test_simul_mesh
(
session
,
images_directory
):
img_path
=
os
.
path
.
join
(
str
(
images_directory
),
"bliss_logo.png"
)
roby
=
session
.
config
.
get
(
"roby"
)
robz
=
session
.
config
.
get
(
"robz"
)
diode
=
session
.
config
.
get
(
"diode"
)
simu_mesh
(
roby
,
robz
,
diode
,
size
=
(
3
,
3
),
imshow
=
False
,
simdatapath
=
img_path
)
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