Skip to content

API Documentation

align_single_filter

Function for aligning images in a single set

Parameters:

Name Type Description Default
image_set ImageSet instance

an ImageSet instance with the relevant files to be aligned

required
reference_image_index int

index of the image in the image_set list that is to be used as reference for cross correlation

0
cleanup bool

whether to cleanup the temporary folders and intermediate drizzling results

True
matching_config dict

keyword arguments that are passed directly to match images

{}
perform_manual_shifts bool

whether or not to apply a manual shift. This manual shift should be given to the ImageSet during construction

True
Source code in crocoa/imalign.py
def align_single_filter(image_set, reference_image_index=0, cleanup=True, matching_config={}, perform_manual_shifts=True):
    """ Function for aligning images in a single set
    Parameters
    ----------
    image_set : ImageSet instance
        an ImageSet instance with the relevant files to be aligned
    reference_image_index : int
        index of the image in the image_set list that is to be used as reference for cross correlation
    cleanup : bool
        whether to cleanup the temporary folders and intermediate drizzling results
    matching_config : dict
        keyword arguments that are passed directly to match images
    perform_manual_shifts : bool
        whether or not to apply a manual shift. This manual shift should be given to the ImageSet 
        during construction
    """
    image_set.make_all_copies()
    if perform_manual_shifts:
        image_set.apply_manual_shifts()
    image_set.drizzle(individual=True)
    source_images = image_set.drizzled_files
    reference_image = source_images[reference_image_index]
    for i, image in enumerate(source_images):
        if i == 0:
            pass
        else:
            dra, ddec = match_images(reference_image, image, **matching_config)
            image_set.images[i].backpropagate_wcs(dra, ddec)

    if cleanup:
        image_set.clean_temp_directories()

align_multiple_filters

Function for aligning image sets between multiple filters

Parameters:

Name Type Description Default
image_sets list or iterable

list of ImageSet instances

required
reference_set_index int

index of the ImageSet in the image_set list that is to be used as reference for cross correlation

0
cleanup bool

whether to cleanup the temporary folders and intermediate drizzling results

True
matching_config dict

keyword arguments that are passed directly to match images

{}
perform_manual_shifts bool

whether or not to apply a manual shift. This manual shift should be given to the ImageSet during construction

True
Source code in crocoa/imalign.py
def align_multiple_filters(image_sets, reference_set_index=0, cleanup=True, matching_config={}, perform_manual_shifts=True):
    """ Function for aligning image sets between multiple filters 
    Parameters
    ----------
    image_sets : list or iterable
        list of ImageSet instances
    reference_set_index : int
        index of the ImageSet in the image_set list that is to be used as reference for cross correlation
    cleanup : bool
        whether to cleanup the temporary folders and intermediate drizzling results
    matching_config : dict
        keyword arguments that are passed directly to match images
    perform_manual_shifts : bool
        whether or not to apply a manual shift. This manual shift should be given to the ImageSet 
        during construction
    """
    source_images = []
    for image_set in image_sets:
        image_set.make_all_copies()
        if perform_manual_shifts:
            image_set.apply_manual_shifts()
        image_set.drizzle()
        # Take the zero index because it should be a list with a single file
        source_images.append(image_set.drizzled_files[0])

    reference_image = source_images[reference_set_index]
    if image_sets[0].verbose:
        print('Running multiple filter alignment')
        print('Using source images')
        print(source_images)
        print('')

    for i, image in enumerate(source_images):
        if i == reference_set_index:
            pass
        else:
            dra, ddec = match_images(str(reference_image), str(image), **matching_config)
            image_sets[i].backpropagate_wcs_shift(dra, ddec)
    if cleanup:
        image_set.clean_temp_directories()

ImageSet

Source code in crocoa/filemanagement.py
class ImageSet:
    def __init__(
        self,
        file_list,
        filtername,
        drizzle_config,
        working_dir="./temp",
        destination_dir=None,
        manual_shifts=None,
        verbose=False,
        file_suffix=None,
    ) -> None:
        """
        Parameters
        ----------
        file_list : list
            list of string file names to be included in the image set
        filtername : str
            Name of the current filter - just used to create subdirectories
        drizzle_config : dict
            configuration dictionary for astrodrizzle
        working_dir : str, optional
            sets the temp directory parent name
        destination_dir : str, optional
            This sets the directory where the resulting files with the backpropagated wcs' are put. If None this defaults
            to './filtername_aligned'
        manual_shifts : dict or tuple
            Either a dictionary mapping dra ddec shifts to individual images in the set or a tuple with a global dra and
            ddec that should be applied to all the frames collectively
        verbose : bool
            whether to output drizzle resutls
        file_suffix : str, optional
            suffix to append to the file name(s)
        """
        self.images = [
            Image(file_name, verbose=verbose, file_suffix=file_suffix)
            for file_name in file_list
        ]
        self.verbose = verbose
        self.drz_config = drizzle_config
        self.filtername = filtername
        self.drz_source_dir = Path(working_dir) / "drz_source" / filtername
        self.drz_target_dir = Path(working_dir) / "drz_target" / filtername
        self.manual_shifts = manual_shifts

        # Set up destination files
        self.destination_dir = destination_dir
        if self.destination_dir is not None:
            self.destination_dir = Path(destination_dir)
            self.destination_dir.mkdir(parents=True, exist_ok=True)
        else:
            self.destination_dir = Path("./{}_aligned".format(filter))
            self.destination_dir.mkdir(parents=True, exist_ok=True)

        # set up drizzle files
        self.drz_source_dir.mkdir(parents=True, exist_ok=True)
        self.drz_target_dir.mkdir(parents=True, exist_ok=True)


    def make_all_copies(self):
        """Create all relevant file copies"""
        self.make_target_copies()
        self.make_driz_source()

    def make_target_copies(self):
        """Make target file copies"""
        for img in self.images:
            img.make_target_copy(self.destination_dir)

    def make_driz_source(self):
        """Make source file copies since drizzle changes the source files it's run on"""
        self.working_source = []
        for image in self.images:
            image.make_working_copy(self.drz_source_dir)
            self.working_source.append(str(image.working_copy))

    def drizzle(self, individual=False):
        """Run the drizzling process"""
        self.drizzled_files = []
        if individual:
            for image in self.working_source:
                if self.verbose:
                    adriz(
                        input=[image],
                        output=str(
                            self.drz_target_dir / os.path.basename(image).split(".")[0]
                        ),
                        **self.drz_config
                    )
                else:
                    with suppress_stdout_stderr():
                        adriz(
                            input=[image],
                            output=str(
                                self.drz_target_dir
                                / os.path.basename(image).split(".")[0]
                            ),
                            **self.drz_config
                        )
                self.drizzled_files.append(
                    list(self.drz_target_dir.glob(
                        os.path.basename(image).split(".")[0] + "*sci*.fits"
                    ))[0]
                )
        else:
            # if not individual we need subdirectories in the drz_target directory
            drz_target = self.drz_target_dir / self.filtername
            drz_target.mkdir(parents=True, exist_ok=True)

            if self.verbose:
                adriz(
                    input=self.working_source,
                    output=str(drz_target),
                    **self.drz_config
                )
            else:
                with suppress_stdout_stderr():
                    adriz(
                        input=self.working_source,
                        output=str(drz_target),
                        **self.drz_config
                    )
            # get the resulting drizzled file(s)
            self.drizzled_files = list(self.drz_target_dir.glob("*sci*.fits"))

    def apply_manual_shifts(self):
        """Take a manual shift and apply it to either all images collectively or to each individual frame"""
        # First parse to understand if we have a collective change or not
        if self.manual_shifts is None:
            if self.verbose:
                print("No manual shifts specified")
            pass

        if isinstance(self.manual_shifts, dict):
            for image in self.images:
                if image in self.manual_shifts.keys():
                    # Add the shift to the working copy
                    image.shift_working_copy_wcs(
                        self.manual_shifts[image]["dra"],
                        self.manual_shifts[image]["ddec"],
                    )
                    # also add it to the target
                    image.backpropagate_wcs(
                        self.manual_shifts[image]["dra"],
                        self.manual_shifts[image]["ddec"],
                    )
        elif isinstance(self.manual_shifts, tuple):
            for image in self.images:
                image.shift_working_copy_wcs(
                    self.manual_shifts[0], self.manual_shifts[1]
                )
                image.backpropagate_wcs(self.manual_shifts[0], self.manual_shifts[1])

    def backpropagate_wcs_shift(self, dra, ddec):
        """propagate the found wcs offset to all images"""
        for image in self.images:
            image.backpropagate_wcs(dra, ddec)

    def clean_temp_directories(self):
        """Remove drizzling directories"""
        shutil.rmtree(self.drz_source_dir)
        shutil.rmtree(self.drz_target_dir)

    def __repr__(self) -> str:
        msg = "< {} ImageSet instance containing: ".format(self.filtername)
        for img in self.images:
            msg += img + ", "
        msg += ">"
        return msg

__init__(file_list, filtername, drizzle_config, working_dir='./temp', destination_dir=None, manual_shifts=None, verbose=False, file_suffix=None)

Parameters:

Name Type Description Default
file_list list

list of string file names to be included in the image set

required
filtername str

Name of the current filter - just used to create subdirectories

required
drizzle_config dict

configuration dictionary for astrodrizzle

required
working_dir str, optional

sets the temp directory parent name

'./temp'
destination_dir str, optional

This sets the directory where the resulting files with the backpropagated wcs' are put. If None this defaults to './filtername_aligned'

None
manual_shifts dict or tuple

Either a dictionary mapping dra ddec shifts to individual images in the set or a tuple with a global dra and ddec that should be applied to all the frames collectively

None
verbose bool

whether to output drizzle resutls

False
file_suffix str, optional

suffix to append to the file name(s)

None
Source code in crocoa/filemanagement.py
def __init__(
    self,
    file_list,
    filtername,
    drizzle_config,
    working_dir="./temp",
    destination_dir=None,
    manual_shifts=None,
    verbose=False,
    file_suffix=None,
) -> None:
    """
    Parameters
    ----------
    file_list : list
        list of string file names to be included in the image set
    filtername : str
        Name of the current filter - just used to create subdirectories
    drizzle_config : dict
        configuration dictionary for astrodrizzle
    working_dir : str, optional
        sets the temp directory parent name
    destination_dir : str, optional
        This sets the directory where the resulting files with the backpropagated wcs' are put. If None this defaults
        to './filtername_aligned'
    manual_shifts : dict or tuple
        Either a dictionary mapping dra ddec shifts to individual images in the set or a tuple with a global dra and
        ddec that should be applied to all the frames collectively
    verbose : bool
        whether to output drizzle resutls
    file_suffix : str, optional
        suffix to append to the file name(s)
    """
    self.images = [
        Image(file_name, verbose=verbose, file_suffix=file_suffix)
        for file_name in file_list
    ]
    self.verbose = verbose
    self.drz_config = drizzle_config
    self.filtername = filtername
    self.drz_source_dir = Path(working_dir) / "drz_source" / filtername
    self.drz_target_dir = Path(working_dir) / "drz_target" / filtername
    self.manual_shifts = manual_shifts

    # Set up destination files
    self.destination_dir = destination_dir
    if self.destination_dir is not None:
        self.destination_dir = Path(destination_dir)
        self.destination_dir.mkdir(parents=True, exist_ok=True)
    else:
        self.destination_dir = Path("./{}_aligned".format(filter))
        self.destination_dir.mkdir(parents=True, exist_ok=True)

    # set up drizzle files
    self.drz_source_dir.mkdir(parents=True, exist_ok=True)
    self.drz_target_dir.mkdir(parents=True, exist_ok=True)

apply_manual_shifts()

Take a manual shift and apply it to either all images collectively or to each individual frame

Source code in crocoa/filemanagement.py
def apply_manual_shifts(self):
    """Take a manual shift and apply it to either all images collectively or to each individual frame"""
    # First parse to understand if we have a collective change or not
    if self.manual_shifts is None:
        if self.verbose:
            print("No manual shifts specified")
        pass

    if isinstance(self.manual_shifts, dict):
        for image in self.images:
            if image in self.manual_shifts.keys():
                # Add the shift to the working copy
                image.shift_working_copy_wcs(
                    self.manual_shifts[image]["dra"],
                    self.manual_shifts[image]["ddec"],
                )
                # also add it to the target
                image.backpropagate_wcs(
                    self.manual_shifts[image]["dra"],
                    self.manual_shifts[image]["ddec"],
                )
    elif isinstance(self.manual_shifts, tuple):
        for image in self.images:
            image.shift_working_copy_wcs(
                self.manual_shifts[0], self.manual_shifts[1]
            )
            image.backpropagate_wcs(self.manual_shifts[0], self.manual_shifts[1])

backpropagate_wcs_shift(dra, ddec)

propagate the found wcs offset to all images

Source code in crocoa/filemanagement.py
def backpropagate_wcs_shift(self, dra, ddec):
    """propagate the found wcs offset to all images"""
    for image in self.images:
        image.backpropagate_wcs(dra, ddec)

clean_temp_directories()

Remove drizzling directories

Source code in crocoa/filemanagement.py
def clean_temp_directories(self):
    """Remove drizzling directories"""
    shutil.rmtree(self.drz_source_dir)
    shutil.rmtree(self.drz_target_dir)

drizzle(individual=False)

Run the drizzling process

Source code in crocoa/filemanagement.py
def drizzle(self, individual=False):
    """Run the drizzling process"""
    self.drizzled_files = []
    if individual:
        for image in self.working_source:
            if self.verbose:
                adriz(
                    input=[image],
                    output=str(
                        self.drz_target_dir / os.path.basename(image).split(".")[0]
                    ),
                    **self.drz_config
                )
            else:
                with suppress_stdout_stderr():
                    adriz(
                        input=[image],
                        output=str(
                            self.drz_target_dir
                            / os.path.basename(image).split(".")[0]
                        ),
                        **self.drz_config
                    )
            self.drizzled_files.append(
                list(self.drz_target_dir.glob(
                    os.path.basename(image).split(".")[0] + "*sci*.fits"
                ))[0]
            )
    else:
        # if not individual we need subdirectories in the drz_target directory
        drz_target = self.drz_target_dir / self.filtername
        drz_target.mkdir(parents=True, exist_ok=True)

        if self.verbose:
            adriz(
                input=self.working_source,
                output=str(drz_target),
                **self.drz_config
            )
        else:
            with suppress_stdout_stderr():
                adriz(
                    input=self.working_source,
                    output=str(drz_target),
                    **self.drz_config
                )
        # get the resulting drizzled file(s)
        self.drizzled_files = list(self.drz_target_dir.glob("*sci*.fits"))

make_all_copies()

Create all relevant file copies

Source code in crocoa/filemanagement.py
def make_all_copies(self):
    """Create all relevant file copies"""
    self.make_target_copies()
    self.make_driz_source()

make_driz_source()

Make source file copies since drizzle changes the source files it's run on

Source code in crocoa/filemanagement.py
def make_driz_source(self):
    """Make source file copies since drizzle changes the source files it's run on"""
    self.working_source = []
    for image in self.images:
        image.make_working_copy(self.drz_source_dir)
        self.working_source.append(str(image.working_copy))

make_target_copies()

Make target file copies

Source code in crocoa/filemanagement.py
def make_target_copies(self):
    """Make target file copies"""
    for img in self.images:
        img.make_target_copy(self.destination_dir)

Diagnostics

Function that produces some convenient comparison files and plots

Parameters:

Name Type Description Default
aligned_files list

list of the aligned files to evaluate

required
target_dir str or Path

where the diagnostics should be saved

required
drz_config dict

drizzle configuration keywords

required
temp_dir str or Path, optional

temporary directory where intermediate drizzle files are put

'./temp'
cleanup bool, optional, default True

whether to clean drizzle products from the target_dir. WARNING: this will clear other fits files as well.

True
combine bool, optional, default False False
filter

required if combine is True

None
Source code in crocoa/filemanagement.py
def make_diagnostics(aligned_files, target_dir, drz_config, temp_dir='./temp', cleanup=True, combine=False, filter=None):
    """ Function that produces some convenient comparison files and plots
    Parameters
    ----------
    aligned_files : list
        list of the aligned files to evaluate
    target_dir : str or Path
        where the diagnostics should be saved
    drz_config : dict
        drizzle configuration keywords
    temp_dir : str or Path, optional
        temporary directory where intermediate drizzle files are put
    cleanup : bool, optional, default True
        whether to clean drizzle products  from the target_dir. 
        WARNING: this will clear other fits files as well.
    combine : bool, optional, default False
    filter: str, optional
        required if combine is True
    """
    if isinstance(target_dir, Path):
        pass
    else:
        target_dir = Path(target_dir)

    if isinstance(temp_dir, Path):
        pass
    else:
        temp_dir = Path(temp_dir)

    target_dir.mkdir(parents=True, exist_ok=True)
    temp_dir.mkdir(parents=True, exist_ok=True)

    images = [Image(file) for file in aligned_files]
    working_source = []
    for image in images:
        image.make_working_copy(temp_dir)
        working_source.append(str(image.working_copy))

    # Drizzle them

    sci_files = []
    if combine:
        if filter is None:
            raise ValueError('filter must be set')
        with suppress_stdout_stderr():
            adriz(
                input=working_source,
                output=str(target_dir / filter),
                **drz_config
            )
        sci_files = list(target_dir.glob("*sci*.fits"))
    else:
        for image in working_source:
            with suppress_stdout_stderr():
                adriz(
                    input=[image],
                    output=str(
                        target_dir
                        / os.path.basename(image).split(".")[0]
                    ),
                    **drz_config
                )
            sci_files.append(
                list(target_dir.glob(
                    os.path.basename(image).split(".")[0] + "*sci*.fits"
                ))[0]
            )

    # Get rid of non_sci files
    if cleanup:
        for file in target_dir.glob('*.fits'):
            if file in sci_files:
                pass
            else:
                os.remove(file)

    # Lets make some difference images
    if len(sci_files)>1:
        reference_image = sci_files.pop(0)
        refdata = fits.getdata(reference_image)

        n_figs = len(sci_files)
        axis_labels = string.ascii_lowercase[:n_figs]
        fig, axes = plt.subplot_mosaic(axis_labels, figsize=(4*n_figs, 4))

        for i,label in enumerate(axis_labels):
            data = fits.getdata(sci_files[i])
            diff = (refdata / np.max(refdata)) - (data/np.max(data))

            axes[label].imshow(diff, cmap='bwr', vmin=-1, vmax=1)
            axes[label].set_title(sci_files[i])

        plt.tight_layout()
        plt.savefig(target_dir / 'difference_images.pdf')

    if cleanup:
        shutil.rmtree(temp_dir)