<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def call_backward(self, proj_data, out=None):
 """Run an ASTRA back-projection on the given data using the GPU. Parameters proj_data : ``proj_space`` element Projection data to which the back-projector is applied. out : ``reco_space`` element, optional Element of the reconstruction space to which the result is written. If ``None``, an element in ``reco_space`` is created. Returns ------- out : ``reco_space`` element Reconstruction data resulting from the application of the back-projector. If ``out`` was provided, the returned object is a reference to it. """

        with self._mutex:
            assert proj_data in self.proj_space
            if out is not None:
                assert out in self.reco_space
            else:
                out = self.reco_space.element()

            # Copy data to GPU memory
            if self.geometry.ndim == 2:
                astra.data2d.store(self.sino_id, proj_data.asarray())
            elif self.geometry.ndim == 3:
                shape = (-1,) + self.geometry.det_partition.shape
                reshaped_proj_data = proj_data.asarray().reshape(shape)
                swapped_proj_data = np.ascontiguousarray(
                    np.swapaxes(reshaped_proj_data, 0, 1))
                astra.data3d.store(self.sino_id, swapped_proj_data)

            # Run algorithm
            astra.algorithm.run(self.algo_id)

            # Copy result to CPU memory
            out[:] = self.out_array

            # Fix scaling to weight by pixel/voxel size
            out *= astra_cuda_bp_scaling_factor(
                self.proj_space, self.reco_space, self.geometry)

            return out