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

Issue:
individual_populations gives *birth* locations, not sampling locations
As pointed out by Tianzhu Xiong in [the SLiM mailing list](https://groups.google.com/g/slim-discuss/c/cIupNq59bRQ/m/89nxvVchAAAJ?utm_medium=email&utm_source=footer&pli=1), `ts.individual_locations` gets its information from nodes, and is therefore the *birth* location; while individual metadata contains the "current" population; these differ if the individual is a migrant. 

So, [the tutorial](https://pyslim.readthedocs.io/en/stable/tutorial.html#individual-metadata) currently has
```
alive = ts.individuals_alive_at(0)
adults = alive[ts.individual_ages[alive] > 2]
pops = [np.where(
           ts.individual_populations[adults] == k)[0] for k in [1, 2]]
```
but if we want to sample individuals from where they *currently* (at the end of the simulation) are, which is probably what the user would want, then we would instead do something like (not tested!):
```
pops = [
   [i for i in adults if ts.individual(i).metadata['subpopulation'] == k]
   for k in [1, 2]
]
```

Probably `individual_locations` should be renamed `individual_birth_locations` or something?


Discussion / hints:
I think the thing to do is keep the name the same but document it.

Fix patch:
diff --git a/docs/development.md b/docs/development.md
index 9506c93e..1a403336 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -35,12 +35,12 @@ python -m pytest tests
 
 If you would like to add some features to ``pyslim``, please read the
 following. If you think there is anything missing,
-please open an `issue <http://github.com/tskit-dev/pyslim/issues>`_ or
-`pull request <http://github.com/tskit-dev/pyslim/pulls>`_ on GitHub!
+please open an [issue](http://github.com/tskit-dev/pyslim/issues>) or
+[pull request](http://github.com/tskit-dev/pyslim/pulls>) on GitHub!
 
 ## Quickstart
 
-- Make a fork of the pyslim repo on `GitHub <http://github.com/tskit-dev/pyslim>`_
+- Make your own fork of the pyslim repo on [GitHub](http://github.com/tskit-dev/pyslim>)
 - Clone your fork into a local directory:
 
 ```bash
@@ -55,3 +55,6 @@ git clone git@github.com:YOUR_GITHUB/pyslim.git
   are ready. Please make sure that (a) the tests pass before you open the pull request; and
   (b) your code passes PEP8 checks before opening the pull request.
 
+For a more detailed walkthrough of development methods,
+see [the stdpopsim documentation](https://popsim-consortium.github.io/stdpopsim-docs/latest/development.html#github-workflow)
+and/or [the tskit documentation](https://tskit.dev/tskit/docs/latest/development.html#workflow).
diff --git a/docs/tutorial.md b/docs/tutorial.md
index 054cf17d..44dfda56 100644
--- a/docs/tutorial.md
+++ b/docs/tutorial.md
@@ -588,13 +588,7 @@ To do this, we need to extract the node IDs from the individuals of the two popu
 that are alive at the end of the simulation.
 
 ```{code-cell}
-pop_indivs = [[], [], []]
-pop_nodes = [[], [], []]
-for i in ts.individuals_alive_at(0):
-  ind = ts.individual(i)
-  pop_indivs[ind.population].append(i)
-  pop_nodes[ind.population].extend(ind.nodes)
-
+pop_nodes = [ts.samples(population=p, time=0) for p in range(ts.num_populations)]
 diversity = ts.diversity(pop_nodes[1:])
 divergence = ts.divergence(pop_nodes[1:])
 
@@ -687,7 +681,8 @@ and {attr}`.SlimTreeSequence.individual_populations` as follows:
 alive = ts.individuals_alive_at(0)
 adults = alive[ts.individual_ages[alive] > 2]
 pops = [
-    np.where(ts.individual_populations[adults] == k)[0] for k in [1, 2]
+   [i for i in adults if ts.individual(i).metadata['subpopulation'] == k]
+   for k in [1, 2]
 ]
 sample_inds = [np.random.choice(pop, 10, replace=False) for pop in pops]
 sample_nodes = []
@@ -697,6 +692,11 @@ for samp in sample_inds:
 sub_ts = ts.simplify(sample_nodes)
 ```
 
+Note that here we have used the *subpopulation* attribute that SLiM places in metadata
+to find out where each individual lives at the end of the simulation.
+We might alternatively have used the *population* attribute of Nodes -
+but, this would give each individual's *birth* location.
+
 The resulting tree sequence does indeed have fewer individuals and fewer trees:
 
 ```{code-cell}
diff --git a/docs/vignette_coalescent_diversity.md b/docs/vignette_coalescent_diversity.md
index 000c9772..9de777e7 100644
--- a/docs/vignette_coalescent_diversity.md
+++ b/docs/vignette_coalescent_diversity.md
@@ -315,11 +315,7 @@ times = list(set(ts.individual_times))
 times.sort()
 print("The times ago at which individuals in the tree sequence were born:", times)
 # The times ago at which individuals in the tree sequence were born: [0.0, 100.0]
-inds_by_time = [ts.individuals_alive_at(t) for t in times]
-nodes_by_time = []
-for inds in inds_by_time:
-  nodes = np.array([ts.individual(i).nodes for i in inds]).flatten()
-  nodes_by_time.append(nodes)
+nodes_by_time = [ts.samples(time=t) for t in times]
 
 num_nodes = np.array([len(x) for x in nodes_by_time])
 p = ts.sample_count_stat(nodes_by_time, lambda x: x/num_nodes, 2, windows='sites',
diff --git a/docs/vignette_continuing.md b/docs/vignette_continuing.md
index 05c326d5..d4753cfe 100644
--- a/docs/vignette_continuing.md
+++ b/docs/vignette_continuing.md
@@ -163,12 +163,7 @@ new_nodes = np.where(new_tables.nodes.time == new_time)[0]
 print(f"There are {len(new_nodes)} nodes from the start of the new simulation.")
 # There are 4425 nodes from the start of the new simulation.
 
-slim_indivs = rts.individuals_alive_at(0)
-slim_nodes = []
-for ind in slim_indivs:
-  slim_nodes.extend(ts.individual(ind).nodes)
-
-slim_nodes = np.array(slim_nodes)
+slim_nodes = rts.samples(time=0)
 assert(len(slim_nodes) == 20000)
 
 # randomly give new_nodes IDs in rts
diff --git a/pyslim/slim_tree_sequence.py b/pyslim/slim_tree_sequence.py
index c35a4370..e80b3a9c 100644
--- a/pyslim/slim_tree_sequence.py
+++ b/pyslim/slim_tree_sequence.py
@@ -170,6 +170,9 @@ class SlimTreeSequence(tskit.TreeSequence):
     in the tree sequence: either the last time they were Remembered, or at the end
     of the simulation, if they are still alive then.
 
+    However, `.individual_populations` gives individuals' birth populations;
+    for their final location use the subpopulation attribute of metadata.
+
     You can create a :class:`.SlimTreeSequence` using one of
 
     - :meth:`.SlimTreeSequence.load_tables`, :meth:`.SlimTreeSequence.load`,


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index caaacb6a..0303bc98 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -36,9 +36,11 @@ jobs:
           CACHE_NUM: 2
         with:
           path: |
-            ${{ steps.find-conda.outputs.CONDA }}/envs/${{ env.CONDA_ENV_NAME }}
-            ~/.bash_profile
-          key: ${{ runner.os }}-${{ matrix.python}}-conda-v10-${{ hashFiles('requirements/CI/pip-requirements.txt') }}-${{ hashFiles('requirements/CI/conda-requirements.txt') }}-${{ env.CACHE_NUM }}
+            c:\Miniconda\envs\anaconda-client-env
+            /usr/share/miniconda/envs/anaconda-client-env
+            ~/osx-conda
+            ~/.profile
+          key: ${{ runner.os }}-${{ matrix.python}}-conda-v${{ env.CACHE_NUM }}-${{ hashFiles('requirements/CI/pip-requirements.txt') }}-${{ hashFiles('requirements/CI/conda-requirements.txt') }}
 
       - name: Install Conda
         uses: conda-incubator/setup-miniconda@v2
@@ -81,14 +83,14 @@ jobs:
           mkdir -p /usr/local/miniconda/envs
           sudo cp -r ~/osx-conda /usr/local/miniconda/envs/anaconda-client-env
 
-# Installing SLiM from conda now.
-#      - name: Build SLiM
-#        run: |
-#          git clone https://github.com/messerlab/SLiM.git
-#          mkdir -p SLiM/Release
-#          cd SLiM/Release
-#          cmake -D CMAKE_BUILD_TYPE=Release ..
-#          make -j 2
+      # Installing SLiM from conda now.
+      # - name: Build SLiM
+      #   run: |
+      #     git clone https://github.com/messerlab/SLiM.git
+      #     mkdir -p SLiM/Release
+      #     cd SLiM/Release
+      #     cmake -D CMAKE_BUILD_TYPE=Release ..
+      #     make -j 2
 
       - name: Run tests
         run: |
diff --git a/tests/test_tree_sequence.py b/tests/test_tree_sequence.py
index bcda8e06..7d5db021 100644
--- a/tests/test_tree_sequence.py
+++ b/tests/test_tree_sequence.py
@@ -543,7 +543,8 @@ def test_post_recap(self, recipe):
     @pytest.mark.parametrize('recipe', recipe_eq("everyone"), indirect=True)
     def test_post_simplify(self, recipe):
         ts = recipe["ts"]
-        keep_indivs = np.random.choice(
+        rng = np.random.default_rng(seed=3)
+        keep_indivs = rng.choice(
                 np.where(ts.individual_times < ts.metadata['SLiM']['generation'] - 1)[0],
                 size=30, replace=False)
         keep_nodes = []