diff --git a/WrightTools/data/_channel.py b/WrightTools/data/_channel.py
index 91a04ed..03d4973 100644
--- a/WrightTools/data/_channel.py
+++ b/WrightTools/data/_channel.py
@@ -152,14 +152,17 @@ class Channel(Dataset):
 
         factor : number (optional)
             Tolerance factor.  Default is 3.
-        replace : {'nan', 'mean', number} (optional)
+        replace : {'nan', 'mean', 'exclusive_mean', number} (optional)
             Behavior of outlier replacement. Default is nan.
 
             nan
                 Outliers are replaced by numpy nans.
 
             mean
-                Outliers are replaced by the mean of its neighborhood.
+                Outliers are replaced by the mean of its neighborhood, including itself.
+
+            exclusive_mean
+                Outilers are replaced by the mean of its neighborhood, not including itself.
 
             number
                 Array becomes given number.
@@ -177,6 +180,7 @@ class Channel(Dataset):
         warnings.warn("trim", category=wt_exceptions.EntireDatasetInMemoryWarning)
         outliers = []
         means = []
+        ex_means = []
         # find outliers
         for idx in np.ndindex(self.shape):
             slices = []
@@ -186,26 +190,33 @@ class Channel(Dataset):
                 slices.append(slice(start, stop, 1))
             neighbors = self[slices]
             mean = np.nanmean(neighbors)
+            sum_ = np.nansum(neighbors)
             limit = np.nanstd(neighbors) * factor
             if np.abs(self[idx] - mean) > limit:
                 outliers.append(idx)
                 means.append(mean)
+                # Note, "- 1" is to exclude the point itself, which is not nan, in order
+                # to enter this if block, as `np.abs(nan - mean)` is nan, which would
+                # evaluate to False
+                ex_means.append((sum_ - self[idx]) / (np.sum(~np.isnan(neighbors)) - 1))
+
         # replace outliers
         i = tuple(zip(*outliers))
-        if replace == "nan":
-            arr = self[:]
-            arr[i] = np.nan
-            self[:] = arr
-        elif replace == "mean":
-            arr = self[:]
-            arr[i] = means
-            self[:] = arr
-        elif isinstance(replace, numbers.Number):
-            arr = self[:]
-            arr[i] = replace
-            self[:] = arr
-        else:
-            raise KeyError("replace must be one of {nan, mean} or some number")
+
+        if len(i) == 0:
+            if verbose:
+                print("No outliers found")
+            return []
+
+        replace = {"nan": np.nan, "mean": means, "exclusive_mean": ex_means}.get(replace, replace)
+
+        # This may someday be available in h5py directly, but seems that day is not yet.
+        # This is annoying because it is the only reason we hold the whole set in memory.
+        # KFS 2019-03-21
+        arr = self[:]
+        arr[i] = replace
+        self[:] = arr
+
         # finish
         if verbose:
             print("%i outliers removed" % len(outliers))

BUG: Trim writes channel to all NaNs when no outliers are present
Example code:
```
# import
import numpy as np
from matplotlib import pyplot as plt
import WrightTools as wt
# create arrays
x = np.linspace(-3, 3, 31)[:, None]
y = np.linspace(-3, 3, 31)[None, :]
arr = np.exp(-1 * (x ** 2 + y ** 2))
# create damaged array
arr2 = arr.copy()
arr2[15,15] = 20
# create data object
d = wt.data.Data()
d.create_variable("x", values=x)
d.create_variable("y", values=y)
d.create_channel("original", arr)
d.create_channel("damaged", arr2)
d.create_channel("trimmed", arr2)
d.create_channel("broken", arr)
d.transform("x", "y")
# now trim
d.trimmed.trim([2,2]) # this one works as expected
d.broken.trim([2,2]) # this one will write the channel to all NaNs
# create figure
fig, gs = wt.artists.create_figure(cols=[1, 1, 1, 1])
for i in range(4):
    ax = plt.subplot(gs[i])
    ax.pcolor(d, channel=i)
    ax.set_title(d.channel_names[i])
# pretty up
ticks = [-2, 0, 2]
wt.artists.set_fig_labels(
    xlabel=d.axes[0].label, ylabel=d.axes[1].label, xticks=ticks, yticks=ticks
)
```
stdout from execution is
```
1 outliers removed
0 outliers removed
/home/darien/source/WrightTools/WrightTools/_dataset.py:373: RuntimeWarning: All-NaN slice encountered
  return np.nanmax(dataset[s])
/home/darien/source/WrightTools/WrightTools/_dataset.py:375: RuntimeWarning: All-NaN axis encountered
  self.attrs["max"] = np.nanmax(list(self.chunkwise(f).values()))
```
![image](https://user-images.githubusercontent.com/15792657/54384984-8c3c9d00-4663-11e9-971b-e911f95489d3.png)

diff --git a/tests/data/trim.py b/tests/data/trim.py
index 2a94167..f096904 100644
--- a/tests/data/trim.py
+++ b/tests/data/trim.py
@@ -32,18 +32,23 @@ def test_trim_2Dgauss():
     d.create_channel("damaged1", arr2)
     d.create_channel("damaged2", arr2)
     d.create_channel("damaged3", arr2)
+    d.create_channel("damaged4", arr2)
     d.transform("x", "y")
     # trim
+    d.original.trim([2, 2], factor=2)
     d.damaged1.trim([2, 2], factor=2)
     d.damaged2.trim([2, 2], factor=2, replace="mean")
     d.damaged3.trim([2, 2], factor=2, replace=0.5)
+    d.damaged4.trim([2, 2], factor=2, replace="exclusive_mean")
     # now heal
     d.create_channel("healed_linear", d.damaged1[:])
     d.heal(channel="healed_linear", fill_value=0, method="linear")
     # check
-    assert np.allclose(d.original[:], d.healed_linear[:], rtol=1e-1, atol=1e-1)
-    assert np.allclose(d.original[:], d.damaged2[:], rtol=1e-1, atol=9e-1)
-    assert np.allclose(d.original[:], d.damaged3[:], rtol=1e-1, atol=5e-1)
+    np.testing.assert_allclose(d.original[:], d.original[:], rtol=1e-1, atol=1e-1)
+    np.testing.assert_allclose(d.original[:], d.healed_linear[:], rtol=1e-1, atol=1e-1)
+    np.testing.assert_allclose(d.original[:], d.damaged2[:], rtol=1e-1, atol=9e-1)
+    np.testing.assert_allclose(d.original[:], d.damaged3[:], rtol=1e-1, atol=5e-1)
+    np.testing.assert_allclose(d.original[:], d.damaged4[:], rtol=1e-1, atol=3e-1)
 
 
 def test_trim_3Dgauss():
@@ -67,7 +72,7 @@ def test_trim_3Dgauss():
     # trim
     d.damaged.trim([2, 2, 2], factor=2, replace="mean")
     # check
-    assert np.allclose(d.original[:], d.damaged[:], rtol=1e-1, atol=9e-1)
+    np.testing.assert_allclose(d.original[:], d.damaged[:], rtol=1e-1, atol=9e-1)
 
 
 if __name__ == "__main__":

pip install -e .[dev]
parse_log_pytest
pytest
pytest pytest-cov
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
black==23.3.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
cfgv==3.3.1
click==8.1.8
coverage==7.2.7
cycler==0.11.0
distlib==0.3.9
filelock==3.12.2
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
fonttools==4.38.0
h5py==3.8.0
identify==2.5.24
imageio==2.31.2
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
kiwisolver==1.4.5
matplotlib==3.5.3
mypy-extensions==1.0.0
nodeenv==1.9.1
numexpr==2.8.6
numpy==1.21.6
packaging @ file:///croot/packaging_1671697413597/work
pathspec==0.11.2
Pillow==9.5.0
platformdirs==3.11.0
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
pre-commit==2.21.0
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pydocstyle==6.3.0
pyparsing==3.1.4
pytest==7.1.2
pytest-cov==4.1.0
python-dateutil==2.9.0.post0
PyYAML==6.0.1
scipy==1.7.3
six==1.17.0
snowballstemmer==2.2.0
tidy_headers==1.0.3
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typed-ast==1.5.5
typing_extensions==4.7.1
virtualenv==20.21.1
-e git+https://github.com/wright-group/WrightTools.git@dc02147913c603792e8a7c12228dc292334d8084#egg=WrightTools
zipp @ file:///croot/zipp_1672387121353/work

name: WrightTools
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
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_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=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - black==23.3.0
      - cfgv==3.3.1
      - click==8.1.8
      - coverage==7.2.7
      - cycler==0.11.0
      - distlib==0.3.9
      - filelock==3.12.2
      - fonttools==4.38.0
      - h5py==3.8.0
      - identify==2.5.24
      - imageio==2.31.2
      - kiwisolver==1.4.5
      - matplotlib==3.5.3
      - mypy-extensions==1.0.0
      - nodeenv==1.9.1
      - numexpr==2.8.6
      - numpy==1.21.6
      - pathspec==0.11.2
      - pillow==9.5.0
      - platformdirs==3.11.0
      - pre-commit==2.21.0
      - pydocstyle==6.3.0
      - pyparsing==3.1.4
      - pytest-cov==4.1.0
      - python-dateutil==2.9.0.post0
      - pyyaml==6.0.1
      - scipy==1.7.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - tidy-headers==1.0.3
      - typed-ast==1.5.5
      - typing-extensions==4.7.1
      - virtualenv==20.21.1
prefix: /opt/conda/envs/WrightTools

tests/data/trim.py::test_trim_2Dgauss
tests/data/trim.py::test_trim_3Dgauss
WrightTools/data/_channel.py
WrightTools/data/_channel.py