Source code for neutompy.postproc.convert

import numpy as np
import numexpr as ne
import logging

__author__  = "Davide Micieli"
__all__     = ['convert_to_uint']


logs = logging.getLogger(__name__)

[docs]def convert_to_uint(arr, nbit=16, down=None, up=None, crop_roi=None): """ This function converts a floating point array to 8 or 16 bit unsigned integer array. The resampling can be performed in a user-specified dynamic range. The array can be also cropped by specifying the ROI coordinates. Parameters ---------- arr : ndarray The floating point array to convert to unsigned integer array. nbit : int The number of bits of the returned array. In must be `8` or `16`, for 8-bit or 16-bit unsigned integer, respectively. Default value is `16`. down: float, optional The lower range limit. If `None`, the lower limit is computed as the minimum value of the input array. up: float, optional The upper range limit. If `None`, the upper limit is computed as the maximum value of the input array. crop_roi: tuple, optional Tuple defining the ROI of the array to crop. E.g. for a 3D stack (smin, smax, rmin, rmax, cmin, cmax), while for a 2D image (rmin, rmax, cmin, cmax). Default value is `None`, which disables the crop of the ROI. Returns ------- m : ndarray The array resampled to 8-bit or 16-bit unsigned integer. """ if(arr.ndim != 3 and arr.ndim != 2): raise ValueError('The input array must have 2 or 3 dimensions.') # check number of bits if(nbit == 8): tp = np.uint8 elif(nbit == 16): tp = np.uint16 else: raise ValueError('The output array type must be 8 bit or 16 bit unsigned integer.') if(crop_roi): old_shape = arr.shape if(arr.ndim == 3): smin, smax, rmin, rmax, cmin, cmax = crop_roi arr = arr[smin:smax, rmin:rmax, cmin:cmax].astype(np.float32) if(arr.ndim == 2): rmin, rmax, cmin, cmax = crop_roi arr = arr[rmin:rmax, cmin:cmax].astype(np.float32) logs.debug('Array cropped: original shape = %s, cropped array shape = %s', old_shape, arr.shape) arr = arr.astype(np.float32) if(down == None): down = arr.min() if(up == None): up = arr.max() down = down.astype(np.float32) up = up.astype(np.float32) factor = np.float32(2.0**nbit - 1.0) arr = np.clip(arr, a_min=down, a_max=up, out=arr) arr = ne.evaluate('factor*(arr - down)/(up - down)', out=arr, truediv=True) logs.info('Array converted to %s using the dynamic range %s - %s', tp, down, up) return (np.round(arr)).astype(dtype=tp)