Example #1
0
class ProjectionSimulator(object):
    """
    Simple class to simulate parallel-beam x-ray projections of a phantom. 
    Since the projections are usually obtained from a phantom, it's preferred
    (for convenience) to match the number of bins to the pixel size of the
    phantom. Otherwise, the phantom needs to be resized before being projected.
    If the reconstruction is performed using a binary system matrix, that
    matrix can be evaluated during the projection. 
    """
    def __init__(self, views, nrBins, phantom=None, start=0, stop=180):
        self.__phantom = phantom 
        self.__nrBins = nrBins
        self._views = views
        self._start = start 
        self._stop = stop
        self._angleInc = (stop-start)/float(views)
        self.__projections = None

    @property 
    def loadSize(self):
        return self._views

    @property 
    def phantom(self):
        return self.__phantom 

    @property 
    def projections(self):
        return self.__projections

    @property 
    def views(self):
        return self._views 

    def initProjections(self):
        """ Initialize the projections object. """
        self.__projections = Projections(self._views, self.__nrBins)

    def projectAll(self, start=0, stop=180):
        """ 
        Simulate a parallel-beam x-ray projection by summing up the phantom
        data matrix column wise, yielding a sinogram line. 
        To this end, the number of bins (that the phantom is projected onto)
        and the phantom pixel size should be equal. Otherwise, the phantom
        needs to be reshaped.
        """
        if self.readyForProjecting():
            for a in range(0, self._views):
                if a%25==0:
                    print "Projecting view " + str(a)
                self.computeOne(a)

    def computeOne(self, view):
        """
        Helper function. Performs a single projection.
        Required in ProjectionSimulatorHandler.process() to signal progress
        after a single projection. 

        :param      view | int 
        """
        rotPhantom = self.phantom.rotate(self._start - view*self._angleInc)
        self.__projections.project(view, rotPhantom)

    def ready(self):
        """
        Convenience method for checking prerequisites for projecting.

        :return     isReady | bool 
        """
        if self.phantom is None or self.projections is None: 
            return False
        if self.__nrBins != self.phantom.size:
            pass #TODO resize phantom
        return True