diff --git a/qutil/domains.py b/qutil/domains.py
index 74b23cbe6720b467e6127fbb768286b06dd50de0..61c00e12b1c7b51b930ecb55856e9cf495f74eac 100644
--- a/qutil/domains.py
+++ b/qutil/domains.py
@@ -337,21 +337,21 @@ class DiscreteInterval(Interval[_IntegralT], Bounded[_IntegralT]):
             return ceil(self.min())
         if value > self:
             return floor(self.max())
-        return round(value)
+        return round(self.round(value))
 
     def next_smallest(self, value: _RealT) -> int:
         if value < self:
             return ceil(self.min())
         if value > self:
             return floor(self.max())
-        return floor(value)
+        return floor(self.round(value))
 
     def next_largest(self, value: _RealT) -> int:
         if value < self:
             return ceil(self.min())
         if value > self:
             return floor(self.max())
-        return ceil(value)
+        return ceil(self.round(value))
 
 
 class ContinuousInterval(Interval[_RealT]):
diff --git a/qutil/misc.py b/qutil/misc.py
index 6653fa75ed738640b1f393af8c16344f01d8d829..4b37f01988ff427fd6dafd5c497e855c921a1c47 100644
--- a/qutil/misc.py
+++ b/qutil/misc.py
@@ -5,7 +5,7 @@ import logging
 import sys
 import time
 import warnings
-from collections.abc import Callable, Hashable, Iterator, MutableMapping
+from collections.abc import Callable, Hashable, Iterator, Mapping, MutableMapping, Sequence
 from contextlib import contextmanager
 from importlib import import_module
 from types import ModuleType
@@ -300,16 +300,26 @@ def timeout(value: float, on_exceeded: Callable[[float], None] | None = None,
             raise TimeoutError(msg.format(exceeded.elapsed))
 
 
-def deprecate_kwarg(old: str, new: str | None = None):
-    """Decorator factory to deprecate the keyword argument *old*.
+def deprecate_kwargs(*args, **kwargs):
+    """Decorator factory to deprecate keyword arguments.
 
-    Optionally in favor of *new*.
+    Optionally in favor of replacements.
+
+    Parameters
+    ----------
+    *args :
+        Positional arguments should be valid identifiers that will be
+        treated as keyword arguments to be deprecated without
+        replacement.
+    **kwargs :
+        Key-value pairs of keyword arguments that should be deprecated
+        *with* replacement: ``{old: new}``.
 
     Examples
     --------
     Deprecate a kwarg in favor of a new name:
 
-    >>> @deprecate_kwarg('old', 'new')
+    >>> @deprecate_kwargs(old='new')
     ... def foo(new=3):
     ...     print(new)
 
@@ -328,7 +338,7 @@ def deprecate_kwarg(old: str, new: str | None = None):
 
     Only deprecate a kwarg without giving a replacement:
 
-    >>> @deprecate_kwarg('old')
+    >>> @deprecate_kwargs('old')
     ... def foo(new=3):
     ...     print(new)
 
@@ -347,26 +357,53 @@ def deprecate_kwarg(old: str, new: str | None = None):
     ...
     TypeError: foo() got an unexpected keyword argument 'old'
 
+    Multiple deprecations:
+
+    >>> @deprecate_kwargs(old1='new1', old2='new2')
+    ... def foo(new1=3, new2=4):
+    ...     print(new1, new2)
+    >>> with filter_warnings(action='error', category=DeprecationWarning):
+    ...     foo(old1=4)
+    Traceback (most recent call last):
+    ...
+    DeprecationWarning: Keyword argument 'old1' of foo is deprecated. Use 'new1' instead.
+    >>> with filter_warnings(action='error', category=DeprecationWarning):
+    ...     foo(old2=5)
+    Traceback (most recent call last):
+    ...
+    DeprecationWarning: Keyword argument 'old2' of foo is deprecated. Use 'new2' instead.
+
     """
 
     def decorator(func):
 
         @wraps(func)
-        def wrapped(*args, **kwargs):
-            if old not in kwargs:
-                return func(*args, **kwargs)
-
-            msg = f"Keyword argument '{old}' of {func.__qualname__} is deprecated."
-            if new is not None:
-                if new in kwargs:
-                    raise TypeError(msg + f" Cannot also specify '{new}'.")
-                else:
-                    msg = msg + f" Use '{new}' instead."
-                    kwargs[new] = kwargs.pop(old)
-
-            warnings.warn(msg, DeprecationWarning, stacklevel=2)
-            return func(*args, **kwargs)
+        def wrapped(*a, **kw):
+            def _handle_single(o, n=None):
+                if o not in kw:
+                    return
+
+                msg = f"Keyword argument '{o}' of {func.__qualname__} is deprecated."
+                if n is not None:
+                    if n in kw:
+                        raise TypeError(msg + f" Cannot also specify '{n}'.")
+                    else:
+                        msg = msg + f" Use '{n}' instead."
+                        kw[n] = kw.pop(o)
+
+                warnings.warn(msg, DeprecationWarning, stacklevel=3)
+
+            for arg in args:
+                _handle_single(arg)
+            for old, new in kwargs.items():
+                _handle_single(old, new)
+            return func(*a, **kw)
 
         return wrapped
 
     return decorator
+
+
+@deprecated('Use deprecate_kwargs instead')
+def deprecate_kwarg(old: str, new: str | None = None):
+    return deprecate_kwargs(old=new)
diff --git a/qutil/signal_processing/fourier_space.py b/qutil/signal_processing/fourier_space.py
index 05643a953501a7d5e3f3622bce581b0fac76debd..85ede1e986486328543e19d2144a00476f69c9f8 100644
--- a/qutil/signal_processing/fourier_space.py
+++ b/qutil/signal_processing/fourier_space.py
@@ -48,7 +48,7 @@ from scipy import integrate
 from qutil import math
 from qutil.caching import cache
 from qutil.functools import wraps
-from qutil.misc import deprecate_kwarg
+from qutil.misc import deprecate_kwargs
 from qutil.signal_processing._common import _parse_filter_edges
 from qutil.typecheck import check_literals
 
@@ -115,7 +115,7 @@ def Id(x: _S, f: _T, *_, **__) -> tuple[_S, _T]:
     return x, f
 
 
-@deprecate_kwarg('deriv_order', 'order')
+@deprecate_kwargs(deriv_order='order')
 def derivative(x, f, order: int = 0, overwrite_x: bool = False,
                **_) -> tuple[np.ndarray, np.ndarray]:
     r"""Compute the (anti-)derivative.
diff --git a/qutil/ui/gate_layout/core.py b/qutil/ui/gate_layout/core.py
index 7e5add7def890a587f36030c6cfdd537a85f3a8f..74fe595252a6568006dc0ce1603b0c2c04f52993 100644
--- a/qutil/ui/gate_layout/core.py
+++ b/qutil/ui/gate_layout/core.py
@@ -3,6 +3,7 @@ Created on Mon Apr 25 11:14:02 2022
 
 @author: Hangleiter
 """
+import logging
 import pathlib
 import warnings
 from itertools import compress
@@ -21,12 +22,11 @@ try:
 except ImportError:
     ezdxf = None
 
-
 DEFAULT_TEXT_KWARGS = dict(backgroundcolor='black',
                            horizontalalignment='center',
                            verticalalignment='center',
                            color='white', fontsize=8)
-
+LOG = logging.getLogger(__name__)
 
 
 class GateLayout:
@@ -49,11 +49,12 @@ class GateLayout:
             gate_mask = [True]*14 + [False, True, False, True, False, True, False, True]
 
         if len(gate_names) != len(gate_mask):
-            warnings.warn(f"Gate name number is different from gate mask number: {len(gate_names)} != {len(gate_mask)}",
-                          stacklevel=2)
+            warnings.warn("Gate name number is different from gate mask number: "
+                          f"{len(gate_names)} != {len(gate_mask)}", stacklevel=2)
 
         self.fig = plt.figure(fignum)
-        self.ax = self.fig.add_axes([0, 0, 1, 1])
+        self.fig.clear()
+        self.ax = self.fig.subplots()
         self.layout_file = layout_file
         self.gate_names = gate_names
         self.gate_mask = gate_mask
@@ -61,7 +62,7 @@ class GateLayout:
 
         self.background_color = matplotlib.colors.to_hex(background_color)
         self.foreground_color = matplotlib.colors.to_hex(foreground_color)
-        self.cmap = matplotlib.cm.get_cmap(cmap)
+        self.cmap = matplotlib.colormaps.get_cmap(cmap)
         self.norm = matplotlib.colors.Normalize(v_min, v_max)
         self.v_min = self.norm.vmin
         self.v_max = self.norm.vmax
@@ -100,7 +101,10 @@ class GateLayout:
             self.get_voltages(force)
         elif isinstance(voltages, dict):
             for gate, voltage in voltages.items():
-                self._latest_voltages[self.gate_names.index(gate)] = voltage
+                try:
+                    self._latest_voltages[self.gate_names.index(gate)] = voltage
+                except ValueError:
+                    LOG.warning(f'Gate not found. Skipping: {gate}')
         else:
             self._latest_voltages[:] = np.broadcast_to(voltages, self._latest_voltages.shape)
 
@@ -117,16 +121,18 @@ class GateLayout:
         return self._latest_voltages
 
     def _setup_figure(self):
-        vertices = get_vertices_from_dfx(self.layout_file, self.background_color, self.foreground_color)
+        vertices = get_vertices_from_dfx(self.layout_file, self.background_color,
+                                         self.foreground_color)
         if len(self.gate_names) != len(vertices):
-            warnings.warn(f"Found {len(vertices)} patches in file but got {len(self.gate_names)} gate names", stacklevel=2)
+            warnings.warn(f"Found {len(vertices)} patches in file but got {len(self.gate_names)} "
+                          "gate names", stacklevel=2)
 
         patches = []
         texts = []
         for idx, verts in enumerate(vertices):
             verts += self._offset[None, :]
-            patches.append(matplotlib.patches.Polygon(verts, True, zorder=0))
-            texts.append(matplotlib.text.Text(*verts.mean(axis=0), f'INIT', **self.text_kwargs))
+            patches.append(matplotlib.patches.Polygon(verts, closed=True, zorder=0))
+            texts.append(matplotlib.text.Text(*verts.mean(axis=0), 'INIT', **self.text_kwargs))
 
         all_coords = np.array([(patch.get_xy().mean(axis=0)) for patch in patches])
 
diff --git a/qutil/ui/gate_layout/qcodes.py b/qutil/ui/gate_layout/qcodes.py
index 1ce8fc9488dc7cfad6b8e2265cb9c8f739faac3c..44914172d17929762cf5b68c138d5417244310dc 100644
--- a/qutil/ui/gate_layout/qcodes.py
+++ b/qutil/ui/gate_layout/qcodes.py
@@ -17,6 +17,7 @@ class QcodesGateLayout(GateLayout):
         class MaskedGate(qc.Parameter):
             def __init__(self, name, *args, **kwargs):
                 super().__init__(name, *args, **kwargs)
+
             def get_raw(self):
                 return 0