Skip to content

Commit 0c47e4c

Browse files
committed
Added statistics to measure the spread of individuals
1 parent 1fcc70e commit 0c47e4c

File tree

3 files changed

+75
-35
lines changed

3 files changed

+75
-35
lines changed

exploration.ipynb

+39-34
Original file line numberDiff line numberDiff line change
@@ -2099,44 +2099,44 @@
20992099
"text": [
21002100
"Gen 0!\n",
21012101
"The current number of sets in pop 0 is 100\n",
2102-
"The current number of sets in pop 1 is 99\n",
2102+
"The current number of sets in pop 1 is 100\n",
21032103
"The current number of sets in pop 2 is 100\n",
21042104
"The current number of sets in pop 3 is 100\n",
21052105
"Gen 50000!\n",
2106-
"The current number of sets in pop 0 is 5\n",
2107-
"The current number of sets in pop 1 is 6\n",
2108-
"The current number of sets in pop 2 is 2\n",
2109-
"The current number of sets in pop 3 is 3\n",
2106+
"The current number of sets in pop 0 is 4\n",
2107+
"The current number of sets in pop 1 is 7\n",
2108+
"The current number of sets in pop 2 is 5\n",
2109+
"The current number of sets in pop 3 is 8\n",
2110+
"[<bound method Subpopulation.count_deme_origin_id of <metapypulation.subpopulation.Subpopulation object at 0x7d0c293abe00>>\n",
2111+
" <bound method Subpopulation.count_deme_origin_id of <metapypulation.subpopulation.Subpopulation object at 0x7d0c2940f110>>\n",
2112+
" <bound method Subpopulation.count_deme_origin_id of <metapypulation.subpopulation.Subpopulation object at 0x7d0c2940f250>>\n",
2113+
" <bound method Subpopulation.count_deme_origin_id of <metapypulation.subpopulation.Subpopulation object at 0x7d0c2924a3f0>>]\n",
21102114
"Gen 100000!\n",
21112115
"The current number of sets in pop 0 is 7\n",
2112-
"The current number of sets in pop 1 is 2\n",
2113-
"The current number of sets in pop 2 is 4\n",
2114-
"The current number of sets in pop 3 is 9\n",
2116+
"The current number of sets in pop 1 is 5\n",
2117+
"The current number of sets in pop 2 is 11\n",
2118+
"The current number of sets in pop 3 is 7\n",
21152119
"Gen 150000!\n",
2116-
"The current number of sets in pop 0 is 30\n",
2117-
"The current number of sets in pop 1 is 17\n",
2118-
"The current number of sets in pop 2 is 19\n",
2119-
"The current number of sets in pop 3 is 17\n",
2120-
"Gen 200000!\n",
2121-
"The current number of sets in pop 0 is 12\n",
2122-
"The current number of sets in pop 1 is 17\n",
2123-
"The current number of sets in pop 2 is 15\n",
2124-
"The current number of sets in pop 3 is 17\n",
2125-
"Gen 250000!\n",
2126-
"The current number of sets in pop 0 is 17\n",
2127-
"The current number of sets in pop 1 is 17\n",
2128-
"The current number of sets in pop 2 is 12\n",
2129-
"The current number of sets in pop 3 is 15\n",
2130-
"Gen 300000!\n",
2131-
"The current number of sets in pop 0 is 10\n",
2132-
"The current number of sets in pop 1 is 16\n",
2133-
"The current number of sets in pop 2 is 15\n",
2134-
"The current number of sets in pop 3 is 19\n",
2135-
"Gen 350000!\n",
2136-
"The current number of sets in pop 0 is 10\n",
2137-
"The current number of sets in pop 1 is 12\n",
2138-
"The current number of sets in pop 2 is 13\n",
2139-
"The current number of sets in pop 3 is 13\n"
2120+
"The current number of sets in pop 0 is 55\n",
2121+
"The current number of sets in pop 1 is 50\n",
2122+
"The current number of sets in pop 2 is 58\n",
2123+
"The current number of sets in pop 3 is 50\n"
2124+
]
2125+
},
2126+
{
2127+
"ename": "KeyboardInterrupt",
2128+
"evalue": "",
2129+
"output_type": "error",
2130+
"traceback": [
2131+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
2132+
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
2133+
"Cell \u001b[0;32mIn[2], line 52\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThe current number of sets in pop \u001b[39m\u001b[38;5;132;01m{\u001b[39;00msubpopulation\u001b[38;5;241m.\u001b[39mid\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m is \u001b[39m\u001b[38;5;132;01m{\u001b[39;00msubpopulation\u001b[38;5;241m.\u001b[39mcount_traits_sets()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 46\u001b[0m \u001b[38;5;66;03m# sub_id = []\u001b[39;00m\n\u001b[1;32m 47\u001b[0m \u001b[38;5;66;03m# for ind in subpopulation.population.individuals:\u001b[39;00m\n\u001b[1;32m 48\u001b[0m \u001b[38;5;66;03m# sub_id.append(ind.original_deme_id)\u001b[39;00m\n\u001b[1;32m 49\u001b[0m \u001b[38;5;66;03m# indexes, counts = np.unique(sub_id, return_counts=True)\u001b[39;00m\n\u001b[1;32m 50\u001b[0m \u001b[38;5;66;03m# print(f\"The current deme index present in population {subpopulation.id} are {indexes} with {counts} counts.\")\u001b[39;00m\n\u001b[0;32m---> 52\u001b[0m \u001b[43mmetapopulation\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmigrate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 53\u001b[0m metapopulation\u001b[38;5;241m.\u001b[39mmake_interact()\n\u001b[1;32m 55\u001b[0m spread \u001b[38;5;241m=\u001b[39m metapopulation\u001b[38;5;241m.\u001b[39mcount_origin_id_spread()\n",
2134+
"File \u001b[0;32m~/Documents/06_Development/03_GRIDH/ArchaeologyMetapopulations/MetapopulationsPython/metapypulation/metapopulation.py:109\u001b[0m, in \u001b[0;36mMetapopulation.migrate\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 106\u001b[0m migration_rate \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmigration_matrix[subpopulation\u001b[38;5;241m.\u001b[39mid][index]\n\u001b[1;32m 107\u001b[0m receiving_subpopulation \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msubpopulations[index]\n\u001b[0;32m--> 109\u001b[0m \u001b[43mreceiving_subpopulation\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreceive_migrants\u001b[49m\u001b[43m(\u001b[49m\u001b[43msubpopulation\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmigration_rate\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 111\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m subpopulation \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msubpopulations:\n\u001b[1;32m 112\u001b[0m subpopulation\u001b[38;5;241m.\u001b[39mincorporate_migrants_in_population()\n",
2135+
"File \u001b[0;32m~/Documents/06_Development/03_GRIDH/ArchaeologyMetapopulations/MetapopulationsPython/metapypulation/subpopulation.py:90\u001b[0m, in \u001b[0;36mSubpopulation.receive_migrants\u001b[0;34m(self, giving_subpopulation, migration_rate)\u001b[0m\n\u001b[1;32m 88\u001b[0m number_of_migrants \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mrandom\u001b[38;5;241m.\u001b[39mbinomial(population_size, migration_rate)\n\u001b[1;32m 89\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m number_of_migrants \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[0;32m---> 90\u001b[0m individuals_to_remove \u001b[38;5;241m=\u001b[39m \u001b[43mgiving_subpopulation\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpopulation\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msample_and_remove\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnumber_of_migrants\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 91\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m individual \u001b[38;5;129;01min\u001b[39;00m individuals_to_remove:\n\u001b[1;32m 92\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mincoming_migrants\u001b[38;5;241m.\u001b[39madd(individual)\n",
2136+
"File \u001b[0;32m~/Documents/06_Development/03_GRIDH/ArchaeologyMetapopulations/MetapopulationsPython/metapypulation/subpopulation.py:332\u001b[0m, in \u001b[0;36mSetOfIndividuals.sample_and_remove\u001b[0;34m(self, number_of_individuals)\u001b[0m\n\u001b[1;32m 322\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21msample_and_remove\u001b[39m(\u001b[38;5;28mself\u001b[39m, number_of_individuals: \u001b[38;5;28mint\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m List[Individual]:\n\u001b[1;32m 323\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 324\u001b[0m \u001b[38;5;124;03m Sample an individual, remove it from the Set and return it in a list.\u001b[39;00m\n\u001b[1;32m 325\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 330\u001b[0m \u001b[38;5;124;03m List[Individual]: List of all the individuals that have been sampled from the population.\u001b[39;00m\n\u001b[1;32m 331\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 332\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshuffle\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 334\u001b[0m list_of_individuals \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 335\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(number_of_individuals):\n",
2137+
"File \u001b[0;32m~/Documents/06_Development/03_GRIDH/ArchaeologyMetapopulations/MetapopulationsPython/metapypulation/subpopulation.py:320\u001b[0m, in \u001b[0;36mSetOfIndividuals.shuffle\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 316\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mshuffle\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 317\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;124;03m Shuffle the Set.\u001b[39;00m\n\u001b[1;32m 319\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 320\u001b[0m \u001b[43mrandom\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshuffle\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mindividuals\u001b[49m\u001b[43m)\u001b[49m\n",
2138+
"File \u001b[0;32m~/Software/miniforge3/envs/abm/lib/python3.13/random.py:361\u001b[0m, in \u001b[0;36mRandom.shuffle\u001b[0;34m(self, x)\u001b[0m\n\u001b[1;32m 358\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mreversed\u001b[39m(\u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m, \u001b[38;5;28mlen\u001b[39m(x))):\n\u001b[1;32m 359\u001b[0m \u001b[38;5;66;03m# pick an element in x[:i+1] with which to exchange x[i]\u001b[39;00m\n\u001b[1;32m 360\u001b[0m j \u001b[38;5;241m=\u001b[39m randbelow(i \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m)\n\u001b[0;32m--> 361\u001b[0m x[i], x[j] \u001b[38;5;241m=\u001b[39m x[j], x[i]\n",
2139+
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
21402140
]
21412141
}
21422142
],
@@ -2171,7 +2171,9 @@
21712171
" \n",
21722172
" metapopulation.migrate()\n",
21732173
" metapopulation.make_interact()\n",
2174-
" \n",
2174+
"spread = metapopulation.count_origin_id_spread()\n",
2175+
"print(spread) \n",
2176+
"\n",
21752177
"metapopulation.migration_matrix = migrations\n",
21762178
"for t in range(simulation_time):\n",
21772179
" if t%1000 == 0:\n",
@@ -2191,7 +2193,10 @@
21912193
" # print(f\"The current deme index present in population {subpopulation.id} are {indexes} with {counts} counts.\")\n",
21922194
" \n",
21932195
" metapopulation.migrate()\n",
2194-
" metapopulation.make_interact()"
2196+
" metapopulation.make_interact()\n",
2197+
"\n",
2198+
"spread = metapopulation.count_origin_id_spread()\n",
2199+
"print(spread)"
21952200
]
21962201
},
21972202
{

metapypulation/metapopulation.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ def metapopulation_shannon_diversity(self) -> float:
186186
return shannon_diversity_index
187187

188188

189-
190189
def metapopulation_test_sets(self) -> int:
191190
"""Calculates number of unique sets of traits in the whole metapopulation.
192191
@@ -226,7 +225,24 @@ def metapopulation_simpson(self) -> float:
226225
simpson_diversity_index = np.sum(frequencies*frequencies)
227226

228227
return simpson_diversity_index
228+
229+
230+
def count_origin_id_spread(self) -> np.ndarray:
231+
"""
232+
Counts the spread of individuals from deme of origin by counting how many individuals from each deme are in each deme.
233+
234+
Returns:
235+
np.ndarray: NxN matrix where N is the number of subpopulations. Rows are local subpopulations, columns are the original deme id.
236+
"""
237+
238+
counts = []
239+
240+
for subpopulation in self.subpopulations:
241+
local_spread = subpopulation.count_deme_origin_id(self.number_of_subpopulations)
242+
counts.append(local_spread)
229243

244+
return np.array(counts)
245+
230246

231247
class SubpopulationIterator(object):
232248
"""

metapypulation/subpopulation.py

+19
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ def shannon_diversity(self) -> float:
189189

190190
return shannon_index
191191

192+
192193
def simpson_diversity(self) -> float:
193194
"""
194195
Calculate the Simpson diversity index of the subpopulation.
@@ -202,6 +203,24 @@ def simpson_diversity(self) -> float:
202203
simpson_diversity_index = np.sum(frequencies*frequencies)
203204

204205
return simpson_diversity_index
206+
207+
208+
def count_deme_origin_id(self, total_number_of_subpopulations: int) -> List[int]:
209+
"""
210+
Count how many individuals originally from each deme are found in this deme. It is generally invoked from Metapopulation to get a summary.
211+
212+
Args:
213+
total_number_of_subpopulations: number of subpopulations in the whole metapopulation.
214+
215+
Returns:
216+
List[int]: list containing a count of individuals for each subpopulation present.
217+
"""
218+
counts = [0]*total_number_of_subpopulations
219+
for individual in self.population:
220+
counts[individual.original_deme_id] += 1
221+
222+
return counts
223+
205224

206225
class IndividualsIterator(object):
207226
"""

0 commit comments

Comments
 (0)