diff --git a/pyramid/config.py b/pyramid/config.py
index 9f45e1f5537f2f5506271c1d5e1ac2f523660e79..c0d9db4e80c7588aab76783d1c2cf55d13bd76e7 100644
--- a/pyramid/config.py
+++ b/pyramid/config.py
@@ -8,11 +8,11 @@ Created on Fri Feb 20 10:59:42 2015
 import os
 
 
-__all__ = ['DIR_PACKAGE', 'DIR_MAGDATA', 'DIR_PHASEMAP']
+__all__ = ['DIR_PACKAGE', 'DIR_FILES', 'LOGGING_CONFIG']
 
 
 DIR_PACKAGE = os.path.join(os.path.dirname(os.path.realpath(__file__)))
-DIR_MAGDATA = os.path.abspath(os.path.join(DIR_PACKAGE, os.pardir, 'files', 'magdata'))
-DIR_PHASEMAP = os.path.abspath(os.path.join(DIR_PACKAGE, os.pardir, 'files', 'phasemap'))
+DIR_FILES = os.path.abspath(os.path.join(DIR_PACKAGE, os.pardir, 'files'))
+LOGGING_CONFIG = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'logging.ini')
 
 del os
diff --git a/pyramid/costfunction.py b/pyramid/costfunction.py
index d7eae39f3a6644b8c301c41afabe062596f4c239..7b3945a2ebccf7e67262be301895aef160219276 100644
--- a/pyramid/costfunction.py
+++ b/pyramid/costfunction.py
@@ -64,10 +64,9 @@ class Costfunction(object):
         self.y = data_set.phase_vec
         self.n = data_set.n
         self.m = data_set.m
-        if data_set.Se_inv is not None:
-            self.Se_inv = data_set.Se_inv
-        else:
-            self.Se_inv = sparse_eye(self.m)
+        if data_set.Se_inv is None:
+            data_set.set_Se_inv_diag_with_conf()
+        self.Se_inv = data_set.Se_inv
         self._log.debug('Created '+str(self))
 
     def __repr__(self):
diff --git a/pyramid/dataset.py b/pyramid/dataset.py
index ca322250a310d23b7b55773cee41d342cc54d715..f493b056fd32a7a1a642416422c9cb66201fc001 100644
--- a/pyramid/dataset.py
+++ b/pyramid/dataset.py
@@ -64,10 +64,36 @@ class DataSet(object):
 
     _log = logging.getLogger(__name__+'.DataSet')
 
+    @property
+    def a(self):
+        return self._a
+
+    @a.setter
+    def a(self, a):
+        assert isinstance(a, Number), 'Grid spacing has to be a number!'
+        assert a >= 0, 'Grid spacing has to be a positive number!'
+        self._a = float(a)
+
+    @property
+    def mask(self):
+        return self._mask
+
+    @mask.setter
+    def mask(self, mask):
+        if mask is not None:
+            assert mask.shape == self.dim, 'Mask dimensions must match!'
+        else:
+            mask = np.ones(self.dim, dtype=bool)
+        self._mask = mask.astype(np.bool)
+
     @property
     def m(self):
         return np.sum([len(p.phase_vec) for p in self.phase_maps])
 
+    @property
+    def n(self):
+        return 3 * np.sum(self.mask)
+
     @property
     def phase_vec(self):
         return np.concatenate([p.phase_vec for p in self.phase_maps])
@@ -87,19 +113,12 @@ class DataSet(object):
 
     def __init__(self, a, dim, b_0=1, mask=None, Se_inv=None):
         self._log.debug('Calling __init__')
-        assert isinstance(a, Number), 'Grid spacing has to be a number!'
-        assert a >= 0, 'Grid spacing has to be a positive number!'
         assert isinstance(dim, tuple) and len(dim) == 3, \
             'Dimension has to be a tuple of length 3!'
-        if mask is None:
-            self.mask = np.ones(dim, dtype=bool)
-        else:
-            assert mask.shape == dim, 'Mask dimensions must match!'
-            self.mask = mask
-        self.n = 3 * np.sum(self.mask)
         self.a = a
         self.dim = dim
         self.b_0 = b_0
+        self.mask = mask
         self.Se_inv = Se_inv
         self.phase_maps = []
         self.projectors = []
@@ -167,27 +186,50 @@ class DataSet(object):
             None
 
         '''
+        assert len(cov_list) == len(self.phase_maps), 'Needs one covariance matrix per phase map!'
         self.Se_inv = sparse.block_diag(cov_list).tocsr()
 
-    def set_Se_inv_diag_with_masks(self, mask_list):
-        '''Set the Se_inv matrix as a block diagonal matrix from a list of masks
+    def set_Se_inv_diag_with_conf(self, conf_list=None):
+        '''Set the Se_inv matrix as a block diagonal matrix from a list of confidence matrizes.
 
         Parameters
         ----------
-        mask_list: list of :class:`~numpy.ndarray`
-            List of 2D masks (one for each projection) which define trust regions.
+        conf_list: list of :class:`~numpy.ndarray` (optional)
+            List of 2D confidence matrizes (one for each projection) which define trust regions.
+            If not given this uses the confidence matrizes of the phase maps.
 
         Returns
         -------
             None
 
         '''
-        cov_list = [sparse.diags(m.flatten().astype(np.float32), 0) for m in mask_list]
+        if conf_list is None:  # if no confidence matrizes are given, extract from the phase maps!
+            conf_list = [phase_map.confidence for phase_map in self.phase_maps]
+        cov_list = [sparse.diags(c.flatten().astype(np.float32), 0) for c in conf_list]
         self.set_Se_inv_block_diag(cov_list)
 
-    def create_3d_mask(self, mask_list):
-        # TODO: method for constructing 3D mask from 2D masks?
-        raise NotImplementedError()
+    def set_3d_mask(self, mask_list=None):
+        '''Set the 3D mask from a list of 2D masks.
+
+        Parameters
+        ----------
+        mask_list: list of :class:`~numpy.ndarray` (optional)
+            List of 2D masks, which represent the projections of the 3D mask. If not given this
+            uses the confidence matrizes of the phase maps. If just one phase map is present, the
+            according mask is simply expanded to 3D and used directly.
+
+        Returns
+        -------
+            None
+
+        '''
+        if mask_list is None:  # if no masks are given, extract from phase maps:
+            mask_list = [phase_map.mask for phase_map in self.phase_maps]
+        if len(mask_list) == 1:  # just one phase_map --> 3D mask equals 2D mask
+            self.mask = np.expand_dims(mask_list[0], axis=0)
+        else:  # 3D mask has to be constructed from 2D masks:
+            # TODO: method for constructing 3D mask from 2D masks? if no list use phase_map masks!
+            raise NotImplementedError()
 
     def display_phase(self, mag_data=None, title='Phase Map',
                       cmap='RdBu', limit=None, norm=None):
diff --git a/pyramid/magdata.py b/pyramid/magdata.py
index 936e4e580af9bbbab6e26c1bdcaf4342ae2fcaa1..f2f9fb41f15a0d0946172115d8b8cb4b53bb9ee1 100644
--- a/pyramid/magdata.py
+++ b/pyramid/magdata.py
@@ -331,6 +331,69 @@ class MagData(object):
         else:
             self.mag_vec = vector
 
+    def flip(self, axis='x'):
+        '''Flip/mirror the magnetization around the specified axis.
+
+        Parameters
+        ----------
+        axis: {'x', 'y', 'z'}, optional
+            The axis around which the magnetization is flipped.
+
+        Returns
+        -------
+        mag_data_flip: :class:`~.MagData`
+           A flipped copy of the :class:`~.MagData` object.
+
+        '''
+        if axis == 'x':
+            mag_x, mag_y, mag_z = self.magnitude[:, :, :, ::-1]
+            magnitude_flip = np.array((-mag_x, mag_y, mag_z))
+        elif axis == 'y':
+            mag_x, mag_y, mag_z = self.magnitude[:, :, ::-1, :]
+            magnitude_flip = np.array((mag_x, -mag_y, mag_z))
+        elif axis == 'z':
+            mag_x, mag_y, mag_z = self.magnitude[:, ::-1, :, :]
+            magnitude_flip = np.array((mag_x, mag_y, -mag_z))
+        else:
+            raise ValueError("Wrong input! 'x', 'y', 'z' allowed!")
+        return MagData(self.a, magnitude_flip)
+
+    def rot90(self, axis='x'):
+        '''Rotate the magnetization 90° around the specified axis (right hand rotation).
+
+        Parameters
+        ----------
+        axis: {'x', 'y', 'z'}, optional
+            The axis around which the magnetization is rotated.
+
+        Returns
+        -------
+        mag_data_rot: :class:`~.MagData`
+           A rotated copy of the :class:`~.MagData` object.
+
+        '''
+        if axis == 'x':
+            magnitude_rot = np.zeros((3, self.dim[1], self.dim[0], self.dim[2]))
+            for i in range(self.dim[2]):
+                mag_x, mag_y, mag_z = self.magnitude[:, :, :, i]
+                mag_xrot, mag_yrot, mag_zrot = np.rot90(mag_x), np.rot90(mag_y), np.rot90(mag_z)
+                magnitude_rot[:, :, :, i] = np.array((mag_xrot, mag_zrot, -mag_yrot))
+        elif axis == 'y':
+            magnitude_rot = np.zeros((3, self.dim[2], self.dim[1], self.dim[0]))
+            for i in range(self.dim[1]):
+                mag_x, mag_y, mag_z = self.magnitude[:, :, i, :]
+                mag_xrot, mag_yrot, mag_zrot = np.rot90(mag_x), np.rot90(mag_y), np.rot90(mag_z)
+                magnitude_rot[:, :, i, :] = np.array((mag_zrot, mag_yrot, -mag_xrot))
+        elif axis == 'z':
+            magnitude_rot = np.zeros((3, self.dim[0], self.dim[2], self.dim[1]))
+            for i in range(self.dim[0]):
+                mag_x, mag_y, mag_z = self.magnitude[:, i, :, :]
+                mag_xrot, mag_yrot, mag_zrot = np.rot90(mag_x), np.rot90(mag_y), np.rot90(mag_z)
+                magnitude_rot[:, i, :, :] = np.array((mag_yrot, -mag_xrot, mag_zrot))
+        else:
+            raise ValueError("Wrong input! 'x', 'y', 'z' allowed!")
+        return MagData(self.a, magnitude_rot)
+
     def save_to_llg(self, filename='magdata.txt'):
         '''Save magnetization data in a file with LLG-format.
 
@@ -353,10 +416,11 @@ class MagData(object):
         data = np.array([xx, yy, zz, x_vec, y_vec, z_vec]).T
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_MAGDATA
-            if not os.path.exists(DIR_MAGDATA):
-                os.makedirs(DIR_MAGDATA)
-            filename = os.path.join(DIR_MAGDATA, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'magdata')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Save data to file:
         with open(filename, 'w') as mag_file:
             mag_file.write('LLGFileCreator: %s\n' % filename)
@@ -383,10 +447,11 @@ class MagData(object):
         SCALE = 1.0E-9 / 1.0E-2  # From cm to nm
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_MAGDATA
-            if not os.path.exists(DIR_MAGDATA):
-                os.makedirs(DIR_MAGDATA)
-            filename = os.path.join(DIR_MAGDATA, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'magdata')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Load data from file:
         data = np.genfromtxt(filename, skip_header=2)
         dim = tuple(np.genfromtxt(filename, dtype=int, skip_header=1, skip_footer=len(data[:, 0])))
@@ -411,10 +476,11 @@ class MagData(object):
         self._log.debug('Calling save_to_netcdf4')
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_MAGDATA
-            if not os.path.exists(DIR_MAGDATA):
-                os.makedirs(DIR_MAGDATA)
-            filename = os.path.join(DIR_MAGDATA, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'magdata')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Save data to file:
         mag_file = netCDF4.Dataset(filename, 'w', format='NETCDF4')
         mag_file.a = self.a
@@ -444,10 +510,11 @@ class MagData(object):
         cls._log.debug('Calling load_from_netcdf4')
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_MAGDATA
-            if not os.path.exists(DIR_MAGDATA):
-                os.makedirs(DIR_MAGDATA)
-            filename = os.path.join(DIR_MAGDATA, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'magdata')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Load data from file:
         mag_file = netCDF4.Dataset(filename, 'r', format='NETCDF4')
         a = mag_file.a
@@ -511,10 +578,11 @@ class MagData(object):
                                  value='{} {} {}'.format(*spin_scale))
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_MAGDATA
-            if not os.path.exists(DIR_MAGDATA):
-                os.makedirs(DIR_MAGDATA)
-            filename = os.path.join(DIR_MAGDATA, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'x3d')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Write the tree into the file in pretty print format:
         tree.write(filename, pretty_print=True)
 
@@ -650,7 +718,10 @@ class MagData(object):
             limit = np.max(self.mag_amp)
         ad = ar_dens
         # Create points and vector components as lists:
-        zz, yy, xx = (np.indices(dim)-a/2).reshape(3, -1)
+        zz, yy, xx = (np.indices(dim)-a/2).reshape((3,)+dim)
+        zz = zz[::ad, ::ad, ::ad].flatten()
+        yy = yy[::ad, ::ad, ::ad].flatten()
+        xx = xx[::ad, ::ad, ::ad].flatten()
         x_mag = self.magnitude[0][::ad, ::ad, ::ad].flatten()
         y_mag = self.magnitude[1][::ad, ::ad, ::ad].flatten()
         z_mag = self.magnitude[2][::ad, ::ad, ::ad].flatten()
diff --git a/pyramid/phasemap.py b/pyramid/phasemap.py
index 047c2758cbd75a71e7f3b2c9474436979a9cb72a..9dddb7254ea1255b8f22d650f58fc69e1df84dc9 100644
--- a/pyramid/phasemap.py
+++ b/pyramid/phasemap.py
@@ -9,6 +9,7 @@ import os
 
 import numpy as np
 from numpy import pi
+from scipy.ndimage.interpolation import zoom
 
 import matplotlib as mpl
 import matplotlib.pyplot as plt
@@ -52,6 +53,13 @@ class PhaseMap(object):
         Matrix containing the phase shift.
     phase_vec: :class:`~numpy.ndarray` (N=2)
         Vector containing the phase shift.
+    mask: :class:`~numpy.ndarray` (boolean, N=2, optional)
+        Mask which determines the projected magnetization distribution, gotten from MIP images or
+        otherwise acquired. Defaults to an array of ones (all pixels are considered).
+    confidence: :class:`~numpy.ndarray` (N=2, optional)
+        Confidence array which determines the trust of specific regions of the phase_map. A value
+        of 1 means the pixel is trustworthy, a value of 0 means it is not. Defaults to an array of
+        ones (full trust for all pixels). Can be used for the construction of Se_inv.
     unit: {'rad', 'mrad'}, optional
         Set the unit of the phase map. This is important for the :func:`display` function,
         because the phase is scaled accordingly. Does not change the phase itself, which is
@@ -126,7 +134,7 @@ class PhaseMap(object):
     def phase(self, phase):
         assert isinstance(phase, np.ndarray), 'Phase has to be a numpy array!'
         assert len(phase.shape) == 2, 'Phase has to be 2-dimensional!'
-        self._phase = np.asarray(phase, dtype=np.float32)
+        self._phase = phase.astype(dtype=np.float32)
         self._dim_uv = phase.shape
 
     @property
@@ -139,6 +147,31 @@ class PhaseMap(object):
         assert np.size(phase_vec) == np.prod(self.dim_uv), 'Vector size has to match phase!'
         self.phase = phase_vec.reshape(self.dim_uv)
 
+    @property
+    def mask(self):
+        return self._mask
+
+    @mask.setter
+    def mask(self, mask):
+        if mask is not None:
+            assert mask.shape == self.phase.shape, 'Mask and phase dimensions must match!!'
+        else:
+            mask = np.ones_like(self.phase, dtype=bool)
+        self._mask = mask.astype(np.bool)
+
+    @property
+    def confidence(self):
+        return self._confidence
+
+    @confidence.setter
+    def confidence(self, confidence):
+        if confidence is not None:
+            assert confidence.shape == self.phase.shape, \
+                'Confidence and phase dimensions must match!'
+        else:
+            confidence = np.ones_like(self.phase)
+        self._confidence = confidence.astype(dtype=np.float32)
+
     @property
     def unit(self):
         return self._unit
@@ -148,25 +181,27 @@ class PhaseMap(object):
         assert unit in self.UNITDICT, 'Unit not supported!'
         self._unit = unit
 
-    def __init__(self, a, phase, unit='rad'):
+    def __init__(self, a, phase, mask=None, confidence=None, unit='rad'):
         self._log.debug('Calling __init__')
         self.a = a
         self.phase = phase
+        self.mask = mask
+        self.confidence = confidence
         self.unit = unit
         self._log.debug('Created '+str(self))
 
     def __repr__(self):
         self._log.debug('Calling __repr__')
-        return '%s(a=%r, phase=%r, unit=%r)' % \
-            (self.__class__, self.a, self.phase, self.unit)
+        return '%s(a=%r, phase=%r, mask=%r, confidence=%r, unit=%r)' % \
+            (self.__class__, self.a, self.phase, self.mask, self.confidence, self.unit)
 
     def __str__(self):
         self._log.debug('Calling __str__')
-        return 'PhaseMap(a=%s, dim_uv=%s)' % (self.a, self.dim_uv)
+        return 'PhaseMap(a=%s, dim_uv=%s, mask=%s)' % (self.a, self.dim_uv, not np.all(self.mask))
 
     def __neg__(self):  # -self
         self._log.debug('Calling __neg__')
-        return PhaseMap(self.a, -self.phase, self.unit)
+        return PhaseMap(self.a, -self.phase, self.mask, self.confidence, self.unit)
 
     def __add__(self, other):  # self + other
         self._log.debug('Calling __add__')
@@ -177,10 +212,11 @@ class PhaseMap(object):
             assert other.a == self.a, 'Added phase has to have the same grid spacing!'
             assert other.phase.shape == self.dim_uv, \
                 'Added magnitude has to have the same dimensions!'
-            return PhaseMap(self.a, self.phase+other.phase, self.unit)
+            mask_comb = np.logical_or(self.mask, other.mask)  # masks combine, confidence resets!
+            return PhaseMap(self.a, self.phase+other.phase, mask_comb, None, self.unit)
         else:  # other is a Number
             self._log.debug('Adding an offset')
-            return PhaseMap(self.a, self.phase+other, self.unit)
+            return PhaseMap(self.a, self.phase+other, self.mask, self.confidence, self.unit)
 
     def __sub__(self, other):  # self - other
         self._log.debug('Calling __sub__')
@@ -191,7 +227,7 @@ class PhaseMap(object):
         assert (isinstance(other, Number)
                 or (isinstance(other, np.ndarray) and other.shape == self.dim_uv)), \
             'PhaseMap objects can only be multiplied by scalar numbers or fitting arrays!'
-        return PhaseMap(self.a, other*self.phase, self.unit)
+        return PhaseMap(self.a, other*self.phase, self.mask, self.confidence, self.unit)
 
     def __radd__(self, other):  # other + self
         self._log.debug('Calling __radd__')
@@ -217,6 +253,86 @@ class PhaseMap(object):
         self._log.debug('Calling __imul__')
         return self.__mul__(other)
 
+    def copy(self):
+        '''Returns a copy of the :class:`~.PhaseMap` object
+
+        Parameters
+        ----------
+        None
+
+        Returns
+        -------
+        phase_map: :class:`~.PhaseMap`
+            A copy of the :class:`~.PhaseMap`.
+
+        '''
+        self._log.debug('Calling copy')
+        return PhaseMap(self.a, self.phase.copy(), self.mask.copy(),
+                        self.confidence.copy(), self.unit)
+
+    def scale_down(self, n=1):
+        '''Scale down the phase map by averaging over two pixels along each axis.
+
+        Parameters
+        ----------
+        n : int, optional
+            Number of times the phase map is scaled down. The default is 1.
+
+        Returns
+        -------
+        None
+
+        Notes
+        -----
+        Acts in place and changes dimensions and grid spacing accordingly.
+        Only possible, if each axis length is a power of 2!
+
+        '''
+        self._log.debug('Calling scale_down')
+        assert n > 0 and isinstance(n, (int, long)), 'n must be a positive integer!'
+        self.a = self.a * 2**n
+        for t in range(n):
+            # Pad if necessary:
+            pv, pu = self.dim_uv[0] % 2, self.dim_uv[1] % 2
+            if pv != 0 or pu != 0:
+                self.phase = np.pad(self.phase, ((0, pv), (0, pu)), mode='constant')
+            # Create coarser grid for the magnetization:
+            dim_uv = self.dim_uv
+            self.phase = self.phase.reshape(dim_uv[0]/2, 2, dim_uv[1]/2, 2).mean(axis=(3, 1))
+            mask = self.mask.reshape(dim_uv[0]/2, 2, dim_uv[1]/2, 2)
+            self.mask = mask[:, 0, :, 0] & mask[:, 1, :, 0] & mask[:, 0, :, 1] & mask[:, 1, :, 1]
+            self.confidence = self.confidence.reshape(dim_uv[0]/2, 2,
+                                                      dim_uv[1]/2, 2).mean(axis=(3, 1))
+
+    def scale_up(self, n=1, order=0):
+        '''Scale up the phase map using spline interpolation of the requested order.
+
+        Parameters
+        ----------
+        n : int, optional
+            Power of 2 with which the grid is scaled. Default is 1, which means every axis is
+            increased by a factor of ``2**1 = 2``.
+        order : int, optional
+            The order of the spline interpolation, which has to be in the range between 0 and 5
+            and defaults to 0.
+
+        Returns
+        -------
+        None
+
+        Notes
+        -----
+        Acts in place and changes dimensions and grid spacing accordingly.
+        '''
+        self._log.debug('Calling scale_up')
+        assert n > 0 and isinstance(n, (int, long)), 'n must be a positive integer!'
+        assert 5 > order >= 0 and isinstance(order, (int, long)), \
+            'order must be a positive integer between 0 and 5!'
+        self.a = self.a / 2**n
+        self.phase = zoom(self.phase, zoom=2**n, order=order)
+        self.mask = zoom(self.mask, zoom=2**n, order=0)
+        self.confidence = zoom(self.confidence, zoom=2**n, order=order)
+
     def save_to_txt(self, filename='phasemap.txt'):
         '''Save :class:`~.PhaseMap` data in a file with txt-format.
 
@@ -234,10 +350,11 @@ class PhaseMap(object):
         self._log.debug('Calling save_to_txt')
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_PHASEMAP
-            if not os.path.exists(DIR_PHASEMAP):
-                os.makedirs(DIR_PHASEMAP)
-            filename = os.path.join(DIR_PHASEMAP, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'phasemap')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Save data to file:
         with open(filename, 'w') as phase_file:
             phase_file.write('{}\n'.format(filename.replace('.txt', '')))
@@ -258,14 +375,20 @@ class PhaseMap(object):
         phase_map : :class:`~.PhaseMap`
             A :class:`~.PhaseMap` object containing the loaded data.
 
+        Notes
+        -----
+        Does not recover the mask, confidence or unit of the original phase map, which default to
+        `None`, `None` and `'rad'`, respectively.
+
         '''
         cls._log.debug('Calling load_from_txt')
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_PHASEMAP
-            if not os.path.exists(DIR_PHASEMAP):
-                os.makedirs(DIR_PHASEMAP)
-            filename = os.path.join(DIR_PHASEMAP, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'phasemap')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Load data from file:
         with open(filename, 'r') as phase_file:
             phase_file.readline()  # Headerline is not used
@@ -286,21 +409,30 @@ class PhaseMap(object):
         -------
         None
 
+        Notes
+        -----
+        Does not save the unit of the original phase map.
+
         '''
         self._log.debug('Calling save_to_netcdf4')
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_PHASEMAP
-            if not os.path.exists(DIR_PHASEMAP):
-                os.makedirs(DIR_PHASEMAP)
-            filename = os.path.join(DIR_PHASEMAP, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'phasemap')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Save data to file:
         phase_file = netCDF4.Dataset(filename, 'w', format='NETCDF4')
         phase_file.a = self.a
         phase_file.createDimension('v_dim', self.dim_uv[0])
         phase_file.createDimension('u_dim', self.dim_uv[1])
         phase = phase_file.createVariable('phase', 'f', ('v_dim', 'u_dim'))
+        mask = phase_file.createVariable('mask', 'b', ('v_dim', 'u_dim'))
+        confidence = phase_file.createVariable('confidence', 'f', ('v_dim', 'u_dim'))
         phase[:] = self.phase
+        mask[:] = self.mask
+        confidence[:] = self.confidence
         phase_file.close()
 
     @classmethod
@@ -317,23 +449,30 @@ class PhaseMap(object):
         phase_map: :class:`~.PhaseMap`
             A :class:`~.PhaseMap` object containing the loaded data.
 
+        Notes
+        -----
+        Does not recover the unit of the original phase map, defaults to `'rad'`.
+
         '''
         cls._log.debug('Calling load_from_netcdf4')
         # Construct path if filename isn't already absolute:
         if not os.path.isabs(filename):
-            from pyramid import DIR_PHASEMAP
-            if not os.path.exists(DIR_PHASEMAP):
-                os.makedirs(DIR_PHASEMAP)
-            filename = os.path.join(DIR_PHASEMAP, filename)
+            from pyramid import DIR_FILES
+            directory = os.path.join(DIR_FILES, 'phasemap')
+            if not os.path.exists(directory):
+                os.makedirs(directory)
+            filename = os.path.join(directory, filename)
         # Load data from file:
         phase_file = netCDF4.Dataset(filename, 'r', format='NETCDF4')
         a = phase_file.a
         phase = phase_file.variables['phase'][:]
+        mask = phase_file.variables['mask'][:]
+        confidence = phase_file.variables['confidence'][:]
         phase_file.close()
-        return PhaseMap(a, phase)
+        return PhaseMap(a, phase, mask, confidence)
 
     def display_phase(self, title='Phase Map', cmap='RdBu', limit=None,
-                      norm=None, axis=None, cbar=True):
+                      norm=None, axis=None, cbar=True, show_mask=True):
         '''Display the phasemap as a colormesh.
 
         Parameters
@@ -372,6 +511,8 @@ class PhaseMap(object):
         axis.set_aspect('equal')
         # Plot the phasemap:
         im = axis.pcolormesh(phase, cmap=cmap, vmin=-limit, vmax=limit, norm=norm)
+        if show_mask and not np.all(self.mask):  # Plot mask if desired and not trivial!
+            axis.contour(self.mask, levels=[0.999999], colors='g')
         # Set the axes ticks and labels:
         axis.set_xlim(0, self.dim_uv[1])
         axis.set_ylim(0, self.dim_uv[0])
@@ -579,7 +720,7 @@ class PhaseMap(object):
         '''
         cls._log.debug('Calling make_color_wheel')
         yy, xx = np.indices((512, 512)) - 256
-        r = np.sqrt(xx ** 2 + yy ** 2)
+        r = np.sqrt(xx**2 + yy**2)
         # Create the wheel:
         color_wheel_magnitude = (1 - np.cos(r * pi/360)) / 2
         color_wheel_magnitude *= 0 * (r > 256) + 1 * (r <= 256)
diff --git a/pyramid/projector.py b/pyramid/projector.py
index a30b91fdb3f058c8adb2acf74cd790ed82cefaef..ef845e9310e668d5470a61100d09900fd8d1abc9 100644
--- a/pyramid/projector.py
+++ b/pyramid/projector.py
@@ -184,12 +184,14 @@ class Projector(object):
                                  'vector- or scalar-field-projection!')
 
     @abc.abstractmethod
-    def get_info(self):
+    def get_info(self, verbose):
         '''Get specific information about the projector as a string.
 
         Parameters
         ----------
-        None
+        verbose: boolean, optional
+            If this is true, the text looks prettier (maybe using latex). Default is False for the
+            use in file names and such.
 
         Returns
         -------
@@ -223,9 +225,12 @@ class XTiltProjector(Projector):
 
     def __init__(self, dim, tilt, dim_uv=None):
 
-        def get_position(p, m, b, size):
-            y, x = np.array(p)[:, 0]+0.5, np.array(p)[:, 1]+0.5
-            return (y-m*x-b)/np.sqrt(m**2+1) + size/2.
+        def get_position(points, center, tilt, size):
+            point_vecs = np.asarray(points)+0.5 - np.asarray(center)  # vectors pointing to points
+            direc_vec = np.array((np.cos(tilt), -np.sin(tilt)))  # vector pointing along projection
+            distances = -np.cross(point_vecs, direc_vec)  # here (special case): divisor is one!
+            # minus because sign is derived of -sin(angle(point_vec, direc_vec)) neg between 0-180°
+            return distances + size/2.  # Shift to center the projection
 
         def get_impact(pos, r, size):
             return [x for x in np.arange(np.floor(pos-r), np.floor(pos+r)+1, dtype=int)
@@ -260,9 +265,7 @@ class XTiltProjector(Projector):
         voxels = list(itertools.product(range(dim_proj), range(dim_perp)))  # z-y-plane
         # Calculate positions along the projected pixel coordinate system:
         center = (dim_proj/2., dim_perp/2.)
-        m = np.where(tilt <= pi, -1/np.tan(tilt+1E-30), 1/np.tan(tilt+1E-30))
-        b = center[0] - m * center[1]
-        positions = get_position(voxels, m, b, dim_v)
+        positions = get_position(voxels, center, tilt, dim_v)
         # Calculate weight-matrix:
         r = 1/np.sqrt(np.pi)  # radius of the voxel circle
         rho = 0.5 / r
@@ -291,12 +294,14 @@ class XTiltProjector(Projector):
         super(XTiltProjector, self).__init__(dim, dim_uv, weight, coeff)
         self._log.debug('Created '+str(self))
 
-    def get_info(self):
+    def get_info(self, verbose=False):
         '''Get specific information about the projector as a string.
 
         Parameters
         ----------
-        None
+        verbose: boolean, optional
+            If this is true, the text looks prettier (maybe using latex). Default is False for the
+            use in file names and such.
 
         Returns
         -------
@@ -304,7 +309,10 @@ class XTiltProjector(Projector):
             Information about the projector as a string, e.g. for the use in plot titles.
 
         '''
-        return 'x-tilt: $\phi = {:3.2f} \pi$'.format(self.tilt/pi)
+        if verbose:
+            return u'x-tilt: $\phi = {:d}$°'.format(int(np.round(self.tilt*180/pi)))
+        else:
+            return u'xtilt_phi={:d}°'.format(int(np.round(self.tilt*180/pi)))
 
 
 class YTiltProjector(Projector):
@@ -330,9 +338,12 @@ class YTiltProjector(Projector):
 
     def __init__(self, dim, tilt, dim_uv=None):
 
-        def get_position(p, m, b, size):
-            y, x = np.array(p)[:, 0]+0.5, np.array(p)[:, 1]+0.5
-            return (y-m*x-b)/np.sqrt(m**2+1) + size/2.
+        def get_position(points, center, tilt, size):
+            point_vecs = np.asarray(points)+0.5 - np.asarray(center)  # vectors pointing to points
+            direc_vec = np.array((np.cos(tilt), -np.sin(tilt)))  # vector pointing along projection
+            distances = -np.cross(point_vecs, direc_vec)  # here (special case): divisor is one!
+            # minus because sign is derived of -sin(angle(point_vec, direc_vec)) neg between 0-180°
+            return distances + size/2.  # Shift to center the projection
 
         def get_impact(pos, r, size):
             return [x for x in np.arange(np.floor(pos-r), np.floor(pos+r)+1, dtype=int)
@@ -367,9 +378,7 @@ class YTiltProjector(Projector):
         voxels = list(itertools.product(range(dim_proj), range(dim_perp)))  # z-x-plane
         # Calculate positions along the projected pixel coordinate system:
         center = (dim_proj/2., dim_perp/2.)
-        m = np.where(tilt <= pi, -1/np.tan(tilt+1E-30), 1/np.tan(tilt+1E-30))
-        b = center[0] - m * center[1]
-        positions = get_position(voxels, m, b, dim_u)
+        positions = get_position(voxels, center, tilt, dim_u)
         # Calculate weight-matrix:
         r = 1/np.sqrt(np.pi)  # radius of the voxel circle
         rho = 0.5 / r
@@ -398,12 +407,14 @@ class YTiltProjector(Projector):
         super(YTiltProjector, self).__init__(dim, dim_uv, weight, coeff)
         self._log.debug('Created '+str(self))
 
-    def get_info(self):
+    def get_info(self, verbose=False):
         '''Get specific information about the projector as a string.
 
         Parameters
         ----------
-        None
+        verbose: boolean, optional
+            If this is true, the text looks prettier (maybe using latex). Default is False for the
+            use in file names and such.
 
         Returns
         -------
@@ -411,7 +422,10 @@ class YTiltProjector(Projector):
             Information about the projector as a string, e.g. for the use in plot titles.
 
         '''
-        return 'y-tilt: $\phi = {:3.2f} \pi$'.format(self.tilt/pi)
+        if verbose:
+            return u'y-tilt: $\phi = {:d}$°'.format(int(np.round(self.tilt*180/pi)))
+        else:
+            return u'ytilt_phi={:d}°'.format(int(np.round(self.tilt*180/pi)))
 
 
 class SimpleProjector(Projector):
@@ -436,16 +450,14 @@ class SimpleProjector(Projector):
 
     _log = logging.getLogger(__name__+'.SimpleProjector')
     AXIS_DICT = {'z': (0, 1, 2), 'y': (1, 0, 2), 'x': (2, 1, 0)}  # (0:z, 1:y, 2:x) -> (proj, v, u)
+    # coordinate switch for 'x': u, v --> z, y (not y, z!)!
 
     def __init__(self, dim, axis='z', dim_uv=None):
         self._log.debug('Calling __init__')
         assert axis in {'z', 'y', 'x'}, 'Projection axis has to be x, y or z (given as a string)!'
         self.axis = axis
         proj, v, u = self.AXIS_DICT[axis]
-        if axis == 'x':
-            dim_proj, dim_v, dim_u = dim[proj], dim[u], dim[v]  # coordinate switch for 'x'!
-        else:
-            dim_proj, dim_v, dim_u = dim[proj], dim[v], dim[u]
+        dim_proj, dim_v, dim_u = dim[proj], dim[v], dim[u]
         dim_z, dim_y, dim_x = dim
         size_2d = dim_u * dim_v
         size_3d = np.prod(dim)
@@ -464,13 +476,11 @@ class SimpleProjector(Projector):
         elif axis == 'x':
             self._log.debug('Projection along the x-axis')
             coeff = [[0, 0, 1], [0, 1, 0]]  # Caution, coordinate switch: u, v --> z, y (not y, z!)
-            #  indices = np.array([np.arange(dim_proj) + row*dim_proj
-            #                      for row in range(size_2d)]).reshape(-1)  # this is u, v --> y, z
             indices = np.array([np.arange(dim_x) + (row % dim_z)*dim_x*dim_y + row//dim_z*dim_x
                                 for row in range(size_2d)]).reshape(-1)
         if dim_uv is not None:
             indptr = indptr.tolist()  # convert to use insert() and append()
-            d_v, d_u = int((dim_uv[0]-dim_v)/2), int((dim_uv[1]-dim_u)/2)  # padding in u and v
+            d_v, d_u = (dim_uv[0]-dim_v)//2, (dim_uv[1]-dim_u)//2  # padding in u and v
             indptr[-1:-1] = [indptr[-1]] * d_v*dim_uv[1]  # append empty rows at the end
             for i in np.arange(dim_v, 0, -1):  # all slices in between
                 u, l = i*dim_u, (i-1)*dim_u+1  # upper / lower slice end
@@ -487,12 +497,14 @@ class SimpleProjector(Projector):
         super(SimpleProjector, self).__init__(dim, dim_uv, weight, coeff)
         self._log.debug('Created '+str(self))
 
-    def get_info(self):
+    def get_info(self, verbose=False):
         '''Get specific information about the projector as a string.
 
         Parameters
         ----------
-        None
+        verbose: boolean, optional
+            If this is true, the text looks prettier (maybe using latex). Default is False for the
+            use in file names and such.
 
         Returns
         -------
@@ -500,6 +512,9 @@ class SimpleProjector(Projector):
             Information about the projector as a string, e.g. for the use in plot titles.
 
         '''
-        return 'projected along {}-axis'.format(self.axis)
+        if verbose:
+            return 'projected along {}-axis'.format(self.axis)
+        else:
+            return '{}axis'.format(self.axis)
 
 # TODO: Arbitrary Projections!
diff --git a/pyramid/version.py b/pyramid/version.py
index bbc3afc970ce7efcbae3a8c2ac5f563c62cdfd1c..6cf8163c9c54cf3c87ea75663823638a2ba29579 100644
--- a/pyramid/version.py
+++ b/pyramid/version.py
@@ -1,3 +1,3 @@
 # THIS FILE IS GENERATED FROM THE PYRAMID SETUP.PY
 version = "0.1.0-dev"
-hg_revision = "4fdb98485ce0+"
+hg_revision = "4b25550ed656+"
diff --git a/scripts/gui/mag_slicer.py b/scripts/gui/mag_slicer.py
index 1ded00a99736e81d2901e9e2299a06db17150939..cd3af7a76126563abe299daba7acc4f0f67e4976 100644
--- a/scripts/gui/mag_slicer.py
+++ b/scripts/gui/mag_slicer.py
@@ -8,12 +8,14 @@
 # WARNING! All changes made in this file will be lost!
 
 
+import os
 import sys
 
 from PyQt4 import QtCore, QtGui
 
 from matplotlibwidget import MatplotlibWidget
 
+import pyramid
 from pyramid.magdata import MagData
 from pyramid.projector import SimpleProjector
 from pyramid.phasemapper import PhaseMapperRDFC
@@ -228,7 +230,8 @@ class UI_MagSlicerMain(QtGui.QWidget):
             self.mplWidgetMag.draw()
 
     def load(self):
-        mag_file = QtGui.QFileDialog.getOpenFileName(self, 'Open Data File', '',
+        directory = os.path.join(pyramid.DIR_FILES, 'magdata')
+        mag_file = QtGui.QFileDialog.getOpenFileName(self, 'Open Data File', directory,
                                                      'NetCDF files (*.nc)')
         self.mag_data = MagData.load_from_netcdf4(mag_file)
         self.mag_data_loaded = True
diff --git a/tests/test_costfunction/phase_map_ref.nc b/tests/test_costfunction/phase_map_ref.nc
index 744cc72c6c2e8f3d3b59862b385df75ac9c40244..1990d52440d21a5429123f2bd375e30ad2c771d7 100644
Binary files a/tests/test_costfunction/phase_map_ref.nc and b/tests/test_costfunction/phase_map_ref.nc differ
diff --git a/tests/test_dataset.py b/tests/test_dataset.py
index 4f06f8203f8507834b685ebfda391012f531d601..2956acf9f95fd67f8b187eb56ce49c90dcb079fd 100644
--- a/tests/test_dataset.py
+++ b/tests/test_dataset.py
@@ -58,17 +58,17 @@ class TestCaseDataSet(unittest.TestCase):
         assert self.data.Se_inv.diagonal().sum() == self.data.m, \
             'Unexpected behaviour in set_Se_inv_block_diag()!'
 
-    def test_set_Se_inv_diag_with_masks(self):
+    def test_set_Se_inv_diag_with_conf(self):
         self.data.append(self.phase_map, self.projector)
         self.data.append(self.phase_map, self.projector)
-        mask_2d = self.mask[1, ...]
-        self.data.set_Se_inv_diag_with_masks([mask_2d, mask_2d])
+        confidence = self.mask[1, ...]
+        self.data.set_Se_inv_diag_with_conf([confidence, confidence])
         assert self.data.Se_inv.shape == (self.data.m, self.data.m), \
             'Unexpected behaviour in set_Se_inv_diag_with_masks()!'
-        assert self.data.Se_inv.diagonal().sum() == 2*mask_2d.sum(), \
+        assert self.data.Se_inv.diagonal().sum() == 2*confidence.sum(), \
             'Unexpected behaviour in set_Se_inv_diag_with_masks()!'
 
-    def test_create_3d_mask(self):
+    def test_set_3d_mask(self):
         self.assertRaises(NotImplementedError, self.data.create_3d_mask, None)
 
 
diff --git a/tests/test_forwardmodel/phase_map_ref.nc b/tests/test_forwardmodel/phase_map_ref.nc
index 744cc72c6c2e8f3d3b59862b385df75ac9c40244..1990d52440d21a5429123f2bd375e30ad2c771d7 100644
Binary files a/tests/test_forwardmodel/phase_map_ref.nc and b/tests/test_forwardmodel/phase_map_ref.nc differ
diff --git a/tests/test_magdata.py b/tests/test_magdata.py
index a178de31891a93609248c941caa5e48032d89499..8b189d250746c789f1535ec20dcf0494fb2c9fd7 100644
--- a/tests/test_magdata.py
+++ b/tests/test_magdata.py
@@ -76,15 +76,39 @@ class TestCaseMagData(unittest.TestCase):
         assert_allclose(self.mag_data.magnitude, reference,
                         err_msg='Unexpected behavior in set_vector()!')
 
+    def test_flip(self):
+        mag_data = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_orig.nc'))
+        mag_data_flipx = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_flipx.nc'))
+        mag_data_flipy = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_flipy.nc'))
+        mag_data_flipz = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_flipz.nc'))
+        assert_allclose(mag_data.flip('x').magnitude, mag_data_flipx.magnitude,
+                        err_msg='Unexpected behavior in flip()! (x)')
+        assert_allclose(mag_data.flip('y').magnitude, mag_data_flipy.magnitude,
+                        err_msg='Unexpected behavior in flip()! (y)')
+        assert_allclose(mag_data.flip('z').magnitude, mag_data_flipz.magnitude,
+                        err_msg='Unexpected behavior in flip()! (z)')
+
+    def test_rot(self):
+        mag_data = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_orig.nc'))
+        mag_data_rotx = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_rotx.nc'))
+        mag_data_roty = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_roty.nc'))
+        mag_data_rotz = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_rotz.nc'))
+        assert_allclose(mag_data.rot('x').magnitude, mag_data_rotx.magnitude,
+                        err_msg='Unexpected behavior in rot()! (x)')
+        assert_allclose(mag_data.rot('y').magnitude, mag_data_roty.magnitude,
+                        err_msg='Unexpected behavior in rot()! (y)')
+        assert_allclose(mag_data.rot('z').magnitude, mag_data_rotz.magnitude,
+                        err_msg='Unexpected behavior in rot()! (z)')
+
     def test_load_from_llg(self):
-        mag_data = MagData.load_from_llg(os.path.join(self.path, 'ref_mag_data.txt'))
+        mag_data = MagData.load_from_llg(os.path.join(self.path, 'mag_data_ref_load.txt'))
         assert_allclose(mag_data.magnitude, self.mag_data.magnitude,
                         err_msg='Unexpected behavior in load_from_llg()!')
         assert_allclose(mag_data.a, self.mag_data.a,
                         err_msg='Unexpected behavior in load_from_llg()!')
 
     def test_load_from_netcdf4(self):
-        mag_data = MagData.load_from_netcdf4(os.path.join(self.path, 'ref_mag_data.nc'))
+        mag_data = MagData.load_from_netcdf4(os.path.join(self.path, 'mag_data_ref_load.nc'))
         assert_allclose(mag_data.magnitude, self.mag_data.magnitude,
                         err_msg='Unexpected behavior in load_from_netcdf4()!')
         assert_allclose(mag_data.a, self.mag_data.a,
diff --git a/tests/test_magdata/mag_data_flipx.nc b/tests/test_magdata/mag_data_flipx.nc
new file mode 100644
index 0000000000000000000000000000000000000000..a52466f5af96b73a67d866a6ce1c6e3edbca8a64
Binary files /dev/null and b/tests/test_magdata/mag_data_flipx.nc differ
diff --git a/tests/test_magdata/mag_data_flipy.nc b/tests/test_magdata/mag_data_flipy.nc
new file mode 100644
index 0000000000000000000000000000000000000000..20f3e9a2018345ea673b14f0d31b4971d385343b
Binary files /dev/null and b/tests/test_magdata/mag_data_flipy.nc differ
diff --git a/tests/test_magdata/mag_data_flipz.nc b/tests/test_magdata/mag_data_flipz.nc
new file mode 100644
index 0000000000000000000000000000000000000000..095ed28c2572d94b2895ef84b8a098d6eddc483e
Binary files /dev/null and b/tests/test_magdata/mag_data_flipz.nc differ
diff --git a/tests/test_magdata/mag_data_orig.nc b/tests/test_magdata/mag_data_orig.nc
new file mode 100644
index 0000000000000000000000000000000000000000..b71ff4c838615b8dd5d43464e74ce0e1a9ec5f92
Binary files /dev/null and b/tests/test_magdata/mag_data_orig.nc differ
diff --git a/tests/test_magdata/mag_data_ref_load.nc b/tests/test_magdata/mag_data_ref_load.nc
new file mode 100644
index 0000000000000000000000000000000000000000..200f66fa5f6c43f56e3746ccbc70013b6f206164
Binary files /dev/null and b/tests/test_magdata/mag_data_ref_load.nc differ
diff --git a/tests/test_magdata/mag_data_ref_load.txt b/tests/test_magdata/mag_data_ref_load.txt
new file mode 100644
index 0000000000000000000000000000000000000000..293c185a73fce0669baba800745f16fcc48d7a2e
--- /dev/null
+++ b/tests/test_magdata/mag_data_ref_load.txt
@@ -0,0 +1,66 @@
+LLGFileCreator: test_magdata/ref_mag_data
+    4    4    4
+5.000000e-07   5.000000e-07   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   5.000000e-07   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   5.000000e-07   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   5.000000e-07   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   1.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   1.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   1.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   1.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   2.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   2.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   2.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   2.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   3.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   3.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   3.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   3.500000e-06   5.000000e-07   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   5.000000e-07   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   5.000000e-07   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   5.000000e-07   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   5.000000e-07   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   1.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   1.500000e-06   1.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+2.500000e-06   1.500000e-06   1.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+3.500000e-06   1.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   2.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   2.500000e-06   1.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+2.500000e-06   2.500000e-06   1.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+3.500000e-06   2.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   3.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   3.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   3.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   3.500000e-06   1.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   5.000000e-07   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   5.000000e-07   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   5.000000e-07   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   5.000000e-07   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   1.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   1.500000e-06   2.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+2.500000e-06   1.500000e-06   2.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+3.500000e-06   1.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   2.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   2.500000e-06   2.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+2.500000e-06   2.500000e-06   2.500000e-06   1.000000e+00   1.000000e+00   1.000000e+00
+3.500000e-06   2.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   3.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   3.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   3.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   3.500000e-06   2.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   5.000000e-07   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   5.000000e-07   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   5.000000e-07   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   5.000000e-07   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   1.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   1.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   1.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   1.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   2.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   2.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   2.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   2.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+5.000000e-07   3.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+1.500000e-06   3.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+2.500000e-06   3.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
+3.500000e-06   3.500000e-06   3.500000e-06   0.000000e+00   0.000000e+00   0.000000e+00
\ No newline at end of file
diff --git a/tests/test_magdata/mag_data_rotx.nc b/tests/test_magdata/mag_data_rotx.nc
new file mode 100644
index 0000000000000000000000000000000000000000..665048b25056a7fec75a8e80ca9abaed58dcfd4e
Binary files /dev/null and b/tests/test_magdata/mag_data_rotx.nc differ
diff --git a/tests/test_magdata/mag_data_roty.nc b/tests/test_magdata/mag_data_roty.nc
new file mode 100644
index 0000000000000000000000000000000000000000..c4623430902ca3a01b97680416aa688bd3903a2e
Binary files /dev/null and b/tests/test_magdata/mag_data_roty.nc differ
diff --git a/tests/test_magdata/mag_data_rotz.nc b/tests/test_magdata/mag_data_rotz.nc
new file mode 100644
index 0000000000000000000000000000000000000000..a55ee115635f01c1598a0f147704f10c68f1c206
Binary files /dev/null and b/tests/test_magdata/mag_data_rotz.nc differ
diff --git a/tests/test_phasemap.py b/tests/test_phasemap.py
index 472222d8e92e3b4c6571850c88314670c985493b..411b7511decaee7d14c3a7699a7f7c051b42a773 100644
--- a/tests/test_phasemap.py
+++ b/tests/test_phasemap.py
@@ -17,22 +17,59 @@ class TestCasePhaseMap(unittest.TestCase):
         self.path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test_phasemap')
         phase = np.zeros((4, 4))
         phase[1:-1, 1:-1] = 1
-        self.phase_map = PhaseMap(10.0, phase)
+        mask = phase.astype(dtype=np.bool)
+        confidence = np.ones((4, 4))
+        self.phase_map = PhaseMap(10.0, phase, mask, confidence)
 
     def tearDown(self):
         self.path = None
         self.phase_map = None
 
+    def test_copy(self):
+        phase_map = self.phase_map
+        phase_map_copy = self.phase_map.copy()
+        assert phase_map == self.phase_map, 'Unexpected behaviour in copy()!'
+        assert phase_map_copy != self.phase_map, 'Unexpected behaviour in copy()!'
+
+    def test_scale_down(self):
+        self.phase_map.scale_down()
+        reference = 1/4. * np.ones((2, 2))
+        assert_allclose(self.phase_map.phase, reference,
+                        err_msg='Unexpected behavior in scale_down()!')
+        assert_allclose(self.phase_map.mask, np.zeros((2, 2), dtype=np.bool),
+                        err_msg='Unexpected behavior in scale_down()!')
+        assert_allclose(self.phase_map.confidence, np.ones((2, 2)),
+                        err_msg='Unexpected behavior in scale_down()!')
+        assert_allclose(self.phase_map.a, 20,
+                        err_msg='Unexpected behavior in scale_down()!')
+
+    def test_scale_up(self):
+        self.phase_map.scale_up()
+        reference = np.zeros((8, 8))
+        reference[2:-2, 2:-2] = 1
+        assert_allclose(self.phase_map.phase, reference,
+                        err_msg='Unexpected behavior in scale_up()!')
+        assert_allclose(self.phase_map.mask, reference.astype(dtype=np.bool),
+                        err_msg='Unexpected behavior in scale_up()!')
+        assert_allclose(self.phase_map.confidence, np.ones((8, 8)),
+                        err_msg='Unexpected behavior in scale_up()!')
+        assert_allclose(self.phase_map.a, 5,
+                        err_msg='Unexpected behavior in scale_up()!')
+
     def test_load_from_txt(self):
         phase_map = PhaseMap.load_from_txt(os.path.join(self.path, 'ref_phase_map.txt'))
-        assert_allclose(phase_map.phase, self.phase_map.phase,
+        assert_allclose(self.phase_map.phase, phase_map.phase,
                         err_msg='Unexpected behavior in load_from_txt()!')
         assert_allclose(phase_map.a, self.phase_map.a,
                         err_msg='Unexpected behavior in load_from_txt()!')
 
     def test_load_from_netcdf4(self):
         phase_map = PhaseMap.load_from_netcdf4(os.path.join(self.path, 'ref_phase_map.nc'))
-        assert_allclose(phase_map.phase, self.phase_map.phase,
+        assert_allclose(self.phase_map.phase, phase_map.phase,
+                        err_msg='Unexpected behavior in load_from_netcdf4()!')
+        assert_allclose(self.phase_map.mask, phase_map.mask,
+                        err_msg='Unexpected behavior in load_from_netcdf4()!')
+        assert_allclose(self.phase_map.confidence, phase_map.confidence,
                         err_msg='Unexpected behavior in load_from_netcdf4()!')
         assert_allclose(phase_map.a, self.phase_map.a,
                         err_msg='Unexpected behavior in load_from_netcdf4()!')
diff --git a/tests/test_phasemap/ref_phase_map.nc b/tests/test_phasemap/ref_phase_map.nc
index 4b69f864f077c05a9d58b7f12e3f04182fc8d131..62d32b4b1925c7555606977fbe34240f4a6d8214 100644
Binary files a/tests/test_phasemap/ref_phase_map.nc and b/tests/test_phasemap/ref_phase_map.nc differ
diff --git a/tests/test_phasemapper/phase_map.nc b/tests/test_phasemapper/phase_map.nc
index a2c2ae7e47b80c712b796fb8bba36a84403fa3a0..dbe3234498122e809bda8ee5e062cc54f43c456b 100644
Binary files a/tests/test_phasemapper/phase_map.nc and b/tests/test_phasemapper/phase_map.nc differ
diff --git a/tests/test_phasemapper/phase_map_fc.nc b/tests/test_phasemapper/phase_map_fc.nc
index 2d614499502b8fa35af42c961d6ce4b971afdb58..ea13e499169e9b8c32baead2c3f5baee40e075ef 100644
Binary files a/tests/test_phasemapper/phase_map_fc.nc and b/tests/test_phasemapper/phase_map_fc.nc differ
diff --git a/tests/test_projector.py b/tests/test_projector.py
index b784fdce044e54c3671f52f874cacc32fb10bfba..ca6fa33d635b73f08e1120f9a0bc90d98216c709 100644
--- a/tests/test_projector.py
+++ b/tests/test_projector.py
@@ -250,7 +250,7 @@ class TestCaseYTiltProjector(unittest.TestCase):
 if __name__ == '__main__':
     suite = unittest.TestLoader().loadTestsFromTestCase(TestCaseSimpleProjector)
     unittest.TextTestRunner(verbosity=2).run(suite)
-    suite = unittest.TestLoader().loadTestsFromTestCase(TestCaseXTiltProjector)
-    unittest.TextTestRunner(verbosity=2).run(suite)
-    suite = unittest.TestLoader().loadTestsFromTestCase(TestCaseYTiltProjector)
-    unittest.TextTestRunner(verbosity=2).run(suite)
+#    suite = unittest.TestLoader().loadTestsFromTestCase(TestCaseXTiltProjector)
+#    unittest.TextTestRunner(verbosity=2).run(suite)
+#    suite = unittest.TestLoader().loadTestsFromTestCase(TestCaseYTiltProjector)
+#    unittest.TextTestRunner(verbosity=2).run(suite)
diff --git a/tests/test_projector/ref_mag_proj_x.nc b/tests/test_projector/ref_mag_proj_x.nc
index 025a3c9090a0e73cbf412772d985cfed6ee93b46..813872f91bfedb6f264ed5b83757c8afe0f935dd 100644
Binary files a/tests/test_projector/ref_mag_proj_x.nc and b/tests/test_projector/ref_mag_proj_x.nc differ