Example #1
0
def create_images_from_boot_images(source,
                                   epoch,
                                   bands,
                                   stokes,
                                   base_path=None):
    """
    :param source:
        Source name.
    :param epoch:
        Sources epoch.
    :param bands:
        Iterable of bands.
    :param base_path: (optional)
        Path to route of directory tree. If ``None`` then use current directory.
        (default: ``None``)
    """

    curdir = os.getcwd()
    print "Stacking bootstrapped images..."
    images = Images()
    for band in bands:
        print " for band ", band
        for stoke in stokes:
            map_path = im_fits_path(source,
                                    band,
                                    epoch,
                                    stoke,
                                    base_path=base_path)
            images.add_from_fits(wildcard=os.path.join(map_path, 'cc_*.fits'))

    return images
Example #2
0
uvdata = UVData(os.path.join(data_dir, uv_fits))
boot = CleanBootstrap([model], uvdata)
os.chdir(data_dir)
boot.run(100, nonparametric=False, use_v=False)
booted_uv_fits = glob.glob(os.path.join(data_dir, 'bootstrapped_data*.fits'))
for i, boot_uv in enumerate(sorted(booted_uv_fits)):
    clean_difmap(boot_uv,
                 'booted_cc_{}.fits'.format(i),
                 'I', (512, 0.1),
                 path=data_dir,
                 path_to_script=path_to_script,
                 outpath=data_dir)
booted_im_fits = glob.glob(os.path.join(data_dir, 'booted_cc*.fits'))

images = Images()
images.add_from_fits(booted_im_fits)
error_image = images.create_error_image()

orig_image = create_clean_image_from_fits_file(os.path.join(data_dir, im_fits))
rms = rms_image_shifted(os.path.join(data_dir, uv_fits),
                        image_fits=os.path.join(data_dir, im_fits),
                        path_to_script=path_to_script)
blc, trc = find_bbox(orig_image.image, level=1.5 * rms)
image_mask = orig_image.image < 2 * rms
label_size = 14
matplotlib.rcParams['xtick.labelsize'] = label_size
matplotlib.rcParams['ytick.labelsize'] = label_size
matplotlib.rcParams['axes.titlesize'] = label_size
matplotlib.rcParams['axes.labelsize'] = label_size
matplotlib.rcParams['font.size'] = label_size
matplotlib.rcParams['legend.fontsize'] = label_size
Example #3
0
        ppol_images = Images()
        pang_images = Images()
        ppol_images.add_images(images_.create_pol_images())
        pang_images.add_images(images_.create_pang_images())
        ppol_error_image = ppol_images.create_error_image(cred_mass=0.95)
        pang_error_image = pang_images.create_error_image(cred_mass=0.68)
        ppol_error_images_dict.update({band: ppol_error_image})
        pang_error_images_dict.update({band: pang_error_image})
        images_ = Images()
        for stoke in stokes:
            map_path = im_fits_path(source,
                                    band,
                                    epoch,
                                    stoke,
                                    base_path=base_path)
            images_.add_from_fits(
                wildcard=os.path.join(map_path, 'cc_orig.fits'))
        ppol_image = images_.create_pol_images()[0]
        ppol_images_dict.update({band: ppol_image})
        mask = ppol_image.image < ppol_error_image.image
        ppol_masks_dict.update({band: mask})

    # Create overall mask for PPOL flux
    masks = [np.array(mask, dtype=int) for mask in ppol_masks_dict.values()]
    ppol_mask = np.zeros(masks[0].shape, dtype=int)
    for mask in masks:
        ppol_mask += mask
    ppol_mask[ppol_mask != 0] = 1
    # Save mask to disk
    np.savetxt(os.path.join(base_path, "ppol_mask.txt"), ppol_mask)
    ppol_mask = np.loadtxt(os.path.join(base_path, "ppol_mask.txt"))
Example #4
0
                     outpath=data_dir, show_difmap_output=False)

# Find shifts between longest and shortest wavelengths
uv_paths_hl = [uv for uv in uv_paths if 'l18' in uv or 'l22' in uv]
cc_paths_hl = [cc for cc in cc_paths if 'l18' in cc or 'l22' in cc]
shift, shifts, r = find_core_shift(uv_paths_hl, cc_paths_hl,
                                   path_to_script=path_to_script,
                                   data_dir=data_dir, do_bootstrap=True,
                                   upsample_factor=1000, n_boot=100)
print "Using circular mask with r = {}".format(r)
# Histogram shifts
plt.hist(np.sqrt(shifts[:, 0] ** 2. + shifts[:, 1] ** 2), bins=15)

# Create ROTM image for current source
images = Images()
images.add_from_fits(wildcard=os.path.join(data_dir,
                                           "{}.*.common.*cn.fits".format(source)))
# Find PPA uncertainty Hovatta's way
# Uncertainty in EVPA calibration [deg]
sigma_evpa = 2.
# D-terms spread [dimensionless] are equal for all frequencies
d_spread = 0.002
n_ant = 8
n_if = 2
n_scans = 10
# For all frequencies calculate D-term error image
sigma_d_images_dict = dict()
for l in ('l18', 'l20', 'l21', 'l22'):
    fname = "{}.{}.common.icn.fits".format(source, l)
    image = create_image_from_fits_file(os.path.join(data_dir, fname))
    i_peak = np.max(image.image.ravel())
    sigma_d_image = d_spread * np.sqrt(image.image ** 2. +
Example #5
0
class MFObservations(object):
    def __init__(self, fits_files, imsizes=None, n_boot=100, common_imsize=None,
                 common_beam=None, find_shifts=False, path_to_script=None,
                 data_dir=None, clear_difmap_logs=True, rotm_slices=None,
                 sigma_evpa=None, sigma_d_term=None, n_scans=None):
        """
        :param fits_files:
            Iterable of FITS files with self-calibrated simultaneous
            mutlifrequency UV-data.
        :param imsizes: (optional)
            Iterable of tuples (image size [pix], pixel size [mas]) for data
            sorted by frequency. If ``None`` then derive from data UV-plane
            coverages. (default: ``None``)
        :param common_imsize: (optional)
            Iterable (image size [pix], pixel size [mas]) for common image
            parameters. If ``None`` then use minimal pixel size but keep the
            same physical size. (default: ``None``)
        :param common_beam: (optional)
            Parameters of beam to convolve CCs to make matched resolution maps.
            If ``None`` then derive from available as beam of lowest frequency.
            (default: ``None``)
        :param find_shifts:
            Boolean. Find shifts between pairs of images at different bands?
            (default: ``False``)
        :param path_to_script:
            Path to `difmap` cleaning script `final_clean_nw`. If ``None`` then
            suppose it is in CWD. (default: ``None``)
        :param data_dir: (optional)
            Directory to store output. If ``None`` then use CWD. (default:
            ``None``)
        :param clear_difmap_logs: (optional)
            Boolean. Clear `difmap` log-files after CLEANing methods? (default:
            ``True``)
        :param rotm_slices: (optional)
            Iterable of start & stop point coordinates (in image coordinates,
            in mas) of ROTM slice to plot. If ``None`` then don't plot any
            slices. (default: ``None``)
        :param sigma_evpa: (optional)
            Iterable of uncertainies of absolute EVPA calibration for each band.
            If ``None`` then use zero values. (default: ``None``)
        :param sigma_d_term: (optional)
            Iterable of D-terms calibration uncertainties for each band. If
            ``None`` then use zero for each band. (default: ``None``)
        :param n_scans: (optional)
            Iterable of numbers of independend scans for each band. If ``None``
            then number of scans is determined from data (some of them may be
            dependent). (default: ``None``)

        """
        self.original_fits_files = fits_files
        self.uvdata_dict = dict()
        self.uvfits_dict = dict()
        self.uvfits_boot_dict = dict()
        self.load_uvdata()
        self.stokes = ('I', 'Q', 'U')
        self.n_boot = n_boot
        self._cs_mask = None
        self._cs_mask_n_sigma = None
        self.rotm_slices = rotm_slices
        self._chisq_crit = chisq_crit_values[len(self.uvdata_dict) - 2]
        self.figures = dict()

        if sigma_evpa is None:
            self.sigma_evpa = np.zeros(len(self.uvdata_dict), dtype=float)
        else:
            assert len(sigma_evpa) == len(self.uvdata_dict)
            self.sigma_evpa = np.array(sigma_evpa)
        if sigma_d_term is None:
            self.sigma_d_term = np.zeros(len(self.uvdata_dict), dtype=float)
        else:
            assert len(sigma_d_term) == len(self.uvdata_dict)
        self.sigma_d_term = np.array(sigma_d_term)
        self.n_scans = n_scans

        if imsizes is None:
            imsizes = [self.uvdata_dict[freq].imsize_by_uv_coverage for
                       freq in self.freqs]
        self.imsizes = imsizes
        self.imsizes_dict = {freq: imsize for freq, imsize in
                             zip(self.freqs, self.imsizes)}

        self._common_imsize = common_imsize

        self._common_beam = common_beam

        self.find_shifts = find_shifts
        if path_to_script is None:
            path_to_script = os.path.join(os.getcwd(), 'final_clean_nw')
        self.path_to_script = path_to_script
        if data_dir is None:
            data_dir = os.getcwd()
        self.data_dir = data_dir
        self.clear_difmap_logs = clear_difmap_logs

        # Container for original CLEAN-images of self-calibrated uv-data
        self.cc_image_dict = dict()
        # Container for paths to FITS-files with original CLEAN-images of
        # self-calibrated uv-data
        self.cc_fits_dict = dict()
        # Container for original CLEAN-image's beam parameters
        self.cc_beam_dict = dict()

        # Containers for images and paths to FITS files with common size images
        self.cc_cs_image_dict = dict()
        self.cc_cs_fits_dict = dict()

        # Container for rms of common sized images
        self._cs_images_rms = dict()

        # Container for rms of original images
        self._images_rms = dict()

        # Instance of ``Images`` class with original common sized images.
        self._original_cs_images = None

        # Containers for paths to FITS files with native parameters images made
        # from bootstraped data
        self.cc_boot_fits_dict = dict()
        # Containers for paths to FITS files with common size images made from
        # bootstraped data
        self.cc_boot_cs_fits_dict = dict()

        # Hovatta-type errors estimation. Values - 2D numpy arrays.
        self.evpa_sigma_dict = dict()
        self.ppol_sigma_dict = dict()

        self._boot_images = None

        # Instance of ``Images`` class with ROTM maps
        self._boot_rotm_images = None

        # Uncertainties found using bootstrapped data (accounting for D- and
        # EVPA-error). Values - instances of ``Image`` class.
        self.evpa_sigma_boot_dict = dict()

        # ROTM image made by conventional method (accounting for D- and
        # EVPA-error in PANG)
        self._rotm_image_conv = None
        # ROTM image made by conventional method (accounting for D-error in
        # PANG only)
        self._rotm_image_conv_grad = None

        # ROTM error map made by conventional method (accounting for D- and
        # EVPA-error in PANG)
        self._rotm_image_sigma_conv = None
        # ROTM error map made by conventional method (accounting for only
        # D-error in PANG)
        self._rotm_image_sigma_conv = None

        # Chi-squared image made by conventional method (must account for both
        # D- and EVPA-error in PANG)
        self._rotm_chisq_image_conv = None

        # ROTM image made using PANG errors obtained by bootstrapping PANG maps
        # with D-terms and EVPA calibrations error accounted for.
        self._rotm_image_boot = None

        # ROTM error map made by bootstrapping with D-terms and EVPA
        # calibration errors accounted for.
        self._rotm_image_sigma_boot = None
        # ROTM error map made by bootstrapping with only D-terms error accounted
        # for.
        self._rotm_image_sigma_boot_grad = None

        # Chi-squared image made by bootstrapped data with D-terms and EVPA
        # calibration errors accounted for.
        self._rotm_chisq_image_boot = None

    def run(self, sigma_evpa=None, sigma_d_term=None, colors_clim=None,
            n_sigma_mask=None, rotm_slices=None, pxls_plot=None,
            plot_points=None, model_generator=None, slice_ylim=None,
            freq_stokes_dict_native=None, freq_stokes_dict_common=None):
        self._t0 = Time.now()
        date, time = str(self._t0.utc.datetime).split()
        self._difmap_commands_file =\
            os.path.join(self.data_dir,
                         "difmap_commands_{}_{}".format(date, time))
        self.clean_original_native(freq_stokes_dict=freq_stokes_dict_native)
        self.clean_original_common(freq_stokes_dict=freq_stokes_dict_common)
        if self.find_shifts:
            self.get_shifts()
        self.bootstrap_uvdata()
        # self.clean_boot_native()
        self.clean_boot_common()
        self.set_common_mask(n_sigma=n_sigma_mask)
        self.analyze_rotm_conv(colors_clim=colors_clim, sigma_evpa=sigma_evpa,
                               sigma_d_term=sigma_d_term,
                               rotm_slices=rotm_slices, pxls_plot=pxls_plot,
                               plot_points=plot_points, slice_ylim=slice_ylim)
        self.analyze_rotm_boot(colors_clim=colors_clim, rotm_slices=rotm_slices,
                               slice_ylim=slice_ylim)

    def load_uvdata(self):
        self.uvdata_dict = dict()
        self.uvfits_dict = dict()
        for fits_file in self.original_fits_files:
            print("Loading UV-FITS file {}".format(os.path.split(fits_file)[-1]))
            uvdata = UVData(fits_file)
            self.uvdata_dict.update({uvdata.band_center: uvdata})
            self.uvfits_dict.update({uvdata.band_center: fits_file})

    @property
    def freqs(self):
        return sorted(self.uvdata_dict.keys())

    @property
    def common_imsize(self):
        if self._common_imsize is None:
            pixsizes = [imsize[1] for imsize in self.imsizes]
            phys_sizes = [imsize[0]*imsize[1] for imsize in self.imsizes]
            pixsize = min(pixsizes)
            phys_size = max(phys_sizes)
            powers = (phys_size / pixsize) // np.array([2**i + 1 for i in range(20)])
            powers = powers.tolist()
            imsize = 2 ** powers.index(0)
            self._common_imsize = imsize, pixsize
            print("Common image parameteres: {}, {}".format(imsize, pixsize))
        return self._common_imsize

    @property
    def common_beam(self):
        """
        :note:
            By default beam of lowest frequency is used.
        """
        if self._common_beam is None:
            self._common_beam = self.cc_beam_dict[self.freqs[0]]
            print("Common beam parameters: {}".format(self._common_beam))
        return self._common_beam

    def cs_images_rms(self):
        raise NotImplementedError
        self._cs_images_rms = None

    def images_rms(self):
        raise NotImplementedError
        self._images_rms = None

    def set_common_mask(self, n_sigma=3.):
        print("Finding rough mask for creating bootstrap images of RM, alpha,"
              " ...")
        cs_mask = pol_mask({stokes: self.cc_cs_image_dict[self.freqs[-1]][stokes] for
                            stokes in self.stokes},
                           rms_cs_dict=None,
                           uv_fits_path=self.uvfits_dict[self.freqs[-1]],
                           n_sigma=n_sigma,
                           path_to_script=self.path_to_script)
        self._cs_mask = cs_mask
        self._cs_mask_n_sigma = n_sigma

    def clean_original_native(self, freq_stokes_dict=None):
        """
        Clean original FITS-files with uv-data using native resolution.
        """
        for freq in self.freqs:
            self.cc_image_dict.update({freq: dict()})
            self.cc_fits_dict.update({freq: dict()})
            self.cc_beam_dict.update({freq: dict()})

        if freq_stokes_dict is not None:
            print("Found CLEANed images of original uvdata with naitive map &"
                  " beam parameters...")
            for freq in self.freqs:
                for stokes in self.stokes:
                    image = create_clean_image_from_fits_file(freq_stokes_dict[freq][stokes])
                    self.cc_image_dict[freq].update({stokes: image})
                    if stokes == 'I':
                        self.cc_beam_dict.update({freq: image.beam})

        else:
            print("Clean original uv-data with native map & beam parameters...")
            for freq in self.freqs:
                print("Cleaning frequency {} with image "
                      "parameters {}".format(freq, self.imsizes_dict[freq]))
                uv_fits_path = self.uvfits_dict[freq]
                uv_dir, uv_fname = os.path.split(uv_fits_path)
                for stokes in self.stokes:
                    outfname = '{}_{}_cc.fits'.format(freq, stokes)
                    outpath = os.path.join(self.data_dir, outfname)
                    # Check if it is already done
                    if not os.path.exists(outpath):
                        clean_difmap(uv_fname, outfname, stokes,
                                     self.imsizes_dict[freq], path=uv_dir,
                                     path_to_script=self.path_to_script,
                                     outpath=self.data_dir,
                                     command_file=self._difmap_commands_file)
                    else:
                        print("Found CLEAN model in file {}".format(outfname))
                    self.cc_fits_dict[freq].update({stokes: os.path.join(self.data_dir,
                                                                         outfname)})
                    image = create_clean_image_from_fits_file(outpath)
                    self.cc_image_dict[freq].update({stokes: image})
                    if stokes == 'I':
                        self.cc_beam_dict.update({freq: image.beam})

        if self.clear_difmap_logs:
            print("Removing difmap log-files...")
            difmap_logs = glob.glob(os.path.join(self.data_dir, "difmap.log*"))
            for difmap_log in difmap_logs:
                os.unlink(difmap_log)

    def clean_original_common(self, freq_stokes_dict=None):

        # if freq_stokes_dict is not None:
        #     print("Found CLEANed images of original uvdata with common map &"
        #           " beam parameters...")
        #     for freq in self.freqs:
        #         self.cc_cs_image_dict.update({freq: dict()})
        #         self.cc_cs_fits_dict.update({freq: dict()})
        #         for stokes in self.stokes:
        #             image = create_clean_image_from_fits_file(freq_stokes_dict[freq][stokes])
        #             self.cc_image_dict[freq].update({stokes: image})
        #             if stokes == 'I':
        #                 self.cc_beam_dict.update({freq: image.beam})

        print("Clean original uv-data with common map parameters "
              " {} and beam {}".format(self.common_imsize, self.common_beam))
        for freq in self.freqs:
            self.cc_cs_image_dict.update({freq: dict()})
            self.cc_cs_fits_dict.update({freq: dict()})

            uv_fits_path = self.uvfits_dict[freq]
            uv_dir, uv_fname = os.path.split(uv_fits_path)
            for stokes in self.stokes:
                outfname = 'cs_{}_{}_cc.fits'.format(freq, stokes)
                outpath = os.path.join(self.data_dir, outfname)
                # Check if it is already done
                if not os.path.exists(outpath):
                    clean_difmap(uv_fname, outfname, stokes, self.common_imsize,
                                 path=uv_dir,
                                 path_to_script=self.path_to_script,
                                 beam_restore=self.common_beam,
                                 outpath=self.data_dir,
                                 command_file=self._difmap_commands_file)
                else:
                    print("Found CLEAN model in file {}".format(outfname))
                self.cc_cs_fits_dict[freq].update({stokes: os.path.join(self.data_dir,
                                                                        outfname)})
                image = create_clean_image_from_fits_file(outpath)
                self.cc_cs_image_dict[freq].update({stokes: image})

        if self.clear_difmap_logs:
            print("Removing difmap log-files...")
            difmap_logs = glob.glob(os.path.join(self.data_dir, "difmap.log*"))
            for difmap_log in difmap_logs:
                os.unlink(difmap_log)

    def get_shifts(self):
        print("Optionally find shifts between original CLEAN-images...")
        print("Determining images shift...")
        beam_pxl = int(self.common_beam[0] / self.common_imsize[1])
        shift_dict = dict()
        freq_1 = self.freqs[0]
        image_1 = self.cc_cs_image_dict[freq_1]['I']

        for freq_2 in self.freqs[1:]:
            image_2 = self.cc_cs_image_dict[freq_2]['I']
            # Coarse grid of possible shifts
            shift = find_shift(image_1, image_2, beam_pxl, 1,
                               max_mask_r=beam_pxl, mask_step=2)
            # More accurate grid of possible shifts
            print("Using fine grid for accurate estimate")
            coarse_grid = range(0, 100, 5)
            idx = coarse_grid.index(shift)
            if idx > 0:
                min_shift = coarse_grid[idx - 1]
            else:
                min_shift = 0
            shift = find_shift(image_1, image_2, coarse_grid[idx + 1], 1,
                               min_shift=min_shift, max_mask_r=200,
                               mask_step=5)

            shift_dict.update({str((freq_1, freq_2,)): shift})

        # Dumping shifts to json file in target directory
        with open(os.path.join(self.data_dir, "shifts.json"), 'w') as fp:
            json.dump(shift_dict, fp)

    def bootstrap_uvdata(self):
        print("Bootstrap self-calibrated uv-data with CLEAN-models...")
        for freq, uv_fits_path in self.uvfits_dict.items():

            # Check if it is already done
            files = glob.glob(os.path.join(self.data_dir,
                                           'boot_{}*.uvf'.format(freq)))
            # If number of found files doesn't equal to ``n_boot`` - remove them
            if not len(files) == self.n_boot:
                for file in files:
                    os.unlink(file)

                # and bootstrap current frequency again
                cc_fits_paths = [self.cc_fits_dict[freq][stokes] for stokes in self.stokes]
                uvdata = self.uvdata_dict[freq]

                models = list()
                for cc_fits_path in cc_fits_paths:
                    ccmodel = create_model_from_fits_file(cc_fits_path)
                    models.append(ccmodel)

                # Position of current ``freq``: ``0`` means the lowest
                # frequency.
                i = self.freqs.index(freq)
                boot = CleanBootstrap(models, uvdata,
                                      sigma_dterms=self.sigma_d_term[i])
                curdir = os.getcwd()
                os.chdir(self.data_dir)
                boot.run(n=self.n_boot, nonparametric=False, use_v=False,
                         use_kde=True, outname=['boot_{}'.format(freq), '.uvf'])
                os.chdir(curdir)

                files = glob.glob(os.path.join(self.data_dir,
                                               'boot_{}*.uvf'.format(freq)))
            print("Found bootstraped uvdata files!")
            self.uvfits_boot_dict.update({freq: sorted(files)})

    def clean_boot_native(self):
        print("Clean bootstrap replications with native restoring beam and map"
              " size...")
        for freq in self.freqs:
            self.cc_boot_fits_dict.update({freq: dict()})
            uv_fits_paths = self.uvfits_boot_dict[freq]
            for stokes in self.stokes:
                for i, uv_fits_path in enumerate(uv_fits_paths):
                    uv_dir, uv_fname = os.path.split(uv_fits_path)
                    outfname = 'boot_{}_{}_cc_{}.fits'.format(freq, stokes,
                                                              str(i + 1).zfill(3))
                    # Check if it is already done
                    if not os.path.exists(os.path.join(self.data_dir,
                                                       outfname)):
                        clean_difmap(uv_fname, outfname, stokes,
                                     self.common_imsize, path=uv_dir,
                                     path_to_script=self.path_to_script,
                                     beam_restore=self.common_beam,
                                     outpath=self.data_dir,
                                     command_file=self._difmap_commands_file)
                    else:
                        print("Found CLEAN model in file {}".format(outfname))
                files = sorted(glob.glob(os.path.join(self.data_dir,
                                                      'boot_{}_{}_cc_*.fits'.format(freq, stokes))))
                self.cc_boot_fits_dict[freq].update({stokes: files})

        if self.clear_difmap_logs:
            print("Removing difmap log-files...")
            difmap_logs = glob.glob(os.path.join(self.data_dir, "difmap.log*"))
            for difmap_log in difmap_logs:
                os.unlink(difmap_log)

    def clean_boot_common(self):
        print("Clean bootstrap replications with common "
              "restoring beams and map sizes...")
        for freq in self.freqs:
            self.cc_boot_cs_fits_dict.update({freq: dict()})
            uv_fits_paths = self.uvfits_boot_dict[freq]
            for stokes in self.stokes:
                for i, uv_fits_path in enumerate(uv_fits_paths):
                    uv_dir, uv_fname = os.path.split(uv_fits_path)
                    outfname = 'cs_boot_{}_{}_cc_{}.fits'.format(freq, stokes,
                                                              str(i + 1).zfill(3))
                    # Check if it is already done
                    if not os.path.exists(os.path.join(self.data_dir,
                                                       outfname)):
                        clean_difmap(uv_fname, outfname, stokes,
                                     self.common_imsize, path=uv_dir,
                                     path_to_script=self.path_to_script,
                                     beam_restore=self.common_beam,
                                     outpath=self.data_dir,
                                     command_file=self._difmap_commands_file)
                    else:
                        print("Found CLEAN model in file {}".format(outfname))
                files = sorted(glob.glob(os.path.join(self.data_dir,
                                                      'cs_boot_{}_{}_cc_*.fits'.format(freq, stokes))))
                self.cc_boot_cs_fits_dict[freq].update({stokes: files})

        if self.clear_difmap_logs:
            print("Removing difmap log-files...")
            difmap_logs = glob.glob(os.path.join(self.data_dir, "difmap.log*"))
            for difmap_log in difmap_logs:
                os.unlink(difmap_log)

    @property
    def original_cs_images(self):
        if self._original_cs_images is None:
            self._original_cs_images = Images()
            for freq in self.freqs:
                for stokes in self.stokes:
                    self.original_cs_images.add_image(self.cc_cs_image_dict[freq][stokes])
        return self._original_cs_images

    def analyze_rotm_conv(self, sigma_evpa=None, sigma_d_term=None,
                          rotm_slices=None, colors_clim=None, n_sigma=None,
                          pxls_plot=None, plot_points=None, slice_ylim=None):
        print("Estimate RM map and it's error using conventional method...")

        if sigma_evpa is None:
            sigma_evpa = self.sigma_evpa
        if sigma_d_term is None:
            sigma_d_term = self.sigma_d_term
        if rotm_slices is None:
            rotm_slices = self.rotm_slices
        if n_sigma is not None:
            self.set_common_mask(n_sigma)

        # Find EVPA error for each frequency
        print("Calculating maps of PANG errors for each band using Hovatta's"
              " approach...")
        # Fetch common size `I` map on highest frequency for plotting PANG error
        # maps
        i_image = self.cc_cs_image_dict[self.freqs[-1]]['I']

        if pxls_plot is not None:
            pxls_plot = [i_image._convert_coordinate(pxl) for pxl in pxls_plot]

        rms = rms_image(i_image)
        blc, trc = find_bbox(i_image.image, 2.*rms,
                             delta=int(i_image._beam.beam[0]))

        for i, freq in enumerate(self.freqs):
            n_ant = len(self.uvdata_dict[freq].antennas)
            n_if = self.uvdata_dict[freq].nif
            d_term = sigma_d_term[i]
            s_evpa = sigma_evpa[i]

            # Get number of scans
            if self.n_scans is not None:
                try:
                    # If `NX` table is present
                    n_scans = len(self.uvdata_dict[freq].scans)
                except TypeError:
                    scans_dict = self.uvdata_dict[freq].scans_bl
                    scan_lengths = list()
                    for scans in scans_dict.values():
                        if scans is not None:
                            scan_lengths.append(len(scans))
                    n_scans = mode(scan_lengths)[0][0]
            else:
                n_scans = self.n_scans[i]

            q = self.cc_cs_image_dict[freq]['Q']
            u = self.cc_cs_image_dict[freq]['U']
            i = self.cc_cs_image_dict[freq]['I']

            # We need ``s_evpa = 0`` for testing RM gradient significance but
            # ``s_evpa != 0`` for calculating RM errors
            pang_std, ppol_std = hovatta_find_sigma_pang(q, u, i, s_evpa,
                                                         d_term, n_ant, n_if,
                                                         n_scans)
            self.evpa_sigma_dict[freq] = pang_std
            fig = iplot(i_image.image, pang_std, x=i_image.x, y=i_image.y,
                        min_abs_level=3. * rms, colors_mask=self._cs_mask,
                        color_clim=[0, 1], blc=blc, trc=trc,
                        beam=self.common_beam, colorbar_label='sigma EVPA, [rad]',
                        show_beam=True, show=False)
            self.figures['EVPA_sigma_{}'.format(freq)] = fig

        sigma_pang_arrays = [self.evpa_sigma_dict[freq] for freq in self.freqs]
        sigma_pang_arrays_grad = [np.sqrt(self.evpa_sigma_dict[freq]**2 -
                                          np.deg2rad(self.sigma_evpa[i])**2) for
                                  i, freq in enumerate(self.freqs)]
        rotm_image, sigma_rotm_image, chisq_image =\
            self.original_cs_images.create_rotm_image(sigma_pang_arrays,
                                                      mask=self._cs_mask,
                                                      return_chisq=True,
                                                      plot_pxls=pxls_plot,
                                                      outdir=self.data_dir,
                                                      mask_on_chisq=False)
        rotm_image_grad, sigma_rotm_image_grad, _ =\
            self.original_cs_images.create_rotm_image(sigma_pang_arrays_grad,
                                                      mask=self._cs_mask,
                                                      return_chisq=True,
                                                      plot_pxls=pxls_plot,
                                                      outdir=self.data_dir,
                                                      mask_on_chisq=False)
        self._rotm_image_conv = rotm_image
        self._rotm_image_conv_grad = rotm_image_grad
        self._rotm_image_sigma_conv = sigma_rotm_image
        self._rotm_image_sigma_conv_grad = sigma_rotm_image_grad
        self._rotm_chisq_image_conv = chisq_image

        i_image = self.cc_cs_image_dict[self.freqs[-1]]['I']
        uv_fits_path = self.uvfits_dict[self.freqs[-1]]
        image_fits_path = self.cc_cs_fits_dict[self.freqs[-1]]['I']
        # RMS using Hovatta-style
        rms = rms_image_shifted(uv_fits_path, image_fits=image_fits_path,
                                path_to_script=self.path_to_script)
        blc, trc = find_bbox(i_image.image, 2.*rms,
                             delta=int(i_image._beam.beam[0]))
        fig = iplot(i_image.image, rotm_image.image, x=i_image.x, y=i_image.y,
                    min_abs_level=3. * rms, colors_mask=self._cs_mask,
                    color_clim=colors_clim, blc=blc, trc=trc,
                    beam=self.common_beam, slice_points=rotm_slices,
                    show_beam=True, show=False, show_points=plot_points,
                    cmap='viridis')
        self.figures['rotm_image_conv'] = fig
        fig = iplot(i_image.image, sigma_rotm_image.image, x=i_image.x,
                    y=i_image.y, min_abs_level=3. * rms,
                    colors_mask=self._cs_mask, color_clim=[0, 200], blc=blc,
                    trc=trc, beam=self.common_beam, slice_points=rotm_slices,
                    show_beam=True, show=False, cmap='viridis', beam_place='ul')
        self.figures['rotm_image_conv_sigma'] = fig
        fig = iplot(i_image.image, sigma_rotm_image_grad.image, x=i_image.x,
                    y=i_image.y, min_abs_level=3. * rms,
                    colors_mask=self._cs_mask, color_clim=[0, 200], blc=blc,
                    trc=trc, beam=self.common_beam, slice_points=rotm_slices,
                    show_beam=True, show=False, cmap='viridis', beam_place='ul')
        self.figures['rotm_image_conv_sigma_grad'] = fig
        fig = iplot(i_image.image, chisq_image.image, x=i_image.x, y=i_image.y,
                    min_abs_level=3. * rms, colors_mask=self._cs_mask,
                    outfile='rotm_chisq_image_conv', outdir=self.data_dir,
                    color_clim=[0., self._chisq_crit], blc=blc, trc=trc,
                    beam=self.common_beam,
                    colorbar_label='Chi-squared', slice_points=rotm_slices,
                    show_beam=True, show=False, cmap='viridis')
        self.figures['rotm_chisq_image_conv'] = fig

        if rotm_slices is not None:
            self.figures['slices_conv'] = dict()
            for rotm_slice in rotm_slices:
                rotm_slice_ = i_image._convert_coordinates(rotm_slice[0],
                                                           rotm_slice[1])
                # Here we use RM image error calculated using PANG errors
                # without contribution of the EVPA calibration errors.
                fig = analyze_rotm_slice(rotm_slice_, rotm_image,
                                         sigma_rotm_image=sigma_rotm_image_grad,
                                         outdir=self.data_dir,
                                         beam_width=int(i_image._beam.beam[0]),
                                         outfname="ROTM_{}_slice".format(rotm_slice),
                                         ylim=slice_ylim)
                self.figures['slices_conv'][str(rotm_slice)] = fig

        return rotm_image, sigma_rotm_image

    @property
    def boot_images(self):
        if self._boot_images is None:
                self._boot_images = Images()
                for freq in self.freqs:
                    for stokes in self.stokes:
                        # FIXME: to low memory usage for now
                        if stokes not in ('Q', 'U'):
                            continue
                        self._boot_images.add_from_fits(self.cc_boot_cs_fits_dict[freq][stokes])
        return self._boot_images

    def create_boot_pang_errors(self, cred_mass=0.68, n_sigma=None):
        """
        Create dictionary with images of PANG errors calculated from bootstrap
        PANG maps.

        :param cred_mass: (optional)
            Credibility mass. (default: ``0.68``)
        :param n_sigma: (optional)
            Sigma clipping for mask. If ``None`` then use instance's value.
            (default: ``None``)
        :return:
            Dictionary with keys - frequencies & values - instances of ``Image``
            class with error maps.
        """
        print("Calculating maps of PANG errors for each band using bootstrapped"
              " PANG maps...")
        result = dict()
        if n_sigma is not None:
            self.set_common_mask(n_sigma)

        # Fetch common size `I` map on highest frequency for plotting PANG error
        # maps
        i_image = self.cc_cs_image_dict[self.freqs[-1]]['I']
        rms = rms_image(i_image)
        blc, trc = find_bbox(i_image.image, 2.*rms,
                             delta=int(i_image._beam.beam[0]))
        for i, freq in enumerate(self.freqs):
            images = self.boot_images.create_pang_images(freq=freq,
                                                         mask=self._cs_mask)
            pang_images = Images()
            pang_images.add_images(images)
            error_image = pang_images.create_error_image(cred_mass=cred_mass)
            # As this errors are used for linear fit judgement only - add EVPA
            # absolute calibration error in quadrature
            evpa_error = np.deg2rad(self.sigma_evpa[i]) * np.ones(error_image.image.shape)
            error_image.image = np.sqrt((error_image.image)**2. + evpa_error**2.)
            result[freq] = error_image
            fig = iplot(i_image.image, error_image.image, x=i_image.x, y=i_image.y,
                        min_abs_level=3. * rms, colors_mask=self._cs_mask,
                        color_clim=[0, 1], blc=blc, trc=trc, beam=self.common_beam,
                        colorbar_label='sigma EVPA, [rad]', slice_points=None,
                        show_beam=True, show=False, cmap='viridis')
            self.figures['EVPA_sigma_boot_{}'.format(freq)] = fig
        self.evpa_sigma_boot_dict = result
        return result
        # FIXME: Beam slice length must be projection - not major axis
        # FIXME: Point fit file name must include coordinates in mas, not pixels
        # FIXME: Figure out how to work with low memory usage!

    def analyze_rotm_boot(self, n_sigma=None, cred_mass=0.68, rotm_slices=None,
                          colors_clim=None, slice_ylim=None,
                          use_conv_image_in_boot_slice=True):
        print("Estimate RM map and it's error using bootstrap...")

        if rotm_slices is None:
            rotm_slices = self.rotm_slices
        if n_sigma is not None:
            self.set_common_mask(n_sigma)
        # This accounts for D-terms and EVPA calibration errors.
        sigma_pangs_dict = self.create_boot_pang_errors()
        sigma_pang_arrays = [sigma_pangs_dict[freq].image for freq in
                             self.freqs]
        # This is RM image made using bootstrap-based PANG errors that
        # originally account for D-terms and EVPA calibration errors.
        rotm_image, _, chisq_image = \
            self.original_cs_images.create_rotm_image(sigma_pang_arrays,
                                                      mask=self._cs_mask,
                                                      return_chisq=True,
                                                      mask_on_chisq=True)
        self._rotm_image_boot = rotm_image
        self._rotm_chisq_image_boot = chisq_image

        i_image = self.cc_cs_image_dict[self.freqs[-1]]['I']
        rms = rms_image(i_image)
        blc, trc = find_bbox(i_image.image, 2.*rms,
                             delta=int(i_image._beam.beam[0]/2))
        fig = iplot(i_image.image, rotm_image.image, x=i_image.x, y=i_image.y,
                    min_abs_level=3. * rms, colors_mask=self._cs_mask,
                    color_clim=colors_clim, blc=blc, trc=trc, beam=self.common_beam,
                    slice_points=rotm_slices, cmap='viridis',
                    show_beam=True, show=False, beam_place="ul")
        self.figures['rotm_image_boot'] = fig
        fig = iplot(i_image.image, chisq_image.image, x=i_image.x, y=i_image.y,
                    min_abs_level=3. * rms, colors_mask=self._cs_mask,
                    color_clim=[0., self._chisq_crit], blc=blc, trc=trc, beam=self.common_beam,
                    colorbar_label='Chi-squared', slice_points=rotm_slices,
                    show_beam=True, show=False, cmap='viridis')
        self.figures['rotm_chisq_image_boot'] = fig

        self._boot_rotm_images =\
            self.boot_images.create_rotm_images(mask=self._cs_mask,
                                                mask_on_chisq=False,
                                                sigma_evpa=self.sigma_evpa)
        sigma_rotm_image =\
            self._boot_rotm_images.create_error_image(cred_mass=cred_mass)
        self._rotm_image_sigma_boot = sigma_rotm_image

        # Now ``self._boot_rotm_images`` doesn't contain contribution from
        # EVPA calibration error
        self._boot_rotm_images =\
            self.boot_images.create_rotm_images(mask=self._cs_mask,
                                                mask_on_chisq=False,
                                                sigma_evpa=None)
        sigma_rotm_image_grad =\
            self._boot_rotm_images.create_error_image(cred_mass=cred_mass)
        self._rotm_image_sigma_boot_grad = sigma_rotm_image_grad


        # This sigma take absolute EVPA calibration uncertainty into
        # account
        fig = iplot(i_image.image, sigma_rotm_image.image, x=i_image.x, y=i_image.y,
                    min_abs_level=3. * rms, colors_mask=self._cs_mask,
                    outfile='rotm_image_boot_sigma', outdir=self.data_dir,
                    color_clim=[0, 200], blc=blc, trc=trc, beam=self.common_beam,
                    slice_points=rotm_slices, cmap='viridis', beam_place='ul',
                    show_beam=True, show=False)
        self.figures['rotm_image_boot_sigma'] = fig
        # This sigma RM doesn't include EVPA
        fig = iplot(i_image.image, sigma_rotm_image_grad.image, x=i_image.x, y=i_image.y,
                    min_abs_level=3. * rms, colors_mask=self._cs_mask,
                    outfile='rotm_image_boot_sigma', outdir=self.data_dir,
                    color_clim=[0, 200], blc=blc, trc=trc, beam=self.common_beam,
                    slice_points=rotm_slices, cmap='viridis', beam_place='ul',
                    show_beam=True, show=False)
        self.figures['rotm_image_boot_sigma_grad'] = fig

        if rotm_slices is not None:
            self.figures['slices_boot'] = dict()
            self.figures['slices_boot_conv'] = dict()
            for rotm_slice in rotm_slices:
                rotm_slice_ = i_image._convert_coordinates(rotm_slice[0],
                                                           rotm_slice[1])
                if use_conv_image_in_boot_slice:
                    rotm_image_ = self._rotm_image_conv
                else:
                    rotm_image_ = rotm_image
                # ``self._boot_rotm_images`` doesn't contain contribution from
                # EVPA calibration error - so used for RM gradient searches

                fig = analyze_rotm_slice(rotm_slice_, rotm_image_,
                                         rotm_images=self._boot_rotm_images,
                                         outdir=self.data_dir,
                                         beam_width=int(i_image._beam.beam[0]),
                                         outfname="ROTM_{}_slice_boot".format(rotm_slice),
                                         ylim=slice_ylim, show_dots_boot=True,
                                         # fig=self.figures['slices_conv'][str(rotm_slice)],
                                         fig=None)
                self.figures['slices_boot'][str(rotm_slice)] = fig

                fig = analyze_rotm_slice(rotm_slice_, rotm_image_,
                                         rotm_images=self._boot_rotm_images,
                                         outdir=self.data_dir,
                                         beam_width=int(i_image._beam.beam[0]),
                                         outfname="ROTM_{}_slice_boot".format(rotm_slice),
                                         ylim=slice_ylim, show_dots_boot=True,
                                         fig=self.figures['slices_conv'][str(rotm_slice)],
                                         # fig=None,
                                         )
                self.figures['slices_boot_conv'][str(rotm_slice)] = fig

        return rotm_image, sigma_rotm_image
Example #6
0
def analyze_source(uv_fits_paths,
                   n_boot,
                   imsizes=None,
                   common_imsize=None,
                   common_beam=None,
                   find_shifts=False,
                   outdir=None,
                   path_to_script=None,
                   clear_difmap_logs=True,
                   rotm_slices=None):
    """
    Function that uses multifrequency self-calibration data for in-depth
    analysis.

    :param uv_fits_paths:
        Iterable of paths to self-calibrated uv-data FITS-files.
    :param n_boot:
        Number of bootstrap replications to use in analysis.
    :param imsizes: (optional)
        Iterable of image parameters (imsize, pixsize) that should be used for
        CLEANing of uv-data if no CLEAN-images are supplied. Should be sorted in
        increasing frequency order. If ``None`` then specify parameters by CLEAN
        images. (default: ``None``)
    :param common_imsize: (optional)
        Image parameters that will be used in making common size images for
        multifrequency analysis. If ``None`` then use physical image size of
        lowest frequency and pixel size of highest frequency. (default:
        ``None``)
    :param outdir: (optional)
        Output directory. This directory will be used for saving picture, data,
        etc. If ``None`` then use CWD. (default: ``None``)
    :param path_to_script: (optional)
        Path ot difmap CLEAN script. If ``None`` then use CWD. (default:
        ``None``)

    :notes:
        Workflow:
        1) Чистка с родным разрешением всех N диапазонов и получение родных
        моделей I, Q, U.
        2) Выбор общей ДН из N возможных
        3) (Опционально) Выбор uv-tapering
        4) Чистка uv-данных для всех диапазонов с (опционально применяемым
            uv-tapering) общей ДН
        5) Оценка сдвига ядра
        6) Создание B наборов из N многочастотных симулированных данных
            используя родные модели
        7) (Опционально) Чистка B наборов из N многочастотных симданных с
            родным разрешением для получения карт ошибок I для каждой из N
            частот
        8) Чистка B наборов из N многочастотных симданных для всех диапазонов с
            (опционально применяемым uv-tapering) общей ДН
        9) Оценка ошибки определения сдвига ядра
        10) Оценка RM и ее ошибки
        11) Оценка alpha и ее ошибки

    """

    # Fail early
    if imsizes is None:
        raise Exception("Provide imsizes argument!")
    if common_imsize is not None:
        print("Using common image size {}".format(common_imsize))
    else:
        raise Exception("Provide common_imsize argument!")

    # Setting up the output directory
    if outdir is None:
        outdir = os.getcwd()
    print("Using output directory {}".format(outdir))
    os.chdir(outdir)

    # Assume input self-calibrated uv-data FITS files have different frequencies
    n_freq = len(uv_fits_paths)
    print("Using {} frequencies".format(n_freq))

    # Assuming full multifrequency analysis
    stokes = ('I', 'Q', 'U')

    # Container for original self-calibrated uv-data
    uv_data_dict = dict()
    # Container for original self-calibrated uv-data FITS-file paths
    uv_fits_dict = dict()
    for uv_fits_path in uv_fits_paths:
        uvdata = UVData(uv_fits_path)
        # Mark frequencies by total band center [Hz] for consistency with image.
        uv_data_dict.update({uvdata.band_center: uvdata})
        uv_fits_dict.update({uvdata.band_center: uv_fits_path})

    # Lowest frequency goes first
    freqs = sorted(uv_fits_dict.keys())
    print("Frequencies are: {}".format(freqs))
    # Assert we have original map parameters for all frequencies
    assert len(imsizes) == n_freq

    # Container for original CLEAN-images of self-calibrated uv-data
    cc_image_dict = dict()
    # Container for paths to FITS-files with original CLEAN-images of
    # self-calibrated uv-data
    cc_fits_dict = dict()
    # Container for original CLEAN-image's beam parameters
    cc_beam_dict = dict()
    for freq in freqs:
        cc_image_dict.update({freq: dict()})
        cc_fits_dict.update({freq: dict()})
        cc_beam_dict.update({freq: dict()})

    # 1.
    # Clean original uv-data with specified map parameters
    print("1. Clean original uv-data with specified map parameters...")
    imsizes_dict = dict()
    for i, freq in enumerate(freqs):
        imsizes_dict.update({freq: imsizes[i]})
    for freq in freqs:
        uv_fits_path = uv_fits_dict[freq]
        uv_dir, uv_fname = os.path.split(uv_fits_path)
        for stoke in stokes:
            outfname = '{}_{}_cc.fits'.format(freq, stoke)
            outpath = os.path.join(outdir, outfname)
            clean_difmap(uv_fname,
                         outfname,
                         stoke,
                         imsizes_dict[freq],
                         path=uv_dir,
                         path_to_script=path_to_script,
                         outpath=outdir)
            cc_fits_dict[freq].update({stoke: os.path.join(outdir, outfname)})
            image = create_clean_image_from_fits_file(outpath)
            cc_image_dict[freq].update({stoke: image})
            if stoke == 'I':
                cc_beam_dict.update({freq: image.beam})

    # Containers for images and paths to FITS files with common size images
    cc_cs_image_dict = dict()
    cc_cs_fits_dict = dict()
    # 2.
    # Choose common beam size
    print("2. Choosing common beam size...")
    if common_beam is None:
        common_beam = cc_beam_dict[freqs[0]]
    print("Using common beam [mas, mas, deg] : {}".format(common_beam))

    # 3.
    # Optionally uv-tapering uv-data
    print("3. Optionally uv-tapering uv-data...")
    print("skipping...")

    # 4.
    # Clean original uv-data with common map parameters
    print("4. Clean original uv-data with common map parameters...")
    for freq in freqs:
        cc_cs_image_dict.update({freq: dict()})
        cc_cs_fits_dict.update({freq: dict()})

        uv_fits_path = uv_fits_dict[freq]
        uv_dir, uv_fname = os.path.split(uv_fits_path)
        for stoke in stokes:
            outfname = 'cs_{}_{}_cc.fits'.format(freq, stoke)
            outpath = os.path.join(outdir, outfname)
            # clean_difmap(uv_fname_cc, outfname, stoke, common_imsize,
            #              path=uv_dir, path_to_script=path_to_script,
            #              outpath=outdir, show_difmap_output=False)
            cc_cs_fits_dict[freq].update(
                {stoke: os.path.join(outdir, outfname)})
            image = create_image_from_fits_file(outpath)
            cc_cs_image_dict[freq].update({stoke: image})

    # 5.
    # Optionally find shifts between original CLEAN-images
    print("5. Optionally find shifts between original CLEAN-images...")
    if find_shifts:
        print("Determining images shift...")
        shift_dict = dict()
        freq_1 = freqs[0]
        image_1 = cc_image_dict[freq_1]['I']

        for freq_2 in freqs[1:]:
            image_2 = cc_image_dict[freq_2]['I']
            # Coarse grid of possible shifts
            shift = find_shift(image_1,
                               image_2,
                               100,
                               5,
                               max_mask_r=200,
                               mask_step=5)
            # More accurate grid of possible shifts
            print("Using fine grid for accurate estimate")
            coarse_grid = range(0, 100, 5)
            idx = coarse_grid.index(shift)
            if idx > 0:
                min_shift = coarse_grid[idx - 1]
            else:
                min_shift = 0
            shift = find_shift(image_1,
                               image_2,
                               coarse_grid[idx + 1],
                               1,
                               min_shift=min_shift,
                               max_mask_r=200,
                               mask_step=5)

            shift_dict.update({str((
                freq_1,
                freq_2,
            )): shift})

        # Dumping shifts to json file in target directory
        with open(os.path.join(outdir, "shifts_original.json"), 'w') as fp:
            json.dump(shift_dict, fp)
    else:
        print("skipping...")

    # 6.
    # Bootstrap self-calibrated uv-data with CLEAN-models
    print("6. Bootstrap self-calibrated uv-data with CLEAN-models...")
    uv_boot_fits_dict = dict()
    for freq, uv_fits_path in uv_fits_dict.items():
        # cc_fits_paths = [cc_fits_dict[freq][stoke] for stoke in stokes]
        # bootstrap_uv_fits(uv_fits_path, cc_fits_paths, n_boot, outpath=outdir,
        #                   outname=('boot_{}'.format(freq), '_uv.fits'))
        files = glob.glob(os.path.join(outdir, 'boot_{}*.fits'.format(freq)))
        uv_boot_fits_dict.update({freq: sorted(files)})

    # 7.
    # Optionally clean bootstrap replications with original restoring beams and
    # map sizes to get error estimates for original resolution maps of I, PPOL,
    # FPOL, ...
    print(
        "7. Optionally clean bootstrap replications with original restoring"
        " beams and map sizes...")
    print("skipping...")

    # 8.
    # Optionally clean bootstrap replications with common restoring beams and
    # map sizes
    print(
        "8. Optionally clean bootstrap replications with common restoring"
        " beams and map sizes...")
    cc_boot_fits_dict = dict()
    for freq in freqs:
        cc_boot_fits_dict.update({freq: dict()})
        uv_fits_paths = uv_boot_fits_dict[freq]
        for stoke in stokes:
            for i, uv_fits_path in enumerate(uv_fits_paths):
                uv_dir, uv_fname = os.path.split(uv_fits_path)
                outfname = 'boot_{}_{}_cc_{}.fits'.format(
                    freq, stoke,
                    str(i + 1).zfill(3))
                # clean_difmap(uv_fname_cc, outfname, stoke, common_imsize,
                #              path=uv_dir, path_to_script=path_to_script,
                #              outpath=outdir, show_difmap_output=False)
            files = sorted(
                glob.glob(
                    os.path.join(outdir,
                                 'boot_{}_{}_cc_*.fits'.format(freq, stoke))))
            cc_boot_fits_dict[freq].update({stoke: files})

    # 9. Optionally estimate RM map and it's error
    print("9. Optionally estimate RM map and it's error...")
    original_cs_images = Images()
    for freq in freqs:
        for stoke in stokes:
            original_cs_images.add_images(cc_cs_image_dict[freq][stoke])

    # Find rough mask for creating bootstrap images of RM, alpha, ...
    print("Finding rough mask for creating bootstrap images of RM, alpha, ...")
    cs_mask = pol_mask(
        {stoke: cc_cs_image_dict[freqs[-1]][stoke]
         for stoke in stokes},
        n_sigma=3.)

    rotm_image, _ = original_cs_images.create_rotm_image(mask=cs_mask)

    boot_images = Images()
    fnames = sorted(glob.glob(os.path.join(data_dir, "boot_*_*_cc_*.fits")))
    for freq in freqs:
        for stoke in stokes:
            boot_images.add_from_fits(cc_boot_fits_dict[freq][stoke])
    boot_rotm_images = boot_images.create_rotm_images(mask=cs_mask)
    s_rotm_image = boot_rotm_images.create_error_image(cred_mass=0.95)

    if rotm_slices is not None:
        fnames = [
            'rotm_slice_spread_{}.png'.format(i + 1)
            for i in range(len(rotm_slices))
        ]
        for rotm_slice, fname in zip(rotm_slices, fnames):
            analyze_rotm_slice(rotm_slice,
                               rotm_image,
                               boot_rotm_images,
                               outdir=outdir,
                               outfname=fname)

    # # Calculate simulataneous confidence bands
    # # Bootstrap slices
    # slices = list()
    # for image in rotm_images_sym.images:
    #     slice_ = image.slice((216, 276), (296, 276))
    #     slices.append(slice_[~np.isnan(slice_)])

    # # Find means
    # obs_slice = rotm_image_sym.slice((216, 276), (296, 276))
    # x = np.arange(216, 296, 1)
    # x = x[~np.isnan(obs_slice)]
    # obs_slice = obs_slice[~np.isnan(obs_slice)]
    # # Find sigmas
    # slices_ = [arr.reshape((1, len(obs_slice))) for arr in slices]
    # sigmas = hdi_of_arrays(slices_).squeeze()
    # means = np.mean(np.vstack(slices), axis=0)
    # diff = obs_slice - means
    # # Move bootstrap curves to original simulated centers
    # slices_ = [slice_ + diff for slice_ in slices]
    # # Find low and upper confidence band
    # low, up = create_sim_conf_band(slices_, obs_slice, sigmas,
    #                                alpha=conf_band_alpha)

    # # Plot confidence bands and model values
    # fig = plt.figure()
    # ax = fig.add_subplot(1, 1, 1)
    # ax.plot(x, low[::-1], 'g')
    # ax.plot(x, up[::-1], 'g')
    # [ax.plot(x, slice_[::-1], 'r', lw=0.15) for slice_ in slices_]
    # ax.plot(x, obs_slice[::-1], '.k')
    # # Plot ROTM model
    # ax.plot(np.arange(216, 296, 1),
    #         rotm_grad_value * (np.arange(216, 296, 1) - 256.)[::-1] +
    #         rotm_value_0)
    # fig.savefig(os.path.join(data_dir, 'rotm_slice_spread.png'),
    #             bbox_inches='tight', dpi=200)
    # plt.close()

    if clear_difmap_logs:
        print("Removing difmap log-files...")
        difmap_logs = glob.glob(os.path.join(outdir, "difmap.log*"))
        for difmpa_log in difmap_logs:
            os.unlink(difmpa_log)