bzr branch
http://darksoft.org/webbzr/tomo/pyhst
4
by csa
Initial import |
1 |
/* ## The PyHST program is Copyright (C) 2002-2008 of the */
|
2 |
/* ## European Synchrotron Radiation Facility (ESRF). */
|
|
3 |
||
4 |
/* ## You may use, distribute and copy the PyMCA XRF Toolkit under the terms of */
|
|
78
by Suren A. Chilingaryan
Add COPYING and fix license statements |
5 |
/* ## GNU General Public License version 3 or (at your any later version. */
|
4
by csa
Initial import |
6 |
|
7 |
||
8 |
#define _FILE_OFFSET_BITS 64
|
|
9 |
||
10 |
||
11 |
#include"Python.h" |
|
12 |
||
13 |
||
14 |
#ifndef _LARGEFILE_SOURCE
|
|
15 |
#define _LARGEFILE_SOURCE
|
|
16 |
#endif
|
|
17 |
||
18 |
#include <stdlib.h> |
|
19 |
#include <stdio.h> |
|
5
by csa
Join CPU and GPU versions with ifdefs in order to limit dublicating code |
20 |
#include<string.h> |
4
by csa
Initial import |
21 |
#include <math.h> |
22 |
||
5
by csa
Join CPU and GPU versions with ifdefs in order to limit dublicating code |
23 |
#include<semaphore.h> |
4
by csa
Initial import |
24 |
|
10
by csa
Timing measurements and various fixes |
25 |
#include <glib.h> |
26 |
||
4
by csa
Initial import |
27 |
#include"structmember.h" |
28 |
||
34
by csa
Migration to numpy |
29 |
#include "numpy/arrayobject.h" |
4
by csa
Initial import |
30 |
|
5
by csa
Join CPU and GPU versions with ifdefs in order to limit dublicating code |
31 |
|
18
by csa
Big redesign (early commit) |
32 |
#include "hst.h" |
7
by csa
more consistent logging |
33 |
#include "debug.h" |
5
by csa
Join CPU and GPU versions with ifdefs in order to limit dublicating code |
34 |
|
4
by csa
Initial import |
35 |
/*
|
36 |
#ifdef LINUX
|
|
37 |
#define _FILE_OFFSET_BITS 64
|
|
38 |
#endif
|
|
39 |
*/
|
|
40 |
||
41 |
||
42 |
||
43 |
/*
|
|
44 |
* The error object to expose
|
|
45 |
*/
|
|
46 |
||
47 |
static PyObject *ErrorObject; |
|
48 |
#define onError(message)\
|
|
49 |
{ PyErr_SetString(ErrorObject, message); return NULL;}
|
|
50 |
||
51 |
||
52 |
||
53 |
typedef struct { |
|
54 |
PyObject_HEAD
|
|
18
by csa
Big redesign (early commit) |
55 |
HSTSetup setup; |
56 |
HSTContextPtr hst; |
|
57 |
||
58 |
FILE *output; /* Identifier for file outp */ |
|
152
by Suren A. Chilingaryan
Support fast writter |
59 |
#ifdef HST_USE_FASTWRITER
|
60 |
fastwriter_t *fw; |
|
61 |
#endif /* HST_USE_FASTWRITER */ |
|
7
by csa
more consistent logging |
62 |
PyObject *logger; /* Message logger object (logging) */ |
38
by csa
Preload data from EDF images while computing slices |
63 |
void *ibuffer1, *ibuffer2; /* Pinned storage for the sinograms */ |
64 |
PyObject *SINO, *SINO1, *SINO2; |
|
18
by csa
Big redesign (early commit) |
65 |
PyObject *SINOGRAMS; /* Storage for the sinogram. Dimensions: */ |
66 |
/* (num_bins,num_projections,dim_slices) */
|
|
67 |
PyObject *axis_corrections; /* Dimensions: */ |
|
68 |
/* (num_projections) */
|
|
228
by Suren A. Chilingaryan
Quality fixes (tex-based) |
69 |
int astra_scaling; |
18
by csa
Big redesign (early commit) |
70 |
int BICUBIC; /* ignored at the moment */ |
4
by csa
Initial import |
71 |
|
72 |
int do_custom_angles; |
|
73 |
float * angles_data; |
|
74 |
||
75 |
PyObject *FilterFunct ; /* object coming from python adn defining the filter */ |
|
76 |
int FilterFunctHasRamp; |
|
77 |
PyObject * FilterOwnerInstance ; |
|
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
78 |
#ifdef HW_USE_PARALLEL_IO
|
79 |
PyObject ** Projections; |
|
80 |
#endif /* HW_USE_PARALLEL_IO */ |
|
10
by csa
Timing measurements and various fixes |
81 |
|
82 |
#ifdef PYHST_MEASURE_TIMINGS
|
|
83 |
double recon_timer; |
|
43
by csa
Option to disable preloading of image files, additional timers |
84 |
double comp_timer; |
85 |
double io_timer; |
|
22
by csa
Timing reporting, few bug fixes |
86 |
PyObject *recon_info; //!< Information about used reconstructors (PyListObject) |
10
by csa
Timing measurements and various fixes |
87 |
#endif /* PYHST_MEASURE_TIMINGS */ |
88 |
||
4
by csa
Initial import |
89 |
} PyHST; |
90 |
||
91 |
staticforward PyTypeObject PyHSTtype; |
|
92 |
||
93 |
#define is_PyHST(v) ((v)->ob_type == &tPyHSType )
|
|
94 |
||
10
by csa
Timing measurements and various fixes |
95 |
|
7
by csa
more consistent logging |
96 |
static void |
22
by csa
Timing reporting, few bug fixes |
97 |
PyHST_log_handler(const gchar *log_domain, GLogLevelFlags log_levels, const gchar *message, PyObject *logger) { |
7
by csa
more consistent logging |
98 |
// PyObject *arglist;
|
99 |
// arglist = Py_BuildValue("(s)", message);
|
|
100 |
||
22
by csa
Timing reporting, few bug fixes |
101 |
if (log_levels&G_LOG_LEVEL_ERROR) PyObject_CallMethod(logger, "critical", "(s)", message); |
102 |
else if (log_levels&G_LOG_LEVEL_CRITICAL) PyObject_CallMethod(logger, "error", "(s)", message); |
|
103 |
else if (log_levels&G_LOG_LEVEL_WARNING) PyObject_CallMethod(logger, "warning", "(s)", message); |
|
104 |
else if (log_levels&G_LOG_LEVEL_MESSAGE) PyObject_CallMethod(logger, "info", "(s)", message); |
|
105 |
else if (log_levels&G_LOG_LEVEL_INFO) PyObject_CallMethod(logger, "info", "(s)", message); |
|
106 |
else PyObject_CallMethod(logger, "debug", "(s)", message); |
|
7
by csa
more consistent logging |
107 |
|
108 |
// Py_DECREF(arglist);
|
|
109 |
}
|
|
110 |
||
4
by csa
Initial import |
111 |
|
112 |
/*
|
|
113 |
* kind of destructor called by garbage collector
|
|
114 |
*/
|
|
115 |
static void |
|
116 |
PyHST_dealloc(PyHST *self) |
|
117 |
{
|
|
22
by csa
Timing reporting, few bug fixes |
118 |
#ifdef PYHST_MEASURE_TIMINGS
|
38
by csa
Preload data from EDF images while computing slices |
119 |
if (self->recon_info) Py_DECREF(self->recon_info); |
22
by csa
Timing reporting, few bug fixes |
120 |
#endif /* PYHST_MEASURE_TIMINGS */ |
38
by csa
Preload data from EDF images while computing slices |
121 |
|
122 |
if (self->hst) hst_destroy_context(self->hst); |
|
18
by csa
Big redesign (early commit) |
123 |
|
152
by Suren A. Chilingaryan
Support fast writter |
124 |
|
125 |
#ifdef HST_USE_FASTWRITER
|
|
126 |
if (self->fw) { |
|
127 |
fastwriter_close(self->fw); |
|
128 |
fastwriter_destroy(self->fw); |
|
129 |
}
|
|
130 |
#endif /* HST_USE_FASTWRITER */ |
|
18
by csa
Big redesign (early commit) |
131 |
if (self->output) fclose(self->output); |
10
by csa
Timing measurements and various fixes |
132 |
|
152
by Suren A. Chilingaryan
Support fast writter |
133 |
|
38
by csa
Preload data from EDF images while computing slices |
134 |
if (self->ibuffer2) { |
135 |
if (self->SINO2) Py_XDECREF(self->SINO2); |
|
136 |
hst_pinned_free(self->ibuffer2); |
|
137 |
}
|
|
138 |
||
139 |
if (self->ibuffer1) { |
|
140 |
if (self->SINO1) Py_XDECREF(self->SINO1); |
|
141 |
hst_pinned_free(self->ibuffer1); |
|
142 |
}
|
|
143 |
||
144 |
if (self->SINO) Py_XDECREF(self->SINO); |
|
145 |
if (self->axis_corrections) Py_XDECREF(self->axis_corrections); |
|
146 |
if (self->logger) Py_XDECREF(self->logger); |
|
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
147 |
|
148 |
#ifdef HW_USE_PARALLEL_IO
|
|
149 |
if (self->Projections) free(self->Projections); |
|
150 |
#endif /* HW_USE_PARALLEL_IO */ |
|
7
by csa
more consistent logging |
151 |
|
4
by csa
Initial import |
152 |
if(self && 0 ) |
153 |
free(self); |
|
154 |
}
|
|
155 |
||
156 |
/*
|
|
157 |
* creation and initialization of a new
|
|
158 |
*/
|
|
159 |
||
160 |
static char PyHST_new_doc[]=""\ |
|
161 |
"/*"\
|
|
162 |
" * creation and initialization of a new PyHST. Lots of arguments:"\
|
|
163 |
" if(!PyArg_ParseTuple(args,\"siiiiifffiiiOii:PyHST_new\", &outputname, &(res->oversampling),&(res->start_x),&(res->start_y),"\ |
|
164 |
" &(res->num_x),&(res->num_y),"\
|
|
165 |
" &(res->axis_position),&(res->angle_offset),&(res->angle_increment),"\
|
|
166 |
" &(res->no_filtering),"\
|
|
167 |
" &(res->num_bins),&(res->num_projections),"\
|
|
168 |
" &(res->SINOGRAMS),"\
|
|
169 |
" &(res->axis_corrections),"\
|
|
170 |
" &(res->BICUBIC),"\
|
|
171 |
" &(res->SUMRULE)"\
|
|
172 |
" ))"\
|
|
173 |
" return NULL;"\
|
|
174 |
" */"; |
|
175 |
||
176 |
static PyObject * |
|
177 |
PyHST_new( PyObject *self, PyObject *args) |
|
178 |
/* return a new instance of edfobject */
|
|
179 |
{
|
|
37
by csa
Optimizations of EDF reading |
180 |
int err = 0; |
4
by csa
Initial import |
181 |
PyHST* res; |
182 |
char * outputname; |
|
168
by Suren A. Chilingaryan
Placeholders for DFI implementation |
183 |
char * method; |
4
by csa
Initial import |
184 |
|
185 |
PyObject *custom_angles ; |
|
7
by csa
more consistent logging |
186 |
PyObject *result; |
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
187 |
PyObject *normalise; |
7
by csa
more consistent logging |
188 |
int log_level; |
4
by csa
Initial import |
189 |
|
22
by csa
Timing reporting, few bug fixes |
190 |
#ifdef PYHST_MEASURE_TIMINGS
|
191 |
int i, j; |
|
192 |
HSTReconstructorConstContextPtr *reconstructors; |
|
193 |
HSTConstString recon_title; |
|
194 |
HSTConstString *timer_names; |
|
195 |
double *timer_values; |
|
196 |
||
197 |
PyObject *recon_dict; |
|
198 |
PyObject *timers_list; |
|
199 |
PyObject *pystr; |
|
200 |
#endif /* PYHST_MEASURE_TIMINGS */ |
|
201 |
||
38
by csa
Preload data from EDF images while computing slices |
202 |
res = (PyHST*) PyObject_NEW(PyHST, &PyHSTtype); |
203 |
||
204 |
res->hst = NULL; |
|
205 |
res->output = NULL; |
|
153
by Suren A. Chilingaryan
Compilation without fastwriter |
206 |
#ifdef HST_USE_FASTWRITER
|
152
by Suren A. Chilingaryan
Support fast writter |
207 |
res->fw = NULL; |
153
by Suren A. Chilingaryan
Compilation without fastwriter |
208 |
#endif /* HST_USE_FASTWRITER */ |
38
by csa
Preload data from EDF images while computing slices |
209 |
res->ibuffer1 = NULL; |
210 |
res->ibuffer2 = NULL; |
|
211 |
||
212 |
#ifdef PYHST_MEASURE_TIMINGS
|
|
213 |
res->recon_info = NULL; |
|
214 |
#endif /* PYHST_MEASURE_TIMINGS */ |
|
4
by csa
Initial import |
215 |
|
228
by Suren A. Chilingaryan
Quality fixes (tex-based) |
216 |
#ifdef PYHST_ASTRA_SCALING
|
217 |
res->astra_scaling = 1; |
|
218 |
#else
|
|
219 |
res->astra_scaling = 0; |
|
220 |
#endif
|
|
221 |
||
168
by Suren A. Chilingaryan
Placeholders for DFI implementation |
222 |
if(!PyArg_ParseTuple(args,"OissiiiiiiiifffiiiOOiiOfiO:PyHST_new", |
18
by csa
Big redesign (early commit) |
223 |
&(res->logger), |
151
by Suren A. Chilingaryan
Multislice mode: preload into the GPU memory complete slices |
224 |
&(res->setup.max_slices), |
18
by csa
Big redesign (early commit) |
225 |
&outputname, |
168
by Suren A. Chilingaryan
Placeholders for DFI implementation |
226 |
&method, |
227 |
&(res->setup.fft_oversampling), |
|
228 |
&(res->setup.dfi_kernel_size), |
|
229 |
&(res->setup.dfi_kernel_points), |
|
18
by csa
Big redesign (early commit) |
230 |
&(res->setup.oversampling), |
231 |
&(res->setup.start_x), |
|
232 |
&(res->setup.start_y), |
|
233 |
&(res->setup.num_x), |
|
234 |
&(res->setup.num_y), |
|
235 |
&(res->setup.axis_position), |
|
236 |
&(res->setup.angle_offset), |
|
237 |
&(res->setup.angle_increment), |
|
238 |
&(res->setup.no_filtering), |
|
239 |
&(res->setup.num_bins), |
|
240 |
&(res->setup.num_projections), |
|
38
by csa
Preload data from EDF images while computing slices |
241 |
&(res->SINO), |
4
by csa
Initial import |
242 |
&(res->axis_corrections), |
243 |
&(res->BICUBIC), |
|
18
by csa
Big redesign (early commit) |
244 |
&(res->setup.sum_rule), |
4
by csa
Initial import |
245 |
&custom_angles, |
18
by csa
Big redesign (early commit) |
246 |
&(res->setup.pente_zone), |
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
247 |
&(res->setup.zerooffmask), |
248 |
&normalise |
|
38
by csa
Preload data from EDF images while computing slices |
249 |
)) { |
250 |
res->SINO = NULL; |
|
251 |
res->logger = NULL; |
|
252 |
res->axis_corrections = NULL; |
|
253 |
||
254 |
Py_DECREF(res); |
|
4
by csa
Initial import |
255 |
return NULL; |
38
by csa
Preload data from EDF images while computing slices |
256 |
}
|
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
257 |
|
258 |
float *norm = (float*) ((PyArrayObject *) normalise)->data; |
|
259 |
res->setup.norm = norm[0]; |
|
260 |
||
38
by csa
Preload data from EDF images while computing slices |
261 |
Py_INCREF(res->logger); |
262 |
Py_INCREF(res->axis_corrections); |
|
263 |
Py_INCREF(res->SINO); |
|
7
by csa
more consistent logging |
264 |
|
18
by csa
Big redesign (early commit) |
265 |
// Configuring the logging subsystem
|
7
by csa
more consistent logging |
266 |
result = PyObject_CallMethod(res->logger, "getEffectiveLevel", "()"); |
267 |
if (result) { |
|
268 |
if (PyInt_Check(result)) log_level = PyInt_AsLong(result); |
|
269 |
else log_level = 0; |
|
270 |
// ||(!PyArg_ParseTuple(result, "i", &log_level))) log_level = 0;
|
|
271 |
Py_DECREF(result); |
|
272 |
} else log_level = 0; |
|
273 |
||
22
by csa
Timing reporting, few bug fixes |
274 |
pyhst_configure_logger(log_level, (GLogFunc)PyHST_log_handler, res->logger); |
18
by csa
Big redesign (early commit) |
275 |
|
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
276 |
#ifdef HW_USE_PARALLEL_IO
|
277 |
res->Projections = (PyObject**)malloc(res->setup.num_projections * sizeof(PyObject*)); |
|
278 |
if (!res->Projections) onError("Memory allocation"); |
|
279 |
#endif /* HW_USE_PARALLEL_IO */ |
|
280 |
||
18
by csa
Big redesign (early commit) |
281 |
// Processing various options
|
4
by csa
Initial import |
282 |
if(PyArray_Check( custom_angles)) { |
283 |
res->do_custom_angles = 1; |
|
284 |
if( ((PyArrayObject *)custom_angles ) ->descr->type_num != PyArray_FLOAT ) onError("arg custom_angles is not an array of float " ) ; |
|
285 |
res->angles_data = (float *) ((PyArrayObject *)custom_angles )->data; |
|
18
by csa
Big redesign (early commit) |
286 |
if( ((PyArrayObject *)custom_angles )->dimensions[0] < res->setup.num_projections ) { |
4
by csa
Initial import |
287 |
onError("arg custom_angles has not the good lenght " ) ; |
288 |
}
|
|
289 |
} else { |
|
290 |
res->do_custom_angles = 0; |
|
291 |
res->angles_data =0; |
|
292 |
}
|
|
293 |
||
18
by csa
Big redesign (early commit) |
294 |
res->FilterFunct=0; |
295 |
res->FilterOwnerInstance=0; |
|
296 |
||
38
by csa
Preload data from EDF images while computing slices |
297 |
if (res->SINO->ob_type == &PyList_Type) { |
298 |
int x, y, z, double_buffer = 1; |
|
299 |
||
300 |
PyObject *tuple = PyList_AsTuple(res->SINO); |
|
301 |
||
302 |
switch (((PyListObject*)(res->SINO))->ob_size) { |
|
303 |
case 3: |
|
304 |
if ((tuple)&&(PyArg_ParseTuple(tuple, "iii", &x, &y, &z))) break; |
|
305 |
else err = 1; |
|
306 |
break; |
|
307 |
case 4: |
|
308 |
if ((tuple)&&(PyArg_ParseTuple(tuple, "iiii", &double_buffer, &x, &y, &z))) break; |
|
309 |
else err = 1; |
|
310 |
break; |
|
311 |
default: |
|
312 |
err = 1; |
|
313 |
}
|
|
314 |
||
228
by Suren A. Chilingaryan
Quality fixes (tex-based) |
315 |
|
38
by csa
Preload data from EDF images while computing slices |
316 |
//pyhst_warning("double buffer: %i\n", double_buffer);
|
4
by csa
Initial import |
317 |
|
38
by csa
Preload data from EDF images while computing slices |
318 |
if (err) { |
319 |
pyhst_error("ERROR : parsing buffer size"); |
|
320 |
Py_DECREF(res); |
|
321 |
return NULL; |
|
322 |
} else { |
|
37
by csa
Optimizations of EDF reading |
323 |
npy_intp dims[3] = {x, y, z}; |
133
by Suren A. Chilingaryan
Pinned OpenCL memory |
324 |
res->ibuffer1 = hst_pinned_malloc(x * y * z * sizeof(float), HST_PINNED_R); |
38
by csa
Preload data from EDF images while computing slices |
325 |
if (res->ibuffer1) { |
326 |
res->SINO1 = PyArray_SimpleNewFromData(3, dims, PyArray_FLOAT, res->ibuffer1); |
|
327 |
if (!res->SINO1) err = 1; |
|
37
by csa
Optimizations of EDF reading |
328 |
} else err = 1; |
38
by csa
Preload data from EDF images while computing slices |
329 |
|
330 |
if (double_buffer > 1) { |
|
133
by Suren A. Chilingaryan
Pinned OpenCL memory |
331 |
res->ibuffer2 = hst_pinned_malloc(x * y * z * sizeof(float), HST_PINNED_R); |
38
by csa
Preload data from EDF images while computing slices |
332 |
if (res->ibuffer2) { |
333 |
res->SINO2 = PyArray_SimpleNewFromData(3, dims, PyArray_FLOAT, res->ibuffer2); |
|
334 |
if (!res->SINO2) err = 1; |
|
335 |
} else err = 1; |
|
336 |
}
|
|
337 |
||
338 |
if (err) { |
|
339 |
pyhst_error("ERROR : allocating pinned memory"); |
|
340 |
Py_DECREF(res); |
|
341 |
return NULL; |
|
342 |
}
|
|
37
by csa
Optimizations of EDF reading |
343 |
}
|
344 |
||
38
by csa
Preload data from EDF images while computing slices |
345 |
res->SINOGRAMS = res->SINO1; |
346 |
} else { |
|
347 |
res->SINOGRAMS = res->SINO; |
|
37
by csa
Optimizations of EDF reading |
348 |
}
|
349 |
||
168
by Suren A. Chilingaryan
Placeholders for DFI implementation |
350 |
if (!strcasecmp(method, "FBP")) { |
351 |
res->setup.method = HST_METHOD_FBP; |
|
352 |
} else if (!strcasecmp(method, "DFI")) { |
|
353 |
res->setup.method = HST_METHOD_DFI; |
|
354 |
} else { |
|
355 |
pyhst_error("ERROR : could not open file %s", outputname); |
|
356 |
Py_DECREF(res); |
|
357 |
return NULL; |
|
358 |
}
|
|
359 |
||
4
by csa
Initial import |
360 |
if(strlen(outputname)>0){ |
152
by Suren A. Chilingaryan
Support fast writter |
361 |
#ifdef HST_USE_FASTWRITER
|
362 |
res->fw = fastwriter_init(outputname, FASTWRITER_FLAGS_OVERWRITE); |
|
363 |
if (res->fw) { |
|
155
by Suren A. Chilingaryan
Force long types |
364 |
fastwriter_set_buffer_size(res->fw, HST_USE_FASTWRITER * 1024ll * 1024ll); |
152
by Suren A. Chilingaryan
Support fast writter |
365 |
if (fastwriter_open(res->fw, outputname, FASTWRITER_FLAGS_OVERWRITE)) { |
366 |
fastwriter_destroy(res->fw); |
|
367 |
res->fw = NULL; |
|
368 |
}
|
|
369 |
}
|
|
370 |
if (!res->fw) { |
|
371 |
#else /* HST_USE_FASTWRITER */ |
|
4
by csa
Initial import |
372 |
res->output=fopen(outputname,"w"); |
373 |
if(!res->output) { |
|
152
by Suren A. Chilingaryan
Support fast writter |
374 |
#endif /* HST_USE_FASTWRITER */ |
8
by csa
remove extra line breaks in log messages |
375 |
pyhst_error("ERROR : could not open file %s", outputname); |
37
by csa
Optimizations of EDF reading |
376 |
Py_DECREF(res); |
4
by csa
Initial import |
377 |
return NULL; |
378 |
}
|
|
38
by csa
Preload data from EDF images while computing slices |
379 |
}
|
18
by csa
Big redesign (early commit) |
380 |
|
381 |
res->hst = hst_create_context(); |
|
382 |
if ((!res->hst)||(hst_init_context(res->hst, &res->setup, res->do_custom_angles?res->angles_data:NULL, (float*) ((PyArrayObject *) res->axis_corrections)->data))) { |
|
37
by csa
Optimizations of EDF reading |
383 |
Py_DECREF(res); |
18
by csa
Big redesign (early commit) |
384 |
return NULL; |
385 |
}
|
|
152
by Suren A. Chilingaryan
Support fast writter |
386 |
|
387 |
#ifdef HST_USE_FASTWRITER
|
|
388 |
hst_set_fastwriter(res->hst, res->fw); |
|
389 |
#else /* HST_USE_FASTWRITER */ |
|
18
by csa
Big redesign (early commit) |
390 |
hst_set_output_file(res->hst, res->output); |
152
by Suren A. Chilingaryan
Support fast writter |
391 |
#endif /* HST_USE_FASTWRITER */ |
392 |
||
10
by csa
Timing measurements and various fixes |
393 |
#ifdef PYHST_MEASURE_TIMINGS
|
394 |
res->recon_timer = 0; |
|
22
by csa
Timing reporting, few bug fixes |
395 |
|
396 |
reconstructors = hst_get_configured_reconstructors(res->hst); |
|
397 |
for (i = 0; reconstructors[i]; i++); |
|
398 |
||
399 |
res->recon_info = PyList_New(i);//(PyArrayObject*)PyArray_FromDims(1, &i, PyArray_OBJECT); |
|
400 |
if (res->recon_info) { |
|
401 |
for (i = 0; reconstructors[i]; i++) { |
|
402 |
recon_dict = PyDict_New(); |
|
403 |
if (recon_dict) { |
|
404 |
recon_title = hst_reconstructor_get_title(reconstructors[i]); |
|
405 |
pystr = PyString_FromString(recon_title?recon_title:"Reconstructor"); |
|
406 |
if (pystr) { |
|
407 |
PyDict_SetItemString(recon_dict, "title", pystr); |
|
408 |
Py_DECREF(pystr); |
|
409 |
}
|
|
410 |
||
411 |
timer_names = hst_reconstructor_get_timers(reconstructors[i], NULL); |
|
412 |
if (timer_names) { |
|
413 |
for (j = 0; timer_names[j]; j++); |
|
414 |
if (j) { |
|
34
by csa
Migration to numpy |
415 |
npy_intp dims = j; |
416 |
timers_list = PyArray_SimpleNew(1, &dims, PyArray_DOUBLE); |
|
22
by csa
Timing reporting, few bug fixes |
417 |
if (timers_list) { |
418 |
timer_values = (double *) ((PyArrayObject*)timers_list)->data; |
|
419 |
for (j = 0; timer_names[j]; j++) { |
|
420 |
timer_values[j] = 0; |
|
421 |
}
|
|
422 |
PyDict_SetItemString(recon_dict, "timers", timers_list); |
|
423 |
Py_DECREF(timers_list); |
|
424 |
}
|
|
425 |
||
426 |
if (timers_list) timers_list = PyList_New(j); |
|
427 |
||
428 |
if (timers_list) { |
|
429 |
for (j = 0; timer_names[j]; j++) { |
|
430 |
pystr = PyString_FromString(timer_names[j]); |
|
431 |
if (pystr) { |
|
432 |
// A reference is stollen by this function
|
|
433 |
PyList_SetItem(timers_list, j, pystr); |
|
434 |
} else { |
|
435 |
Py_INCREF(Py_None); |
|
436 |
PyList_SetItem(timers_list, j, Py_None); |
|
437 |
}
|
|
438 |
}
|
|
439 |
PyDict_SetItemString(recon_dict, "timer_names", timers_list); |
|
440 |
Py_DECREF(timers_list); |
|
441 |
}
|
|
442 |
||
443 |
timers_list = PyInt_FromLong(0); |
|
444 |
if (timers_list) { |
|
445 |
PyDict_SetItemString(recon_dict, "slices", timers_list); |
|
446 |
Py_DECREF(timers_list); |
|
447 |
}
|
|
448 |
}
|
|
449 |
}
|
|
450 |
||
451 |
PyList_SetItem(res->recon_info, i, recon_dict); |
|
452 |
// SetItem steals a reference, we do not need Py_DECREF(recon_dict);
|
|
453 |
} else { |
|
454 |
Py_INCREF(Py_None); |
|
455 |
PyList_SetItem(res->recon_info, i, Py_None); |
|
456 |
}
|
|
457 |
}
|
|
458 |
} else { |
|
459 |
Py_INCREF(Py_None); |
|
460 |
res->recon_info = Py_None; |
|
461 |
}
|
|
10
by csa
Timing measurements and various fixes |
462 |
#endif /* PYHST_MEASURE_TIMINGS */ |
463 |
||
4
by csa
Initial import |
464 |
return (PyObject*) res; |
465 |
}
|
|
466 |
||
45
by csa
Fixes measurements of I/O timings |
467 |
|
4
by csa
Initial import |
468 |
static PyObject * |
469 |
PyHST_close( PyObject *self, PyObject *args) |
|
470 |
/* return a new instance of edfobject */
|
|
471 |
{
|
|
45
by csa
Fixes measurements of I/O timings |
472 |
#ifdef PYHST_MEASURE_TIMINGS
|
473 |
PyHST *ctx; |
|
474 |
GTimer *timer; |
|
475 |
double time; |
|
476 |
||
477 |
ctx = (PyHST *)self; |
|
478 |
timer = g_timer_new(); |
|
479 |
#endif /* PYHST_MEASURE_TIMINGS */ |
|
480 |
||
18
by csa
Big redesign (early commit) |
481 |
if (((PyHST *) self)->output) { |
482 |
hst_set_output_file(((PyHST*)self)->hst, NULL); |
|
152
by Suren A. Chilingaryan
Support fast writter |
483 |
#ifdef HST_USE_FASTWRITER
|
484 |
fastwriter_close(((PyHST*)self)->fw); |
|
485 |
fastwriter_destroy(((PyHST*)self)->fw); |
|
486 |
#else /* HST_USE_FASTWRITER */ |
|
18
by csa
Big redesign (early commit) |
487 |
fclose( ( (PyHST *) self)->output); |
488 |
((PyHST *) self)->output = NULL; |
|
152
by Suren A. Chilingaryan
Support fast writter |
489 |
#endif /* HST_USE_FASTWRITER */ |
18
by csa
Big redesign (early commit) |
490 |
}
|
45
by csa
Fixes measurements of I/O timings |
491 |
|
492 |
#ifdef PYHST_MEASURE_TIMINGS
|
|
493 |
g_timer_stop(timer); |
|
494 |
time = g_timer_elapsed(timer, NULL); |
|
495 |
ctx->io_timer += time; |
|
496 |
ctx->recon_timer += time; |
|
141
by Suren A. Chilingaryan
Counter optimization |
497 |
// ctx->comp_timer += time;
|
45
by csa
Fixes measurements of I/O timings |
498 |
g_timer_destroy(timer); |
499 |
#endif /* PYHST_MEASURE_TIMINGS */ |
|
500 |
||
4
by csa
Initial import |
501 |
Py_INCREF( Py_None); |
502 |
return Py_None; |
|
503 |
||
504 |
}
|
|
505 |
||
506 |
||
18
by csa
Big redesign (early commit) |
507 |
void PyHST_setFilter(PyHST *self, int dim_fft, float *FILTER) { |
508 |
int j; |
|
509 |
||
510 |
PyObject *FilterFunct; |
|
511 |
PyObject *FilterOwnerInstance; |
|
512 |
int FilterFunctHasRamp; |
|
513 |
||
514 |
PyObject * pyargs, *pyres; |
|
515 |
||
516 |
FilterFunct = self->FilterFunct; |
|
517 |
FilterOwnerInstance = self->FilterOwnerInstance; |
|
518 |
FilterFunctHasRamp = self->FilterFunctHasRamp; |
|
519 |
||
520 |
if(FilterFunctHasRamp==0) { |
|
521 |
pyargs = Py_BuildValue("(O,f)", FilterOwnerInstance,0.5); |
|
522 |
pyres = PyEval_CallObject(FilterFunct, pyargs); |
|
523 |
} else { |
|
524 |
pyargs = Py_BuildValue("(O,l,l)", FilterOwnerInstance,dim_fft/2, dim_fft); |
|
525 |
pyres = PyEval_CallObject(FilterFunct, pyargs); |
|
526 |
}
|
|
527 |
||
528 |
if (pyres==NULL) pyhst_fail("Filter have failed"); |
|
529 |
||
530 |
if(FilterFunctHasRamp==0) { |
|
531 |
FILTER[1]= PyFloat_AsDouble(pyres)/dim_fft; ; /* This is the real part of the highest frequency */ |
|
532 |
} else { |
|
533 |
FILTER[1]= PyFloat_AsDouble(pyres)*2.0/dim_fft; ; /* This is the real part of the highest frequency */ |
|
534 |
}
|
|
535 |
||
536 |
Py_DECREF(pyargs); |
|
537 |
Py_DECREF(pyres ); |
|
538 |
||
539 |
if(FilterFunctHasRamp) { |
|
23
by csa
Perform pair of convolutions using a single complex fourier transformation in CUDA reconstruction module (early commit) |
540 |
pyargs = Py_BuildValue("(O,i,i)", FilterOwnerInstance, 0, dim_fft); |
18
by csa
Big redesign (early commit) |
541 |
pyres = PyEval_CallObject(FilterFunct, pyargs); |
542 |
FILTER[0]= PyFloat_AsDouble(pyres)*2.0/dim_fft; ; /* This is the real part of the highest frequency */ |
|
543 |
} else { |
|
544 |
FILTER[0] = 0; |
|
545 |
}
|
|
546 |
||
547 |
for(j=1;j<dim_fft / 2; j++) { |
|
548 |
if(FilterFunctHasRamp==0) { |
|
549 |
||
550 |
pyargs = Py_BuildValue("(O,f)",FilterOwnerInstance,j * 1.0 / dim_fft ); |
|
551 |
pyres = PyEval_CallObject(FilterFunct, pyargs); |
|
552 |
||
553 |
FILTER[2 * j] = PyFloat_AsDouble(pyres)* j * 2.0 / dim_fft/ dim_fft ; |
|
554 |
FILTER[2 * j+1] = FILTER[2 * j]; |
|
555 |
} else { |
|
556 |
||
557 |
pyargs = Py_BuildValue("(O,i,i)",FilterOwnerInstance,j , dim_fft); |
|
558 |
pyres = PyEval_CallObject(FilterFunct, pyargs); |
|
559 |
||
560 |
||
561 |
FILTER[2 * j] = PyFloat_AsDouble(pyres)* 2.0/dim_fft ; |
|
562 |
FILTER[2 * j+1] = FILTER[2 * j]; |
|
563 |
}
|
|
564 |
||
565 |
||
566 |
Py_DECREF(pyargs); |
|
567 |
Py_DECREF(pyres ); |
|
568 |
||
569 |
}
|
|
570 |
}
|
|
571 |
||
572 |
||
4
by csa
Initial import |
573 |
static char PyHST_SetFilterFunct_doc[]=""\ |
574 |
"/* Set the Filter with a python Function."\
|
|
575 |
" needs one argument : a function(x)"\
|
|
576 |
" X goes from -0.5 to 0.5 "\
|
|
577 |
" the function must return a float"\
|
|
578 |
" */"\
|
|
579 |
""; |
|
580 |
||
581 |
||
582 |
static PyObject * PyHST_SetFilterFunct(PyObject *self_a, PyObject *args) |
|
583 |
{
|
|
584 |
PyHST *self; |
|
585 |
self = (PyHST *) self_a; |
|
586 |
if(!PyArg_ParseTuple(args,"OOi:PyHST_SetFilterFunct",&self->FilterOwnerInstance , &self->FilterFunct, &self->FilterFunctHasRamp) ) { |
|
587 |
return NULL; |
|
588 |
}
|
|
589 |
Py_XINCREF(self->FilterFunct); |
|
590 |
Py_XINCREF(self->FilterOwnerInstance); |
|
591 |
||
18
by csa
Big redesign (early commit) |
592 |
hst_set_filter(self->hst, self->FilterFunct?(HSTFilterFunction)PyHST_setFilter:NULL, self); |
593 |
||
4
by csa
Initial import |
594 |
Py_INCREF( Py_None); |
595 |
return Py_None; |
|
596 |
||
597 |
}
|
|
598 |
||
599 |
||
600 |
static char PyHST_calcSlices_doc[]=""\ |
|
601 |
"/* calculate a number of slices given as argument"\
|
|
602 |
" Takes two arguments : "\
|
|
603 |
"if(!PyArg_ParseTuple(args,\"ii:PyHST_calcSlices\", &num_slices ))"\ |
|
604 |
" return NULL;"\
|
|
605 |
" */"\
|
|
606 |
""; |
|
607 |
||
608 |
/* l ' ordinamento dimensioni per SINOGRAMS est num_slices self->num_projections self->num_bins
|
|
609 |
||
610 |
sarebbe saggio verificare en passant che corrisponde alle dimensioni di self->SINOGRAMS
|
|
611 |
*/
|
|
612 |
static char PyHST_calcMedian_doc[]=""; |
|
613 |
||
614 |
#define swap_float( a,b) tmp_swap=(a); (a)=(b); (b)=tmp_swap;
|
|
615 |
||
616 |
int compare_floats (const void * A, |
|
617 |
const void * B) |
|
618 |
{
|
|
619 |
||
620 |
float *a, *b; |
|
621 |
a=(float *)A; |
|
622 |
b=(float *)B; |
|
623 |
||
624 |
||
625 |
if (*a > *b) |
|
626 |
return 1; |
|
627 |
else if (*a < *b) |
|
628 |
return -1; |
|
629 |
else
|
|
630 |
return 0; |
|
631 |
}
|
|
632 |
||
633 |
float getmedian(float *room_for_median, int dim2 ) { |
|
634 |
||
635 |
qsort ( room_for_median , dim2 , sizeof(float), compare_floats ); |
|
636 |
||
637 |
||
638 |
return 0.5*( room_for_median[ dim2/2 ] |
|
639 |
+ room_for_median[ (int)(dim2/2.0-0.1 )] |
|
640 |
) ; |
|
641 |
||
642 |
||
643 |
}
|
|
644 |
||
645 |
static PyObject * |
|
646 |
PyHST_calcMedian(PyObject *self_a, PyObject *args) |
|
647 |
{
|
|
648 |
int num_slices; |
|
649 |
float *SLICE; |
|
650 |
int first_slice; |
|
651 |
int last_slice; |
|
652 |
PyHST *self; |
|
653 |
PyObject *options , *arr_a ; |
|
654 |
||
655 |
||
656 |
char *padding; |
|
657 |
char *axis_to_the_center; |
|
658 |
||
659 |
||
660 |
int offset, stride; |
|
661 |
float * data, * toorder; |
|
662 |
int iv,ix,i; |
|
663 |
int nd; |
|
37
by csa
Optimizations of EDF reading |
664 |
int dims[2]; |
4
by csa
Initial import |
665 |
int domean; |
666 |
double sum; |
|
667 |
||
8
by csa
remove extra line breaks in log messages |
668 |
pyhst_debug(" sono in median "); |
4
by csa
Initial import |
669 |
|
670 |
first_slice=0; |
|
671 |
options = 0 ; |
|
672 |
padding = "E"; /* E as extrema, other value is 0 (zero) */ |
|
673 |
axis_to_the_center = "N"; /* 'Y' or 'N' */ |
|
674 |
||
675 |
self = (PyHST *) self_a; |
|
676 |
||
677 |
if(!PyArg_ParseTuple(args,"ii|O:PyHST_calcSlices", &num_slices, &domean, &options)) |
|
678 |
return NULL; |
|
679 |
last_slice=first_slice+num_slices-1; |
|
680 |
||
18
by csa
Big redesign (early commit) |
681 |
SLICE=malloc( num_slices * self->setup.num_bins* sizeof(float) ); |
4
by csa
Initial import |
682 |
|
18
by csa
Big redesign (early commit) |
683 |
if( ((PyArrayObject *) self->SINOGRAMS)->dimensions[1] != self->setup.num_projections) { |
684 |
pyhst_fail(" ((PyArrayObject *) self->SINOGRAMS)->dimensions[0] != self->num_projections %d %d ", ((PyArrayObject *) self->SINOGRAMS)->dimensions[1] , self->setup.num_projections ); |
|
4
by csa
Initial import |
685 |
}
|
18
by csa
Big redesign (early commit) |
686 |
if( ((PyArrayObject *) self->SINOGRAMS)->dimensions[2] != self->setup.num_bins) { |
687 |
pyhst_fail(" ((PyArrayObject *) self->SINOGRAMS)->dimensions[2] != self->num_bins %d %d ", ((PyArrayObject *) self->SINOGRAMS)->dimensions[2] , self->setup.num_bins ); |
|
4
by csa
Initial import |
688 |
}
|
689 |
||
690 |
/* if( ((PyArrayObject *) self->SINOGRAMS)->dimensions[0] != num_slices ) { */
|
|
8
by csa
remove extra line breaks in log messages |
691 |
/* pyhst_debug(" ((PyArrayObject *) self->SINOGRAMS)->dimensions[0] != num_slices %d %d ", ((PyArrayObject *) self->SINOGRAMS)->dimensions[0] , num_slices ); */
|
4
by csa
Initial import |
692 |
/* exit(0); */
|
693 |
/* } */
|
|
694 |
||
695 |
||
696 |
data = (float*) ((PyArrayObject *) self->SINOGRAMS)->data; |
|
18
by csa
Big redesign (early commit) |
697 |
toorder = malloc( self->setup.num_projections* sizeof(float)); |
4
by csa
Initial import |
698 |
for(iv=0; iv<num_slices; iv++) { |
18
by csa
Big redesign (early commit) |
699 |
for(ix=0; ix<self->setup.num_bins; ix++) { |
4
by csa
Initial import |
700 |
|
18
by csa
Big redesign (early commit) |
701 |
offset = iv*self->setup.num_bins*self->setup.num_projections + ix; |
702 |
stride = self->setup.num_bins; |
|
703 |
for(i=0; i<self->setup.num_projections;i++) { |
|
4
by csa
Initial import |
704 |
toorder[i] = data[offset+i*stride]; |
705 |
}
|
|
706 |
if(domean==0){ |
|
18
by csa
Big redesign (early commit) |
707 |
SLICE[iv*self->setup.num_bins + ix] =getmedian(toorder, self->setup.num_projections); |
4
by csa
Initial import |
708 |
} else { |
709 |
sum=0; |
|
18
by csa
Big redesign (early commit) |
710 |
for(i=0; i<self->setup.num_projections;i++) { |
4
by csa
Initial import |
711 |
sum += toorder[i]; |
712 |
}
|
|
18
by csa
Big redesign (early commit) |
713 |
SLICE[iv*self->setup.num_bins + ix] = sum / self->setup.num_projections; |
4
by csa
Initial import |
714 |
}
|
715 |
}
|
|
716 |
}
|
|
717 |
||
718 |
nd=2; |
|
719 |
dims[0] =num_slices ; |
|
18
by csa
Big redesign (early commit) |
720 |
dims[1] = self->setup.num_bins; |
4
by csa
Initial import |
721 |
arr_a = PyArray_FromDims(nd,dims,PyArray_FLOAT ) ; |
18
by csa
Big redesign (early commit) |
722 |
memcpy( ((PyArrayObject *) arr_a)->data, SLICE , num_slices * self->setup.num_bins*sizeof(float) ); |
4
by csa
Initial import |
723 |
|
724 |
free(toorder); |
|
725 |
free(SLICE); |
|
726 |
return PyArray_Return((PyArrayObject *) arr_a); |
|
727 |
||
728 |
}
|
|
729 |
||
18
by csa
Big redesign (early commit) |
730 |
static PyObject * |
731 |
PyHST_RECON(PyHST *self, int num_slices, PyObject *options, PyArrayObject *Oslice) { |
|
6
by csa
GPU based FFT: first test |
732 |
int err; |
18
by csa
Big redesign (early commit) |
733 |
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
734 |
PyObject * dic_key; |
735 |
PyObject * dic_value; |
|
736 |
||
737 |
char *padding; |
|
738 |
char *axis_to_the_center; |
|
739 |
||
740 |
#ifdef PYHST_MEASURE_TIMINGS
|
|
741 |
GTimer *timer; |
|
22
by csa
Timing reporting, few bug fixes |
742 |
|
743 |
int i; |
|
744 |
HSTReconstructorConstContextPtr *reconstructors; |
|
745 |
PyObject *recon_dict; |
|
746 |
PyObject *timers; |
|
747 |
PyObject *slices; |
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
748 |
#endif /* PYHST_MEASURE_TIMINGS */ |
749 |
||
750 |
padding = "E"; /* E as extrema, other value is 0 (zero) */ |
|
751 |
axis_to_the_center = "N"; /* 'Y' or 'N' */ |
|
752 |
||
753 |
if(options!=0) { |
|
754 |
dic_key = PyString_FromString("padding"); |
|
755 |
dic_value = PyDict_GetItem(options, dic_key); |
|
756 |
if( dic_value ) { |
|
757 |
padding = PyString_AsString(dic_value ); |
|
758 |
}
|
|
759 |
Py_DECREF(dic_key); |
|
760 |
dic_key = PyString_FromString("axis_to_the_center"); |
|
761 |
dic_value = PyDict_GetItem(options, dic_key); |
|
762 |
if( dic_value ) { |
|
763 |
axis_to_the_center = PyString_AsString(dic_value ); |
|
764 |
}
|
|
765 |
Py_DECREF(dic_key); |
|
766 |
}
|
|
767 |
||
18
by csa
Big redesign (early commit) |
768 |
// padding[0]=='E' pads with extrema, '0' ( zero ) with zeros , defaults to 'E'
|
769 |
hst_set_padding(self->hst, *padding == '0'); |
|
770 |
||
771 |
// /* 'Y' or 'N' */
|
|
772 |
hst_set_axis_mode(self->hst, *axis_to_the_center == 'Y'); |
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
773 |
|
774 |
#ifdef PYHST_MEASURE_TIMINGS
|
|
775 |
timer = g_timer_new(); |
|
776 |
#endif /* PYHST_MEASURE_TIMINGS */ |
|
777 |
||
38
by csa
Preload data from EDF images while computing slices |
778 |
if ((Oslice)||(!self->ibuffer2)) { |
779 |
err = hst_reconstruct_slices(self->hst, |
|
780 |
num_slices, |
|
18
by csa
Big redesign (early commit) |
781 |
Oslice?(float*)Oslice->data:NULL, |
782 |
(float*) ((PyArrayObject *) self->SINOGRAMS)->data |
|
38
by csa
Preload data from EDF images while computing slices |
783 |
);
|
784 |
} else { |
|
785 |
hst_reconstruct_wait(self->hst); |
|
786 |
||
787 |
err = hst_reconstruct_start(self->hst, num_slices, (float*) ((PyArrayObject *) self->SINOGRAMS)->data); |
|
788 |
||
789 |
if (self->SINOGRAMS == self->SINO1) self->SINOGRAMS = self->SINO2; |
|
790 |
else self->SINOGRAMS = self->SINO1; |
|
791 |
}
|
|
792 |
||
18
by csa
Big redesign (early commit) |
793 |
check_code(err, "hst_reconstruct_slices"); |
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
794 |
|
795 |
#ifdef PYHST_MEASURE_TIMINGS
|
|
796 |
if (timer) { |
|
797 |
self->recon_timer += g_timer_elapsed(timer, NULL); |
|
798 |
g_timer_destroy(timer); |
|
799 |
}
|
|
43
by csa
Option to disable preloading of image files, additional timers |
800 |
|
801 |
self->comp_timer = hst_get_recon_timer(self->hst); |
|
802 |
self->io_timer = hst_get_io_timer(self->hst); |
|
22
by csa
Timing reporting, few bug fixes |
803 |
|
804 |
if (self->recon_info) { |
|
805 |
reconstructors = hst_get_configured_reconstructors(self->hst); |
|
806 |
for (i = 0; reconstructors[i]; i++) { |
|
807 |
recon_dict = PyList_GetItem(self->recon_info, i); |
|
808 |
if (recon_dict) { |
|
809 |
timers = PyDict_GetItemString(recon_dict, "timers"); |
|
810 |
if (timers) { |
|
811 |
hst_reconstructor_get_timers(reconstructors[i], (double *) ((PyArrayObject*)timers)->data); |
|
812 |
}
|
|
813 |
||
814 |
slices = PyInt_FromLong(reconstructors[i]->processed_slices); |
|
815 |
if (slices) { |
|
816 |
PyDict_SetItemString(recon_dict, "slices", slices); |
|
817 |
Py_DECREF(slices); |
|
818 |
}
|
|
819 |
}
|
|
820 |
}
|
|
821 |
}
|
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
822 |
#endif /* PYHST_MEASURE_TIMINGS */ |
823 |
||
824 |
Py_INCREF( Py_None); |
|
825 |
return Py_None; |
|
826 |
}
|
|
827 |
||
828 |
||
829 |
static PyObject * |
|
830 |
PyHST_calcSlices(PyObject *self_a, PyObject *args) |
|
831 |
{
|
|
832 |
PyHST *self; |
|
833 |
||
834 |
int num_slices; |
|
835 |
PyObject *options ; |
|
836 |
||
837 |
self = (PyHST *) self_a; |
|
838 |
||
839 |
if(!PyArg_ParseTuple(args,"i|O:PyHST_calcSlices", &num_slices, &options)) |
|
840 |
return NULL; |
|
841 |
||
842 |
return PyHST_RECON(self, num_slices, options, NULL); |
|
843 |
}
|
|
844 |
||
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
845 |
|
846 |
||
847 |
static char PyHST_startPreprocessing_doc[]=""; |
|
848 |
static PyObject * |
|
849 |
PyHST_startPreprocessing(PyObject *self_a, PyObject *args) { |
|
850 |
PyHST *self; |
|
851 |
||
852 |
int num_slices; |
|
853 |
||
854 |
self = (PyHST *) self_a; |
|
855 |
||
856 |
if(!PyArg_ParseTuple(args,"i:PyHST_calcSlices", &num_slices)) |
|
857 |
return NULL; |
|
858 |
||
859 |
hst_preprocess_start(self->hst, num_slices, (float*) ((PyArrayObject *) self->SINOGRAMS)->data); |
|
860 |
||
861 |
Py_INCREF( Py_None); |
|
862 |
return Py_None; |
|
863 |
}
|
|
864 |
||
865 |
static char PyHST_waitPreprocessing_doc[]=""; |
|
866 |
static PyObject * |
|
867 |
PyHST_waitPreprocessing(PyObject *self_a, PyObject *args) { |
|
868 |
int i; |
|
869 |
PyHST *self; |
|
870 |
||
871 |
self = (PyHST *) self_a; |
|
872 |
||
873 |
hst_preprocess_wait(self->hst); |
|
874 |
||
875 |
#ifdef HW_USE_PARALLEL_IO
|
|
876 |
for (i = 0; i < self->setup.num_projections; i++) { |
|
877 |
Py_DECREF(self->Projections[i]); |
|
878 |
}
|
|
879 |
#endif /* HW_USE_PARALLEL_IO */ |
|
880 |
||
881 |
Py_INCREF( Py_None); |
|
882 |
return Py_None; |
|
883 |
}
|
|
884 |
||
885 |
||
886 |
static char PyHST_transposeSlices_doc[]=""\ |
|
887 |
"/* transposes a number of slices given as argument"\
|
|
888 |
" */"\
|
|
889 |
""; |
|
890 |
static PyObject * |
|
891 |
PyHST_transposeSlices(PyObject *self_a, PyObject *args) |
|
892 |
{
|
|
893 |
PyHST *self; |
|
894 |
||
895 |
int err; |
|
896 |
int proj; |
|
897 |
PyObject *item; |
|
898 |
||
899 |
self = (PyHST *) self_a; |
|
900 |
||
901 |
if(!PyArg_ParseTuple(args,"Oi:PyHST_calcSlices", &item, &proj)) |
|
902 |
return NULL; |
|
903 |
||
904 |
Py_INCREF(item); |
|
905 |
||
906 |
float *in = (float*) ((PyArrayObject *) item)->data; |
|
907 |
err = hst_preprocess_projection(self->hst, proj, in); |
|
908 |
||
909 |
#ifdef HW_USE_PARALLEL_IO
|
|
910 |
self->Projections[proj] = item; |
|
911 |
#else /* HW_USE_PARALLEL_IO */ |
|
912 |
Py_DECREF(item); |
|
913 |
#endif /* HW_USE_PARALLEL_IO */ |
|
914 |
||
915 |
Py_INCREF( Py_None); |
|
916 |
return Py_None; |
|
917 |
}
|
|
918 |
||
919 |
||
920 |
||
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
921 |
static char PyHST_calcSlicesMemory_doc[]=""\ |
922 |
"/* calculate a number of slices given as argument"\
|
|
923 |
" Takes three arguments : "\
|
|
924 |
"if(!PyArg_ParseTuple(args,\"iiO:PyHST_calcSlices\", &num_slices, &Oslice))"\ |
|
925 |
" return NULL;"\
|
|
926 |
" */"\
|
|
927 |
""; |
|
928 |
static PyObject * |
|
929 |
PyHST_calcSlicesMemory(PyObject *self_a, PyObject *args) |
|
930 |
{
|
|
931 |
PyHST *self; |
|
932 |
||
933 |
int num_slices; |
|
934 |
PyObject *options ; |
|
935 |
PyArrayObject * Oslice ; |
|
936 |
||
937 |
self = (PyHST *) self_a; |
|
938 |
||
939 |
if(!PyArg_ParseTuple(args,"iO|O:PyHST_calcSlicesMemory", &num_slices, &Oslice, &options ) ) |
|
940 |
return NULL; |
|
941 |
||
942 |
return PyHST_RECON(self, num_slices, options, Oslice); |
|
943 |
}
|
|
944 |
||
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
945 |
|
946 |
||
38
by csa
Preload data from EDF images while computing slices |
947 |
static PyObject * |
948 |
PyHST_waitCompletion(PyObject *self_a, PyObject *args) |
|
949 |
{
|
|
950 |
PyHST *self; |
|
951 |
self = (PyHST *) self_a; |
|
952 |
||
42
by csa
Fix measuring overall reconstruction time |
953 |
#ifdef PYHST_MEASURE_TIMINGS
|
43
by csa
Option to disable preloading of image files, additional timers |
954 |
int i; |
955 |
HSTReconstructorConstContextPtr *reconstructors; |
|
956 |
PyObject *recon_dict; |
|
957 |
PyObject *timers; |
|
958 |
PyObject *slices; |
|
959 |
||
42
by csa
Fix measuring overall reconstruction time |
960 |
GTimer *timer; |
961 |
||
962 |
timer = g_timer_new(); |
|
963 |
#endif /* PYHST_MEASURE_TIMINGS */ |
|
964 |
||
38
by csa
Preload data from EDF images while computing slices |
965 |
hst_reconstruct_wait(self->hst); |
966 |
||
42
by csa
Fix measuring overall reconstruction time |
967 |
#ifdef PYHST_MEASURE_TIMINGS
|
968 |
if (timer) { |
|
969 |
self->recon_timer += g_timer_elapsed(timer, NULL); |
|
970 |
g_timer_destroy(timer); |
|
971 |
}
|
|
43
by csa
Option to disable preloading of image files, additional timers |
972 |
|
973 |
self->comp_timer = hst_get_recon_timer(self->hst); |
|
974 |
self->io_timer = hst_get_io_timer(self->hst); |
|
975 |
||
976 |
if (self->recon_info) { |
|
977 |
reconstructors = hst_get_configured_reconstructors(self->hst); |
|
978 |
for (i = 0; reconstructors[i]; i++) { |
|
979 |
recon_dict = PyList_GetItem(self->recon_info, i); |
|
980 |
if (recon_dict) { |
|
981 |
timers = PyDict_GetItemString(recon_dict, "timers"); |
|
982 |
if (timers) { |
|
983 |
hst_reconstructor_get_timers(reconstructors[i], (double *) ((PyArrayObject*)timers)->data); |
|
984 |
}
|
|
985 |
||
986 |
slices = PyInt_FromLong(reconstructors[i]->processed_slices); |
|
987 |
if (slices) { |
|
988 |
PyDict_SetItemString(recon_dict, "slices", slices); |
|
989 |
Py_DECREF(slices); |
|
990 |
}
|
|
991 |
}
|
|
992 |
}
|
|
993 |
}
|
|
994 |
||
42
by csa
Fix measuring overall reconstruction time |
995 |
#endif /* PYHST_MEASURE_TIMINGS */ |
996 |
||
38
by csa
Preload data from EDF images while computing slices |
997 |
Py_INCREF( Py_None); |
998 |
return Py_None; |
|
999 |
}
|
|
1000 |
||
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1001 |
|
1002 |
static PyMethodDef PyHST_methods[]={ |
|
132
by Suren A. Chilingaryan
Pipelined preprocessing (normalize & transpose) |
1003 |
{"startPreprocessing",(PyCFunction) PyHST_startPreprocessing, METH_VARARGS,PyHST_startPreprocessing_doc}, |
1004 |
{"waitPreprocessing",(PyCFunction) PyHST_waitPreprocessing, METH_VARARGS,PyHST_waitPreprocessing_doc}, |
|
1005 |
{"transposeSlices",(PyCFunction) PyHST_transposeSlices, METH_VARARGS,PyHST_transposeSlices_doc}, |
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1006 |
{"calcSlices",(PyCFunction) PyHST_calcSlices, METH_VARARGS,PyHST_calcSlices_doc}, |
1007 |
{"calcMedian",(PyCFunction) PyHST_calcMedian, METH_VARARGS,PyHST_calcMedian_doc}, |
|
1008 |
{"calcSlicesMemory",(PyCFunction) PyHST_calcSlicesMemory, METH_VARARGS,PyHST_calcSlicesMemory_doc}, |
|
38
by csa
Preload data from EDF images while computing slices |
1009 |
{"waitCompletion",(PyCFunction) PyHST_waitCompletion, METH_VARARGS,NULL}, |
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1010 |
{"setFilterFunct",(PyCFunction) PyHST_SetFilterFunct, METH_VARARGS,PyHST_SetFilterFunct_doc}, |
1011 |
{"close", (PyCFunction) PyHST_close, METH_VARARGS, NULL }, |
|
1012 |
{ NULL, NULL} |
|
1013 |
};
|
|
1014 |
||
1015 |
||
1016 |
static struct memberlist PyHST_memberlist[]={ |
|
37
by csa
Optimizations of EDF reading |
1017 |
{"SINOGRAMS", T_OBJECT, offsetof(PyHST, SINOGRAMS)}, |
228
by Suren A. Chilingaryan
Quality fixes (tex-based) |
1018 |
{"astra_scaling", T_INT, offsetof(PyHST, astra_scaling)}, |
41
by csa
Bug fixes |
1019 |
#ifdef PYHST_MEASURE_TIMINGS
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1020 |
{"recon_timer", T_DOUBLE, offsetof(PyHST, recon_timer)}, |
43
by csa
Option to disable preloading of image files, additional timers |
1021 |
{"comp_timer", T_DOUBLE, offsetof(PyHST, comp_timer)}, |
1022 |
{"io_timer", T_DOUBLE, offsetof(PyHST, io_timer)}, |
|
22
by csa
Timing reporting, few bug fixes |
1023 |
{"recon", T_OBJECT, offsetof(PyHST, recon_info)}, |
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1024 |
#endif /* PYHST_MEASURE_TIMINGS */ |
1025 |
{ NULL } |
|
1026 |
};
|
|
1027 |
||
1028 |
static PyMethodDef PyHST_functions[] = { |
|
1029 |
{"PyHST", PyHST_new, METH_VARARGS, PyHST_new_doc }, |
|
1030 |
{ NULL, NULL} |
|
1031 |
};
|
|
1032 |
||
1033 |
||
1034 |
||
1035 |
static PyObject * |
|
1036 |
PyHST_getattr(PyHST *self, char *attr) |
|
1037 |
{
|
|
1038 |
PyObject *res; |
|
1039 |
||
1040 |
res= Py_FindMethod(PyHST_methods, (PyObject*) self, attr); |
|
1041 |
if(NULL !=res) |
|
1042 |
return res; |
|
1043 |
else { |
|
1044 |
PyErr_Clear(); |
|
1045 |
return PyMember_Get((char*) self,PyHST_memberlist, attr); |
|
1046 |
}
|
|
1047 |
}
|
|
1048 |
||
1049 |
||
1050 |
||
22
by csa
Timing reporting, few bug fixes |
1051 |
static PyObject *logger = NULL; |
1052 |
||
20
by csa
do more correct initialization |
1053 |
void finiPyHST_c(void) |
1054 |
{
|
|
1055 |
hst_free(); |
|
22
by csa
Timing reporting, few bug fixes |
1056 |
if (logger) { |
1057 |
pyhst_configure_logger(0, (GLogFunc)NULL, NULL); |
|
1058 |
Py_DECREF(logger); |
|
1059 |
}
|
|
20
by csa
do more correct initialization |
1060 |
}
|
1061 |
||
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1062 |
void initPyHST_c(void) |
1063 |
{
|
|
22
by csa
Timing reporting, few bug fixes |
1064 |
PyObject *logger_mod; |
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1065 |
PyObject *m, *d; |
142
by Suren A. Chilingaryan
Adjust number of slices per block to number of reconstructors |
1066 |
size_t n_rec; |
22
by csa
Timing reporting, few bug fixes |
1067 |
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1068 |
m = Py_InitModule("PyHST_c", PyHST_functions); |
1069 |
d = PyModule_GetDict(m); |
|
1070 |
ErrorObject = Py_BuildValue("s","PyHST_c.error"); |
|
1071 |
PyDict_SetItemString(d,"error", ErrorObject); |
|
1072 |
if(PyErr_Occurred()) |
|
1073 |
Py_FatalError("can't initialize module PyHST_c"); |
|
20
by csa
do more correct initialization |
1074 |
else { |
22
by csa
Timing reporting, few bug fixes |
1075 |
logger_mod = PyImport_ImportModule("logger"); |
1076 |
if (logger_mod) { |
|
1077 |
logger = PyObject_GetAttrString(logger_mod, "logger"); |
|
1078 |
Py_DECREF(logger_mod); |
|
1079 |
if (logger) { |
|
1080 |
pyhst_configure_logger(0, (GLogFunc)PyHST_log_handler, logger); |
|
1081 |
}
|
|
1082 |
}
|
|
1083 |
||
20
by csa
do more correct initialization |
1084 |
hst_init(); |
142
by Suren A. Chilingaryan
Adjust number of slices per block to number of reconstructors |
1085 |
n_rec = hst_get_balanced_number_of_reconstructors(); |
1086 |
PyModule_AddIntConstant(m, "RECONSTRUCTORS", n_rec); |
|
1087 |
||
20
by csa
do more correct initialization |
1088 |
Py_AtExit(finiPyHST_c); |
1089 |
}
|
|
11
by csa
Eextensive pointer usage is reduced and c_hst_recon is beutificated with astyle |
1090 |
#ifdef import_array
|
1091 |
import_array(); |
|
1092 |
#endif
|
|
1093 |
}
|
|
1094 |
||
1095 |
||
1096 |
||
1097 |
static PyTypeObject PyHSTtype = { |
|
1098 |
PyObject_HEAD_INIT(&PyType_Type) |
|
1099 |
0, |
|
1100 |
"PyHST", |
|
1101 |
sizeof(PyHST), |
|
1102 |
0, |
|
1103 |
(destructor) PyHST_dealloc, |
|
1104 |
0, |
|
1105 |
(getattrfunc) PyHST_getattr, |
|
1106 |
};
|
|
1107 |