Skip to content

Commit 9901ad3

Browse files
authored
Merge pull request #257 from European-XFEL/dev
0.9.1
2 parents 03117a2 + 6218b9c commit 9901ad3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2562
-3281
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ EXtra-foam
1313

1414
![Overview](docs/images/extra_foam_0.9.0.jpg)
1515

16-
*EXtra-foam* (previously known as *[karaboFAI](https://in.xfel.eu/readthedocs/docs/karabofai/en/latest/)*) is a
17-
framework that provides super fast on-line (real-time) and off-line data analysis and visualization for
18-
experiments at European XFEL that using 2D detectors (e.g. AGIPD, DSSC, LPD, ePix100, FastCCD, JungFrau,
19-
etc.), together with other 1D detectors (e.g. XGM, digitizer, etc.) and various control data.
16+
*EXtra-foam* is a framework that provides real-time and off-line data analysis (**detector geometry**,
17+
**pump-probe**, **azimuthal integration**, **ROI**, **statistics**, etc.) and visualization for experiments
18+
that use **2D area detectors** (*AGIPD*, *LPD*, *DSSC*, *FastCCD*, *JungFrau*, *ePix100*, etc.) and
19+
**1D detectors** (*Gotthard*, *XGM*, *digitizer*, etc.) at European XFEL.
2020

2121
[Documentation](https://extra-foam.readthedocs.io/en/latest/)
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# EXtra-foam azimuthal integration benchmark"
8+
]
9+
},
10+
{
11+
"cell_type": "code",
12+
"execution_count": null,
13+
"metadata": {},
14+
"outputs": [],
15+
"source": [
16+
"import os.path as osp\n",
17+
"\n",
18+
"import numpy as np\n",
19+
"from pyFAI.azimuthalIntegrator import AzimuthalIntegrator as PyfaiAzimuthalIntegrator\n",
20+
"from scipy.signal import find_peaks\n",
21+
"import matplotlib.pyplot as plt\n",
22+
"\n",
23+
"import extra_foam\n",
24+
"print(extra_foam.__version__)\n",
25+
"\n",
26+
"from extra_foam.algorithms import AzimuthalIntegrator, ConcentricRingsFinder\n",
27+
"from extra_foam.algorithms import mask_image_data"
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"def load_image(filepath):\n",
37+
" img = np.load(osp.join(osp.expanduser('~'), filepath))\n",
38+
" mask = np.zeros_like(img, dtype=bool)\n",
39+
" mask_image_data(img, out=mask)\n",
40+
" _, ax = plt.subplots(figsize=(12, 12))\n",
41+
" ax.imshow(img)\n",
42+
" \n",
43+
" return img, mask\n",
44+
"\n",
45+
"# img, mask = load_image(\"jf_ring.npy\")\n",
46+
"img, mask = load_image(\"jf_ring_6modules.npy\")\n",
47+
"# img, mask = load_image(\"lpd.npy\")"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": null,
53+
"metadata": {},
54+
"outputs": [],
55+
"source": [
56+
"dist = 1 # sample distance\n",
57+
"npt = 1024 # number of integration points\n",
58+
"pixel1, pixel2 = 0.75e-6, 0.75e-6 # pixel size (y, x)\n",
59+
"cy, cx = 537, 1132 \n",
60+
"poni1, poni2 = cy * pixel1, cx * pixel2 # integration center (y, x)"
61+
]
62+
},
63+
{
64+
"cell_type": "code",
65+
"execution_count": null,
66+
"metadata": {},
67+
"outputs": [],
68+
"source": [
69+
"# %%timeit\n",
70+
"\n",
71+
"pyfai_integrator = PyfaiAzimuthalIntegrator(\n",
72+
" dist=dist, poni1=poni1, poni2=poni2, pixel1=pixel1, pixel2=pixel2, wavelength=1e-10)\n",
73+
"\n",
74+
"q_gt, I_gt = pyfai_integrator.integrate1d(img, npt, mask=mask, unit=\"q_A^-1\")"
75+
]
76+
},
77+
{
78+
"cell_type": "code",
79+
"execution_count": null,
80+
"metadata": {},
81+
"outputs": [],
82+
"source": [
83+
"# %%timeit\n",
84+
"\n",
85+
"integrator = AzimuthalIntegrator(\n",
86+
" dist=dist, poni1=poni1, poni2=poni2, pixel1=pixel1, pixel2=pixel2, wavelength=1e-10)\n",
87+
"\n",
88+
"q, I = integrator.integrate1d(img, npt=npt)"
89+
]
90+
},
91+
{
92+
"cell_type": "code",
93+
"execution_count": null,
94+
"metadata": {},
95+
"outputs": [],
96+
"source": [
97+
"_, ax = plt.subplots(figsize=(12, 6))\n",
98+
"\n",
99+
"ax.plot(1e-10 * q, I, '-', label='EXtra-foam')\n",
100+
"ax.plot(q_gt, I_gt, '--', label='pyFAI')\n",
101+
"ax.set_xlabel(\"q (1/A)\", fontsize=16)\n",
102+
"ax.set_ylabel(\"I (arb.)\", fontsize=16)\n",
103+
"ax.legend(fontsize=16)"
104+
]
105+
},
106+
{
107+
"cell_type": "code",
108+
"execution_count": null,
109+
"metadata": {},
110+
"outputs": [],
111+
"source": [
112+
"# %%timeit\n",
113+
"\n",
114+
"min_count = 500\n",
115+
"prominence = 100\n",
116+
"distance = 10\n",
117+
"\n",
118+
"finder = ConcentricRingsFinder(pixel2, pixel1)\n",
119+
"cx, cy = finder.search(img, cx, cy, min_count=min_count)"
120+
]
121+
},
122+
{
123+
"cell_type": "code",
124+
"execution_count": null,
125+
"metadata": {},
126+
"outputs": [],
127+
"source": [
128+
"q, s = finder.integrate(img, cx, cy, min_count=min_count)\n",
129+
"\n",
130+
"i_peaks = find_peaks(s, distance=distance, prominence=prominence)[0]\n",
131+
"\n",
132+
"_, ax = plt.subplots(figsize=(12, 6))\n",
133+
"\n",
134+
"ax.plot(q, s, '-')\n",
135+
"ax.plot(q[i_peaks], s[i_peaks], 'x')\n",
136+
"ax.set_xlabel(\"Radial (pixel)\", fontsize=16)\n",
137+
"ax.set_ylabel(\"I (arb.)\", fontsize=16)\n",
138+
"\n",
139+
"print(\"Optimized cx = \", cx, \", cy = \", cy)"
140+
]
141+
},
142+
{
143+
"cell_type": "code",
144+
"execution_count": null,
145+
"metadata": {},
146+
"outputs": [],
147+
"source": []
148+
}
149+
],
150+
"metadata": {
151+
"kernelspec": {
152+
"display_name": "foam-gcc6",
153+
"language": "python",
154+
"name": "foam-gcc6"
155+
},
156+
"language_info": {
157+
"codemirror_mode": {
158+
"name": "ipython",
159+
"version": 3
160+
},
161+
"file_extension": ".py",
162+
"mimetype": "text/x-python",
163+
"name": "python",
164+
"nbconvert_exporter": "python",
165+
"pygments_lexer": "ipython3",
166+
"version": "3.7.6"
167+
}
168+
},
169+
"nbformat": 4,
170+
"nbformat_minor": 4
171+
}

benchmarks/gui/benchmark_imageview.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
All rights reserved.
99
"""
1010
import time
11+
from collections import deque
1112

1213
import numpy as np
1314

@@ -21,6 +22,8 @@
2122

2223
class BenchmarkImageViewSpeed:
2324
def __init__(self):
25+
self._dt = deque(maxlen=60)
26+
2427
self._timer = QTimer()
2528
self._timer.timeout.connect(self.update)
2629

@@ -40,9 +43,9 @@ def update(self):
4043
self._count += 1
4144

4245
now = time.time()
43-
dt = now - self._prev_t
46+
self._dt.append(now - self._prev_t)
4447
self._prev_t = now
45-
fps = 1.0/dt
48+
fps = len(self._dt) / sum(self._dt)
4649

4750
self._view.setTitle(f"{fps:.2f} fps")
4851

benchmarks/gui/benchmark_plotwidget.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"""
1010
import time
1111
from enum import IntEnum
12+
from collections import deque
1213

1314
import numpy as np
1415

@@ -29,24 +30,28 @@ class PlotType(IntEnum):
2930

3031
class BenchmarkPlotItemSpeed:
3132
def __init__(self, plot_type=PlotType.Line):
33+
self._dt = deque(maxlen=60)
34+
3235
self._timer = QTimer()
3336
self._timer.timeout.connect(self.update)
37+
# self._timer.singleShot(1, self.update)
3438

3539
self._widget = PlotWidgetF()
40+
self._widget.addLegend()
3641

3742
if plot_type == PlotType.Line:
38-
self._graph = self._widget.plotCurve()
43+
self._graph = self._widget.plotCurve(name='line')
3944
n_pts = 5000
4045
elif plot_type == PlotType.Bar:
41-
self._graph = self._widget.plotBar()
46+
self._graph = self._widget.plotBar(name='bar')
4247
n_pts = 300
4348
elif plot_type == PlotType.StatisticsBar:
44-
self._graph = self._widget.plotStatisticsBar()
49+
self._graph = self._widget.plotStatisticsBar(name='statistics bar')
4550
self._graph.setBeam(1)
4651
n_pts = 500
4752
elif plot_type == PlotType.Scatter:
48-
self._graph = self._widget.plotScatter()
49-
n_pts = 3000
53+
self._graph = self._widget.plotScatter(name='scatter')
54+
n_pts = 5000
5055
else:
5156
raise ValueError(f"Unknown plot type: {plot_type}")
5257

@@ -77,16 +82,16 @@ def update(self):
7782
self._count += 1
7883

7984
now = time.time()
80-
dt = now - self._prev_t
85+
self._dt.append(now - self._prev_t)
8186
self._prev_t = now
82-
fps = 1.0 / dt
87+
fps = len(self._dt) / sum(self._dt)
8388

8489
self._widget.setTitle(f"{fps:.2f} fps")
8590

8691
app.processEvents() # force complete redraw for every plot
8792

8893

8994
if __name__ == '__main__':
90-
bench = BenchmarkPlotItemSpeed(PlotType.Line)
95+
bench = BenchmarkPlotItemSpeed(PlotType.Scatter)
9196
bench.start()
9297
app.exec_()

docs/changelog.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
CHANGELOG
22
=========
33

4+
0.9.1 (15 July 2020)
5+
------------------------
6+
7+
- **Bug Fix**
8+
9+
- Fix transform type update in TransformView in ImageTool. #251
10+
11+
- **Improvement**
12+
13+
- PlotItem will not be shown in legend if its name is empty. #254
14+
- Improve y2-axis plot implementation. #253
15+
- Improve stack detector modules. #247
16+
- Implement ScatterPlotItem to replace the pyqtgraph one. #238
17+
18+
- **New Feature**
19+
20+
- Implement curve fitting in correlation window. #255
21+
- Implement azimuthal integration and concentric ring detection in C++. #252
22+
23+
424
0.9.0 (30 June 2020)
525
------------------------
626

0 commit comments

Comments
 (0)