diff --git a/CHANGES.rst b/CHANGES.rst
index 8c3abdd..dc7f4c0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -24,6 +24,9 @@
 
 - Add comments to ``WCSNAMEa`` header keywords. [#143]
 
+- Added ``archive_wcs()`` function with more advanced control over how to
+  archive primary WCS and with more capabilities, such as auto-renaming. [#153]
+
 
 1.5.3 (2019-09-23)
 ------------------
diff --git a/stwcs/updatewcs/__init__.py b/stwcs/updatewcs/__init__.py
index b104ce3..0ec53ba 100644
--- a/stwcs/updatewcs/__init__.py
+++ b/stwcs/updatewcs/__init__.py
@@ -187,7 +187,8 @@ def makecorr(f, allowed_corr):
                 ext_wcs = wcsutil.HSTWCS(fobj=f, ext=i)
                 # check if it exists first!!!
                 # 'O ' can be safely archived again because it has been restored first.
-                wcsutil.archiveWCS(f, ext=i, wcskey="O", wcsname="OPUS", reusekey=True)
+                wcsutil.archive_wcs(f, ext=i, wcskey="O", wcsname="OPUS",
+                                    mode=wcsutil.ArchiveMode.OVERWRITE_KEY)
 
                 ext_wcs.readModel(update=True, header=hdr)
                 for c in allowed_corr:
diff --git a/stwcs/wcsutil/altwcs.py b/stwcs/wcsutil/altwcs.py
index 174733c..cddcad1 100644
--- a/stwcs/wcsutil/altwcs.py
+++ b/stwcs/wcsutil/altwcs.py
@@ -1,4 +1,5 @@
 import string
+from enum import IntFlag
 
 import numpy as np
 from astropy import wcs as pywcs
@@ -14,7 +15,7 @@ default_log_level = log.getEffectiveLevel()
 
 __all__ = ["archiveWCS", "available_wcskeys", "convertAltWCS", "deleteWCS", "next_wcskey",
            "pc2cd", "readAltWCS", "restoreWCS", "wcskeys", "wcsnames",
-           "wcs_from_key"]
+           "wcs_from_key", "archive_wcs", "ArchiveMode"]
 
 
 altwcskw = ['WCSAXES', 'CRVAL', 'CRPIX', 'PC', 'CDELT', 'CD', 'CTYPE', 'CUNIT',
@@ -25,9 +26,22 @@ altwcskw_extra = ['LATPOLE', 'LONPOLE', 'RESTWAV', 'RESTFRQ']
 # that need to be archived/restored with the rest of WCS here:
 STWCS_KWDS = ['WCSTYPE', 'RMS_RA', 'RMS_DEC', 'NMATCH', 'FITNAME', 'HDRNAME', 'ORIENTAT']
 
+_DEFAULT_WCSNAME = 'ARCHIVED_WCS'
+
 # file operations
 
 
+class ArchiveMode(IntFlag):
+    NO_CONFLICT = 0  # Fail if WCS key or name already exists (unless identical WCS)
+    AUTO_RENAME = 1  # rename primary WCS if same name is already used by an Alt WCS (to keep Alt WCS names unique)
+    OVERWRITE_KEY = 2  # overwrite an existing Alt WCS
+    QUIET_ABORT = 4  # quit if conflicts without raising exceptions
+
+AM = ArchiveMode
+
+
+@deprecated(since='1.6.0', message='', name='archiveWCS',
+            alternative='archive_wcs')
 def archiveWCS(fname, ext, wcskey=" ", wcsname=" ", reusekey=False):
     """
     Copy the primary WCS to the header as an alternate WCS
@@ -67,95 +81,354 @@ def archiveWCS(fname, ext, wcskey=" ", wcsname=" ", reusekey=False):
     wcsutil.restoreWCS: Copy an alternate WCS to the primary WCS
 
     """
-    if wcsname.strip() == '':
-        wcsname = ' '
+    mode = AM.OVERWRITE_KEY if reusekey else AM.NO_CONFLICT
+    archive_wcs(fname, ext, wcskey=wcskey, wcsname=wcsname, mode=mode)
+
+
+def archive_wcs(fname, ext, wcskey=None, wcsname=None, mode=ArchiveMode.NO_CONFLICT):
+    """
+    Copy the primary WCS to the header as an alternate WCS
+    with the specified ``wcskey`` and name ``wcsname``.
+    It loops over all extensions in 'ext'.
+
+    Parameters
+    ----------
+    fname :  string or `astropy.io.fits.HDUList`
+        File name or a `astropy.io.fits.HDUList` whose primary WCS need to be
+        archived.
+
+    ext : int, tuple, str, or list of integers or tuples (e.g.('sci',1))
+        Specifies FITS extensions whose primary WCS should be archived.
+
+        If a string is provided, it should specify the EXTNAME of extensions
+        with WCSs to be archived
+
+    wcskey : {'A'-'Z'}, None, optional
+        When ``wcskey`` is `None`, and ``wcsname`` is not `None` and an
+        alternate WCS exist with the same name as ``wcsname``, the key of
+        this alernate WCS will be used for ``wcskey``. If ``wcsname`` is unique,
+        the next available key will be used. If ``wcskey`` is a letter ``'A'-'Z'``,
+        the primary WCS will be archived to the indicated key. If an
+        alternate WCS with the specified key already exist an exception will be
+        raisen unless mode includes either flag ``ArchiveMode.OVERWRITE_KEY`` or
+        ``ArchiveMode.QUIET_ABORT``.
+
+    wcsname : str, None, optional
+        Name of alternate WCS description. If `None`, the WCS name will be
+        initially set to the name of the primary WCS if available. If primary
+        WCS does not have ``'WCSNAME'`` set and provided ``wcskey`` is not
+        `None` and a WCS with this key already exists in the header, the name
+        of this alternate WCS will be used. I this alternate WCS does not have
+        ``'WCSNAME'`` set and provided, a default WCS name will be used.
+
+        .. note::
+            An exception will be raisen if an alternate WCS with provided
+            name already exists in image's headers unless ``mode`` includes
+            ``ArchiveMode.AUTO_RENAME`` flag in which case ``wcsname`` will be
+            automatically adjusted to be unique.
+
+    mode : int, optional
+        An integer mask containing one or more flags from ``ArchiveMode``:
+
+        - ``NO_CONFLICT``: Archive only when provided WCS key or name
+          do not conflict with existing alternate WCS or when existing
+          alternate WCS is identical to the primary WCS being archived.
+
+        - ``AUTO_RENAME``: Rename primary WCS if same name is already used
+          by an alternate WCS (in order to keep alternate WCS names unique).
+
+        - ``OVERWRITE_KEY``: Overwrite an existing alternate WCS with the
+          same key as ``wcskey``.
+
+        - ``QUIET_ABORT``: Stop archiving and quit if conflicts exists
+          without raising exceptions.
+
+    Returns
+    -------
+    wcs_id : tuple (str or None, str or None)
+        Returns effective WCS key and name used for the archived WCS.
+        If archival failed due to conflicts, and ``mode`` was set to
+        ``ArchiveMode.QUIET_ABORT`` a tuple of ``(None, None)`` will be returned.
+
+    """
+    if wcsname is not None and not isinstance(wcsname, str):
+        raise TypeError("'wcsname' must be a string")
 
-    if len(wcskey) != 1 or wcskey.strip() not in string.ascii_letters:
+    if (wcskey is not None and
+            ((not isinstance(wcskey, str) or len(wcskey) != 1 or
+              wcskey.strip() not in string.ascii_uppercase))):
         raise ValueError(
             "Parameter 'wcskey' must be a character - one of 'A'-'Z' or ' '."
         )
 
     if isinstance(fname, str):
-        f = fits.open(fname, mode='update')
+        # open file:
+        h = fits.open(fname, mode='update')
+        close_hdulist = True
     else:
-        f = fname
+        h = fname
+        close_hdulist = False
 
-    if not _parpasscheck(f, ext, wcskey, wcsname):
-        closefobj(fname, f)
-        raise ValueError("Input parameters problem")
+        # validate file object and open mode:
+        if not isinstance(h, fits.HDUList):
+            if close_hdulist:
+                h.close()
+            raise TypeError("'fname' must be either a FITS file object or a string file name.")
 
-    # Interpret input 'ext' value to get list of extensions to process
-    ext = _buildExtlist(f, ext)
+        if h.fileinfo(0) is not None and h.fileinfo(0)['filemode'] != 'update':
+            if close_hdulist:
+                h.close()
+            raise ValueError("'fname' must be a file object opened in 'update' mode.")
+
+    # validate and interpret extension(s):
+    try:
+        if isinstance(ext, list):
+            map(_validate_ext, ext)
+        else:
+            _validate_ext(ext)
+            ext = [ext]
 
-    if wcsname == ' ':
-        wcsname = wcs_from_key(f, ext[0]).get('WCSNAME', ' ')
+    except ValueError as e:
+        if close_hdulist:
+            h.close()
+        raise e
 
     wcsext = ext[0]
-    if wcskey != " " and wcskey in wcskeys(f[wcsext].header) and not reusekey:
-        closefobj(fname, f)
-        raise KeyError(f"Wcskey '{wcskey}' is aready used. \
-        Run archiveWCS() with reusekey=True to overwrite this alternate WCS. \
-        Alternatively choose another wcskey with altwcs.available_wcskeys().")
-
-    elif wcskey == " ":
-        # wcsname exists, overwrite it if reuse is True or get the next key
-        if wcsname in _alt_wcs_names(f[wcsext].header).values():
-            if reusekey:
-                # try getting the key from an existing WCS with WCSNAME
-                wkey = getKeyFromName(f[wcsext].header, wcsname)
-                wname = wcsname
-                if wkey == ' ':
-                    wkey = _next_wcskey(f[wcsext].header)
-                elif wkey is None:
-                    closefobj(fname, f)
-                    raise KeyError(f"Could not get a valid wcskey from wcsname '{wcsname:s}'")
+    hdr = h[wcsext].header
+
+    wcs_names = _alt_wcs_names(hdr)
+    wcs_names_u = {k: v.upper() for k, v in wcs_names.items()}
+    wcsname_u = None if wcsname is None else wcsname.upper()
+    wcs_keys = wcskeys(h, wcsext)
+
+    # validate and process mode:
+    if mode & ~sum(AM):
+        raise ValueError("Unrecognized 'mode' flag.")
+    overwrite_key = bool(mode & AM.OVERWRITE_KEY)
+    auto_rename = bool(mode & AM.AUTO_RENAME)
+
+    wcs_id = (None, None)
+
+    # do not overwrite OPUS WCS if present regardless of 'mode':
+    if wcskey == 'O' and wcskey in wcs_keys:
+        if close_hdulist:
+            h.close()
+        log.debug("WCS name 'OPUS' already exists and cannot be overwritten.")
+        return wcs_id
+
+    elif wcsname == 'OPUS' and wcsname in wcs_names_u.values():
+        if close_hdulist:
+            h.close()
+        log.debug("WCS name 'OPUS' already exists and cannot be overwritten.")
+        return wcs_id
+
+    if wcsname is None:
+        if 'WCSNAME' in hdr:
+            # use WCS name of the primary WCS if available:
+            wcsname = hdr['WCSNAME']
+            if not wcsname.strip():
+                wcsname = _DEFAULT_WCSNAME
+                auto_rename = True
+
+        elif wcs_names:
+            # use the name of the Alt WCS with largest key:
+            wcsname = wcs_names[max(wcs_names.keys())]
+            auto_rename = True
+
+        else:
+            # assign default name
+            wcsname = _DEFAULT_WCSNAME
+            auto_rename = True
+
+    elif wcsname_u in wcs_names_u.values():
+        if (wcskey is not None and wcskey in wcs_names and
+                wcsname_u != wcs_names_u[wcskey] and not auto_rename):
+            msg = (
+                "'wcsname' must be unique in image header. Provided 'wcsname' "
+                "was already used for an alternate WCS with a different key "
+                "than the supplied 'wcskey'. Add ArchiveMode.AUTO_RENAME flag "
+                "to 'mode' in order to allow 'archive_wcs()' to modify "
+                "'wcsname' to be unique."
+            )
+
+            if AM.QUIET_ABORT:
+                log.warning(msg)
+                return wcs_id
             else:
-                closefobj(fname, f)
-                raise KeyError(
-                    f"Wcsname '{wcsname}' is aready used. Run archiveWCS() "
-                    "with reusekey=True to overwrite this alternate WCS. "
-                    "Alternatively choose another wcskey with "
-                    "altwcs.available_wcskeys() or choose another wcsname."
+                raise ValueError(msg)
+
+        elif wcskey is None:
+            # pick the key that corresponds to the provided WCS name:
+            key_match = sorted([k for k, v in wcs_names_u.items() if v == wcsname_u])[-1]
+
+            if _test_wcs_equal(h, wcsext, ' ', key_match) or overwrite_key:
+                wcskey = key_match
+
+            elif not auto_rename:
+                msg = (
+                    "'wcsname' must be unique in image header. Provided 'wcsname' "
+                    "was already used by an alternate WCS. Add either "
+                    "ArchiveMode.AUTO_RENAME flag to 'mode' in order to allow "
+                    "'archive_wcs()' to modify 'wcsname' to be unique or "
+                    "ArchiveMode.OVERWRITE_KEY flag in order to allow "
+                    "'archive_wcs()' to overwrite an existing WCS."
                 )
+                if AM.QUIET_ABORT:
+                    log.warning(msg)
+                    return wcs_id
+                else:
+                    raise ValueError(msg)
 
         else:
-            wkey = _next_wcskey(f[wcsext].header)
-            if wcsname != ' ':
-                wname = wcsname
-            else:
-                # determine which WCSNAME needs to be replicated in archived WCS
-                wnames = _alt_wcs_names(f[wcsext].header)
-
-                if len(wnames) > 0:
-                    if ' ' in wnames:
-                        wname = wnames[' ']
-                    else:
-                        akeys = string.ascii_uppercase
-                        wname = "DEFAULT"
-                        for key in akeys[-1::]:
-                            if key in wnames:
-                                wname = wnames
-                                break
+            if wcskey in wcs_keys and not overwrite_key:
+                msg = (f"Alternate WCS with WCS key '{key_match}' is "
+                       "already present in header. To overwrite an "
+                       "existing WCS add ArchiveMode.OVERWRITE_KEY flag "
+                       "to 'mode'."
+                )
+                if AM.QUIET_ABORT:
+                    log.warning(msg)
+                    return wcs_id
                 else:
-                    wname = "DEFAULT"
+                    raise ValueError(msg)
+
     else:
-        wkey = wcskey
-        wname = wcsname
+        auto_rename = False
+
+    if wcskey is None:
+        wcskey = _next_wcskey(hdr)
+
+    # check if name is present in Alt WCS and if renaming is allowed:
+    if auto_rename:
+        wcsname = _auto_increment_wcsname(wcsname, wcs_names.values())
 
     log.setLevel('WARNING')
 
+    wcs_id = (wcskey, wcsname)
+
     for e in ext:
-        hwcs = wcs_from_key(f, e, from_key=' ', to_key=wkey)
+        hwcs = wcs_from_key(h, e, from_key=' ', to_key=wcskey)
 
-        if not hwcs:
+        if hwcs is None:
             continue
 
-        hwcs.set(f'WCSNAME{wkey:.1s}', wname, 'Coordinate system title', before=0)
+        # remove old WCS if present:
+        if wcskey in wcs_keys:
+            hwcs = wcs_from_key(h, e, from_key=wcskey)
+            for k in hwcs:
+                if k in h[e].header:
+                    del h[e].header[k]
+
+        hwcs.set(f'WCSNAME{wcskey:.1s}', wcsname, 'Coordinate system title', before=0)
 
-        f[e].header.update(hwcs)
+        h[e].header.update(hwcs)
 
     log.setLevel(default_log_level)
-    closefobj(fname, f)
+    if close_hdulist:
+        h.close()
+
+    return wcs_id
+
+
+def _validate_ext(ext):
+    if not (isinstance(ext, int) or isinstance(ext, str) or
+            (isinstance(ext, tuple) and len(ext) == 2 and
+             isinstance(ext[0], str) and isinstance(ext[1], int))):
+        raise ValueError(
+            "'ext' must be int, str, or a tuple of the form (extname, extver), "
+            "where, extname is a string and extver is an integer number."
+        )
+
+
+def _auto_increment_wcsname(wcsname, alt_names):
+    """
+    Examples
+    --------
+    >>> altwcs._auto_increment_wcsname('IDC', ['IDC_A'])
+    'IDC'
+
+    >>> altwcs._auto_increment_wcsname('IDC', ['IDC_A', 'IDC'])
+    'IDC-1'
+
+    >>> altwcs._auto_increment_wcsname('IDC', ['IDC_A', 'IDC', 'IDC-1'])
+    'IDC-2'
+
+    >>> altwcs._auto_increment_wcsname('IDC-1', ['IDC_A', 'IDC', 'IDC-1'])
+    'IDC-2'
+
+    >>> altwcs._auto_increment_wcsname('IDC-2', ['IDC_A', 'IDC', 'IDC-1'])
+    'IDC-2'
+
+    >>> altwcs._auto_increment_wcsname('IDC_A', ['IDC_A', 'IDC', 'IDC-1'])
+    'IDC_A-1'
+
+    """
+    separators = ['-', '_', ' ']  # in this order. First separator defines default
+    wcsname_u = wcsname.upper()
+    alt_names_u = [n.upper() for n in alt_names]
+    if wcsname_u not in alt_names_u:
+        return wcsname
+
+    def find_counters(wname_u):
+        num = {k: [] for k in separators}
+        wname_u_len = len(wname_u)
+        for name in alt_names_u:
+            if name.startswith(wname_u) and len(name) > wname_u_len:
+                for sep in separators:
+                    if name[wname_u_len] == sep:
+                        num_str = name[wname_u_len+1:]
+                        if '_' not in num_str:
+                            try:
+                                num[sep].append(int(num_str))
+                                break
+                            except:
+                                pass
+        return num
+
+    # figure out if wcsname ends in numbers:
+    idx = max(wcsname.rfind(sep) for sep in separators)
+
+    if idx >= 0:
+        try:
+            num_str = wcsname[idx + 1:].replace('_', '-')
+            wcs_num = int(num_str)
+            separator = wcsname[idx]
+            wcsname_root = wcsname[:idx]
+            wcsname_root_u = wcsname_root.upper()
+
+            num = find_counters(wcsname_root_u)
+            for sep in separators:
+                if num[sep]:
+                    max_num = max(num[sep]) + 1
+                    return f'{wcsname_root}{separator}{max_num:d}'
+            return f'{wcsname_root}{separator}{wcs_num + 1:d}'
+
+        except Exception as e:
+            pass
+
+    num = find_counters(wcsname_u)
+    for sep in separators:
+        if num[sep]:
+            max_num = max(num[sep]) + 1
+            return f'{wcsname}{sep}{max_num:d}'
+
+    return f'{wcsname:s}{separators[0]}1'
+
+
+def _test_wcs_equal(h, ext, wcskey1, wcskey2):
+    hwcs1 = wcs_from_key(h, ext, from_key=wcskey1, to_key=' ')
+    if 'WCSNAME' in hwcs1:
+        del hwcs1['WCSNAME']
+
+    hwcs2 = wcs_from_key(h, ext, from_key=wcskey2, to_key=' ')
+    if 'WCSNAME' in hwcs2:
+        del hwcs2['WCSNAME']
+
+    sdiff = set(c.image for c in hwcs1.cards).symmetric_difference(
+        c.image for c in hwcs2.cards
+    )
+
+    return not bool(sdiff)
 
 
 def restore_from_to(f, fromext=None, toext=None, wcskey=" ", wcsname=" "):
@@ -559,7 +832,7 @@ def wcs_from_key(fobj, ext, from_key=' ', to_key=None):
     return hwcs
 
 
-@deprecated(since='1.5.4', message='', name='readAltWCS',
+@deprecated(since='1.6.0', message='', name='readAltWCS',
             alternative='wcs_from_key')
 def readAltWCS(fobj, ext, wcskey=' ', verbose=False):
     """
@@ -585,7 +858,7 @@ def readAltWCS(fobj, ext, wcskey=' ', verbose=False):
     return hwcs if hwcs else None
 
 
-@deprecated(since='1.5.4', message='', name='convertAltWCS',
+@deprecated(since='1.6.0', message='', name='convertAltWCS',
             alternative='wcs_from_key')
 def convertAltWCS(fobj, ext, oldkey=' ', newkey=' '):
     """
diff --git a/stwcs/wcsutil/convertwcs.py b/stwcs/wcsutil/convertwcs.py
index e745c2e..e58c1eb 100644
--- a/stwcs/wcsutil/convertwcs.py
+++ b/stwcs/wcsutil/convertwcs.py
@@ -46,7 +46,7 @@ def archive_prefix_OPUS_WCS(fobj, extname='SCI'):
     # Insure that the 'O' alternate WCS is present
     if 'O' not in wcsutil.wcskeys(hdr):
         # if not, archive the Primary WCS as the default OPUS WCS
-        wcsutil.archiveWCS(fobj, extlist, wcskey='O', wcsname='OPUS')
+        wcsutil.archive_wcs(fobj, extlist, wcskey='O', wcsname='OPUS')
 
     # find out how many SCI extensions are in the image
     numextn = fileutil.countExtn(fobj, extname=extname)
diff --git a/stwcs/wcsutil/headerlet.py b/stwcs/wcsutil/headerlet.py
index c7b616a..ce2de87 100644
--- a/stwcs/wcsutil/headerlet.py
+++ b/stwcs/wcsutil/headerlet.py
@@ -1970,15 +1970,16 @@ class Headerlet(fits.HDUList):
                         else:
                             priwcs_name = 'UNKNOWN'
                 nextkey = altwcs._next_wcskey(fobj[target_ext].header)
-                altwcs.archiveWCS(fobj, ext=sciext_list, wcskey=nextkey,
-                                  wcsname=priwcs_name)
+                altwcs.archive_wcs(fobj, ext=sciext_list, wcskey=nextkey,
+                                   wcsname=priwcs_name)
+
             else:
                 for hname in altwcs._alt_wcs_names(fobj[target_ext].header).values():
                     if hname not in hdrlet_extnames:
                         nextkey = altwcs._next_wcskey(fobj[target_ext].header)
                         # Archive original WCS as alternate WCS with its own key
-                        altwcs.archiveWCS(fobj, ext=sciext_list, wcskey=nextkey,
-                                  wcsname=hname)
+                        altwcs.archive_wcs(fobj, ext=sciext_list,
+                                           wcskey=nextkey, wcsname=hname)
 
                         # create HeaderletHDU for alternate WCS now
                         alt_hlet = create_headerlet(fobj, sciext=sciext_list,
diff --git a/stwcs/wcsutil/wcscorr.py b/stwcs/wcsutil/wcscorr.py
index b2edbb1..9d44076 100644
--- a/stwcs/wcsutil/wcscorr.py
+++ b/stwcs/wcsutil/wcscorr.py
@@ -97,7 +97,7 @@ def init_wcscorr(input, force=False):
         # if so, get its values directly, otherwise, archive the PRIMARY WCS
         # as the OPUS values in the WCSCORR table
         if 'O' not in used_wcskeys:
-            altwcs.archiveWCS(fimg, ('SCI', extver), wcskey='O', wcsname='OPUS')
+            altwcs.archive_wcs(fimg, ('SCI', extver), wcskey='O', wcsname='OPUS')
         wkey = 'O'
 
         wcs = stwcs.wcsutil.HSTWCS(fimg, ext=('SCI', extver), wcskey=wkey)

Strange code in altwcs
There is a very strange line of code in `stwcs.wcsutil.altwcs.py`:

https://github.com/spacetelescope/stwcs/blob/cb361e6e1b9cd64c4ce9e4dc032713fc9a034b2e/stwcs/wcsutil/altwcs.py#L121

It is a loop that loops only over the last element:

```python
>>> for k in ['a', 'b', 'c'][-1::]:
>>>    print(k)
c
```

CC: @stsci-hack @nden 
diff --git a/stwcs/tests/test_altwcs.py b/stwcs/tests/test_altwcs.py
index 4e8bc59..0892f6a 100644
--- a/stwcs/tests/test_altwcs.py
+++ b/stwcs/tests/test_altwcs.py
@@ -5,7 +5,7 @@ from ..wcsutil import altwcs
 from .. import updatewcs
 from .. import wcsutil
 import numpy as np
-from numpy.testing import utils
+from numpy import testing
 import pytest
 
 from . import data
@@ -39,11 +39,11 @@ def compare_wcs(w1, w2, exclude_keywords=None):
     for kw in keywords:
         kw1 = getattr(w1.wcs, kw)
         kw2 = getattr(w2.wcs, kw)
-        utils.assert_allclose(kw1, kw2, 1e-10)
-    #utils.assert_allclose(w1.wcs.crpix, w2.wcs.crpix, 1e-10)
-    #utils.assert_allclose(w1.wcs.cd, w2.wcs.cd, 1e-10)
+        testing.assert_allclose(kw1, kw2, 1e-10)
+    # testing.assert_allclose(w1.wcs.crpix, w2.wcs.crpix, 1e-10)
+    # testing.assert_allclose(w1.wcs.cd, w2.wcs.cd, 1e-10)
     if not exclude_ctype:
-        utils.assert_array_equal(np.array(w1.wcs.ctype), np.array(w2.wcs.ctype))
+        testing.assert_array_equal(np.array(w1.wcs.ctype), np.array(w2.wcs.ctype))
 
 class TestAltWCS(object):
 
@@ -75,13 +75,15 @@ class TestAltWCS(object):
         self.ww = wcsutil.HSTWCS(self.acs_file, ext=1)
 
     def test_archive(self):
-        altwcs.archiveWCS(self.acs_file, ext=1, wcskey='Z', wcsname='ZTEST', reusekey=False)
+        altwcs.archive_wcs(self.acs_file, ext=1, wcskey='Z', wcsname='ZTEST',
+                           mode=altwcs.ArchiveMode.OVERWRITE_KEY)
         w1 = wcsutil.HSTWCS(self.acs_file, ext=1)
         w1z = wcsutil.HSTWCS(self.acs_file, ext=1, wcskey='Z')
         compare_wcs(w1, w1z)
 
     def test_archive_clobber(self):
-        altwcs.archiveWCS(self.acs_file, ext=1, wcskey='Z', wcsname='ZTEST', reusekey=True)
+        altwcs.archive_wcs(self.acs_file, ext=1, wcskey='Z', wcsname='ZTEST',
+                           mode=altwcs.ArchiveMode.OVERWRITE_KEY)
         w1 = wcsutil.HSTWCS(self.acs_file, ext=1)
         w1z = wcsutil.HSTWCS(self.acs_file, ext=1, wcskey='Z')
         compare_wcs(w1, w1z)
@@ -95,7 +97,7 @@ class TestAltWCS(object):
 
     def test_restore_wcs_mem(self):
         # test restore on an HDUList object
-        altwcs.archiveWCS(self.acs_file, ext=[('SCI', 1), ('SCI', 2)], wcskey='T')
+        altwcs.archive_wcs(self.acs_file, ext=[('SCI', 1), ('SCI', 2)], wcskey='T')
         pyfits.setval(self.acs_file, ext=('SCI', 1), keyword='CRVAL1', value=1)
         pyfits.setval(self.acs_file, ext=('SCI', 2), keyword='CRVAL1', value=1)
         f = pyfits.open(self.acs_file, mode='update')
@@ -107,7 +109,7 @@ class TestAltWCS(object):
 
     def test_restore_simple(self):
         # test restore on simple fits format
-        altwcs.archiveWCS(self.simplefits, ext=0, wcskey='R')
+        altwcs.archive_wcs(self.simplefits, ext=0, wcskey='R')
         pyfits.setval(self.simplefits, ext=0, keyword='CRVAL1R', value=1)
         altwcs.restoreWCS(self.simplefits, ext=0, wcskey='R')
         wo = wcsutil.HSTWCS(self.simplefits, ext=0, wcskey='R')
diff --git a/stwcs/tests/test_updatewcs.py b/stwcs/tests/test_updatewcs.py
index 4de9bca..b227e99 100644
--- a/stwcs/tests/test_updatewcs.py
+++ b/stwcs/tests/test_updatewcs.py
@@ -8,7 +8,7 @@ from ..updatewcs import apply_corrections
 from ..distortion import utils as dutils
 from ..wcsutil import HSTWCS
 import numpy as np
-from numpy.testing import utils
+from numpy import testing
 import pytest
 
 
@@ -56,10 +56,10 @@ class TestStwcs(object):
         crpix = np.array([0., 0.])
         cdelt = np.array([1., 1.])
         pc = np.array([[1., 0], [0., 1.]])
-        utils.assert_equal(self.w.wcs.crval, crval)
-        utils.assert_equal(self.w.wcs.crpix, crpix)
-        utils.assert_equal(self.w.wcs.pc, pc)
-        utils.assert_equal(self.w.wcs.cdelt, cdelt)
+        testing.assert_equal(self.w.wcs.crval, crval)
+        testing.assert_equal(self.w.wcs.crpix, crpix)
+        testing.assert_equal(self.w.wcs.pc, pc)
+        testing.assert_equal(self.w.wcs.cdelt, cdelt)
         assert((self.w.wcs.ctype == np.array(['', ''])).all())
 
     def test_simple_sci1(self):
@@ -89,7 +89,7 @@ class TestStwcs(object):
         fpx1 = dpx1 + (self.w1.sip_pix2foc(dpx1, 1)-dpx1+self.w1.wcs.crpix) + \
             (self.w1.p4_pix2foc(dpx1, 1)-dpx1)
         pipelinepx1 = self.w1.wcs_pix2world(fpx1, 1)
-        utils.assert_almost_equal(pipelinepx1, sky1)
+        testing.assert_almost_equal(pipelinepx1, sky1)
 
     def test_pipeline_sci2(self):
         """
@@ -101,7 +101,7 @@ class TestStwcs(object):
         fpx4 = dpx4 + (self.w4.sip_pix2foc(dpx4, 1)-dpx4 + self.w4.wcs.crpix) + \
             (self.w4.p4_pix2foc(dpx4, 1)-dpx4)
         pipelinepx4 = self.w4.wcs_pix2world(fpx4, 1)
-        utils.assert_almost_equal(pipelinepx4, sky4)
+        testing.assert_almost_equal(pipelinepx4, sky4)
 
     def test_outwcs(self):
         """
@@ -110,11 +110,11 @@ class TestStwcs(object):
         outwcs = dutils.output_wcs([self.w1, self.w4])
 
         #print('outwcs.wcs.crval = {0}'.format(outwcs.wcs.crval))
-        utils.assert_allclose(
+        testing.assert_allclose(
             outwcs.wcs.crval, np.array([5.65109952, -72.0674181]), atol=1e-7)
 
-        utils.assert_almost_equal(outwcs.wcs.crpix, np.array([2107.0, 2118.5]))
-        utils.assert_almost_equal(
+        testing.assert_almost_equal(outwcs.wcs.crpix, np.array([2107.0, 2118.5]))
+        testing.assert_almost_equal(
             outwcs.wcs.cd,
             np.array([[1.2787045268089949e-05, 5.4215042082174661e-06],
                       [5.4215042082174661e-06, -1.2787045268089949e-05]]))
@@ -127,18 +127,18 @@ class TestStwcs(object):
         w4 = HSTWCS(self.acs_file, ext=('SCI', 2))
         w1r = HSTWCS(self.ref_file, ext=('SCI', 1))
         w4r = HSTWCS(self.ref_file, ext=('SCI', 2))
-        utils.assert_almost_equal(w1.wcs.crval, w1r.wcs.crval)
-        utils.assert_almost_equal(w1.wcs.crpix, w1r.wcs.crpix)
-        utils.assert_almost_equal(w1.wcs.cd, w1r.wcs.cd)
+        testing.assert_almost_equal(w1.wcs.crval, w1r.wcs.crval)
+        testing.assert_almost_equal(w1.wcs.crpix, w1r.wcs.crpix)
+        testing.assert_almost_equal(w1.wcs.cd, w1r.wcs.cd)
         assert((np.array(w1.wcs.ctype) == np.array(w1r.wcs.ctype)).all())
-        utils.assert_almost_equal(w1.sip.a, w1r.sip.a)
-        utils.assert_almost_equal(w1.sip.b, w1r.sip.b)
-        utils.assert_almost_equal(w4.wcs.crval, w4r.wcs.crval)
-        utils.assert_almost_equal(w4.wcs.crpix, w4r.wcs.crpix)
-        utils.assert_almost_equal(w4.wcs.cd, w4r.wcs.cd)
+        testing.assert_almost_equal(w1.sip.a, w1r.sip.a)
+        testing.assert_almost_equal(w1.sip.b, w1r.sip.b)
+        testing.assert_almost_equal(w4.wcs.crval, w4r.wcs.crval)
+        testing.assert_almost_equal(w4.wcs.crpix, w4r.wcs.crpix)
+        testing.assert_almost_equal(w4.wcs.cd, w4r.wcs.cd)
         assert((np.array(self.w4.wcs.ctype) == np.array(w4r.wcs.ctype)).all())
-        utils.assert_almost_equal(w4.sip.a, w4r.sip.a)
-        utils.assert_almost_equal(w4.sip.b, w4r.sip.b)
+        testing.assert_almost_equal(w4.sip.a, w4r.sip.a)
+        testing.assert_almost_equal(w4.sip.b, w4r.sip.b)
 
 
 def test_remove_npol_distortion():

pip install -e .[all]
parse_log_pytest
pytest
pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
astropy==6.0.1
astropy-iers-data==0.2025.3.31.0.36.18
certifi==2025.1.31
charset-normalizer==3.4.1
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
idna==3.10
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
lxml==5.3.1
numpy==1.26.4
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
pyerfa==2.0.1.5
pytest @ file:///croot/pytest_1738938843180/work
PyYAML==6.0.2
requests==2.32.3
stsci.tools==4.2.0
-e git+https://github.com/spacetelescope/stwcs.git@831ea8a5ba0e78fb668a792ecccca0321eb41df1#egg=stwcs
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
urllib3==2.3.0

name: stwcs
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - astropy==6.0.1
      - astropy-iers-data==0.2025.3.31.0.36.18
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - idna==3.10
      - lxml==5.3.1
      - numpy==1.26.4
      - pyerfa==2.0.1.5
      - pyyaml==6.0.2
      - requests==2.32.3
      - stsci-tools==4.2.0
      - urllib3==2.3.0
prefix: /opt/conda/envs/stwcs

stwcs/tests/test_altwcs.py::TestAltWCS::test_archive stwcs/tests/test_altwcs.py::TestAltWCS::test_archive_clobber stwcs/tests/test_altwcs.py::TestAltWCS::test_restore_wcs_mem stwcs/tests/test_altwcs.py::TestAltWCS::test_restore_simple stwcs/tests/test_altwcs.py::TestAltWCS::test_restore_wcs_from_to stwcs/tests/test_altwcs.py::TestAltWCS::test_delete_wcs
stwcs/tests/test_altwcs.py::TestAltWCS::test_restore_wcs stwcs/tests/test_altwcs.py::TestAltWCS::test_pars_file_mode1 stwcs/tests/test_altwcs.py::TestAltWCS::test_pars_file_mode2 stwcs/tests/test_altwcs.py::TestAltWCS::test_pars_ext stwcs/tests/test_altwcs.py::TestAltWCS::test_pars_wcskey_not1char stwcs/tests/test_altwcs.py::TestAltWCS::test_pars_wcskey stwcs/tests/test_updatewcs.py::TestStwcs::test_default stwcs/tests/test_updatewcs.py::TestStwcs::test_simple_sci1 stwcs/tests/test_updatewcs.py::TestStwcs::test_simple_sci2 stwcs/tests/test_updatewcs.py::TestStwcs::test_pipeline_sci1 stwcs/tests/test_updatewcs.py::TestStwcs::test_pipeline_sci2 stwcs/tests/test_updatewcs.py::TestStwcs::test_outwcs stwcs/tests/test_updatewcs.py::TestStwcs::test_repeate stwcs/tests/test_updatewcs.py::test_remove_npol_distortion stwcs/tests/test_updatewcs.py::test_remove_npol_distortion_hdulist stwcs/tests/test_updatewcs.py::test_remove_d2im_distortion stwcs/tests/test_updatewcs.py::test_missing_idctab stwcs/tests/test_updatewcs.py::test_missing_npolfile stwcs/tests/test_updatewcs.py::test_missing_d2imfile stwcs/tests/test_updatewcs.py::test_found_idctab stwcs/tests/test_updatewcs.py::test_add_radesys stwcs/tests/test_updatewcs.py::test_update_d2im_distortion stwcs/tests/test_updatewcs.py::test_apply_d2im stwcs/tests/test_updatewcs.py::test_update_waiver_wfpc2 stwcs/tests/test_updatewcs.py::test_update_stis_asn
stwcs/wcsutil/altwcs.py stwcs/updatewcs/__init__.py stwcs/wcsutil/headerlet.py stwcs/wcsutil/wcscorr.py CHANGES.rst stwcs/wcsutil/convertwcs.py
stwcs/wcsutil/altwcs.py stwcs/updatewcs/__init__.py stwcs/wcsutil/headerlet.py stwcs/wcsutil/wcscorr.py CHANGES.rst stwcs/wcsutil/convertwcs.py