Repository: tskit-dev/msprime (language: python)

Issue:
Change the model name for "wf_ped"
After taking some folks on a tour of the simulate-through-pedigree API there was universal agreement that the name "wf_ped" is unhelpful and confusing. The "Wright-Fisher" bit got in there because under the hood the details of how recombination happens is handled by the same code as the DTWF model, but actually this doesn't really have anything to do with a Wright-Fisher process.

So, any suggestions? Here are the [existing models](https://tskit.dev/msprime/docs/latest/ancestry.html#sec-ancestry-quickref) for reference.

The simplest and most obvious is to call the ancestry model class ``Pedigree()`` with a shorthand string "pedigree", but I wonder if this will confuse people into thinking that we are simulating a pedigree rather than simulating *within* a pedigree? Perhaps this confusion would be alleviated if we documented the ``sim_pedigree()`` function as part of the public API?


Discussion / hints:
`FixedPedigree` perhaps?
I like it!
``FixedPedigree`` sounds right for the class name, what should we call the short-cut string? "fixed_pedigree" is the obvious choice I guess?
> `FixedPedigree` sounds right for the class name, what should we call the short-cut string? "fixed_pedigree" is the obvious choice I guess?

Yes, make it as obvious as possible I reckon. We could also use "KnownPedigee", but I think "Fixed" is better.

Fix patch:
diff --git a/algorithms.py b/algorithms.py
index 2d197c3f7..a5885bf4b 100644
--- a/algorithms.py
+++ b/algorithms.py
@@ -824,7 +824,7 @@ def simulate(self, end_time):
             self.hudson_simulate(end_time)
         elif self.model == "dtwf":
             self.dtwf_simulate()
-        elif self.model == "wf_ped":
+        elif self.model == "fixed_pedigree":
             self.pedigree_simulate()
         elif self.model == "single_sweep":
             self.single_sweep_simulate()
@@ -2098,9 +2098,9 @@ def verify(self):
         Checks that the state of the simulator is consistent.
         """
         self.verify_segments()
-        if self.model != "wf_ped":
-            # The wf_ped model doesn't maintain a bunch of stuff. It would probably
-            # be simpler if it did.
+        if self.model != "fixed_pedigree":
+            # The fixed_pedigree model doesn't maintain a bunch of stuff.
+            # It would probably be simpler if it did.
             self.verify_overlaps()
             for label in range(self.num_labels):
                 if self.recomb_mass_index is None:
diff --git a/lib/dev-tools/dev-cli.c b/lib/dev-tools/dev-cli.c
index e9af2fe31..bc2542b09 100644
--- a/lib/dev-tools/dev-cli.c
+++ b/lib/dev-tools/dev-cli.c
@@ -313,8 +313,8 @@ read_model_config(msp_t *msp, config_t *config)
         ret = msp_set_simulation_model_smc_prime(msp);
     } else if (strcmp(name, "dtwf") == 0) {
         ret = msp_set_simulation_model_dtwf(msp);
-    } else if (strcmp(name, "wf_ped") == 0) {
-        ret = msp_set_simulation_model_wf_ped(msp);
+    } else if (strcmp(name, "fixed_pedigree") == 0) {
+        ret = msp_set_simulation_model_fixed_pedigree(msp);
     } else if (strcmp(name, "dirac") == 0) {
         s = config_setting_get_member(setting, "psi");
         if (s == NULL) {
diff --git a/lib/msprime.c b/lib/msprime.c
index c1730c092..e87893cbc 100644
--- a/lib/msprime.c
+++ b/lib/msprime.c
@@ -5349,7 +5349,7 @@ msp_get_model_name(msp_t *self)
             ret = "dtwf";
             break;
         case MSP_MODEL_WF_PED:
-            ret = "wf_ped";
+            ret = "fixed_pedigree";
             break;
         case MSP_MODEL_SWEEP:
             ret = "single-sweep";
@@ -7159,7 +7159,7 @@ msp_set_simulation_model_dtwf(msp_t *self)
 }
 
 int
-msp_set_simulation_model_wf_ped(msp_t *self)
+msp_set_simulation_model_fixed_pedigree(msp_t *self)
 {
     int ret;
     tsk_size_t j, k;
diff --git a/lib/msprime.h b/lib/msprime.h
index cc17b89c9..853f3af61 100644
--- a/lib/msprime.h
+++ b/lib/msprime.h
@@ -420,7 +420,7 @@ int msp_set_simulation_model_hudson(msp_t *self);
 int msp_set_simulation_model_smc(msp_t *self);
 int msp_set_simulation_model_smc_prime(msp_t *self);
 int msp_set_simulation_model_dtwf(msp_t *self);
-int msp_set_simulation_model_wf_ped(msp_t *self);
+int msp_set_simulation_model_fixed_pedigree(msp_t *self);
 int msp_set_simulation_model_dirac(msp_t *self, double psi, double c);
 int msp_set_simulation_model_beta(msp_t *self, double alpha, double truncation_point);
 int msp_set_simulation_model_sweep_genic_selection(msp_t *self, double position,
diff --git a/msprime/__init__.py b/msprime/__init__.py
index 2702a7284..729e75a56 100644
--- a/msprime/__init__.py
+++ b/msprime/__init__.py
@@ -44,7 +44,7 @@
     SmcPrimeApproxCoalescent,
     StandardCoalescent,
     SweepGenicSelection,
-    WrightFisherPedigree,
+    FixedPedigree,
 )
 
 from msprime.core import __version__
@@ -146,7 +146,7 @@
     "SmcPrimeApproxCoalescent",
     "StandardCoalescent",
     "SweepGenicSelection",
-    "WrightFisherPedigree",
+    "FixedPedigree",
     "log_arg_likelihood",
     "log_mutation_likelihood",
     "mutate",
diff --git a/msprime/_msprimemodule.c b/msprime/_msprimemodule.c
index 87f8b3ba5..3e647720f 100644
--- a/msprime/_msprimemodule.c
+++ b/msprime/_msprimemodule.c
@@ -1073,13 +1073,13 @@ Simulator_parse_simulation_model(Simulator *self, PyObject *py_model)
     PyObject *smc_s = NULL;
     PyObject *smc_prime_s = NULL;
     PyObject *dtwf_s = NULL;
-    PyObject *wf_ped_s = NULL;
+    PyObject *fixed_pedigree_s = NULL;
     PyObject *dirac_s = NULL;
     PyObject *beta_s = NULL;
     PyObject *sweep_genic_selection_s = NULL;
     PyObject *value;
     int is_hudson, is_dtwf, is_smc, is_smc_prime, is_dirac, is_beta,
-        is_sweep_genic_selection, is_wf_ped;
+        is_sweep_genic_selection, is_fixed_pedigree;
     double psi, c, alpha, truncation_point;
 
     hudson_s = Py_BuildValue("s", "hudson");
@@ -1090,8 +1090,8 @@ Simulator_parse_simulation_model(Simulator *self, PyObject *py_model)
     if (dtwf_s == NULL) {
         goto out;
     }
-    wf_ped_s = Py_BuildValue("s", "wf_ped");
-    if (wf_ped_s == NULL) {
+    fixed_pedigree_s = Py_BuildValue("s", "fixed_pedigree");
+    if (fixed_pedigree_s == NULL) {
         goto out;
     }
     smc_s = Py_BuildValue("s", "smc");
@@ -1138,12 +1138,12 @@ Simulator_parse_simulation_model(Simulator *self, PyObject *py_model)
     if (is_dtwf) {
         err = msp_set_simulation_model_dtwf(self->sim);
     }
-    is_wf_ped = PyObject_RichCompareBool(py_name, wf_ped_s, Py_EQ);
-    if (is_wf_ped == -1) {
+    is_fixed_pedigree = PyObject_RichCompareBool(py_name, fixed_pedigree_s, Py_EQ);
+    if (is_fixed_pedigree == -1) {
         goto out;
     }
-    if (is_wf_ped) {
-        err = msp_set_simulation_model_wf_ped(self->sim);
+    if (is_fixed_pedigree) {
+        err = msp_set_simulation_model_fixed_pedigree(self->sim);
     }
 
     is_smc = PyObject_RichCompareBool(py_name, smc_s, Py_EQ);
@@ -1221,7 +1221,7 @@ Simulator_parse_simulation_model(Simulator *self, PyObject *py_model)
     }
 
     if (! (is_hudson || is_dtwf || is_smc || is_smc_prime || is_dirac
-                || is_beta || is_sweep_genic_selection || is_wf_ped)) {
+                || is_beta || is_sweep_genic_selection || is_fixed_pedigree)) {
         PyErr_SetString(PyExc_ValueError, "Unknown simulation model");
         goto out;
     }
@@ -1233,7 +1233,7 @@ Simulator_parse_simulation_model(Simulator *self, PyObject *py_model)
 out:
     Py_XDECREF(hudson_s);
     Py_XDECREF(dtwf_s);
-    Py_XDECREF(wf_ped_s);
+    Py_XDECREF(fixed_pedigree_s);
     Py_XDECREF(smc_s);
     Py_XDECREF(smc_prime_s);
     Py_XDECREF(beta_s);
diff --git a/msprime/ancestry.py b/msprime/ancestry.py
index 408e6471f..9feac2e96 100644
--- a/msprime/ancestry.py
+++ b/msprime/ancestry.py
@@ -60,7 +60,7 @@ def _model_factory(model: None | str | AncestryModel) -> AncestryModel:
         "smc": SmcApproxCoalescent(),
         "smc_prime": SmcPrimeApproxCoalescent(),
         "dtwf": DiscreteTimeWrightFisher(),
-        "wf_ped": WrightFisherPedigree(),
+        "fixed_pedigree": FixedPedigree(),
     }
     if model is None:
         model_instance = StandardCoalescent()
@@ -865,7 +865,7 @@ def _parse_sim_ancestry(
 
     models = _parse_model_arg(model)
     is_dtwf = isinstance(models[0], DiscreteTimeWrightFisher)
-    is_pedigree = any(isinstance(model, WrightFisherPedigree) for model in models)
+    is_pedigree = any(isinstance(model, FixedPedigree) for model in models)
 
     if is_pedigree:
         if demography is not None:
@@ -1693,7 +1693,7 @@ class DiscreteTimeWrightFisher(AncestryModel):
     name = "dtwf"
 
 
-class WrightFisherPedigree(AncestryModel):
+class FixedPedigree(AncestryModel):
     # TODO Complete documentation.
     # TODO Since the pedigree is a necessary parameter for this simulation
     # model and it cannot be used with any other model we should make it a
@@ -1701,10 +1701,10 @@ class WrightFisherPedigree(AncestryModel):
     # streamline a bunch of logic.
     """
     Backwards-time simulations through a pre-specified pedigree, with diploid
-    individuals and back-and-forth recombination. The string ``"wf_ped"`` can
+    individuals and back-and-forth recombination. The string ``"fixed_pedigree"`` can
     be used to refer to this model.
     """
-    name = "wf_ped"
+    name = "fixed_pedigree"
 
 
 class ParametricAncestryModel(AncestryModel):


Test patch:
diff --git a/lib/tests/test_pedigrees.c b/lib/tests/test_pedigrees.c
index da80f04ca..b40614e27 100644
--- a/lib/tests/test_pedigrees.c
+++ b/lib/tests/test_pedigrees.c
@@ -739,7 +739,7 @@ test_errors(void)
     tables.nodes.time[0] = 0.001;
     CU_ASSERT_EQUAL_FATAL(msp_alloc(&msp, &tables, rng), 0);
     CU_ASSERT_EQUAL_FATAL(msp_set_ploidy(&msp, 2), 0);
-    ret = msp_set_simulation_model_wf_ped(&msp);
+    ret = msp_set_simulation_model_fixed_pedigree(&msp);
     CU_ASSERT_EQUAL_FATAL(ret, MSP_ERR_PEDIGREE_IND_NODE_TIME_DISAGREE);
     tsk_table_collection_free(&tables);
     msp_free(&msp);
@@ -753,7 +753,7 @@ test_errors(void)
     tables.nodes.population[0] = 1;
     CU_ASSERT_EQUAL_FATAL(msp_alloc(&msp, &tables, rng), 0);
     CU_ASSERT_EQUAL_FATAL(msp_set_ploidy(&msp, 2), 0);
-    ret = msp_set_simulation_model_wf_ped(&msp);
+    ret = msp_set_simulation_model_fixed_pedigree(&msp);
     CU_ASSERT_EQUAL_FATAL(ret, MSP_ERR_PEDIGREE_IND_NODE_POPULATION_DISAGREE);
     tsk_table_collection_free(&tables);
     msp_free(&msp);
@@ -766,7 +766,7 @@ test_errors(void)
     tables.nodes.individual[0] = TSK_NULL;
     CU_ASSERT_EQUAL_FATAL(msp_alloc(&msp, &tables, rng), 0);
     CU_ASSERT_EQUAL_FATAL(msp_set_ploidy(&msp, 2), 0);
-    ret = msp_set_simulation_model_wf_ped(&msp);
+    ret = msp_set_simulation_model_fixed_pedigree(&msp);
     CU_ASSERT_EQUAL_FATAL(ret, MSP_ERR_PEDIGREE_IND_NOT_DIPLOID);
     tsk_table_collection_free(&tables);
     msp_free(&msp);
@@ -779,7 +779,7 @@ test_errors(void)
     tsk_individual_table_add_row(&tables.individuals, 0, NULL, 0, NULL, 0, NULL, 0);
     CU_ASSERT_EQUAL_FATAL(msp_alloc(&msp, &tables, rng), 0);
     CU_ASSERT_EQUAL_FATAL(msp_set_ploidy(&msp, 2), 0);
-    ret = msp_set_simulation_model_wf_ped(&msp);
+    ret = msp_set_simulation_model_fixed_pedigree(&msp);
     CU_ASSERT_EQUAL_FATAL(ret, MSP_ERR_PEDIGREE_IND_NOT_TWO_PARENTS);
     tsk_table_collection_free(&tables);
     msp_free(&msp);
@@ -844,7 +844,7 @@ test_combined_with_other_models(void)
 
     /* This is cheating slightly because we should be testing if we throw the
      * error after simulating other models, but the effect is the same */
-    ret = msp_set_simulation_model_wf_ped(&msp);
+    ret = msp_set_simulation_model_fixed_pedigree(&msp);
     CU_ASSERT_EQUAL_FATAL(ret, MSP_ERR_OTHER_MODELS_WITH_PED);
 
     tsk_table_collection_free(&tables);
diff --git a/lib/tests/testlib.c b/lib/tests/testlib.c
index 6c2bace03..ba5da346f 100644
--- a/lib/tests/testlib.c
+++ b/lib/tests/testlib.c
@@ -106,7 +106,7 @@ build_pedigree_sim(msp_t *msp, tsk_table_collection_t *tables, gsl_rng *rng,
     if (ret != 0) {
         goto out;
     }
-    ret = msp_set_simulation_model_wf_ped(msp);
+    ret = msp_set_simulation_model_fixed_pedigree(msp);
 out:
     return ret;
 }
diff --git a/tests/test_algorithms.py b/tests/test_algorithms.py
index 601b99c57..f87f9263d 100644
--- a/tests/test_algorithms.py
+++ b/tests/test_algorithms.py
@@ -186,7 +186,7 @@ def test_pedigree(self, num_founders, num_generations, r):
         with tempfile.TemporaryDirectory() as tmpdir:
             ts_path = pathlib.Path(tmpdir) / "pedigree.trees"
             tables.dump(ts_path)
-            ts = self.run_script(f"0 --from-ts {ts_path} -r {r} --model=wf_ped")
+            ts = self.run_script(f"0 --from-ts {ts_path} -r {r} --model=fixed_pedigree")
         for node in ts.nodes():
             assert node.individual != tskit.NULL
         assert ts.num_samples == 2 * num_founders
@@ -235,7 +235,7 @@ def test_pedigree_trio(self, r):
         with tempfile.TemporaryDirectory() as tmpdir:
             ts_path = pathlib.Path(tmpdir) / "pedigree.trees"
             input_tables.dump(ts_path)
-            ts = self.run_script(f"0 --from-ts {ts_path} -r {r} --model=wf_ped")
+            ts = self.run_script(f"0 --from-ts {ts_path} -r {r} --model=fixed_pedigree")
         output_tables = ts.dump_tables()
         input_tables.individuals.assert_equals(output_tables.individuals)
         input_tables.nodes.assert_equals(output_tables.nodes[: len(input_tables.nodes)])
@@ -247,5 +247,5 @@ def test_one_gen_pedigree(self, num_founders):
         with tempfile.TemporaryDirectory() as tmpdir:
             ts_path = pathlib.Path(tmpdir) / "pedigree.trees"
             tables.dump(ts_path)
-            ts = self.run_script(f"0 --from-ts {ts_path} -r 1 --model=wf_ped")
+            ts = self.run_script(f"0 --from-ts {ts_path} -r 1 --model=fixed_pedigree")
         assert len(ts.dump_tables().edges) == 0
diff --git a/tests/test_ancestry.py b/tests/test_ancestry.py
index dd0e81bc0..2eb8a5af8 100644
--- a/tests/test_ancestry.py
+++ b/tests/test_ancestry.py
@@ -809,35 +809,39 @@ def test_samples_and_initial_state(self):
 class TestParseSimAncestryPedigree:
     def test_pedigree_requires_initial_state(self):
         with pytest.raises(ValueError, match="Must specify an input pedigree"):
-            ancestry._parse_sim_ancestry(model="wf_ped")
+            ancestry._parse_sim_ancestry(model="fixed_pedigree")
 
     def test_pedigree_requires_no_demography(self):
         demography = msprime.Demography.isolated_model([1])
         with pytest.raises(ValueError, match="Cannot specify demography"):
-            ancestry._parse_sim_ancestry(model="wf_ped", demography=demography)
+            ancestry._parse_sim_ancestry(model="fixed_pedigree", demography=demography)
 
     def test_pedigree_requires_no_population_size(self):
         with pytest.raises(ValueError, match="Cannot specify population_size"):
-            ancestry._parse_sim_ancestry(model="wf_ped", population_size=1)
+            ancestry._parse_sim_ancestry(model="fixed_pedigree", population_size=1)
 
     @pytest.mark.parametrize("ploidy", [1, 3])
     def test_pedigree_requires_ploidy2(self, ploidy):
         with pytest.raises(ValueError, match="must have ploidy=2"):
             ancestry._parse_sim_ancestry(
-                model="wf_ped", initial_state=tskit.TableCollection(1), ploidy=ploidy
+                model="fixed_pedigree",
+                initial_state=tskit.TableCollection(1),
+                ploidy=ploidy,
             )
 
     def test_pedigree_requires_no_samples(self):
         with pytest.raises(ValueError, match="Cannot specify both samples and"):
             ancestry._parse_sim_ancestry(
-                model="wf_ped", initial_state=tskit.TableCollection(1), samples=10
+                model="fixed_pedigree",
+                initial_state=tskit.TableCollection(1),
+                samples=10,
             )
 
     def test_pedigree_requires_no_gc(self):
         pb = msprime.PedigreeBuilder()
         with pytest.raises(ValueError, match="Gene conversion not supported"):
             ancestry._parse_sim_ancestry(
-                model="wf_ped",
+                model="fixed_pedigree",
                 initial_state=pb.finalise(10),
                 gene_conversion_rate=1,
                 gene_conversion_tract_length=2,
@@ -847,21 +851,25 @@ def test_pedigree_requires_no_full_arg(self):
         pb = msprime.PedigreeBuilder()
         with pytest.raises(ValueError, match="Full ARG recording not supported"):
             ancestry._parse_sim_ancestry(
-                model="wf_ped", initial_state=pb.finalise(10), record_full_arg=True
+                model="fixed_pedigree",
+                initial_state=pb.finalise(10),
+                record_full_arg=True,
             )
 
     def test_pedigree_requires_no_record_migrations(self):
         pb = msprime.PedigreeBuilder()
         with pytest.raises(ValueError, match="Migration recording not supported"):
             ancestry._parse_sim_ancestry(
-                model="wf_ped", initial_state=pb.finalise(10), record_migrations=True
+                model="fixed_pedigree",
+                initial_state=pb.finalise(10),
+                record_migrations=True,
             )
 
     def test_pedigree_requires_no_start_time(self):
         pb = msprime.PedigreeBuilder()
         with pytest.raises(ValueError, match="Cannot specify start_time"):
             ancestry._parse_sim_ancestry(
-                model="wf_ped", initial_state=pb.finalise(10), start_time=1
+                model="fixed_pedigree", initial_state=pb.finalise(10), start_time=1
             )
 
     def test_pedigree_with_following_model(self):
@@ -870,7 +878,7 @@ def test_pedigree_with_following_model(self):
             ValueError, match="Cannot use FixedPedigree simulation in conjunction"
         ):
             ancestry._parse_sim_ancestry(
-                model=["wf_ped", "hudson"], initial_state=pb.finalise(10)
+                model=["fixed_pedigree", "hudson"], initial_state=pb.finalise(10)
             )
 
     def test_pedigree_with_previous_model(self):
@@ -879,7 +887,7 @@ def test_pedigree_with_previous_model(self):
             ValueError, match="Cannot use FixedPedigree simulation in conjunction"
         ):
             ancestry._parse_sim_ancestry(
-                model=["hudson", "wf_ped"], initial_state=pb.finalise(10)
+                model=["hudson", "fixed_pedigree"], initial_state=pb.finalise(10)
             )
 
 
@@ -1488,6 +1496,7 @@ def test_model_change_events_error(self):
             msprime.simulate(
                 Ne=100,
                 sample_size=2,
+                random_seed=2,
                 model=None,
                 demographic_events=[
                     msprime.SimulationModelChange(
@@ -2168,7 +2177,7 @@ def test_simulation_models(self):
             msprime.SmcApproxCoalescent(),
             msprime.SmcPrimeApproxCoalescent(),
             msprime.DiscreteTimeWrightFisher(),
-            msprime.WrightFisherPedigree(),
+            msprime.FixedPedigree(),
             msprime.BetaCoalescent(),
             msprime.BetaCoalescent(alpha=1, truncation_point=10),
             msprime.DiracCoalescent(),
diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py
index 6546f14e6..f01c857d8 100644
--- a/tests/test_lowlevel.py
+++ b/tests/test_lowlevel.py
@@ -990,7 +990,7 @@ def test_trio_no_coal(self):
         sim = _msprime.Simulator(
             ll_tables,
             random_generator=_msprime.RandomGenerator(1),
-            model={"name": "wf_ped"},
+            model={"name": "fixed_pedigree"},
         )
         ancestors = sim.ancestors
         assert len(sim.ancestors) == 2
@@ -1026,7 +1026,7 @@ def test_large_family(self):
         sim = _msprime.Simulator(
             ll_tables,
             random_generator=_msprime.RandomGenerator(1),
-            model={"name": "wf_ped"},
+            model={"name": "fixed_pedigree"},
         )
         ancestors = sim.ancestors
         assert len(sim.ancestors) == 2 * n
diff --git a/tests/test_models.py b/tests/test_models.py
index a2ae535c0..b1ce3f71d 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -26,7 +26,6 @@
 import msprime
 from msprime import _msprime
 from msprime import ancestry
-from msprime import pedigrees
 
 
 nonparametric_model_classes = [
@@ -34,6 +33,7 @@
     msprime.SmcApproxCoalescent,
     msprime.SmcPrimeApproxCoalescent,
     msprime.DiscreteTimeWrightFisher,
+    msprime.FixedPedigree,
 ]
 
 
@@ -66,9 +66,9 @@ def test_dtwf(self):
         assert repr(model) == repr_s
         assert str(model) == repr_s
 
-    def test_wf_pedigree(self):
-        model = msprime.WrightFisherPedigree()
-        repr_s = "WrightFisherPedigree(duration=None)"
+    def test_fixed_pedigreeigree(self):
+        model = msprime.FixedPedigree()
+        repr_s = "FixedPedigree(duration=None)"
         assert repr(model) == repr_s
         assert str(model) == repr_s
 
@@ -113,7 +113,7 @@ def test_named_model_variants(self):
             ("smc", msprime.SmcApproxCoalescent),
             ("smc_prime", msprime.SmcPrimeApproxCoalescent),
             ("dtwf", msprime.DiscreteTimeWrightFisher),
-            ("wf_ped", msprime.WrightFisherPedigree),
+            ("fixed_pedigree", msprime.FixedPedigree),
         ]
         for name, model_class in simulation_models:
             model = ancestry._model_factory(model=name.upper())
@@ -140,7 +140,7 @@ def test_model_instances(self):
             msprime.SmcApproxCoalescent(),
             msprime.SmcPrimeApproxCoalescent(),
             msprime.DiscreteTimeWrightFisher(),
-            msprime.WrightFisherPedigree(),
+            msprime.FixedPedigree(),
             msprime.SweepGenicSelection(
                 position=0.5,
                 start_frequency=0.1,
@@ -506,20 +506,6 @@ def test_dtwf(self):
         assert ts is not None
         self.verify_non_binary(ts)
 
-    @pytest.mark.skip("Pedigrees broken")
-    def test_wf_ped(self):
-        inds = np.array([1, 2, 3, 4])
-        parent_indices = np.array([2, 3, 2, 3, -1, -1, -1, -1]).reshape(-1, 2)
-        times = np.array([0, 0, 1, 1])
-        is_sample = np.array([1, 1, 0, 0])
-
-        model = msprime.WrightFisherPedigree()
-        ped = pedigrees.Pedigree(
-            inds, parent_indices, times, is_sample, sex=None, ploidy=2
-        )
-        ts = msprime.simulate(2, pedigree=ped, model=model)
-        assert ts is not None
-
 
 class TestDtwf:
     """
@@ -587,99 +573,6 @@ class TestMixedModels:
     Tests that we can run mixed simulation models.
     """
 
-    @pytest.mark.skip("Pedigrees broken")
-    def test_ped_wf_single_locus(self):
-        inds = np.array([1, 2, 3, 4, 5, 6])
-        parent_indices = np.array([4, 5, 4, 5, 4, 5, 4, 5, -1, -1, -1, -1]).reshape(
-            -1, 2
-        )
-        times = np.array([0, 0, 0, 0, 1, 1])
-        is_sample = np.array([1, 1, 1, 1, 0, 0])
-        t = max(times)
-
-        model = msprime.WrightFisherPedigree()
-        ped = pedigrees.Pedigree(
-            inds, parent_indices, times, is_sample, sex=None, ploidy=2
-        )
-        ts = msprime.simulate(
-            sample_size=4,
-            Ne=2,
-            pedigree=ped,
-            model=model,
-            demographic_events=[msprime.SimulationModelChange(t, "dtwf")],
-        )
-        tree = ts.first()
-        assert tree.num_roots == 1
-        all_times = ts.tables.nodes.time
-        ped_times = all_times[np.logical_and(all_times > 0, all_times <= t)]
-        assert ped_times.shape[0] > 0
-        assert np.all(ped_times == np.floor(ped_times))
-        wf_times = all_times[all_times > t]
-        assert wf_times.shape[0] > 0
-
-    @pytest.mark.skip("Pedigrees broken")
-    def test_pedigree_unsupported_events(self):
-        inds = np.array([1, 2, 3, 4, 5, 6])
-        parent_indices = np.array([4, 5, 4, 5, 4, 5, 4, 5, -1, -1, -1, -1]).reshape(
-            -1, 2
-        )
-        times = np.array([0, 0, 0, 0, 1, 1])
-        is_sample = np.array([1, 1, 1, 1, 0, 0])
-        t = max(times)
-
-        ped = pedigrees.Pedigree(
-            inds, parent_indices, times, is_sample, sex=None, ploidy=2
-        )
-
-        bad_model_change = msprime.SimulationModelChange(
-            0.5, msprime.DiscreteTimeWrightFisher()
-        )
-        with pytest.raises(RuntimeError, match="not support interruption"):
-            msprime.simulate(
-                4,
-                pedigree=ped,
-                demographic_events=[bad_model_change],
-                model="wf_ped",
-            )
-        bad_demographic_event = msprime.PopulationParametersChange(t, initial_size=2)
-        with pytest.raises(_msprime.LibraryError):
-            msprime.simulate(
-                4,
-                pedigree=ped,
-                demographic_events=[bad_demographic_event],
-                model="wf_ped",
-            )
-
-    @pytest.mark.skip("Pedigrees broken")
-    def test_ped_wf_recombination(self):
-        inds = np.array([1, 2, 3, 4, 5, 6])
-        parent_indices = np.array([4, 5, 4, 5, 4, 5, 4, 5, -1, -1, -1, -1]).reshape(
-            -1, 2
-        )
-        times = np.array([0, 0, 0, 0, 1, 1])
-        is_sample = np.array([1, 1, 1, 1, 0, 0])
-        t = max(times)
-
-        model = msprime.WrightFisherPedigree()
-        ped = pedigrees.Pedigree(
-            inds, parent_indices, times, is_sample, sex=None, ploidy=2
-        )
-        ts = msprime.simulate(
-            sample_size=4,
-            pedigree=ped,
-            recombination_rate=0.1,
-            model=model,
-            demographic_events=[msprime.SimulationModelChange(time=1, model="dtwf")],
-        )
-        tree = ts.first()
-        assert tree.num_roots == 1
-        all_times = ts.tables.nodes.time
-        ped_times = all_times[np.logical_and(all_times > 0, all_times <= t)]
-        assert ped_times.shape[0] > 0
-        assert np.all(ped_times == np.floor(ped_times))
-        wf_times = all_times[all_times > t]
-        assert wf_times.shape[0] > 0
-
     def test_wf_hudson_single_locus(self):
         t = 10
         ts = msprime.sim_ancestry(
diff --git a/tests/test_pedigree.py b/tests/test_pedigree.py
index 4eda6a58f..fa29325f5 100644
--- a/tests/test_pedigree.py
+++ b/tests/test_pedigree.py
@@ -93,7 +93,9 @@ class TestSimPedigree:
     def verify(self, tables):
         tables.sequence_length = 10
         # Check that we can simulate with it.
-        msprime.sim_ancestry(initial_state=tables, model="wf_ped", random_seed=2)
+        msprime.sim_ancestry(
+            initial_state=tables, model="fixed_pedigree", random_seed=2
+        )
 
     def test_zero_generations(self):
         tables = pedigrees.sim_pedigree(population_size=10, end_time=0, random_seed=1)
@@ -349,7 +351,7 @@ def verify(self, input_tables, recombination_rate=0):
         # Using this low-level interface to make debugging easier. It's the
         # same effect as calling ts = msprime.sim_ancestry(...)
         sim = msprime.ancestry._parse_sim_ancestry(
-            model="wf_ped",
+            model="fixed_pedigree",
             initial_state=initial_state,
             recombination_rate=recombination_rate,
             random_seed=1,
@@ -651,13 +653,13 @@ def test_just_samples(self):
 class TestSimulateThroughPedigreeEventByEvent(TestSimulateThroughPedigree):
     def verify(self, input_tables, recombination_rate=0):
         ts1 = msprime.sim_ancestry(
-            model="wf_ped",
+            model="fixed_pedigree",
             initial_state=input_tables,
             recombination_rate=recombination_rate,
             random_seed=1,
         )
         sim = msprime.ancestry._parse_sim_ancestry(
-            model="wf_ped",
+            model="fixed_pedigree",
             initial_state=input_tables,
             recombination_rate=recombination_rate,
             random_seed=1,
@@ -676,7 +678,7 @@ class TestContinueSimulateThroughPedigree(TestSimulateThroughPedigree):
     def verify(self, input_tables, recombination_rate=0):
 
         ts1 = msprime.sim_ancestry(
-            model="wf_ped",
+            model="fixed_pedigree",
             initial_state=input_tables,
             recombination_rate=recombination_rate,
             random_seed=42,
@@ -745,7 +747,7 @@ def verify(self, input_tables, recombination_rate=0):
         num_replicates = 5
         replicates = list(
             msprime.sim_ancestry(
-                model="wf_ped",
+                model="fixed_pedigree",
                 initial_state=input_tables,
                 recombination_rate=recombination_rate,
                 random_seed=42,
@@ -754,7 +756,7 @@ def verify(self, input_tables, recombination_rate=0):
         )
 
         ts1 = msprime.sim_ancestry(
-            model="wf_ped",
+            model="fixed_pedigree",
             initial_state=input_tables,
             recombination_rate=recombination_rate,
             random_seed=42,
@@ -781,7 +783,7 @@ def test_one_parent_removed_each_individual(self):
         tables.individuals.parents = parents
 
         ts = msprime.sim_ancestry(
-            model="wf_ped",
+            model="fixed_pedigree",
             initial_state=tables,
             random_seed=42,
         )
@@ -800,7 +802,7 @@ def test_10_percent_parents_removed(self):
         tables.individuals.parents = parents
 
         ts = msprime.sim_ancestry(
-            model="wf_ped",
+            model="fixed_pedigree",
             initial_state=tables,
             random_seed=42,
         )
@@ -820,7 +822,7 @@ def test_parents_are_samples(self):
         with pytest.raises(_msprime.LibraryError, match="1855"):
             msprime.sim_ancestry(
                 initial_state=tables,
-                model="wf_ped",
+                model="fixed_pedigree",
             )
 
     @pytest.mark.parametrize("num_parents", [0, 1, 3])
@@ -829,7 +831,7 @@ def test_not_two_parents(self, num_parents):
         parents = [add_pedigree_individual(tables, time=1) for _ in range(num_parents)]
         add_pedigree_individual(tables, parents=parents, time=0)
         with pytest.raises(_msprime.InputError, match="exactly two parents"):
-            msprime.sim_ancestry(initial_state=tables, model="wf_ped")
+            msprime.sim_ancestry(initial_state=tables, model="fixed_pedigree")
 
     @pytest.mark.parametrize("num_nodes", [0, 1, 3])
     def test_not_two_nodes(self, num_nodes):
@@ -840,7 +842,7 @@ def test_not_two_nodes(self, num_nodes):
                 flags=tskit.NODE_IS_SAMPLE, time=0, individual=ind, population=0
             )
         with pytest.raises(_msprime.InputError, match="exactly two nodes"):
-            msprime.sim_ancestry(initial_state=tables, model="wf_ped")
+            msprime.sim_ancestry(initial_state=tables, model="fixed_pedigree")
 
     def test_node_times_disagree(self):
         tables = get_base_tables(100)
@@ -852,7 +854,7 @@ def test_node_times_disagree(self):
             flags=tskit.NODE_IS_SAMPLE, time=1, individual=ind, population=0
         )
         with pytest.raises(_msprime.InputError, match="times for the two nodes"):
-            msprime.sim_ancestry(initial_state=tables, model="wf_ped")
+            msprime.sim_ancestry(initial_state=tables, model="fixed_pedigree")
 
     def test_node_populations_disagree(self):
         tables = get_base_tables(100)
@@ -865,7 +867,7 @@ def test_node_populations_disagree(self):
             flags=tskit.NODE_IS_SAMPLE, time=0, individual=ind, population=1
         )
         with pytest.raises(_msprime.InputError, match="populations for the two nodes"):
-            msprime.sim_ancestry(initial_state=tables, model="wf_ped")
+            msprime.sim_ancestry(initial_state=tables, model="fixed_pedigree")
 
     def test_no_samples(self):
         tables = get_base_tables(100)
@@ -873,14 +875,14 @@ def test_no_samples(self):
         tables.nodes.add_row(flags=0, time=0, individual=ind, population=0)
         tables.nodes.add_row(flags=0, time=0, individual=ind, population=0)
         with pytest.raises(_msprime.InputError, match="samples"):
-            msprime.sim_ancestry(initial_state=tables, model="wf_ped")
+            msprime.sim_ancestry(initial_state=tables, model="fixed_pedigree")
 
     def test_pedigree_time_travel(self):
         tables = get_base_tables(100)
         parents = [add_pedigree_individual(tables, time=0) for _ in range(2)]
         add_pedigree_individual(tables, time=1, parents=parents, is_sample=True)
         with pytest.raises(_msprime.InputError, match="time for a parent must be"):
-            msprime.sim_ancestry(initial_state=tables, model="wf_ped")
+            msprime.sim_ancestry(initial_state=tables, model="fixed_pedigree")
 
     @pytest.mark.parametrize("num_founders", [2, 3, 10, 20])
     def test_all_samples(self, num_founders):
@@ -894,7 +896,7 @@ def test_all_samples(self, num_founders):
         flags[:] = tskit.NODE_IS_SAMPLE
         tables.nodes.flags = flags
         with pytest.raises(_msprime.LibraryError, match="1855"):
-            msprime.sim_ancestry(initial_state=tables, model="wf_ped")
+            msprime.sim_ancestry(initial_state=tables, model="fixed_pedigree")
 
 
 class TestSimulateThroughPedigreeMultiplePops:
@@ -907,7 +909,7 @@ def test_demography_raises_error(self):
             msprime.sim_ancestry(
                 initial_state=tables,
                 demography=demography,
-                model="wf_ped",
+                model="fixed_pedigree",
                 random_seed=1,
             )
 
@@ -917,7 +919,9 @@ def test_trio_parents_different_pops(self):
         parents = [pb.add_individual(time=2, population=j) for j in range(2)]
         pb.add_individual(time=0, parents=parents, population=0)
         pedigree = pb.finalise(1)
-        ts = msprime.sim_ancestry(initial_state=pedigree, model="wf_ped", random_seed=1)
+        ts = msprime.sim_ancestry(
+            initial_state=pedigree, model="fixed_pedigree", random_seed=1
+        )
         # Founders are in different populations so cannot coalesce
         with pytest.raises(_msprime.LibraryError, match="Infinite waiting"):
             msprime.sim_ancestry(initial_state=ts, demography=demography, random_seed=2)
@@ -929,7 +933,9 @@ def test_trio_parents_same_pop(self):
         pb.add_individual(time=0, parents=parents, population=0)
         pedigree = pb.finalise(1)
 
-        ts = msprime.sim_ancestry(initial_state=pedigree, model="wf_ped", random_seed=1)
+        ts = msprime.sim_ancestry(
+            initial_state=pedigree, model="fixed_pedigree", random_seed=1
+        )
         ts = msprime.sim_ancestry(
             initial_state=ts, demography=demography, random_seed=2
         )
@@ -949,7 +955,9 @@ def test_trio_parents_different_pops_with_split(self):
         pb.add_individual(time=0, parents=parents, population=0)
         pedigree = pb.finalise(1)
 
-        ts = msprime.sim_ancestry(initial_state=pedigree, model="wf_ped", random_seed=1)
+        ts = msprime.sim_ancestry(
+            initial_state=pedigree, model="fixed_pedigree", random_seed=1
+        )
         # Should be able to coalesce due to the added population split
         ts = msprime.sim_ancestry(
             initial_state=ts, demography=demography, random_seed=2
@@ -967,7 +975,9 @@ def test_trio_parents_different_pops_with_migrations(self):
         pb.add_individual(time=0, parents=parents, population=0)
         pedigree = pb.finalise(1)
 
-        ts = msprime.sim_ancestry(initial_state=pedigree, model="wf_ped", random_seed=1)
+        ts = msprime.sim_ancestry(
+            initial_state=pedigree, model="fixed_pedigree", random_seed=1
+        )
         # Should be able to coalesce due to symmetric migration
         ts = msprime.sim_ancestry(
             initial_state=ts, demography=demography, random_seed=2