|
4 | 4 | import xsimlab as xs
|
5 | 5 | from adascape.base import IR12SpeciationModel
|
6 | 6 | from orographic_precipitation.fastscape_ext import OrographicPrecipitation, OrographicDrainageDischarge
|
7 |
| - |
| 7 | +from scipy.spatial import ConvexHull |
8 | 8 |
|
9 | 9 | @xs.process
|
10 | 10 | class Speciation:
|
@@ -47,11 +47,10 @@ class Speciation:
|
47 | 47 | grid_x = xs.foreign(UniformRectilinearGrid2D, "x")
|
48 | 48 | grid_y = xs.foreign(UniformRectilinearGrid2D, "y")
|
49 | 49 |
|
50 |
| - disp_boundary = xs.variable(default=None, description="dispersal boundaries as an xr.DataArray " |
51 |
| - "with vertices [[x,y],...] of bounded area " |
52 |
| - "with dimensions p and d", |
53 |
| - static=True, dims=[(), ('p', 'd')]) |
54 |
| - |
| 50 | + disp_boundary = xs.variable(default=None, description="dispersal boundary value to define minimum elevation of the island," \ |
| 51 | + " where individuals can disperse. Default None, no boundary is applied.", |
| 52 | + static=True) |
| 53 | + |
55 | 54 | _model = xs.any_object(description="speciation model instance")
|
56 | 55 | _individuals = xs.any_object(description="speciation model state dictionary")
|
57 | 56 |
|
@@ -127,6 +126,8 @@ class IR12Speciation(Speciation):
|
127 | 126 | description="individual's fitness value"
|
128 | 127 | )
|
129 | 128 |
|
| 129 | + topo_elevation = xs.foreign(SurfaceTopography, "elevation") |
| 130 | + |
130 | 131 | def _get_model_params(self):
|
131 | 132 | return {
|
132 | 133 | "r": self.r,
|
@@ -173,9 +174,20 @@ def run_step(self):
|
173 | 174 | self.abundance = self._model.abundance
|
174 | 175 | self._model.evaluate_fitness()
|
175 | 176 |
|
| 177 | + def _island_boundary(self): |
| 178 | + xx, yy = np.meshgrid(self.grid_x, self.grid_y) |
| 179 | + island_mask = self.topo_elevation > self.disp_boundary |
| 180 | + island_grid = np.column_stack((xx[island_mask], yy[island_mask])) |
| 181 | + cvhull = ConvexHull(island_grid) |
| 182 | + return island_grid[cvhull.vertices] |
| 183 | + |
176 | 184 | @xs.runtime(args='step_delta')
|
177 | 185 | def finalize_step(self, dt):
|
178 |
| - self._model.update_individuals(dt, self.disp_boundary) |
| 186 | + if self.disp_boundary is not None: |
| 187 | + boundary_points = self._island_boundary() |
| 188 | + self._model.update_individuals(dt, boundary_points) |
| 189 | + else: |
| 190 | + self._model.update_individuals(dt) |
179 | 191 |
|
180 | 192 | @fitness.compute
|
181 | 193 | def _get_fitness(self):
|
|
0 commit comments