def setDummyValue(self, dummy, delta_dummy): """ Enables dummy value functionality and uploads the value to the OpenCL device. Image values that are similar to the dummy value are set to 0. @param dummy: value in image of missing values (masked pixels?) @param delta_dummy: precision for dummy values """ if not self._ctx: raise RuntimeError("You may not call" " Integrator1d.setDummyValue(dummy,delta_dummy)" " at this point. There is no Active context." " (Hint: run init())") else: with self.lock: self.do_dummy = True pyopencl.enqueue_copy(self._queue, self._cl_mem["dummyval"], numpy.array((dummy,), dtype=numpy.float32)) pyopencl.enqueue_copy(self._queue, self._cl_mem["dummyval_delta"], numpy.array((delta_dummy,), dtype=numpy.float32))
def loadTth(self, tth, dtth, tth_min=None, tth_max=None): """ Load the 2th arrays along with the min and max value. loadTth maybe be recalled at any time of the execution in order to update the 2th arrays. loadTth is required and must be called at least once after a configure() """ if not self._ctx: raise RuntimeError("You may not call loadTth() at this point." " There is no Active context." " (Hint: run init())") if not self._cl_mem["tth"]: raise RuntimeError("You may not call loadTth() at this point," " OpenCL is not configured" " (Hint: run configure())") ctth = numpy.ascontiguousarray(tth.ravel(), dtype=numpy.float32) cdtth = numpy.ascontiguousarray(dtth.ravel(), dtype=numpy.float32) with self.lock: self._tth_max = (ctth + cdtth).max() * \ (1.0 + numpy.finfo(numpy.float32).eps) self._tth_min = max(0.0, (ctth - cdtth).min()) if tth_min is None: tth_min = self._tth_min if tth_max is None: tth_max = self._tth_max copy_tth = pyopencl.enqueue_copy(self._queue, self._cl_mem["tth"], ctth) copy_dtth = pyopencl.enqueue_copy(self._queue, self._cl_mem["tth_delta"], cdtth) pyopencl.enqueue_copy(self._queue, self._cl_mem["tth_min_max"], numpy.array((self._tth_min, self._tth_max), dtype=numpy.float32)) logger.debug("kernel get_spans sizes: \t%s %s", self.wdim_data, self.tdim) get_spans = \ self._cl_program.get_spans(self._queue, self.wdim_data, self.tdim, *self._cl_kernel_args["get_spans"]) # Group 2th span ranges group_spans(__global float *span_range) logger.debug("kernel group_spans sizes: \t%s %s", self.wdim_data, self.tdim) group_spans = \ self._cl_program.group_spans(self._queue, self.wdim_data, self.tdim, self._cl_mem["span_ranges"]) self._calc_tth_out(tth_min, tth_max) if self.logfile: self.log(copy_2th=copy_tth, copy_delta2th=copy_dtth, get_spans=get_spans, group_spans=group_spans)
def setSolidAngle(self, solidAngle): """ Enables SolidAngle correction and uploads the suitable array to the OpenCL device. By default the program will assume no solidangle correction unless setSolidAngle() is called. From then on, all integrations will be corrected via the SolidAngle array. If the SolidAngle array needs to be changes, one may just call setSolidAngle() again with that array @param solidAngle: the solid angle of the given pixel @type solidAngle: ndarray """ if not self._ctx: raise RuntimeError("You may not call Integrator1d.setSolidAngle()" " at this point. There is no Active context." " (Hint: run init())") cSolidANgle = numpy.ascontiguousarray(solidAngle.ravel(), dtype=numpy.float32) with self.lock: self.do_solidangle = True copy_solidangle = pyopencl.enqueue_copy(self._queue, self._cl_mem["solidangle"], cSolidANgle) if self.logfile: self.log(copy_solidangle=copy_solidangle)
def setRange(self, lowerBound, upperBound): """ Instructs the program to use a user - defined range for 2th values setRange is optional. By default the integration will use the tth_min and tth_max given by loadTth() as integration range. When setRange is called it sets a new integration range without affecting the 2th array. All values outside that range will then be discarded when interpolating. Currently, if the interval of 2th (2th + -d2th) is not all inside the range specified, it is discarded. The bins of the histogram are RESCALED to the defined range and not the original tth_max - tth_min range. setRange can be called at any point and as many times required after a valid configuration is created. @param lowerBound: lower bound of the integration range @type lowerBound: float @param upperBound: upper bound of the integration range @type upperBound: float """ if self._ctx is None: raise RuntimeError("You may not call setRange() at this point." " There is no Active context." " (Hint: run init())") if not (self.nData > 1 and self._cl_mem["tth_range"]): raise RuntimeError("You may not call setRange() at this point," " the required buffers are not allocated" " (Hint: run config())") with self.lock: self.useTthRange = True copy_2thrange = \ pyopencl.enqueue_copy(self._queue, self._cl_mem["tth_range"], numpy.array((lowerBound, upperBound), dtype=numpy.float32)) self._cl_kernel_args["create_histo_binarray"][8] = \ self._cl_mem["tth_range"] self._cl_kernel_args["get_spans"][2] = self._cl_mem["tth_range"] if self.logfile: self.log(copy_2thrange=copy_2thrange)
def setMask(self, mask): """ Enables the use of a Mask during integration. The Mask can be updated by recalling setMask at any point. The Mask must be a PyFAI Mask. Pixels with 0 are masked out. TODO: check and invert! @param mask: numpy.ndarray of integer. """ if not self._ctx: raise RuntimeError("You may not call" " Integrator1d.setDummyValue(dummy,delta_dummy)" " at this point. There is no Active context." " (Hint: run init())") cMask = numpy.ascontiguousarray(mask.ravel(), dtype=numpy.int32) with self.lock: self.do_mask = True copy_mask = pyopencl.enqueue_copy(self._queue, self._cl_mem["mask"], cMask) if self.logfile: self.log(copy_mask=copy_mask)
def execute(self, image): """ Perform a 1D azimuthal integration execute() may be called only after an OpenCL device is configured and a Tth array has been loaded (at least once) It takes the input image and based on the configuration provided earlier it performs the 1D integration. Notice that if the provided image is bigger than N then only N points will be taked into account, while if the image is smaller than N the result may be catastrophic. set/unset and loadTth methods have a direct impact on the execute() method. All the rest of the methods will require at least a new configuration via configure(). Takes an image, integrate and return the histogram and weights @param image: image to be processed as a numpy array @return: tth_out, histogram, bins TODO: to improve performances, the image should be casted to float32 in an optimal way: currently using numpy machinery but would be better if done in OpenCL """ assert image.size == self.nData if not self._ctx: raise RuntimeError("You may not call execute() at this point." " There is no Active context." " (Hint: run init())") if not self._cl_mem["histogram"]: raise RuntimeError("You may not call execute() at this point," " kernels are not configured" " (Hint: run configure())") if not self._tth_max: raise RuntimeError("You may not call execute() at this point." " There is no 2th array loaded." " (Hint: run loadTth())") with self.lock: copy_img = pyopencl.enqueue_copy( self._queue, self._cl_mem["image"], numpy.ascontiguousarray(image.ravel(), dtype=numpy.float32)) logger.debug("kernel uimemset2 sizes: \t%s %s", self.wdim_bins, self.tdim) memset = \ self._cl_program.uimemset2(self._queue, self.wdim_bins, self.tdim, *self._cl_kernel_args["uimemset2"]) if self.do_dummy: logger.debug("kernel dummyval_correction sizes: \t%s %s", self.wdim_data, self.tdim) dummy = self._cl_program.dummyval_correction( self._queue, self.wdim_data, self.tdim, self._cl_kernel_args["dummyval_correction"]) if self.do_solidangle: sa = self._cl_program.solidangle_correction( self._queue, self.wdim_data, self.tdim, *self._cl_kernel_args["solidangle_correction"]) logger.debug("kernel create_histo_binarray sizes: \t%s %s", self.wdim_data, self.tdim) integrate = self._cl_program.create_histo_binarray( self._queue, self.wdim_data, self.tdim, *self._cl_kernel_args["create_histo_binarray"]) #convert to float convert = self._cl_program.ui2f2(self._queue, self.wdim_data, self.tdim, *self._cl_kernel_args["ui2f2"]) histogram = numpy.empty(self.nBins, dtype=numpy.float32) bins = numpy.empty(self.nBins, dtype=numpy.float32) copy_hist = pyopencl.enqueue_copy(self._queue, histogram, self._cl_mem["histogram"]) copy_bins = pyopencl.enqueue_copy(self._queue, bins, self._cl_mem["weights"]) if self.logfile: self.log(copy_in=copy_img, memset2=memset) if self.do_dummy: self.log(dummy_corr=dummy) if self.do_solidangle: self.log(solid_angle=sa) self.log(integrate=integrate, convert_uint2float=convert, copy_hist=copy_hist, copy_bins=copy_bins) pyopencl.enqueue_barrier(self._queue).wait() return self.tth_out, histogram, bins