diff --git a/attune/curve/_base.py b/attune/curve/_base.py
index 71d2ae9..e3982a4 100644
--- a/attune/curve/_base.py
+++ b/attune/curve/_base.py
@@ -57,7 +57,12 @@ class Curve:
 
         self.__version__ = __version__
         self.setpoints = setpoints
-        self.dependents = {d.name: d for d in dependents}
+        if isinstance(dependents, Dependent):
+            dependents = [dependents]
+        if isinstance(dependents, dict):
+            self.dependents = dependents
+        else:
+            self.dependents = {d.name: d for d in dependents}
         self.name = name
         self.kind = kind
         self.subcurve = subcurve
@@ -65,7 +70,7 @@ class Curve:
         self.interaction = interaction
         # set dependents as attributes of self
         for obj in self.dependents.values():
-            if len(obj[:]) != len(self.setpoints[:]):
+            if len(obj) != len(self.setpoints):
                 raise ValueError("Dependents must be the same length as setpoints")
             setattr(self, obj.name, obj)
         # initialize function object
@@ -119,6 +124,16 @@ class Curve:
     def __getitem__(self, key):
         return self.dependents[key]
 
+    def __setitem__(self, key, value):
+        value = copy_.deepcopy(value)
+        value.name = key
+        if value.interpolator is not None:
+            value.positions = value(self.setpoints[:], self.setpoints.units)
+        elif len(value) != len(self.setpoints):
+            raise ValueError(f"Incorrect number of points in dependent: {len(value)} for number of setpoints: {len(self.setpoints)}")
+        value.interpolator = self.method(self.setpoints, value)
+        self.dependents[key] = value
+
     def __call__(self, value, units=None, full=True):
         return self.get_dependent_positions(value, units, full=full)
 
@@ -498,7 +513,7 @@ class Curve:
         else:
             save_directory = pathlib.Path(save_directory)
         # array
-        out_arr = np.zeros([len(self.dependents) + 1, len(self.setpoints[:])])
+        out_arr = np.zeros([len(self.dependents) + 1, len(self.setpoints)])
         out_arr[0] = self.setpoints[:]
         out_arr[1:] = np.array([dependent.positions for dependent in self.dependents.values()])
         # filename
diff --git a/attune/curve/_dependent.py b/attune/curve/_dependent.py
index 2e31b92..6c79722 100644
--- a/attune/curve/_dependent.py
+++ b/attune/curve/_dependent.py
@@ -15,6 +15,9 @@ class Variable(object):
     def __setitem__(self, key, value):
         self.positions[key] = value
 
+    def __len__(self):
+        return len(self.positions)
+
     def convert(self, units):
         self.positions = wt.units.convert(self.positions, self.units, units)
         self.units = units

method to add dependent(s) to curve
diff --git a/tests/Curve/setitem.py b/tests/Curve/setitem.py
new file mode 100644
index 0000000..e56caa0
--- /dev/null
+++ b/tests/Curve/setitem.py
@@ -0,0 +1,40 @@
+import attune
+import numpy as np
+import pytest
+
+def test_set_new():
+    d = attune.Dependent(np.linspace(0,10,21), "d1")
+    s = attune.Setpoints(np.linspace(120, 240, 21), "s1")
+    c = attune.Curve(s, d, "c")
+    d = attune.Dependent(np.linspace(10,100,21), "d2")
+
+    c["d3"] = d
+
+    assert "d3" in c.dependents
+    assert "d2" not in c.dependents
+    assert np.allclose(c["d3"][:], d[:])
+    assert c["d3"].name == "d3"
+
+def test_set_incompatable():
+    d = attune.Dependent(np.linspace(0,10,21), "d1")
+    s = attune.Setpoints(np.linspace(120, 240, 21), "s1")
+    c = attune.Curve(s, d, "c")
+    d = attune.Dependent(np.linspace(10,100,25), "d2")
+
+    with pytest.raises(ValueError):
+        c["d3"] = d
+
+def test_set_from_outside_curve():
+    d = attune.Dependent(np.linspace(0,10,21), "d1")
+    s = attune.Setpoints(np.linspace(120, 240, 21), "s1")
+    c = attune.Curve(s, d, "c")
+    d = attune.Dependent(np.linspace(10,100,30), "d2")
+    s = attune.Setpoints(np.linspace(100, 250, 30), "s2")
+    c2 = attune.Curve(s, d, "c")
+
+    c["d3"] = c2["d2"]
+
+    assert "d3" in c.dependents
+    assert "d2" not in c.dependents
+    assert np.allclose(c["d3"][:], d(c.setpoints[:]))
+    assert c["d3"].name == "d3"

pip install -e .[dev]
parse_log_pytest
requirements.txt
cython pytest pytest-cov
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/wright-group/attune.git@b24175ac58d2b590b6b2d4419904c00bdb9f3509#egg=attune
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
Cython==3.0.12
distlib==0.3.9
exceptiongroup==1.2.2
filelock==3.12.2
fonttools==4.38.0
h5py==3.8.0
identify==2.5.24
imageio==2.31.2
importlib-metadata==6.7.0
iniconfig==2.0.0
kiwisolver==1.4.5
markdown-it-py==2.2.0
matplotlib==3.5.3
mdurl==0.1.2
mypy-extensions==1.0.0
nodeenv==1.9.1
numexpr==2.8.6
numpy==1.21.6
packaging==24.0
pathspec==0.11.2
Pillow==9.5.0
Pint==0.18
platformdirs==4.0.0
pluggy==1.2.0
pre-commit==2.21.0
Pygments==2.17.2
pyparsing==3.1.4
pytest==7.4.4
pytest-cov==4.1.0
python-dateutil==2.9.0.post0
PyYAML==6.0.1
rich==13.8.1
scipy==1.7.3
six==1.17.0
swebench-matterhorn @ file:///swebench_matterhorn
tidy_headers==1.0.3
tomli==2.0.1
typed-ast==1.5.5
typing_extensions==4.7.1
virtualenv==20.26.6
WrightTools==3.5.3
zipp==3.15.0

name: attune
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
  - certifi=2022.12.7=py37h06a4308_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
  - pip=22.3.1=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
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - 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
      - cython==3.0.12
      - distlib==0.3.9
      - exceptiongroup==1.2.2
      - filelock==3.12.2
      - fonttools==4.38.0
      - h5py==3.8.0
      - identify==2.5.24
      - imageio==2.31.2
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - kiwisolver==1.4.5
      - markdown-it-py==2.2.0
      - matplotlib==3.5.3
      - mdurl==0.1.2
      - mypy-extensions==1.0.0
      - nodeenv==1.9.1
      - numexpr==2.8.6
      - numpy==1.21.6
      - packaging==24.0
      - pathspec==0.11.2
      - pillow==9.5.0
      - pint==0.18
      - platformdirs==4.0.0
      - pluggy==1.2.0
      - pre-commit==2.21.0
      - pygments==2.17.2
      - pyparsing==3.1.4
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - python-dateutil==2.9.0.post0
      - pyyaml==6.0.1
      - rich==13.8.1
      - scipy==1.7.3
      - six==1.17.0
      - swebench-matterhorn==0.0.0
      - tidy-headers==1.0.3
      - tomli==2.0.1
      - typed-ast==1.5.5
      - typing-extensions==4.7.1
      - virtualenv==20.26.6
      - wrighttools==3.5.3
      - zipp==3.15.0
prefix: /opt/conda/envs/attune

tests/Curve/setitem.py::test_set_new tests/Curve/setitem.py::test_set_incompatable tests/Curve/setitem.py::test_set_from_outside_curve
attune/curve/_base.py attune/curve/_dependent.py
attune/curve/_base.py attune/curve/_dependent.py