From 39260b2790b499e9760f18b9707610eef221d28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 14:00:30 +0000 Subject: [PATCH 01/46] Create CONTRIBUTING.md --- CONTRIBUTING.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d5e8244 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,101 @@ +# The RangeShifter platform - An eco-evolutionary modelling framework + +## How to contribute + +Thank you for your interest in contributing to the RangeShifter platform. +In this document we will give you guidance on how to contribute to the RangeShifter project regarding issues, bug fixing and adding new features. In this guidance we distinguish between contributing to the RangeShifter core code and the R interface (RangeShiftR package). + +## Repo structure +![Rangeshifter repo structure](RangeShiftR/man/figures/RS_repos.png) + +RangeShifter is distributed with three user interfaces, each living in their own repo: + +- the RangeShifter GUI (clickable Windows interface)* +- RangeShifter Batch Mode (command line interface) +- the RangeShiftR package (R interface) + +All three share the same source code for the core simulation (i.e., the actual model), which lives in its own repo (RScore). Each of the interfaces keeps a copy of this core code in a subfolder called RScore, kept in sync with the RScore repo via a git subtree (see Git subtree usage section). + +*The RangeShifter GUI is currently being rewritten, and is not open source yet. + +### RangeShifter core code + +As mentioned above, the RangeShifter core code is located and maintained in thsi repo, which is currently only maintained by the RangeShifter development team. +Any changes regarding the RangeShifter core code should be done in this repository and afterwards synced with all interfaces using the git subtree feature (see [Git subtree usage section](https://github.com/RangeShifter/RangeShiftR-package-dev/blob/development-guidelines/CONTRIBUTING.md#git-subtree-usage)). + +#### Bugs + +To report a bug, please [open an issue](https://github.com/RangeShifter/RangeShiftR-package-dev/issues/new), using the Bug Report template. +Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch/issues) for the batch interface). +To propose a bug fix (thank you!!), please create and work on your own branch or fork, from either `main` or `develop` (preferred), and open a pull request when your fix is ready to be merged into the original branch. + +**For RangeShifter-batch only, (for now?):** as a prerequisite for merging, please ensure that your version passes status check (that is, RangeShifter can still build and run as intended). +This can be seen in the Actions panel for every commit and at the bottom of the pull request. + +Maintainers will review the pull request, possibly request changes, and eventually integrate the bug fix into RScore, and update the subtrees to bring the fix to all interfaces. + +#### New features + +Do you have an idea of a new feature in the RangeShifter platform that should be integrated and is of use for other RangeShifter users? +Please get in touch with the RangeShifter development team (rangeshiftr@uni-potsdam.de (*or other mail?*) to discuss a collaboration. + +Alternatively*, proceed as with the bug fix above: create your own branch or fork _from `develop`_ and work from there, and submit a pull request when your new features are ready to join the core code. +We recommend that you update your branch regularly to new changes on `develop` (using `git merge develop`) to reduce the risk of merge conflicts or your version getting out-of-touch in the late stages of development. +We also recommend that you work in small commits, as this makes the code easier to debug, and makes it easier for maintainers to understand your contributions when reviewing a pull request. + +*Do we welcome independent contributions? + + +*TODO - move the two sections below into their own document?* + +## Git usage + +## Git subtree usage + +In order to ensure that the same version of RangeShifter's core code is used by all three interfaces (RangeShiftR, RangeShifter-batch and the GUI), each interface repo keeps a copy of RScore as a git subtree. In this section we describe how to interact with RScore via these git subtrees. + +First, in a local clone of one of the interface repos, add a remote named `RScore` pointing to the RScore repo. This will be convenient as a shortcut for git subtree commands. + +```bash +git remote add RScore https://github.com/RangeShifter/RScore.git +``` + +### Pulling new changes + +To update the RScore subfolder with new changes made to the RScore repo, one can use the `git subtree pull` command: + +```bash +git subtree pull --prefix RScore +``` + +Note the path must match the location of the RScore subfolder, and the branch must match the one the subtree was originally added from (by default, this should be `main`). + +e.g. for RangeShifter-batch, use: + +```bash +git subtree pull --prefix src/RScore RScore main +``` + +while for RangeShiftR, use: + +```bash +git subtree pull --prefix RangeShiftR/src/RScore RScore main +``` + +### Pushing new changes to RScore + +We haven't yet found a way to push new changes made in a RScore subfolder back into the RScore repo. This is why we ask that contributions are made directly inside the RScore repo. + +If you know how to do this, please drop us a line! + +Alternatively, if you have already made changes on the subfolder, you could copy its contents into a new branch in RScore, then open a pull request. + +### Switching the subfolder to a new branch + +There is unfortunately to do so. To track a different branch of RScore, one must delete the RScore subfolder (via git) and import the subtree again: + +```bash +git rm src/RScore -r +git commit -m "switching subtree branch" +git subtree add --prefix src/RScore RScore +``` From de759524878671511c91ada2b152e3612bb4fbcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 15:17:11 +0000 Subject: [PATCH 02/46] Create git.md --- git.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 git.md diff --git a/git.md b/git.md new file mode 100644 index 0000000..39fed1e --- /dev/null +++ b/git.md @@ -0,0 +1,53 @@ +## Git usage + + +## Git subtree usage + +In order to ensure that the same version of RangeShifter's core code is used by all three interfaces (RangeShiftR, RangeShifter-batch and the GUI), each interface repo keeps a copy of RScore as a git subtree. In this section we describe how to interact with RScore via these git subtrees. + +First, in a local clone of one of the interface repos, add a remote named `RScore` pointing to the RScore repo. This will be convenient as a shortcut for git subtree commands. + +```bash +git remote add RScore https://github.com/RangeShifter/RScore.git +``` + +### Pulling new changes + +To update the RScore subfolder with new changes made to the RScore repo, one can use the `git subtree pull` command: + +```bash +git subtree pull --prefix RScore +``` + +The path must match the location of the RScore subfolder, and the branch must match the one the subtree was originally added from (by default, this should be `main`). + +e.g. for RangeShifter-batch, use: + +```bash +git subtree pull --prefix src/RScore RScore main +``` + +while for RangeShiftR, use: + +```bash +git subtree pull --prefix RangeShiftR/src/RScore RScore main +``` + +### Pushing new changes to RScore + +We haven't yet found a way to push new changes made in a RScore subfolder back into the RScore repo. This is why we ask that contributions are made directly inside the RScore repo. + +If you know how to do this, please drop us a line! + +Alternatively, if you have already made changes via the subfolder, you could copy its contents into a new branch in RScore, then open a pull request to merge. + +### Switching the subfolder to a new branch + +There is unfortunately no way to do so. +To track a different branch of RScore, one must delete the RScore subfolder (via git) and import the subtree again: + +```bash +git rm src/RScore -r +git commit -m "switching subtree branch" +git subtree add --prefix src/RScore RScore +``` From 2e579f26096e0da057ca9605d512535aa9c371ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 15:17:34 +0000 Subject: [PATCH 03/46] move git sections to git.md --- CONTRIBUTING.md | 55 ------------------------------------------------- 1 file changed, 55 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d5e8244..726a754 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,58 +44,3 @@ We recommend that you update your branch regularly to new changes on `develop` ( We also recommend that you work in small commits, as this makes the code easier to debug, and makes it easier for maintainers to understand your contributions when reviewing a pull request. *Do we welcome independent contributions? - - -*TODO - move the two sections below into their own document?* - -## Git usage - -## Git subtree usage - -In order to ensure that the same version of RangeShifter's core code is used by all three interfaces (RangeShiftR, RangeShifter-batch and the GUI), each interface repo keeps a copy of RScore as a git subtree. In this section we describe how to interact with RScore via these git subtrees. - -First, in a local clone of one of the interface repos, add a remote named `RScore` pointing to the RScore repo. This will be convenient as a shortcut for git subtree commands. - -```bash -git remote add RScore https://github.com/RangeShifter/RScore.git -``` - -### Pulling new changes - -To update the RScore subfolder with new changes made to the RScore repo, one can use the `git subtree pull` command: - -```bash -git subtree pull --prefix RScore -``` - -Note the path must match the location of the RScore subfolder, and the branch must match the one the subtree was originally added from (by default, this should be `main`). - -e.g. for RangeShifter-batch, use: - -```bash -git subtree pull --prefix src/RScore RScore main -``` - -while for RangeShiftR, use: - -```bash -git subtree pull --prefix RangeShiftR/src/RScore RScore main -``` - -### Pushing new changes to RScore - -We haven't yet found a way to push new changes made in a RScore subfolder back into the RScore repo. This is why we ask that contributions are made directly inside the RScore repo. - -If you know how to do this, please drop us a line! - -Alternatively, if you have already made changes on the subfolder, you could copy its contents into a new branch in RScore, then open a pull request. - -### Switching the subfolder to a new branch - -There is unfortunately to do so. To track a different branch of RScore, one must delete the RScore subfolder (via git) and import the subtree again: - -```bash -git rm src/RScore -r -git commit -m "switching subtree branch" -git subtree add --prefix src/RScore RScore -``` From 6f1b0cd3c63849be2cffdf7ca1acb8b586f589a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 15:26:41 +0000 Subject: [PATCH 04/46] Update CONTRIBUTING.md --- CONTRIBUTING.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 726a754..d97c774 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,39 @@ All three share the same source code for the core simulation (i.e., the actual m *The RangeShifter GUI is currently being rewritten, and is not open source yet. -### RangeShifter core code + +## Roles + +#### Maintainers +- @JetteReeg +- @TheoPannetier + +Maintainers are responsible for coordinating development efforts and ensuring that RangeShifter keeps building continuously. + +#### Developers +Regular contributors and members of the RangeShifter development team + +#### Contributors + +Anyone who whishes to make changes to RangeShifter's code, including regular developers. + +## Branching policy + +This policy applies to RScore and all three RangeShifter interfaces. +RangeShifter uses the following branching structure: + +- `main` is the default branch, where the stable releases live. Because it contains the version of RangeShifter that users normally interact with, it must be stable and build at all times. +Only maintainers should make changes to `main`, either directly for small changes (e.g. typo fixes), or by merging `develop` into `main` for any larger change. +- `develop` is the development branch containing new features not yet made available to users. +Contributors are welcome to make changes to `develop`, but because this is the version that every contributor uses as a reference, one should ensure that new changes do not break `develop`. +If one happens to break `develop`, it should be their first priority to fix it. +For this reason, we recommend working from feature branches instead. +- Feature branches are created from `develop` by contributors to work on a new feature or other change, e.g. `cmake`, `mutualism`, etc. +Contributors can also create their own branch, e.g. `theo` or `jette` to experiment with the code or implement miscellaneous changes. +Once a contributor deems their changes ready to be added to the development version, they should merge their changes from the feature branch into `develop`. +Optionally, we encourage contributors to seek a review from one or more developers and or maintainers by opening a pull request to merge their branch into develop. + +### Contributing to RangeShifter core code As mentioned above, the RangeShifter core code is located and maintained in thsi repo, which is currently only maintained by the RangeShifter development team. Any changes regarding the RangeShifter core code should be done in this repository and afterwards synced with all interfaces using the git subtree feature (see [Git subtree usage section](https://github.com/RangeShifter/RangeShiftR-package-dev/blob/development-guidelines/CONTRIBUTING.md#git-subtree-usage)). From b63f539578794fa520ca2022dec3a7c65dd66f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 15:31:45 +0000 Subject: [PATCH 05/46] add rs_repos figures --- RS_repos.png | Bin 0 -> 550746 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 RS_repos.png diff --git a/RS_repos.png b/RS_repos.png new file mode 100644 index 0000000000000000000000000000000000000000..b138a01541cc2311bea5e501e3c820f694379e9d GIT binary patch literal 550746 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�y%(n6^hLBlclghmjeMKv6FA+ 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

9a)$#PIHaL%XAO$s|SEF3%S~SB0~Q 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

9uUlLJu&pJS-@1s{&zPq4`Z_hE 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%0A(3fA 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 z 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 C-JS6O literal 0 HcmV?d00001 From 9536d985a9c3d8b63416085d6b24120a2bedf446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 15:44:03 +0000 Subject: [PATCH 06/46] fix pic and user page links --- CONTRIBUTING.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d97c774..2999fb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ Thank you for your interest in contributing to the RangeShifter platform. In this document we will give you guidance on how to contribute to the RangeShifter project regarding issues, bug fixing and adding new features. In this guidance we distinguish between contributing to the RangeShifter core code and the R interface (RangeShiftR package). ## Repo structure -![Rangeshifter repo structure](RangeShiftR/man/figures/RS_repos.png) +![Rangeshifter repo structure](RS_repos.png) RangeShifter is distributed with three user interfaces, each living in their own repo: @@ -18,17 +18,16 @@ All three share the same source code for the core simulation (i.e., the actual m *The RangeShifter GUI is currently being rewritten, and is not open source yet. - ## Roles #### Maintainers -- @JetteReeg -- @TheoPannetier +- [@JetteReeg](https://github.com/JetteReeg) +- [@TheoPannetier](https://github.com/TheoPannetier) Maintainers are responsible for coordinating development efforts and ensuring that RangeShifter keeps building continuously. #### Developers -Regular contributors and members of the RangeShifter development team +Regular contributors and members of the [RangeShifter development team](https://github.com/orgs/RangeShifter/people) #### Contributors From ae4860204fea99786baa23f4b8dc617d98a92b60 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 21 Nov 2023 16:41:45 +0000 Subject: [PATCH 07/46] proper README and updating CONTRIBUTING #14 --- .gitignore | 4 +++ CONTRIBUTING.md | 24 +++++++++-------- README.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++-- RScore_logo.png | Bin 0 -> 95923 bytes git.md | 53 ------------------------------------- 5 files changed, 83 insertions(+), 66 deletions(-) create mode 100644 RScore_logo.png delete mode 100644 git.md diff --git a/.gitignore b/.gitignore index 31831ca..1039657 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,7 @@ vignettes/*.pdf # compilation files *.o + +# Visual Studio +.vs/ +out/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2999fb2..96ed93f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,9 +3,10 @@ ## How to contribute Thank you for your interest in contributing to the RangeShifter platform. -In this document we will give you guidance on how to contribute to the RangeShifter project regarding issues, bug fixing and adding new features. In this guidance we distinguish between contributing to the RangeShifter core code and the R interface (RangeShiftR package). +In this document we will give you guidance on how to contribute to the RangeShifter project regarding issues, bug fixing and adding new features. ## Repo structure + ![Rangeshifter repo structure](RS_repos.png) RangeShifter is distributed with three user interfaces, each living in their own repo: @@ -14,19 +15,21 @@ RangeShifter is distributed with three user interfaces, each living in their own - RangeShifter Batch Mode (command line interface) - the RangeShiftR package (R interface) -All three share the same source code for the core simulation (i.e., the actual model), which lives in its own repo (RScore). Each of the interfaces keeps a copy of this core code in a subfolder called RScore, kept in sync with the RScore repo via a git subtree (see Git subtree usage section). +All three share the same source code for the core simulation (i.e., the actual model), which lives in this repo (RScore). Each of the interfaces keeps a copy of this core code in a subfolder called RScore, kept in sync with the RScore repo via a git subtree (see Git subtree usage section). *The RangeShifter GUI is currently being rewritten, and is not open source yet. ## Roles #### Maintainers + - [@JetteReeg](https://github.com/JetteReeg) - [@TheoPannetier](https://github.com/TheoPannetier) Maintainers are responsible for coordinating development efforts and ensuring that RangeShifter keeps building continuously. #### Developers + Regular contributors and members of the [RangeShifter development team](https://github.com/orgs/RangeShifter/people) #### Contributors @@ -39,20 +42,19 @@ This policy applies to RScore and all three RangeShifter interfaces. RangeShifter uses the following branching structure: - `main` is the default branch, where the stable releases live. Because it contains the version of RangeShifter that users normally interact with, it must be stable and build at all times. -Only maintainers should make changes to `main`, either directly for small changes (e.g. typo fixes), or by merging `develop` into `main` for any larger change. + Only maintainers should make changes to `main`, either directly for small changes (e.g. typo fixes), or by merging `develop` into `main` for any larger change. - `develop` is the development branch containing new features not yet made available to users. -Contributors are welcome to make changes to `develop`, but because this is the version that every contributor uses as a reference, one should ensure that new changes do not break `develop`. -If one happens to break `develop`, it should be their first priority to fix it. -For this reason, we recommend working from feature branches instead. + Contributors are welcome to make changes to `develop`, but because this is the version that every contributor uses as a reference, one should ensure that new changes do not break `develop`. + If one happens to break `develop`, it should be their first priority to fix it. + For this reason, we recommend working from feature branches instead. - Feature branches are created from `develop` by contributors to work on a new feature or other change, e.g. `cmake`, `mutualism`, etc. -Contributors can also create their own branch, e.g. `theo` or `jette` to experiment with the code or implement miscellaneous changes. -Once a contributor deems their changes ready to be added to the development version, they should merge their changes from the feature branch into `develop`. -Optionally, we encourage contributors to seek a review from one or more developers and or maintainers by opening a pull request to merge their branch into develop. + Contributors can also create their own branch, e.g. `theo` or `jette` to experiment with the code or implement miscellaneous changes. + Once a contributor deems their changes ready to be added to the development version, they should merge their changes from the feature branch into `develop`. + Optionally, we encourage contributors to seek a review from one or more developers and or maintainers by opening a pull request to merge their branch into develop. ### Contributing to RangeShifter core code -As mentioned above, the RangeShifter core code is located and maintained in thsi repo, which is currently only maintained by the RangeShifter development team. -Any changes regarding the RangeShifter core code should be done in this repository and afterwards synced with all interfaces using the git subtree feature (see [Git subtree usage section](https://github.com/RangeShifter/RangeShiftR-package-dev/blob/development-guidelines/CONTRIBUTING.md#git-subtree-usage)). +Any changes regarding the RangeShifter core code should be done in this repository and can afterwards be synced with all interfaces using the git subtree feature (see [Git subtree](https://github.com/RangeShifter/RScore/tree/main#usage-git-subtrees) section in the README). #### Bugs diff --git a/README.md b/README.md index 10a8386..6463793 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,67 @@ -# Rangeshifter core code +# RangeShifter core code -This repo contains the core simulation code for RangeShifter v2.0 +![](https://github.com/RangeShifter/RScore/blob/development-guidelines/RScore_logo.png) + +This repo contains the core simulation code for RangeShifter v2.0 and is not meant to be compiled or run on its own. + +If you are only interested in using RangeShifter, you can ignore this and head to the repo of one of the interfaces: + +- [WIP] RangeShifter GUI + +- [RangeShiftR](https://github.com/RangeShifter/RangeShiftR-pkg) + +- [RangeShifter-batch](https://github.com/RangeShifter/RangeShifter_batch) + +## Usage: git subtree + +In order to ensure that the same version of RangeShifter's core code is used by all three interfaces (RangeShiftR, RangeShifter-batch and the GUI), each interface repo keeps a copy of RScore as a git subtree. In this section, we describe how to use the git subtrees to update the subfolder and copy this repo anew. + +First, in a local clone of one of the interface repos, add a remote named `RScore` pointing to the RScore repo. This will be convenient as a shortcut for git subtree commands. + +```bash +git remote add RScore https://github.com/RangeShifter/RScore.git +``` + +### Pulling new changes + +To update the RScore subfolder with new changes made to the RScore repo, one can use the `git subtree pull` command: + +```bash +git subtree pull --prefix RScore +``` + +Note the path must match the location of the RScore subfolder, and the branch must match the one the subtree was originally added from (by default, this should be `main`). + +e.g. for RangeShifter-batch, use: + +```bash +git subtree pull --prefix src/RScore RScore main +``` + +while for RangeShiftR, use: + +```bash +git subtree pull --prefix RangeShiftR/src/RScore RScore main +``` + +### Pushing new changes to RScore + +We haven't yet found a way to push new changes made in a RScore subfolder back into the RScore repo. This is why we ask that contributions are made directly inside the RScore repo. + +If you know how to do this, please drop us a line! + +Alternatively, if you have already made changes on the subfolder, you could copy its contents into a new branch in RScore, then open a pull request. + +### Switching the subfolder to a new branch + +There is unfortunately to do so. To track a different branch of RScore, one must delete the RScore subfolder (via git) and import the subtree again: + +```bash +git rm src/RScore -r +git commit -m "switching subtree branch" +git subtree add --prefix src/RScore RScore +``` + +## Contributing to RangeShifter core code + +See [CONTRIBUTING](https://github.com/RangeShifter/RScore/blob/main/CONTRIBUTING.md). diff --git a/RScore_logo.png b/RScore_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..dfce26753c37fc9289b9333486a8e7dbaba4422f GIT binary patch literal 95923 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 literal 0 HcmV?d00001 diff --git a/git.md b/git.md deleted file mode 100644 index 39fed1e..0000000 --- a/git.md +++ /dev/null @@ -1,53 +0,0 @@ -## Git usage - - -## Git subtree usage - -In order to ensure that the same version of RangeShifter's core code is used by all three interfaces (RangeShiftR, RangeShifter-batch and the GUI), each interface repo keeps a copy of RScore as a git subtree. In this section we describe how to interact with RScore via these git subtrees. - -First, in a local clone of one of the interface repos, add a remote named `RScore` pointing to the RScore repo. This will be convenient as a shortcut for git subtree commands. - -```bash -git remote add RScore https://github.com/RangeShifter/RScore.git -``` - -### Pulling new changes - -To update the RScore subfolder with new changes made to the RScore repo, one can use the `git subtree pull` command: - -```bash -git subtree pull --prefix RScore -``` - -The path must match the location of the RScore subfolder, and the branch must match the one the subtree was originally added from (by default, this should be `main`). - -e.g. for RangeShifter-batch, use: - -```bash -git subtree pull --prefix src/RScore RScore main -``` - -while for RangeShiftR, use: - -```bash -git subtree pull --prefix RangeShiftR/src/RScore RScore main -``` - -### Pushing new changes to RScore - -We haven't yet found a way to push new changes made in a RScore subfolder back into the RScore repo. This is why we ask that contributions are made directly inside the RScore repo. - -If you know how to do this, please drop us a line! - -Alternatively, if you have already made changes via the subfolder, you could copy its contents into a new branch in RScore, then open a pull request to merge. - -### Switching the subfolder to a new branch - -There is unfortunately no way to do so. -To track a different branch of RScore, one must delete the RScore subfolder (via git) and import the subtree again: - -```bash -git rm src/RScore -r -git commit -m "switching subtree branch" -git subtree add --prefix src/RScore RScore -``` From 7faf3e1591a591c5d75a6ee3e302a023cec43c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 17:48:21 +0000 Subject: [PATCH 08/46] Create git_cheatsheet.md --- git_cheatsheet.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 git_cheatsheet.md diff --git a/git_cheatsheet.md b/git_cheatsheet.md new file mode 100644 index 0000000..53ca175 --- /dev/null +++ b/git_cheatsheet.md @@ -0,0 +1,107 @@ +# Git Cheatsheet + +Quick reference on Git usage for RangeShifter contributors + +#### Creating a local copy of this repo + +```bash +git clone https://github.com/RangeShifter/RScore.git +``` + +#### Enquire about the current state of changes + +``` +git status +``` +This will display whether the local branch is up-to-date with its GitHub counterpart, what files have been changed and if they are staged for commit or not. + +#### Updating the active branch with latest changes (pulling) + +```bash +git pull +``` + +#### Updating the active branch with another branch (merging) + +```bash +git merge +``` + +Merging may trigger a merge conflict is the same lines have been changed on both branches. See Solving Merge Conflict below. + +#### Staging changes to be committed +Changes to local files must first be added to the commit queue ("staged") before being committed. + +```bash +git add # single file +git add . # entire active folder +``` + +#### Creating a commit + +```bash +git commit -m "commit message" +``` + +A good commit message is concise, but descriptive. + +#### Uploading local commits to GitHub (pushing) + +```bash +git push +``` + +#### Switching to an existing branch + +```bash +git checkout +``` +Switching does not update the new active branch with GitHub automatically, so make sure to pull after switching! + +#### Creating a new branch from active branch + +```bash +git branch +``` +You will also need to set the corresponding branch on `origin` (GitHub) before you can push: + +```bash +git push --set-upstream origin +``` + +New branches can also be created on GitHub (drop-down button in the top-left corner of the main page). +New branches on GitHub are brought to the local copy with the next pull. + +#### Deleting a branch locally + +```bash +git branch -d +``` + +#### Instruct Git to not track some files + +Open `.gitignore` and add the path to the files or folders to exclude from the git history. +Check with `git status` that the files are indeed not tracked by git anymore. + +#### Solving a merge conflict +Merge conflicts can arise when multiple contributors simulatneously change the same line of code. +In such cases, git is incapable of deciding which version should be kept and asks for human input. +Git tells you which files are affected by the conflict. +Open each file and resolve **each** section that looks like this: + +``` +After opening the box, we can affirm that +<<<<<<<<<<< HEAD # delete this line +Shroedinger's cat is alive. # delete either this... +================ # delete this line +Shroedinger's cat is dead. # ... or this (or keep both, or none, or a different solution) +>>>>>>>>>>> SHA # delete this line +What an insightful result! +``` + +Ctrl+F "HEAD" is really helpful for finding the conflicts in large files. +When you are done, create a commit stating e.g. "solved merge conflict" and push. + +## Git subtrees + +See [Git subtrees](https://github.com/RangeShifter/RScore/tree/development-guidelines#usage-git-subtree) section in README. From a87d4f41d1fac080b55ed59bb8c661d00feaace6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Tue, 21 Nov 2023 18:00:39 +0000 Subject: [PATCH 09/46] fix logo placement --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6463793..22611a5 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# RangeShifter core code - -![](https://github.com/RangeShifter/RScore/blob/development-guidelines/RScore_logo.png) +# RangeShifter core code This repo contains the core simulation code for RangeShifter v2.0 and is not meant to be compiled or run on its own. + + If you are only interested in using RangeShifter, you can ignore this and head to the repo of one of the interfaces: - [WIP] RangeShifter GUI From f856ac7fd4eb3b161772868b5b337c5858383f0d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 23 Nov 2023 12:35:44 +0000 Subject: [PATCH 10/46] revise branching policy --- CONTRIBUTING.md | 31 +++++++++++++++++-------------- branches.png | Bin 0 -> 93065 bytes 2 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 branches.png diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96ed93f..cd66c7f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,7 +30,7 @@ Maintainers are responsible for coordinating development efforts and ensuring th #### Developers -Regular contributors and members of the [RangeShifter development team](https://github.com/orgs/RangeShifter/people) +Regular contributors and members of the [RangeShifter development team](https://github.com/orgs/RangeShifter/people), including maintainers. #### Contributors @@ -38,19 +38,25 @@ Anyone who whishes to make changes to RangeShifter's code, including regular dev ## Branching policy +![](branches.png) + This policy applies to RScore and all three RangeShifter interfaces. RangeShifter uses the following branching structure: -- `main` is the default branch, where the stable releases live. Because it contains the version of RangeShifter that users normally interact with, it must be stable and build at all times. - Only maintainers should make changes to `main`, either directly for small changes (e.g. typo fixes), or by merging `develop` into `main` for any larger change. -- `develop` is the development branch containing new features not yet made available to users. - Contributors are welcome to make changes to `develop`, but because this is the version that every contributor uses as a reference, one should ensure that new changes do not break `develop`. - If one happens to break `develop`, it should be their first priority to fix it. - For this reason, we recommend working from feature branches instead. -- Feature branches are created from `develop` by contributors to work on a new feature or other change, e.g. `cmake`, `mutualism`, etc. - Contributors can also create their own branch, e.g. `theo` or `jette` to experiment with the code or implement miscellaneous changes. - Once a contributor deems their changes ready to be added to the development version, they should merge their changes from the feature branch into `develop`. - Optionally, we encourage contributors to seek a review from one or more developers and or maintainers by opening a pull request to merge their branch into develop. +- `main` is the default branch, where stable releases live. Because it contains the version of RangeShifter that users normally interact with, it must be stable and build at all times. + Only maintainers should make significant changes to `main`, normally by merging `develop` into `main` to make newly developed features available to users, and marking a release while doing so. +- `develop` is the development branch containing new, in-development features. It is the reference branch for all developers. Contributors may make small changes directly to `develop` but should ensure that new changes do not break the build. If one happens to break `develop`, it should be their top priority to fix it as this will disrupt the work of all other contributors. + Larger changes should instead be developed on feature branches. +- Larger changes should be first developed on feature (e.g. `cmake`, `mutualism`, etc.) or contributor (e.g., `theo`) branches. Contributors are welcome to experiment and break such branches at any time, as this will not impact users or other contributors. + + When progress is deemed satisfactory, changes can be brought to `develop`. Please open a pull request on GitHub, and assign at least one maintainer as a reviewer. As a pre-requisite, RangeShifter must build on the branch before merging. Please enter a descriptive title and use the description field to describe what you have changed. + + In the meantime, we encourage contributors to work in small and frequent commits, and to merge `develop` into their branch often to update their branch with newest changes. + + + + +If you need a reminder on the main git commands related to committing and branching, head to the [Git cheatsheet](https://github.com/RangeShifter/RScore/blob/development-guidelines/git_cheatsheet.md). ### Contributing to RangeShifter core code @@ -62,9 +68,6 @@ To report a bug, please [open an issue](https://github.com/RangeShifter/RangeShi Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch/issues) for the batch interface). To propose a bug fix (thank you!!), please create and work on your own branch or fork, from either `main` or `develop` (preferred), and open a pull request when your fix is ready to be merged into the original branch. -**For RangeShifter-batch only, (for now?):** as a prerequisite for merging, please ensure that your version passes status check (that is, RangeShifter can still build and run as intended). -This can be seen in the Actions panel for every commit and at the bottom of the pull request. - Maintainers will review the pull request, possibly request changes, and eventually integrate the bug fix into RScore, and update the subtrees to bring the fix to all interfaces. #### New features diff --git a/branches.png b/branches.png new file mode 100644 index 0000000000000000000000000000000000000000..12e3a96ea82f7e3be71fb3ce0ac4294e2f287a18 GIT binary patch literal 93065 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

Er)FTB;GmW=8QOt+z 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 literal 0 HcmV?d00001 From 6a9e15af2dad97895d8cdf73cf2d4e8d70be73a2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 23 Nov 2023 13:42:36 +0000 Subject: [PATCH 11/46] draft for main --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31e59e4..4a1584e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Config file for compilation with CMake # Only relevant for Batch mode, but this file needs to live in the RScore folder -add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp) +add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp "Main.cpp") # pass config definitions to compiler if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") From 6fefa2104864dfaebaa834a5b44ebdd166f40079 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 23 Nov 2023 13:42:50 +0000 Subject: [PATCH 12/46] draft for main --- Main.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Main.cpp diff --git a/Main.cpp b/Main.cpp new file mode 100644 index 0000000..74b036f --- /dev/null +++ b/Main.cpp @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------------- + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * + * This file is part of RangeShifter. + * + * RangeShifter is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RangeShifter is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RangeShifter. If not, see . + * + --------------------------------------------------------------------------*/ + +#include +#include +#include + +using namespace std; + +#if LINUX_CLUSTER || R_CMD +#include +#else +#include +#endif + +void assert_error(const string& exptd_err_msg, void (*x)(void)) { + string err_msg{ "No error.\n" }; + try { x(); } + catch (exception& e) { err_msg = e.what(); } + assert(err_msg == exptd_err_msg); +} + +void run_unit_tests() { + cout << "******* Unit test output *******" << endl; + testRSrandom(); + testIndividual(); + cout << endl << "************************" << endl; +} + +#if LINUX_CLUSTER || RS_RCPP +int main(int argc, char* argv[]) +#else +int _tmain(int argc, _TCHAR* argv[]) +#endif +{ +#ifdef NDEBUG + cout << "This code is only for running tests and not meant to run in release." << endl; + return 1; +# else + assert(0.1 > 0.0); // assert does run correctly + run_unit_tests(); + cout << "All tests have completed." << endl; + return 0; // if tests succeed, we are happy +# endif // NDEBUG +} \ No newline at end of file From febd01c64f9f03a52b70ba84c56a0ad73587cf20 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 23 Nov 2023 13:45:03 +0000 Subject: [PATCH 13/46] import changes from rs_batch_dev::unit_test --- CMakeLists.txt | 14 +- Individual.cpp | 3400 ++++++++++++++++++++---------------------------- Individual.h | 15 +- Landscape.cpp | 8 +- Population.cpp | 3080 ++++++++++++++++++------------------------- Population.h | 3 - RSrandom.cpp | 29 +- RSrandom.h | 6 +- Utils.cpp | 9 + Utils.h | 12 + 10 files changed, 2730 insertions(+), 3846 deletions(-) create mode 100644 Utils.cpp create mode 100644 Utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a1584e..56c5971 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,17 @@ # Config file for compilation with CMake # Only relevant for Batch mode, but this file needs to live in the RScore folder -add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp "Main.cpp") +add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) # pass config definitions to compiler +target_compile_definitions(RScore PRIVATE RSWIN64) + +# enable LINUX_CLUSTER macro on Linux + macOS if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64" "LINUX_CLUSTER") -else() # Windows - target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64") + add_compile_definitions("LINUX_CLUSTER") +endif() + +# Debug Mode by default, unless "release" is passed +if(NOT DEFINED release) + add_compile_definitions(RSDEBUG) endif() \ No newline at end of file diff --git a/Individual.cpp b/Individual.cpp index 357f175..cc7bf6e 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Individual.h" //--------------------------------------------------------------------------- @@ -30,82 +30,70 @@ int Individual::indCounter = 0; //--------------------------------------------------------------------------- // Individual constructor -Individual::Individual(Cell *pCell,Patch *pPatch,short stg,short a,short repInt, - float probmale,bool movt,short moveType) +Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short repInt, + float probmale, bool movt, short moveType) { -indId = indCounter; indCounter++; // unique identifier for each individual -#if RSDEBUG -//DEBUGLOG << "Individual::Individual(): indId=" << indId -// << " stg=" << stg << " a=" << a << " probmale=" << probmale -// << endl; -#endif + indId = indCounter; + indCounter++; // unique identifier for each individual -stage = stg; -if (probmale <= 0.0) sex = 0; -else sex = pRandom->Bernoulli(probmale); -age = a; -status = 0; + stage = stg; + if (probmale <= 0.0) sex = 0; + else sex = pRandom->Bernoulli(probmale); + age = a; + status = 0; -if (sex == 0 && repInt > 0) { // set no. of fallow seasons for female - fallow = pRandom->IRandom(0,repInt); -} -else fallow = 9999; -isDeveloping = false; -pPrevCell = pCurrCell = pCell; -pNatalPatch = pPatch; -if (movt) { - locn loc = pCell->getLocn(); - path = new pathData; - path->year = 0; path->total = 0; path->out = 0; - path->pSettPatch = 0; path->settleStatus = 0; -// path->leftNatalPatch = false; + if (sex == 0 && repInt > 0) { // set no. of fallow seasons for female + fallow = pRandom->IRandom(0, repInt); + } + else fallow = 9999; + isDeveloping = false; + pPrevCell = pCurrCell = pCell; + pNatalPatch = pPatch; + if (movt) { + locn loc = pCell->getLocn(); + path = new pathData; + path->year = 0; path->total = 0; path->out = 0; + path->pSettPatch = 0; path->settleStatus = 0; #if RS_RCPP - path->pathoutput = 1; -#endif - if (moveType == 1) { // SMS - // set up location data for SMS - smsData = new smsdata; - smsData->dp = smsData->gb = smsData->alphaDB = 1.0; - smsData->betaDB = 1; - smsData->prev.x = loc.x; smsData->prev.y = loc.y; // previous location - smsData->goal.x = loc.x; smsData->goal.y = loc.y; // goal location - initialised for dispersal bias - } - else smsData = 0; - if (moveType == 2) { // CRW - // set up continuous co-ordinates etc. for CRW movement - crw = new crwParams; - crw->xc = ((float)pRandom->Random()*0.999f) + (float)loc.x; - crw->yc = (float)(pRandom->Random()*0.999f) + (float)loc.y; - crw->prevdrn = (float)(pRandom->Random()*2.0 * PI); - crw->stepL = crw->rho = 0.0; - } - else crw = 0; -} -else { - path = 0; crw = 0; smsData = 0; -} -emigtraits = 0; -kerntraits = 0; -setttraits = 0; -pGenome = 0; -#if RSDEBUG -//locn currloc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::Individual(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -//// << " smsData=" << smsData << " dp=" << smsData->dp -// << endl; -#endif + path->pathoutput = 1; +#endif + if (moveType == 1) { // SMS + // set up location data for SMS + smsData = new smsdata; + smsData->dp = smsData->gb = smsData->alphaDB = 1.0; + smsData->betaDB = 1; + smsData->prev.x = loc.x; smsData->prev.y = loc.y; // previous location + smsData->goal.x = loc.x; smsData->goal.y = loc.y; // goal location - initialised for dispersal bias + } + else smsData = 0; + if (moveType == 2) { // CRW + // set up continuous co-ordinates etc. for CRW movement + crw = new crwParams; + crw->xc = ((float)pRandom->Random() * 0.999f) + (float)loc.x; + crw->yc = (float)(pRandom->Random() * 0.999f) + (float)loc.y; + crw->prevdrn = (float)(pRandom->Random() * 2.0 * PI); + crw->stepL = crw->rho = 0.0; + } + else crw = 0; + } + else { + path = 0; crw = 0; smsData = 0; + } + emigtraits = 0; + kerntraits = 0; + setttraits = 0; + pGenome = 0; } Individual::~Individual(void) { -if (path != 0) delete path; -if (crw != 0) delete crw; -if (smsData != 0) delete smsData; -if (emigtraits != 0) delete emigtraits; -if (kerntraits != 0) delete kerntraits; -if (setttraits != 0) delete setttraits; + if (path != 0) delete path; + if (crw != 0) delete crw; + if (smsData != 0) delete smsData; + if (emigtraits != 0) delete emigtraits; + if (kerntraits != 0) delete kerntraits; + if (setttraits != 0) delete setttraits; -if (pGenome != 0) delete pGenome; + if (pGenome != 0) delete pGenome; } @@ -114,376 +102,301 @@ if (pGenome != 0) delete pGenome; //--------------------------------------------------------------------------- // Set genes for individual variation from species initialisation parameters -void Individual::setGenes(Species *pSpecies,int resol) { -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -simParams sim = paramsSim->getSim(); -int ntraits; // first trait for all/female expression, second for male expression - -if (gen.trait1Chromosome) { - pGenome = new Genome(pSpecies->getNChromosomes(),pSpecies->getNLoci(0), - pSpecies->isDiploid()); -} -else { - pGenome = new Genome(pSpecies); -} -#if RSDEBUG -//DEBUGLOG << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " sex=" << sex -// << " trait1Chromosome=" << gen.trait1Chromosome << " pGenome=" << pGenome -// << endl; -#endif - -int gposn = 0; // current position on genome -int expr = 0; // gene expression type - NOT CURRENTLY USED - -//int emigposn = 0; -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): emigration genes" << endl; -#endif -if (emig.indVar) { // set emigration genes - int emigposn = gposn; - double d0,alpha,beta; - emigParams eparams; -// emigScales scale = pSpecies->getEmigScales(); - if (emig.sexDep) { // must be a sexual species - ntraits = 2; +void Individual::setGenes(Species* pSpecies, int resol) { + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + simParams sim = paramsSim->getSim(); + int ntraits; // first trait for all/female expression, second for male expression + + if (gen.trait1Chromosome) { + pGenome = new Genome(pSpecies->getNChromosomes(), pSpecies->getNLoci(0), + pSpecies->isDiploid()); } else { - if (dem.repType == 0) { // asexual reproduction (haploid) - ntraits = 1; - } - else { // sexual reproduction - ntraits = 1; - } + pGenome = new Genome(pSpecies); } - for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males - eparams = pSpecies->getEmigParams(0,g); - d0 = pRandom->Normal(0.0,eparams.d0SD) / eparams.d0Scale; - if (emig.densDep) { - alpha = pRandom->Normal(0.0,eparams.alphaSD) / eparams.alphaScale; - beta = pRandom->Normal(0.0,eparams.betaSD) / eparams.betaScale; + + int gposn = 0; // current position on genome + int expr = 0; // gene expression type - NOT CURRENTLY USED + + if (emig.indVar) { // set emigration genes + int emigposn = gposn; + double d0, alpha, beta; + emigParams eparams; + if (emig.sexDep) { // must be a sexual species + ntraits = 2; } -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " eparams.d0Mean=" << eparams.d0Mean << " eparams.d0SD=" << eparams.d0SD -// << " eparams.d0Scale=" << eparams.d0Scale << " d0=" << d0 -//// << " log(d0/(1.0-d0))=" << log(d0/(1.0-d0)) -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " eparams.alphaMean=" << eparams.alphaMean << " eparams.alphaSD=" << eparams.alphaSD -// << " eparams.alphaScale=" << eparams.alphaScale << " alpha=" << alpha -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD -// << " eparams.betaScale=" << eparams.betaScale << " beta=" << beta -// << endl; -#endif - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,d0,gen.alleleSD); - if (emig.densDep) { - pGenome->setGene(gposn++,expr,alpha,gen.alleleSD); - pGenome->setGene(gposn++,expr,beta,gen.alleleSD); + else { + if (dem.repType == 0) { // asexual reproduction (haploid) + ntraits = 1; + } + else { // sexual reproduction + ntraits = 1; } } - else { - pGenome->setTrait(pSpecies,gposn++,d0,gen.alleleSD); + for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males + eparams = pSpecies->getEmigParams(0, g); + d0 = pRandom->Normal(0.0, eparams.d0SD) / eparams.d0Scale; if (emig.densDep) { - pGenome->setTrait(pSpecies,gposn++,alpha,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,beta,gen.alleleSD); + alpha = pRandom->Normal(0.0, eparams.alphaSD) / eparams.alphaScale; + beta = pRandom->Normal(0.0, eparams.betaSD) / eparams.betaScale; + } + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, d0, gen.alleleSD); + if (emig.densDep) { + pGenome->setGene(gposn++, expr, alpha, gen.alleleSD); + pGenome->setGene(gposn++, expr, beta, gen.alleleSD); + } + } + else { + pGenome->setTrait(pSpecies, gposn++, d0, gen.alleleSD); + if (emig.densDep) { + pGenome->setTrait(pSpecies, gposn++, alpha, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, beta, gen.alleleSD); + } } } - } - // record phenotypic traits - if (emig.densDep) { - setEmigTraits(pSpecies,emigposn,3,emig.sexDep); - } - else { - setEmigTraits(pSpecies,emigposn,1,emig.sexDep); - } -} - -//int trfrposn = 0; -if (trfr.indVar) { // set transfer genes - int trfrposn = gposn; - if (trfr.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ntraits = 1; + // record phenotypic traits + if (emig.densDep) { + setEmigTraits(pSpecies, emigposn, 3, emig.sexDep); } - else { // sexual reproduction - ntraits = 1; + else { + setEmigTraits(pSpecies, emigposn, 1, emig.sexDep); } } -// trfrScales scale = pSpecies->getTrfrScales(); - if (trfr.moveModel) { - if (trfr.moveType == 1) { // set SMS genes - double dp,gb,alphaDB,betaDB; - trfrSMSParams smsparams = pSpecies->getSMSParams(0,0); // only traits for females/all - trfrSMSTraits smstraits = pSpecies->getSMSTraits(); - dp = pRandom->Normal(0.0,smsparams.dpSD) / smsparams.dpScale; - gb = pRandom->Normal(0.0,smsparams.gbSD) / smsparams.gbScale; - if (smstraits.goalType == 2) { - alphaDB = pRandom->Normal(0.0,smsparams.alphaDBSD) / smsparams.alphaDBScale; - betaDB = pRandom->Normal(0.0,smsparams.betaDBSD) / smsparams.betaDBScale; + + //int trfrposn = 0; + if (trfr.indVar) { // set transfer genes + int trfrposn = gposn; + if (trfr.sexDep) { // must be a sexual species + ntraits = 2; + } + else { + if (dem.repType == 0) { // asexual reproduction + ntraits = 1; } - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,dp,gen.alleleSD); - pGenome->setGene(gposn++,expr,gb,gen.alleleSD); + else { // sexual reproduction + ntraits = 1; + } + } + if (trfr.moveModel) { + if (trfr.moveType == 1) { // set SMS genes + double dp, gb, alphaDB, betaDB; + trfrSMSParams smsparams = pSpecies->getSMSParams(0, 0); // only traits for females/all + trfrSMSTraits smstraits = pSpecies->getSMSTraits(); + dp = pRandom->Normal(0.0, smsparams.dpSD) / smsparams.dpScale; + gb = pRandom->Normal(0.0, smsparams.gbSD) / smsparams.gbScale; if (smstraits.goalType == 2) { - pGenome->setGene(gposn++,expr,alphaDB,gen.alleleSD); - pGenome->setGene(gposn++,expr,betaDB,gen.alleleSD); + alphaDB = pRandom->Normal(0.0, smsparams.alphaDBSD) / smsparams.alphaDBScale; + betaDB = pRandom->Normal(0.0, smsparams.betaDBSD) / smsparams.betaDBScale; + } + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, dp, gen.alleleSD); + pGenome->setGene(gposn++, expr, gb, gen.alleleSD); + if (smstraits.goalType == 2) { + pGenome->setGene(gposn++, expr, alphaDB, gen.alleleSD); + pGenome->setGene(gposn++, expr, betaDB, gen.alleleSD); + } + } + else { + pGenome->setTrait(pSpecies, gposn++, dp, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, gb, gen.alleleSD); + if (smstraits.goalType == 2) { + pGenome->setTrait(pSpecies, gposn++, alphaDB, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, betaDB, gen.alleleSD); + } } + // record phenotypic traits + if (smstraits.goalType == 2) + setSMSTraits(pSpecies, trfrposn, 4, false); + else + setSMSTraits(pSpecies, trfrposn, 2, false); } - else { - pGenome->setTrait(pSpecies,gposn++,dp,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,gb,gen.alleleSD); - if (smstraits.goalType == 2) { - pGenome->setTrait(pSpecies,gposn++,alphaDB,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,betaDB,gen.alleleSD); + if (trfr.moveType == 2) { // set CRW genes + double stepL, rho; + trfrCRWParams m = pSpecies->getCRWParams(0, 0); // only traits for females/all + stepL = pRandom->Normal(0.0, m.stepLgthSD) / m.stepLScale; + rho = pRandom->Normal(0.0, m.rhoSD) / m.rhoScale; + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, stepL, gen.alleleSD); + pGenome->setGene(gposn++, expr, rho, gen.alleleSD); + } + else { + pGenome->setTrait(pSpecies, gposn++, stepL, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, rho, gen.alleleSD); + } + // record phenotypic traits + setCRWTraits(pSpecies, trfrposn, 2, false); + } + } + else { // set kernel genes + double dist1, dist2, prob1; + trfrKernParams k; + for (int g = 0; g < ntraits; g++) { // first traits for females/all, second for males + k = pSpecies->getKernParams(0, g); + dist1 = pRandom->Normal(0.0, k.dist1SD) / k.dist1Scale; + if (trfr.twinKern) + { + dist2 = pRandom->Normal(0.0, k.dist2SD) / k.dist2Scale; + prob1 = pRandom->Normal(0.0, k.PKern1SD) / k.PKern1Scale; + } + if (gen.trait1Chromosome) { + pGenome->setGene(gposn++, expr, dist1, gen.alleleSD); + if (trfr.twinKern) + { + pGenome->setGene(gposn++, expr, dist2, gen.alleleSD); + pGenome->setGene(gposn++, expr, prob1, gen.alleleSD); + } + } + else { + pGenome->setTrait(pSpecies, gposn++, dist1, gen.alleleSD); + if (trfr.twinKern) + { + pGenome->setTrait(pSpecies, gposn++, dist2, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, prob1, gen.alleleSD); + } } } // record phenotypic traits - if (smstraits.goalType == 2) - setSMSTraits(pSpecies,trfrposn,4,false); - else - setSMSTraits(pSpecies,trfrposn,2,false); - } - if (trfr.moveType == 2) { // set CRW genes - double stepL,rho; - trfrCRWParams m = pSpecies->getCRWParams(0,0); // only traits for females/all - stepL = pRandom->Normal(0.0,m.stepLgthSD) / m.stepLScale; - rho = pRandom->Normal(0.0,m.rhoSD) / m.rhoScale; - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,stepL,gen.alleleSD); - pGenome->setGene(gposn++,expr,rho,gen.alleleSD); + if (trfr.twinKern) + { + setKernTraits(pSpecies, trfrposn, 3, resol, trfr.sexDep); } else { - pGenome->setTrait(pSpecies,gposn++,stepL,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,rho,gen.alleleSD); + setKernTraits(pSpecies, trfrposn, 1, resol, trfr.sexDep); } - // record phenotypic traits - setCRWTraits(pSpecies,trfrposn,2,false); } } - else { // set kernel genes - double dist1,dist2,prob1; - trfrKernParams k; - for (int g = 0; g < ntraits; g++) { // first traits for females/all, second for males - k = pSpecies->getKernParams(0,g); - dist1 = pRandom->Normal(0.0,k.dist1SD) / k.dist1Scale; - if (trfr.twinKern) - { - dist2 = pRandom->Normal(0.0,k.dist2SD) / k.dist2Scale; - prob1 = pRandom->Normal(0.0,k.PKern1SD) / k.PKern1Scale; + + if (sett.indVar) { + int settposn = gposn; + double s0, alpha, beta; + settParams sparams; + if (sett.sexDep) { // must be a sexual species + ntraits = 2; + } + else { + if (dem.repType == 0) { // asexual reproduction + ntraits = 1; } + else { // sexual reproduction + ntraits = 1; + } + } + for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males + if (sim.batchMode) { + sparams = pSpecies->getSettParams(0, g); + } + else { // individual variability not (yet) implemented as sex-dependent in GUI + sparams = pSpecies->getSettParams(0, 0); + } + s0 = pRandom->Normal(0.0, sparams.s0SD) / sparams.s0Scale; + alpha = pRandom->Normal(0.0, sparams.alphaSSD) / sparams.alphaSScale; + beta = pRandom->Normal(0.0, sparams.betaSSD) / sparams.betaSScale; + if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,dist1,gen.alleleSD); - if (trfr.twinKern) - { - pGenome->setGene(gposn++,expr,dist2,gen.alleleSD); - pGenome->setGene(gposn++,expr,prob1,gen.alleleSD); - } + pGenome->setGene(gposn++, expr, s0, gen.alleleSD); + pGenome->setGene(gposn++, expr, alpha, gen.alleleSD); + pGenome->setGene(gposn++, expr, beta, gen.alleleSD); } else { - pGenome->setTrait(pSpecies,gposn++,dist1,gen.alleleSD); - if (trfr.twinKern) - { - pGenome->setTrait(pSpecies,gposn++,dist2,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,prob1,gen.alleleSD); - } - } + pGenome->setTrait(pSpecies, gposn++, s0, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, alpha, gen.alleleSD); + pGenome->setTrait(pSpecies, gposn++, beta, gen.alleleSD); + } } // record phenotypic traits - if (trfr.twinKern) - { - setKernTraits(pSpecies,trfrposn,3,resol,trfr.sexDep); - } - else { - setKernTraits(pSpecies,trfrposn,1,resol,trfr.sexDep); - } + setSettTraits(pSpecies, settposn, 3, sett.sexDep); } -} -//int settposn = 0; -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): settlement genes" << endl; -#endif -if (sett.indVar) { - int settposn = gposn; - double s0,alpha,beta; - settParams sparams; -// settScales scale = pSpecies->getSettScales(); - if (sett.sexDep) { // must be a sexual species - ntraits = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ntraits = 1; - } - else { // sexual reproduction - ntraits = 1; - } - } - for (int g = 0; g < ntraits; g++) { // first trait for females/all, second for males - if (sim.batchMode) { - sparams = pSpecies->getSettParams(0,g); - } - else { // individual variability not (yet) implemented as sex-dependent in GUI - sparams = pSpecies->getSettParams(0,0); - } - s0 = pRandom->Normal(0.0,sparams.s0SD) / sparams.s0Scale; - alpha = pRandom->Normal(0.0,sparams.alphaSSD) / sparams.alphaSScale; - beta = pRandom->Normal(0.0,sparams.betaSSD) / sparams.betaSScale; -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " sparams.s0Mean=" << sparams.s0Mean -// << " sparams.s0SD=" << sparams.s0SD -// << " sparams.s0Scale=" << sparams.s0Scale -// << " s0=" << s0 -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " sparams.alphaSMean=" << sparams.alphaSMean -// << " sparams.alphaSSD=" << sparams.alphaSSD -// << " sparams.alphaSScale=" << sparams.alphaSScale -// << " alpha=" << alpha -// << endl; -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " g=" << g -// << " sparams.betaSMean=" << sparams.betaSMean -// << " sparams.betaSSD=" << sparams.betaSSD -// << " sparams.betaSScale=" << sparams.betaSScale -// << " beta=" << beta -// << endl; -#endif - if (gen.trait1Chromosome) { - pGenome->setGene(gposn++,expr,s0,gen.alleleSD); - pGenome->setGene(gposn++,expr,alpha,gen.alleleSD); - pGenome->setGene(gposn++,expr,beta,gen.alleleSD); - } - else { - pGenome->setTrait(pSpecies,gposn++,s0,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,alpha,gen.alleleSD); - pGenome->setTrait(pSpecies,gposn++,beta,gen.alleleSD); + if (!gen.trait1Chromosome) { + if (gen.neutralMarkers || pSpecies->getNNeutralLoci() > 0) { + pGenome->setNeutralLoci(pSpecies, gen.alleleSD); } } - // record phenotypic traits - setSettTraits(pSpecies,settposn,3,sett.sexDep); -} - -if (!gen.trait1Chromosome) { - if (gen.neutralMarkers || pSpecies->getNNeutralLoci() > 0) { - pGenome->setNeutralLoci(pSpecies,gen.alleleSD); - } -} -#if RSDEBUG -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished" -// << endl; -#endif } // Inherit genome from parent(s) -void Individual::setGenes(Species *pSpecies,Individual *mother,Individual *father, +void Individual::setGenes(Species* pSpecies, Individual* mother, Individual* father, int resol) { -#if RSDEBUG -//locn currloc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::setGenes(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -//// << " pSpecies=" << pSpecies -// << " mother=" << mother -// << " motherID=" << mother->getId() -// << " father=" << father; -//if (father != 0) DEBUGLOG << " fatherID=" << father->getId(); -//DEBUGLOG << endl; -#endif -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); - -Genome *pFatherGenome; -if (father == 0) pFatherGenome = 0; else pFatherGenome = father->pGenome; + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); -pGenome = new Genome(pSpecies,mother->pGenome,pFatherGenome); + Genome* pFatherGenome; + if (father == 0) pFatherGenome = 0; else pFatherGenome = father->pGenome; -if (emig.indVar) { - // record emigration traits - if (father == 0) { // haploid - if (emig.densDep) { - setEmigTraits(pSpecies,0,3,0); - } - else { - setEmigTraits(pSpecies,0,1,0); - } - } - else { // diploid - if (emig.densDep) { - setEmigTraits(pSpecies,0,3,emig.sexDep); - } - else { - setEmigTraits(pSpecies,0,1,emig.sexDep); - } - } -} + pGenome = new Genome(pSpecies, mother->pGenome, pFatherGenome); -if (trfr.indVar) { - // record movement model traits - if (trfr.moveModel) { - if (trfr.moveType == 1) { // SMS - trfrSMSTraits s = pSpecies->getSMSTraits(); - if (s.goalType == 2) - setSMSTraits(pSpecies,trfr.movtTrait[0],4,0); - else - setSMSTraits(pSpecies,trfr.movtTrait[0],2,0); - } - if (trfr.moveType == 2) { // CRW - setCRWTraits(pSpecies,trfr.movtTrait[0],2,0); - } - } - else { // kernel + if (emig.indVar) { + // record emigration traits if (father == 0) { // haploid - if (trfr.twinKern) - { - setKernTraits(pSpecies,trfr.movtTrait[0],3,resol,0); + if (emig.densDep) { + setEmigTraits(pSpecies, 0, 3, 0); } else { - setKernTraits(pSpecies,trfr.movtTrait[0],1,resol,0); + setEmigTraits(pSpecies, 0, 1, 0); } } else { // diploid - if (trfr.twinKern) - { - setKernTraits(pSpecies,trfr.movtTrait[0],3,resol,trfr.sexDep); + if (emig.densDep) { + setEmigTraits(pSpecies, 0, 3, emig.sexDep); } else { - setKernTraits(pSpecies,trfr.movtTrait[0],1,resol,trfr.sexDep); + setEmigTraits(pSpecies, 0, 1, emig.sexDep); } } } -} -if (sett.indVar) { - // record settlement traits - if (father == 0) { // haploid - setSettTraits(pSpecies,sett.settTrait[0],3,0); - } - else { // diploid - setSettTraits(pSpecies,sett.settTrait[0],3,sett.sexDep); -// setSettTraits(pSpecies,sett.settTrait[0],3,0); + if (trfr.indVar) { + // record movement model traits + if (trfr.moveModel) { + if (trfr.moveType == 1) { // SMS + trfrSMSTraits s = pSpecies->getSMSTraits(); + if (s.goalType == 2) + setSMSTraits(pSpecies, trfr.movtTrait[0], 4, 0); + else + setSMSTraits(pSpecies, trfr.movtTrait[0], 2, 0); + } + if (trfr.moveType == 2) { // CRW + setCRWTraits(pSpecies, trfr.movtTrait[0], 2, 0); + } + } + else { // kernel + if (father == 0) { // haploid + if (trfr.twinKern) + { + setKernTraits(pSpecies, trfr.movtTrait[0], 3, resol, 0); + } + else { + setKernTraits(pSpecies, trfr.movtTrait[0], 1, resol, 0); + } + } + else { // diploid + if (trfr.twinKern) + { + setKernTraits(pSpecies, trfr.movtTrait[0], 3, resol, trfr.sexDep); + } + else { + setKernTraits(pSpecies, trfr.movtTrait[0], 1, resol, trfr.sexDep); + } + } + } } -} -#if RSDEBUG -//emigParams e = getEmigTraits(0,1,0); -//DEBUGLOG << "Individual::setGenes(): indId=" << indId << " finished " -// << " d0=" << e.d0 -//// << " alpha=" << e.alpha << " beta=" << e.beta -// << endl; -#endif + if (sett.indVar) { + // record settlement traits + if (father == 0) { // haploid + setSettTraits(pSpecies, sett.settTrait[0], 3, 0); + } + else { // diploid + setSettTraits(pSpecies, sett.settTrait[0], 3, sett.sexDep); + } + } } //--------------------------------------------------------------------------- @@ -491,12 +404,12 @@ if (sett.indVar) { // Identify whether an individual is a potentially breeding female - // if so, return her stage, otherwise return 0 int Individual::breedingFem(void) { -if (sex == 0) { - if (status == 0 || status == 4 || status == 5) return stage; + if (sex == 0) { + if (status == 0 || status == 4 || status == 5) return stage; + else return 0; + } else return 0; } -else return 0; -} int Individual::getId(void) { return indId; } @@ -505,617 +418,428 @@ int Individual::getSex(void) { return sex; } int Individual::getStatus(void) { return status; } indStats Individual::getStats(void) { -indStats s; -s.stage = stage; s.sex = sex; s.age = age; s.status = status; s.fallow = fallow; -s.isDeveloping = isDeveloping; -return s; + indStats s; + s.stage = stage; s.sex = sex; s.age = age; s.status = status; s.fallow = fallow; + s.isDeveloping = isDeveloping; + return s; } Cell* Individual::getLocn(const short option) { -if (option == 0) { // return previous location - return pPrevCell; -} -else { // return current location - return pCurrCell; -} + if (option == 0) { // return previous location + return pPrevCell; + } + else { // return current location + return pCurrCell; + } } Patch* Individual::getNatalPatch(void) { return pNatalPatch; } void Individual::setYearSteps(int t) { -if (path != 0 && t >= 0) { - if (t >= 0) path->year = t; - else path->year = 666; -} -#if RSDEBUG -//DEBUGLOG << "Individual::setYearSteps(): indId=" << indId -// << " t=" << t << " path->year=" << path->year -// << endl; -#endif + if (path != 0 && t >= 0) { + if (t >= 0) path->year = t; + else path->year = 666; + } } pathSteps Individual::getSteps(void) { -pathSteps s; -if (path == 0) { - s.year = 0; s.total = 0; s.out = 0; -} -else { - s.year = path->year; s.total = path->total; s.out = path->out; -} -return s; + pathSteps s; + if (path == 0) { + s.year = 0; s.total = 0; s.out = 0; + } + else { + s.year = path->year; s.total = path->total; s.out = path->out; + } + return s; } settlePatch Individual::getSettPatch(void) { -settlePatch s; -if (path == 0) { - s.pSettPatch = 0; s.settleStatus = 0; -} -else { - s.pSettPatch = path->pSettPatch; s.settleStatus = path->settleStatus; -} -return s; + settlePatch s; + if (path == 0) { + s.pSettPatch = 0; s.settleStatus = 0; + } + else { + s.pSettPatch = path->pSettPatch; s.settleStatus = path->settleStatus; + } + return s; } void Individual::setSettPatch(const settlePatch s) { -if (path == 0) { - path = new pathData; - path->year = 0; path->total = 0; path->out = 0; path->settleStatus = 0; + if (path == 0) { + path = new pathData; + path->year = 0; path->total = 0; path->out = 0; path->settleStatus = 0; #if RS_RCPP - path->pathoutput = 1; + path->pathoutput = 1; #endif -} -if (s.settleStatus >= 0 && s.settleStatus <= 2) path->settleStatus = s.settleStatus; -path->pSettPatch = s.pSettPatch; + } + if (s.settleStatus >= 0 && s.settleStatus <= 2) path->settleStatus = s.settleStatus; + path->pSettPatch = s.pSettPatch; } // Set phenotypic emigration traits -void Individual::setEmigTraits(Species *pSpecies,short emiggenelocn,short nemigtraits, +void Individual::setEmigTraits(Species* pSpecies, short emiggenelocn, short nemigtraits, bool sexdep) { -#if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " emiggenelocn=" << emiggenelocn << " nemigtraits=" << nemigtraits << " sexdep=" << sexdep -// << endl; -#endif -emigTraits e; e.d0 = e.alpha = e.beta = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - if (nemigtraits == 3) { // emigration is density-dependent - e.d0 = (float)pGenome->express(emiggenelocn+3*sex,0,0); - e.alpha = (float)pGenome->express(emiggenelocn+3*sex+1,0,0); - e.beta = (float)pGenome->express(emiggenelocn+3*sex+2,0,0); + emigTraits e; e.d0 = e.alpha = e.beta = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + if (nemigtraits == 3) { // emigration is density-dependent + e.d0 = (float)pGenome->express(emiggenelocn + 3 * sex, 0, 0); + e.alpha = (float)pGenome->express(emiggenelocn + 3 * sex + 1, 0, 0); + e.beta = (float)pGenome->express(emiggenelocn + 3 * sex + 2, 0, 0); + } + else { + e.d0 = (float)pGenome->express(emiggenelocn + sex, 0, 0); + } } else { - e.d0 = (float)pGenome->express(emiggenelocn+sex,0,0); + e.d0 = (float)pGenome->express(emiggenelocn, 0, 0); + if (nemigtraits == 3) { // emigration is density-dependent + e.alpha = (float)pGenome->express(emiggenelocn + 1, 0, 0); + e.beta = (float)pGenome->express(emiggenelocn + 2, 0, 0); + } } } else { - e.d0 = (float)pGenome->express(emiggenelocn,0,0); - if (nemigtraits == 3) { // emigration is density-dependent - e.alpha = (float)pGenome->express(emiggenelocn+1,0,0); - e.beta = (float)pGenome->express(emiggenelocn+2,0,0); - } - } - } - else { - if (sexdep) { - if (nemigtraits == 3) { // emigration is density-dependent - e.d0 = (float)pGenome->express(pSpecies,emiggenelocn+3*sex); - e.alpha = (float)pGenome->express(pSpecies,emiggenelocn+3*sex+1); - e.beta = (float)pGenome->express(pSpecies,emiggenelocn+3*sex+2); + if (sexdep) { + if (nemigtraits == 3) { // emigration is density-dependent + e.d0 = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex); + e.alpha = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex + 1); + e.beta = (float)pGenome->express(pSpecies, emiggenelocn + 3 * sex + 2); + } + else { + e.d0 = (float)pGenome->express(pSpecies, emiggenelocn + sex); + } } else { - e.d0 = (float)pGenome->express(pSpecies,emiggenelocn+sex); - } - } - else { - e.d0 = (float)pGenome->express(pSpecies,emiggenelocn); - if (nemigtraits == 3) { // emigration is density-dependent - e.alpha = (float)pGenome->express(pSpecies,emiggenelocn+1); - e.beta = (float)pGenome->express(pSpecies,emiggenelocn+2); + e.d0 = (float)pGenome->express(pSpecies, emiggenelocn); + if (nemigtraits == 3) { // emigration is density-dependent + e.alpha = (float)pGenome->express(pSpecies, emiggenelocn + 1); + e.beta = (float)pGenome->express(pSpecies, emiggenelocn + 2); + } } } } -} -#if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta -// << endl; -#endif -emigParams eparams; -if (sexdep) { - eparams = pSpecies->getEmigParams(0,sex); -} -else { - eparams = pSpecies->getEmigParams(0,0); -} -#if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD -// << " eparams.betaScale=" << eparams.betaScale -// << endl; -#endif -emigtraits = new emigTraits; -emigtraits->d0 = (float)(e.d0*eparams.d0Scale + eparams.d0Mean); -emigtraits->alpha = (float)(e.alpha*eparams.alphaScale + eparams.alphaMean); -emigtraits->beta = (float)(e.beta*eparams.betaScale + eparams.betaMean); -#if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " emigtraits->d0=" << emigtraits->d0 -// << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta -// << endl; -#endif -if (emigtraits->d0 < 0.0) emigtraits->d0 = 0.0; -if (emigtraits->d0 > 1.0) emigtraits->d0 = 1.0; -#if RSDEBUG -//DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId -// << " emigtraits->d0=" << emigtraits->d0 -// << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta -// << endl; -#endif -return; + emigParams eparams; + if (sexdep) { + eparams = pSpecies->getEmigParams(0, sex); + } + else { + eparams = pSpecies->getEmigParams(0, 0); + } + emigtraits = new emigTraits; + emigtraits->d0 = (float)(e.d0 * eparams.d0Scale + eparams.d0Mean); + emigtraits->alpha = (float)(e.alpha * eparams.alphaScale + eparams.alphaMean); + emigtraits->beta = (float)(e.beta * eparams.betaScale + eparams.betaMean); + if (emigtraits->d0 < 0.0) emigtraits->d0 = 0.0; + if (emigtraits->d0 > 1.0) emigtraits->d0 = 1.0; + return; } // Get phenotypic emigration traits emigTraits Individual::getEmigTraits(void) { -#if RSDEBUG -//DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId -// << endl; -#endif -emigTraits e; e.d0 = e.alpha = e.beta = 0.0; -if (emigtraits != 0) { - e.d0 = emigtraits->d0; - e.alpha = emigtraits->alpha; - e.beta = emigtraits->beta; -} -#if RSDEBUG -//DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId -// << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta -// << endl; -#endif - -return e; + emigTraits e; e.d0 = e.alpha = e.beta = 0.0; + if (emigtraits != 0) { + e.d0 = emigtraits->d0; + e.alpha = emigtraits->alpha; + e.beta = emigtraits->beta; + } + return e; } // Set phenotypic transfer by kernel traits -void Individual::setKernTraits(Species *pSpecies,short kerngenelocn,short nkerntraits, - int resol,bool sexdep) { -#if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " kerngenelocn=" << kerngenelocn << " nkerntraits=" << nkerntraits << " sexdep=" << sexdep -// << endl; -#endif -trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - if (nkerntraits == 3) { // twin kernel - k.meanDist1 = (float)pGenome->express(kerngenelocn+3*sex,0,sex); - k.meanDist2 = (float)pGenome->express(kerngenelocn+3*sex+1,0,sex); - k.probKern1 = (float)pGenome->express(kerngenelocn+3*sex+2,0,sex); +void Individual::setKernTraits(Species* pSpecies, short kerngenelocn, short nkerntraits, + int resol, bool sexdep) { + trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + if (nkerntraits == 3) { // twin kernel + k.meanDist1 = (float)pGenome->express(kerngenelocn + 3 * sex, 0, sex); + k.meanDist2 = (float)pGenome->express(kerngenelocn + 3 * sex + 1, 0, sex); + k.probKern1 = (float)pGenome->express(kerngenelocn + 3 * sex + 2, 0, sex); + } + else { + k.meanDist1 = (float)pGenome->express(kerngenelocn + sex, 0, sex); + } } else { - k.meanDist1 = (float)pGenome->express(kerngenelocn+sex,0,sex); + k.meanDist1 = (float)pGenome->express(kerngenelocn, 0, 0); + if (nkerntraits == 3) { // twin kernel + k.meanDist2 = (float)pGenome->express(kerngenelocn + 1, 0, 0); + k.probKern1 = (float)pGenome->express(kerngenelocn + 2, 0, 0); + } } } else { - k.meanDist1 = (float)pGenome->express(kerngenelocn,0,0); - if (nkerntraits == 3) { // twin kernel - k.meanDist2 = (float)pGenome->express(kerngenelocn+1,0,0); - k.probKern1 = (float)pGenome->express(kerngenelocn+2,0,0); - } - } - } - else { - if (sexdep) { - if (nkerntraits == 3) { // twin kernel - k.meanDist1 = (float)pGenome->express(pSpecies,kerngenelocn+3*sex); - k.meanDist2 = (float)pGenome->express(pSpecies,kerngenelocn+3*sex+1); - k.probKern1 = (float)pGenome->express(pSpecies,kerngenelocn+3*sex+2); + if (sexdep) { + if (nkerntraits == 3) { // twin kernel + k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex); + k.meanDist2 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex + 1); + k.probKern1 = (float)pGenome->express(pSpecies, kerngenelocn + 3 * sex + 2); + } + else { + k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn + sex); + } } else { - k.meanDist1 = (float)pGenome->express(pSpecies,kerngenelocn+sex); - } - } - else { - k.meanDist1 = (float)pGenome->express(pSpecies,kerngenelocn); - if (nkerntraits == 3) { // twin kernel - k.meanDist2 = (float)pGenome->express(pSpecies,kerngenelocn+1); - k.probKern1 = (float)pGenome->express(pSpecies,kerngenelocn+2); + k.meanDist1 = (float)pGenome->express(pSpecies, kerngenelocn); + if (nkerntraits == 3) { // twin kernel + k.meanDist2 = (float)pGenome->express(pSpecies, kerngenelocn + 1); + k.probKern1 = (float)pGenome->express(pSpecies, kerngenelocn + 2); + } } } - } -} -#if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist2 -// << " k.probKern1=" << k.probKern1 -// << endl; -#endif + } -trfrKernParams kparams; -if (sexdep) { - kparams = pSpecies->getKernParams(0,sex); -} -else { - kparams = pSpecies->getKernParams(0,0); -} -kerntraits = new trfrKernTraits; -kerntraits->meanDist1 = (float)(k.meanDist1*kparams.dist1Scale + kparams.dist1Mean); -kerntraits->meanDist2 = (float)(k.meanDist2*kparams.dist2Scale + kparams.dist2Mean); -kerntraits->probKern1 = (float)(k.probKern1*kparams.PKern1Scale + kparams.PKern1Mean); -#if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " kerntraits->meanDist1=" << kerntraits->meanDist1 -// << " kerntraits->meanDist2=" << kerntraits->meanDist2 -// << " kerntraits->probKern1=" << kerntraits->probKern1 -// << endl; -#endif -if (!pSpecies->useFullKernel()) { - // kernel mean(s) may not be less than landscape resolution - if (kerntraits->meanDist1 < resol) kerntraits->meanDist1 = (float)resol; - if (kerntraits->meanDist2 < resol) kerntraits->meanDist2 = (float)resol; -} -if (kerntraits->probKern1 < 0.0) kerntraits->probKern1 = 0.0; -if (kerntraits->probKern1 > 1.0) kerntraits->probKern1 = 1.0; -#if RSDEBUG -//DEBUGLOG << "Individual::setKernTraits(): indId=" << indId -// << " kerntraits->meanDist1=" << kerntraits->meanDist1 -// << " kerntraits->meanDist2=" << kerntraits->meanDist2 -// << " kerntraits->probKern1=" << kerntraits->probKern1 -// << endl; -#endif -return; + trfrKernParams kparams; + if (sexdep) { + kparams = pSpecies->getKernParams(0, sex); + } + else { + kparams = pSpecies->getKernParams(0, 0); + } + kerntraits = new trfrKernTraits; + kerntraits->meanDist1 = (float)(k.meanDist1 * kparams.dist1Scale + kparams.dist1Mean); + kerntraits->meanDist2 = (float)(k.meanDist2 * kparams.dist2Scale + kparams.dist2Mean); + kerntraits->probKern1 = (float)(k.probKern1 * kparams.PKern1Scale + kparams.PKern1Mean); + if (!pSpecies->useFullKernel()) { + // kernel mean(s) may not be less than landscape resolution + if (kerntraits->meanDist1 < resol) kerntraits->meanDist1 = (float)resol; + if (kerntraits->meanDist2 < resol) kerntraits->meanDist2 = (float)resol; + } + if (kerntraits->probKern1 < 0.0) kerntraits->probKern1 = 0.0; + if (kerntraits->probKern1 > 1.0) kerntraits->probKern1 = 1.0; + return; } // Get phenotypic emigration traits trfrKernTraits Individual::getKernTraits(void) { -#if RSDEBUG -//DEBUGLOG << "Individual::getKernTraits(): indId=" << indId -// << endl; -#endif -trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; -if (kerntraits != 0) { - k.meanDist1 = kerntraits->meanDist1; - k.meanDist2 = kerntraits->meanDist2; - k.probKern1 = kerntraits->probKern1; -} -#if RSDEBUG -//DEBUGLOG << "Individual::getKernTraits(): indId=" << indId -// << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist1 -// << " k.probKern1=" << k.probKern1 -// << endl; -#endif - -return k; + trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; + if (kerntraits != 0) { + k.meanDist1 = kerntraits->meanDist1; + k.meanDist2 = kerntraits->meanDist2; + k.probKern1 = kerntraits->probKern1; + } + return k; } // Set phenotypic transfer by SMS traits -void Individual::setSMSTraits(Species *pSpecies,short SMSgenelocn,short nSMStraits, - bool sexdep) { -#if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId -// << " SMSgenelocn=" << SMSgenelocn << " nSMStraits=" << nSMStraits << " sexdep=" << sexdep -// << endl; -#endif -trfrSMSTraits s = pSpecies->getSMSTraits(); -double dp,gb,alphaDB,betaDB; -dp = gb = alphaDB = betaDB = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - dp = pGenome->express(SMSgenelocn,0,0); - gb = pGenome->express(SMSgenelocn+1,0,0); - if (nSMStraits == 4) { - alphaDB = pGenome->express(SMSgenelocn+2,0,0); - betaDB = pGenome->express(SMSgenelocn+3,0,0); +void Individual::setSMSTraits(Species* pSpecies, short SMSgenelocn, short nSMStraits, + bool sexdep) { + trfrSMSTraits s = pSpecies->getSMSTraits(); + double dp, gb, alphaDB, betaDB; + dp = gb = alphaDB = betaDB = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + dp = pGenome->express(SMSgenelocn, 0, 0); + gb = pGenome->express(SMSgenelocn + 1, 0, 0); + if (nSMStraits == 4) { + alphaDB = pGenome->express(SMSgenelocn + 2, 0, 0); + betaDB = pGenome->express(SMSgenelocn + 3, 0, 0); + } + } + else { + dp = pGenome->express(SMSgenelocn, 0, 0); + gb = pGenome->express(SMSgenelocn + 1, 0, 0); + if (nSMStraits == 4) { + alphaDB = pGenome->express(SMSgenelocn + 2, 0, 0); + betaDB = pGenome->express(SMSgenelocn + 3, 0, 0); + } } } else { - dp = pGenome->express(SMSgenelocn,0,0); - gb = pGenome->express(SMSgenelocn+1,0,0); - if (nSMStraits == 4) { - alphaDB = pGenome->express(SMSgenelocn+2,0,0); - betaDB = pGenome->express(SMSgenelocn+3,0,0); + if (sexdep) { + dp = pGenome->express(pSpecies, SMSgenelocn); + gb = pGenome->express(pSpecies, SMSgenelocn + 1); + if (nSMStraits == 4) { + alphaDB = pGenome->express(pSpecies, SMSgenelocn + 2); + betaDB = pGenome->express(pSpecies, SMSgenelocn + 3); + } + } + else { + dp = pGenome->express(pSpecies, SMSgenelocn); + gb = pGenome->express(pSpecies, SMSgenelocn + 1); + if (nSMStraits == 4) { + alphaDB = pGenome->express(pSpecies, SMSgenelocn + 2); + betaDB = pGenome->express(pSpecies, SMSgenelocn + 3); + } } } } + trfrSMSParams smsparams; + if (sexdep) { + smsparams = pSpecies->getSMSParams(0, 0); + } else { - if (sexdep) { - dp = pGenome->express(pSpecies,SMSgenelocn); - gb = pGenome->express(pSpecies,SMSgenelocn+1); - if (nSMStraits == 4) { - alphaDB = pGenome->express(pSpecies,SMSgenelocn+2); - betaDB = pGenome->express(pSpecies,SMSgenelocn+3); - } - } - else { - dp = pGenome->express(pSpecies,SMSgenelocn); - gb = pGenome->express(pSpecies,SMSgenelocn+1); - if (nSMStraits == 4) { - alphaDB = pGenome->express(pSpecies,SMSgenelocn+2); - betaDB = pGenome->express(pSpecies,SMSgenelocn+3); - } - } + smsparams = pSpecies->getSMSParams(0, 0); } -} -#if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId -// << " dp=" << dp << " gb=" << gb -// << " alphaDB=" << alphaDB << " betaDB=" << betaDB -// << endl; -#endif - -trfrSMSParams smsparams; -if (sexdep) { - smsparams = pSpecies->getSMSParams(0,0); -} -else { - smsparams = pSpecies->getSMSParams(0,0); -} -smsData->dp = (float)(dp*smsparams.dpScale + smsparams.dpMean); -smsData->gb = (float)(gb*smsparams.gbScale + smsparams.gbMean); -if (s.goalType == 2) { - smsData->alphaDB = (float)(alphaDB*smsparams.alphaDBScale + smsparams.alphaDBMean); - smsData->betaDB = (int)(betaDB*smsparams.betaDBScale + smsparams.betaDBMean + 0.5); -} -else { - smsData->alphaDB = s.alphaDB; - smsData->betaDB = s.betaDB; -} -#if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits() 1111: indId=" << indId -// << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb -// << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB -// << endl; -#endif -if (smsData->dp < 1.0) smsData->dp = 1.0; -if (smsData->gb < 1.0) smsData->gb = 1.0; -if (smsData->alphaDB <= 0.0) smsData->alphaDB = 0.000001f; -if (smsData->betaDB < 1) smsData->betaDB = 1; -#if RSDEBUG -//DEBUGLOG << "Individual::setSMSTraits() 2222: indId=" << indId -// << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb -// << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB -// << endl; -#endif -return; + smsData->dp = (float)(dp * smsparams.dpScale + smsparams.dpMean); + smsData->gb = (float)(gb * smsparams.gbScale + smsparams.gbMean); + if (s.goalType == 2) { + smsData->alphaDB = (float)(alphaDB * smsparams.alphaDBScale + smsparams.alphaDBMean); + smsData->betaDB = (int)(betaDB * smsparams.betaDBScale + smsparams.betaDBMean + 0.5); + } + else { + smsData->alphaDB = s.alphaDB; + smsData->betaDB = s.betaDB; + } + if (smsData->dp < 1.0) smsData->dp = 1.0; + if (smsData->gb < 1.0) smsData->gb = 1.0; + if (smsData->alphaDB <= 0.0) smsData->alphaDB = 0.000001f; + if (smsData->betaDB < 1) smsData->betaDB = 1; + return; } // Get phenotypic transfer by SMS traits trfrSMSTraits Individual::getSMSTraits(void) { -#if RSDEBUG -//DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId << " smsData=" << smsData -// << endl; -#endif -trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; -if (smsData != 0) { - s.dp = smsData->dp; s.gb = smsData->gb; - s.alphaDB = smsData->alphaDB; s.betaDB = smsData->betaDB; -} -#if RSDEBUG -//DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId -// << " s.dp=" << s.dp << " s.gb=" << s.gb -// << " s.alphaDB=" << s.alphaDB << " s.betaDB=" << s.betaDB -// << endl; -#endif -return s; + trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; + if (smsData != 0) { + s.dp = smsData->dp; s.gb = smsData->gb; + s.alphaDB = smsData->alphaDB; s.betaDB = smsData->betaDB; + } + return s; } // Set phenotypic transfer by CRW traits -void Individual::setCRWTraits(Species *pSpecies,short CRWgenelocn,short nCRWtraits, +void Individual::setCRWTraits(Species* pSpecies, short CRWgenelocn, short nCRWtraits, bool sexdep) { -#if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " CRWgenelocn=" << CRWgenelocn << " nCRWtraits=" << nCRWtraits << " sexdep=" << sexdep -// << endl; -#endif -trfrCRWTraits c; c.stepLength = c.rho = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - c.stepLength = (float)pGenome->express(CRWgenelocn+sex,0,sex); - c.rho = (float)pGenome->express(CRWgenelocn+2+sex,0,sex); + trfrCRWTraits c; c.stepLength = c.rho = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + c.stepLength = (float)pGenome->express(CRWgenelocn + sex, 0, sex); + c.rho = (float)pGenome->express(CRWgenelocn + 2 + sex, 0, sex); + } + else { + c.stepLength = (float)pGenome->express(CRWgenelocn, 0, 0); + c.rho = (float)pGenome->express(CRWgenelocn + 1, 0, 0); + } } else { - c.stepLength = (float)pGenome->express(CRWgenelocn,0,0); - c.rho = (float)pGenome->express(CRWgenelocn+1,0,0); + if (sexdep) { + c.stepLength = (float)pGenome->express(pSpecies, CRWgenelocn + sex); + c.rho = (float)pGenome->express(pSpecies, CRWgenelocn + 2 + sex); + } + else { + c.stepLength = (float)pGenome->express(pSpecies, CRWgenelocn); + c.rho = (float)pGenome->express(pSpecies, CRWgenelocn + 1); + } } } + + trfrCRWParams cparams; + if (sexdep) { + cparams = pSpecies->getCRWParams(0, sex); + } else { - if (sexdep) { - c.stepLength = (float)pGenome->express(pSpecies,CRWgenelocn+sex); - c.rho = (float)pGenome->express(pSpecies,CRWgenelocn+2+sex); - } - else { - c.stepLength = (float)pGenome->express(pSpecies,CRWgenelocn); - c.rho = (float)pGenome->express(pSpecies,CRWgenelocn+1); - } + cparams = pSpecies->getCRWParams(0, 0); } -} -#if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho -// << endl; -#endif - -trfrCRWParams cparams; -if (sexdep) { - cparams = pSpecies->getCRWParams(0,sex); -} -else { - cparams = pSpecies->getCRWParams(0,0); -} -crw->stepL = (float)(c.stepLength*cparams.stepLScale + cparams.stepLgthMean); -crw->rho = (float)(c.rho*cparams.rhoScale + cparams.rhoMean); -#if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho -// << endl; -#endif -if (crw->stepL < 1.0) crw->stepL = 1.0; -if (crw->rho < 0.0) crw->rho = 0.0; -if (crw->rho > 0.999) crw->rho = 0.999f; -#if RSDEBUG -//DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId -// << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho -// << endl; -#endif -return; + crw->stepL = (float)(c.stepLength * cparams.stepLScale + cparams.stepLgthMean); + crw->rho = (float)(c.rho * cparams.rhoScale + cparams.rhoMean); + if (crw->stepL < 1.0) crw->stepL = 1.0; + if (crw->rho < 0.0) crw->rho = 0.0; + if (crw->rho > 0.999) crw->rho = 0.999f; + return; } // Get phenotypic transfer by CRW traits trfrCRWTraits Individual::getCRWTraits(void) { -#if RSDEBUG -//DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId -// << endl; -#endif -trfrCRWTraits c; c.stepLength = c.rho = 0.0; -if (crw != 0) { - c.stepLength = crw->stepL; - c.rho = crw->rho; -} -#if RSDEBUG -//DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId -// << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho -// << endl; -#endif - -return c; - + trfrCRWTraits c; c.stepLength = c.rho = 0.0; + if (crw != 0) { + c.stepLength = crw->stepL; + c.rho = crw->rho; + } + return c; } // Set phenotypic settlement traits -void Individual::setSettTraits(Species *pSpecies,short settgenelocn,short nsetttraits, +void Individual::setSettTraits(Species* pSpecies, short settgenelocn, short nsetttraits, bool sexdep) { -#if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId << " sex=" << sex -// << " settgenelocn=" << settgenelocn << " nsetttraits=" << nsetttraits << " sexdep=" << sexdep -// << endl; -#endif -//simParams sim = paramsSim->getSim(); -settleTraits s; s.s0 = s.alpha = s.beta = 0.0; -if (pGenome != 0) { - if (pSpecies->has1ChromPerTrait()) { - if (sexdep) { - s.s0 = (float)pGenome->express(settgenelocn+3*sex,0,0); - s.alpha = (float)pGenome->express(settgenelocn+3*sex+1,0,0); - s.beta = (float)pGenome->express(settgenelocn+3*sex+2,0,0); + settleTraits s; s.s0 = s.alpha = s.beta = 0.0; + if (pGenome != 0) { + if (pSpecies->has1ChromPerTrait()) { + if (sexdep) { + s.s0 = (float)pGenome->express(settgenelocn + 3 * sex, 0, 0); + s.alpha = (float)pGenome->express(settgenelocn + 3 * sex + 1, 0, 0); + s.beta = (float)pGenome->express(settgenelocn + 3 * sex + 2, 0, 0); + } + else { + s.s0 = (float)pGenome->express(settgenelocn, 0, 0); + s.alpha = (float)pGenome->express(settgenelocn + 1, 0, 0); + s.beta = (float)pGenome->express(settgenelocn + 2, 0, 0); + } } else { - s.s0 = (float)pGenome->express(settgenelocn,0,0); - s.alpha = (float)pGenome->express(settgenelocn+1,0,0); - s.beta = (float)pGenome->express(settgenelocn+2,0,0); + if (sexdep) { + s.s0 = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex); + s.alpha = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex + 1); + s.beta = (float)pGenome->express(pSpecies, settgenelocn + 3 * sex + 2); + } + else { + s.s0 = (float)pGenome->express(pSpecies, settgenelocn); + s.alpha = (float)pGenome->express(pSpecies, settgenelocn + 1); + s.beta = (float)pGenome->express(pSpecies, settgenelocn + 2); + } + } } - else { - if (sexdep) { - s.s0 = (float)pGenome->express(pSpecies,settgenelocn+3*sex); - s.alpha = (float)pGenome->express(pSpecies,settgenelocn+3*sex+1); - s.beta = (float)pGenome->express(pSpecies,settgenelocn+3*sex+2); - } - else { - s.s0 = (float)pGenome->express(pSpecies,settgenelocn); - s.alpha = (float)pGenome->express(pSpecies,settgenelocn+1); - s.beta = (float)pGenome->express(pSpecies,settgenelocn+2); - } - } -} -#if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta -// << endl; -#endif - -settParams sparams; -if (sexdep) { - sparams = pSpecies->getSettParams(0,sex); -} -else { - sparams = pSpecies->getSettParams(0,0); -} -#if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " sparams.s0Mean=" << sparams.s0Mean << " sparams.s0SD=" << sparams.s0SD -// << " sparams.s0Scale=" << sparams.s0Scale -// << endl; -#endif -setttraits = new settleTraits; -setttraits->s0 = (float)(s.s0*sparams.s0Scale + sparams.s0Mean); -setttraits->alpha = (float)(s.alpha*sparams.alphaSScale + sparams.alphaSMean); -setttraits->beta = (float)(s.beta*sparams.betaSScale + sparams.betaSMean); -#if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " setttraits->s0=" << setttraits->s0 -// << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta -// << endl; -#endif -if (setttraits->s0 < 0.0) setttraits->s0 = 0.0; -if (setttraits->s0 > 1.0) setttraits->s0 = 1.0; -#if RSDEBUG -//DEBUGLOG << "Individual::setSettTraits(): indId=" << indId -// << " setttraits->s0=" << setttraits->s0 -// << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta -// << endl; -#endif -return; + settParams sparams; + if (sexdep) { + sparams = pSpecies->getSettParams(0, sex); + } + else { + sparams = pSpecies->getSettParams(0, 0); + } + setttraits = new settleTraits; + setttraits->s0 = (float)(s.s0 * sparams.s0Scale + sparams.s0Mean); + setttraits->alpha = (float)(s.alpha * sparams.alphaSScale + sparams.alphaSMean); + setttraits->beta = (float)(s.beta * sparams.betaSScale + sparams.betaSMean); + if (setttraits->s0 < 0.0) setttraits->s0 = 0.0; + if (setttraits->s0 > 1.0) setttraits->s0 = 1.0; + return; } // Get phenotypic settlement traits settleTraits Individual::getSettTraits(void) { -#if RSDEBUG -//DEBUGLOG << "Individual::getSettTraits(): indId=" << indId -// << endl; -#endif -settleTraits s; s.s0 = s.alpha = s.beta = 0.0; -if (setttraits != 0) { - s.s0 = setttraits->s0; - s.alpha = setttraits->alpha; - s.beta = setttraits->beta; -} -#if RSDEBUG -//DEBUGLOG << "Individual::getSettTraits(): indId=" << indId -// << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta -// << endl; -#endif + settleTraits s; s.s0 = s.alpha = s.beta = 0.0; + if (setttraits != 0) { + s.s0 = setttraits->s0; + s.alpha = setttraits->alpha; + s.beta = setttraits->beta; + } -return s; + return s; } -/* -locus Individual::getAlleles(int g) { -locus l; l.allele[0] = l.allele[1] = 0.0; -if (pGenome != 0) l = pGenome->getAlleles(g); -return l; -} -*/ void Individual::setStatus(short s) { -if (s >= 0 && s <= 9) status = s; -status = s; + if (s >= 0 && s <= 9) status = s; + status = s; } void Individual::developing(void) { -isDeveloping = true; + isDeveloping = true; } void Individual::develop(void) { -stage++; isDeveloping = false; + stage++; isDeveloping = false; } void Individual::ageIncrement(short maxage) { -if (status < 6) { // alive - age++; - if (age > maxage) status = 9; // exceeds max. age - dies - else { - if (path != 0) path->year = 0; // reset annual step count for movement models - if (status == 3) // waiting to continue dispersal - status = 1; + if (status < 6) { // alive + age++; + if (age > maxage) status = 9; // exceeds max. age - dies + else { + if (path != 0) path->year = 0; // reset annual step count for movement models + if (status == 3) // waiting to continue dispersal + status = 1; + } } } -} void Individual::incFallow(void) { fallow++; } @@ -1123,551 +847,406 @@ void Individual::resetFallow(void) { fallow = 0; } //--------------------------------------------------------------------------- // Move to a specified neighbouring cell -void Individual::moveto(Cell *newCell) { -// check that location is indeed a neighbour of the current cell -locn currloc = pCurrCell->getLocn(); -locn newloc = newCell->getLocn(); -double d = sqrt(((double)currloc.x-(double)newloc.x)*((double)currloc.x-(double)newloc.x) - + ((double)currloc.y-(double)newloc.y)*((double)currloc.y-(double)newloc.y)); -if (d >= 1.0 && d < 1.5) { // ok - pCurrCell = newCell; status = 5; -} +void Individual::moveto(Cell* newCell) { + // check that location is indeed a neighbour of the current cell + locn currloc = pCurrCell->getLocn(); + locn newloc = newCell->getLocn(); + double d = sqrt(((double)currloc.x - (double)newloc.x) * ((double)currloc.x - (double)newloc.x) + + ((double)currloc.y - (double)newloc.y) * ((double)currloc.y - (double)newloc.y)); + if (d >= 1.0 && d < 1.5) { // ok + pCurrCell = newCell; status = 5; + } } //--------------------------------------------------------------------------- // Move to a new cell by sampling a dispersal distance from a single or double // negative exponential kernel // Returns 1 if still dispersing (including having found a potential patch), otherwise 0 -int Individual::moveKernel(Landscape *pLandscape,Species *pSpecies, - const short repType,const bool absorbing) +int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, + const short repType, const bool absorbing) { -intptr patch; -int patchNum = 0; -int newX = 0,newY = 0; -int dispersing = 1; -double xrand,yrand,meandist,dist,r1,rndangle,nx,ny; -float localK; -trfrKernTraits kern; -Cell* pCell; -Patch* pPatch; -locn loc = pCurrCell->getLocn(); - -landData land = pLandscape->getLandData(); - -bool usefullkernel = pSpecies->useFullKernel(); -trfrRules trfr = pSpecies->getTrfr(); -settleRules sett = pSpecies->getSettRules(stage,sex); - -pCell = NULL; -pPatch = NULL; - -if (trfr.indVar) { // get individual's kernel parameters - kern.meanDist1 = kern.meanDist2 = kern.probKern1 = 0.0; -// kparams = pSpecies->getKernParams(stage,sex); - if (pGenome != 0) { - kern.meanDist1 = kerntraits->meanDist1; - if (trfr.twinKern) - { - kern.meanDist2 = kerntraits->meanDist2; - kern.probKern1 = kerntraits->probKern1; - } - } -} -else { // get kernel parameters for the species - if (trfr.sexDep) { - if (trfr.stgDep) { - kern = pSpecies->getKernTraits(stage,sex); - } - else { - kern = pSpecies->getKernTraits(0,sex); + intptr patch; + int patchNum = 0; + int newX = 0, newY = 0; + int dispersing = 1; + double xrand, yrand, meandist, dist, r1, rndangle, nx, ny; + float localK; + trfrKernTraits kern; + Cell* pCell; + Patch* pPatch; + locn loc = pCurrCell->getLocn(); + + landData land = pLandscape->getLandData(); + + bool usefullkernel = pSpecies->useFullKernel(); + trfrRules trfr = pSpecies->getTrfr(); + settleRules sett = pSpecies->getSettRules(stage, sex); + + pCell = NULL; + pPatch = NULL; + + if (trfr.indVar) { // get individual's kernel parameters + kern.meanDist1 = kern.meanDist2 = kern.probKern1 = 0.0; + if (pGenome != 0) { + kern.meanDist1 = kerntraits->meanDist1; + if (trfr.twinKern) + { + kern.meanDist2 = kerntraits->meanDist2; + kern.probKern1 = kerntraits->probKern1; + } } } - else { - if (trfr.stgDep) { - kern = pSpecies->getKernTraits(stage,0); + else { // get kernel parameters for the species + if (trfr.sexDep) { + if (trfr.stgDep) { + kern = pSpecies->getKernTraits(stage, sex); + } + else { + kern = pSpecies->getKernTraits(0, sex); + } } else { - kern = pSpecies->getKernTraits(0,0); + if (trfr.stgDep) { + kern = pSpecies->getKernTraits(stage, 0); + } + else { + kern = pSpecies->getKernTraits(0, 0); + } } } -} -#if RSDEBUG -//Patch *startPatch = (Patch*)startpatch; -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " x=" << loc.x << " y=" << loc.y -//// << " natalPatch = " << natalPatch -//// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() -// << " kern.meanDist1=" << kern.meanDist1; -//if (trfr.twinKern) { -// DEBUGLOG << " meanDist2=" << kern.meanDist2 << " probKern1=" << kern.probKern1; -//} -//DEBUGLOG << endl; -#endif -// scale the appropriate kernel mean to the cell size -if (trfr.twinKern) -{ - if (pRandom->Bernoulli(kern.probKern1)) - meandist = kern.meanDist1 / (float)land.resol; + // scale the appropriate kernel mean to the cell size + if (trfr.twinKern) + { + if (pRandom->Bernoulli(kern.probKern1)) + meandist = kern.meanDist1 / (float)land.resol; + else + meandist = kern.meanDist2 / (float)land.resol; + } else - meandist = kern.meanDist2 / (float)land.resol; -} -else - meandist = kern.meanDist1 / (float)land.resol; -#if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; -#endif -// scaled mean may not be less than 1 unless emigration derives from the kernel -// (i.e. the 'use full kernel' option is applied) -if (!usefullkernel && meandist < 1.0) meandist = 1.0; -#if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; -#endif + meandist = kern.meanDist1 / (float)land.resol; -#if RSDEBUG -//Patch *startPatch = (Patch*)startpatch; -//DEBUGLOG << "Individual::moveKernel(): indId = " << indId << " x = " << x << " y = " << y -// << " natalPatch = " << natalPatch -//// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() -// << " meanDist1 = " << kern.meanDist1; -//if (trfr.twinKern) { -// DEBUGLOG << " probKern1 = " << kern.probKern1 << " meanDist2 = " << kern.meanDist2; -//} -//DEBUGLOG << " meandist = " << meandist << endl; -#endif + // scaled mean may not be less than 1 unless emigration derives from the kernel + // (i.e. the 'use full kernel' option is applied) + if (!usefullkernel && meandist < 1.0) meandist = 1.0; -int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 -do { + int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 do { do { - // randomise the cell within the patch, provided that the individual is still in - // its natal cell (i.e. not waiting in the matrix) - // this is because, if the patch is very large, the individual is near the centre - // and the (single) kernel mean is (not much more than) the cell size, an infinite - // loop could otherwise result, as the individual never reaches the patch edge - // (in a cell-based model, this has no effect, other than as a processing overhead) - if (status == 1) { - pCell = pNatalPatch->getRandomCell(); - if (pCell != 0) { - loc = pCell->getLocn(); + do { + // randomise the cell within the patch, provided that the individual is still in + // its natal cell (i.e. not waiting in the matrix) + // this is because, if the patch is very large, the individual is near the centre + // and the (single) kernel mean is (not much more than) the cell size, an infinite + // loop could otherwise result, as the individual never reaches the patch edge + // (in a cell-based model, this has no effect, other than as a processing overhead) + if (status == 1) { + pCell = pNatalPatch->getRandomCell(); + if (pCell != 0) { + loc = pCell->getLocn(); + } } - } - // randomise the position of the individual inside the cell - xrand = (double)loc.x + pRandom->Random()*0.999; - yrand = (double)loc.y + pRandom->Random()*0.999; - - r1 = 0.0000001 + pRandom->Random()*(1.0-0.0000001); -// dist = (-1.0*meandist)*std::log(r1); - dist = (-1.0*meandist)*log(r1); // for LINUX_CLUSTER - - rndangle = pRandom->Random() * 2.0 * PI; - nx = xrand + dist * sin(rndangle); - ny = yrand + dist * cos(rndangle); - if (nx < 0.0) newX = -1; else newX = (int)nx; - if (ny < 0.0) newY = -1; else newY = (int)ny; -#if RSDEBUG - if (path != 0) (path->year)++; -#endif - loopsteps++; + // randomise the position of the individual inside the cell + xrand = (double)loc.x + pRandom->Random() * 0.999; + yrand = (double)loc.y + pRandom->Random() * 0.999; + + r1 = 0.0000001 + pRandom->Random() * (1.0 - 0.0000001); + // dist = (-1.0*meandist)*std::log(r1); + dist = (-1.0 * meandist) * log(r1); // for LINUX_CLUSTER + + rndangle = pRandom->Random() * 2.0 * PI; + nx = xrand + dist * sin(rndangle); + ny = yrand + dist * cos(rndangle); + if (nx < 0.0) newX = -1; else newX = (int)nx; + if (ny < 0.0) newY = -1; else newY = (int)ny; #if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status -// << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY -// << " loc.x=" << loc.x << " loc.y=" << loc.y -// << endl; + if (path != 0) (path->year)++; #endif - } while (loopsteps < 1000 && + loopsteps++; + } while (loopsteps < 1000 && ((!absorbing && (newX < land.minX || newX > land.maxX - || newY < land.minY || newY > land.maxY)) - || (!usefullkernel && newX == loc.x && newY == loc.y)) + || newY < land.minY || newY > land.maxY)) + || (!usefullkernel && newX == loc.x && newY == loc.y)) ); - if (loopsteps < 1000) { - if (newX < land.minX || newX > land.maxX + if (loopsteps < 1000) { + if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) { // beyond absorbing boundary - pCell = 0; - patch = 0; - patchNum = -1; - } - else { - pCell = pLandscape->findCell(newX,newY); - if (pCell == 0) { // no-data cell + pCell = 0; patch = 0; patchNum = -1; } else { - patch = pCell->getPatch(); - if (patch == 0) { // matrix - pPatch = 0; - patchNum = 0; + pCell = pLandscape->findCell(newX, newY); + if (pCell == 0) { // no-data cell + patch = 0; + patchNum = -1; } else { - pPatch = (Patch*)patch; - patchNum = pPatch->getPatchNum(); + patch = pCell->getPatch(); + if (patch == 0) { // matrix + pPatch = 0; + patchNum = 0; + } + else { + pPatch = (Patch*)patch; + patchNum = pPatch->getPatchNum(); + } } } } - } - else { - patch = 0; - patchNum = -1; - } -#if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status -// << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY -// << " pCell=" << pCell << " patch=" << patch << " patchNum=" << patchNum -// << endl; -#endif - } while (!absorbing && patchNum < 0 && loopsteps < 1000); // in a no-data region -} -while (!usefullkernel && pPatch == pNatalPatch && loopsteps < 1000); // still in the original (natal) patch + else { + patch = 0; + patchNum = -1; + } + } while (!absorbing && patchNum < 0 && loopsteps < 1000); // in a no-data region + } while (!usefullkernel && pPatch == pNatalPatch && loopsteps < 1000); // still in the original (natal) patch -if (loopsteps < 1000) { - if (pCell == 0) { // beyond absorbing boundary or in no-data cell - pCurrCell = 0; - status = 6; - dispersing = 0; - } - else { - pCurrCell = pCell; - if (pPatch == 0) localK = 0.0; // matrix - else localK = pPatch->getK(); - if (patchNum > 0 && localK > 0.0) { // found a new patch - status = 2; // record as potential settler + if (loopsteps < 1000) { + if (pCell == 0) { // beyond absorbing boundary or in no-data cell + pCurrCell = 0; + status = 6; + dispersing = 0; } else { - dispersing = 0; - // can wait in matrix if population is stage structured ... - if (pSpecies->stageStructured()) { - // ... and wait option is applied ... - if (sett.wait) { // ... it is - status = 3; // waiting + pCurrCell = pCell; + if (pPatch == 0) localK = 0.0; // matrix + else localK = pPatch->getK(); + if (patchNum > 0 && localK > 0.0) { // found a new patch + status = 2; // record as potential settler + } + else { + dispersing = 0; + // can wait in matrix if population is stage structured ... + if (pSpecies->stageStructured()) { + // ... and wait option is applied ... + if (sett.wait) { // ... it is + status = 3; // waiting + } + else // ... it is not + status = 6; // dies (unless there is a suitable neighbouring cell) } - else // ... it is not + else status = 6; // dies (unless there is a suitable neighbouring cell) } - else - status = 6; // dies (unless there is a suitable neighbouring cell) } } -} -else { - status = 6; - dispersing = 0; -} -#if RSDEBUG -//DEBUGLOG << "Individual::moveKernel(): indId=" << indId -// << " newX=" << newX << " newY=" << newY -// << " patch=" << patch -// << " patchNum=" << patchNum << " status=" << status; -//DEBUGLOG << endl; -#endif - -// apply dispersal-related mortality, which may be distance-dependent -dist *= (float)land.resol; // re-scale distance moved to landscape scale -if (status < 7) { - double dispmort; - trfrMortParams mort = pSpecies->getMortParams(); - if (trfr.distMort) { - dispmort = 1.0 / (1.0 + exp(-(dist - mort.mortBeta)*mort.mortAlpha)); - } else { - dispmort = mort.fixedMort; - } - if (pRandom->Bernoulli(dispmort)) { - status = 7; // dies + status = 6; dispersing = 0; } -} -return dispersing; + // apply dispersal-related mortality, which may be distance-dependent + dist *= (float)land.resol; // re-scale distance moved to landscape scale + if (status < 7) { + double dispmort; + trfrMortParams mort = pSpecies->getMortParams(); + if (trfr.distMort) { + dispmort = 1.0 / (1.0 + exp(-(dist - mort.mortBeta) * mort.mortAlpha)); + } + else { + dispmort = mort.fixedMort; + } + if (pRandom->Bernoulli(dispmort)) { + status = 7; // dies + dispersing = 0; + } + } + + return dispersing; } //--------------------------------------------------------------------------- // Make a single movement step according to a mechanistic movement model // Returns 1 if still dispersing (including having found a potential patch), otherwise 0 -int Individual::moveStep(Landscape *pLandscape,Species *pSpecies, - const short landIx,const bool absorbing) +int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, + const short landIx, const bool absorbing) { -if (status != 1) return 0; // not currently dispersing - -intptr patch; -int patchNum; -int newX,newY; -locn loc; -int dispersing = 1; -double xcnew,ycnew; -double angle; -double mortprob,rho,steplen; -movedata move; -Patch* pPatch = 0; -bool absorbed = false; -//int popsize; - -landData land = pLandscape->getLandData(); -simParams sim = paramsSim->getSim(); - -trfrRules trfr = pSpecies->getTrfr(); -trfrCRWTraits movt = pSpecies->getCRWTraits(); -settleSteps settsteps = pSpecies->getSteps(stage,sex); - -patch = pCurrCell->getPatch(); -#if RSDEBUG -//DEBUGLOG << "Individual::moveStep() AAAA: indId=" << indId -// << " pCurrCell=" << pCurrCell << " patch=" << patch -// << endl; -#endif + if (status != 1) return 0; // not currently dispersing + + intptr patch; + int patchNum; + int newX, newY; + locn loc; + int dispersing = 1; + double xcnew, ycnew; + double angle; + double mortprob, rho, steplen; + movedata move; + Patch* pPatch = 0; + bool absorbed = false; + + landData land = pLandscape->getLandData(); + simParams sim = paramsSim->getSim(); + + trfrRules trfr = pSpecies->getTrfr(); + trfrCRWTraits movt = pSpecies->getCRWTraits(); + settleSteps settsteps = pSpecies->getSteps(stage, sex); + + patch = pCurrCell->getPatch(); -if (patch == 0) { // matrix - pPatch = 0; - patchNum = 0; -} -else { - pPatch = (Patch*)patch; - patchNum = pPatch->getPatchNum(); -} -// apply step-dependent mortality risk ... -if (trfr.habMort) -{ // habitat-dependent - int h = pCurrCell->getHabIndex(landIx); - if (h < 0) { // no-data cell - should not occur, but if it does, individual dies - mortprob = 1.0; - } - else mortprob = pSpecies->getHabMort(h); -#if RSDEBUG -//locn temploc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep(): x=" << temploc.x << " y=" << temploc.x -// << " landIx=" << landIx << " h=" << h << " mortprob=" << mortprob -// << endl; -#endif -} -else mortprob = movt.stepMort; -// ... unless individual has not yet left natal patch in emigration year -if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { - mortprob = 0.0; -} -#if RSDEBUG -locn loc0,loc1,loc2; -//loc0 = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep() BBBB: indId=" << indId << " status=" << status -// << " path->year=" << path->year << " path->out=" << path->out -// << " settleStatus=" << path->settleStatus -// << " x=" << loc0.x << " y=" << loc0.y -//// << " patch=" << patch -// << " pPatch=" << pPatch -// << " patchNum=" << patchNum; -//// << " natalPatch=" << natalPatch; -////if (crw != 0) { -//// DEBUGLOG << " xc=" << crw->xc << " yc=" << crw->yc; -//// DEBUGLOG << " rho=" << movt.rho << " stepLength=" << movt.stepLength; -////} -//DEBUGLOG << endl; -#endif -if (pRandom->Bernoulli(mortprob)) { // individual dies - status = 7; - dispersing = 0; -} -else { // take a step - (path->year)++; - (path->total)++; -// if (pPatch != pNatalPatch || path->out > 0) (path->out)++; - if (patch == 0 || pPatch == 0 || patchNum == 0) { // not in a patch - if (path != 0) path->settleStatus = 0; // reset path settlement status - (path->out)++; + if (patch == 0) { // matrix + pPatch = 0; + patchNum = 0; } - loc = pCurrCell->getLocn(); - newX = loc.x; newY = loc.y; - - - switch (trfr.moveType) { - - case 1: // SMS -#if RSDEBUG -//loc1 = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep() FFFF: indId=" << indId << " status=" << status -//// << " path->year=" << path->year -// << " path->season=" << path->season -// << " x=" << loc1.x << " y=" << loc1.y -// << " smsData->goalType=" << smsData->goalType -// << " goal.x=" << smsData->goal.x -// << " goal.y=" << smsData->goal.y -// << endl; -#endif - move = smsMove(pLandscape,pSpecies,landIx,pPatch==pNatalPatch,trfr.indVar,absorbing); -#if RSDEBUG -//DEBUGLOG << "Individual::moveStep() GGGG: indId=" << indId << " status=" << status -// << " move.dist=" << move.dist -// << endl; -#endif - if (move.dist < 0.0) { - // either INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE - // or individual has crossed absorbing boundary ... - // ... individual dies - status = 6; - dispersing = 0; + else { + pPatch = (Patch*)patch; + patchNum = pPatch->getPatchNum(); + } + // apply step-dependent mortality risk ... + if (trfr.habMort) + { // habitat-dependent + int h = pCurrCell->getHabIndex(landIx); + if (h < 0) { // no-data cell - should not occur, but if it does, individual dies + mortprob = 1.0; + } + else mortprob = pSpecies->getHabMort(h); + } + else mortprob = movt.stepMort; + // ... unless individual has not yet left natal patch in emigration year + if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { + mortprob = 0.0; + } + if (pRandom->Bernoulli(mortprob)) { // individual dies + status = 7; + dispersing = 0; + } + else { // take a step + (path->year)++; + (path->total)++; + if (patch == 0 || pPatch == 0 || patchNum == 0) { // not in a patch + if (path != 0) path->settleStatus = 0; // reset path settlement status + (path->out)++; } - else { -#if RSDEBUG -//loc1 = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::moveStep() HHHH: indId=" << indId << " status=" << status -// << " path->year=" << path->year -// << " x=" << loc1.x << " y=" << loc1.y -//// << " smsData = " << smsData -// << endl; -#endif + loc = pCurrCell->getLocn(); + newX = loc.x; newY = loc.y; + - // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... + switch (trfr.moveType) { - patch = pCurrCell->getPatch(); - //int patchnum; - if (patch == 0) { - pPatch = 0; - //patchnum = 0; + case 1: // SMS + move = smsMove(pLandscape, pSpecies, landIx, pPatch == pNatalPatch, trfr.indVar, absorbing); + if (move.dist < 0.0) { + // either INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE + // or individual has crossed absorbing boundary ... + // ... individual dies + status = 6; + dispersing = 0; } else { - pPatch = (Patch*)patch; - //patchnum = pPatch->getPatchNum(); - } - if (sim.saveVisits && pPatch != pNatalPatch) { - pCurrCell->incrVisits(); + + // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... + + patch = pCurrCell->getPatch(); + if (patch == 0) { + pPatch = 0; + } + else { + pPatch = (Patch*)patch; + } + if (sim.saveVisits && pPatch != pNatalPatch) { + pCurrCell->incrVisits(); + } } - } - break; + break; - case 2: // CRW - if (trfr.indVar) { - if (crw != 0) { - movt.stepLength = crw->stepL; - movt.rho = crw->rho; + case 2: // CRW + if (trfr.indVar) { + if (crw != 0) { + movt.stepLength = crw->stepL; + movt.rho = crw->rho; + } } - } - steplen = movt.stepLength; if (steplen < 0.2*land.resol) steplen = 0.2*land.resol; - rho = movt.rho; if (rho > 0.99) rho = 0.99; - if (pPatch == pNatalPatch) { - rho = 0.99; // to promote leaving natal patch - path->out = 0; - } - if (movt.straigtenPath && path->settleStatus > 0) { - // individual is in a patch and has already determined whether to settle - rho = 0.99; // to promote leaving the patch - path->out = 0; - } - int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 - do { + steplen = movt.stepLength; if (steplen < 0.2 * land.resol) steplen = 0.2 * land.resol; + rho = movt.rho; if (rho > 0.99) rho = 0.99; + if (pPatch == pNatalPatch) { + rho = 0.99; // to promote leaving natal patch + path->out = 0; + } + if (movt.straigtenPath && path->settleStatus > 0) { + // individual is in a patch and has already determined whether to settle + rho = 0.99; // to promote leaving the patch + path->out = 0; + } + int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 do { - // new direction - if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY - || pCurrCell == 0) { - // individual has tried to go out-of-bounds or into no-data area - // allow random move to prevent repeated similar move - angle = wrpcauchy(crw->prevdrn,0.0); + do { + // new direction + if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY + || pCurrCell == 0) { + // individual has tried to go out-of-bounds or into no-data area + // allow random move to prevent repeated similar move + angle = wrpcauchy(crw->prevdrn, 0.0); + } + else + angle = wrpcauchy(crw->prevdrn, rho); + // new continuous cell coordinates + xcnew = crw->xc + sin(angle) * steplen / (float)land.resol; + ycnew = crw->yc + cos(angle) * steplen / (float)land.resol; + if (xcnew < 0.0) newX = -1; else newX = (int)xcnew; + if (ycnew < 0.0) newY = -1; else newY = (int)ycnew; + loopsteps++; + } while (!absorbing && loopsteps < 1000 && + (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)); + if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) + pCurrCell = 0; + else + pCurrCell = pLandscape->findCell(newX, newY); + if (pCurrCell == 0) { // no-data cell or beyond absorbing boundary + patch = 0; + if (absorbing) absorbed = true; } else - angle = wrpcauchy(crw->prevdrn,rho); - // new continuous cell coordinates - xcnew = crw->xc + sin(angle) * steplen/(float)land.resol; - ycnew = crw->yc + cos(angle) * steplen/(float)land.resol; - if (xcnew < 0.0) newX = -1; else newX = (int)xcnew; - if (ycnew < 0.0) newY = -1; else newY = (int)ycnew; - loopsteps++; -#if RSDEBUG -//DEBUGLOG << "Individual::moveStep(): indId=" << indId -// << " xc=" << crw->xc << " yc=" << crw->yc << " pCurrCell=" << pCurrCell -// << " steps=" << path->year << " loopsteps=" << loopsteps -// << " steplen=" << steplen << " rho=" << rho << " angle=" << angle -// << " xcnew=" << xcnew << " ycnew=" << ycnew << " newX=" << newX << " newY=" << newY << endl; -#endif - } - while (!absorbing && loopsteps < 1000 && - (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)); - if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) - pCurrCell = 0; - else - pCurrCell = pLandscape->findCell(newX,newY); - if (pCurrCell == 0) { // no-data cell or beyond absorbing boundary - patch = 0; - if (absorbing) absorbed = true; - } - else - patch = pCurrCell->getPatch(); -#if RSDEBUG -//DEBUGLOG << "Individual::moveStep(): indId=" << indId -// << " loopsteps=" << loopsteps << " absorbed=" << absorbed -// << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; -#endif - } while (!absorbing && pCurrCell == 0 && loopsteps < 1000); - crw->prevdrn = (float)angle; - crw->xc = (float)xcnew; crw->yc = (float)ycnew; - if (absorbed) { // beyond absorbing boundary or in no-data square - status = 6; - dispersing = 0; - pCurrCell = 0; - } - else { - if (loopsteps >= 1000) { // unable to make a move - // INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE - // NEED TO TAKE SOME FORM OF INFORMATIVE ACTION ... - // ... individual dies as it cannot move + patch = pCurrCell->getPatch(); + } while (!absorbing && pCurrCell == 0 && loopsteps < 1000); + crw->prevdrn = (float)angle; + crw->xc = (float)xcnew; crw->yc = (float)ycnew; + if (absorbed) { // beyond absorbing boundary or in no-data square status = 6; dispersing = 0; - // current cell will be invalid (zero), so set back to previous cell - pCurrCell = pPrevCell; + pCurrCell = 0; } - } -#if RSDEBUG -//DEBUGLOG << "Individual::moveStep(): indId=" << indId -// << " status=" << status -// << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; -#endif - break; + else { + if (loopsteps >= 1000) { // unable to make a move + // INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE + // NEED TO TAKE SOME FORM OF INFORMATIVE ACTION ... + // ... individual dies as it cannot move + status = 6; + dispersing = 0; + // current cell will be invalid (zero), so set back to previous cell + pCurrCell = pPrevCell; + } + } + break; - } // end of switch (trfr.moveType) + } // end of switch (trfr.moveType) -#if RSDEBUG -//locn loc2; -//if (pCurrCell > 0) { -// loc2 = pCurrCell->getLocn(); -//} -//else { -// loc2.x = -9999; loc2.y = -9999; -//} -//DEBUGLOG << "Individual::moveStep() ZZZZ: indId=" << indId -// << " status=" << status -// << " path->total=" << path->total -// << " x=" << loc2.x << " y=" << loc2.y -// << " patch=" << patch; -//if (patch > 0) { -// pPatch = (Patch*)patch; -// DEBUGLOG << " patchNum=" << pPatch->getPatchNum() -// << " getK()=" << pPatch->getK() -// << " popn=" << pPatch->getPopn((int)pSpecies); -//} -// DEBUGLOG << endl; -#endif - if (patch > 0 // not no-data area or matrix - && path->total >= settsteps.minSteps) { - pPatch = (Patch*)patch; - if (pPatch != pNatalPatch) - { - // determine whether the new patch is potentially suitable - if (pPatch->getK() > 0.0) - { // patch is suitable + if (patch > 0 // not no-data area or matrix + && path->total >= settsteps.minSteps) { + pPatch = (Patch*)patch; + if (pPatch != pNatalPatch) + { + // determine whether the new patch is potentially suitable + if (pPatch->getK() > 0.0) + { // patch is suitable status = 2; + } } } - } - if (status != 2 && status != 6) { // suitable patch not found, not already dead - if (path->year >= settsteps.maxStepsYr) { - status = 3; // waits until next year - } - if (path->total >= settsteps.maxSteps) { - status = 6; // dies - dispersing = 0; + if (status != 2 && status != 6) { // suitable patch not found, not already dead + if (path->year >= settsteps.maxStepsYr) { + status = 3; // waits until next year + } + if (path->total >= settsteps.maxSteps) { + status = 6; // dies + dispersing = 0; + } } - } -} // end of single movement step + } // end of single movement step -return dispersing; + return dispersing; } @@ -1676,696 +1255,478 @@ return dispersing; // Functions to implement the SMS algorithm // Move to a neighbouring cell according to the SMS algorithm -movedata Individual::smsMove(Landscape *pLand,Species *pSpecies, - const short landIx,const bool natalPatch,const bool indvar,const bool absorbing) +movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, + const short landIx, const bool natalPatch, const bool indvar, const bool absorbing) { -array3x3d nbr; // to hold weights/costs/probs of moving to neighbouring cells -array3x3d goal; // to hold weights for moving towards a goal location -array3x3f hab; // to hold weights for habitat (includes percep range) -int x2,y2; // x index from 0=W to 2=E, y index from 0=N to 2=S -int newX = 0,newY = 0; -Cell *pCell; -Cell *pNewCell = NULL; -double sum_nbrs = 0.0; -movedata move; -int cellcost,newcellcost; -locn current; - -//if (write_out) { -// out<findCell(x,y); -if (pCurrCell == 0) -{ -// x,y is a NODATA square - this should not occur here -// return a negative distance to indicate an error - move.dist = -69.0; move.cost = 0.0; - return move; -} - -#if RSDEBUG -//DEBUGLOG << "Individual::smsMove(): this=" << this << endl; -#endif + array3x3d nbr; // to hold weights/costs/probs of moving to neighbouring cells + array3x3d goal; // to hold weights for moving towards a goal location + array3x3f hab; // to hold weights for habitat (includes percep range) + int x2, y2; // x index from 0=W to 2=E, y index from 0=N to 2=S + int newX = 0, newY = 0; + Cell* pCell; + Cell* pNewCell = NULL; + double sum_nbrs = 0.0; + movedata move; + int cellcost, newcellcost; + locn current; + + if (pCurrCell == 0) + { + // x,y is a NODATA square - this should not occur here + // return a negative distance to indicate an error + move.dist = -69.0; move.cost = 0.0; + return move; + } -landData land = pLand->getLandData(); -trfrSMSTraits movt = pSpecies->getSMSTraits(); -current = pCurrCell->getLocn(); - -//get weights for directional persistence.... -//if ((path->out > 0 && path->out < 10 && path->out < 2*movt.pr) -if ((path->out > 0 && path->out <= (movt.pr+1)) -|| natalPatch -|| (movt.straigtenPath && path->settleStatus > 0)) { - // inflate directional persistence to promote leaving the patch - if (indvar) nbr = getSimDir(current.x,current.y,10.0f*smsData->dp); - else nbr = getSimDir(current.x,current.y,10.0f*movt.dp); -} -else { - if (indvar) nbr = getSimDir(current.x,current.y,smsData->dp); - else nbr = getSimDir(current.x,current.y,movt.dp); -} -if (natalPatch || path->settleStatus > 0) path->out = 0; -//if (natalPatch) path->out = 0; -#if RSDEBUG -//DEBUGLOG << "Individual::smsMove() 0000: nbr matrix" << endl; -//for (y2 = 2; y2 > -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} -#endif -//if (write_out) { -// out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << hab.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} -#endif - pCurrCell->setEffCosts(hab); -} -else { // they have already been calculated - no action required -// if (write_out) { -// out<<"*** using previous effective costs ***"< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) { -// out< -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { - if(x2 == 1 && y2 == 1) nbr.cell[x2][y2] = 0.0; - else { - if(x2 == 1 || y2 == 1) //not diagonal - nbr.cell[x2][y2] = nbr.cell[x2][y2]*goal.cell[x2][y2]*hab.cell[x2][y2]; - else // diagonal - nbr.cell[x2][y2] = (float)SQRT2*nbr.cell[x2][y2]*goal.cell[x2][y2]*hab.cell[x2][y2]; - } -// if (write_out) { -// out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} -#endif + if (natalPatch || path->settleStatus > 0) path->out = 0; -// determine reciprocal of effective cost for the 8 neighbours -//if (write_out) out<<"reciprocal weighted effective costs:"< -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { - if (nbr.cell[x2][y2] > 0.0) nbr.cell[x2][y2] = 1.0f/nbr.cell[x2][y2]; -// if (write_out) { -// out<year == path->total) { // first year of dispersal - use no. of steps outside natal patch + nsteps = path->out; + } + else { // use total no. of steps + nsteps = path->total; + } + if (indvar) { + double exp_arg = -((double)nsteps - (double)smsData->betaDB) * (-smsData->alphaDB); + if (exp_arg > 100.0) exp_arg = 100.0; // to prevent exp() overflow error + gb = 1.0 + (smsData->gb - 1.0) / (1.0 + exp(exp_arg)); + } + else { + double exp_arg = -((double)nsteps - (double)movt.betaDB) * (-movt.alphaDB); + if (exp_arg > 100.0) exp_arg = 100.0; // to prevent exp() overflow error + gb = 1.0 + (movt.gb - 1.0) / (1.0 + exp(exp_arg)); + } } -// if (write_out) out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) { -// temp.cell[x2][y2] = nbr.cell[x2][y2]; -// if (current.x == 488 && current.y == 422) { -// pCell = pLand->findCell((current.x+x2-1),(current.y+y2-1)); -// DEBUGLOG << "Individual::smsMove(): this=" << this -// << " IN THE PROBLEM CELL" -// << " y=" << current.y << " x=" << current.x -// << " y2=" << y2 << " x2=" << x2 -// << " pCell=" << pCell; -// if (pCell != 0) DEBUGLOG << " pCell->getCost=" << pCell->getCost(); -// DEBUGLOG << endl; -// } -// } -//} -#endif + hab = pCurrCell->getEffCosts(); + + if (hab.cell[0][0] < 0.0) { // costs have not already been calculated + hab = getHabMatrix(pLand, pSpecies, current.x, current.y, movt.pr, movt.prMethod, + landIx, absorbing); + pCurrCell->setEffCosts(hab); + } + else { + // they have already been calculated - no action required + } -for (y2 = 2; y2 > -1; y2--) { - for (x2 = 0; x2 < 3; x2++) { - if (!absorbing) { - if ((current.y+y2-1) < land.minY || (current.y+y2-1) > land.maxY - || (current.x+x2-1) < land.minX || (current.x+x2-1) > land.maxX) - // cell is beyond current landscape limits - nbr.cell[x2][y2] = 0.0; - else { // check if no-data cell - pCell = pLand->findCell((current.x+x2-1),(current.y+y2-1)); - if (pCell == 0) nbr.cell[x2][y2] = 0.0; // no-data cell + // determine weighted effective cost for the 8 neighbours + // multiply directional persistence, goal bias and habitat habitat-dependent weights + for (y2 = 2; y2 > -1; y2--) { + for (x2 = 0; x2 < 3; x2++) { + if (x2 == 1 && y2 == 1) nbr.cell[x2][y2] = 0.0; + else { + if (x2 == 1 || y2 == 1) //not diagonal + nbr.cell[x2][y2] = nbr.cell[x2][y2] * goal.cell[x2][y2] * hab.cell[x2][y2]; + else // diagonal + nbr.cell[x2][y2] = (float)SQRT2 * nbr.cell[x2][y2] * goal.cell[x2][y2] * hab.cell[x2][y2]; } } -#if RSDEBUG -//DEBUGLOG << "Individual::smsMove(): this=" << this -// << " y=" << current.y << " x=" << current.x -// << " y2=" << y2 << " x2=" << x2 -// << " pCell=" << pCell -// << endl; -#endif -// if (write_out) { -// out< 0.0) { // should always be the case, but safest to check... + // determine reciprocal of effective cost for the 8 neighbours for (y2 = 2; y2 > -1; y2--) { for (x2 = 0; x2 < 3; x2++) { - nbr.cell[x2][y2] = nbr.cell[x2][y2]/(float)sum_nbrs; -// if (write_out) { -// out< 0.0) nbr.cell[x2][y2] = 1.0f / nbr.cell[x2][y2]; } -// if (write_out) out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} -#endif -// set up cell selection probabilities -//if (write_out) out<<"rnd = "< land.maxX - || newY < land.minY || newY > land.maxY))); - if (loopsteps >= 1000) pNewCell = 0; - else { - if (newX < land.minX || newX > land.maxX - || newY < land.minY || newY > land.maxY) { - pNewCell = 0; + } + + // set up cell selection probabilities + double cumulative[9]; + int j = 0; + cumulative[0] = nbr.cell[0][0]; + for (y2 = 0; y2 < 3; y2++) { + for (x2 = 0; x2 < 3; x2++) { + if (j != 0) cumulative[j] = cumulative[j - 1] + nbr.cell[x2][y2]; + j++; } - pNewCell = pLand->findCell(newX,newY); } -} -while (!absorbing && pNewCell == 0 && loopsteps < 1000); // no-data cell -#if RSDEBUG -//DEBUGLOG << "Individual::smsMove() 8888: pNewCell=" << pNewCell -// << " loopsteps=" << loopsteps -// << " current.x=" << current.x << " current.y=" << current.y -// << " newX=" << newX << " newY=" << newY -// << " land.minX=" << land.minX << " land.minY=" << land.minY -// << " land.maxX=" << land.maxX << " land.maxY=" << land.maxY -// << endl; -#endif -if (loopsteps >= 1000 || pNewCell == 0) { - // unable to make a move or crossed absorbing boundary - // flag individual to die - move.dist = -123.0; - if (pNewCell == 0) pCurrCell = pNewCell; -} -else { - newcellcost = pNewCell->getCost(); - move.cost = move.dist*0.5f*((float)cellcost + (float)newcellcost); - // make the selected move - if ((short)memory.size() == movt.memSize) { - memory.pop(); // remove oldest memory element - } - memory.push(current); // record previous location in memory - //if (write_out) out << "queue length is " << memory.size() << endl; - pCurrCell = pNewCell; -} -return move; + + // select direction at random based on cell selection probabilities + // landscape boundaries and no-data cells may be reflective or absorbing + cellcost = pCurrCell->getCost(); + int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 + do { + do { + double rnd = pRandom->Random(); + j = 0; + for (y2 = 0; y2 < 3; y2++) { + for (x2 = 0; x2 < 3; x2++) { + if (rnd < cumulative[j]) { + newX = current.x + x2 - 1; + newY = current.y + y2 - 1; + if (x2 == 1 || y2 == 1) move.dist = (float)(land.resol); + else move.dist = (float)(land.resol) * (float)SQRT2; + y2 = 999; x2 = 999; //to break out of x2 and y2 loops. + } + j++; + } + } + loopsteps++; + } while (loopsteps < 1000 + && (!absorbing && (newX < land.minX || newX > land.maxX + || newY < land.minY || newY > land.maxY))); + if (loopsteps >= 1000) pNewCell = 0; + else { + if (newX < land.minX || newX > land.maxX + || newY < land.minY || newY > land.maxY) { + pNewCell = 0; + } + pNewCell = pLand->findCell(newX, newY); + } + } while (!absorbing && pNewCell == 0 && loopsteps < 1000); // no-data cell + if (loopsteps >= 1000 || pNewCell == 0) { + // unable to make a move or crossed absorbing boundary + // flag individual to die + move.dist = -123.0; + if (pNewCell == 0) pCurrCell = pNewCell; + } + else { + newcellcost = pNewCell->getCost(); + move.cost = move.dist * 0.5f * ((float)cellcost + (float)newcellcost); + // make the selected move + if ((short)memory.size() == movt.memSize) { + memory.pop(); // remove oldest memory element + } + memory.push(current); // record previous location in memory + pCurrCell = pNewCell; + } + return move; } // Weight neighbouring cells on basis of current movement direction -array3x3d Individual::getSimDir(const int x, const int y, const float dp) +array3x3d Individual::getSimDir(const int x, const int y, const float dp) { -array3x3d d; -locn prev; -double theta; -int xx,yy; - -//if (write_out) out<<"step 0"<goal.x) == 0 && (y - smsData->goal.y) == 0) { - // at goal, set matrix to unity -// if (write_out) out<<"*** at goal: x,y = "<goal.x) == 0 && (y - smsData->goal.y) == 0) { + // at goal, set matrix to unity + for (xx = 0; xx < 3; xx++) { + for (yy = 0; yy < 3; yy++) { + d.cell[xx][yy] = 1.0; + } } + return d; + } + if (goaltype == 1) { + // TEMPORARY CODE - GOAL TYPE 1 NOT YET IMPLEMENTED, AS WE HAVE NO MEANS OF + // CAPTURING THE GOAL LOCATION OF EACH INDIVIDUAL + for (xx = 0; xx < 3; xx++) { + for (yy = 0; yy < 3; yy++) { + d.cell[xx][yy] = 1.0; + } + } + return d; } - return d; + else // goaltype == 2 + theta = atan2(((double)x - (double)smsData->goal.x), ((double)y - (double)smsData->goal.y)); + d = calcWeightings(gb, (float)theta); } - else // goaltype == 2 - theta = atan2(((double)x -(double)smsData->goal.x),((double)y-(double)smsData->goal.y)); -// if (write_out) out<<"goalx,goaly: "< 7.0 * PI / 8.0) { dx = 0; dy = -1; } -else { - if (fabs(theta) > 5.0 * PI / 8.0) { dy = -1; if (theta > 0) dx = 1; else dx = -1; } + if (fabs(theta) > 7.0 * PI / 8.0) { dx = 0; dy = -1; } else { - if (fabs(theta) > 3.0 * PI / 8.0) { dy = 0; if (theta > 0) dx = 1; else dx = -1; } + if (fabs(theta) > 5.0 * PI / 8.0) { dy = -1; if (theta > 0) dx = 1; else dx = -1; } else { - if (fabs(theta) > PI / 8.0) { dy = 1; if (theta > 0) dx = 1; else dx = -1; } - else { dy = 1; dx = 0; } + if (fabs(theta) > 3.0 * PI / 8.0) { dy = 0; if (theta > 0) dx = 1; else dx = -1; } + else { + if (fabs(theta) > PI / 8.0) { dy = 1; if (theta > 0) dx = 1; else dx = -1; } + else { dy = 1; dx = 0; } + } } - } -} -// if (write_out) out<<"goalx,goaly: "< 1) dx -= 2; yy = dy; - d.cell[xx+1][yy+1] = (float)i1; d.cell[-xx+1][yy+1] = (float)i1; - d.cell[xx+1][-yy+1] = (float)i3; d.cell[-xx+1][-yy+1] = (float)i3; - } - else { // theta points W or E - yy = dy+1; if (yy > 1) dy -= 2; xx = dx; - d.cell[xx+1][yy+1] = (float)i1; d.cell[xx+1][-yy+1] = (float)i1; - d.cell[-xx+1][yy+1] = (float)i3; d.cell[-xx+1][-yy+1] = (float)i3; - } -} -else { // theta points to an ordinal direction - d.cell[dx+1][-dy+1] = (float)i2; d.cell[-dx+1][dy+1] = (float)i2; - xx = dx+1; if (xx > 1) xx -= 2; d.cell[xx+1][dy+1] = (float)i1; - yy = dy+1; if (yy > 1) yy -= 2; d.cell[dx+1][yy+1] = (float)i1; - d.cell[-xx+1][-dy+1] = (float)i3; d.cell[-dx+1][-yy+1] = (float)i3; - } - -return d; + } + d.cell[1][1] = 0; // central cell has zero weighting + d.cell[dx + 1][dy + 1] = (float)i0; + d.cell[-dx + 1][-dy + 1] = (float)i4; + if (dx == 0 || dy == 0) { // theta points to a cardinal direction + d.cell[dy + 1][dx + 1] = (float)i2; d.cell[-dy + 1][-dx + 1] = (float)i2; + if (dx == 0) { // theta points N or S + xx = dx + 1; if (xx > 1) dx -= 2; yy = dy; + d.cell[xx + 1][yy + 1] = (float)i1; d.cell[-xx + 1][yy + 1] = (float)i1; + d.cell[xx + 1][-yy + 1] = (float)i3; d.cell[-xx + 1][-yy + 1] = (float)i3; + } + else { // theta points W or E + yy = dy + 1; if (yy > 1) dy -= 2; xx = dx; + d.cell[xx + 1][yy + 1] = (float)i1; d.cell[xx + 1][-yy + 1] = (float)i1; + d.cell[-xx + 1][yy + 1] = (float)i3; d.cell[-xx + 1][-yy + 1] = (float)i3; + } + } + else { // theta points to an ordinal direction + d.cell[dx + 1][-dy + 1] = (float)i2; d.cell[-dx + 1][dy + 1] = (float)i2; + xx = dx + 1; if (xx > 1) xx -= 2; d.cell[xx + 1][dy + 1] = (float)i1; + yy = dy + 1; if (yy > 1) yy -= 2; d.cell[dx + 1][yy + 1] = (float)i1; + d.cell[-xx + 1][-dy + 1] = (float)i3; d.cell[-dx + 1][-yy + 1] = (float)i3; + } + + return d; } // Weight neighbouring cells on basis of (habitat) costs -array3x3f Individual::getHabMatrix(Landscape *pLand,Species *pSpecies, - const int x,const int y,const short pr,const short prmethod,const short landIx, +array3x3f Individual::getHabMatrix(Landscape* pLand, Species* pSpecies, + const int x, const int y, const short pr, const short prmethod, const short landIx, const bool absorbing) { -array3x3f w; // array of effective costs to be returned -int ncells,x4,y4; -double weight,sumweights; -// NW and SE corners of effective cost array relative to the current cell (x,y): -int xmin = 0,ymin = 0,xmax = 0,ymax = 0; -int cost,nodatacost,h; -Cell *pCell; + array3x3f w; // array of effective costs to be returned + int ncells, x4, y4; + double weight, sumweights; + // NW and SE corners of effective cost array relative to the current cell (x,y): + int xmin = 0, ymin = 0, xmax = 0, ymax = 0; + int cost, nodatacost, h; + Cell* pCell; -landData land = pLand->getLandData(); -if (absorbing) nodatacost = ABSNODATACOST; -else nodatacost = NODATACOST; + landData land = pLand->getLandData(); + if (absorbing) nodatacost = ABSNODATACOST; + else nodatacost = NODATACOST; -for (int x2=-1; x2<2; x2++) { // index of relative move in x direction - for (int y2=-1; y2<2; y2++) { // index of relative move in x direction + for (int x2 = -1; x2 < 2; x2++) { // index of relative move in x direction + for (int y2 = -1; y2 < 2; y2++) { // index of relative move in x direction - w.cell[x2+1][y2+1] = 0.0; // initialise costs array to zeroes + w.cell[x2 + 1][y2 + 1] = 0.0; // initialise costs array to zeroes - // set up corners of perceptual range relative to current cell - if (x2==0 && y2==0) { // current cell - do nothing - xmin=0; ymin=0; xmax=0; ymax=0; - } - else { - if (x2==0 || y2==0) { // not diagonal (rook move) - if (x2==0){ // vertical (N-S) move - //out<<"ROOK N-S: x2 = "< land.maxX) x4 = x+x3-land.maxX-1; else x4 = x+x3; } - if ((y+y3) < 0) y4 = y+y3+land.maxY+1; - else { if ((y+y3) > land.maxY) y4 = y+y3-land.maxY-1; else y4 = y+y3; } -// if (write_out && (x4 < 0 || y4 < 0)) { -// out<<"ERROR: x "< land.maxX || y4 < 0 || y4 > land.maxY) { - // unexpected problem - e.g. due to ridiculously large PR - // treat as a no-data cell - cost = nodatacost; - } - else { - // add cost of cell to total PR cost - pCell = pLand->findCell(x4,y4); - if (pCell == 0) { // no-data cell + if (xmin > xmax) { int z = xmax; xmax = xmin; xmin = z; } // swap xmin and xmax + if (ymin > ymax) { int z = ymax; ymax = ymin; ymin = z; } // swap ymin and ymax + + // calculate effective mean cost of cells in perceptual range + ncells = 0; weight = 0.0; sumweights = 0.0; + if (x2 != 0 || y2 != 0) { // not central cell (i.e. current cell) + for (int x3 = xmin; x3 <= xmax; x3++) { + for (int y3 = ymin; y3 <= ymax; y3++) { + // if cell is out of bounds, treat landscape as a torus + // for purpose of obtaining a cost, + if ((x + x3) < 0) x4 = x + x3 + land.maxX + 1; + else { if ((x + x3) > land.maxX) x4 = x + x3 - land.maxX - 1; else x4 = x + x3; } + if ((y + y3) < 0) y4 = y + y3 + land.maxY + 1; + else { if ((y + y3) > land.maxY) y4 = y + y3 - land.maxY - 1; else y4 = y + y3; } + if (x4 < 0 || x4 > land.maxX || y4 < 0 || y4 > land.maxY) { + // unexpected problem - e.g. due to ridiculously large PR + // treat as a no-data cell cost = nodatacost; } else { - cost = pCell->getCost(); - if (cost < 0) cost = nodatacost; + // add cost of cell to total PR cost + pCell = pLand->findCell(x4, y4); + if (pCell == 0) { // no-data cell + cost = nodatacost; + } else { - if (cost == 0) { // cost not yet set for the cell - h = pCell->getHabIndex(landIx); - cost = pSpecies->getHabCost(h); -#if RSDEBUG -//DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 -// << " landIx=" << landIx << " h=" << h << " cost=" << cost -// << endl; -#endif - pCell->setCost(cost); - } + cost = pCell->getCost(); + if (cost < 0) cost = nodatacost; else { -#if RSDEBUG -//DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 -// << " cost=" << cost -// << endl; -#endif - - } + if (cost == 0) { // cost not yet set for the cell + h = pCell->getHabIndex(landIx); + cost = pSpecies->getHabCost(h); + pCell->setCost(cost); + } + else { + + } + } } } + if (prmethod == 1) { // arithmetic mean + w.cell[x2 + 1][y2 + 1] += cost; + ncells++; + } + if (prmethod == 2) { // harmonic mean + if (cost > 0) { + w.cell[x2 + 1][y2 + 1] += (1.0f / (float)cost); + ncells++; + } + } + if (prmethod == 3) { // arithmetic mean weighted by inverse distance + if (cost > 0) { + // NB distance is still given by (x3,y3) + weight = 1.0f / (double)sqrt((pow((double)x3, 2) + pow((double)y3, 2))); + w.cell[x2 + 1][y2 + 1] += (float)(weight * (double)cost); + ncells++; sumweights += weight; + } + } + } //end of y3 loop + } //end of x3 loop + if (ncells > 0) { + if (prmethod == 1) w.cell[x2 + 1][y2 + 1] /= ncells; // arithmetic mean + if (prmethod == 2) w.cell[x2 + 1][y2 + 1] = ncells / w.cell[x2 + 1][y2 + 1]; // hyperbolic mean + if (prmethod == 3 && sumweights > 0) + w.cell[x2 + 1][y2 + 1] /= (float)sumweights; // weighted arithmetic mean + } + } + else { // central cell + // record cost if not already recorded + // has effect of preparing for storing effective costs for the cell + pCell = pLand->findCell(x, y); + cost = pCell->getCost(); + if (cost < 0) cost = nodatacost; + else { + if (cost == 0) { // cost not yet set for the cell + h = pCell->getHabIndex(landIx); + cost = pSpecies->getHabCost(h); + pCell->setCost(cost); } - if (prmethod==1) { // arithmetic mean - w.cell[x2+1][y2+1] += cost; - ncells++; - } - if (prmethod==2) { // harmonic mean - if (cost > 0) { - w.cell[x2+1][y2+1] += (1.0f/(float)cost); - ncells++; - } - } - if (prmethod==3) { // arithmetic mean weighted by inverse distance - if (cost>0) { - // NB distance is still given by (x3,y3) - weight = 1.0f /(double)sqrt((pow((double)x3,2)+pow((double)y3,2))); - w.cell[x2+1][y2+1] += (float)(weight*(double)cost); - ncells++; sumweights += weight; - } - } -// if (write_out2) out2<get_target() > 50) targetseen++; -// } -//#endif - } //end of y3 loop - } //end of x3 loop -// if (write_out) out<<"ncells in PR = "<total << "\t" << loc.x << "\t" << loc.y << "\t" - << status << "\t" - << endl; + << path->total << "\t" << loc.x << "\t" << loc.y << "\t" + << status << "\t" + << endl; } // if not anymore dispersing... - if(status > 1 && status < 10){ + if (status > 1 && status < 10) { prev_loc = pPrevCell->getLocn(); // record only if this is the first step as non-disperser if (path->pathoutput) { // if this is also the first step taken at all, record the start cell first - if(path->total == 1){ + if (path->total == 1) { outMovePaths << year << "\t" << indId << "\t" - << "0\t" << prev_loc.x << "\t" << prev_loc.y << "\t" - << "0\t" // status at start cell is 0 - << endl; + << "0\t" << prev_loc.x << "\t" << prev_loc.y << "\t" + << "0\t" // status at start cell is 0 + << endl; } outMovePaths << year << "\t" << indId << "\t" - << path->total << "\t" << loc.x << "\t" << loc.y << "\t" - << status << "\t" - << endl; + << path->total << "\t" << loc.x << "\t" << loc.y << "\t" + << status << "\t" + << endl; // current cell will be invalid (zero), so set back to previous cell //pPrevCell = pCurrCell; path->pathoutput = 0; @@ -2422,33 +1783,76 @@ void Individual::outMovePath(const int year) //--------------------------------------------------------------------------- -double wrpcauchy (double location, double rho) { -double result; - -if(rho < 0.0 || rho > 1.0) { -// ML_ERR_return_NAN; - result = location; -} +double wrpcauchy(double location, double rho) { + double result; -if(rho == 0) - result = pRandom->Random() * M_2PI; -else - if(rho == 1) result = location; - else { - result = fmod(cauchy(location, -log(rho)), M_2PI); + if (rho < 0.0 || rho > 1.0) { + result = location; } -return result; + + if (rho == 0) + result = pRandom->Random() * M_2PI; + else + if (rho == 1) result = location; + else { + result = fmod(cauchy(location, -log(rho)), M_2PI); + } + return result; } double cauchy(double location, double scale) { -if (scale < 0) return location; -//return location + scale * tan(M_PI * unif_rand()); -return location + scale * tan(PI * pRandom->Random()); -//return location + scale * tan(M_PI * pRandom->Random()); + if (scale < 0) return location; + return location + scale * tan(PI * pRandom->Random()); } -//#endif -//#endif //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- + +#if RSDEBUG + + +void testIndividual() { + + Patch* pPatch = new Patch(0, 0); + int cell_x = 2; + int cell_y = 5; + int cell_hab = 2; + Cell* pCell = new Cell(cell_x, cell_y, (intptr)pPatch, cell_hab); + + // Create an individual + short stg = 0; + short age = 0; + short repInt = 0; + float probmale = 0; + bool uses_movt_process = true; + short moveType = 1; + Individual ind(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); + + // An individual... + { + std::vector inds; + for (int i = 0; i < 2; i++) + { + inds.push_back(new Individual(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType)); + } + } + + // Reproduces + // depending on whether it is sexual or not + // depending on the stage + // depending on the trait inheritance + + + // Disperses + // Emigrates + // Transfers + // Settles + + // Survives + + // Develops + +} +#endif // RSDEBUG + diff --git a/Individual.h b/Individual.h index d843d7e..bdc4ecb 100644 --- a/Individual.h +++ b/Individual.h @@ -49,7 +49,6 @@ Last updated: 26 October 2021 by Steve Palmer #include using namespace std; -//#include "mathlib.h" #include "Parameters.h" #include "Species.h" #include "Landscape.h" @@ -73,7 +72,6 @@ struct pathData { // to hold path data common to SMS and CRW models short settleStatus; // whether ind may settle in current patch // 0 = not set, 1 = debarred through density dependence rule // 2 = OK to settle subject to finding a mate -// bool leftNatalPatch; // individual has moved out of its natal patch #if RS_RCPP short pathoutput; #endif @@ -209,13 +207,6 @@ class Individual { const short, // landscape change index const bool // absorbing boundaries? ); - void drawMove( // Visualise paths resulting from movement simulation model - // NULL for the batch version - const float, // initial x co-ordinate - const float, // initial y co-ordinate - const float, // final x co-ordinate - const float // final y co-ordinate - ); movedata smsMove( // Move to a neighbouring cell according to the SMS algorithm Landscape*, // pointer to Landscape Species*, // pointer to Species @@ -313,5 +304,9 @@ extern ofstream DEBUGLOG; extern ofstream outMovePaths; #endif -//--------------------------------------------------------------------------- +#if RSDEBUG +void testIndividual(); #endif + +//--------------------------------------------------------------------------- +#endif // IndividualH diff --git a/Landscape.cpp b/Landscape.cpp index b74e7f2..be63ae9 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -184,10 +184,8 @@ if (!dfile.is_open()) return 21; // read landscape data from header records of distribution file // NB headers of all files have already been compared -double tmpresol; dfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> tmpresol >> header >> nodata; -resol = (int) tmpresol; + >> header >> resol >> header >> nodata; #if RS_RCPP if (!dfile.good()) { // corrupt file stream @@ -2096,10 +2094,8 @@ if (fileNum == 0) { // read landscape data from header records of habitat file // NB headers of all files have already been compared -double tmpresol; hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> tmpresol >> header >> habnodata; -resol = (int) tmpresol; + >> header >> resol >> header >> habnodata; #if RS_RCPP if (!hfile.good()) { diff --git a/Population.cpp b/Population.cpp index 002e860..4af1e84 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Population.h" //--------------------------------------------------------------------------- @@ -30,655 +30,442 @@ ofstream outInds; //--------------------------------------------------------------------------- -Population::Population(void) { -nSexes = nStages = 0; -pPatch = NULL; -pSpecies = NULL; -return; +Population::Population(void) { + nSexes = nStages = 0; + pPatch = NULL; + pSpecies = NULL; + return; } -Population::Population(Species *pSp,Patch *pPch,int ninds,int resol) +Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) { -// constructor for a Population of a specified size -#if RSDEBUG -//DEBUGLOG << "Population::Population(): this=" << this -// << " pPch=" << pPch << " ninds="<< ninds << endl; -#endif - -int n,nindivs,age = 0,minage,maxage,nAges = 0; -int cumtotal = 0; -float probmale; -double ageprob,ageprobsum; -std::vector ageProb; // for quasi-equilibrium initial age distribution -Cell *pCell; + // constructor for a Population of a specified size + + int n, nindivs, age = 0, minage, maxage, nAges = 0; + int cumtotal = 0; + float probmale; + double ageprob, ageprobsum; + std::vector ageProb; // for quasi-equilibrium initial age distribution + Cell* pCell; + + if (ninds > 0) { + inds.reserve(ninds); + juvs.reserve(ninds); + } -if (ninds > 0) { - inds.reserve(ninds); - juvs.reserve(ninds); -} + pSpecies = pSp; + pPatch = pPch; + // record the new population in the patch + patchPopn pp; + pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; + pPatch->addPopn(pp); -pSpecies = pSp; -pPatch = pPch; -// record the new population in the patch -patchPopn pp; -pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; -pPatch->addPopn(pp); -#if RSDEBUG -//DEBUGLOG << "Population::Population(): this=" << this -// << " added population to patch " << endl; -#endif + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + initParams init = paramsInit->getInit(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -//trfrSMSTraits sms = pSpecies->getSMSTraits(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -initParams init = paramsInit->getInit(); - -// determine no. of stages and sexes of species to initialise -if (dem.stageStruct) { - nStages = sstruct.nStages; -} -else // non-structured population has 2 stages, but user only ever sees stage 1 - nStages = 2; -if (dem.repType == 0) { nSexes = 1; probmale = 0.0; } -else { nSexes = 2; probmale = dem.propMales; } - -// set up population sub-totals -for (int stg = 0; stg < NSTAGES; stg++) { - for (int sex = 0; sex < NSEXES; sex++) { - nInds[stg][sex] = 0; + // determine no. of stages and sexes of species to initialise + if (dem.stageStruct) { + nStages = sstruct.nStages; + } + else // non-structured population has 2 stages, but user only ever sees stage 1 + nStages = 2; + if (dem.repType == 0) { nSexes = 1; probmale = 0.0; } + else { nSexes = 2; probmale = dem.propMales; } + + // set up population sub-totals + for (int stg = 0; stg < NSTAGES; stg++) { + for (int sex = 0; sex < NSEXES; sex++) { + nInds[stg][sex] = 0; + } } -} -// set up local copy of minimum age table -short minAge[NSTAGES][NSEXES]; -for (int stg = 0; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - if (dem.stageStruct) { - if (dem.repType == 1) { // simple sexual model - // both sexes use minimum ages recorded for females - minAge[stg][sex] = pSpecies->getMinAge(stg,0); + // set up local copy of minimum age table + short minAge[NSTAGES][NSEXES]; + for (int stg = 0; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + if (dem.stageStruct) { + if (dem.repType == 1) { // simple sexual model + // both sexes use minimum ages recorded for females + minAge[stg][sex] = pSpecies->getMinAge(stg, 0); + } + else { + minAge[stg][sex] = pSpecies->getMinAge(stg, sex); + } } - else { - minAge[stg][sex] = pSpecies->getMinAge(stg,sex); + else { // non-structured population + minAge[stg][sex] = 0; } } - else { // non-structured population - minAge[stg][sex] = 0; - } -#if RSDEBUG -//DEBUGLOG << "Population::Population(): 1111 " -// << " minAge[" << stg << "][" << sex << "]=" << minAge[stg][sex] -// << endl; -#endif } -} -// individuals of new population must be >= stage 1 -for (int stg = 1; stg < nStages; stg++) { - if (dem.stageStruct) { // allocate to stages according to initialisation conditions - // final stage is treated separately to ensure that correct total - // no. of individuals is created - if (stg == nStages-1) { - n = ninds - cumtotal; + // individuals of new population must be >= stage 1 + for (int stg = 1; stg < nStages; stg++) { + if (dem.stageStruct) { // allocate to stages according to initialisation conditions + // final stage is treated separately to ensure that correct total + // no. of individuals is created + if (stg == nStages - 1) { + n = ninds - cumtotal; + } + else { + n = (int)(ninds * paramsInit->getProp(stg) + 0.5); + cumtotal += n; + } } - else { - n = (int)(ninds * paramsInit->getProp(stg) + 0.5); - cumtotal += n; + else { // non-structured - all individuals go into stage 1 + n = ninds; } - } - else { // non-structured - all individuals go into stage 1 - n = ninds; - } -// for (int sex = 0; sex < nSexes; sex++) { -// if (n < nSexes) n = nSexes; // to ensure at least one individual of each age is created -// subPops.push_back(new SubPop(loc,stg,sex,n/nSexes)); -// } - // establish initial age distribution - minage = maxage = stg; - if (dem.stageStruct) { - // allow for stage-dependent minimum ages (use whichever sex is greater) - if (minAge[stg][0] > 0 && minage < minAge[stg][0]) minage = minAge[stg][0]; - if (nSexes == 2 && minAge[stg][1] > 0 && minage < minAge[stg][1]) minage = minAge[stg][1]; - // allow for specified age distribution - if (init.initAge != 0) { // not lowest age - if (stg == nStages-1) maxage = sstruct.maxAge; // final stage - else { // all other stages - use female max age, as sex of individuals is not predetermined - maxage = minAge[stg+1][0] - 1; - } - if (maxage < minage) maxage = minage; - nAges = maxage - minage + 1; - if (init.initAge == 2) { // quasi-equilibrium distribution - double psurv = (double)pSpecies->getSurv(stg,0); // use female survival for the stage - ageProb.clear(); - ageprobsum = 0.0; - ageprob = 1.0; - for (int i = 0; i < nAges; i++) { - ageProb.push_back(ageprob); ageprobsum += ageprob; ageprob *= psurv; + // establish initial age distribution + minage = maxage = stg; + if (dem.stageStruct) { + // allow for stage-dependent minimum ages (use whichever sex is greater) + if (minAge[stg][0] > 0 && minage < minAge[stg][0]) minage = minAge[stg][0]; + if (nSexes == 2 && minAge[stg][1] > 0 && minage < minAge[stg][1]) minage = minAge[stg][1]; + // allow for specified age distribution + if (init.initAge != 0) { // not lowest age + if (stg == nStages - 1) maxage = sstruct.maxAge; // final stage + else { // all other stages - use female max age, as sex of individuals is not predetermined + maxage = minAge[stg + 1][0] - 1; } - for (int i = 0; i < nAges; i++) { - ageProb[i] /= ageprobsum; - if (i > 0) ageProb[i] += ageProb[i-1]; // to give cumulative probability + if (maxage < minage) maxage = minage; + nAges = maxage - minage + 1; + if (init.initAge == 2) { // quasi-equilibrium distribution + double psurv = (double)pSpecies->getSurv(stg, 0); // use female survival for the stage + ageProb.clear(); + ageprobsum = 0.0; + ageprob = 1.0; + for (int i = 0; i < nAges; i++) { + ageProb.push_back(ageprob); ageprobsum += ageprob; ageprob *= psurv; + } + for (int i = 0; i < nAges; i++) { + ageProb[i] /= ageprobsum; + if (i > 0) ageProb[i] += ageProb[i - 1]; // to give cumulative probability + } } } } - } -#if RSDEBUG -//DEBUGLOG << "Population::Population(): this=" << this -// << " n=" << n << " stg=" << stg << " minage=" << minage << " maxage=" << maxage -// << endl; -#endif - // create individuals - int sex; - nindivs = (int)inds.size(); - for (int i = 0; i < n; i++) { - pCell = pPatch->getRandomCell(); - if (dem.stageStruct) { - switch (init.initAge) { - case 0: // lowest possible age - age = minage; - break; - case 1: // randomised - if (maxage > minage) age = pRandom->IRandom(minage,maxage); - else age = minage; - break; - case 2: // quasi-equilibrium - if (nAges > 1) { - double rrr = pRandom->Random(); - int ageclass = 0; - while (rrr > ageProb[ageclass]) ageclass++; - age = minage + ageclass; + // create individuals + int sex; + nindivs = (int)inds.size(); + for (int i = 0; i < n; i++) { + pCell = pPatch->getRandomCell(); + if (dem.stageStruct) { + switch (init.initAge) { + case 0: // lowest possible age + age = minage; + break; + case 1: // randomised + if (maxage > minage) age = pRandom->IRandom(minage, maxage); + else age = minage; + break; + case 2: // quasi-equilibrium + if (nAges > 1) { + double rrr = pRandom->Random(); + int ageclass = 0; + while (rrr > ageProb[ageclass]) ageclass++; + age = minage + ageclass; + } + else age = minage; + break; } - else age = minage; - break; } - } - else age = stg; + else age = stg; #if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - inds.push_back(new Individual(pCell,pPatch,stg,age,sstruct.repInterval, - probmale,true,trfr.moveType)); + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, + probmale, true, trfr.moveType)); #else - inds.push_back(new Individual(pCell,pPatch,stg,age,sstruct.repInterval, - probmale,trfr.moveModel,trfr.moveType)); -#endif - sex = inds[nindivs+i]->getSex(); - if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) - { - // individual variation - set up genetics - inds[nindivs+i]->setGenes(pSpecies,resol); + inds.push_back(new Individual(pCell, pPatch, stg, age, sstruct.repInterval, + probmale, trfr.moveModel, trfr.moveType)); +#endif + sex = inds[nindivs + i]->getSex(); + if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) + { + // individual variation - set up genetics + inds[nindivs + i]->setGenes(pSpecies, resol); + } + nInds[stg][sex]++; } - nInds[stg][sex]++; } } -#if RSDEBUG -//DEBUGLOG << "Population::Population(): this=" << this -// << " finished " << endl; -#endif -} Population::~Population(void) { -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - if (inds[i] != NULL) delete inds[i]; -} -inds.clear(); -int njuvs = (int)juvs.size(); -for (int i = 0; i < njuvs; i++) { - if (juvs[i] != NULL) delete juvs[i]; -} -juvs.clear(); -} - -traitsums Population::getTraits(Species *pSpecies) { -int g; -traitsums ts; -for (int i = 0; i < NSEXES; i++) { - ts.ninds[i] = 0; - ts.sumD0[i] = ts.ssqD0[i] = 0.0; - ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; - ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; - ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; - ts.sumDP[i] = ts.ssqDP[i] = 0.0; - ts.sumGB[i] = ts.ssqGB[i] = 0.0; - ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; - ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; - ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; - ts.sumS0[i] = ts.ssqS0[i] = 0.0; - ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; -} -//locus loc; + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + if (inds[i] != NULL) delete inds[i]; + } + inds.clear(); + int njuvs = (int)juvs.size(); + for (int i = 0; i < njuvs; i++) { + if (juvs[i] != NULL) delete juvs[i]; + } + juvs.clear(); +} + +traitsums Population::getTraits(Species* pSpecies) { + int g; + traitsums ts; + for (int i = 0; i < NSEXES; i++) { + ts.ninds[i] = 0; + ts.sumD0[i] = ts.ssqD0[i] = 0.0; + ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; + ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; + ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; + ts.sumDP[i] = ts.ssqDP[i] = 0.0; + ts.sumGB[i] = ts.ssqGB[i] = 0.0; + ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; + ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; + ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; + ts.sumS0[i] = ts.ssqS0[i] = 0.0; + ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + } -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); -int ninds = (int)inds.size(); -#if RSDEBUG -//DEBUGLOG << "Population::getTraits(): ninds = " << ts.ninds[0] -//// << " nalleles = "<< nalleles -//// << " nemiggenes = " << nemiggenes << " ntrfrgenes = " << ntrfrgenes -// << endl; -#endif -for (int i = 0; i < ninds; i++) { - int sex = inds[i]->getSex(); - if (emig.sexDep || trfr.sexDep || sett.sexDep) g = sex; else g = 0; - ts.ninds[g] += 1; - // emigration traits - emigTraits e = inds[i]->getEmigTraits(); - if (emig.sexDep) g = sex; else g = 0; - ts.sumD0[g] += e.d0; ts.ssqD0[g] += e.d0 * e.d0; - ts.sumAlpha[g] += e.alpha; ts.ssqAlpha[g] += e.alpha * e.alpha; - ts.sumBeta[g] += e.beta; ts.ssqBeta[g] += e.beta * e.beta; - // transfer traits - trfrKernTraits k = inds[i]->getKernTraits(); - if (trfr.sexDep) g = sex; else g = 0; - ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; - ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; - ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; - trfrSMSTraits sms = inds[i]->getSMSTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; - ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; - ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; - ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; -#if RSDEBUG -//DEBUGLOG << "Population::getTraits():" -// << " i=" << i << " g=" << g -// << " sms.dp= " << sms.dp << " sms.gb= " << sms.gb -// << " ts.sumDP[g]= " << ts.sumDP[g] << " ts.ssqDP[g]= " << ts.ssqDP[g] -// << " ts.sumGB[g]= " << ts.sumGB[g] << " ts.ssqGB[g]= " << ts.ssqGB[g] -// << endl; -#endif - trfrCRWTraits c = inds[i]->getCRWTraits(); - g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; - ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; - // settlement traits - settleTraits s = inds[i]->getSettTraits(); - if (sett.sexDep) g = sex; else g = 0; -// g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ts.sumS0[g] += s.s0; ts.ssqS0[g] += s.s0 * s.s0; - ts.sumAlphaS[g] += s.alpha; ts.ssqAlphaS[g] += s.alpha * s.alpha; - ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; -#if RSDEBUG -//DEBUGLOG << "Population::getTraits():" -// << " i=" << i << " g=" << g << " a=" << a -// << " e.d0= " << e.d0 << " e.alpha= " << e.alpha << " e.beta= " << e.beta -// << " mnd0= " << emigTraits[g]->mnD0 << " mnAlpha= " << emigTraits[g]->mnAlpha << " mnBeta= " << emigTraits[g]->mnBeta -// << " sqd0= " << emigTraits[g]->sqD0 << " sqAlpha= " << emigTraits[g]->sqAlpha << " sqBeta= " << emigTraits[g]->sqBeta -// << endl; -#endif -} + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + int sex = inds[i]->getSex(); + if (emig.sexDep || trfr.sexDep || sett.sexDep) g = sex; else g = 0; + ts.ninds[g] += 1; + // emigration traits + emigTraits e = inds[i]->getEmigTraits(); + if (emig.sexDep) g = sex; else g = 0; + ts.sumD0[g] += e.d0; ts.ssqD0[g] += e.d0 * e.d0; + ts.sumAlpha[g] += e.alpha; ts.ssqAlpha[g] += e.alpha * e.alpha; + ts.sumBeta[g] += e.beta; ts.ssqBeta[g] += e.beta * e.beta; + // transfer traits + trfrKernTraits k = inds[i]->getKernTraits(); + if (trfr.sexDep) g = sex; else g = 0; + ts.sumDist1[g] += k.meanDist1; ts.ssqDist1[g] += k.meanDist1 * k.meanDist1; + ts.sumDist2[g] += k.meanDist2; ts.ssqDist2[g] += k.meanDist2 * k.meanDist2; + ts.sumProp1[g] += k.probKern1; ts.ssqProp1[g] += k.probKern1 * k.probKern1; + trfrSMSTraits sms = inds[i]->getSMSTraits(); + g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + ts.sumDP[g] += sms.dp; ts.ssqDP[g] += sms.dp * sms.dp; + ts.sumGB[g] += sms.gb; ts.ssqGB[g] += sms.gb * sms.gb; + ts.sumAlphaDB[g] += sms.alphaDB; ts.ssqAlphaDB[g] += sms.alphaDB * sms.alphaDB; + ts.sumBetaDB[g] += sms.betaDB; ts.ssqBetaDB[g] += sms.betaDB * sms.betaDB; + trfrCRWTraits c = inds[i]->getCRWTraits(); + g = 0; // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + ts.sumStepL[g] += c.stepLength; ts.ssqStepL[g] += c.stepLength * c.stepLength; + ts.sumRho[g] += c.rho; ts.ssqRho[g] += c.rho * c.rho; + // settlement traits + settleTraits s = inds[i]->getSettTraits(); + if (sett.sexDep) g = sex; else g = 0; + ts.sumS0[g] += s.s0; ts.ssqS0[g] += s.s0 * s.s0; + ts.sumAlphaS[g] += s.alpha; ts.ssqAlphaS[g] += s.alpha * s.alpha; + ts.sumBetaS[g] += s.beta; ts.ssqBetaS[g] += s.beta * s.beta; + } -return ts; + return ts; } int Population::getNInds(void) { return (int)inds.size(); } -popStats Population::getStats(void) +popStats Population::getStats(void) { -popStats p; -int ninds; -float fec; -bool breeders[2]; breeders[0] = breeders[1] = false; -demogrParams dem = pSpecies->getDemogr(); -p.pSpecies = pSpecies; -p.pPatch = pPatch; -p.spNum = pSpecies->getSpNum(); -p.nInds = (int)inds.size(); -p.nNonJuvs = p.nAdults = 0; -p.breeding = false; -#if RSDEBUG -//DEBUGLOG << "Population::getStats(): this=" << this -//// << " p.pSpecies=" << p.pSpecies << " p.spNum=" << p.spNum -// << " p.pPatch=" << p.pPatch << " patchNum=" << p.pPatch->getPatchNum() -// << " nStages=" << nStages << " nSexes=" << nSexes << " p.nInds=" << p.nInds -// << endl; -#endif -for (int stg = 1; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - ninds = nInds[stg][sex]; - p.nNonJuvs += ninds; -#if RSDEBUG -//DEBUGLOG << "Population::getStats(): this=" << this -// << " stg=" << stg << " sex=" << sex -// << " nInds[stg][sex]=" << nInds[stg][sex] << " p.nNonJuvs=" << p.nNonJuvs -// << endl; -#endif - if (ninds > 0) { - if (pSpecies->stageStructured()) { - if (dem.repType == 2) fec = pSpecies->getFec(stg,sex); - else fec = pSpecies->getFec(stg,0); - if (fec > 0.0) { breeders[sex] = true; p.nAdults += ninds; } + popStats p; + int ninds; + float fec; + bool breeders[2]; breeders[0] = breeders[1] = false; + demogrParams dem = pSpecies->getDemogr(); + p.pSpecies = pSpecies; + p.pPatch = pPatch; + p.spNum = pSpecies->getSpNum(); + p.nInds = (int)inds.size(); + p.nNonJuvs = p.nAdults = 0; + p.breeding = false; + for (int stg = 1; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + ninds = nInds[stg][sex]; + p.nNonJuvs += ninds; + + if (ninds > 0) { + if (pSpecies->stageStructured()) { + if (dem.repType == 2) fec = pSpecies->getFec(stg, sex); + else fec = pSpecies->getFec(stg, 0); + if (fec > 0.0) { breeders[sex] = true; p.nAdults += ninds; } + } + else breeders[sex] = true; } - else breeders[sex] = true; } } -} -// is there a breeding population present? -if (nSexes == 1) { - p.breeding = breeders[0]; -} -else { - if (breeders[0] && breeders[1]) p.breeding = true; -} -#if RSDEBUG -//DEBUGLOG << "Population::getStats(): this=" << this -// << " p.nInds=" << p.nInds << " p.nAdults=" << p.nAdults << " p.nNonJuvs=" << p.nNonJuvs -// << " breeders[0]=" << breeders[0] << " breeders[1]=" << breeders[1] -// << " p.breeding=" << p.breeding -// << endl; -#endif -return p; + // is there a breeding population present? + if (nSexes == 1) { + p.breeding = breeders[0]; + } + else { + if (breeders[0] && breeders[1]) p.breeding = true; + } + return p; } Species* Population::getSpecies(void) { return pSpecies; } int Population::totalPop(void) { -int t = 0; -for (int stg = 0; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - t += nInds[stg][sex]; -#if RSDEBUG -//DEBUGLOG << "Population::totalPop(): this=" << this -// << " stg=" << stg << " sex=" << sex -// << " nInds[stg][sex]=" << nInds[stg][sex] << " t=" << t -// << endl; -#endif + int t = 0; + for (int stg = 0; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + t += nInds[stg][sex]; + } } -} -return t; + return t; } int Population::stagePop(int stg) { -int t = 0; -if (stg < 0 || stg >= nStages) return t; -for (int sex = 0; sex < nSexes; sex++) { - t += nInds[stg][sex]; -} -return t; + int t = 0; + if (stg < 0 || stg >= nStages) return t; + for (int sex = 0; sex < nSexes; sex++) { + t += nInds[stg][sex]; + } + return t; } //--------------------------------------------------------------------------- // Remove all Individuals void Population::extirpate(void) { -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - if (inds[i] != NULL) delete inds[i]; -} -inds.clear(); -int njuvs = (int)juvs.size(); -for (int i = 0; i < njuvs; i++) { - if (juvs[i] != NULL) delete juvs[i]; -} -juvs.clear(); -for (int sex = 0; sex < nSexes; sex++) { - for (int stg = 0; stg < nStages; stg++) { - nInds[stg][sex] = 0; + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + if (inds[i] != NULL) delete inds[i]; + } + inds.clear(); + int njuvs = (int)juvs.size(); + for (int i = 0; i < njuvs; i++) { + if (juvs[i] != NULL) delete juvs[i]; + } + juvs.clear(); + for (int sex = 0; sex < nSexes; sex++) { + for (int stg = 0; stg < nStages; stg++) { + nInds[stg][sex] = 0; + } } -} } //--------------------------------------------------------------------------- // Produce juveniles and hold them in the juvs vector -void Population::reproduction(const float localK,const float envval,const int resol) +void Population::reproduction(const float localK, const float envval, const int resol) { -// get population size at start of reproduction -int ninds = (int)inds.size(); -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): this=" << this -// << " ninds=" << ninds -// << endl; -#endif // RSDEBUG -if (ninds == 0) return; - -int nsexes,stage,sex,njuvs,nj,nmales,nfemales; -Cell *pCell; -indStats ind; -double expected; -bool skipbreeding; - -//envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -simView v = paramsSim->getViews(); - -if (dem.repType == 0) nsexes = 1; else nsexes = 2; + // get population size at start of reproduction + int ninds = (int)inds.size(); + if (ninds == 0) return; -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): this=" << this -// << " pSpecies=" << pSpecies -// << " localK=" << localK << " envval=" << envval << " resol=" << resol -// << " sstruct.nStages=" << sstruct.nStages << " nsexes=" << nsexes << " ninds=" << ninds -// << endl; -#endif + int nsexes, stage, sex, njuvs, nj, nmales, nfemales; + Cell* pCell; + indStats ind; + double expected; + bool skipbreeding; -// set up local copy of species fecundity table -float fec[NSTAGES][NSEXES]; -for (int stg = 0; stg < sstruct.nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (dem.stageStruct) { - if (dem.repType == 1) { // simple sexual model - // both sexes use fecundity recorded for females - fec[stg][sex] = pSpecies->getFec(stg,0); + envStochParams env = paramsStoch->getStoch(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + simView v = paramsSim->getViews(); + + if (dem.repType == 0) nsexes = 1; else nsexes = 2; + + // set up local copy of species fecundity table + float fec[NSTAGES][NSEXES]; + for (int stg = 0; stg < sstruct.nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (dem.stageStruct) { + if (dem.repType == 1) { // simple sexual model + // both sexes use fecundity recorded for females + fec[stg][sex] = pSpecies->getFec(stg, 0); + } + else fec[stg][sex] = pSpecies->getFec(stg, sex); + } + else { // non-structured population + if (stg == 1) fec[stg][sex] = dem.lambda; // adults + else fec[stg][sex] = 0.0; // juveniles } - else - fec[stg][sex] = pSpecies->getFec(stg,sex); -// if (sex == 0 && fec[stg][sex] > dem.lambda) dem.lambda = fec[stg][sex]; - } - else { // non-structured population - if (stg == 1) fec[stg][sex] = dem.lambda; // adults - else fec[stg][sex] = 0.0; // juveniles } -#if RSDEBUG -//if (ninds > 0) { -//DEBUGLOG << "Population::reproduction(): fec[" << stg << "][" << sex << "] = " << fec[stg][sex] -// << endl; -//} -#endif } -} -if (dem.stageStruct) { -#if RSDEBUG -//if (ninds > 0) { -// DEBUGLOG << "Population::reproduction(): ninds=" << ninds << " localK=" << localK -// << " effect of density dependence:" << endl; -//} -#endif - // apply environmental effects and density dependence - // to all non-zero female non-juvenile stages - for (int stg = 1; stg < nStages; stg++) { - if (fec[stg][0] > 0.0) { - // apply any effect of environmental gradient and/or stochasticty - fec[stg][0] *= envval; - if (env.stoch && !env.inK) { - // fecundity (at low density) is constrained to lie between limits specified - // for the species - float limit; - limit = pSpecies->getMinMax(0); - if (fec[stg][0] < limit) fec[stg][0] = limit; - limit = pSpecies->getMinMax(1); - if (fec[stg][0] > limit) fec[stg][0] = limit; - } - if (sstruct.fecDens) { // apply density dependence - float effect = 0.0; - if (sstruct.fecStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN - // AND males precede females - float weight = 0.0; - for (int effstg = 0; effstg < nStages; effstg++) { - for (int effsex = 0; effsex < nSexes; effsex++) { - if (dem.repType == 2) { - if (effsex == 0) weight = pSpecies->getDDwtFec(2*stg+1,2*effstg+1); - else weight = pSpecies->getDDwtFec(2*stg+1,2*effstg); - } - else { - weight = pSpecies->getDDwtFec(stg,effstg); + if (dem.stageStruct) { + // apply environmental effects and density dependence + // to all non-zero female non-juvenile stages + for (int stg = 1; stg < nStages; stg++) { + if (fec[stg][0] > 0.0) { + // apply any effect of environmental gradient and/or stochasticty + fec[stg][0] *= envval; + if (env.stoch && !env.inK) { + // fecundity (at low density) is constrained to lie between limits specified + // for the species + float limit; + limit = pSpecies->getMinMax(0); + if (fec[stg][0] < limit) fec[stg][0] = limit; + limit = pSpecies->getMinMax(1); + if (fec[stg][0] > limit) fec[stg][0] = limit; + } + if (sstruct.fecDens) { // apply density dependence + float effect = 0.0; + if (sstruct.fecStageDens) { // stage-specific density dependence + // NOTE: matrix entries represent effect of ROW on COLUMN + // AND males precede females + float weight = 0.0; + for (int effstg = 0; effstg < nStages; effstg++) { + for (int effsex = 0; effsex < nSexes; effsex++) { + if (dem.repType == 2) { + if (effsex == 0) weight = pSpecies->getDDwtFec(2 * stg + 1, 2 * effstg + 1); + else weight = pSpecies->getDDwtFec(2 * stg + 1, 2 * effstg); + } + else { + weight = pSpecies->getDDwtFec(stg, effstg); + } + effect += (float)nInds[effstg][effsex] * weight; } - effect += (float)nInds[effstg][effsex] * weight; -#if RSDEBUG -//if (ninds > 0) { -// DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex << " nInds=" << nInds[effstg][effsex]; -// DEBUGLOG << " weight=" << weight << " effect=" << effect -// << endl; -//} -#endif } } + else // not stage-specific + effect = (float)totalPop(); + if (localK > 0.0) fec[stg][0] *= exp(-effect / localK); } - else // not stage-specific - effect = (float)totalPop(); - if (localK > 0.0) fec[stg][0] *= exp(-effect/localK); -#if RSDEBUG -//if (ninds > 0) { -// DEBUGLOG << " eff popn=" << effect << " exponential=" << exp(-effect/localK); -// DEBUGLOG << " fec[" << stg << "][0]=" << fec[stg][0] -// << endl; -//} -#endif } } } -} -else { // non-structured - set fecundity for adult females only - // apply any effect of environmental gradient and/or stochasticty - fec[1][0] *= envval; - if (env.stoch && !env.inK) { - // fecundity (at low density) is constrained to lie between limits specified - // for the species - float limit; - limit = pSpecies->getMinMax(0); - if (fec[1][0] < limit) fec[1][0] = limit; - limit = pSpecies->getMinMax(1); - if (fec[1][0] > limit) fec[1][0] = limit; - } - // apply density dependence - if (localK > 0.0) { -//#if GOBYMODEL -// ddeffect[1] = (float)ninds/localK; -//#else - if (dem.repType == 1 || dem.repType == 2) { // sexual model - // apply factor of 2 (as in manual, eqn. 6) - fec[1][0] *= 2.0; + else { // non-structured - set fecundity for adult females only + // apply any effect of environmental gradient and/or stochasticty + fec[1][0] *= envval; + if (env.stoch && !env.inK) { + // fecundity (at low density) is constrained to lie between limits specified + // for the species + float limit; + limit = pSpecies->getMinMax(0); + if (fec[1][0] < limit) fec[1][0] = limit; + limit = pSpecies->getMinMax(1); + if (fec[1][0] > limit) fec[1][0] = limit; } - fec[1][0] /= (1.0f + fabs(dem.lambda-1.0f)*pow(((float)ninds/localK),dem.bc)); -//#endif - } -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): dem.lambda=" << dem.lambda << " ninds=" << ninds -// << " localK=" << localK << " dem.bc=" << dem.bc << " fec[1][0]=" << fec[1][0] -// << endl; -#endif -} - -double propBreed; -Individual *father; -std::vector fathers; - -switch (dem.repType) { - -case 0: // asexual model - for (int i = 0; i < ninds; i++) { - stage = inds[i]->breedingFem(); -#if RSDEBUG -//DEBUGLOG << "Population::reproduction():" -// << " i=" << i << " ID=" << inds[i]->getId() << " stage=" << stage -// << endl; -#endif - if (stage > 0) { // female of breeding age - if (dem.stageStruct) { - // determine whether she must miss current breeding attempt - ind = inds[i]->getStats(); - if (ind.fallow >= sstruct.repInterval) { - if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; - else skipbreeding = true; - } - else skipbreeding = true; // cannot breed this time - } - else skipbreeding = false; // not structured - always breed - if (skipbreeding) { - inds[i]->incFallow(); - } - else { // attempt to breed - inds[i]->resetFallow(); - expected = fec[stage][0]; - if (expected <= 0.0) njuvs = 0; - else njuvs = pRandom->Poisson(expected); - nj = (int)juvs.size(); - pCell = pPatch->getRandomCell(); - for (int j = 0; j < njuvs; j++) { -#if RSDEBUG - // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - juvs.push_back(new Individual(pCell,pPatch,0,0,0,0.0,true,trfr.moveType)); -#else - juvs.push_back(new Individual(pCell,pPatch,0,0,0,0.0,trfr.moveModel,trfr.moveType)); -#endif - nInds[0][0]++; - if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) - { - // juv inherits genome from parent (mother) - juvs[nj+j]->setGenes(pSpecies,inds[i],0,resol); - } - } + // apply density dependence + if (localK > 0.0) { + if (dem.repType == 1 || dem.repType == 2) { // sexual model + // apply factor of 2 (as in manual, eqn. 6) + fec[1][0] *= 2.0; } + fec[1][0] /= (1.0f + fabs(dem.lambda - 1.0f) * pow(((float)ninds / localK), dem.bc)); } } - break; -case 1: // simple sexual model -case 2: // complex sexual model - // count breeding females and males - // add breeding males to list of potential fathers -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): case 1:" -// << " fec[1][0]=" << fec[1][0] << " fec[1][1]=" << fec[1][1] -// << endl; -#endif - nfemales = nmales = 0; - for (int i = 0; i < ninds; i++) { - ind = inds[i]->getStats(); - if (ind.sex == 0 && fec[ind.stage][0] > 0.0) nfemales++; - if (ind.sex == 1 && fec[ind.stage][1] > 0.0) { - fathers.push_back(inds[i]); - nmales++; -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): i=" << i << " nmales=" << nmales -// << " inds[i]=" << inds[i] << endl; -#endif - } - } -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): breeding nfemales=" << nfemales -// << " breeding nmales=" << nmales << endl; -#endif - if (nfemales > 0 && nmales > 0) - { // population can breed - if (dem.repType == 2) { // complex sexual model - // calculate proportion of eligible females which breed - propBreed = (2.0*dem.harem*nmales)/(nfemales+dem.harem*nmales); - if (propBreed > 1.0) propBreed = 1.0; -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): harem=" << dem.harem -// << " nfemales=" << nfemales << " nmales=" << nmales << " propBreed=" << propBreed -// << endl; -#endif - } - else propBreed = 1.0; + double propBreed; + Individual* father; + std::vector fathers; + + switch (dem.repType) { + + case 0: // asexual model for (int i = 0; i < ninds; i++) { stage = inds[i]->breedingFem(); - if (stage > 0 && fec[stage][0] > 0.0) { // (potential) breeding female + if (stage > 0) { // female of breeding age if (dem.stageStruct) { // determine whether she must miss current breeding attempt ind = inds[i]->getStats(); @@ -694,685 +481,568 @@ case 2: // complex sexual model } else { // attempt to breed inds[i]->resetFallow(); - // NOTE: FOR COMPLEX SEXUAL MODEL, NO. OF FEMALES *ACTUALLY* BREEDING DOES NOT - // NECESSARILY EQUAL THE EXPECTED NO. FROM EQN. 7 IN THE MANUAL... - if (pRandom->Bernoulli(propBreed)) { - expected = fec[stage][0]; // breeds -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): THIS LINE SHOULD NOT APPEAR FOR GOBY MODEL" -// << " expected=" << expected -// << endl; -#endif - } - else expected = 0.0; // fails to breed + expected = fec[stage][0]; if (expected <= 0.0) njuvs = 0; else njuvs = pRandom->Poisson(expected); + nj = (int)juvs.size(); + pCell = pPatch->getRandomCell(); + for (int j = 0; j < njuvs; j++) { #if RSDEBUG -//DEBUGLOG << "Population::reproduction():" -// << " i " << i << " ID=" << inds[i]->getId() << " stage=" << stage -// << " expected=" << expected << " njuvs=" << njuvs << endl; + // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, 0.0, true, trfr.moveType)); +#else + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, 0.0, trfr.moveModel, trfr.moveType)); #endif - if (njuvs > 0) - { - nj = (int)juvs.size(); + nInds[0][0]++; + if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) + { + // juv inherits genome from parent (mother) + juvs[nj + j]->setGenes(pSpecies, inds[i], 0, resol); + } + } + } + } + } + break; + + case 1: // simple sexual model + case 2: // complex sexual model + // count breeding females and males + // add breeding males to list of potential fathers + + nfemales = nmales = 0; + for (int i = 0; i < ninds; i++) { + ind = inds[i]->getStats(); + if (ind.sex == 0 && fec[ind.stage][0] > 0.0) nfemales++; + if (ind.sex == 1 && fec[ind.stage][1] > 0.0) { + fathers.push_back(inds[i]); + nmales++; + } + } + if (nfemales > 0 && nmales > 0) + { // population can breed + if (dem.repType == 2) { // complex sexual model + // calculate proportion of eligible females which breed + propBreed = (2.0 * dem.harem * nmales) / (nfemales + dem.harem * nmales); + if (propBreed > 1.0) propBreed = 1.0; + } + else propBreed = 1.0; + for (int i = 0; i < ninds; i++) { + stage = inds[i]->breedingFem(); + if (stage > 0 && fec[stage][0] > 0.0) { // (potential) breeding female + if (dem.stageStruct) { + // determine whether she must miss current breeding attempt + ind = inds[i]->getStats(); + if (ind.fallow >= sstruct.repInterval) { + if (pRandom->Bernoulli(sstruct.probRep)) skipbreeding = false; + else skipbreeding = true; + } + else skipbreeding = true; // cannot breed this time + } + else skipbreeding = false; // not structured - always breed + if (skipbreeding) { + inds[i]->incFallow(); + } + else { // attempt to breed + inds[i]->resetFallow(); + // NOTE: FOR COMPLEX SEXUAL MODEL, NO. OF FEMALES *ACTUALLY* BREEDING DOES NOT + // NECESSARILY EQUAL THE EXPECTED NO. FROM EQN. 7 IN THE MANUAL... + if (pRandom->Bernoulli(propBreed)) { + expected = fec[stage][0]; // breeds + } + else expected = 0.0; // fails to breed + if (expected <= 0.0) njuvs = 0; + else njuvs = pRandom->Poisson(expected); + if (njuvs > 0) + { + nj = (int)juvs.size(); // select father at random from breeding males ... int rrr = 0; - if (nmales > 1) rrr = pRandom->IRandom(0,nmales-1); + if (nmales > 1) rrr = pRandom->IRandom(0, nmales - 1); father = fathers[rrr]; -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): i = " << i << " rrr = " << rrr -// << " father = " << father << endl; -#endif pCell = pPatch->getRandomCell(); for (int j = 0; j < njuvs; j++) { #if RSDEBUG // NOTE: CURRENTLY SETTING ALL INDIVIDUALS TO RECORD NO. OF STEPS ... - juvs.push_back(new Individual(pCell,pPatch,0,0,0,dem.propMales,true,trfr.moveType)); + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, true, trfr.moveType)); #else - juvs.push_back(new Individual(pCell,pPatch,0,0,0,dem.propMales,trfr.moveModel,trfr.moveType)); + juvs.push_back(new Individual(pCell, pPatch, 0, 0, 0, dem.propMales, trfr.moveModel, trfr.moveType)); #endif - sex = juvs[nj+j]->getSex(); + sex = juvs[nj + j]->getSex(); nInds[0][sex]++; if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) { // juv inherits genome from parents - juvs[nj+j]->setGenes(pSpecies,inds[i],father,resol); + juvs[nj + j]->setGenes(pSpecies, inds[i], father, resol); } } + } } } } } - } - fathers.clear(); - break; - -} // end of switch (dem.repType) + fathers.clear(); + break; -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): before reprodn. " << " inds.size() = " << inds.size() -// << endl; -#endif + } // end of switch (dem.repType) // THIS MAY NOT BE CORRECT FOR MULTIPLE SPECIES IF THERE IS SOME FORM OF // CROSS-SPECIES DENSITY-DEPENDENT FECUNDITY - -#if RSDEBUG -//DEBUGLOG << "Population::reproduction(): after reprodn. this = " << this -// << " juvs.size() = " << juvs.size() << " inds.size() = " << inds.size() -// << endl; -#endif - } // Following reproduction of ALL species, add juveniles to the population prior to dispersal void Population::fledge(void) { -#if RSDEBUG -//DEBUGLOG << "Population::fledge(): this=" << this -// << " ninds=" << (int)inds.size() -// << " njuvs=" << (int)juvs.size() -// << endl; -#endif -demogrParams dem = pSpecies->getDemogr(); + demogrParams dem = pSpecies->getDemogr(); -if (dem.stageStruct) { // juveniles are added to the individuals vector - inds.insert(inds.end(),juvs.begin(),juvs.end()); -// nInds += nJuvs; nJuvs = 0; -} -else { // all adults die and juveniles replace adults - int ninds = (int)inds.size(); - for (int i = 0; i < ninds; i++) { - delete inds[i]; + if (dem.stageStruct) { // juveniles are added to the individuals vector + inds.insert(inds.end(), juvs.begin(), juvs.end()); } - inds.clear(); - for (int sex = 0; sex < nSexes; sex++) { - nInds[1][sex] = 0; // set count of adults to zero + else { // all adults die and juveniles replace adults + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + delete inds[i]; + } + inds.clear(); + for (int sex = 0; sex < nSexes; sex++) { + nInds[1][sex] = 0; // set count of adults to zero + } + inds = juvs; } - inds = juvs; -} -juvs.clear(); + juvs.clear(); } // Determine which individuals will disperse void Population::emigration(float localK) { -int nsexes; -double disp,Pdisp,NK; -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -emigTraits eparams; -trfrRules trfr = pSpecies->getTrfr(); -indStats ind; -#if RSDEBUG -//DEBUGLOG << "Population::emigration(): this=" << this -// << " nStages=" << sstruct.nStages -//// << " emig.emigGenes[0]=" << emig.emigGenes[0] -//// << " emig.emigGenes[1]=" << emig.emigGenes[1] -// << endl; -#endif + int nsexes; + double disp, Pdisp, NK; + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + emigTraits eparams; + trfrRules trfr = pSpecies->getTrfr(); + indStats ind; // to avoid division by zero, assume carrying capacity is at least one individual // localK can be zero if there is a moving gradient or stochasticity in K -if (localK < 1.0) localK = 1.0; -NK = (float)totalPop() / localK; + if (localK < 1.0) localK = 1.0; + NK = (float)totalPop() / localK; -int ninds = (int)inds.size(); + int ninds = (int)inds.size(); -// set up local copy of emigration probability table -// used when there is no individual variability -// NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING -if (dem.repType == 0) nsexes = 1; else nsexes = 2; -double Pemig[NSTAGES][NSEXES]; + // set up local copy of emigration probability table + // used when there is no individual variability + // NB - IT IS DOUBTFUL THIS CONTRIBUTES ANY SUBSTANTIAL TIME SAVING + if (dem.repType == 0) nsexes = 1; else nsexes = 2; + double Pemig[NSTAGES][NSEXES]; -for (int stg = 0; stg < sstruct.nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (emig.indVar) Pemig[stg][sex] = 0.0; - else { - if (emig.densDep) { - if (emig.sexDep) { - if (emig.stgDep) { - eparams = pSpecies->getEmigTraits(stg,sex); + for (int stg = 0; stg < sstruct.nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (emig.indVar) Pemig[stg][sex] = 0.0; + else { + if (emig.densDep) { + if (emig.sexDep) { + if (emig.stgDep) { + eparams = pSpecies->getEmigTraits(stg, sex); + } + else { + eparams = pSpecies->getEmigTraits(0, sex); + } } - else { - eparams = pSpecies->getEmigTraits(0,sex); + else { // !emig.sexDep + if (emig.stgDep) { + eparams = pSpecies->getEmigTraits(stg, 0); + } + else { + eparams = pSpecies->getEmigTraits(0, 0); + } } - } - else { // !emig.sexDep - if (emig.stgDep) { - eparams = pSpecies->getEmigTraits(stg,0); - } - else { - eparams = pSpecies->getEmigTraits(0,0); - } - } - Pemig[stg][sex] = eparams.d0/(1.0+exp(-(NK - eparams.beta)*eparams.alpha)); -#if RSDEBUG -//if (ppLand.patch_model) { -// DEBUGLOG << "Population::emigration(): stg=" << stg << " sex=" << sex -// << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK -// << " d0=" << eparams.d0 << " beta=" << eparams.beta << " alpha=" << eparams.alpha -// << " Pemig[stg][sex]=" << Pemig[stg][sex] -// << endl; -//} -#endif - } - else { // density-independent - if (emig.sexDep) { - if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getEmigD0(stg,sex); - } - else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getEmigD0(0,sex); - } - } - else { // !emig.sexDep - if (emig.stgDep) { - Pemig[stg][sex] = pSpecies->getEmigD0(stg,0); - } - else { // !emig.stgDep - Pemig[stg][sex] = pSpecies->getEmigD0(0,0); - } - } - } - } // end of !emig.indVar -#if RSDEBUG -//DEBUGLOG << "Population::emigration(): this=" << (int)this -// << " totalPop()=" << totalPop() -// << " Pemig[" << stg << "][" << sex << "]="<< Pemig[stg][sex] << endl; -#endif - } -} - -//#if GROUPDISP -//bool newgroup = true; -//int currentsize = 0; -//#endif // GROUPDISP - -//#if PARTMIGRN -//double cumprop[7]; -//cumprop[0] = 0.0; -//for (int i = 1; i < 7; i++) { -// cumprop[i] = cumprop[i-1] + pSpecies->getPropDispMigrn(i); -//#if RSDEBUG -//DEBUGLOG << "Population::emigration(): i=" << i -// << " cumprop[i]=" << cumprop[i] -// << endl; -//#endif -//} -//#endif // PARTMIGRN -// - -for (int i = 0; i < ninds; i++) { - ind = inds[i]->getStats(); - if (ind.status < 1) - { - if (emig.indVar) { // individual variability in emigration - if (dem.stageStruct && ind.stage != emig.emigStage) { - // emigration may not occur - Pdisp = 0.0; - } - else { // non-structured or individual is in emigration stage - eparams = inds[i]->getEmigTraits(); - if (emig.densDep) { // density-dependent - NK = (float)totalPop() / localK; - Pdisp = eparams.d0/(1.0+exp(-(NK - eparams.beta)*eparams.alpha)); + Pemig[stg][sex] = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } else { // density-independent if (emig.sexDep) { - Pdisp = Pemig[0][ind.sex] + eparams.d0; + if (emig.stgDep) { + Pemig[stg][sex] = pSpecies->getEmigD0(stg, sex); + } + else { // !emig.stgDep + Pemig[stg][sex] = pSpecies->getEmigD0(0, sex); + } } - else { - Pdisp = Pemig[0][0] + eparams.d0; + else { // !emig.sexDep + if (emig.stgDep) { + Pemig[stg][sex] = pSpecies->getEmigD0(stg, 0); + } + else { // !emig.stgDep + Pemig[stg][sex] = pSpecies->getEmigD0(0, 0); + } } } - } - } // end of individual variability - else { // no individual variability + } // end of !emig.indVar + } + } - if (emig.densDep) { - if (emig.sexDep) { - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; - } - else { - Pdisp = Pemig[0][ind.sex]; - } + for (int i = 0; i < ninds; i++) { + ind = inds[i]->getStats(); + if (ind.status < 1) + { + if (emig.indVar) { // individual variability in emigration + if (dem.stageStruct && ind.stage != emig.emigStage) { + // emigration may not occur + Pdisp = 0.0; } - else { // !emig.sexDep - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + else { // non-structured or individual is in emigration stage + eparams = inds[i]->getEmigTraits(); + if (emig.densDep) { // density-dependent + NK = (float)totalPop() / localK; + Pdisp = eparams.d0 / (1.0 + exp(-(NK - eparams.beta) * eparams.alpha)); } - else { - Pdisp = Pemig[0][0]; + else { // density-independent + if (emig.sexDep) { + Pdisp = Pemig[0][ind.sex] + eparams.d0; + } + else { + Pdisp = Pemig[0][0] + eparams.d0; + } } } -#if RSDEBUG -//if (ppLand.patch_model) { -// DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage -// << " totalPop=" << totalPop() << " localK=" << localK << " NK=" << NK -// << " Pdisp=" << Pdisp -// << endl; -//} -#endif - } - else { // density-independent - if (emig.sexDep) { - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][ind.sex]; + } // end of individual variability + else { // no individual variability + + if (emig.densDep) { + if (emig.sexDep) { + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][ind.sex]; + } + else { + Pdisp = Pemig[0][ind.sex]; + } } - else { // !emig.stgDep - Pdisp = Pemig[0][ind.sex]; + else { // !emig.sexDep + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][0]; + } + else { + Pdisp = Pemig[0][0]; + } } } - else { // !emig.sexDep - if (emig.stgDep) { - Pdisp = Pemig[ind.stage][0]; + else { // density-independent + if (emig.sexDep) { + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][ind.sex]; + } + else { // !emig.stgDep + Pdisp = Pemig[0][ind.sex]; + } } - else { // !emig.stgDep - Pdisp = Pemig[0][0]; + else { // !emig.sexDep + if (emig.stgDep) { + Pdisp = Pemig[ind.stage][0]; + } + else { // !emig.stgDep + Pdisp = Pemig[0][0]; + } } } -//#if GROUPDISP -// if (emig.groupdisp) { -// if (Pdisp > 0) { -// -// } -// -// } -//#endif // GROUPDISP - } - - } // end of no individual variability - disp = pRandom->Bernoulli(Pdisp); -#if RSDEBUG -//DEBUGLOG << "Population::emigration(): i=" << i << " sex=" << ind.sex << " stage=" << ind.stage -// << " Pdisp=" << Pdisp << " disp=" << disp << endl; -#endif + } // end of no individual variability - if (disp == 1) { // emigrant - inds[i]->setStatus(1); - } - } // end of if (ind.status < 1) condition -} // end of for loop + disp = pRandom->Bernoulli(Pdisp); + + if (disp == 1) { // emigrant + inds[i]->setStatus(1); + } + } // end of if (ind.status < 1) condition + } // end of for loop } // All individuals emigrate after patch destruction void Population::allEmigrate(void) { -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - inds[i]->setStatus(1); -} + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + inds[i]->setStatus(1); + } } // If an Individual has been identified as an emigrant, remove it from the Population disperser Population::extractDisperser(int ix) { -disperser d; -indStats ind = inds[ix]->getStats(); -#if RSDEBUG -//if (ind.status > 0) { -// DEBUGLOG << "Population::extractDisperser(): ix = " << ix << " inds[ix] = " << inds[ix] -// << " indId = " << inds[ix]->getId() << " ind.status = " << ind.status -// << endl; -//} -#endif -if (ind.status == 1) { // emigrant - d.pInd = inds[ix]; d.yes = true; - inds[ix] = 0; - nInds[ind.stage][ind.sex]--; -} -else { - d.pInd = NULL; d.yes = false; -} -return d; + disperser d; + indStats ind = inds[ix]->getStats(); + if (ind.status == 1) { // emigrant + d.pInd = inds[ix]; d.yes = true; + inds[ix] = 0; + nInds[ind.stage][ind.sex]--; + } + else { + d.pInd = NULL; d.yes = false; + } + return d; } // For an individual identified as being in the matrix population: // if it is a settler, return its new location and remove it from the current population // otherwise, leave it in the matrix population for possible reporting before deletion disperser Population::extractSettler(int ix) { -disperser d; -Cell* pCell; -//Patch* pPatch; + disperser d; + Cell* pCell; -indStats ind = inds[ix]->getStats(); + indStats ind = inds[ix]->getStats(); -pCell = inds[ix]->getLocn(1); -#if RSDEBUG -//DEBUGLOG << "Population::extractSettler(): ix = " << ix << " inds[ix] = " << inds[ix] -// << " indId = " << inds[ix]->getId() << " ind.status = " << ind.status << endl; -#endif -d.pInd = inds[ix]; d.pCell = pCell; d.yes = false; -if (ind.status == 4 || ind.status == 5) { // settled - d.yes = true; - inds[ix] = 0; - nInds[ind.stage][ind.sex]--; -} -return d; + pCell = inds[ix]->getLocn(1); + d.pInd = inds[ix]; d.pCell = pCell; d.yes = false; + if (ind.status == 4 || ind.status == 5) { // settled + d.yes = true; + inds[ix] = 0; + nInds[ind.stage][ind.sex]--; + } + return d; } // Add a specified individual to the new/current dispersal group // Add a specified individual to the population -void Population::recruit(Individual *pInd) { -inds.push_back(pInd); -indStats ind = pInd->getStats(); -nInds[ind.stage][ind.sex]++; -#if RSDEBUG -//DEBUGLOG << "Population::recruit(): patchNum=" << pPatch->getPatchNum() -// << " indId=" << pInd->getId() -// << " nInds[" << ind.stage << "][" << ind.sex << "]=" << nInds[ind.stage][ind.sex] -// << endl; -#endif +void Population::recruit(Individual* pInd) { + inds.push_back(pInd); + indStats ind = pInd->getStats(); + nInds[ind.stage][ind.sex]++; } //--------------------------------------------------------------------------- // Transfer is run for populations in the matrix only #if RS_RCPP // included also SEASONAL -int Population::transfer(Landscape *pLandscape,short landIx,short nextseason) +int Population::transfer(Landscape* pLandscape, short landIx, short nextseason) #else -int Population::transfer(Landscape *pLandscape,short landIx) +int Population::transfer(Landscape* pLandscape, short landIx) #endif { -int ndispersers = 0; -int disperser; -short othersex; -bool mateOK,densdepOK; -intptr patch,popn; -int patchnum; -double localK,popsize,settprob; -Patch *pPatch = 0; -Cell *pCell = 0; -indStats ind; -Population *pNewPopn = 0; -locn newloc,nbrloc; - -landData ppLand = pLandscape->getLandData(); -short reptype = pSpecies->getRepType(); -trfrRules trfr = pSpecies->getTrfr(); -settleType settletype = pSpecies->getSettle(); -settleRules sett; -settleTraits settDD; -settlePatch settle; -simParams sim = paramsSim->getSim(); - -// each individual takes one step -// for dispersal by kernel, this should be the only step taken -int ninds = (int)inds.size(); -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 0000: ninds = " << ninds -// << " ndispersers = " << ndispersers << endl; -#endif -for (int i = 0; i < ninds; i++) { -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 1111: i = " << i << " ID = " << inds[i]->getId() -// << endl; -#endif - if (trfr.moveModel) { -#if RSDEBUG -//pCell = inds[i]->getLocn(1); -//locn loc = pCell->getLocn(); -//DEBUGLOG << "Population::transfer(): 1112: i = " << i << " ID = " << inds[i]->getId() -// << " before:" << " x = " << loc.x << " y = " << loc.y -// << endl; -#endif - disperser = inds[i]->moveStep(pLandscape,pSpecies,landIx,sim.absorbing); -#if RSDEBUG -//pCell = inds[i]->getLocn(1); -//newloc = pCell->getLocn(); -//DEBUGLOG << "Population::transfer(): 1113: i = " << i << " ID = " << inds[i]->getId() -// << " after: " << " x = " << newloc.x << " y = " << newloc.y -// << endl; -#endif - } - else { - disperser = inds[i]->moveKernel(pLandscape,pSpecies,reptype,sim.absorbing); - } - ndispersers += disperser; - if (disperser) { - if (reptype > 0) - { // sexual species - record as potential settler in new patch - if (inds[i]->getStatus() == 2) - { // disperser has found a patch - pCell = inds[i]->getLocn(1); - patch = pCell->getPatch(); - if (patch != 0) { // not no-data area - pPatch = (Patch*)patch; - pPatch->incrPossSettler(pSpecies,inds[i]->getSex()); + int ndispersers = 0; + int disperser; + short othersex; + bool mateOK, densdepOK; + intptr patch, popn; + int patchnum; + double localK, popsize, settprob; + Patch* pPatch = 0; + Cell* pCell = 0; + indStats ind; + Population* pNewPopn = 0; + locn newloc, nbrloc; + + landData ppLand = pLandscape->getLandData(); + short reptype = pSpecies->getRepType(); + trfrRules trfr = pSpecies->getTrfr(); + settleType settletype = pSpecies->getSettle(); + settleRules sett; + settleTraits settDD; + settlePatch settle; + simParams sim = paramsSim->getSim(); + + // each individual takes one step + // for dispersal by kernel, this should be the only step taken + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + if (trfr.moveModel) { + disperser = inds[i]->moveStep(pLandscape, pSpecies, landIx, sim.absorbing); + } + else { + disperser = inds[i]->moveKernel(pLandscape, pSpecies, reptype, sim.absorbing); + } + ndispersers += disperser; + if (disperser) { + if (reptype > 0) + { // sexual species - record as potential settler in new patch + if (inds[i]->getStatus() == 2) + { // disperser has found a patch + pCell = inds[i]->getLocn(1); + patch = pCell->getPatch(); + if (patch != 0) { // not no-data area + pPatch = (Patch*)patch; + pPatch->incrPossSettler(pSpecies, inds[i]->getSex()); + } } } } } -} -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 5555: ninds=" << ninds -// << " ndispersers=" << ndispersers << endl; -#endif // each individual which has reached a potential patch decides whether to settle -for (int i = 0; i < ninds; i++) { - ind = inds[i]->getStats(); - if (ind.sex == 0) othersex = 1; else othersex = 0; - if (settletype.stgDep) { - if (settletype.sexDep) sett = pSpecies->getSettRules(ind.stage,ind.sex); - else sett = pSpecies->getSettRules(ind.stage,0); - } - else { - if (settletype.sexDep) sett = pSpecies->getSettRules(0,ind.sex); - else sett = pSpecies->getSettRules(0,0); - } - if (ind.status == 2) - { // awaiting settlement - pCell = inds[i]->getLocn(1); - if (pCell == 0) { - // this condition can occur in a patch-based model at the time of a dynamic landscape - // change when there is a range restriction in place, since a patch can straddle the - // range restriction and an individual forced to disperse upon patch removal could - // start its trajectory beyond the boundary of the restrictyed range - such a model is - // not good practice, but the condition must be handled by killing the individual conceerned - ind.status = 6; + for (int i = 0; i < ninds; i++) { + ind = inds[i]->getStats(); + if (ind.sex == 0) othersex = 1; else othersex = 0; + if (settletype.stgDep) { + if (settletype.sexDep) sett = pSpecies->getSettRules(ind.stage, ind.sex); + else sett = pSpecies->getSettRules(ind.stage, 0); } else { - -#if RSDEBUG -//newloc = pCell->getLocn(); -//DEBUGLOG << "Population::transfer(): 6666: i=" << i << " ID=" << inds[i]->getId() -// << " sex=" << ind.sex << " status=" << ind.status -// << " pCell=" << pCell << " x=" << newloc.x << " y=" << newloc.y -// << " findMate=" << sett.findMate -//// << " wait=" << sett.wait -//// << " go2nbrLocn=" << sett.go2nbrLocn -// << endl; -#endif - - mateOK = false; - if (sett.findMate) { - // determine whether at least one individual of the opposite sex is present in the - // new population - if (matePresent(pCell,othersex)) mateOK = true; -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 7777: othersex=" << othersex -// << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize << " mateOK=" << mateOK -// << endl; -#endif - } - else { // no requirement to find a mate - mateOK = true; + if (settletype.sexDep) sett = pSpecies->getSettRules(0, ind.sex); + else sett = pSpecies->getSettRules(0, 0); + } + if (ind.status == 2) + { // awaiting settlement + pCell = inds[i]->getLocn(1); + if (pCell == 0) { + // this condition can occur in a patch-based model at the time of a dynamic landscape + // change when there is a range restriction in place, since a patch can straddle the + // range restriction and an individual forced to disperse upon patch removal could + // start its trajectory beyond the boundary of the restrictyed range - such a model is + // not good practice, but the condition must be handled by killing the individual conceerned + ind.status = 6; } + else { + mateOK = false; + if (sett.findMate) { + // determine whether at least one individual of the opposite sex is present in the + // new population + if (matePresent(pCell, othersex)) mateOK = true; + } + else { // no requirement to find a mate + mateOK = true; + } - densdepOK = false; - settle = inds[i]->getSettPatch(); - if (sett.densDep) - { - patch = pCell->getPatch(); -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8880: i=" << i << " patch=" << patch -// << endl; -#endif - if (patch != 0) { // not no-data area - pPatch = (Patch*)patch; - if (settle.settleStatus == 0 - || settle.pSettPatch != pPatch) - // note: second condition allows for having moved from one patch to another - // adjacent one - { -// inds[i]->resetPathOut(); // reset steps out of patch to zero - // determine whether settlement occurs in the (new) patch - localK = (double)pPatch->getK(); - popn = pPatch->getPopn((intptr)pSpecies); -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8881: i=" << i << " patchNum=" << pPatch->getPatchNum() -// << " localK=" << localK << " popn=" << popn << endl; -#endif - if (popn == 0) { // population has not been set up in the new patch - popsize = 0.0; - } - else { - pNewPopn = (Population*)popn; - popsize = (double)pNewPopn->totalPop(); - } - if (localK > 0.0) { - // make settlement decision - if (settletype.indVar) settDD = inds[i]->getSettTraits(); + densdepOK = false; + settle = inds[i]->getSettPatch(); + if (sett.densDep) + { + patch = pCell->getPatch(); + if (patch != 0) { // not no-data area + pPatch = (Patch*)patch; + if (settle.settleStatus == 0 + || settle.pSettPatch != pPatch) + // note: second condition allows for having moved from one patch to another + // adjacent one + { + // determine whether settlement occurs in the (new) patch + localK = (double)pPatch->getK(); + popn = pPatch->getPopn((intptr)pSpecies); + if (popn == 0) { // population has not been set up in the new patch + popsize = 0.0; + } + else { + pNewPopn = (Population*)popn; + popsize = (double)pNewPopn->totalPop(); + } + if (localK > 0.0) { + // make settlement decision + if (settletype.indVar) settDD = inds[i]->getSettTraits(); #if RS_RCPP - else settDD = pSpecies->getSettTraits(ind.stage,ind.sex); + else settDD = pSpecies->getSettTraits(ind.stage, ind.sex); #else - else { - if (settletype.sexDep) { - if (settletype.stgDep) - settDD = pSpecies->getSettTraits(ind.stage,ind.sex); - else - settDD = pSpecies->getSettTraits(0,ind.sex); - } else { - if (settletype.stgDep) - settDD = pSpecies->getSettTraits(ind.stage,0); - else - settDD = pSpecies->getSettTraits(0,0); + if (settletype.sexDep) { + if (settletype.stgDep) + settDD = pSpecies->getSettTraits(ind.stage, ind.sex); + else + settDD = pSpecies->getSettTraits(0, ind.sex); + } + else { + if (settletype.stgDep) + settDD = pSpecies->getSettTraits(ind.stage, 0); + else + settDD = pSpecies->getSettTraits(0, 0); + } } - } #endif //RS_RCPP - settprob = settDD.s0 / - (1.0 + exp(-(popsize/localK - (double)settDD.beta) * (double)settDD.alpha)); -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8888: i=" << i << " ind.stage=" << ind.stage -// << " this=" << this << " pNewPopn=" << pNewPopn << " popsize=" << popsize -// << " localK=" << localK << " alpha=" << settDD.alpha << " beta=" << settDD.beta -// << " settprob=" << settprob -// << endl; -#endif - if (pRandom->Bernoulli(settprob)) { // settlement allowed - densdepOK = true; - settle.settleStatus = 2; - } - else { // settlement procluded - settle.settleStatus = 1; + settprob = settDD.s0 / + (1.0 + exp(-(popsize / localK - (double)settDD.beta) * (double)settDD.alpha)); + + if (pRandom->Bernoulli(settprob)) { // settlement allowed + densdepOK = true; + settle.settleStatus = 2; + } + else { // settlement procluded + settle.settleStatus = 1; + } + settle.pSettPatch = pPatch; } -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 8889: i=" << i -// << " settleStatus=" << settle.settleStatus << " mateOK=" << (int)mateOK; -//if (settle.settleStatus == 2 && mateOK) { -// DEBUGLOG << " SETTLES -"; -// if (ind.sex == 1) DEBUGLOG << " MALE "; else DEBUGLOG << " FEMALE "; -//} -//DEBUGLOG << endl; -#endif - settle.pSettPatch = pPatch; + inds[i]->setSettPatch(settle); } - inds[i]->setSettPatch(settle); - } - else { - if (settle.settleStatus == 2) { // previously allowed to settle - densdepOK = true; + else { + if (settle.settleStatus == 2) { // previously allowed to settle + densdepOK = true; + } } } } - } - else { // no density-dependent settlement - densdepOK = true; - settle.settleStatus = 2; - settle.pSettPatch = pPatch; - inds[i]->setSettPatch(settle); - } + else { // no density-dependent settlement + densdepOK = true; + settle.settleStatus = 2; + settle.pSettPatch = pPatch; + inds[i]->setSettPatch(settle); + } - if (mateOK && densdepOK) { // can recruit to patch - ind.status = 4; - ndispersers--; - } - else { // does not recruit - if (trfr.moveModel) { - ind.status = 1; // continue dispersing, unless ... - // ... maximum steps has been exceeded - pathSteps steps = inds[i]->getSteps(); - settleSteps settsteps = pSpecies->getSteps(ind.stage,ind.sex); - if (steps.year >= settsteps.maxStepsYr) { - ind.status = 3; // waits until next year - } - if (steps.total >= settsteps.maxSteps) { - ind.status = 6; // dies - } + if (mateOK && densdepOK) { // can recruit to patch + ind.status = 4; + ndispersers--; } - else { // dispersal kernel - if (sett.wait) { - ind.status = 3; // wait until next dispersal event + else { // does not recruit + if (trfr.moveModel) { + ind.status = 1; // continue dispersing, unless ... + // ... maximum steps has been exceeded + pathSteps steps = inds[i]->getSteps(); + settleSteps settsteps = pSpecies->getSteps(ind.stage, ind.sex); + if (steps.year >= settsteps.maxStepsYr) { + ind.status = 3; // waits until next year + } + if (steps.total >= settsteps.maxSteps) { + ind.status = 6; // dies + } } - else { - ind.status = 6; // (dies unless a neighbouring cell is suitable) + else { // dispersal kernel + if (sett.wait) { + ind.status = 3; // wait until next dispersal event + } + else { + ind.status = 6; // (dies unless a neighbouring cell is suitable) + } + ndispersers--; } - ndispersers--; } } - } - inds[i]->setStatus(ind.status); - } + inds[i]->setStatus(ind.status); + } #if RS_RCPP - // write each individuals current movement step and status to paths file - if (trfr.moveModel && sim.outPaths) { - if(nextseason >= sim.outStartPaths && nextseason%sim.outIntPaths==0) { + // write each individuals current movement step and status to paths file + if (trfr.moveModel && sim.outPaths) { + if (nextseason >= sim.outStartPaths && nextseason % sim.outIntPaths == 0) { inds[i]->outMovePath(nextseason); + } } - } #endif - if (!trfr.moveModel && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) - { - // for kernel-based transfer only ... - // determine whether recruitment to a neighbouring cell is possible -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): neighbour cell search: sett.go2nbrLocn = " << sett.go2nbrLocn -// << " ind.status = " << ind.status -// << endl; -#endif - pCell = inds[i]->getLocn(1); - newloc = pCell->getLocn(); - vector nbrlist; - for (int dx = -1; dx < 2; dx++) { - for (int dy = -1; dy < 2; dy++) { - if (dx !=0 || dy != 0) { //cell is not the current cell - nbrloc.x = newloc.x + dx; nbrloc.y = newloc.y + dy; - if (nbrloc.x >= 0 && nbrloc.x <= ppLand.maxX - && nbrloc.y >= 0 && nbrloc.y <= ppLand.maxY) { // within landscape - // add to list of potential neighbouring cells if suitable, etc. - pCell = pLandscape->findCell(nbrloc.x,nbrloc.y); - if (pCell != 0) { // not no-data area - patch = pCell->getPatch(); - if (patch != 0) { // not no-data area - pPatch = (Patch*)patch; - patchnum = pPatch->getPatchNum(); - if (patchnum > 0 && pPatch != inds[i]->getNatalPatch()) - { // not the matrix or natal patch - if (pPatch->getK() > 0.0) - { // suitable - if (sett.findMate) { - if (matePresent(pCell,othersex)) nbrlist.push_back(pCell); + if (!trfr.moveModel && sett.go2nbrLocn && (ind.status == 3 || ind.status == 6)) + { + // for kernel-based transfer only ... + // determine whether recruitment to a neighbouring cell is possible + + pCell = inds[i]->getLocn(1); + newloc = pCell->getLocn(); + vector nbrlist; + for (int dx = -1; dx < 2; dx++) { + for (int dy = -1; dy < 2; dy++) { + if (dx != 0 || dy != 0) { //cell is not the current cell + nbrloc.x = newloc.x + dx; nbrloc.y = newloc.y + dy; + if (nbrloc.x >= 0 && nbrloc.x <= ppLand.maxX + && nbrloc.y >= 0 && nbrloc.y <= ppLand.maxY) { // within landscape + // add to list of potential neighbouring cells if suitable, etc. + pCell = pLandscape->findCell(nbrloc.x, nbrloc.y); + if (pCell != 0) { // not no-data area + patch = pCell->getPatch(); + if (patch != 0) { // not no-data area + pPatch = (Patch*)patch; + patchnum = pPatch->getPatchNum(); + if (patchnum > 0 && pPatch != inds[i]->getNatalPatch()) + { // not the matrix or natal patch + if (pPatch->getK() > 0.0) + { // suitable + if (sett.findMate) { + if (matePresent(pCell, othersex)) nbrlist.push_back(pCell); + } + else + nbrlist.push_back(pCell); } - else - nbrlist.push_back(pCell); } } } @@ -1380,61 +1050,54 @@ for (int i = 0; i < ninds; i++) { } } } - } - int listsize = (int)nbrlist.size(); - if (listsize > 0) { // there is at least one suitable neighbouring cell - if (listsize == 1) { - inds[i]->moveto(nbrlist[0]); - } - else { // select at random from the list - int rrr = pRandom->IRandom(0,listsize-1); - inds[i]->moveto(nbrlist[rrr]); + int listsize = (int)nbrlist.size(); + if (listsize > 0) { // there is at least one suitable neighbouring cell + if (listsize == 1) { + inds[i]->moveto(nbrlist[0]); + } + else { // select at random from the list + int rrr = pRandom->IRandom(0, listsize - 1); + inds[i]->moveto(nbrlist[rrr]); + } } + // else list empty - do nothing - individual retains its current location and status } - // else list empty - do nothing - individual retains its current location and status } -} -#if RSDEBUG -//DEBUGLOG << "Population::transfer(): 9999: ninds = " << ninds -// << " ndispersers = " << ndispersers << endl; -#endif - - -return ndispersers; + return ndispersers; } // Determine whether there is a potential mate present in a patch which a potential // settler has reached -bool Population::matePresent(Cell *pCell,short othersex) +bool Population::matePresent(Cell* pCell, short othersex) { -int patch; -Patch *pPatch; -Population *pNewPopn; -int popsize = 0; -bool matefound = false; - -patch = (int)pCell->getPatch(); -if (patch != 0) { - pPatch = (Patch*)pCell->getPatch(); - if (pPatch->getPatchNum() > 0) { // not the matrix patch - if (pPatch->getK() > 0.0) - { // suitable - pNewPopn = (Population*)pPatch->getPopn((intptr)pSpecies); - if (pNewPopn != 0) { - // count members of other sex already resident in the patch - for (int stg = 0; stg < nStages; stg++) { - popsize += pNewPopn->nInds[stg][othersex]; + int patch; + Patch* pPatch; + Population* pNewPopn; + int popsize = 0; + bool matefound = false; + + patch = (int)pCell->getPatch(); + if (patch != 0) { + pPatch = (Patch*)pCell->getPatch(); + if (pPatch->getPatchNum() > 0) { // not the matrix patch + if (pPatch->getK() > 0.0) + { // suitable + pNewPopn = (Population*)pPatch->getPopn((intptr)pSpecies); + if (pNewPopn != 0) { + // count members of other sex already resident in the patch + for (int stg = 0; stg < nStages; stg++) { + popsize += pNewPopn->nInds[stg][othersex]; + } + } + if (popsize < 1) { + // add any potential settlers of the other sex + popsize += pPatch->getPossSettlers(pSpecies, othersex); } - } - if (popsize < 1) { - // add any potential settlers of the other sex - popsize += pPatch->getPossSettlers(pSpecies,othersex); } } } -} -if (popsize > 0) matefound = true; -return matefound; + if (popsize > 0) matefound = true; + return matefound; } //--------------------------------------------------------------------------- @@ -1444,794 +1107,565 @@ return matefound; // FOR MULTIPLE SPECIES, MAY NEED TO SEPARATE OUT THIS IDENTIFICATION STAGE, // SO THAT IT CAN BE PERFORMED FOR ALL SPECIES BEFORE ANY UPDATING OF POPULATIONS -void Population::survival0(float localK,short option0,short option1) +void Population::survival0(float localK, short option0, short option1) { -// option0: 0 - stage 0 (juveniles) only -// 1 - all stages -// 2 - stage 1 and above (all non-juveniles) -// option1: 0 - development only (when survival is annual) -// 1 - development and survival -// 2 - survival only (when survival is annual) - -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " pSpecies=" << pSpecies << " this=" << this << " PatchNum=" << pPatch->getPatchNum() -//#if SEASONAL -// << " season=" << season -//#endif // SEASONAL -// << " localK=" << localK << " option=" << option -// << endl; -#endif + // option0: 0 - stage 0 (juveniles) only + // 1 - all stages + // 2 - stage 1 and above (all non-juveniles) + // option1: 0 - development only (when survival is annual) + // 1 - development and survival + // 2 - survival only (when survival is annual) + + densDepParams ddparams = pSpecies->getDensDep(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); -densDepParams ddparams = pSpecies->getDensDep(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); - -// get surrent population size -int ninds = (int)inds.size(); -if (ninds == 0) return; - -// set up local copies of species development and survival tables -int nsexes; -if (dem.repType == 0) nsexes = 1; else nsexes = 2; -float dev[NSTAGES][NSEXES]; -float surv[NSTAGES][NSEXES]; -short minAge[NSTAGES][NSEXES]; -for (int stg = 0; stg < sstruct.nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (dem.stageStruct) { - if (dem.repType == 1) { // simple sexual model - // both sexes use development and survival recorded for females - dev[stg][sex] = pSpecies->getDev(stg,0); - surv[stg][sex] = pSpecies->getSurv(stg,0); - minAge[stg][sex] = pSpecies->getMinAge(stg,0); - } - else { - dev[stg][sex] = pSpecies->getDev(stg,sex); - surv[stg][sex] = pSpecies->getSurv(stg,sex); - minAge[stg][sex] = pSpecies->getMinAge(stg,sex); - } - if (option1 == 0) surv[stg][sex] = 1.0; // development only - all survive - if (option1 == 2) dev[stg][sex] = 0.0; // survival only - none develops - } - else { // non-structured population - if (stg == 1) { // adults - dev[stg][sex] = 0.0; surv[stg][sex] = 0.0; minAge[stg][sex] = 0; + // get surrent population size + int ninds = (int)inds.size(); + if (ninds == 0) return; + + // set up local copies of species development and survival tables + int nsexes; + if (dem.repType == 0) nsexes = 1; else nsexes = 2; + float dev[NSTAGES][NSEXES]; + float surv[NSTAGES][NSEXES]; + short minAge[NSTAGES][NSEXES]; + for (int stg = 0; stg < sstruct.nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (dem.stageStruct) { + if (dem.repType == 1) { // simple sexual model + // both sexes use development and survival recorded for females + dev[stg][sex] = pSpecies->getDev(stg, 0); + surv[stg][sex] = pSpecies->getSurv(stg, 0); + minAge[stg][sex] = pSpecies->getMinAge(stg, 0); + } + else { + dev[stg][sex] = pSpecies->getDev(stg, sex); + surv[stg][sex] = pSpecies->getSurv(stg, sex); + minAge[stg][sex] = pSpecies->getMinAge(stg, sex); + } + if (option1 == 0) surv[stg][sex] = 1.0; // development only - all survive + if (option1 == 2) dev[stg][sex] = 0.0; // survival only - none develops } - else { // juveniles - dev[stg][sex] = 1.0; surv[stg][sex] = 1.0; minAge[stg][sex] = 0; + else { // non-structured population + if (stg == 1) { // adults + dev[stg][sex] = 0.0; surv[stg][sex] = 0.0; minAge[stg][sex] = 0; + } + else { // juveniles + dev[stg][sex] = 1.0; surv[stg][sex] = 1.0; minAge[stg][sex] = 0; + } } } -#if RSDEBUG -//DEBUGLOG << "Population::survival0(): 1111 " -// << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] -// << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] -// << endl; -#endif } -} -if (dem.stageStruct) { -#if RSDEBUG -// DEBUGLOG << "Population::survival0(): 2222 " -// << " ninds=" << ninds << " localK=" << localK -// << " effect of density dependence:" << endl; -// for (int st = 0; st < nStages; st++) { -// for (int sx = 0; sx < nsexes; sx++) { -// DEBUGLOG << "st=" << st << " sx=" << sx << " nInds=" << nInds[st][sx] << endl; -// } -// } -#endif + if (dem.stageStruct) { // apply density dependence in development and/or survival probabilities - for (int stg = 0; stg < nStages; stg++) { - for (int sex = 0; sex < nsexes; sex++) { - if (option1 != 2 && sstruct.devDens && stg > 0) { + for (int stg = 0; stg < nStages; stg++) { + for (int sex = 0; sex < nsexes; sex++) { + if (option1 != 2 && sstruct.devDens && stg > 0) { #if RSDEBUG -// DEBUGLOG << "DD in DEVELOPMENT for stg=" << stg << " sex=" << sex << endl; + // DEBUGLOG << "DD in DEVELOPMENT for stg=" << stg << " sex=" << sex << endl; #endif // NB DD in development does NOT apply to juveniles, // which must develop to stage 1 if they survive - float effect = 0.0; - if (sstruct.devStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN - // AND males precede females - float weight = 0.0; - for (int effstg = 0; effstg < nStages; effstg++) { - for (int effsex = 0; effsex < nSexes; effsex++) { - if (dem.repType == 2) { - int rowincr,colincr; - if (effsex == 0) rowincr = 1; else rowincr = 0; - if (sex == 0) colincr = 1; else colincr = 0; - weight = pSpecies->getDDwtDev(2*stg+colincr,2*effstg+rowincr); - } - else { - weight = pSpecies->getDDwtDev(stg,effstg); + float effect = 0.0; + if (sstruct.devStageDens) { // stage-specific density dependence + // NOTE: matrix entries represent effect of ROW on COLUMN + // AND males precede females + float weight = 0.0; + for (int effstg = 0; effstg < nStages; effstg++) { + for (int effsex = 0; effsex < nSexes; effsex++) { + if (dem.repType == 2) { + int rowincr, colincr; + if (effsex == 0) rowincr = 1; else rowincr = 0; + if (sex == 0) colincr = 1; else colincr = 0; + weight = pSpecies->getDDwtDev(2 * stg + colincr, 2 * effstg + rowincr); + } + else { + weight = pSpecies->getDDwtDev(stg, effstg); + } + effect += (float)nInds[effstg][effsex] * weight; } - effect += (float)nInds[effstg][effsex] * weight; -#if RSDEBUG -// DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; -// DEBUGLOG << " weight=" << weight << " effect=" << effect -// << endl; -#endif } } - } - else // not stage-specific - effect = (float)totalPop(); - if (localK > 0.0) - dev[stg][sex] *= exp(-(ddparams.devCoeff*effect)/localK); -#if RSDEBUG -//DEBUGLOG << "Population::survival0(): 2288 " << " effect=" << effect; -//if (localK > 0.0) -// DEBUGLOG << " exp=" << exp(-(ddparams.devCoeff*effect)/localK); -//DEBUGLOG << " dev[" << stg << "][" << sex << "] = " << dev[stg][sex] -// << endl; -#endif - } // end of if (sstruct.devDens && stg > 0) - if (option1 != 0 && sstruct.survDens) { -#if RSDEBUG -// DEBUGLOG << "DD in SURVIVAL for stg=" << stg << " sex=" << sex << endl; -#endif - float effect = 0.0; - if (sstruct.survStageDens) { // stage-specific density dependence - // NOTE: matrix entries represent effect of ROW on COLUMN - // AND males precede females - float weight = 0.0; - for (int effstg = 0; effstg < nStages; effstg++) { - for (int effsex = 0; effsex < nSexes; effsex++) { - if (dem.repType == 2) { - int rowincr,colincr; - if (effsex == 0) rowincr = 1; else rowincr = 0; - if (sex == 0) colincr = 1; else colincr = 0; - weight = pSpecies->getDDwtSurv(2*stg+colincr,2*effstg+rowincr); - } - else { - weight = pSpecies->getDDwtSurv(stg,effstg); + else // not stage-specific + effect = (float)totalPop(); + if (localK > 0.0) + dev[stg][sex] *= exp(-(ddparams.devCoeff * effect) / localK); + } // end of if (sstruct.devDens && stg > 0) + if (option1 != 0 && sstruct.survDens) { + float effect = 0.0; + if (sstruct.survStageDens) { // stage-specific density dependence + // NOTE: matrix entries represent effect of ROW on COLUMN + // AND males precede females + float weight = 0.0; + for (int effstg = 0; effstg < nStages; effstg++) { + for (int effsex = 0; effsex < nSexes; effsex++) { + if (dem.repType == 2) { + int rowincr, colincr; + if (effsex == 0) rowincr = 1; else rowincr = 0; + if (sex == 0) colincr = 1; else colincr = 0; + weight = pSpecies->getDDwtSurv(2 * stg + colincr, 2 * effstg + rowincr); + } + else { + weight = pSpecies->getDDwtSurv(stg, effstg); + } + effect += (float)nInds[effstg][effsex] * weight; } - effect += (float)nInds[effstg][effsex] * weight; -#if RSDEBUG -// DEBUGLOG << " effstg=" << effstg << " effsex=" << effsex; -// DEBUGLOG << " weight=" << weight << " effect=" << effect -// << endl; -#endif } } - } - else // not stage-specific - effect = (float)totalPop(); - if (localK > 0.0) - surv[stg][sex] *= exp(-(ddparams.survCoeff*effect)/localK); -#if RSDEBUG -//DEBUGLOG << "Population::survival0(): 3333 " << " effect=" << effect; -//if (localK > 0.0) -// DEBUGLOG << " exp = " << exp(-(ddparams.survCoeff*effect)/localK); -//DEBUGLOG << " surv[" << stg << "][" << sex << "] = " << surv[stg][sex] -// << endl; -#endif - } // end of if (sstruct.survDens) + else // not stage-specific + effect = (float)totalPop(); + if (localK > 0.0) + surv[stg][sex] *= exp(-(ddparams.survCoeff * effect) / localK); + } // end of if (sstruct.survDens) + } } } -} -// identify which individuals die or develop -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" << " ninds " << ninds -// << endl; -#endif -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() -// << " stage=" << ind.stage << " status=" << ind.status << " sex=" << ind.sex -//#if PARTMIGRN -// << " migrnstatus=" << inds[i]->getMigrnStatus() -//#endif // PARTMIGRN -// << endl; -#endif - if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { - // condition for processing the stage is met... - if (ind.status < 6) { // not already doomed - double probsurv = surv[ind.stage][ind.sex]; - // does the individual survive? - if (pRandom->Bernoulli(probsurv)) { // survives - // does the individual develop? - double probdev = dev[ind.stage][ind.sex]; - if (ind.stage < nStages-1) { // not final stage -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() -// << " age=" << ind.age << " minAge[stage+1]=" << minAge[ind.stage+1][ind.sex] -// << " probdev=" << probdev -// << endl; -#endif - if (ind.age >= minAge[ind.stage+1][ind.sex]) { // old enough to enter next stage -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() << " OLD ENOUGH" -// << endl; -#endif - if (pRandom->Bernoulli(probdev)) { - inds[i]->developing(); + // identify which individuals die or develop + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); + if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { + // condition for processing the stage is met... + if (ind.status < 6) { // not already doomed + double probsurv = surv[ind.stage][ind.sex]; + // does the individual survive? + if (pRandom->Bernoulli(probsurv)) { // survives + // does the individual develop? + double probdev = dev[ind.stage][ind.sex]; + if (ind.stage < nStages - 1) { // not final stage + if (ind.age >= minAge[ind.stage + 1][ind.sex]) { // old enough to enter next stage + if (pRandom->Bernoulli(probdev)) { + inds[i]->developing(); + } } } } - } - else { // doomed to die -#if RSDEBUG -//DEBUGLOG << "Population::survival0():" -// << " i=" << i << " indId=" << inds[i]->getId() << " DIES" -// << endl; -#endif - inds[i]->setStatus(8); + else { // doomed to die + inds[i]->setStatus(8); + } } } } -#if RSDEBUG -//ind = inds[i]->getStats(); -//DEBUGLOG << "Population::survival0():" -// << " i = " << i << " ID = " << inds[i]->getId() -// << " stage = " << ind.stage << " status = " << ind.status -// << endl; -#endif -} } // Apply survival changes to the population void Population::survival1(void) { -int ninds = (int)inds.size(); -#if RSDEBUG -//DEBUGLOG << "Population::survival1(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() << " ninds=" << ninds -// << endl; -#endif -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); -#if RSDEBUG -//DEBUGLOG << "Population::survival1(): i=" << i -// << " indId=" << inds[i]->getId() << " stage=" << ind.stage << " sex=" << ind.sex -// << " isDeveloping=" << ind.isDeveloping << " status=" << ind.status -// << endl; -#endif - if (ind.status > 5) { // doomed to die - delete inds[i]; - inds[i] = NULL; - nInds[ind.stage][ind.sex]--; - } - else { - if (ind.isDeveloping) { // develops to next stage + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); + if (ind.status > 5) { // doomed to die + delete inds[i]; + inds[i] = NULL; nInds[ind.stage][ind.sex]--; - inds[i]->develop(); - nInds[ind.stage+1][ind.sex]++; + } + else { + if (ind.isDeveloping) { // develops to next stage + nInds[ind.stage][ind.sex]--; + inds[i]->develop(); + nInds[ind.stage + 1][ind.sex]++; + } } } -} -#if RSDEBUG -//DEBUGLOG << "Population::survival1(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() << " completed individuals loop" -// << endl; -#endif - -#if RSDEBUG -//for (int i = 0; i < inds.size(); i++) { -//DEBUGLOG << "Population::survival1():" << " inds[" << i << "] = " << inds[i] << endl; -//} -#endif // remove pointers to dead individuals -clean(); -#if RSDEBUG -//DEBUGLOG << "Population::survival1(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() << " finished" -// << endl; -#endif - + clean(); } void Population::ageIncrement(void) { -int ninds = (int)inds.size(); -stageParams sstruct = pSpecies->getStage(); -#if RSDEBUG -//DEBUGLOG << "Population::ageIncrement():" << " inds.size() = " << inds.size() -// << endl; -#endif -for (int i = 0; i < ninds; i++) { - inds[i]->ageIncrement(sstruct.maxAge); -} + int ninds = (int)inds.size(); + stageParams sstruct = pSpecies->getStage(); + for (int i = 0; i < ninds; i++) { + inds[i]->ageIncrement(sstruct.maxAge); + } } //--------------------------------------------------------------------------- // Remove zero pointers to dead or dispersed individuals void Population::clean(void) { -int ninds = (int)inds.size(); -if (ninds > 0) { -// sort (inds.begin(), inds.end()); -// reverse (inds.begin(), inds.end()); -// -// while (inds.size() > 0 && inds[inds.size()-1] == NULL ) { -// inds.pop_back(); -// } - // ALTERNATIVE METHOD: AVOIDS SLOW SORTING OF POPULATION - std::vector survivors; // all surviving individuals - for (int i = 0; i < ninds; i++) { - if (inds[i] != NULL) { - survivors.push_back(inds[i]); + int ninds = (int)inds.size(); + if (ninds > 0) { + // ALTERNATIVE METHOD: AVOIDS SLOW SORTING OF POPULATION + std::vector survivors; // all surviving individuals + for (int i = 0; i < ninds; i++) { + if (inds[i] != NULL) { + survivors.push_back(inds[i]); + } } - } - inds.clear(); - inds = survivors; + inds.clear(); + inds = survivors; #if RS_RCPP - shuffle(inds.begin(), inds.end(), pRandom->getRNG() ); + shuffle(inds.begin(), inds.end(), pRandom->getRNG()); #else #if !RSDEBUG - // do not randomise individuals in RSDEBUG mode, as the function uses rand() - // and therefore the randomisation will differ between identical runs of RS - shuffle(inds.begin(), inds.end(), pRandom->getRNG() ); + // do not randomise individuals in RSDEBUG mode, as the function uses rand() + // and therefore the randomisation will differ between identical runs of RS + shuffle(inds.begin(), inds.end(), pRandom->getRNG()); #endif // !RSDEBUG #endif // RS_RCPP -} + } } //--------------------------------------------------------------------------- // Open population file and write header record -bool Population::outPopHeaders(int landNr,bool patchModel) { +bool Population::outPopHeaders(int landNr, bool patchModel) { -if (landNr == -999) { // close file - if (outPop.is_open()) outPop.close(); - outPop.clear(); - return true; -} + if (landNr == -999) { // close file + if (outPop.is_open()) outPop.close(); + outPop.clear(); + return true; + } -string name; -//landParams ppLand = pLandscape->getLandParams(); -//envStochParams env = paramsStoch->getStoch(); -simParams sim = paramsSim->getSim(); -envGradParams grad = paramsGrad->getGradient(); + string name; + simParams sim = paramsSim->getSim(); + envGradParams grad = paramsGrad->getGradient(); -// NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER -// ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); + // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER + // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); -if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_Pop.txt"; -} -else{ - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) +"_Pop.txt"; -} -outPop.open(name.c_str()); -outPop << "Rep\tYear\tRepSeason"; -if (patchModel) outPop << "\tPatchID\tNcells"; -else outPop << "\tx\ty"; -// determine whether environmental data need be written for populations -bool writeEnv = false; -if (grad.gradient) writeEnv = true; -if (paramsStoch->envStoch()) writeEnv = true; -if (writeEnv) outPop << "\tEpsilon\tGradient\tLocal_K"; -outPop << "\tSpecies\tNInd"; -#if RSDEBUG -//DEBUGLOG << "Population::outPopHeaders(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() -// << " totalPop()=" << totalPop() -// << " nStages=" << nStages << " nSexes=" << nSexes -// << endl; -#endif -if (dem.stageStruct) { - if (dem.repType == 0) - { - for (int i = 1; i < sstruct.nStages; i++) outPop << "\tNInd_stage" << i ; - outPop << "\tNJuvs"; + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_Pop.txt"; } else { - for (int i = 1; i < sstruct.nStages; i++) - outPop << "\tNfemales_stage" << i << "\tNmales_stage" << i ; - outPop << "\tNJuvFemales\tNJuvMales"; + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Pop.txt"; } -} -else { - if (dem.repType != 0) outPop << "\tNfemales\tNmales"; -} -outPop << endl; + outPop.open(name.c_str()); + outPop << "Rep\tYear\tRepSeason"; + if (patchModel) outPop << "\tPatchID\tNcells"; + else outPop << "\tx\ty"; + // determine whether environmental data need be written for populations + bool writeEnv = false; + if (grad.gradient) writeEnv = true; + if (paramsStoch->envStoch()) writeEnv = true; + if (writeEnv) outPop << "\tEpsilon\tGradient\tLocal_K"; + outPop << "\tSpecies\tNInd"; + if (dem.stageStruct) { + if (dem.repType == 0) + { + for (int i = 1; i < sstruct.nStages; i++) outPop << "\tNInd_stage" << i; + outPop << "\tNJuvs"; + } + else { + for (int i = 1; i < sstruct.nStages; i++) + outPop << "\tNfemales_stage" << i << "\tNmales_stage" << i; + outPop << "\tNJuvFemales\tNJuvMales"; + } + } + else { + if (dem.repType != 0) outPop << "\tNfemales\tNmales"; + } + outPop << endl; -return outPop.is_open(); + return outPop.is_open(); } //--------------------------------------------------------------------------- // Write record to population file -void Population::outPopulation(int rep,int yr,int gen,float eps, - bool patchModel,bool writeEnv,bool gradK) +void Population::outPopulation(int rep, int yr, int gen, float eps, + bool patchModel, bool writeEnv, bool gradK) { -Cell *pCell; - -#if RSDEBUG -//DEBUGLOG << "Population::outPopulations(): this=" << this -// << " writeEnv " << (int)writeEnv -// << endl; -#endif - + Cell* pCell; // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -popStats p; - -outPop << rep << "\t" << yr << "\t" << gen; -if (patchModel) { - outPop << "\t" << pPatch->getPatchNum(); - outPop << "\t" << pPatch->getNCells(); -} -else { - locn loc = pPatch->getCellLocn(0); - outPop << "\t" << loc.x << "\t" << loc.y; -} -if (writeEnv) { - if (pPatch->getPatchNum() == 0) { // matrix - outPop << "\t0\t0\t0"; + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + popStats p; + + outPop << rep << "\t" << yr << "\t" << gen; + if (patchModel) { + outPop << "\t" << pPatch->getPatchNum(); + outPop << "\t" << pPatch->getNCells(); } else { - float k = pPatch->getK(); - float envval = 0.0; - pCell = pPatch->getRandomCell(); - if (pCell != 0) envval = pCell->getEnvVal(); - outPop << "\t" << eps << "\t" << envval << "\t" << k; + locn loc = pPatch->getCellLocn(0); + outPop << "\t" << loc.x << "\t" << loc.y; } -} -#if RSDEBUG -//DEBUGLOG << "Population::outPopulation(): this=" << this -// << " patchNum=" << pPatch->getPatchNum() -// << " totalPop()=" << totalPop() -// << " nStages=" << nStages << " nSexes=" << nSexes -// << endl; -#endif -outPop << "\t" << pSpecies->getSpNum(); -if (dem.stageStruct) { - p = getStats(); - outPop << "\t" << p.nNonJuvs; - // non-juvenile stage totals from permanent array - for (int stg = 1; stg < nStages; stg++) { - for (int sex = 0; sex < nSexes; sex++) { - outPop << "\t" << nInds[stg][sex]; + if (writeEnv) { + if (pPatch->getPatchNum() == 0) { // matrix + outPop << "\t0\t0\t0"; + } + else { + float k = pPatch->getK(); + float envval = 0.0; + pCell = pPatch->getRandomCell(); + if (pCell != 0) envval = pCell->getEnvVal(); + outPop << "\t" << eps << "\t" << envval << "\t" << k; } } - // juveniles from permanent array - for (int sex = 0; sex < nSexes; sex++) { - outPop << "\t" << nInds[0][sex]; - } -} -else { // non-structured population - outPop << "\t" << totalPop(); - if (dem.repType != 0) - { // sexual model - outPop << "\t" << nInds[1][0] << "\t" << nInds[1][1]; - } -} -outPop << endl; - -/* -#if RS_ABC -obsdata obs; -if (abcYear) { - int nobs = (int)pABCmaster->NObs(); - for (int i = 0; i < nobs; i++) { - obs = pABCmaster->getObsData(i); -#if RSDEBUG -//DEBUGLOG << "Population::outPopulation(): this=" << this << " i=" << i << " yr=" << yr -// << " obs.year=" << obs.year << " obs.type=" << obs.type << " obs.name=" << obs.name -// << " obs.x=" << obs.x << " obs.y=" << obs.y -// << endl; -#endif - if (obs.year == yr && obs.type == 2) { - if (obs.name == "NInds" || obs.name == "Occupied") { - bool match = false; - if (patchModel) { - if (obs.x == pPatch->getPatchNum()) { - match = true; -#if RSDEBUG -//DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" -// << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" << obs.x -// << " pPatch->PatchNum()=" << pPatch->getPatchNum() -// << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs -// << endl; -#endif - } - } - else { - locn loc = pPatch->getCentroid(); - if (obs.x == loc.x && obs.y == loc.y) { - match = true; -#if RSDEBUG -DEBUGLOG << "Population::outPopulation(): i=" << i << " PROCESS Population NInds" - << " obs.id=" << obs.id << " obs.value=" << obs.value << " obs.x=" - << obs.x << " obs.y=" << obs.y << " loc.x=" << loc.x << " loc.y=" << loc.y - << " totalPop()=" << totalPop() << " p.nNonJuvs=" << p.nNonJuvs - << endl; -#endif - } - } - if (match) { - if (obs.name == "NInds") { - if (dem.stageStruct) - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.nNonJuvs,obs.weight); - else - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,totalPop(),obs.weight); - } - else { // obs.name == "Occupied" - pABCmaster->AddNewPred(sim.simulation,obs.id,rep,obs.value,p.breeding,obs.weight); - } - } + outPop << "\t" << pSpecies->getSpNum(); + if (dem.stageStruct) { + p = getStats(); + outPop << "\t" << p.nNonJuvs; + // non-juvenile stage totals from permanent array + for (int stg = 1; stg < nStages; stg++) { + for (int sex = 0; sex < nSexes; sex++) { + outPop << "\t" << nInds[stg][sex]; } } + // juveniles from permanent array + for (int sex = 0; sex < nSexes; sex++) { + outPop << "\t" << nInds[0][sex]; + } } -} -#endif // ABC -*/ + else { // non-structured population + outPop << "\t" << totalPop(); + if (dem.repType != 0) + { // sexual model + outPop << "\t" << nInds[1][0] << "\t" << nInds[1][1]; + } + } + outPop << endl; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Open individuals file and write header record -void Population::outIndsHeaders(int rep,int landNr,bool patchModel) +void Population::outIndsHeaders(int rep, int landNr, bool patchModel) { -if (landNr == -999) { // close file - if (outInds.is_open()) { - outInds.close(); outInds.clear(); + if (landNr == -999) { // close file + if (outInds.is_open()) { + outInds.close(); outInds.clear(); + } + return; } - return; -} -string name; -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -simParams sim = paramsSim->getSim(); - -if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Inds.txt"; -} -else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep) +"_Inds.txt"; -} -outInds.open(name.c_str()); - -outInds << "Rep\tYear\tRepSeason\tSpecies\tIndID\tStatus"; -if (patchModel) outInds << "\tNatal_patch\tPatchID"; -else outInds << "\tNatal_X\tNatal_Y\tX\tY"; -if (dem.repType != 0) outInds << "\tSex"; -if (dem.stageStruct) outInds << "\tAge\tStage"; -if (emig.indVar) { - if (emig.densDep) outInds << "\tD0\tAlpha\tBeta"; - else outInds << "\tEP"; -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { // SMS - outInds << "\tDP\tGB\tAlphaDB\tBetaDB"; + string name; + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + simParams sim = paramsSim->getSim(); + + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Inds.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + + "_Rep" + Int2Str(rep) + "_Inds.txt"; + } + outInds.open(name.c_str()); + + outInds << "Rep\tYear\tRepSeason\tSpecies\tIndID\tStatus"; + if (patchModel) outInds << "\tNatal_patch\tPatchID"; + else outInds << "\tNatal_X\tNatal_Y\tX\tY"; + if (dem.repType != 0) outInds << "\tSex"; + if (dem.stageStruct) outInds << "\tAge\tStage"; + if (emig.indVar) { + if (emig.densDep) outInds << "\tD0\tAlpha\tBeta"; + else outInds << "\tEP"; + } + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { // SMS + outInds << "\tDP\tGB\tAlphaDB\tBetaDB"; + } + if (trfr.moveType == 2) { // CRW + outInds << "\tStepLength\tRho"; + } } - if (trfr.moveType == 2) { // CRW - outInds << "\tStepLength\tRho"; + else { // kernel + outInds << "\tMeanDistI"; + if (trfr.twinKern) outInds << "\tMeanDistII\tPKernelI"; } } - else { // kernel - outInds << "\tMeanDistI"; - if (trfr.twinKern) outInds << "\tMeanDistII\tPKernelI"; + if (sett.indVar) { + outInds << "\tS0\tAlphaS\tBetaS"; } -} -if (sett.indVar) { - outInds << "\tS0\tAlphaS\tBetaS"; -} -outInds << "\tDistMoved"; + outInds << "\tDistMoved"; #if RSDEBUG -// ALWAYS WRITE NO. OF STEPS -outInds << "\tNsteps"; + // ALWAYS WRITE NO. OF STEPS + outInds << "\tNsteps"; #else -if (trfr.moveModel) outInds << "\tNsteps"; + if (trfr.moveModel) outInds << "\tNsteps"; #endif -outInds << endl; + outInds << endl; } //--------------------------------------------------------------------------- // Write records to individuals file -void Population::outIndividual(Landscape *pLandscape,int rep,int yr,int gen, +void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, int patchNum) { -//int x, y, p_id; -bool writeInd; -pathSteps steps; -Cell *pCell; - -landParams ppLand = pLandscape->getLandParams(); -//landOrigin lim = pLandscape->getOrigin(); -demogrParams dem = pSpecies->getDemogr(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -short spNum = pSpecies->getSpNum(); - -int ninds = (int)inds.size(); - -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); - if (yr == -1) { // write all initialised individuals - writeInd = true; - outInds << rep << "\t" << yr << "\t" << dem.repSeasons-1; - } - else { - if (dem.stageStruct && gen < 0) { // write status 9 individuals only - if (ind.status == 9) { - writeInd = true; - outInds << rep << "\t" << yr << "\t" << dem.repSeasons-1; - } - else writeInd = false; - } - else { + //int x, y, p_id; + bool writeInd; + pathSteps steps; + Cell* pCell; + + landParams ppLand = pLandscape->getLandParams(); + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + short spNum = pSpecies->getSpNum(); + + int ninds = (int)inds.size(); + + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); + if (yr == -1) { // write all initialised individuals writeInd = true; - outInds << rep << "\t" << yr << "\t" << gen; - } - } - if (writeInd) { - outInds << "\t" << spNum << "\t" << inds[i]->getId(); - if (dem.stageStruct) outInds << "\t" << ind.status; - else { // non-structured population - outInds << "\t" << ind.status; + outInds << rep << "\t" << yr << "\t" << dem.repSeasons - 1; } - pCell = inds[i]->getLocn(1); - locn loc; - if (pCell == 0) loc.x = loc.y = -1; // beyond boundary or in no-data cell - else loc = pCell->getLocn(); - pCell = inds[i]->getLocn(0); - locn natalloc = pCell->getLocn(); -//#if SEASONAL -// pCell = inds[i]->getLocn(2); -// locn prevloc = pCell->getLocn(); -//#endif - if (ppLand.patchModel) { - outInds << "\t" << inds[i]->getNatalPatch()->getPatchNum(); - if (loc.x == -1) outInds << "\t-1"; - else outInds << "\t" << patchNum; - } - else { // cell-based model - // EITHER write co-ordinates in cell units ... - outInds << "\t" << (float)natalloc.x << "\t" << natalloc.y; - outInds << "\t" << (float)loc.x << "\t" << (float)loc.y ; - // ... OR write co-ordinates in real-world units -// outInds << "\t" << (float)natalloc.x * (float)ppLand.resol + (float)lim.minEast -// << "\t" << natalloc.y * (float)ppLand.resol + (float)lim.minNorth; -// outInds << "\t" << (float)loc.x * (float)ppLand.resol + (float)lim.minEast -// << "\t" << (float)loc.y * (float)ppLand.resol + (float)lim.minNorth; - } - if (dem.repType != 0) outInds <<"\t" << ind.sex; - if (dem.stageStruct) outInds <<"\t" << ind.age <<"\t"<< ind.stage; - - if (emig.indVar) { - emigTraits e = inds[i]->getEmigTraits(); - if (emig.densDep) { - outInds << "\t" << e.d0 << "\t" << e.alpha << "\t" << e.beta; + else { + if (dem.stageStruct && gen < 0) { // write status 9 individuals only + if (ind.status == 9) { + writeInd = true; + outInds << rep << "\t" << yr << "\t" << dem.repSeasons - 1; + } + else writeInd = false; } else { - outInds << "\t" << e.d0; + writeInd = true; + outInds << rep << "\t" << yr << "\t" << gen; } - } // end of if (emig.indVar) - - if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { // SMS - trfrSMSTraits s = inds[i]->getSMSTraits(); - outInds << "\t" << s.dp << "\t" << s.gb; - outInds << "\t" << s.alphaDB << "\t" << s.betaDB; - } // end of SMS - if (trfr.moveType == 2) { // CRW - trfrCRWTraits c = inds[i]->getCRWTraits(); - outInds << "\t" << c.stepLength << "\t" << c.rho; -#if RSDEBUG -//DEBUGLOG << "Population::outIndividual():" -// << " patchNum=" << patchNum << " i=" << i << " ID=" << inds[i]->getId() -// << " nTrfrGenes=" << nTrfrGenes << " loc[0][0].allele[0]=" << loc[0][0].allele[0] -// << endl; -#endif - } // end of CRW + } + if (writeInd) { + outInds << "\t" << spNum << "\t" << inds[i]->getId(); + if (dem.stageStruct) outInds << "\t" << ind.status; + else { // non-structured population + outInds << "\t" << ind.status; } - else { // kernel - trfrKernTraits k = inds[i]->getKernTraits(); - if (trfr.twinKern) - { - outInds << "\t" << k.meanDist1 << "\t" << k.meanDist2 << "\t" << k.probKern1; + pCell = inds[i]->getLocn(1); + locn loc; + if (pCell == 0) loc.x = loc.y = -1; // beyond boundary or in no-data cell + else loc = pCell->getLocn(); + pCell = inds[i]->getLocn(0); + locn natalloc = pCell->getLocn(); + if (ppLand.patchModel) { + outInds << "\t" << inds[i]->getNatalPatch()->getPatchNum(); + if (loc.x == -1) outInds << "\t-1"; + else outInds << "\t" << patchNum; + } + else { // cell-based model + outInds << "\t" << (float)natalloc.x << "\t" << natalloc.y; + outInds << "\t" << (float)loc.x << "\t" << (float)loc.y; + } + if (dem.repType != 0) outInds << "\t" << ind.sex; + if (dem.stageStruct) outInds << "\t" << ind.age << "\t" << ind.stage; + + if (emig.indVar) { + emigTraits e = inds[i]->getEmigTraits(); + if (emig.densDep) { + outInds << "\t" << e.d0 << "\t" << e.alpha << "\t" << e.beta; } else { - outInds << "\t" << k.meanDist1; + outInds << "\t" << e.d0; + } + } // end of if (emig.indVar) + + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { // SMS + trfrSMSTraits s = inds[i]->getSMSTraits(); + outInds << "\t" << s.dp << "\t" << s.gb; + outInds << "\t" << s.alphaDB << "\t" << s.betaDB; + } // end of SMS + if (trfr.moveType == 2) { // CRW + trfrCRWTraits c = inds[i]->getCRWTraits(); + outInds << "\t" << c.stepLength << "\t" << c.rho; + } // end of CRW + } + else { // kernel + trfrKernTraits k = inds[i]->getKernTraits(); + if (trfr.twinKern) + { + outInds << "\t" << k.meanDist1 << "\t" << k.meanDist2 << "\t" << k.probKern1; + } + else { + outInds << "\t" << k.meanDist1; + } } } - } - if (sett.indVar) { - settleTraits s = inds[i]->getSettTraits(); - outInds << "\t" << s.s0 << "\t" << s.alpha << "\t" << s.beta; - } + if (sett.indVar) { + settleTraits s = inds[i]->getSettTraits(); + outInds << "\t" << s.s0 << "\t" << s.alpha << "\t" << s.beta; + } - // distance moved (metres) - if (loc.x == -1) outInds << "\t-1"; - else { - float d = ppLand.resol * sqrt((float)((natalloc.x-loc.x)*(natalloc.x-loc.x) - + (natalloc.y-loc.y)*(natalloc.y-loc.y))); - outInds << "\t" << d; - } + // distance moved (metres) + if (loc.x == -1) outInds << "\t-1"; + else { + float d = ppLand.resol * sqrt((float)((natalloc.x - loc.x) * (natalloc.x - loc.x) + + (natalloc.y - loc.y) * (natalloc.y - loc.y))); + outInds << "\t" << d; + } #if RSDEBUG - // ALWAYS WRITE NO. OF STEPS - steps = inds[i]->getSteps(); - outInds << "\t" << steps.year; -#else - if (trfr.moveModel) { + // ALWAYS WRITE NO. OF STEPS steps = inds[i]->getSteps(); outInds << "\t" << steps.year; - } +#else + if (trfr.moveModel) { + steps = inds[i]->getSteps(); + outInds << "\t" << steps.year; + } #endif - outInds << endl; - } // end of writeInd condition - -} + outInds << endl; + } // end of writeInd condition + } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Write records to genetics file -void Population::outGenetics(const int rep,const int year,const int landNr) +void Population::outGenetics(const int rep, const int year, const int landNr) { -simParams sim = paramsSim->getSim(); + simParams sim = paramsSim->getSim(); -if (landNr >= 0) { // open file - Genome *pGenome; - genomeData gen = pSpecies->getGenomeData(); - if (gen.trait1Chromosome) { - pGenome = new Genome(pSpecies->getNChromosomes(),pSpecies->getNLoci(0), - pSpecies->isDiploid()); - } - else { - pGenome = new Genome(pSpecies); + if (landNr >= 0) { // open file + Genome* pGenome; + genomeData gen = pSpecies->getGenomeData(); + if (gen.trait1Chromosome) { + pGenome = new Genome(pSpecies->getNChromosomes(), pSpecies->getNLoci(0), + pSpecies->isDiploid()); + } + else { + pGenome = new Genome(pSpecies); + } + pGenome->outGenHeaders(rep, landNr, sim.outGenXtab); + delete pGenome; + return; } - pGenome->outGenHeaders(rep,landNr,sim.outGenXtab); - delete pGenome; - return; -} -if (landNr == -999) { // close file - Genome *pGenome = new Genome(); - pGenome->outGenHeaders(rep,landNr,sim.outGenXtab); - delete pGenome; - return; -} - -short spNum = pSpecies->getSpNum(); -short nstages = 1; -if (pSpecies->stageStructured()) { - stageParams sstruct = pSpecies->getStage(); - nstages = sstruct.nStages; -} + if (landNr == -999) { // close file + Genome* pGenome = new Genome(); + pGenome->outGenHeaders(rep, landNr, sim.outGenXtab); + delete pGenome; + return; + } + short spNum = pSpecies->getSpNum(); + short nstages = 1; + if (pSpecies->stageStructured()) { + stageParams sstruct = pSpecies->getStage(); + nstages = sstruct.nStages; + } -int ninds = (int)inds.size(); -for (int i = 0; i < ninds; i++) { - indStats ind = inds[i]->getStats(); - if (year == 0 || sim.outGenType == 1 - || (sim.outGenType == 0 && ind.stage == 0) - || (sim.outGenType == 2 && ind.stage == nstages-1)) { - inds[i]->outGenetics(rep,year,spNum,landNr,sim.outGenXtab); + int ninds = (int)inds.size(); + for (int i = 0; i < ninds; i++) { + indStats ind = inds[i]->getStats(); + if (year == 0 || sim.outGenType == 1 + || (sim.outGenType == 0 && ind.stage == 0) + || (sim.outGenType == 2 && ind.stage == nstages - 1)) { + inds[i]->outGenetics(rep, year, spNum, landNr, sim.outGenXtab); + } } -} } diff --git a/Population.h b/Population.h index 9c8efd8..fd1fa66 100644 --- a/Population.h +++ b/Population.h @@ -50,9 +50,6 @@ Last updated: 22 January 2022 by Steve Palmer #include #include -//#include -//#include -//#include using namespace std; #include "Parameters.h" diff --git a/RSrandom.cpp b/RSrandom.cpp index 79744c9..1b9f523 100644 --- a/RSrandom.cpp +++ b/RSrandom.cpp @@ -26,7 +26,6 @@ #if !RS_RCPP - #if RSDEBUG #include "Parameters.h" extern paramSim* paramsSim; @@ -94,6 +93,8 @@ int RSrandom::IRandom(int min, int max) int RSrandom::Bernoulli(double p) { + if (p < 0) throw runtime_error("Bernoulli's p cannot be negative.\n"); + if (p > 1) throw runtime_error("Bernoulli's p cannot be above 1.\n"); return Random() < p; } @@ -190,6 +191,8 @@ int RSrandom::Poisson(double mean) } int RSrandom::Bernoulli(double p) { + if (p < 0) throw runtime_error("Bernoulli's p cannot be negative.\n"); + if (p > 1) throw runtime_error("Bernoulli's p cannot be above 1.\n"); return Random() < p; } @@ -253,4 +256,28 @@ int RSrandom::Poisson(double mean) #endif // RS_RCPP + +#if RSDEBUG + void testRSrandom() { + + { + // Bernoulli distribution + // Abuse cases + assert_error("Bernoulli's p cannot be negative.\n", []{ + RSrandom rsr; + rsr.Bernoulli(-0.3); + }); + assert_error("Bernoulli's p cannot be above 1.\n", [] { + RSrandom rsr; + rsr.Bernoulli(1.1); + }); + // Use cases + RSrandom rsr; + assert(rsr.Bernoulli(0) == 0); + assert(rsr.Bernoulli(1) == 1); + int bern_trial = rsr.Bernoulli(0.5); + assert(bern_trial == 0 || bern_trial == 1); + } + } +#endif // RSDEBUG //--------------------------------------------------------------------------- diff --git a/RSrandom.h b/RSrandom.h index 98d91f4..0e61c19 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -38,7 +38,8 @@ Last updated: 12 January 2021 by Steve Palmer #include #include -//#include +#include +#include "Utils.h" #if RS_RCPP #include "../Version.h" @@ -131,6 +132,9 @@ extern ofstream DEBUGLOG; #endif // !RS_RCPP +#if RSDEBUG + void testRSrandom(); +#endif // RSDEBUG //--------------------------------------------------------------------------- diff --git a/Utils.cpp b/Utils.cpp new file mode 100644 index 0000000..049bc9e --- /dev/null +++ b/Utils.cpp @@ -0,0 +1,9 @@ +#include "Utils.h" + +// Evaluate a lambda and assert we get the correct error +void assert_error(const string& exptd_err_msg, void (*lambda)(void)) { + string err_msg{ "No error.\n" }; + try { lambda(); } // evaluate + catch (exception& e) { err_msg = e.what(); } + assert(err_msg == exptd_err_msg); +} \ No newline at end of file diff --git a/Utils.h b/Utils.h new file mode 100644 index 0000000..948a8c2 --- /dev/null +++ b/Utils.h @@ -0,0 +1,12 @@ +#ifndef UtilsH +#define UtilsH + +#include +#include +#include +using namespace std; + +// Evaluate a lambda and assert we get the correct error +void assert_error(const string& exptd_err_msg, void (*x)(void)); + +#endif // UtilsH From 3e654d899b3157fdb934d3b9dc77f034dcdcffac Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 23 Nov 2023 16:14:53 +0000 Subject: [PATCH 14/46] functional main --- CMakeLists.txt | 16 ++++++++++++-- Main.cpp | 57 +++++++++++++++++++++++++++++++++++++++----------- Utils.cpp | 17 +++++++++++++++ Utils.h | 6 ++++++ 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56c5971..dda2692 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,17 @@ +cmake_minimum_required(VERSION 3.10) + +# set the project name and version +project(RScore VERSION 2.1.0) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) + # Config file for compilation with CMake # Only relevant for Batch mode, but this file needs to live in the RScore folder -add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) +add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) +#add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) # pass config definitions to compiler target_compile_definitions(RScore PRIVATE RSWIN64) @@ -14,4 +24,6 @@ endif() # Debug Mode by default, unless "release" is passed if(NOT DEFINED release) add_compile_definitions(RSDEBUG) -endif() \ No newline at end of file +endif() + +target_include_directories(RScore PUBLIC "${PROJECT_BINARY_DIR}") diff --git a/Main.cpp b/Main.cpp index 74b036f..0f6ae48 100644 --- a/Main.cpp +++ b/Main.cpp @@ -19,11 +19,6 @@ * --------------------------------------------------------------------------*/ -#include -#include -#include - -using namespace std; #if LINUX_CLUSTER || R_CMD #include @@ -31,12 +26,20 @@ using namespace std; #include #endif -void assert_error(const string& exptd_err_msg, void (*x)(void)) { - string err_msg{ "No error.\n" }; - try { x(); } - catch (exception& e) { err_msg = e.what(); } - assert(err_msg == exptd_err_msg); -} +#include +#include +#include +#include +#include "Individual.h" +#include "Community.h" +#include "RSrandom.h" +#include "Utils.h" +#include "Parameters.h" +#include "Landscape.h" +#include "Species.h" +#include "SubCommunity.h" + +using namespace std; void run_unit_tests() { cout << "******* Unit test output *******" << endl; @@ -45,6 +48,36 @@ void run_unit_tests() { cout << endl << "************************" << endl; } +// Global vars +string habmapname, patchmapname, distnmapname; +string costmapname, genfilename; +string landFile; +paramGrad* paramsGrad; +paramStoch* paramsStoch; +paramInit* paramsInit; +paramSim* paramsSim; +RSrandom* pRandom; +ofstream DEBUGLOG; +ofstream MUTNLOG; +vector hfnames; +Species* pSpecies; +Community* pComm; +void DebugGUI(string msg) { + // nothing +} +void MemoLine(string msg) { + /// nothing +} +traitCanvas SetupTraitCanvas(void) { + traitCanvas tcanv; + for (int i = 0; i < NTRAITS; i++) { tcanv.pcanvas[i] = 0; } + return tcanv; +} +void Landscape::setLandMap(void) { } +void Landscape::drawLandscape(int rep, int yr, int landnum) { } +void Community::viewOccSuit(int year, double mn, double se) { } +void Community::draw(int rep, int yr, int gen, int landNum) { } + #if LINUX_CLUSTER || RS_RCPP int main(int argc, char* argv[]) #else @@ -60,4 +93,4 @@ int _tmain(int argc, _TCHAR* argv[]) cout << "All tests have completed." << endl; return 0; // if tests succeed, we are happy # endif // NDEBUG -} \ No newline at end of file +} diff --git a/Utils.cpp b/Utils.cpp index 049bc9e..9d36b92 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -1,5 +1,22 @@ #include "Utils.h" +const string Int2Str(const int x) +{ + ostringstream o; + if (!(o << x)) return "ERROR"; + return o.str(); +} +const string Float2Str(const float x) { + ostringstream o; + if (!(o << x)) return "ERROR"; + return o.str(); +} +const string Double2Str(const double x) { + ostringstream o; + if (!(o << x)) return "ERROR"; + return o.str(); +} + // Evaluate a lambda and assert we get the correct error void assert_error(const string& exptd_err_msg, void (*lambda)(void)) { string err_msg{ "No error.\n" }; diff --git a/Utils.h b/Utils.h index 948a8c2..34854a7 100644 --- a/Utils.h +++ b/Utils.h @@ -3,9 +3,15 @@ #include #include +#include + #include using namespace std; +const string Int2Str(const int x); +const string Float2Str(const float x); +const string Double2Str(const double x); + // Evaluate a lambda and assert we get the correct error void assert_error(const string& exptd_err_msg, void (*x)(void)); From 313402294f41d1f68a23f3f3c5b27698fa55631d Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 23 Nov 2023 17:09:45 +0000 Subject: [PATCH 15/46] compile RScore as standalone with CMake, fix #16 --- CMakeLists.txt | 27 ++++++++++++++------------- Main.cpp | 1 - 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dda2692..c14a3e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,16 @@ -cmake_minimum_required(VERSION 3.10) - -# set the project name and version -project(RScore VERSION 2.1.0) - -# specify the C++ standard -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED True) - # Config file for compilation with CMake -# Only relevant for Batch mode, but this file needs to live in the RScore folder -add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) -#add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) +if (NOT batchmode) # that is, RScore as a standalone + cmake_minimum_required(VERSION 3.10) + # set the project name and version + project(RScore VERSION 2.1.0) + # specify the C++ standard + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED True) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) +else() # that is, RScore compiled as library within RangeShifter_batch + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp Genome.cpp Individual.cpp Landscape.cpp Model.cpp Parameters.cpp Patch.cpp Population.cpp RandomCheck.cpp RSrandom.cpp SubCommunity.cpp Utils.cpp) +endif() # pass config definitions to compiler target_compile_definitions(RScore PRIVATE RSWIN64) @@ -26,4 +25,6 @@ if(NOT DEFINED release) add_compile_definitions(RSDEBUG) endif() -target_include_directories(RScore PUBLIC "${PROJECT_BINARY_DIR}") +if(NOT batchmode) + target_include_directories(RScore PUBLIC "${PROJECT_BINARY_DIR}") +endif() \ No newline at end of file diff --git a/Main.cpp b/Main.cpp index 0f6ae48..42f783b 100644 --- a/Main.cpp +++ b/Main.cpp @@ -19,7 +19,6 @@ * --------------------------------------------------------------------------*/ - #if LINUX_CLUSTER || R_CMD #include #else From 14177eebe01c6aa9e921752d95e57f76c623db12 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Thu, 23 Nov 2023 17:10:16 +0000 Subject: [PATCH 16/46] go github action --- .github/workflows/check.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/check.yml diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..2e86587 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,26 @@ +name: check +on: push + +jobs: + check: + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + include: + - os: windows-latest + path_to_exe: ./build/Debug/RScore.exe + - os: ubuntu-latest + path_to_exe: ./build/RScore + - os: macos-latest + path_to_exe: ./build/RScore + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + + - name: build + run: | + mkdir build && cd build + cmake ../ && cmake --build . + + - name: run + run: ${{ matrix.path_to_exe }} From 2b566bb6f6efe9c28c1d5e6a7558d8abcb74afb2 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 28 Nov 2023 15:05:51 +0000 Subject: [PATCH 17/46] rm commented out code and fix indentation in Genome --- Genome.cpp | 958 +++++++++++++++-------------------------------------- Genome.h | 110 +----- 2 files changed, 274 insertions(+), 794 deletions(-) diff --git a/Genome.cpp b/Genome.cpp index 90d030b..59a68b1 100644 --- a/Genome.cpp +++ b/Genome.cpp @@ -1,26 +1,23 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- #include "Genome.h" //--------------------------------------------------------------------------- @@ -29,242 +26,125 @@ ofstream outGenetic; //--------------------------------------------------------------------------- -#ifdef RSDEBUG -//std::ofstream chromdebug("chromdebug.txt"); -//std::ofstream chromdebug1("chromdebug1.txt"); -#endif - -//--------------------------------------------------------------------------- - Chromosome::Chromosome(int nloc) { -#if RSDEBUG -//DEBUGLOG << "Chromosome::Chromosome(): this=" << this -// << " nloc=" << nloc -//// << " maternalLoci.size()=" << maternalLoci.size() -//// << " paternalLoci.size()=" << paternalLoci.size() -// << endl; -//DebugGUI("Chromosome::Chromosome(): this=" + Int2Str((int)this) -// + " nloc=" + Int2Str(nloc) -//// + " maternalLoci.size()=" + Int2Str((int)maternalLoci.size()) -//// + " paternalLoci.size()=" + Int2Str((int)paternalLoci.size()) -// ); -#endif -if (nloc > 0) nloci = nloc; else nloci = 1; -pLoci = new locus[nloci]; -for (int i = 0; i < nloci; i++) { - pLoci[i].allele[0] = pLoci[i].allele[1] = 0; -} + if (nloc > 0) nloci = nloc; else nloci = 1; + pLoci = new locus[nloci]; + for (int i = 0; i < nloci; i++) { + pLoci[i].allele[0] = pLoci[i].allele[1] = 0; + } } Chromosome::~Chromosome() { -#if RSDEBUG -//DEBUGLOG << "Chromosome::~Chromosome(): this=" << this << endl; -#endif -#if RSDEBUG -//DEBUGLOG << "Chromosome::Chromosome(): deleting this=" << this << endl; -//DebugGUI("Chromosome::Chromosome(): deleting this=" + Int2Str((int)this)); -#endif -if (pLoci != 0) { -// for (int i = 0; i < nloci; i++) { -// delete pLoci[i]; pLoci[i] = NULL; -// } - delete[] pLoci; pLoci = NULL; -} + if (pLoci != 0) { + delete[] pLoci; pLoci = NULL; + } } short Chromosome::nLoci(void) { return nloci; } locus Chromosome::alleles(const int loc) { // return allele values at a specified locus -locus l; l.allele[0] = l.allele[1] = 0; -if (loc >= 0 && loc < nloci) { - l.allele[0] = pLoci[loc].allele[0]; l.allele[1] = pLoci[loc].allele[1]; -} -return l; + locus l; l.allele[0] = l.allele[1] = 0; + if (loc >= 0 && loc < nloci) { + l.allele[0] = pLoci[loc].allele[0]; l.allele[1] = pLoci[loc].allele[1]; + } + return l; } double Chromosome::additive(const bool diploid) { -int sum = 0; -for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; -} -#if RSDEBUG -//DEBUGLOG << "Chromosome::additive(): this=" << this -// << " sum=" << sum -// << endl; -#endif -return (double)sum / INTBASE; + int sum = 0; + for (int i = 0; i < nloci; i++) { + sum += pLoci[i].allele[0]; + if (diploid) sum += pLoci[i].allele[1]; + } + return (double)sum / INTBASE; } double Chromosome::meanvalue(const bool diploid) { -int sum = 0; -double mean; -for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; -} -mean = (double)sum / (double)nloci; -if (diploid) mean /= 2.0; -mean /= INTBASE; -#if RSDEBUG -//DEBUGLOG << "Chromosome::meanvalue(): this=" << this -// << " sum=" << sum -// << " mean=" << mean -// << endl; -#endif -return mean; + int sum = 0; + double mean; + for (int i = 0; i < nloci; i++) { + sum += pLoci[i].allele[0]; + if (diploid) sum += pLoci[i].allele[1]; + } + mean = (double)sum / (double)nloci; + if (diploid) mean /= 2.0; + mean /= INTBASE; + return mean; } -double Chromosome::additive(const short loc,const bool diploid) { -int sum = 0; -sum += pLoci[loc].allele[0]; -if (diploid) sum += pLoci[loc].allele[1]; -#if RSDEBUG -//DEBUGLOG << "Chromosome::additive(): this=" << this -// << " sum=" << sum -// << endl; -#endif -return (double)sum / INTBASE; +double Chromosome::additive(const short loc, const bool diploid) { + int sum = 0; + sum += pLoci[loc].allele[0]; + if (diploid) sum += pLoci[loc].allele[1]; + return (double)sum / INTBASE; } -/* -double Chromosome::probval(const bool diploid) { -double genval,phenval; -int sum = 0; -for (int i = 0; i < nloci; i++) { - sum += pLoci[i].allele[0]; - if (diploid) sum += pLoci[i].allele[1]; -} -genval = (double)sum / INTBASE; -phenval = 1.0 / (1.0 + exp(-genval)); -#if RSDEBUG -//DEBUGLOG << "Chromosome::probval(): this=" << this -// << " sum=" << sum -// << " genval=" << genval -// << " phenval=" << phenval -// << endl; -#endif -return phenval; -} -*/ - // Set up chromosome at simulation initialisation -//void Chromosome::initialise(const float mean,const float sd, -// const bool diploid) { -void Chromosome::initialise(const double mean, const double sd, - const bool diploid) { -double avalue; -double intbase = INTBASE; -//// adjust mean and s.d. allowing for number of alleles determining phenotype -//double adjmean,adjsd,factor; -//if (diploid) factor = (double)(nloci * 2); else factor = (double)(nloci); -//adjmean = mean / factor; -//adjsd = sqrt(sd * sd / factor); -for (int i = 0; i < nloci; i++) { -// avalue = pRandom->Normal(adjmean,adjsd); - avalue = pRandom->Normal(mean,sd); - if (avalue > 0.0) - pLoci[i].allele[0] = (int)(avalue * intbase + 0.5); - else - pLoci[i].allele[0] = (int)(avalue * intbase - 0.5); -#if RSDEBUG -//DEBUGLOG << "Chromosome::initialise(): this=" << this -// << " mean=" << mean << " sd=" << sd -// << " i=" << i << " avalue=" << avalue -// << " allele[0]=" << pLoci[i].allele[0]; -//DEBUGLOG << endl; -#endif - if (diploid) { -// avalue = pRandom->Normal(adjmean,adjsd); - avalue = pRandom->Normal(mean,sd); +void Chromosome::initialise(const double mean, const double sd, + const bool diploid) { + double avalue; + double intbase = INTBASE; + + for (int i = 0; i < nloci; i++) { + avalue = pRandom->Normal(mean, sd); if (avalue > 0.0) - pLoci[i].allele[1] = (int)(avalue * intbase + 0.5); + pLoci[i].allele[0] = (int)(avalue * intbase + 0.5); else - pLoci[i].allele[1] = (int)(avalue * intbase - 0.5); -#if RSDEBUG -//DEBUGLOG << "Chromosome::initialise(): this=" << this -// << " mean=" << mean << " sd=" << sd -// << " i=" << i << " avalue=" << avalue -// << " allele[1]=" << pLoci[i].allele[1]; -//DEBUGLOG << endl; -#endif + pLoci[i].allele[0] = (int)(avalue * intbase - 0.5); + if (diploid) { + avalue = pRandom->Normal(mean, sd); + if (avalue > 0.0) + pLoci[i].allele[1] = (int)(avalue * intbase + 0.5); + else + pLoci[i].allele[1] = (int)(avalue * intbase - 0.5); + } } -} } // Set up specified locus at simulation initialisation -void Chromosome::initialise(const short locus,const short posn,const int aval) +void Chromosome::initialise(const short locus, const short posn, const int aval) { -// note that initialising value is ADDED to current value to allow for pleiotropy -pLoci[locus].allele[posn] += aval; + // note that initialising value is ADDED to current value to allow for pleiotropy + pLoci[locus].allele[posn] += aval; } // Inherit from specified parent -void Chromosome::inherit(const Chromosome *parentChr,const short posn,const short nloc, - const double probmutn,const double probcross,const double mutnSD,const bool diploid) +void Chromosome::inherit(const Chromosome* parentChr, const short posn, const short nloc, + const double probmutn, const double probcross, const double mutnSD, const bool diploid) { - -// NOTE: At present for diploid genome, presence of crossover is determined at each -// locus (except first). However, Roslyn has shown that it is more efficient to sample -// crossover locations from geometric distribution if number of loci is large. -// HOW LARGE IS 'LARGE' IN THIS CASE?... - -//// adjust mutation variance for number of loci -//double mutnsd; -//if (diploid) -// mutnsd = sqrt(mutnSD * mutnSD / (double)(2*nloc)); -//else -// mutnsd = sqrt(mutnSD * mutnSD / (double)nloc); -int ix = 0; // indexes maternal and paternal strands -if (diploid) ix = pRandom->Bernoulli(0.5); // start index at random -for (int i = 0; i < nloc; i++) { - if (diploid) { - pLoci[i].allele[posn] = parentChr->pLoci[i].allele[ix]; - if (pRandom->Bernoulli(probcross)) { // crossover occurs - if (ix == 0) ix = 1; else ix = 0; + // NOTE: At present for diploid genome, presence of crossover is determined at each + // locus (except first). However, Roslyn has shown that it is more efficient to sample + // crossover locations from geometric distribution if number of loci is large. + // HOW LARGE IS 'LARGE' IN THIS CASE?... + + int ix = 0; // indexes maternal and paternal strands + if (diploid) ix = pRandom->Bernoulli(0.5); // start index at random + for (int i = 0; i < nloc; i++) { + if (diploid) { + pLoci[i].allele[posn] = parentChr->pLoci[i].allele[ix]; + if (pRandom->Bernoulli(probcross)) { // crossover occurs + if (ix == 0) ix = 1; else ix = 0; + } } - } - else - pLoci[i].allele[posn] = parentChr->pLoci[i].allele[0]; -#if RSDEBUG -//DEBUGLOG << "Chromosome::inherit(): this=" << this -// << " posn=" << posn << " nloc=" << nloc << " pmutn=" << pmutn -// << " i=" << i << " allele=" << pLoci[i].allele[posn] -// << endl; -#endif - if (pRandom->Bernoulli(probmutn)) { // mutation occurs - double intbase = INTBASE; -#if RSDEBUG - int oldval = pLoci[i].allele[posn]; -#endif -// double mutnvalue = pRandom->Normal(0,mutnsd); - double mutnvalue = pRandom->Normal(0,mutnSD); - if (mutnvalue > 0.0) - pLoci[i].allele[posn] += (int)(intbase * mutnvalue + 0.5); else - pLoci[i].allele[posn] += (int)(intbase * mutnvalue - 0.5); + pLoci[i].allele[posn] = parentChr->pLoci[i].allele[0]; + if (pRandom->Bernoulli(probmutn)) { // mutation occurs + double intbase = INTBASE; #if RSDEBUG -//DEBUGLOG << "Chromosome::inherit(): this=" << this -// << " probmutn=" << probmutn << " nloc=" << nloc -//// << " mutnsd=" << mutnsd -// << " mutnSD=" << mutnSD -// << " posn=" << posn << " locus=" << i << " MUTATED " -// << " old=" << oldval << " new=" << pLoci[i].allele[posn] -// << endl; + int oldval = pLoci[i].allele[posn]; #endif + double mutnvalue = pRandom->Normal(0, mutnSD); + if (mutnvalue > 0.0) + pLoci[i].allele[posn] += (int)(intbase * mutnvalue + 0.5); + else + pLoci[i].allele[posn] += (int)(intbase * mutnvalue - 0.5); #if RSDEBUG -//MUTNLOG << 1 << endl; -MUTNLOG << mutnvalue << " " << oldval << " " << pLoci[i].allele[posn] << " " << endl; + MUTNLOG << mutnvalue << " " << oldval << " " << pLoci[i].allele[posn] << " " << endl; #endif + } } -#if RSDEBUG -// else { -//MUTNLOG << 0 << endl; -// } -#endif -} } @@ -273,92 +153,68 @@ MUTNLOG << mutnvalue << " " << oldval << " " << pLoci[i].allele[posn] << " " << // NB THIS FUNCTION IS CURRENTLY NOT BEING CALLED TO CONSTRUCT AN INSTANCE OF Genome // Genome(int) IS USED INSTEAD -Genome::Genome(){ -pChromosome = NULL; -nChromosomes = 0; +Genome::Genome() { + pChromosome = NULL; + nChromosomes = 0; } // Set up new genome at initialisation for 1 chromosome per trait -Genome::Genome(int nchromosomes,int nloci,bool d) { -#if RSDEBUG -//DEBUGLOG << "Genome::Genome(): this=" << this -// << " nchromosomes=" << nchromosomes << " nLoci=" << nLoci -// << endl; -#endif +Genome::Genome(int nchromosomes, int nloci, bool d) { -diploid = d; -if (nchromosomes > 0) nChromosomes = nchromosomes; else nChromosomes = 1; -pChromosome = new Chromosome *[nChromosomes]; -for (int i = 0; i < nChromosomes; i++) { - pChromosome[i] = new Chromosome(nloci); -// pChromosome[i]->initialise(alleleMean,alleleSD); -} + diploid = d; + if (nchromosomes > 0) nChromosomes = nchromosomes; else nChromosomes = 1; + pChromosome = new Chromosome * [nChromosomes]; + for (int i = 0; i < nChromosomes; i++) { + pChromosome[i] = new Chromosome(nloci); + } } // Set up new genome at initialisation for trait mapping -Genome::Genome(Species *pSpecies) { -int nloci; -nChromosomes = pSpecies->getNChromosomes(); -diploid = pSpecies->isDiploid(); -#if RSDEBUG -//DEBUGLOG << "Genome::Genome(): this=" << this -// << " nChromosomes=" << nChromosomes -// << endl; -#endif -pChromosome = new Chromosome *[nChromosomes]; -for (int i = 0; i < nChromosomes; i++) { - nloci = pSpecies->getNLoci(i); -#if RSDEBUG -//DEBUGLOG << "Genome::Genome(): this=" << this -// << " i=" << i << " nloci=" << nloci << endl; -#endif - pChromosome[i] = new Chromosome(nloci); -} +Genome::Genome(Species* pSpecies) { + int nloci; + nChromosomes = pSpecies->getNChromosomes(); + diploid = pSpecies->isDiploid(); + pChromosome = new Chromosome * [nChromosomes]; + for (int i = 0; i < nChromosomes; i++) { + nloci = pSpecies->getNLoci(i); + pChromosome[i] = new Chromosome(nloci); + } } // Inherit genome from parent(s) -Genome::Genome(Species *pSpecies,Genome *mother,Genome *father) +Genome::Genome(Species* pSpecies, Genome* mother, Genome* father) { -genomeData gen = pSpecies->getGenomeData(); - -nChromosomes = mother->nChromosomes; -diploid = mother->diploid; -pChromosome = new Chromosome *[nChromosomes]; - -for (int i = 0; i < nChromosomes; i++) { - pChromosome[i] = new Chromosome(mother->pChromosome[i]->nLoci()); - inherit(mother,0,i,gen.probMutn,gen.probCrossover,gen.mutationSD); - if (diploid) { - if (father == 0) { // species is hermaphrodite - inherit again from mother - inherit(mother,1,i,gen.probMutn,gen.probCrossover,gen.mutationSD); + genomeData gen = pSpecies->getGenomeData(); + + nChromosomes = mother->nChromosomes; + diploid = mother->diploid; + pChromosome = new Chromosome * [nChromosomes]; + + for (int i = 0; i < nChromosomes; i++) { + pChromosome[i] = new Chromosome(mother->pChromosome[i]->nLoci()); + inherit(mother, 0, i, gen.probMutn, gen.probCrossover, gen.mutationSD); + if (diploid) { + if (father == 0) { // species is hermaphrodite - inherit again from mother + inherit(mother, 1, i, gen.probMutn, gen.probCrossover, gen.mutationSD); + } + else inherit(father, 1, i, gen.probMutn, gen.probCrossover, gen.mutationSD); } - else inherit(father,1,i,gen.probMutn,gen.probCrossover,gen.mutationSD); } -} } -Genome::~Genome(){ +Genome::~Genome() { -if (pChromosome == NULL) return; + if (pChromosome == NULL) return; -for (int i = 0; i < nChromosomes; i++) { - delete pChromosome[i]; -} -delete[] pChromosome; + for (int i = 0; i < nChromosomes; i++) { + delete pChromosome[i]; + } + delete[] pChromosome; } -/* -Genome::~Genome(void) -{ -if (genome != 0) { - delete genome; genome = NULL; -} -} -*/ - //--------------------------------------------------------------------------- void Genome::setDiploid(bool dip) { diploid = dip; } @@ -368,493 +224,195 @@ short Genome::getNChromosomes(void) { return nChromosomes; } //--------------------------------------------------------------------------- // Inherit from specified parent -void Genome::inherit(const Genome *parent,const short posn,const short chr, - const double probmutn,const double probcross,const double mutnSD) +void Genome::inherit(const Genome* parent, const short posn, const short chr, + const double probmutn, const double probcross, const double mutnSD) { -// adjust mutation variance for number of loci -//double mutnSD = sqrt(mutationSD * mutationSD / (double)nLoci); -//for (int i = 0; i < nChromosomes; i++) { -// pChromosome[i]->inherit(parent->pChromosome[i],pChromosome[i]->nLoci()); -//} -pChromosome[chr]->inherit(parent->pChromosome[chr],posn,parent->pChromosome[chr]->nLoci(), - probmutn,probcross,mutnSD,diploid); + pChromosome[chr]->inherit(parent->pChromosome[chr], posn, parent->pChromosome[chr]->nLoci(), + probmutn, probcross, mutnSD, diploid); } -void Genome::outGenHeaders(const int rep,const int landNr,const bool xtab) +void Genome::outGenHeaders(const int rep, const int landNr, const bool xtab) { -if (landNr == -999) { // close file - if (outGenetic.is_open()) { - outGenetic.close(); outGenetic.clear(); + if (landNr == -999) { // close file + if (outGenetic.is_open()) { + outGenetic.close(); outGenetic.clear(); + } + return; } - return; -} - -string name; -simParams sim = paramsSim->getSim(); -if (sim.batchMode) { - name = paramsSim->getDir(2) - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Genetics.txt"; -} -else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep) +"_Genetics.txt"; -} -outGenetic.open(name.c_str()); + string name; + simParams sim = paramsSim->getSim(); -outGenetic << "Rep\tYear\tSpecies\tIndID"; -if (xtab) { - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - outGenetic << "\tChr" << i << "Loc" << j << "Allele0"; - if (diploid) outGenetic << "\tChr" << i << "Loc" << j << "Allele1"; + if (sim.batchMode) { + name = paramsSim->getDir(2) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + "_Genetics.txt"; + } + else { + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + + "_Rep" + Int2Str(rep) + "_Genetics.txt"; + } + outGenetic.open(name.c_str()); + + outGenetic << "Rep\tYear\tSpecies\tIndID"; + if (xtab) { + for (int i = 0; i < nChromosomes; i++) { + int nloci = pChromosome[i]->nLoci(); + for (int j = 0; j < nloci; j++) { + outGenetic << "\tChr" << i << "Loc" << j << "Allele0"; + if (diploid) outGenetic << "\tChr" << i << "Loc" << j << "Allele1"; + } } + outGenetic << endl; + } + else { + outGenetic << "\tChromosome\tLocus\tAllele0"; + if (diploid) outGenetic << "\tAllele1"; + outGenetic << endl; } - outGenetic << endl; -} -else { - outGenetic << "\tChromosome\tLocus\tAllele0"; - if (diploid) outGenetic << "\tAllele1"; - outGenetic << endl; -} } -void Genome::outGenetics(const int rep,const int year,const int spnum, - const int indID,const bool xtab) - { -locus l; -if (xtab) { - outGenetic << rep << "\t" << year << "\t" << spnum << "\t" << indID; - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - l = pChromosome[i]->alleles(j); - outGenetic << "\t" << l.allele[0]; - if (diploid) outGenetic << "\t" << l.allele[1]; +void Genome::outGenetics(const int rep, const int year, const int spnum, + const int indID, const bool xtab) +{ + locus l; + if (xtab) { + outGenetic << rep << "\t" << year << "\t" << spnum << "\t" << indID; + for (int i = 0; i < nChromosomes; i++) { + int nloci = pChromosome[i]->nLoci(); + for (int j = 0; j < nloci; j++) { + l = pChromosome[i]->alleles(j); + outGenetic << "\t" << l.allele[0]; + if (diploid) outGenetic << "\t" << l.allele[1]; + } } + outGenetic << endl; } - outGenetic << endl; -} -else { - for (int i = 0; i < nChromosomes; i++) { - int nloci = pChromosome[i]->nLoci(); - for (int j = 0; j < nloci; j++) { - outGenetic << rep << "\t" << year << "\t" << spnum << "\t" - << indID << "\t" << i << "\t" << j; - l = pChromosome[i]->alleles(j); - outGenetic << "\t" << l.allele[0]; - if (diploid) outGenetic << "\t" << l.allele[1]; - outGenetic << endl; + else { + for (int i = 0; i < nChromosomes; i++) { + int nloci = pChromosome[i]->nLoci(); + for (int j = 0; j < nloci; j++) { + outGenetic << rep << "\t" << year << "\t" << spnum << "\t" + << indID << "\t" << i << "\t" << j; + l = pChromosome[i]->alleles(j); + outGenetic << "\t" << l.allele[0]; + if (diploid) outGenetic << "\t" << l.allele[1]; + outGenetic << endl; + } } } } -} //--------------------------------------------------------------------------- // Set up new gene at initialisation for 1 chromosome per trait -//void Genome::setGene(const short chr,const short exp, -// const float traitval,const float alleleSD) void Genome::setGene(const short chr, const short exp, - const double traitval, const double alleleSD) -// NB PARAMETER exp FOR EXPRESSION TYPE IS NOT CURRENTLY USED... + const double traitval, const double alleleSD) + // NB PARAMETER exp FOR EXPRESSION TYPE IS NOT CURRENTLY USED... { -#if RSDEBUG -//DEBUGLOG << "Genome::setGene(): this=" << this -// << " chr=" << chr -// << " exp=" << exp << " traitval=" << traitval -// << " alleleSD=" << alleleSD -// << endl; -#endif -if (chr >= 0 && chr < nChromosomes) { - pChromosome[chr]->initialise(traitval,alleleSD,diploid); -} + if (chr >= 0 && chr < nChromosomes) { + pChromosome[chr]->initialise(traitval, alleleSD, diploid); + } } // Set up trait at initialisation for trait mapping -//void Genome::setTrait(Species *pSpecies,const int trait, -// const float traitval,const float alleleSD) void Genome::setTrait(Species* pSpecies, const int trait, - const double traitval, const double alleleSD) + const double traitval, const double alleleSD) { -traitAllele allele; -int nalleles = pSpecies->getNTraitAlleles(trait); -int ntraitmaps = pSpecies->getNTraitMaps(); -#if RSDEBUG -//DEBUGLOG << "Genome::setTrait(): this=" << this << " ntraitmaps=" << ntraitmaps -// << " trait=" << trait << " traitval=" << traitval << " alleleSD=" << alleleSD -// << " nalleles=" << nalleles -// << endl; -#endif - -int avalue; -double intbase = INTBASE; -if (trait < ntraitmaps) { -// // adjust mean and s.d. allowing for number of alleles determining phenotype -// double adjmean,adjsd,factor; -// if (diploid) factor = (double)(nalleles * 2); else factor = (double)(nalleles); -// adjmean = traitval / factor; -// adjsd = sqrt(alleleSD * alleleSD / factor); - - for (int i = 0; i < nalleles; i++) { - allele = pSpecies->getTraitAllele(trait,i); -// avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); - avalue = (int)(pRandom->Normal(traitval,alleleSD) * intbase); -#if RSDEBUG -//DEBUGLOG << "Genome::setTrait(): this=" << this -// << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus -// << " posn=" << 0 << " avalue=" << avalue -// << endl; -#endif - pChromosome[allele.chromo]->initialise(allele.locus,0,avalue); - if (diploid) { -// avalue = (int)(pRandom->Normal(adjmean,adjsd) * intbase); - avalue = (int)(pRandom->Normal(traitval,alleleSD) * intbase); - pChromosome[allele.chromo]->initialise(allele.locus,1,avalue); + traitAllele allele; + int nalleles = pSpecies->getNTraitAlleles(trait); + int ntraitmaps = pSpecies->getNTraitMaps(); + + int avalue; + double intbase = INTBASE; + if (trait < ntraitmaps) { + for (int i = 0; i < nalleles; i++) { + allele = pSpecies->getTraitAllele(trait, i); + avalue = (int)(pRandom->Normal(traitval, alleleSD) * intbase); + pChromosome[allele.chromo]->initialise(allele.locus, 0, avalue); + if (diploid) { + avalue = (int)(pRandom->Normal(traitval, alleleSD) * intbase); + pChromosome[allele.chromo]->initialise(allele.locus, 1, avalue); + } } } -} -else { // insufficient traits were defined - // alleles cannot be initialised - all individuals have mean phenotype -#if RSDEBUG -//DEBUGLOG << "Genome::setTrait(): this=" << this -// << " *** unable to initialise undefined trait ***" << endl; -#endif -} + else { // insufficient traits were defined + // alleles cannot be initialised - all individuals have mean phenotype + } } // Set up trait at initialisation for trait mapping -void Genome::setNeutralLoci(Species *pSpecies,const double alleleSD) +void Genome::setNeutralLoci(Species* pSpecies, const double alleleSD) { -traitAllele allele; -int nneutral = pSpecies->getNNeutralLoci(); -#if RSDEBUG -//DEBUGLOG << "Genome::setNeutralLoci(): this=" << this -// << " nneutral=" << nneutral << " alleleSD=" << alleleSD -// << endl; -#endif - -//int avalue; -double avalue; -double intbase = INTBASE; -//// adjust allele s.d. for diploid genotype -//double adjsd,factor; -//if (diploid) factor = 2.0; else factor = 1.0; -//adjsd = sqrt(alleleSD * alleleSD / factor); - -for (int i = 0; i < nneutral; i++) { - allele = pSpecies->getNeutralAllele(i); -// avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); -// pChromosome[allele.chromo]->initialise(allele.locus,0,avalue); - avalue = pRandom->Normal(0.0,alleleSD); - if (avalue > 0.0) - pChromosome[allele.chromo]->initialise(allele.locus,0,(int)(avalue * intbase + 0.5)); - else - pChromosome[allele.chromo]->initialise(allele.locus,0,(int)(avalue * intbase - 0.5)); -#if RSDEBUG -//DEBUGLOG << "Genome::setNeutralLoci(): this=" << this -// << " i=" << i << " chromo=" << allele.chromo << " locus=" << allele.locus -// << " avalue=" << avalue -// << endl; -#endif - if (diploid) { -// avalue = (int)(pRandom->Normal(0.0,adjsd) * intbase); -// pChromosome[allele.chromo]->initialise(allele.locus,1,avalue); - avalue = pRandom->Normal(0.0,alleleSD); + traitAllele allele; + int nneutral = pSpecies->getNNeutralLoci(); + + double avalue; + double intbase = INTBASE; + for (int i = 0; i < nneutral; i++) { + allele = pSpecies->getNeutralAllele(i); + avalue = pRandom->Normal(0.0, alleleSD); if (avalue > 0.0) - pChromosome[allele.chromo]->initialise(allele.locus,1,(int)(avalue * intbase + 0.5)); + pChromosome[allele.chromo]->initialise(allele.locus, 0, (int)(avalue * intbase + 0.5)); else - pChromosome[allele.chromo]->initialise(allele.locus,1,(int)(avalue * intbase - 0.5)); + pChromosome[allele.chromo]->initialise(allele.locus, 0, (int)(avalue * intbase - 0.5)); + if (diploid) { + avalue = pRandom->Normal(0.0, alleleSD); + if (avalue > 0.0) + pChromosome[allele.chromo]->initialise(allele.locus, 1, (int)(avalue * intbase + 0.5)); + else + pChromosome[allele.chromo]->initialise(allele.locus, 1, (int)(avalue * intbase - 0.5)); + } } } -} - -// Return a single allele, having applied mutation -// Either allele is returned with equal probability, unless the gene is sex-linked, -// in which case a male returns the allele inherited from his father and a female -// returns the allele inherited from her mother -/* -double Genome::copy(int i,int sexx) -{ -double genevalue = 0.0; -return genevalue; -} -*/ // Return the expressed value of a gene when species has one chromosome per trait -double Genome::express(short chr,short expr,short indsex) +double Genome::express(short chr, short expr, short indsex) { -double genevalue = 0.0; -//if (expr == 1) { -// genevalue = pChromosome[chr]->probval(diploid); -//} -//else -//genevalue = pChromosome[chr]->additive(diploid); -genevalue = pChromosome[chr]->meanvalue(diploid); -#if RSDEBUG -//DEBUGLOG << "Genome::express(): this=" << this -// << " chr=" << chr -// << " genevalue=" << genevalue -// << endl; -#endif -return genevalue; -} -/* -// Return the expressed value of an allele -double Genome::express(short chr,short loc) -{ -double genevalue = 0.0; -//if (expr == 1) { -// genevalue = pChromosome[chr]->probval(diploid); -//} -//else -genevalue = pChromosome[chr]->additive(loc,diploid); -#if RSDEBUG -//DEBUGLOG << "Genome::express(): this=" << this -// << " expr=" << expr -// << " genevalue=" << genevalue -// << endl; -#endif -return genevalue; + double genevalue = 0.0; + genevalue = pChromosome[chr]->meanvalue(diploid); + return genevalue; } -*/ // Return the expressed value of a trait when genetic architecture is defined -double Genome::express(Species *pSpecies,short traitnum) +double Genome::express(Species* pSpecies, short traitnum) { -double genevalue = 0.0; - -traitAllele allele; -int nalleles = pSpecies->getNTraitAlleles(traitnum); -if (nalleles > 0) { - for (int i = 0; i < nalleles; i++) { - allele = pSpecies->getTraitAllele(traitnum,i); - genevalue += pChromosome[allele.chromo]->additive(allele.locus,diploid); - } - genevalue /= (double)nalleles; - if (diploid) genevalue /= 2.0; -} - -// genevalue = pChromosome[chr]->additive(diploid); -#if RSDEBUG -//DEBUGLOG << "Genome::express(): this=" << this -// << " traitnum=" << traitnum << " nalleles=" << nalleles -// << " genevalue=" << genevalue -// << endl; -#endif -return genevalue; -} - - -locusOK Genome::getAlleles(short chr,short loc) { -locusOK l; -l.allele[0] = l.allele[1] = 0; l.ok = false; -//double intbase = INTBASE; -if (chr >= 0 && chr < nChromosomes) { - if (pChromosome[chr] != 0) { - if (loc >= 0 && loc < pChromosome[chr]->nLoci()) { - locus a = pChromosome[chr]->alleles(loc); - l.allele[0] = a.allele[0]; l.allele[1] = a.allele[1]; l.ok = true; + double genevalue = 0.0; + + traitAllele allele; + int nalleles = pSpecies->getNTraitAlleles(traitnum); + if (nalleles > 0) { + for (int i = 0; i < nalleles; i++) { + allele = pSpecies->getTraitAllele(traitnum, i); + genevalue += pChromosome[allele.chromo]->additive(allele.locus, diploid); } + genevalue /= (double)nalleles; + if (diploid) genevalue /= 2.0; } + return genevalue; } -// l.allele[0] = (int)(intbase * pChromosome[0]->additive(diploid)); -return l; -} -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - -// OLD CODE WHICH MIGHT BE USEFUL FOR IMPLEMENTING ALTERNATIVE FORMS OF EXPRESSION - -/* - -// Set up new genome at initialisation -Genome::Genome(int g) { -if (g < 1) return; - -genomesize = g; -genome = new gene *[genomesize]; -for (int i = 0; i < genomesize; i++) { - genome[i] = new gene; - genome[i]->expression = 0; genome[i]->mutntype = 0; - genome[i]->Pmutn = 0.0; genome[i]->mutnSize = 0.0; - genome[i]->allele[0] = genome[i]->allele[1] = 0.0; -} - -} - -// Inherit genome from parent(s) -Genome::Genome(Genome *mother,Genome *father) -{ -#if RSDEBUG -//locn currloc = currCell->getLocn(); -//DEBUGLOG << "Genome::setGenes(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -// << " pSpecies=" << pSpecies -// << " mother=" << mother -// << " father=" << father -// << endl; -#endif - -genomesize = mother->genomesize; -genome = new gene *[genomesize]; -for (int i = 0; i < genomesize; i++) { - genome[i] = new gene; - genome[i]->expression = mother->genome[i]->expression; - genome[i]->mutntype = mother->genome[i]->mutntype; - genome[i]->Pmutn = mother->genome[i]->Pmutn; - genome[i]->mutnSize = mother->genome[i]->mutnSize; - genome[i]->allele[0] = mother->copy(i,0); - if (father == 0) genome[i]->allele[1] = 0.0; - else genome[i]->allele[1] = father->copy(i,1); -} - -} - -Genome::~Genome(void) -{ -if (genome != 0) { - for (int i = 0; i < genomesize; i++) { - delete genome[i]; genome[i] = NULL; - } - delete genome; genome = NULL; -} - -} - -// Set up new gene -void Genome::setGene(int i,short exp,short mtype,float pmut,float msize,double a0,double a1) -{ -if (exp >= 0 && exp <= 4) genome[i]->expression = exp; -if (mtype >= 0 && mtype <= 5) genome[i]->mutntype = mtype; -if (pmut >= 0.0 && pmut <= 1.0) genome[i]->Pmutn = pmut; -if (msize > 0.0) genome[i]->mutnSize = msize; -genome[i]->allele[0] = a0; -genome[i]->allele[1] = a1; -} - -// Return a single allele, having applied mutation -// Either allele is returned with equal probability, unless the gene is sex-linked, -// in which case a male returns the allele inherited from his father and a female -// returns the allele inherited from her mother -double Genome::copy(int i,int sexx) -{ -double genevalue,logP,logitP; - -switch (genome[i]->expression) { -case 0: // haploid - genevalue = genome[i]->allele[0]; - break; -case 1: // sex-linked gene - if (sexx == 0 || sexx == 1) genevalue = genome[i]->allele[sexx]; - else return -999999.999; // indicates error in sex of parent animal - break; -default: // otherwise - select one of the alleles at random - genevalue = genome[i]->allele[pRandom->Bernoulli(0.5)]; - ; -} -#if RSDEBUG -//DEBUGLOG << "Gene::copy(): expression=" << expression -// << " mutntype=" << mutntype -// << " Pmutn=" << Pmutn << " mutnSize=" << mutnSize -// << " allele[0]=" << allele[0] << " allele[1]=" << allele[1] -// << " genevalue=" << genevalue -// << endl; -#endif -// apply mutation to the gene -if (pRandom->Random() < genome[i]->Pmutn) { - switch (genome[i]->mutntype) { - case 0: genevalue = pRandom->Random(); break; - case 1: genevalue += pRandom->Normal(0.0,genome[i]->mutnSize); break; - case 2: - logitP = log(genevalue/(1.0-genevalue)); - logitP += pRandom->Normal(0.0,genome[i]->mutnSize); - genevalue = 1.0 / (1 + exp(-logitP)); - if (genevalue >= 1.0) genevalue = 0.999999999; - if (genevalue <= 0.0) genevalue = 0.000000001; - break; - case 3: - logP = log(genevalue); - logP += pRandom->Normal(0.0,genome[i]->mutnSize); - genevalue = exp(logP); - break; - case 4: - genevalue += pRandom->Random()*(2.0*genome[i]->mutnSize) - genome[i]->mutnSize; - break; - case 5: - genevalue += pRandom->Random()*(2.0*genome[i]->mutnSize) - genome[i]->mutnSize; - if (genevalue > 1.0) genevalue = 1.0; - if (genevalue < 0.0) genevalue = 0.0; - break; - default: genevalue = -888888.888; // error in mutation type +locusOK Genome::getAlleles(short chr, short loc) { + locusOK l; + l.allele[0] = l.allele[1] = 0; l.ok = false; + if (chr >= 0 && chr < nChromosomes) { + if (pChromosome[chr] != 0) { + if (loc >= 0 && loc < pChromosome[chr]->nLoci()) { + locus a = pChromosome[chr]->alleles(loc); + l.allele[0] = a.allele[0]; l.allele[1] = a.allele[1]; l.ok = true; + } + } } -} -#if RSDEBUG -//DEBUGLOG << "Gene::copy():" -// << " allele[0]=" << allele[0] << " allele[1]=" << allele[1] -// << " genevalue=" << genevalue -// << endl; -#endif -return genevalue; -} - -// Return the expressed value of a gene -double Genome::express(int i,int sexx) -{ -double genevalue; - -switch (genome[i]->expression) { - case 0: // sex-linked gene - genevalue = genome[i]->allele[0]; - break; - case 1: // sex-linked gene - if (sexx == 0 || sexx == 1) genevalue = genome[i]->allele[sexx]; - else genevalue = -999999.999; // indicates error in sex of parent animal - break; - case 2: // dominance of greater value - genevalue = genome[i]->allele[0]; - if (genome[i]->allele[1] > genevalue) genevalue = genome[i]->allele[1]; - break; - case 3: // co-dominance (mean value) - genevalue = (genome[i]->allele[0] + genome[i]->allele[1]) / 2.0; - break; - case 4: // sex-expressed co-dominance -// NB does not differ from co-dominance other than when genes interact to determine -// phenotypic level of expression - genevalue = (genome[i]->allele[0] + genome[i]->allele[1]) / 2.0; -// if (sexx == 0 || sexx == 1) genevalue = genome[i]->allele[sexx]; -// else genevalue = -999999.999; // indicates error in sex of parent animal - break; -default: genevalue = -777777.777; // error in expression type -} - -return genevalue; + return l; } -locus Genome::getAlleles(int g) { -locus l; -if (g >= 0 && g < genomesize) { - l.allele[0] = genome[g]->allele[0]; - l.allele[1] = genome[g]->allele[1]; -} -else { - l.allele[0] = l.allele[1] = 0.0; -} -return l; -} - -*/ - //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/Genome.h b/Genome.h index d42c161..4f01ede 100644 --- a/Genome.h +++ b/Genome.h @@ -1,43 +1,29 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ - -RangeShifter v2.0 Genome - -Implements the Genome class - -Author: Steve Palmer & Roslyn Henry, University of Aberdeen - -Last updated: 28 July 2021 by Greta Bocedi - -------------------------------------------------------------------------------*/ #ifndef GenomeH #define GenomeH #include #include -//#include "maths.h" #include "Parameters.h" #include "Species.h" @@ -65,7 +51,6 @@ class Chromosome { const short, // locus const bool // diploid ); -// double probval(const bool); locus alleles( // Return allele values at a specified locus const int // position of locus on chromosome ); @@ -93,25 +78,19 @@ class Chromosome { private: short nloci; - locus *pLoci; + locus* pLoci; }; //--------------------------------------------------------------------------- -class Genome{ +class Genome { public: -// -// static float delPMutation, delEffectSize, delDominance, delBackMutation ,genomeMeanRecombination; -// static int delMaxSize, delNMutations; -// static bool genomeCanRecombine, genomeCompletelyUnlinked; -// - Genome(); - Genome(int,int,bool); + Genome(int, int, bool); Genome(Species*); - Genome(Species*,Genome*,Genome*); + Genome(Species*, Genome*, Genome*); ~Genome(); void setGene( // Set up new gene at initialisation for 1 chromosome per trait const short, // chromosome number @@ -129,22 +108,16 @@ class Genome{ Species*, // pointer to Species const double // s.d. of allelic variance ); -// double copy(int,int); double express( - // Return the expressed value of a gene when species has one chromosome per trait + // Return the expressed value of a gene when species has one chromosome per trait short, // chromosome number short, // expression type (NOT CURRENTLY USED) short // individual's sex (NOT CURRENTLY USED) ); -// double express( -// short, // chromosome number -// short // locus on chromosome -// ); double express( - // Return the expressed value of a trait when genetic architecture is defined + // Return the expressed value of a trait when genetic architecture is defined Species*, // pointer to Species short // trait number -// bool // true if trait is sex-dependent ); locusOK getAlleles( // Get allele values at a specified locus short, // chromosome number @@ -161,8 +134,6 @@ class Genome{ const double, // crossover probability const double // s.d. of mutation magnitude (genetic scale) ); -// void setStaticData(genomeData); -// genomeData getStaticData(void); short getNChromosomes(void); void outGenHeaders( const int, // replicate @@ -181,64 +152,15 @@ class Genome{ private: short nChromosomes; // no. of chromosomes bool diploid; - Chromosome **pChromosome; - -}; - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- + Chromosome** pChromosome; -/* - -struct gene { - short expression; // used to control how gene is expressed: - // 0 = haploid - // 1 = sex-linked - // 2 = dominance of greater value - // 3 = co-dominance (mean value) - // 4 = sex-expressed (but not sex-linked) - short mutntype; // mutation type: - // 0 = random in [0,1] - // 1 = normal - // 2 = logit scale - // 3 = log-normal (gene must be positive) - // 4 = RS method - random in specified range - // 5 = RS method - random in specified range and constrained to [0,1] - float Pmutn; // mutation probability - float mutnSize; // mutation size (s.d. of normal distribution) - double allele[2]; // allele pair: [0] from mother, [1] from father }; -; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -class Genome -{ -public: - Genome(int); - Genome(Genome*,Genome*); - ~Genome(void); - void setGene(int); - void setGene(int,short,short,float,float,double,double); // new gene - double copy(int,int); - double express(int,int); - locus getAlleles( // Get allele values at a specified locus - int // locus position within genome - ); - -private: - int genomesize; - gene **genome; - -}; - -*/ - -//--------------------------------------------------------------------------- - -extern paramSim *paramsSim; -extern RSrandom *pRandom; +extern paramSim* paramsSim; +extern RSrandom* pRandom; #if RSDEBUG extern ofstream DEBUGLOG; From 5a25d947dbdd9c803709feaa58b41aead2cf4719 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 28 Nov 2023 15:38:45 +0000 Subject: [PATCH 18/46] rm commented out code, fix indentation from Landscape --- Landscape.cpp | 3669 ++++++++++++++++++++++--------------------------- Landscape.h | 5 - 2 files changed, 1665 insertions(+), 2009 deletions(-) diff --git a/Landscape.cpp b/Landscape.cpp index be63ae9..d1a26df 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Landscape.h" //--------------------------------------------------------------------------- @@ -37,119 +37,119 @@ ofstream outMovePaths; // Initial species distribution functions -InitDist::InitDist(Species *pSp) +InitDist::InitDist(Species* pSp) { -pSpecies = pSp; -resol = 0; -maxX = 0; -maxY = 0; -minEast = 0.0; -minNorth = 0.0; + pSpecies = pSp; + resol = 0; + maxX = 0; + maxY = 0; + minEast = 0.0; + minNorth = 0.0; } InitDist::~InitDist() { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) - if (cells[i] != NULL) delete cells[i]; -cells.clear(); + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) + if (cells[i] != NULL) delete cells[i]; + cells.clear(); } void InitDist::setDistribution(int nInit) { -int rr = 0; -int ncells = (int)cells.size(); -if (nInit == 0) { // set all cells to be initialised - for (int i = 0; i < ncells; i++) { - cells[i]->setCell(true); - } -} -else { // set specified number of cells at random to be initialised - if (nInit > ncells/2) { // use backwards selection method - for (int i = 0; i < ncells; i++) cells[i]->setCell(true); - for (int i = 0; i < (ncells-nInit); i++) { - do { - rr = pRandom->IRandom(0,ncells-1); - } while (!cells[rr]->selected()); - cells[rr]->setCell(false); + int rr = 0; + int ncells = (int)cells.size(); + if (nInit == 0) { // set all cells to be initialised + for (int i = 0; i < ncells; i++) { + cells[i]->setCell(true); } } - else { // use forwards selection method - for (int i = 0; i < ncells; i++) cells[i]->setCell(false); - for (int i = 0; i < nInit; i++) { - do { - rr = pRandom->IRandom(0,ncells-1); - } while (cells[rr]->selected()); - cells[rr]->setCell(true); + else { // set specified number of cells at random to be initialised + if (nInit > ncells / 2) { // use backwards selection method + for (int i = 0; i < ncells; i++) cells[i]->setCell(true); + for (int i = 0; i < (ncells - nInit); i++) { + do { + rr = pRandom->IRandom(0, ncells - 1); + } while (!cells[rr]->selected()); + cells[rr]->setCell(false); + } + } + else { // use forwards selection method + for (int i = 0; i < ncells; i++) cells[i]->setCell(false); + for (int i = 0; i < nInit; i++) { + do { + rr = pRandom->IRandom(0, ncells - 1); + } while (cells[rr]->selected()); + cells[rr]->setCell(true); + } } } } -} // Set a specified cell (by position in cells vector) -void InitDist::setDistCell(int ix,bool init) { -cells[ix]->setCell(init); +void InitDist::setDistCell(int ix, bool init) { + cells[ix]->setCell(init); } // Set a specified cell (by co-ordinates) -void InitDist::setDistCell(locn loc,bool init) { -locn cellloc; -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - cellloc = cells[i]->getLocn(); - if (cellloc.x == loc.x && cellloc.y == loc.y) { - cells[i]->setCell(init); - i = ncells; +void InitDist::setDistCell(locn loc, bool init) { + locn cellloc; + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + cellloc = cells[i]->getLocn(); + if (cellloc.x == loc.x && cellloc.y == loc.y) { + cells[i]->setCell(init); + i = ncells; + } } } -} // Specified location is within the initial distribution? bool InitDist::inInitialDist(locn loc) { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - if (cells[i]->toInitialise(loc)) { // cell is to be initialised - return true; + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + if (cells[i]->toInitialise(loc)) { // cell is to be initialised + return true; + } } -} -return false; + return false; } int InitDist::cellCount(void) { -return (int)cells.size(); + return (int)cells.size(); } // Return the co-ordinates of a specified initial distribution cell locn InitDist::getCell(int ix) { -locn loc; -if (ix >= 0 && ix < (int)cells.size()) { - loc = cells[ix]->getLocn(); -} -else { - loc.x = loc.y = -666; // indicates invalid index specified -} -return loc; + locn loc; + if (ix >= 0 && ix < (int)cells.size()) { + loc = cells[ix]->getLocn(); + } + else { + loc.x = loc.y = -666; // indicates invalid index specified + } + return loc; } // Return the co-ordinates of a specified initial distribution cell if it has been // selected - otherwise return negative co-ordinates locn InitDist::getSelectedCell(int ix) { -locn loc; loc.x = loc.y = -666; -if (ix < (int)cells.size()) { - if (cells[ix]->selected()) { - loc = cells[ix]->getLocn(); + locn loc; loc.x = loc.y = -666; + if (ix < (int)cells.size()) { + if (cells[ix]->selected()) { + loc = cells[ix]->getLocn(); + } } -} -return loc; + return loc; } locn InitDist::getDimensions(void) { -locn d; d.x = maxX; d.y = maxY; return d; + locn d; d.x = maxX; d.y = maxY; return d; } void InitDist::resetDistribution(void) { -int ncells = (int)cells.size(); -for (int i = 0; i < ncells; i++) { - cells[i]->setCell(false); -} + int ncells = (int)cells.size(); + for (int i = 0; i < ncells; i++) { + cells[i]->setCell(false); + } } //--------------------------------------------------------------------------- @@ -158,64 +158,60 @@ for (int i = 0; i < ncells; i++) { int InitDist::readDistribution(string distfile) { #if RS_RCPP -wstring header; + wstring header; #else -string header; + string header; #endif -int p,nodata; -int ncols,nrows; + int p, nodata; + int ncols, nrows; #if RS_RCPP -wifstream dfile; // species distribution file input stream + wifstream dfile; // species distribution file input stream #else -ifstream dfile; // species distribution file input stream + ifstream dfile; // species distribution file input stream #endif -// open distribution file + // open distribution file #if !RS_RCPP || RSWIN64 dfile.open(distfile.c_str()); #else dfile.open(distfile, std::ios::binary); - if(spdistraster.utf) { + if (spdistraster.utf) { // apply BOM-sensitive UTF-16 facet dfile.imbue(std::locale(dfile.getloc(), new std::codecvt_utf16)); } #endif -if (!dfile.is_open()) return 21; + if (!dfile.is_open()) return 21; -// read landscape data from header records of distribution file -// NB headers of all files have already been compared -dfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> resol >> header >> nodata; + // read landscape data from header records of distribution file + // NB headers of all files have already been compared + dfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth + >> header >> resol >> header >> nodata; #if RS_RCPP -if (!dfile.good()) { - // corrupt file stream - StreamErrorR(distfile); - dfile.close(); - dfile.clear(); - return 144; -} + if (!dfile.good()) { + // corrupt file stream + StreamErrorR(distfile); + dfile.close(); + dfile.clear(); + return 144; + } #endif -maxX = ncols-1; maxY = nrows-1; + maxX = ncols - 1; maxY = nrows - 1; -// set up bad integer value to ensure that valid values are read -int badvalue = -9; if (nodata == -9) badvalue = -99; + // set up bad integer value to ensure that valid values are read + int badvalue = -9; if (nodata == -9) badvalue = -99; -for (int y = nrows-1; y >= 0; y--) { - for (int x = 0; x < ncols; x++) { - p = badvalue; + for (int y = nrows - 1; y >= 0; y--) { + for (int x = 0; x < ncols; x++) { + p = badvalue; #if RS_RCPP - if(dfile >> p) { + if (dfile >> p) { #else - dfile >> p; -#endif -#if RSDEBUG -//DEBUGLOG << "InitDist::readDistribution():" -// << " y = " << y << " x = " << x << " p = " << p << endl; + dfile >> p; #endif if (p == nodata || p == 0 || p == 1) { // only valid values if (p == 1) { // species present - cells.push_back(new DistCell(x,y)); + cells.push_back(new DistCell(x, y)); } } else { // error in file @@ -223,26 +219,27 @@ for (int y = nrows-1; y >= 0; y--) { return 22; } #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(distfile); - dfile.close(); - dfile.clear(); - return 144; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif + StreamErrorR(distfile); + dfile.close(); + dfile.clear(); + return 144; + } +#endif + } } -} #if RS_RCPP - dfile >> p; - if (!dfile.eof()) EOFerrorR(distfile); +dfile >> p; +if (!dfile.eof()) EOFerrorR(distfile); #endif -dfile.close(); dfile.clear(); -return 0; + dfile.close(); dfile.clear(); + return 0; } @@ -251,268 +248,203 @@ return 0; // Landscape functions Landscape::Landscape(void) { -patchModel = false; spDist = false; generated = false; fractal = false; continuous = false; -dynamic = false; habIndexed = false; -resol = spResol = landNum = 0; -rasterType = 0; -nHab = nHabMax = 0; -dimX = dimY = 100; -minX = minY = 0; -maxX = maxY = 99; -minPct = maxPct = propSuit = hurst = 0.0; -maxCells = 100; -gpix = 1.0; -pix = (int)gpix; -minEast = minNorth = 0.0; -cells = 0; -#if RSDEBUG -// NOTE: do NOT write to output stream before it has been opened - it will be empty -//DebugGUI("Landscape::Landscape(): this = " + Int2Str((int)this) -// + " pCell = " + Int2Str((int)pCell)); -//DEBUGLOGGUI << "Landscape::Landscape(): this = " << this << " pCell = " << pCell << endl; -#endif -connectMatrix = 0; -epsGlobal = 0; -patchChgMatrix = 0; -costsChgMatrix = 0; - -#if RSDEBUG -//DEBUGLOG << "Landscape::Landscape():" -// << " rasterType= " << rasterType << endl; -#endif -#if RSDEBUG -//MemoLine(("Landscape::Landscape(): landscape created " + Int2Str(0) -// ).c_str()); -#endif + patchModel = false; spDist = false; generated = false; fractal = false; continuous = false; + dynamic = false; habIndexed = false; + resol = spResol = landNum = 0; + rasterType = 0; + nHab = nHabMax = 0; + dimX = dimY = 100; + minX = minY = 0; + maxX = maxY = 99; + minPct = maxPct = propSuit = hurst = 0.0; + maxCells = 100; + gpix = 1.0; + pix = (int)gpix; + minEast = minNorth = 0.0; + cells = 0; + connectMatrix = 0; + epsGlobal = 0; + patchChgMatrix = 0; + costsChgMatrix = 0; } Landscape::~Landscape() { -#if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): this=" + Int2Str((int)this) + " cells=" + Int2Str((int)cells) -// + " maxX=" + Int2Str(maxX) + " maxY=" + Int2Str(maxY)).c_str()); -#endif -if (cells != 0) { - for (int y = dimY-1; y >= 0; y--) { -#if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): y=" + Int2Str(y) + " cells[y]=" + Int2Str((int)cells[y])).c_str()); -#endif - for (int x = 0; x < dimX; x++) { -#if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): y=" + Int2Str(y) + " x=" + Int2Str(x) -// + " cells[y][x]=" + Int2Str((int)cells[y][x])).c_str()); -#endif - if (cells[y][x] != 0) delete cells[y][x]; - } - if (cells[y] != 0) { -#if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): deleting cells[y]=" + Int2Str((int)cells[y])).c_str()); -#endif -// delete cells[y]; - delete[] cells[y]; + if (cells != 0) { + for (int y = dimY - 1; y >= 0; y--) { + + for (int x = 0; x < dimX; x++) { + + if (cells[y][x] != 0) delete cells[y][x]; + } + if (cells[y] != 0) { + delete[] cells[y]; + } } + delete[] cells; + cells = 0; } - delete[] cells; - cells = 0; -} -#if RSDEBUG -//DebugGUI(("Landscape::~Landscape(): this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); -#endif - -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) - if (patches[i] != NULL) delete patches[i]; -patches.clear(); + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) + if (patches[i] != NULL) delete patches[i]; + patches.clear(); -int ndistns = (int)distns.size(); -for (int i = 0; i < ndistns; i++) - if (distns[i] != NULL) delete distns[i]; -distns.clear(); + int ndistns = (int)distns.size(); + for (int i = 0; i < ndistns; i++) + if (distns[i] != NULL) delete distns[i]; + distns.clear(); -int ninitcells = (int)initcells.size(); -for (int i = 0; i < ninitcells; i++) - if (initcells[i] != NULL) delete initcells[i]; -initcells.clear(); + int ninitcells = (int)initcells.size(); + for (int i = 0; i < ninitcells; i++) + if (initcells[i] != NULL) delete initcells[i]; + initcells.clear(); -patchnums.clear(); -habCodes.clear(); -colours.clear(); -landchanges.clear(); -patchchanges.clear(); + patchnums.clear(); + habCodes.clear(); + colours.clear(); + landchanges.clear(); + patchchanges.clear(); -deleteConnectMatrix(); -deletePatchChgMatrix(); -if (epsGlobal != 0) delete[] epsGlobal; + deleteConnectMatrix(); + deletePatchChgMatrix(); + if (epsGlobal != 0) delete[] epsGlobal; -#if RSDEBUG -//MemoLine(("Landscape::~Landscape(): landscape deleted " + Int2Str(1) -// ).c_str()); -#endif } // Remove all patches and cells // Used for replicating artificial landscape without deleting the landscape itself void Landscape::resetLand(void) { -#if RSDEBUG -//DebugGUI("Landscape::resetLand(): starting..."); -#endif -resetLandLimits(); -int npatches = (int)patches.size(); -#if RSDEBUG -//DebugGUI(("Landscape::resetLand(): npatches=" + Int2Str(npatches) -// ).c_str()); -#endif -for (int i = 0; i < npatches; i++) if (patches[i] != NULL) delete patches[i]; -patches.clear(); -#if RSDEBUG -//DebugGUI("Landscape::resetLand(): finished resetting patches"); -#endif + resetLandLimits(); + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) if (patches[i] != NULL) delete patches[i]; + patches.clear(); -#if RSDEBUG -//DebugGUI(("Landscape::resetLand(): this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); -#endif -if (cells != 0) { - for(int y = dimY-1; y >= 0; y--){ -#if RSDEBUG -//DebugGUI(("Landscape::resetLand(): y=" + Int2Str(y) + " cells[y]=" + Int2Str((int)cells[y])).c_str()); -#endif - for (int x = 0; x < dimX; x++) { -#if RSDEBUG -//DebugGUI(("Landscape::resetLand(): y=" + Int2Str(y) + " x=" + Int2Str(x) -// + " cells[y][x]=" + Int2Str((int)cells[y][x])).c_str()); -#endif - if (cells[y][x] != 0) delete cells[y][x]; - } - if (cells[y] != 0) { -#if RSDEBUG -//DebugGUI(("Landscape::resetLand(): deleting cells[y]=" + Int2Str((int)cells[y])).c_str()); -#endif - delete[] cells[y]; + if (cells != 0) { + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) delete cells[y][x]; + } + if (cells[y] != 0) { + delete[] cells[y]; + } } + delete[] cells; + cells = 0; } - delete[] cells; - cells = 0; -} -#if RSDEBUG -//DebugGUI(("Landscape::resetLand(): this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); -#endif } -void Landscape::setLandParams(landParams ppp,bool batchMode) +void Landscape::setLandParams(landParams ppp, bool batchMode) { -generated = ppp.generated; patchModel = ppp.patchModel; spDist = ppp.spDist; -dynamic = ppp.dynamic; -landNum = ppp.landNum; -if (ppp.resol > 0) resol = ppp.resol; -if (ppp.spResol > 0 && ppp.spResol%ppp.resol == 0) spResol = ppp.spResol; -if ((ppp.rasterType >= 0 && ppp.rasterType <= 2) || ppp.rasterType == 9) - rasterType = ppp.rasterType; -if (ppp.nHab >= 1) nHab = ppp.nHab; -if (ppp.nHabMax >= 1) nHabMax = ppp.nHabMax; -if (ppp.dimX > 0) dimX = ppp.dimX; -if (ppp.dimY > 0) dimY = ppp.dimY; -if (ppp.minX >= 0 && ppp.maxX >= 0 && ppp.minX <= ppp.maxX && ppp.maxX < dimX) { - minX = ppp.minX; maxX = ppp.maxX; -} -else { - minX = 0; maxX = dimX - 1; -} -if (ppp.minY >= 0 && ppp.maxY >= 0 && ppp.minY <= ppp.maxY && ppp.maxY < dimY) { - minY = ppp.minY; maxY = ppp.maxY; -} -else { - minY = 0; maxY = dimY - 1; -} -if (batchMode && rasterType == 0) { - // in batch mode, set up sequential habitat codes if not already present - if (habCodes.size() == 0) { - for (int i = 0; i < nHabMax; i++) { - habCodes.push_back(i+1); + generated = ppp.generated; patchModel = ppp.patchModel; spDist = ppp.spDist; + dynamic = ppp.dynamic; + landNum = ppp.landNum; + if (ppp.resol > 0) resol = ppp.resol; + if (ppp.spResol > 0 && ppp.spResol % ppp.resol == 0) spResol = ppp.spResol; + if ((ppp.rasterType >= 0 && ppp.rasterType <= 2) || ppp.rasterType == 9) + rasterType = ppp.rasterType; + if (ppp.nHab >= 1) nHab = ppp.nHab; + if (ppp.nHabMax >= 1) nHabMax = ppp.nHabMax; + if (ppp.dimX > 0) dimX = ppp.dimX; + if (ppp.dimY > 0) dimY = ppp.dimY; + if (ppp.minX >= 0 && ppp.maxX >= 0 && ppp.minX <= ppp.maxX && ppp.maxX < dimX) { + minX = ppp.minX; maxX = ppp.maxX; + } + else { + minX = 0; maxX = dimX - 1; + } + if (ppp.minY >= 0 && ppp.maxY >= 0 && ppp.minY <= ppp.maxY && ppp.maxY < dimY) { + minY = ppp.minY; maxY = ppp.maxY; + } + else { + minY = 0; maxY = dimY - 1; + } + if (batchMode && rasterType == 0) { + // in batch mode, set up sequential habitat codes if not already present + if (habCodes.size() == 0) { + for (int i = 0; i < nHabMax; i++) { + habCodes.push_back(i + 1); + } } } } -} landParams Landscape::getLandParams(void) { -landParams ppp; -ppp.generated = generated; ppp.patchModel = patchModel; ppp.spDist = spDist; -ppp.dynamic = dynamic; -ppp.landNum = landNum; -ppp.resol = resol; ppp.spResol = spResol; -ppp.rasterType = rasterType; -ppp.nHab = nHab; ppp.nHabMax = nHabMax; -ppp.dimX = dimX; ppp.dimY = dimY; -ppp.minX = minX; ppp.minY = minY; -ppp.maxX = maxX; ppp.maxY = maxY; -return ppp; + landParams ppp; + ppp.generated = generated; ppp.patchModel = patchModel; ppp.spDist = spDist; + ppp.dynamic = dynamic; + ppp.landNum = landNum; + ppp.resol = resol; ppp.spResol = spResol; + ppp.rasterType = rasterType; + ppp.nHab = nHab; ppp.nHabMax = nHabMax; + ppp.dimX = dimX; ppp.dimY = dimY; + ppp.minX = minX; ppp.minY = minY; + ppp.maxX = maxX; ppp.maxY = maxY; + return ppp; } landData Landscape::getLandData(void) { -landData dd; -dd.resol = resol; -dd.dimX = dimX; dd.dimY = dimY; -dd.minX = minX; dd.minY = minY; -dd.maxX = maxX; dd.maxY = maxY; -return dd; + landData dd; + dd.resol = resol; + dd.dimX = dimX; dd.dimY = dimY; + dd.minX = minX; dd.minY = minY; + dd.maxX = maxX; dd.maxY = maxY; + return dd; } void Landscape::setGenLandParams(genLandParams ppp) { -fractal = ppp.fractal; -continuous = ppp.continuous; -if (ppp.minPct > 0.0 && ppp.minPct < 100.0) minPct = ppp.minPct; -if (ppp.maxPct > 0.0 && ppp.maxPct <= 100.0) maxPct = ppp.maxPct; -if (ppp.propSuit >= 0.0 && ppp.propSuit <= 1.0) propSuit = ppp.propSuit; -if (ppp.hurst > 0.0 && ppp.hurst < 1.0) hurst = ppp.hurst; -if (ppp.maxCells > 0) maxCells = ppp.maxCells; + fractal = ppp.fractal; + continuous = ppp.continuous; + if (ppp.minPct > 0.0 && ppp.minPct < 100.0) minPct = ppp.minPct; + if (ppp.maxPct > 0.0 && ppp.maxPct <= 100.0) maxPct = ppp.maxPct; + if (ppp.propSuit >= 0.0 && ppp.propSuit <= 1.0) propSuit = ppp.propSuit; + if (ppp.hurst > 0.0 && ppp.hurst < 1.0) hurst = ppp.hurst; + if (ppp.maxCells > 0) maxCells = ppp.maxCells; } genLandParams Landscape::getGenLandParams(void) { -genLandParams ppp; -ppp.fractal = fractal; ppp.continuous = continuous; -ppp.minPct = minPct; ppp.maxPct = maxPct; ppp.propSuit = propSuit; ppp.hurst = hurst; -ppp.maxCells = maxCells; -return ppp; + genLandParams ppp; + ppp.fractal = fractal; ppp.continuous = continuous; + ppp.minPct = minPct; ppp.maxPct = maxPct; ppp.propSuit = propSuit; ppp.hurst = hurst; + ppp.maxCells = maxCells; + return ppp; } -void Landscape::setLandLimits(int x0,int y0,int x1,int y1) { -if (x0 >= 0 && x1 >= 0 && x0 <= x1 && x1 < dimX -&& y0 >= 0 && y1 >= 0 && y0 <= y1 && y1 < dimY) { - minX = x0; maxX = x1; minY = y0; maxY = y1; -} +void Landscape::setLandLimits(int x0, int y0, int x1, int y1) { + if (x0 >= 0 && x1 >= 0 && x0 <= x1 && x1 < dimX + && y0 >= 0 && y1 >= 0 && y0 <= y1 && y1 < dimY) { + minX = x0; maxX = x1; minY = y0; maxY = y1; + } } void Landscape::resetLandLimits(void) { -minX = minY = 0; maxX = dimX-1; maxY = dimY-1; + minX = minY = 0; maxX = dimX - 1; maxY = dimY - 1; } //--------------------------------------------------------------------------- void Landscape::setLandPix(landPix p) { -if (p.pix > 0) pix = p.pix; -if (p.gpix > 0.0) gpix = p.gpix; + if (p.pix > 0) pix = p.pix; + if (p.gpix > 0.0) gpix = p.gpix; } landPix Landscape::getLandPix(void) { -landPix p; -p.pix = pix; p.gpix = gpix; -return p; + landPix p; + p.pix = pix; p.gpix = gpix; + return p; } void Landscape::setOrigin(landOrigin origin) { -minEast = origin.minEast; minNorth = origin.minNorth; + minEast = origin.minEast; minNorth = origin.minNorth; } landOrigin Landscape::getOrigin(void) { -landOrigin origin; -origin.minEast = minEast; origin.minNorth = minNorth; -return origin; + landOrigin origin; + origin.minEast = minEast; origin.minNorth = minNorth; + return origin; } //--------------------------------------------------------------------------- @@ -522,110 +454,94 @@ return origin; bool Landscape::habitatsIndexed(void) { return habIndexed; } void Landscape::listHabCodes(void) { -int nhab = (int)habCodes.size(); + int nhab = (int)habCodes.size(); #if RS_RCPP && !R_CMD -Rcpp::Rcout << endl; -for (int i = 0; i < nhab; i++) { - Rcpp::Rcout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; -} -Rcpp::Rcout << endl; + Rcpp::Rcout << endl; + for (int i = 0; i < nhab; i++) { + Rcpp::Rcout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; + } + Rcpp::Rcout << endl; #else -cout << endl; -for (int i = 0; i < nhab; i++) { - cout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; -} -cout << endl; + cout << endl; + for (int i = 0; i < nhab; i++) { + cout << "Habitat code[ " << i << "] = " << habCodes[i] << endl; + } + cout << endl; #endif } void Landscape::addHabCode(int hab) { -int nhab = (int)habCodes.size(); -bool addCode = true; -for (int i = 0; i < nhab; i++) { - if (hab == habCodes[i]) { - addCode = false; i = nhab+1; + int nhab = (int)habCodes.size(); + bool addCode = true; + for (int i = 0; i < nhab; i++) { + if (hab == habCodes[i]) { + addCode = false; i = nhab + 1; + } } -} -if (addCode) { habCodes.push_back(hab); nHab++; } + if (addCode) { habCodes.push_back(hab); nHab++; } } // Get the index number of the specified habitat in the habitats vector int Landscape::findHabCode(int hab) { -int nhab = (int)habCodes.size(); -for (int i = 0; i < nhab; i++) { - if (hab == habCodes[i]) return i; -} -return -999; + int nhab = (int)habCodes.size(); + for (int i = 0; i < nhab; i++) { + if (hab == habCodes[i]) return i; + } + return -999; } // Get the specified habitat code int Landscape::getHabCode(int ixhab) { -if (ixhab < (int)habCodes.size()) return habCodes[ixhab]; -else return -999; + if (ixhab < (int)habCodes.size()) return habCodes[ixhab]; + else return -999; } void Landscape::clearHabitats(void) { -habCodes.clear(); -colours.clear(); + habCodes.clear(); + colours.clear(); } void Landscape::addColour(rgb c) { -colours.push_back(c); + colours.push_back(c); } -void Landscape::changeColour(int i,rgb col) { -int ncolours = (int)colours.size(); -if (i >= 0 && i < ncolours) { - if (col.r >=0 && col.r <= 255 && col.g >=0 && col.g <= 255 && col.b >=0 && col.b <= 255) - colours[i] = col; -} +void Landscape::changeColour(int i, rgb col) { + int ncolours = (int)colours.size(); + if (i >= 0 && i < ncolours) { + if (col.r >= 0 && col.r <= 255 && col.g >= 0 && col.g <= 255 && col.b >= 0 && col.b <= 255) + colours[i] = col; + } } rgb Landscape::getColour(int ix) { -return colours[ix]; + return colours[ix]; } int Landscape::colourCount(void) { -return (int)colours.size(); + return (int)colours.size(); } //--------------------------------------------------------------------------- void Landscape::setCellArray(void) { -#if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): start: this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); -#endif -if (cells != 0) resetLand(); -//cells = new Cell **[maxY+1]; -cells = new Cell **[dimY]; -#if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): cells=" + Int2Str((int)cells)).c_str()); -#endif -for (int y = dimY-1; y >= 0; y--) { - cells[y] = new Cell *[dimX]; -#if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): y=" + Int2Str(y) -// + " cells[y]=" + Int2Str((int)cells[y])).c_str()); -#endif - for (int x = 0; x < dimX; x++) { - cells[y][x] = 0; + if (cells != 0) resetLand(); + cells = new Cell * *[dimY]; + for (int y = dimY - 1; y >= 0; y--) { + cells[y] = new Cell * [dimX]; + for (int x = 0; x < dimX; x++) { + cells[y][x] = 0; + } } } -#if RSDEBUG -//DebugGUI(("Landscape::setCellArray(): end: this=" + Int2Str((int)this) -// + " cells=" + Int2Str((int)cells)).c_str()); -#endif -} void Landscape::addPatchNum(int p) { -int npatches = (int)patchnums.size(); -bool addpatch = true; -for (int i = 0; i < npatches; i++) { - if (p == patchnums[i]) { - addpatch = false; i = npatches+1; + int npatches = (int)patchnums.size(); + bool addpatch = true; + for (int i = 0; i < npatches; i++) { + if (p == patchnums[i]) { + addpatch = false; i = npatches + 1; + } } -} -if (addpatch) patchnums.push_back(p); + if (addpatch) patchnums.push_back(p); } @@ -635,147 +551,106 @@ either binary (habitat index 0 is the matrix, 1 is suitable habitat) or continuous (0 is the matrix, >0 is suitable habitat) */ void Landscape::generatePatches(void) { -int x,y,ncells; -double p; -Patch *pPatch; -Cell *pCell; + int x, y, ncells; + double p; + Patch* pPatch; + Cell* pCell; -vector ArtLandscape; + vector ArtLandscape; -#if RSDEBUG -//int iiiiii = (int)fractal; -//DEBUGLOG << "Landscape::generatePatches(): (int)fractal=" << iiiiii -// << " rasterType=" << rasterType -// << " continuous=" << continuous -// << " dimX=" << dimX << " dimY=" << dimY -// << " propSuit=" << propSuit -// << " hurst=" << hurst -// << " maxPct=" << maxPct << " minPct=" << minPct -// << endl; -#endif - -setCellArray(); - -int patchnum = 0; // initial patch number for cell-based landscape -// create patch 0 - the matrix patch (even if there is no matrix) -newPatch(patchnum++); - -// as landscape generator returns cells in a random sequence, first set up all cells -// in the landscape in the correct sequence, then update them and create patches for -// habitat cells -for (int yy = dimY-1; yy >= 0; yy--) { - for (int xx = 0; xx < dimX; xx++) { -#if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): yy=" << yy << " xx=" << xx << endl; -#endif - addNewCellToLand(xx,yy,0); + setCellArray(); + + int patchnum = 0; // initial patch number for cell-based landscape + // create patch 0 - the matrix patch (even if there is no matrix) + newPatch(patchnum++); + + // as landscape generator returns cells in a random sequence, first set up all cells + // in the landscape in the correct sequence, then update them and create patches for + // habitat cells + for (int yy = dimY - 1; yy >= 0; yy--) { + for (int xx = 0; xx < dimX; xx++) { + addNewCellToLand(xx, yy, 0); + } } -} -if (continuous) rasterType = 2; -else rasterType = 0; -if (fractal) { - p = 1.0 - propSuit; - // fractal_landscape() requires Max_prop > 1 (but does not check it!) - // as in turn it calls runif(1.0,Max_prop) - double maxpct; - if (maxPct < 1.0) maxpct = 100.0; else maxpct = maxPct; + if (continuous) rasterType = 2; + else rasterType = 0; + if (fractal) { + p = 1.0 - propSuit; + // fractal_landscape() requires Max_prop > 1 (but does not check it!) + // as in turn it calls runif(1.0,Max_prop) + double maxpct; + if (maxPct < 1.0) maxpct = 100.0; else maxpct = maxPct; - ArtLandscape = fractal_landscape(dimY,dimX,hurst,p,maxpct,minPct); + ArtLandscape = fractal_landscape(dimY, dimX, hurst, p, maxpct, minPct); - vector::iterator iter = ArtLandscape.begin(); - while (iter != ArtLandscape.end()) { - x = iter->y_coord; y = iter->x_coord; -#if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): x=" << x << " y=" << y -// << " iter->avail=" << iter->avail -// << " iter->value=" << iter->value << endl; -#endif - pCell = findCell(x,y); - if (continuous) { - if (iter->value > 0.0) { // habitat - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch,iter->value); - } - else { // matrix - addCellToPatch(pCell,patches[0],iter->value); - } - } - else { // discrete - if (iter->avail == 0) { // matrix - addCellToPatch(pCell,patches[0]); + vector::iterator iter = ArtLandscape.begin(); + while (iter != ArtLandscape.end()) { + x = iter->y_coord; y = iter->x_coord; + pCell = findCell(x, y); + if (continuous) { + if (iter->value > 0.0) { // habitat + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch, iter->value); + } + else { // matrix + addCellToPatch(pCell, patches[0], iter->value); + } } - else { // habitat - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - pCell->changeHabIndex(0,1); + else { // discrete + if (iter->avail == 0) { // matrix + addCellToPatch(pCell, patches[0]); + } + else { // habitat + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + pCell->changeHabIndex(0, 1); + } } + iter++; } - iter++; } -} -else { // random landscape - int hab = 0; - ncells = (int)((float)(dimX) * (float)(dimY) * propSuit + 0.00001); // no. of cells to initialise -#if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): dimX=" << dimX << " dimY=" << dimY -// << " propSuit=" << propSuit -// << " PRODUCT=" << ((float)(dimX) * (float)(dimY) * propSuit + 0.00001) -// << " ncells=" << ncells << endl; -#endif - int i = 0; - do { + else { // random landscape + int hab = 0; + ncells = (int)((float)(dimX) * (float)(dimY)*propSuit + 0.00001); // no. of cells to initialise + int i = 0; do { - x = pRandom->IRandom(0,dimX-1); y = pRandom->IRandom(0,dimY-1); - pCell = findCell(x,y); - hab = pCell->getHabIndex(0); - } while (hab > 0); -#if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches() 00000: y=" << y << " x=" << x -// << " i=" << i << " hab=" << hab << " patchnum=" << patchnum -// << endl; -#endif - pPatch = newPatch(patchnum++); - pCell = findCell(x,y); - addCellToPatch(pCell,pPatch); - pCell->changeHabIndex(0,1); - if (continuous) { - pCell->setHabitat((float)(minPct + pRandom->Random() * (maxPct - minPct))); - } - i++; - } while (i < ncells); - // remaining cells need to be added to the matrix patch - p = 0.0; - x = 0; - for (int yy = dimY-1; yy >= 0; yy--) { - for (int xx = 0; xx < dimX; xx++) { - pCell = findCell(xx,yy); + do { + x = pRandom->IRandom(0, dimX - 1); y = pRandom->IRandom(0, dimY - 1); + pCell = findCell(x, y); + hab = pCell->getHabIndex(0); + } while (hab > 0); + pPatch = newPatch(patchnum++); + pCell = findCell(x, y); + addCellToPatch(pCell, pPatch); + pCell->changeHabIndex(0, 1); if (continuous) { - if (pCell->getHabitat(0) <= 0.0) - { - addCellToPatch(pCell,patches[0],(float)p); - } + pCell->setHabitat((float)(minPct + pRandom->Random() * (maxPct - minPct))); } - else { // discrete - if (pCell->getHabIndex(0) == 0) { -#if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches() 11111: yy=" << yy << " xx=" << xx -// << endl; -#endif - addCellToPatch(pCell,patches[0],x); + i++; + } while (i < ncells); + // remaining cells need to be added to the matrix patch + p = 0.0; + x = 0; + for (int yy = dimY - 1; yy >= 0; yy--) { + for (int xx = 0; xx < dimX; xx++) { + pCell = findCell(xx, yy); + if (continuous) { + if (pCell->getHabitat(0) <= 0.0) + { + addCellToPatch(pCell, patches[0], (float)p); + } + } + else { // discrete + if (pCell->getHabIndex(0) == 0) { + addCellToPatch(pCell, patches[0], x); + } } } } } } -#if RSDEBUG -//DEBUGLOG << "Landscape::generatePatches(): finished, no. of patches = " -// << patchCount() << endl; -#endif - -} - //--------------------------------------------------------------------------- // Landscape patch-management functions @@ -783,518 +658,419 @@ else { // random landscape //--------------------------------------------------------------------------- /* Create a patch for each suitable cell of a cell-based landscape (all other habitat cells are added to the matrix patch) */ -void Landscape::allocatePatches(Species *pSpecies) +void Landscape::allocatePatches(Species* pSpecies) { -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): pSpecies=" << pSpecies -// << " N patches=" << (int)patches.size() << endl; -#endif -//int hx; -float habK; -Patch *pPatch; -Cell *pCell; - -// delete all existing patches -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): i=" << i -// << " patches[i]=" << patches[i] << endl; -#endif - if (patches[i] != NULL) delete patches[i]; -} -patches.clear(); -// create the matrix patch -patches.push_back(new Patch(0,0)); -Patch *matrixPatch = patches[0]; -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): npatches=" << npatches -// << " N patches=" << (int)patches.size() << endl; -#endif -int patchnum = 1; + float habK; + Patch* pPatch; + Cell* pCell; -switch (rasterType) { - -case 0: // habitat codes - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " cells=" << cells[y][x] << endl; -#endif - if (cells[y][x] != 0) { // not no-data cell - pCell = cells[y][x]; -// hx = pCell->getHabIndex(); -// habK = pSpecies->getHabK(hx); - habK = 0.0; - int nhab = pCell->nHabitats(); - for (int i = 0; i < nhab; i++) { - habK += pSpecies->getHabK(pCell->getHabIndex(i)); -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " i=" << i -// << " cells[y][x]=" << cells[y][x] -// << " pCell=" << pCell -// << " habK=" << habK << endl; -#endif - } - if (habK > 0.0) { // cell is suitable - create a patch for it - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - } - else { // cell is not suitable - add to the matrix patch - addCellToPatch(pCell,matrixPatch); - pPatch = 0; + // delete all existing patches + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (patches[i] != NULL) delete patches[i]; + } + patches.clear(); + // create the matrix patch + patches.push_back(new Patch(0, 0)); + Patch* matrixPatch = patches[0]; + int patchnum = 1; + + switch (rasterType) { + + case 0: // habitat codes + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not no-data cell + pCell = cells[y][x]; + habK = 0.0; + int nhab = pCell->nHabitats(); + for (int i = 0; i < nhab; i++) { + habK += pSpecies->getHabK(pCell->getHabIndex(i)); + } + if (habK > 0.0) { // cell is suitable - create a patch for it + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + } + else { // cell is not suitable - add to the matrix patch + addCellToPatch(pCell, matrixPatch); + pPatch = 0; + } } } } - } - break; -case 1: // habitat cover - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " cells=" << cells[y][x] << endl; -#endif - if (cells[y][x] != 0) { // not no-data cell - pCell = cells[y][x]; - habK = 0.0; - int nhab = pCell->nHabitats(); -// for (int i = 0; i < nHab; i++) - for (int i = 0; i < nhab; i++) - { - habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " i=" << i -// << " cells[y][x]=" << cells[y][x] -// << " pCell=" << pCell -// << " habK=" << habK << endl; -#endif - } - if (habK > 0.0) { // cell is suitable - create a patch for it - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - } - else { // cell is not suitable - add to the matrix patch - addCellToPatch(pCell,matrixPatch); - pPatch = 0; + break; + case 1: // habitat cover + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not no-data cell + pCell = cells[y][x]; + habK = 0.0; + int nhab = pCell->nHabitats(); + for (int i = 0; i < nhab; i++) + { + habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; + } + if (habK > 0.0) { // cell is suitable - create a patch for it + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + } + else { // cell is not suitable - add to the matrix patch + addCellToPatch(pCell, matrixPatch); + pPatch = 0; + } } } } - } - break; -case 2: // habitat quality - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " cells=" << cells[y][x] << endl; -#endif - if (cells[y][x] != 0) { // not no-data cell - pCell = cells[y][x]; - habK = 0.0; - int nhab = pCell->nHabitats(); -// for (int i = 0; i < nHab; i++) - for (int i = 0; i < nhab; i++) - { - habK += pSpecies->getHabK(0) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y -// << " i=" << i -// << " cells[y][x]=" << cells[y][x] -// << " pCell=" << pCell -// << " habK=" << habK << endl; -#endif - } - if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it - pPatch = newPatch(patchnum++); - addCellToPatch(pCell,pPatch); - } - else { // cell is never suitable - add to the matrix patch - addCellToPatch(pCell,matrixPatch); - pPatch = 0; + break; + case 2: // habitat quality + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + + if (cells[y][x] != 0) { // not no-data cell + pCell = cells[y][x]; + habK = 0.0; + int nhab = pCell->nHabitats(); + // for (int i = 0; i < nHab; i++) + for (int i = 0; i < nhab; i++) + { + habK += pSpecies->getHabK(0) * pCell->getHabitat(i) / 100.0f; + } + if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it + pPatch = newPatch(patchnum++); + addCellToPatch(pCell, pPatch); + } + else { // cell is never suitable - add to the matrix patch + addCellToPatch(pCell, matrixPatch); + pPatch = 0; + } } } } - } - break; - -} // end of switch (rasterType) - -#if RSDEBUG -//DEBUGLOG << "Landscape::allocatePatches(): finished, N patches = " << (int)patches.size() << endl; -#endif + break; + } // end of switch (rasterType) } -Patch* Landscape::newPatch(int num) +Patch* Landscape::newPatch(int num) { -int npatches = (int)patches.size(); -patches.push_back(new Patch(num,num)); -return patches[npatches]; + int npatches = (int)patches.size(); + patches.push_back(new Patch(num, num)); + return patches[npatches]; } -Patch* Landscape::newPatch(int seqnum,int num) +Patch* Landscape::newPatch(int seqnum, int num) { -int npatches = (int)patches.size(); -patches.push_back(new Patch(seqnum,num)); -return patches[npatches]; + int npatches = (int)patches.size(); + patches.push_back(new Patch(seqnum, num)); + return patches[npatches]; } void Landscape::resetPatches(void) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - patches[i]->resetLimits(); -} + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + patches[i]->resetLimits(); + } } -void Landscape::addNewCellToLand(int x,int y,float q) { -if (q < 0.0) // no-data cell - no Cell created - cells[y][x] = 0; -else - cells[y][x] = new Cell(x,y,0,q); +void Landscape::addNewCellToLand(int x, int y, float q) { + if (q < 0.0) // no-data cell - no Cell created + cells[y][x] = 0; + else + cells[y][x] = new Cell(x, y, 0, q); } -void Landscape::addNewCellToLand(int x,int y,int hab) { -if (hab < 0) // no-data cell - no Cell created - cells[y][x] = 0; -else - cells[y][x] = new Cell(x,y,0,hab); +void Landscape::addNewCellToLand(int x, int y, int hab) { + if (hab < 0) // no-data cell - no Cell created + cells[y][x] = 0; + else + cells[y][x] = new Cell(x, y, 0, hab); } -void Landscape::addNewCellToPatch(Patch *pPatch,int x,int y,float q) { -if (q < 0.0) { // no-data cell - no Cell created - cells[y][x] = 0; -} -else { // create the new cell - cells[y][x] = new Cell(x,y,(intptr)pPatch,q); - if (pPatch != 0) { // not the matrix patch - // add the cell to the patch - pPatch->addCell(cells[y][x],x,y); +void Landscape::addNewCellToPatch(Patch* pPatch, int x, int y, float q) { + if (q < 0.0) { // no-data cell - no Cell created + cells[y][x] = 0; + } + else { // create the new cell + cells[y][x] = new Cell(x, y, (intptr)pPatch, q); + if (pPatch != 0) { // not the matrix patch + // add the cell to the patch + pPatch->addCell(cells[y][x], x, y); + } } -} } -void Landscape::addNewCellToPatch(Patch *pPatch,int x,int y,int hab) { -if (hab < 0) // no-data cell - no Cell created - cells[y][x] = 0; -else { // create the new cell - cells[y][x] = new Cell(x,y,(intptr)pPatch,hab); - if (pPatch != 0) { // not the matrix patch - // add the cell to the patch - pPatch->addCell(cells[y][x],x,y); +void Landscape::addNewCellToPatch(Patch* pPatch, int x, int y, int hab) { + if (hab < 0) // no-data cell - no Cell created + cells[y][x] = 0; + else { // create the new cell + cells[y][x] = new Cell(x, y, (intptr)pPatch, hab); + if (pPatch != 0) { // not the matrix patch + // add the cell to the patch + pPatch->addCell(cells[y][x], x, y); + } } } -} -void Landscape::addCellToPatch(Cell *pCell,Patch *pPatch) { -pCell->setPatch((intptr)pPatch); -locn loc = pCell->getLocn(); -// add the cell to the patch -pPatch->addCell(pCell,loc.x,loc.y); +void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch) { + pCell->setPatch((intptr)pPatch); + locn loc = pCell->getLocn(); + // add the cell to the patch + pPatch->addCell(pCell, loc.x, loc.y); } -void Landscape::addCellToPatch(Cell *pCell,Patch *pPatch,float q) { -pCell->setPatch((intptr)pPatch); -// update the habitat type of the cell -pCell->setHabitat(q); -locn loc = pCell->getLocn(); -// add the cell to the patch -pPatch->addCell(pCell,loc.x,loc.y); +void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch, float q) { + pCell->setPatch((intptr)pPatch); + // update the habitat type of the cell + pCell->setHabitat(q); + locn loc = pCell->getLocn(); + // add the cell to the patch + pPatch->addCell(pCell, loc.x, loc.y); } -void Landscape::addCellToPatch(Cell *pCell,Patch *pPatch,int hab) { -pCell->setPatch((intptr)pPatch); -// update the habitat type of the cell -pCell->setHabIndex(hab); -locn loc = pCell->getLocn(); -// add the cell to the patch -pPatch->addCell(pCell,loc.x,loc.y); +void Landscape::addCellToPatch(Cell* pCell, Patch* pPatch, int hab) { + pCell->setPatch((intptr)pPatch); + // update the habitat type of the cell + pCell->setHabIndex(hab); + locn loc = pCell->getLocn(); + // add the cell to the patch + pPatch->addCell(pCell, loc.x, loc.y); } patchData Landscape::getPatchData(int ix) { -patchData ppp; -ppp.pPatch = patches[ix]; ppp.patchNum = patches[ix]->getPatchNum(); -ppp.nCells = patches[ix]->getNCells(); -locn randloc; randloc.x = -666; randloc.y = -666; -Cell *pCell = patches[ix]->getRandomCell(); -if (pCell != 0) { - randloc = pCell->getLocn(); -} -ppp.x = randloc.x; ppp.y = randloc.y; -return ppp; + patchData ppp; + ppp.pPatch = patches[ix]; ppp.patchNum = patches[ix]->getPatchNum(); + ppp.nCells = patches[ix]->getNCells(); + locn randloc; randloc.x = -666; randloc.y = -666; + Cell* pCell = patches[ix]->getRandomCell(); + if (pCell != 0) { + randloc = pCell->getLocn(); + } + ppp.x = randloc.x; ppp.y = randloc.y; + return ppp; } bool Landscape::existsPatch(int num) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - if (num == patches[i]->getPatchNum()) return true; -} -return false; + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (num == patches[i]->getPatchNum()) return true; + } + return false; } Patch* Landscape::findPatch(int num) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - if (num == patches[i]->getPatchNum()) return patches[i]; -} -return 0; + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (num == patches[i]->getPatchNum()) return patches[i]; + } + return 0; } void Landscape::resetPatchPopns(void) { -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - patches[i]->resetPopn(); -} + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + patches[i]->resetPopn(); + } } -void Landscape::updateCarryingCapacity(Species *pSpecies,int yr,short landIx) { -envGradParams grad = paramsGrad->getGradient(); -bool gradK = false; -if (grad.gradient && grad.gradType == 1) gradK = true; // gradient in carrying capacity -patchLimits landlimits; -landlimits.xMin = minX; landlimits.xMax = maxX; -landlimits.yMin = minY; landlimits.yMax = maxY; -#if RSDEBUG -//DEBUGLOG << "Landscape::updateCarryingCapacity(): yr=" << yr -// << " xMin=" << landlimits.xMin << " yMin=" << landlimits.yMin -// << " xMax=" << landlimits.xMax << " yMax=" << landlimits.yMax -// << endl; -#endif -int npatches = (int)patches.size(); -for (int i = 0; i < npatches; i++) { - if (patches[i]->getPatchNum() != 0) { // not matrix patch - patches[i]->setCarryingCapacity(pSpecies,landlimits, - getGlobalStoch(yr),nHab,rasterType,landIx,gradK); +void Landscape::updateCarryingCapacity(Species* pSpecies, int yr, short landIx) { + envGradParams grad = paramsGrad->getGradient(); + bool gradK = false; + if (grad.gradient && grad.gradType == 1) gradK = true; // gradient in carrying capacity + patchLimits landlimits; + landlimits.xMin = minX; landlimits.xMax = maxX; + landlimits.yMin = minY; landlimits.yMax = maxY; + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + if (patches[i]->getPatchNum() != 0) { // not matrix patch + patches[i]->setCarryingCapacity(pSpecies, landlimits, + getGlobalStoch(yr), nHab, rasterType, landIx, gradK); + } } -} } -Cell* Landscape::findCell(int x,int y) { -if (x >= 0 && x < dimX && y >= 0 && y < dimY) return cells[y][x]; -else return 0; +Cell* Landscape::findCell(int x, int y) { + if (x >= 0 && x < dimX && y >= 0 && y < dimY) return cells[y][x]; + else return 0; } int Landscape::patchCount(void) { -return (int)patches.size(); + return (int)patches.size(); } void Landscape::listPatches(void) { -patchLimits p; -int npatches = (int)patches.size(); + patchLimits p; + int npatches = (int)patches.size(); #if RS_RCPP && !R_CMD -Rcpp::Rcout << endl; -for (int i = 0; i < npatches; i++) { - p = patches[i]->getLimits(); - Rcpp::Rcout << "Patch " << patches[i]->getPatchNum() - << " xMin = " << p.xMin << " xMax = " << p.xMax - << " \tyMin = " << p.yMin << " yMax = " << p.yMax - << endl; -} -Rcpp::Rcout << endl; + Rcpp::Rcout << endl; + for (int i = 0; i < npatches; i++) { + p = patches[i]->getLimits(); + Rcpp::Rcout << "Patch " << patches[i]->getPatchNum() + << " xMin = " << p.xMin << " xMax = " << p.xMax + << " \tyMin = " << p.yMin << " yMax = " << p.yMax + << endl; + } + Rcpp::Rcout << endl; #else -cout << endl; -for (int i = 0; i < npatches; i++) { - p = patches[i]->getLimits(); - cout << "Patch " << patches[i]->getPatchNum() - << " xMin = " << p.xMin << " xMax = " << p.xMax - << " \tyMin = " << p.yMin << " yMax = " << p.yMax - << endl; -} -cout << endl; + cout << endl; + for (int i = 0; i < npatches; i++) { + p = patches[i]->getLimits(); + cout << "Patch " << patches[i]->getPatchNum() + << " xMin = " << p.xMin << " xMax = " << p.xMax + << " \tyMin = " << p.yMin << " yMax = " << p.yMax + << endl; + } + cout << endl; #endif } // Check that total cover of any cell does not exceed 100% // and identify matrix cells int Landscape::checkTotalCover(void) { -if (rasterType != 1) return 0; // not appropriate test -int nCells = 0; -for(int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) - { // not a no-data cell - float sumCover = 0.0; - for (int i = 0; i < nHab; i++) { - sumCover += cells[y][x]->getHabitat(i); -#if RSDEBUG -//DebugGUI(("Landscape::checkTotalCover(): y=" + Int2Str(y) -// + " x=" + Int2Str(x) -// + " i=" + Int2Str(i) -// + " sumCover=" + Float2Str(sumCover) -// ).c_str()); -#endif + if (rasterType != 1) return 0; // not appropriate test + int nCells = 0; + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) + { // not a no-data cell + float sumCover = 0.0; + for (int i = 0; i < nHab; i++) { + sumCover += cells[y][x]->getHabitat(i); + } + if (sumCover > 100.00001) nCells++; // decimal part to allow for floating point error + if (sumCover <= 0.0) // cell is a matrix cell + cells[y][x]->setHabIndex(0); + else + cells[y][x]->setHabIndex(1); } - if (sumCover > 100.00001) nCells++; // decimal part to allow for floating point error - if (sumCover <= 0.0) // cell is a matrix cell - cells[y][x]->setHabIndex(0); - else - cells[y][x]->setHabIndex(1); } } -} -return nCells; + return nCells; } // Convert habitat codes stored on loading habitat codes landscape to // sequential sorted index numbers void Landscape::updateHabitatIndices(void) { -// sort codes -sort (habCodes.begin(),habCodes.end()); -nHab = (int)habCodes.size(); -// convert codes in landscape -int h; -int changes = (int)landchanges.size(); -#if RSDEBUG -//DebugGUI(("Landscape::updateHabitatIndices(): nHab=" + Int2Str(nHab) -// + " changes=" + Int2Str(changes) -// ).c_str()); -#endif -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - for (int c = 0; c <= changes; c++) { - h = cells[y][x]->getHabIndex(c); -#if RSDEBUG -//DebugGUI(("Landscape::updateHabitatIndices() 00000: y=" + Int2Str(y) -// + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) -// ).c_str()); -#endif - if (h >= 0) { - h = findHabCode(h); -#if RSDEBUG -//DebugGUI(("Landscape::updateHabitatIndices() 11111: y=" + Int2Str(y) -// + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) -// ).c_str()); -#endif - cells[y][x]->changeHabIndex(c,h); + // sort codes + sort(habCodes.begin(), habCodes.end()); + nHab = (int)habCodes.size(); + // convert codes in landscape + int h; + int changes = (int)landchanges.size(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + for (int c = 0; c <= changes; c++) { + h = cells[y][x]->getHabIndex(c); + + if (h >= 0) { + h = findHabCode(h); + + cells[y][x]->changeHabIndex(c, h); + } } } } } -} -habIndexed = true; + habIndexed = true; } -void Landscape::setEnvGradient(Species *pSpecies,bool initial) +void Landscape::setEnvGradient(Species* pSpecies, bool initial) { -float dist_from_opt,dev; -float habK; -//int hab; -double envval; -// gradient parameters -envGradParams grad = paramsGrad->getGradient(); -#if RSDEBUG -//DEBUGLOG << "Landscape::setEnvGradient(): grad.opt_y = " << grad.opt_y -// << " grad.grad_inc = " << grad.grad_inc << " grad.factor " << grad.factor -// << endl; -#endif -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - // NB: gradient lies in range 0-1 for all types, and is applied when necessary... - // ... implies gradient increment will be dimensionless in range 0-1 (but << 1) - if (cells[y][x] != 0) { // not no-data cell - habK = 0.0; - int nhab = cells[y][x]->nHabitats(); - for (int i = 0; i < nhab; i++) { - switch (rasterType) { - case 0: - habK += pSpecies->getHabK(cells[y][x]->getHabIndex(i)); - break; - case 1: - habK += pSpecies->getHabK(i) * cells[y][x]->getHabitat(i) / 100.0f; - break; - case 2: - habK += pSpecies->getHabK(0) * cells[y][x]->getHabitat(i) / 100.0f; - break; + float dist_from_opt, dev; + float habK; + double envval; + // gradient parameters + envGradParams grad = paramsGrad->getGradient(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + // NB: gradient lies in range 0-1 for all types, and is applied when necessary... + // ... implies gradient increment will be dimensionless in range 0-1 (but << 1) + if (cells[y][x] != 0) { // not no-data cell + habK = 0.0; + int nhab = cells[y][x]->nHabitats(); + for (int i = 0; i < nhab; i++) { + switch (rasterType) { + case 0: + habK += pSpecies->getHabK(cells[y][x]->getHabIndex(i)); + break; + case 1: + habK += pSpecies->getHabK(i) * cells[y][x]->getHabitat(i) / 100.0f; + break; + case 2: + habK += pSpecies->getHabK(0) * cells[y][x]->getHabitat(i) / 100.0f; + break; + } } - } -#if RSDEBUG -//DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x -// << " dist_from_opt=" << dist_from_opt << " rasterType=" << rasterType << " hab=" << hab -// << endl; -#endif - if (habK > 0.0) { // suitable cell - if (initial) { // set local environmental deviation - cells[y][x]->setEnvDev((float)pRandom->Random()*(2.0f) - 1.0f); + + if (habK > 0.0) { // suitable cell + if (initial) { // set local environmental deviation + cells[y][x]->setEnvDev((float)pRandom->Random() * (2.0f) - 1.0f); + } + dist_from_opt = (float)(fabs((double)grad.opt_y - (double)y)); + dev = cells[y][x]->getEnvDev(); + envval = 1.0 - dist_from_opt * grad.grad_inc + dev * grad.factor; + if (envval < 0.000001) envval = 0.0; + if (envval > 1.0) envval = 1.0; } - dist_from_opt = (float)(fabs((double)grad.opt_y - (double)y)); - dev = cells[y][x]->getEnvDev(); - envval = 1.0 - dist_from_opt*grad.grad_inc + dev*grad.factor; -#if RSDEBUG -//DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x -// << " dist_from_opt=" << dist_from_opt << " dev=" << dev << " p=" << p -// << endl; -#endif - if (envval < 0.000001) envval = 0.0; - if (envval > 1.0) envval = 1.0; + else envval = 0.0; + cells[y][x]->setEnvVal((float)envval); } - else envval = 0.0; - cells[y][x]->setEnvVal((float)envval); } } -} } void Landscape::setGlobalStoch(int nyears) { -envStochParams env = paramsStoch->getStoch(); -if (epsGlobal != 0) delete[] epsGlobal; -epsGlobal = new float[nyears]; -epsGlobal[0] = (float)(pRandom->Normal(0.0,env.std)*sqrt(1.0-(env.ac*env.ac))); -for (int i = 1; i < nyears; i++){ - epsGlobal[i] = (float)(env.ac*epsGlobal[i-1] + pRandom->Normal(0.0,env.std)*sqrt(1.0-(env.ac*env.ac))); -} + envStochParams env = paramsStoch->getStoch(); + if (epsGlobal != 0) delete[] epsGlobal; + epsGlobal = new float[nyears]; + epsGlobal[0] = (float)(pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); + for (int i = 1; i < nyears; i++) { + epsGlobal[i] = (float)(env.ac * epsGlobal[i - 1] + pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); + } } float Landscape::getGlobalStoch(int yr) { -if (epsGlobal != 0 && yr >= 0) { - return epsGlobal[yr]; -} -else return 0.0; + if (epsGlobal != 0 && yr >= 0) { + return epsGlobal[yr]; + } + else return 0.0; } void Landscape::updateLocalStoch(void) { -envStochParams env = paramsStoch->getStoch(); -float randpart; -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - randpart = (float)(pRandom->Normal(0.0,env.std) * sqrt(1.0-(env.ac*env.ac))); -#if RSDEBUG -//DEBUGLOG << "Landscape::updateLocalStoch(): y=" << y << " x=" << x -// << " env.std= " << env.std << " env.ac= " << env.ac << " randpart= " << randpart -// << endl; -#endif - cells[y][x]->updateEps((float)env.ac,randpart); + envStochParams env = paramsStoch->getStoch(); + float randpart; + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + randpart = (float)(pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); + cells[y][x]->updateEps((float)env.ac, randpart); + } } } -} } void Landscape::resetCosts(void) { -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - cells[y][x]->resetCost(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + cells[y][x]->resetCost(); + } } } } -} void Landscape::resetEffCosts(void) { -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - cells[y][x]->resetEffCosts(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + cells[y][x]->resetEffCosts(); + } } } } -} //--------------------------------------------------------------------------- @@ -1303,62 +1079,50 @@ for(int y = dimY-1; y >= 0; y--){ void Landscape::setDynamicLand(bool dyn) { dynamic = dyn; } void Landscape::addLandChange(landChange c) { -#if RSDEBUG -//DebugGUI(("Landscape::addLandChange(): chgnum=" + Int2Str(c.chgnum) -// + " chgyear=" + Int2Str(c.chgyear) -// ).c_str()); -#endif -landchanges.push_back(c); + landchanges.push_back(c); } int Landscape::numLandChanges(void) { return (int)landchanges.size(); } landChange Landscape::getLandChange(short ix) { -landChange c; c.chgnum = c.chgyear = 0; -c.habfile = c.pchfile = c.costfile = "none"; -int nchanges = (int)landchanges.size(); -if (ix < nchanges) c = landchanges[ix]; -return c; + landChange c; c.chgnum = c.chgyear = 0; + c.habfile = c.pchfile = c.costfile = "none"; + int nchanges = (int)landchanges.size(); + if (ix < nchanges) c = landchanges[ix]; + return c; } void Landscape::deleteLandChanges(void) { -while (landchanges.size() > 0) landchanges.pop_back(); -landchanges.clear(); + while (landchanges.size() > 0) landchanges.pop_back(); + landchanges.clear(); } #if RS_RCPP && !R_CMD int Landscape::readLandChange(int filenum, bool costs, wifstream& hfile, wifstream& pfile, wifstream& cfile, int habnodata, int pchnodata, int costnodata) #else -int Landscape::readLandChange(int filenum,bool costs) +int Landscape::readLandChange(int filenum, bool costs) #endif { #if RSDEBUG -DEBUGLOG << "Landscape::readLandChange(): filenum=" << filenum << " costs=" << int(costs) - << endl; + DEBUGLOG << "Landscape::readLandChange(): filenum=" << filenum << " costs=" << int(costs) + << endl; #endif #if RS_RCPP -wstring header; + wstring header; #else -string header; -int ncols,nrows,habnodata,costnodata,pchnodata; -costnodata = 0; -pchnodata = 0; + string header; + int ncols, nrows, habnodata, costnodata, pchnodata; + costnodata = 0; + pchnodata = 0; #endif -int h = 0,p = 0,c = 0, pchseq = 0; -float hfloat,pfloat,cfloat; -simParams sim = paramsSim->getSim(); - -if (filenum < 0) return 19; + int h = 0, p = 0, c = 0, pchseq = 0; + float hfloat, pfloat, cfloat; + simParams sim = paramsSim->getSim(); -//if (patchModel && (rasterType == 0 || rasterType == 2)) { -// if (filenum == 0) { // first change -// createPatchChgMatrix(); -// } -// pchseq = patchCount(); -//} -if (patchModel) pchseq = patchCount(); + if (filenum < 0) return 19; + if (patchModel) pchseq = patchCount(); #if !RS_RCPP ifstream hfile; // habitat file input stream @@ -1367,643 +1131,577 @@ if (patchModel) pchseq = patchCount(); #endif #if !RS_RCPP || R_CMD -// open habitat file and optionally also patch and costs files -hfile.open(landchanges[filenum].habfile.c_str()); -if (!hfile.is_open()) return 30; -if (patchModel) { - pfile.open(landchanges[filenum].pchfile.c_str()); - if (!pfile.is_open()) { - hfile.close(); hfile.clear(); - return 31; + // open habitat file and optionally also patch and costs files + hfile.open(landchanges[filenum].habfile.c_str()); + if (!hfile.is_open()) return 30; + if (patchModel) { + pfile.open(landchanges[filenum].pchfile.c_str()); + if (!pfile.is_open()) { + hfile.close(); hfile.clear(); + return 31; + } } -} -if (costs) { - cfile.open(landchanges[filenum].costfile.c_str()); - if (!cfile.is_open()) { - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); + if (costs) { + cfile.open(landchanges[filenum].costfile.c_str()); + if (!cfile.is_open()) { + hfile.close(); hfile.clear(); + if (pfile.is_open()) { + pfile.close(); pfile.clear(); + } + return 32; } - return 32; } -} -// read header records of habitat (and patch) file(s) -// NB headers of all files have already been compared -hfile >> header >> ncols >> header >> nrows >> header >> hfloat >> header >> hfloat - >> header >> hfloat >> header >> habnodata; -if (patchModel) { - for (int i = 0; i < 5; i++) pfile >> header >> pfloat; - pfile >> header >> pchnodata; -} -if (costs) { - for (int i = 0; i < 5; i++) cfile >> header >> cfloat; - cfile >> header >> costnodata; -} + // read header records of habitat (and patch) file(s) + // NB headers of all files have already been compared + hfile >> header >> ncols >> header >> nrows >> header >> hfloat >> header >> hfloat + >> header >> hfloat >> header >> habnodata; + if (patchModel) { + for (int i = 0; i < 5; i++) pfile >> header >> pfloat; + pfile >> header >> pchnodata; + } + if (costs) { + for (int i = 0; i < 5; i++) cfile >> header >> cfloat; + cfile >> header >> costnodata; + } #endif -// set up bad float values to ensure that valid values are read -float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; -float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; -float badcfloat = -9.0; if (costnodata == -9) badcfloat = -99.0; + // set up bad float values to ensure that valid values are read + float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; + float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; + float badcfloat = -9.0; if (costnodata == -9) badcfloat = -99.0; -switch (rasterType) { + switch (rasterType) { -case 0: // raster with habitat codes - 100% habitat each cell - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + case 0: // raster with habitat codes - 100% habitat each cell + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; + h = (int)hfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("habitatchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 171; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - if (patchModel) { - pfloat = badpfloat; + StreamErrorR("habitatchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 171; + } +#endif + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("patchchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 172; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - } - if (costs) { - cfloat = badcfloat; + StreamErrorR("patchchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 172; + } +#endif + } + if (costs) { + cfloat = badcfloat; #if RS_RCPP - if(cfile >> cfloat) { + if (cfile >> cfloat) { #else - cfile >> cfloat; + cfile >> cfloat; #endif - c = (int)cfloat; + c = (int)cfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("costchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 173; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR("costchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 173; + } #endif + } + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if (h == habnodata) { // invalid no data cell in change map + hfile.close(); hfile.clear(); + return 36; + } + else { + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { + // invalid habitat code + hfile.close(); hfile.clear(); + if (patchModel) { pfile.close(); pfile.clear(); } + return 33; } -#if RSDEBUG -//DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " h=" + Int2Str(h) + " p=" + Int2Str(p) -//).c_str()); + else { + addHabCode(h); + cells[y][x]->setHabIndex(h); + } + } + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; #endif - if (cells[y][x] != 0) { // not a no data cell (in initial landscape) - if (h == habnodata) { // invalid no data cell in change map - hfile.close(); hfile.clear(); - return 36; - } - else { - if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { - // invalid habitat code - hfile.close(); hfile.clear(); - if (patchModel) { pfile.close(); pfile.clear(); } - return 33; - } - else { - addHabCode(h); - cells[y][x]->setHabIndex(h); - } - } - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 34; - } - else { - patchChgMatrix[y][x][2] = p; - if (p > 0 && !existsPatch(p)) { - addPatchNum(p); - newPatch(pchseq++,p); - } - } + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++, p); } - if (costs) { - if (c < 1) { // invalid cost - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); - } - return 38; - } - else { - costsChgMatrix[y][x][2] = c; - } + } + } + if (costs) { + if (c < 1) { // invalid cost + hfile.close(); hfile.clear(); + if (pfile.is_open()) { + pfile.close(); pfile.clear(); } + return 38; + } + else { + costsChgMatrix[y][x][2] = c; } } } + } + } #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR("habitatchgfile"); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR("patchchgfile"); - } - if (costs) - { - cfile >> cfloat; - if (!cfile.eof()) EOFerrorR("costchgfile"); - } + hfile >> hfloat; + if (!hfile.eof()) EOFerrorR("habitatchgfile"); + if (patchModel) + { + pfile >> pfloat; + if (!pfile.eof()) EOFerrorR("patchchgfile"); + } + if (costs) + { + cfile >> cfloat; + if (!cfile.eof()) EOFerrorR("costchgfile"); + } #endif - break; + break; case 2: // habitat quality - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; + h = (int)hfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("habitatchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 172; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - if (patchModel) { - pfloat = badpfloat; + StreamErrorR("habitatchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 172; + } +#endif + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("patchchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 175; - } -#endif } - if (costs) { - cfloat = badcfloat; + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR("patchchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 175; + } +#endif + } + if (costs) { + cfloat = badcfloat; #if RS_RCPP - if(cfile >> cfloat) { + if (cfile >> cfloat) { #else - cfile >> cfloat; + cfile >> cfloat; #endif - c = (int)cfloat; + c = (int)cfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR("costchgfile"); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 173; - } -#endif } -#if RSDEBUG -//MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) -// + " p=" + Int2Str(p)).c_str()); + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR("costchgfile"); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 173; + } #endif - if (cells[y][x] != 0) { // not a no data cell (in initial landscape) - if (h == habnodata) { // invalid no data cell in change map + } + if (cells[y][x] != 0) { // not a no data cell (in initial landscape) + if (h == habnodata) { // invalid no data cell in change map + hfile.close(); hfile.clear(); + if (patchModel) { pfile.close(); pfile.clear(); } + return 36; + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score hfile.close(); hfile.clear(); if (patchModel) { pfile.close(); pfile.clear(); } - return 36; + return 37; } else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score - hfile.close(); hfile.clear(); - if (patchModel) { pfile.close(); pfile.clear(); } - return 37; - } - else { - cells[y][x]->setHabitat(hfloat); + cells[y][x]->setHabitat(hfloat); + } + } + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif + hfile.close(); hfile.clear(); + pfile.close(); pfile.clear(); + return 34; + } + else { + patchChgMatrix[y][x][2] = p; + if (p > 0 && !existsPatch(p)) { + addPatchNum(p); + newPatch(pchseq++, p); } } - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); + } + if (costs) { + if (c < 1) { // invalid cost + hfile.close(); hfile.clear(); + if (pfile.is_open()) { pfile.close(); pfile.clear(); - return 34; - } - else { - patchChgMatrix[y][x][2] = p; - if (p > 0 && !existsPatch(p)) { - addPatchNum(p); - newPatch(pchseq++,p); - } } + return 38; } - if (costs) { - if (c < 1) { // invalid cost - hfile.close(); hfile.clear(); - if (pfile.is_open()) { - pfile.close(); pfile.clear(); - } - return 38; - } - else { - costsChgMatrix[y][x][2] = c; - } + else { + costsChgMatrix[y][x][2] = c; } } } - } + } + } #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR("habitatchgfile"); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR("patchchgfile"); - } - if (costs) - { - cfile >> cfloat; - if (!cfile.eof()) EOFerrorR("costchgfile"); - } + hfile >> hfloat; + if (!hfile.eof()) EOFerrorR("habitatchgfile"); + if (patchModel) + { + pfile >> pfloat; + if (!pfile.eof()) EOFerrorR("patchchgfile"); + } + if (costs) + { + cfile >> cfloat; + if (!cfile.eof()) EOFerrorR("costchgfile"); + } #endif - break; + break; default: break; -} + } -if (hfile.is_open()) { hfile.close(); hfile.clear(); } -if (pfile.is_open()) { pfile.close(); pfile.clear(); } -if (cfile.is_open()) { cfile.close(); cfile.clear(); } -return 0; + if (hfile.is_open()) { hfile.close(); hfile.clear(); } + if (pfile.is_open()) { pfile.close(); pfile.clear(); } + if (cfile.is_open()) { cfile.close(); cfile.clear(); } + return 0; } // Create & initialise patch change matrix void Landscape::createPatchChgMatrix(void) { -intptr patch; -Patch *pPatch; -Cell *pCell; -if (patchChgMatrix != 0) deletePatchChgMatrix(); -patchChgMatrix = new int **[dimY]; -for(int y = dimY-1; y >= 0; y--){ - patchChgMatrix[y] = new int *[dimX]; - for (int x = 0; x < dimX; x++) { - patchChgMatrix[y][x] = new int [3]; - pCell = findCell(x,y); - if (pCell == 0) { // no-data cell - patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = 0; - } - else { - // record initial patch number - patch = pCell->getPatch(); - if (patch == 0) { // matrix cell + intptr patch; + Patch* pPatch; + Cell* pCell; + if (patchChgMatrix != 0) deletePatchChgMatrix(); + patchChgMatrix = new int** [dimY]; + for (int y = dimY - 1; y >= 0; y--) { + patchChgMatrix[y] = new int* [dimX]; + for (int x = 0; x < dimX; x++) { + patchChgMatrix[y][x] = new int[3]; + pCell = findCell(x, y); + if (pCell == 0) { // no-data cell patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = 0; } else { - pPatch = (Patch*)patch; - patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = pPatch->getPatchNum(); + // record initial patch number + patch = pCell->getPatch(); + if (patch == 0) { // matrix cell + patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = 0; + } + else { + pPatch = (Patch*)patch; + patchChgMatrix[y][x][0] = patchChgMatrix[y][x][1] = pPatch->getPatchNum(); + } } + patchChgMatrix[y][x][2] = 0; } - patchChgMatrix[y][x][2] = 0; -#if RSDEBUG -//DebugGUI(("Landscape::createPatchChgMatrix(): y=" + Int2Str(y) -// + " x=" + Int2Str(x) -// + " patchChgMatrix[y][x][0]=" + Int2Str(patchChgMatrix[y][x][0]) -// + " [1]=" + Int2Str(patchChgMatrix[y][x][1]) -// + " [2]=" + Int2Str(patchChgMatrix[y][x][2]) -// ).c_str()); -#endif } } -} void Landscape::recordPatchChanges(int landIx) { -if (patchChgMatrix == 0) return; // should not occur -patchChange chg; - -for(int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - if (landIx == 0) { // reset to original landscape - if (patchChgMatrix[y][x][0] != patchChgMatrix[y][x][2]) { - // record change of patch for current cell - chg.chgnum = 666666; chg.x = x; chg.y = y; - chg.oldpatch = patchChgMatrix[y][x][2]; - chg.newpatch = patchChgMatrix[y][x][0]; - patchchanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldpatch=" + Int2Str(chg.oldpatch) -// + " chg.newpatch=" + Int2Str(chg.newpatch) -// ).c_str()); -#endif - } - } - else { // any other change - if (patchChgMatrix[y][x][2] != patchChgMatrix[y][x][1]) { - // record change of patch for current cell - chg.chgnum = landIx; chg.x = x; chg.y = y; - chg.oldpatch = patchChgMatrix[y][x][1]; - chg.newpatch = patchChgMatrix[y][x][2]; - patchchanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldpatch=" + Int2Str(chg.oldpatch) -// + " chg.newpatch=" + Int2Str(chg.newpatch) -// ).c_str()); -#endif + if (patchChgMatrix == 0) return; // should not occur + patchChange chg; + + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (landIx == 0) { // reset to original landscape + if (patchChgMatrix[y][x][0] != patchChgMatrix[y][x][2]) { + // record change of patch for current cell + chg.chgnum = 666666; chg.x = x; chg.y = y; + chg.oldpatch = patchChgMatrix[y][x][2]; + chg.newpatch = patchChgMatrix[y][x][0]; + patchchanges.push_back(chg); + } + } + else { // any other change + if (patchChgMatrix[y][x][2] != patchChgMatrix[y][x][1]) { + // record change of patch for current cell + chg.chgnum = landIx; chg.x = x; chg.y = y; + chg.oldpatch = patchChgMatrix[y][x][1]; + chg.newpatch = patchChgMatrix[y][x][2]; + patchchanges.push_back(chg); + } } + // reset cell for next landscape change + patchChgMatrix[y][x][1] = patchChgMatrix[y][x][2]; } - // reset cell for next landscape change - patchChgMatrix[y][x][1] = patchChgMatrix[y][x][2]; } -} } int Landscape::numPatchChanges(void) { return (int)patchchanges.size(); } patchChange Landscape::getPatchChange(int i) { -patchChange c; c.chgnum = 99999999; c.x = c.y = c.oldpatch = c.newpatch = -1; -if (i >= 0 && i < (int)patchchanges.size()) c = patchchanges[i]; -return c; + patchChange c; c.chgnum = 99999999; c.x = c.y = c.oldpatch = c.newpatch = -1; + if (i >= 0 && i < (int)patchchanges.size()) c = patchchanges[i]; + return c; } void Landscape::deletePatchChgMatrix(void) { -if (patchChgMatrix != 0) { - for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - delete[] patchChgMatrix[y][x]; + if (patchChgMatrix != 0) { + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + delete[] patchChgMatrix[y][x]; + } + delete[] patchChgMatrix[y]; } - delete[] patchChgMatrix[y]; } -} -patchChgMatrix = 0; + patchChgMatrix = 0; } // Create & initialise costs change matrix void Landscape::createCostsChgMatrix(void) { -//intptr patch; -//Patch *pPatch; -Cell *pCell; -if (costsChgMatrix != 0) deleteCostsChgMatrix(); -costsChgMatrix = new int **[dimY]; -for(int y = dimY-1; y >= 0; y--){ - costsChgMatrix[y] = new int *[dimX]; - for (int x = 0; x < dimX; x++) { - costsChgMatrix[y][x] = new int [3]; - pCell = findCell(x,y); - if (pCell == 0) { // no-data cell - costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = 0; - } - else { - // record initial cost - costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = pCell->getCost(); + Cell* pCell; + if (costsChgMatrix != 0) deleteCostsChgMatrix(); + costsChgMatrix = new int** [dimY]; + for (int y = dimY - 1; y >= 0; y--) { + costsChgMatrix[y] = new int* [dimX]; + for (int x = 0; x < dimX; x++) { + costsChgMatrix[y][x] = new int[3]; + pCell = findCell(x, y); + if (pCell == 0) { // no-data cell + costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = 0; + } + else { + // record initial cost + costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = pCell->getCost(); + } + costsChgMatrix[y][x][2] = 0; } - costsChgMatrix[y][x][2] = 0; -#if RSDEBUG -//DebugGUI(("Landscape::createCostsChgMatrix(): y=" + Int2Str(y) -// + " x=" + Int2Str(x) -// + " costsChgMatrix[y][x][0]=" + Int2Str(costsChgMatrix[y][x][0]) -// + " [1]=" + Int2Str(costsChgMatrix[y][x][1]) -// + " [2]=" + Int2Str(costsChgMatrix[y][x][2]) -// ).c_str()); -#endif } } -} void Landscape::recordCostChanges(int landIx) { #if RSDEBUG -DEBUGLOG << "Landscape::recordCostChanges(): landIx=" << landIx << endl; -#endif -if (costsChgMatrix == 0) return; // should not occur -costChange chg; - -for(int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - if (landIx == 0) { // reset to original landscape - if (costsChgMatrix[y][x][0] != costsChgMatrix[y][x][2]) { - // record change of cost for current cell - chg.chgnum = 666666; chg.x = x; chg.y = y; - chg.oldcost = costsChgMatrix[y][x][2]; - chg.newcost = costsChgMatrix[y][x][0]; - costschanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldcost=" + Int2Str(chg.oldcost) -// + " chg.newcost=" + Int2Str(chg.newcost) -// ).c_str()); + DEBUGLOG << "Landscape::recordCostChanges(): landIx=" << landIx << endl; #endif + if (costsChgMatrix == 0) return; // should not occur + costChange chg; + + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (landIx == 0) { // reset to original landscape + if (costsChgMatrix[y][x][0] != costsChgMatrix[y][x][2]) { + // record change of cost for current cell + chg.chgnum = 666666; chg.x = x; chg.y = y; + chg.oldcost = costsChgMatrix[y][x][2]; + chg.newcost = costsChgMatrix[y][x][0]; + costschanges.push_back(chg); + } } - } - else { // any other change -#if RSDEBUG -//if (x < 20 && y == 0) { -// DEBUGLOG << "Landscape::recordCostChanges(): x=" << x << " y=" << y -// << " costsChgMatrix[y][x][0]=" << costsChgMatrix[y][x][0] -// << " costsChgMatrix[y][x][1]=" << costsChgMatrix[y][x][1] -// << " costsChgMatrix[y][x][2]=" << costsChgMatrix[y][x][2] -// << endl; -//} -#endif - if (costsChgMatrix[y][x][2] != costsChgMatrix[y][x][1]) { - // record change of cost for current cell - chg.chgnum = landIx; chg.x = x; chg.y = y; - chg.oldcost = costsChgMatrix[y][x][1]; - chg.newcost = costsChgMatrix[y][x][2]; - costschanges.push_back(chg); -#if RSDEBUG -//DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) -// + " chg.chgnum=" + Int2Str(chg.chgnum) -// + " chg.x=" + Int2Str(chg.x) -// + " chg.y=" + Int2Str(chg.y) -// + " chg.oldcost=" + Int2Str(chg.oldcost) -// + " chg.newcost=" + Int2Str(chg.newcost) -// ).c_str()); -#endif + else { // any other change + if (costsChgMatrix[y][x][2] != costsChgMatrix[y][x][1]) { + // record change of cost for current cell + chg.chgnum = landIx; chg.x = x; chg.y = y; + chg.oldcost = costsChgMatrix[y][x][1]; + chg.newcost = costsChgMatrix[y][x][2]; + costschanges.push_back(chg); + } } + // reset cell for next landscape change + costsChgMatrix[y][x][1] = costsChgMatrix[y][x][2]; } - // reset cell for next landscape change - costsChgMatrix[y][x][1] = costsChgMatrix[y][x][2]; } -} } int Landscape::numCostChanges(void) { return (int)costschanges.size(); } costChange Landscape::getCostChange(int i) { -costChange c; c.chgnum = 99999999; c.x = c.y = c.oldcost = c.newcost = -1; -if (i >= 0 && i < (int)costschanges.size()) c = costschanges[i]; -return c; + costChange c; c.chgnum = 99999999; c.x = c.y = c.oldcost = c.newcost = -1; + if (i >= 0 && i < (int)costschanges.size()) c = costschanges[i]; + return c; } void Landscape::deleteCostsChgMatrix(void) { -if (costsChgMatrix != 0) { - for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - delete[] costsChgMatrix[y][x]; + if (costsChgMatrix != 0) { + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + delete[] costsChgMatrix[y][x]; + } + delete[] costsChgMatrix[y]; } - delete[] costsChgMatrix[y]; } -} -costsChgMatrix = 0; + costsChgMatrix = 0; } //--------------------------------------------------------------------------- // Species distribution functions -int Landscape::newDistribution(Species *pSpecies, string distname) { -int readcode; -int ndistns = (int)distns.size(); -distns.push_back(new InitDist(pSpecies)); -readcode = distns[ndistns]->readDistribution(distname); -if (readcode != 0) { // error encountered - // delete the distribution created above - delete distns[ndistns]; - distns.pop_back(); -} -return readcode; +int Landscape::newDistribution(Species* pSpecies, string distname) { + int readcode; + int ndistns = (int)distns.size(); + distns.push_back(new InitDist(pSpecies)); + readcode = distns[ndistns]->readDistribution(distname); + if (readcode != 0) { // error encountered + // delete the distribution created above + delete distns[ndistns]; + distns.pop_back(); + } + return readcode; } -void Landscape::setDistribution(Species *pSpecies,int nInit) { -// WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... -// ... CURRENTLY IT IS THE ONLY ONE -distns[0]->setDistribution(nInit); +void Landscape::setDistribution(Species* pSpecies, int nInit) { + // WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... + // ... CURRENTLY IT IS THE ONLY ONE + distns[0]->setDistribution(nInit); } // Specified cell match one of the distribution cells to be initialised? -bool Landscape::inInitialDist(Species *pSpecies,locn loc) { -// convert landscape co-ordinates to distribution co-ordinates -locn initloc; -initloc.x = loc.x * resol / spResol; -initloc.y = loc.y * resol / spResol; -// WILL HAVE TO GET CORRECT SPECIES WHEN THERE ARE MULTIPLE SPECIES ... -bool initialise = distns[0]->inInitialDist(initloc); -return initialise; +bool Landscape::inInitialDist(Species* pSpecies, locn loc) { + // convert landscape co-ordinates to distribution co-ordinates + locn initloc; + initloc.x = loc.x * resol / spResol; + initloc.y = loc.y * resol / spResol; + // WILL HAVE TO GET CORRECT SPECIES WHEN THERE ARE MULTIPLE SPECIES ... + bool initialise = distns[0]->inInitialDist(initloc); + return initialise; } -void Landscape::deleteDistribution(Species *pSpecies) { -// WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... -// ... CURRENTLY IT IS THE ONLY ONE ... -// ... FOR MULTIPLE SPECIES IT MAY BE BETTER TO USE A DYNAMIC ARRAY FOR -// SPECIES DISTRIBUTIONS INDEXED BY SPECIES NUMBER, RATHER THAN A VECTOR -if (distns[0] != 0) delete distns[0]; distns.clear(); +void Landscape::deleteDistribution(Species* pSpecies) { + // WILL NEED TO SELECT DISTRIBUTION FOR CORRECT SPECIES ... + // ... CURRENTLY IT IS THE ONLY ONE ... + // ... FOR MULTIPLE SPECIES IT MAY BE BETTER TO USE A DYNAMIC ARRAY FOR + // SPECIES DISTRIBUTIONS INDEXED BY SPECIES NUMBER, RATHER THAN A VECTOR + if (distns[0] != 0) delete distns[0]; distns.clear(); } // Return no. of initial distributions int Landscape::distnCount(void) { -return (int)distns.size(); + return (int)distns.size(); } int Landscape::distCellCount(int dist) { -return distns[dist]->cellCount(); + return distns[dist]->cellCount(); } // Set a cell in a specified initial distribution (by position in cells vector) -void Landscape::setDistnCell(int dist,int ix,bool init) { -distns[dist]->setDistCell(ix,init); +void Landscape::setDistnCell(int dist, int ix, bool init) { + distns[dist]->setDistCell(ix, init); } // Set a cell in a specified initial distribution (by given co-ordinates) -void Landscape::setDistnCell(int dist,locn loc,bool init) { -distns[dist]->setDistCell(loc,init); +void Landscape::setDistnCell(int dist, locn loc, bool init) { + distns[dist]->setDistCell(loc, init); } // Get the co-ordinates of a specified cell in a specified initial distribution -locn Landscape::getDistnCell(int dist,int ix) { -return distns[dist]->getCell(ix); +locn Landscape::getDistnCell(int dist, int ix) { + return distns[dist]->getCell(ix); } // Get the co-ordinates of a specified cell in a specified initial distribution // Returns negative co-ordinates if the cell is not selected -locn Landscape::getSelectedDistnCell(int dist,int ix) { -return distns[dist]->getSelectedCell(ix); +locn Landscape::getSelectedDistnCell(int dist, int ix) { + return distns[dist]->getSelectedCell(ix); } // Get the dimensions of a specified initial distribution locn Landscape::getDistnDimensions(int dist) { -return distns[dist]->getDimensions(); + return distns[dist]->getDimensions(); } // Reset the distribution for a given species so that all cells are deselected -void Landscape::resetDistribution(Species *pSp) { -// CURRENTLY WORKS FOR FIRST SPECIES ONLY ... -distns[0]->resetDistribution(); +void Landscape::resetDistribution(Species* pSp) { + // CURRENTLY WORKS FOR FIRST SPECIES ONLY ... + distns[0]->resetDistribution(); } //--------------------------------------------------------------------------- @@ -2011,23 +1709,23 @@ distns[0]->resetDistribution(); // Initialisation cell functions int Landscape::initCellCount(void) { -return (int)initcells.size(); + return (int)initcells.size(); } -void Landscape::addInitCell(int x,int y) { -initcells.push_back(new DistCell(x,y)); +void Landscape::addInitCell(int x, int y) { + initcells.push_back(new DistCell(x, y)); } locn Landscape::getInitCell(int ix) { -return initcells[ix]->getLocn(); + return initcells[ix]->getLocn(); } void Landscape::clearInitCells(void) { -int ncells = (int)initcells.size(); -for (int i = 0; i < ncells; i++) { - delete initcells[i]; -} -initcells.clear(); + int ncells = (int)initcells.size(); + for (int i = 0; i < ncells; i++) { + delete initcells[i]; + } + initcells.clear(); } //--------------------------------------------------------------------------- @@ -2035,24 +1733,24 @@ initcells.clear(); // Read landscape file(s) // Returns error code or zero if read correctly -int Landscape::readLandscape(int fileNum,string habfile,string pchfile,string costfile) +int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string costfile) { -// fileNum == 0 for (first) habitat file and optional patch file -// fileNum > 0 for subsequent habitat files under the %cover option + // fileNum == 0 for (first) habitat file and optional patch file + // fileNum > 0 for subsequent habitat files under the %cover option #if RS_RCPP -wstring header; + wstring header; #else -string header; + string header; #endif -int h,seq,p,habnodata; -int pchnodata = 0; -int ncols,nrows; -float hfloat,pfloat; -Patch *pPatch; -simParams sim = paramsSim->getSim(); + int h, seq, p, habnodata; + int pchnodata = 0; + int ncols, nrows; + float hfloat, pfloat; + Patch* pPatch; + simParams sim = paramsSim->getSim(); -if (fileNum < 0) return 19; + if (fileNum < 0) return 19; #if RS_RCPP wifstream hfile; // habitat file input stream @@ -2061,41 +1759,41 @@ if (fileNum < 0) return 19; ifstream hfile; // habitat file input stream ifstream pfile; // patch file input stream #endif -initParams init = paramsInit->getInit(); + initParams init = paramsInit->getInit(); -// open habitat file and optionally also patch file + // open habitat file and optionally also patch file #if !RS_RCPP || RSWIN64 -hfile.open(habfile.c_str()); + hfile.open(habfile.c_str()); #else -hfile.open(habfile, std::ios::binary); -if(landraster.utf) { - // apply BOM-sensitive UTF-16 facet - hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); -} + hfile.open(habfile, std::ios::binary); + if (landraster.utf) { + // apply BOM-sensitive UTF-16 facet + hfile.imbue(std::locale(hfile.getloc(), new std::codecvt_utf16)); + } #endif -if (!hfile.is_open()) return 11; -if (fileNum == 0) { - if (patchModel) { + if (!hfile.is_open()) return 11; + if (fileNum == 0) { + if (patchModel) { #if !RS_RCPP || RSWIN64 - pfile.open(pchfile.c_str()); + pfile.open(pchfile.c_str()); #else - pfile.open(pchfile, std::ios::binary); - if(patchraster.utf) { - // apply BOM-sensitive UTF-16 facet - pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); - } + pfile.open(pchfile, std::ios::binary); + if (patchraster.utf) { + // apply BOM-sensitive UTF-16 facet + pfile.imbue(std::locale(pfile.getloc(), new std::codecvt_utf16)); + } #endif - if (!pfile.is_open()) { - hfile.close(); hfile.clear(); - return 12; + if (!pfile.is_open()) { + hfile.close(); hfile.clear(); + return 12; + } } } -} -// read landscape data from header records of habitat file -// NB headers of all files have already been compared -hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth - >> header >> resol >> header >> habnodata; + // read landscape data from header records of habitat file + // NB headers of all files have already been compared + hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> minNorth + >> header >> resol >> header >> habnodata; #if RS_RCPP if (!hfile.good()) { @@ -2111,70 +1809,71 @@ hfile >> header >> ncols >> header >> nrows >> header >> minEast >> header >> mi } #endif -dimX = ncols; dimY = nrows; minX = maxY = 0; maxX = dimX-1; maxY = dimY-1; -if (fileNum == 0) { - // set initialisation limits to landscape limits - init.minSeedX = init.minSeedY = 0; - init.maxSeedX = maxX; init.maxSeedY = maxY; - paramsInit->setInit(init); -} - -if (fileNum == 0) { - if (patchModel) { - for (int i = 0; i < 5; i++) pfile >> header >> pfloat; - pfile >> header >> pchnodata; + dimX = ncols; dimY = nrows; minX = maxY = 0; maxX = dimX - 1; maxY = dimY - 1; + if (fileNum == 0) { + // set initialisation limits to landscape limits + init.minSeedX = init.minSeedY = 0; + init.maxSeedX = maxX; init.maxSeedY = maxY; + paramsInit->setInit(init); } + + if (fileNum == 0) { + if (patchModel) { + for (int i = 0; i < 5; i++) pfile >> header >> pfloat; + pfile >> header >> pchnodata; + } #if RS_RCPP - if (!pfile.good()) { - // corrupt file stream - StreamErrorR(pchfile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; - } + if (!pfile.good()) { + // corrupt file stream + StreamErrorR(pchfile); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 135; + } #endif - setCellArray(); -} + setCellArray(); + } -// set up bad float values to ensure that valid values are read -float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; -float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; + // set up bad float values to ensure that valid values are read + float badhfloat = -9.0; if (habnodata == -9) badhfloat = -99.0; + float badpfloat = -9.0; if (pchnodata == -9) badpfloat = -99.0; -seq = 0; // initial sequential patch landscape -p = 0; // initial patch number for cell-based landscape -// create patch 0 - the matrix patch (even if there is no matrix) -if (fileNum == 0) newPatch(seq++,p++); + seq = 0; // initial sequential patch landscape + p = 0; // initial patch number for cell-based landscape + // create patch 0 - the matrix patch (even if there is no matrix) + if (fileNum == 0) newPatch(seq++, p++); -switch (rasterType) { + switch (rasterType) { -case 0: // raster with habitat codes - 100% habitat each cell - if (fileNum > 0) return 19; // error condition - should not occur - for (int y = dimY-1; y >= 0; y--) { - for (int x = 0; x < dimX; x++) { - hfloat = badhfloat; + case 0: // raster with habitat codes - 100% habitat each cell + if (fileNum > 0) return 19; // error condition - should not occur + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else - hfile >> hfloat; + hfile >> hfloat; #endif - h = (int)hfloat; - if (patchModel) { - pfloat = badpfloat; + h = (int)hfloat; + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif p = (int)pfloat; #if RS_RCPP - } else { + } + else { // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif StreamErrorR(pchfile); hfile.close(); hfile.clear(); @@ -2183,100 +1882,95 @@ case 0: // raster with habitat codes - 100% habitat each cell return 132; } #endif - } + } #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(habfile); - hfile.close(); - hfile.clear(); - if (patchModel) { - pfile.close(); - pfile.clear(); } - return 135; + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(habfile); + hfile.close(); + hfile.clear(); + if (patchModel) { + pfile.close(); + pfile.clear(); } + return 135; + } #endif + if (h == habnodata) + addNewCellToLand(x, y, -1); // add cell only to landscape + else { -#if RSDEBUG -//DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) -// + " h=" + Int2Str(h) + " p=" + Int2Str(p) -//).c_str()); + // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT + // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) + // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... + + if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { + // invalid habitat code +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat code." << std::endl; #endif - if (h == habnodata) - addNewCellToLand(x,y,-1); // add cell only to landscape + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); + } + return 13; + } else { - - // THERE IS AN ANOMALY HERE - CURRENTLY HABITAT 0 IS OK FOR GUI VERSION BUT - // NOT ALLOWED FOR BATCH VERSION (HABITATS MUST BE 1...n) - // SHOULD WE MAKE THE TWO VERSIONS AGREE? ... - - if (h < 0 || (sim.batchMode && (h < 1 || h > nHabMax))) { - // invalid habitat code - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat code." << std::endl; - #endif - hfile.close(); hfile.clear(); - if (patchModel) { + addHabCode(h); + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif + hfile.close(); hfile.clear(); pfile.close(); pfile.clear(); + return 14; } - return 13; - } - else { - addHabCode(h); - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0,x,y,h); + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, h); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, h); + // addNewCellToPatch(findPatch(p),x,y,h); } else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch,x,y,h); -// addNewCellToPatch(findPatch(p),x,y,h); - } - else { - pPatch = newPatch(seq++,p); - addNewCellToPatch(pPatch,x,y,h); - } + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, h); } } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x,y,h); - } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, h); } } } - } + } + } #if RS_RCPP - hfile >> hfloat; - if (!hfile.eof()) EOFerrorR(habfile); - if (patchModel) - { - pfile >> pfloat; - if (!pfile.eof()) EOFerrorR(pchfile); - } +hfile >> hfloat; +if (!hfile.eof()) EOFerrorR(habfile); +if (patchModel) +{ + pfile >> pfloat; + if (!pfile.eof()) EOFerrorR(pchfile); +} #endif - break; +break; case 1: // multiple % cover - for (int y = dimY-1; y >= 0; y--) { + for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else hfile >> hfloat; #endif @@ -2285,110 +1979,107 @@ case 1: // multiple % cover if (patchModel) { pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else pfile >> pfloat; #endif p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(pchfile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(pchfile); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 135; + } #endif } //end if patchmodel - -#if RSDEBUG -//MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) -// + " p=" + Int2Str(p)).c_str()); + if (h == habnodata) { + addNewCellToLand(x, y, -1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; #endif - if (h == habnodata) { - addNewCellToLand(x,y,-1); // add cell only to landscape + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); + } + return 17; } else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; - #endif - hfile.close(); hfile.clear(); - if (patchModel) { + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif + hfile.close(); hfile.clear(); pfile.close(); pfile.clear(); + return 14; } - return 17; - } - else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0,x,y,hfloat); + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, hfloat); + } + else { + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, hfloat); + // addNewCellToPatch(findPatch(p),x,y,hfloat); } else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch,x,y,hfloat); -// addNewCellToPatch(findPatch(p),x,y,hfloat); - } - else { - pPatch = newPatch(seq++,p); - addNewCellToPatch(pPatch,x,y,hfloat); - } + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, hfloat); } } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x,y,hfloat); - } + } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, hfloat); } } } - else { // additional habitat cover layers - if (h != habnodata) { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; - #endif - hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; - } - else { - cells[y][x]->setHabitat(hfloat); - } - } // end of h != habnodata } -#if RS_RCPP - } else { // couldn't read from hfile - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(habfile); - hfile.close(); - hfile.clear(); +else { // additional habitat cover layers + if (h != habnodata) { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid cover score +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat cover score." << std::endl; +#endif + hfile.close(); hfile.clear(); if (patchModel) { - pfile.close(); - pfile.clear(); + pfile.close(); pfile.clear(); } - return 133; + return 17; + } + else { + cells[y][x]->setHabitat(hfloat); } + } // end of h != habnodata +} +#if RS_RCPP + } +else { // couldn't read from hfile + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; +#endif + StreamErrorR(habfile); + hfile.close(); + hfile.clear(); + if (patchModel) { + pfile.close(); + pfile.clear(); + } + return 133; +} #endif } @@ -2407,105 +2098,103 @@ case 1: // multiple % cover case 2: // habitat quality if (fileNum > 0) return 19; // error condition - should not occur - for (int y = dimY-1; y >= 0; y--) { + for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { hfloat = badhfloat; #if RS_RCPP - if(hfile >> hfloat) { + if (hfile >> hfloat) { #else hfile >> hfloat; #endif h = (int)hfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(habfile); - hfile.close(); - hfile.clear(); - if (patchModel) { - pfile.close(); - pfile.clear(); - } - return 134; } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - if (patchModel) { - pfloat = badpfloat; + StreamErrorR(habfile); + hfile.close(); + hfile.clear(); + if (patchModel) { + pfile.close(); + pfile.clear(); + } + return 134; + } +#endif + if (patchModel) { + pfloat = badpfloat; #if RS_RCPP - if(pfile >> pfloat) { + if (pfile >> pfloat) { #else - pfile >> pfloat; + pfile >> pfloat; #endif - p = (int)pfloat; + p = (int)pfloat; #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(pchfile); - hfile.close(); - hfile.clear(); - pfile.close(); - pfile.clear(); - return 135; - } + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif - } -#if RSDEBUG -//MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) -// + " p=" + Int2Str(p)).c_str()); + StreamErrorR(pchfile); + hfile.close(); + hfile.clear(); + pfile.close(); + pfile.clear(); + return 135; + } #endif - if (h == habnodata) { - addNewCellToLand(x,y,-1); // add cell only to landscape + } + if (h == habnodata) { + addNewCellToLand(x, y, -1); // add cell only to landscape + } + else { + if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; +#endif + hfile.close(); hfile.clear(); + if (patchModel) { + pfile.close(); pfile.clear(); } - else { - if (hfloat < 0.0 || hfloat > 100.0) { // invalid quality score - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Found invalid habitat quality score." << std::endl; - #endif + return 17; + } + else { + if (patchModel) { + if (p < 0 || p == pchnodata) { // invalid patch code +#if RS_RCPP && !R_CMD + if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; + else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; +#endif hfile.close(); hfile.clear(); - if (patchModel) { - pfile.close(); pfile.clear(); - } - return 17; + pfile.close(); pfile.clear(); + return 14; + } + if (p == 0) { // cell is in the matrix + addNewCellToPatch(0, x, y, hfloat); } else { - if (patchModel) { - if (p < 0 || p == pchnodata) { // invalid patch code - #if RS_RCPP && !R_CMD - if (p == pchnodata) Rcpp::Rcout << "Found patch NA in valid habitat cell." << std::endl; - else Rcpp::Rcout << "Found negative patch ID in valid habitat cell." << std::endl; - #endif - hfile.close(); hfile.clear(); - pfile.close(); pfile.clear(); - return 14; - } - if (p == 0) { // cell is in the matrix - addNewCellToPatch(0,x,y,hfloat); - } - else { - if (existsPatch(p)) { - pPatch = findPatch(p); - addNewCellToPatch(pPatch,x,y,hfloat); -// addNewCellToPatch(findPatch(p),x,y,hfloat); - } - else { - addPatchNum(p); - pPatch = newPatch(seq++,p); - addNewCellToPatch(pPatch,x,y,hfloat); - } - } + if (existsPatch(p)) { + pPatch = findPatch(p); + addNewCellToPatch(pPatch, x, y, hfloat); + // addNewCellToPatch(findPatch(p),x,y,hfloat); } - else { // cell-based model - // add cell to landscape (patches created later) - addNewCellToLand(x,y,hfloat); + else { + addPatchNum(p); + pPatch = newPatch(seq++, p); + addNewCellToPatch(pPatch, x, y, hfloat); } } } + else { // cell-based model + // add cell to landscape (patches created later) + addNewCellToLand(x, y, hfloat); + } + } + } } } #if RS_RCPP @@ -2521,19 +2210,19 @@ case 2: // habitat quality default: break; -} // end switch(rasterType) + } // end switch(rasterType) -if (hfile.is_open()) { hfile.close(); hfile.clear(); } -if (pfile.is_open()) { pfile.close(); pfile.clear(); } + if (hfile.is_open()) { hfile.close(); hfile.clear(); } + if (pfile.is_open()) { pfile.close(); pfile.clear(); } -if (sim.batchMode) { - if (costfile != "NULL") { - int retcode = readCosts(costfile); - if (retcode < 0) return 54; + if (sim.batchMode) { + if (costfile != "NULL") { + int retcode = readCosts(costfile); + if (retcode < 0) return 54; + } } -} -return 0; + return 0; } @@ -2552,47 +2241,34 @@ int Landscape::readCosts(string fname) ifstream costs; // cost map file input stream #endif -//int hc,maxYcost,maxXcost,NODATACost,hab; -int hc,maxYcost,maxXcost,NODATACost; -float minLongCost, minLatCost; int resolCost; -float fcost; + //int hc,maxYcost,maxXcost,NODATACost,hab; + int hc, maxYcost, maxXcost, NODATACost; + float minLongCost, minLatCost; int resolCost; + float fcost; #if RS_RCPP -wstring header; + wstring header; #else -string header; + string header; #endif -Cell *pCell; + Cell* pCell; #if !RS_RCPP -simView v = paramsSim->getViews(); + simView v = paramsSim->getViews(); #endif -int maxcost = 0; + int maxcost = 0; -#if RSDEBUG -#if BATCH -//DEBUGLOG << "Landscape::readCosts(): fname=" << fname << endl; -#endif -#endif // open cost file #if !RS_RCPP || RSWIN64 costs.open(fname.c_str()); #else costs.open(fname, std::ios::binary); - if(costsraster.utf) { + if (costsraster.utf) { // apply BOM-sensitive UTF-16 facet costs.imbue(std::locale(costs.getloc(), new std::codecvt_utf16)); } #endif -//if (!costs.is_open()) { -// MessageDlg("COSTS IS NOT OPEN!!!!!", -// mtError, TMsgDlgButtons() << mbRetry,0); -//} -//else { -// MessageDlg("Costs is open!", -// mtError, TMsgDlgButtons() << mbRetry,0); -//} -// read headers and check that they correspond to the landscape ones -costs >> header; + // read headers and check that they correspond to the landscape ones + costs >> header; #if RS_RCPP if (!costs.good()) { // corrupt file stream @@ -2605,73 +2281,62 @@ costs >> header; #else if (header != "ncols" && header != "NCOLS") { #endif -// MessageDlg("The selected file is not a raster.", -// MessageDlg("Header problem in import_CostsLand()", -// mtError, TMsgDlgButtons() << mbRetry,0); - costs.close(); costs.clear(); - return -1; -} -costs >> maxXcost >> header >> maxYcost >> header >> minLongCost; -costs >> header >> minLatCost >> header >> resolCost >> header >> NODATACost; + costs.close(); costs.clear(); + return -1; + } + costs >> maxXcost >> header >> maxYcost >> header >> minLongCost; + costs >> header >> minLatCost >> header >> resolCost >> header >> NODATACost; #if !RS_RCPP -MemoLine("Loading costs map. Please wait..."); + MemoLine("Loading costs map. Please wait..."); #endif -for (int y = maxYcost - 1; y > -1; y--){ - for (int x = 0; x < maxXcost; x++){ + for (int y = maxYcost - 1; y > -1; y--) { + for (int x = 0; x < maxXcost; x++) { #if RS_RCPP - if(costs >> fcost) { + if (costs >> fcost) { #else - costs >> fcost; + costs >> fcost; #endif - hc = (int)fcost; // read as float and convert to int + hc = (int)fcost; // read as float and convert to int #if RS_RCPP - } else { - // corrupt file stream - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; - #endif - StreamErrorR(fname); - costs.close(); - costs.clear(); - return -181; - } -#endif - if ( hc < 1 && hc != NODATACost ) { -#if RSDEBUG -#if BATCH -// DEBUGLOG << "Landscape::readCosts(): x=" << x << " y=" << y -// << " fcost=" << fcost << " hc=" << hc -// << endl; + } + else { + // corrupt file stream +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "At (x,y) = " << x << "," << y << " :" << std::endl; #endif + StreamErrorR(fname); + costs.close(); + costs.clear(); + return -181; + } #endif + if (hc < 1 && hc != NODATACost) { #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Cost map my only contain values of 1 or higher, but found " << fcost << "." << endl; + Rcpp::Rcout << "Cost map my only contain values of 1 or higher, but found " << fcost << "." << endl; #endif - // error - zero / negative cost not allowed -// MessageDlg("Error in the costs map file : zero or negative cost detected." -// , mtError, TMsgDlgButtons() << mbOK,0); - costs.close(); costs.clear(); - return -999; - } - pCell = findCell(x,y); - if (pCell != 0) { // not no-data cell - pCell->setCost(hc); - if (hc > maxcost) maxcost = hc; + // error - zero / negative cost not allowed + costs.close(); costs.clear(); + return -999; + } + pCell = findCell(x, y); + if (pCell != 0) { // not no-data cell + pCell->setCost(hc); + if (hc > maxcost) maxcost = hc; + } } } -} #if RS_RCPP - costs >> fcost; - if (costs.eof()) { - #if RS_RCPP && !R_CMD - Rcpp::Rcout << "Costs map loaded." << endl; - #endif - } - else EOFerrorR(fname); +costs >> fcost; +if (costs.eof()) { +#if RS_RCPP && !R_CMD + Rcpp::Rcout << "Costs map loaded." << endl; +#endif +} +else EOFerrorR(fname); #else - MemoLine("Costs map loaded."); +MemoLine("Costs map loaded."); #endif costs.close(); costs.clear(); @@ -2684,63 +2349,63 @@ return maxcost; rasterdata CheckRasterFile(string fname) { -rasterdata r; -string header; -int inint; -ifstream infile; - -r.ok = true; -r.errors = r.ncols = r.nrows = r.cellsize = 0; -r.xllcorner = r.yllcorner = 0.0; - -infile.open(fname.c_str()); -if (infile.is_open()) { - infile >> header >> r.ncols; + rasterdata r; + string header; + int inint; + ifstream infile; + + r.ok = true; + r.errors = r.ncols = r.nrows = r.cellsize = 0; + r.xllcorner = r.yllcorner = 0.0; + + infile.open(fname.c_str()); + if (infile.is_open()) { + infile >> header >> r.ncols; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.ncols=" + Int2Str(r.ncols) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.ncols=" + Int2Str(r.ncols) + ).c_str()); #endif - if (header != "ncols" && header != "NCOLS") r.errors++; - infile >> header >> r.nrows; + if (header != "ncols" && header != "NCOLS") r.errors++; + infile >> header >> r.nrows; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.nrows=" + Int2Str(r.nrows) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.nrows=" + Int2Str(r.nrows) + ).c_str()); #endif - if (header != "nrows" && header != "NROWS") r.errors++; - infile >> header >> r.xllcorner; + if (header != "nrows" && header != "NROWS") r.errors++; + infile >> header >> r.xllcorner; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.xllcorner=" + Float2Str(r.xllcorner) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.xllcorner=" + Float2Str(r.xllcorner) + ).c_str()); #endif - if (header != "xllcorner" && header != "XLLCORNER") r.errors++; - infile >> header >> r.yllcorner; + if (header != "xllcorner" && header != "XLLCORNER") r.errors++; + infile >> header >> r.yllcorner; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.yllcorner=" + Float2Str(r.yllcorner) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.yllcorner=" + Float2Str(r.yllcorner) + ).c_str()); #endif - if (header != "yllcorner" && header != "YLLCORNER") r.errors++; - infile >> header >> r.cellsize; + if (header != "yllcorner" && header != "YLLCORNER") r.errors++; + infile >> header >> r.cellsize; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " r.cellsize=" + Int2Str(r.cellsize) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " r.cellsize=" + Int2Str(r.cellsize) + ).c_str()); #endif - if (header != "cellsize" && header != "CELLSIZE") r.errors++; - infile >> header >> inint; + if (header != "cellsize" && header != "CELLSIZE") r.errors++; + infile >> header >> inint; #if RSDEBUG -DebugGUI(("CheckRasterFile(): header=" + header + " inint=" + Int2Str(inint) - ).c_str()); + DebugGUI(("CheckRasterFile(): header=" + header + " inint=" + Int2Str(inint) + ).c_str()); #endif - if (header != "NODATA_value" && header != "NODATA_VALUE") r.errors++; - infile.close(); + if (header != "NODATA_value" && header != "NODATA_VALUE") r.errors++; + infile.close(); + infile.clear(); + if (r.errors > 0) r.ok = false; + } + else { + r.ok = false; r.errors = -111; + } infile.clear(); - if (r.errors > 0) r.ok = false; -} -else { - r.ok = false; r.errors = -111; -} -infile.clear(); -return r; + return r; } //--------------------------------------------------------------------------- @@ -2750,74 +2415,74 @@ return r; // Create & initialise connectivity matrix void Landscape::createConnectMatrix(void) { -if (connectMatrix != 0) deleteConnectMatrix(); -int npatches = (int)patches.size(); + if (connectMatrix != 0) deleteConnectMatrix(); + int npatches = (int)patches.size(); #if RSDEBUG -//DEBUGLOG << "Landscape::createConnectMatrix(): npatches=" << npatches << endl; + //DEBUGLOG << "Landscape::createConnectMatrix(): npatches=" << npatches << endl; #endif -connectMatrix = new int *[npatches]; -for (int i = 0; i < npatches; i++) { - connectMatrix[i] = new int[npatches]; - for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; -} + connectMatrix = new int* [npatches]; + for (int i = 0; i < npatches; i++) { + connectMatrix[i] = new int[npatches]; + for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; + } } // Re-initialise connectivity matrix void Landscape::resetConnectMatrix(void) { -if (connectMatrix != 0) { - int npatches = (int)patches.size(); - for (int i = 0; i < npatches; i++) { - for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; + if (connectMatrix != 0) { + int npatches = (int)patches.size(); + for (int i = 0; i < npatches; i++) { + for (int j = 0; j < npatches; j++) connectMatrix[i][j] = 0; + } } } -} // Increment connectivity count between two specified patches -void Landscape::incrConnectMatrix(int p0,int p1) { -int npatches = (int)patches.size(); -if (connectMatrix == 0 || p0 < 0 || p0 >= npatches || p1 < 0 || p1 >= npatches) return; -connectMatrix[p0][p1]++; +void Landscape::incrConnectMatrix(int p0, int p1) { + int npatches = (int)patches.size(); + if (connectMatrix == 0 || p0 < 0 || p0 >= npatches || p1 < 0 || p1 >= npatches) return; + connectMatrix[p0][p1]++; } // Delete connectivity matrix void Landscape::deleteConnectMatrix(void) { -if (connectMatrix != 0) { - int npatches = (int)patches.size(); - for (int j = 0; j < npatches; j++) { - if (connectMatrix[j] != 0) - delete connectMatrix[j]; + if (connectMatrix != 0) { + int npatches = (int)patches.size(); + for (int j = 0; j < npatches; j++) { + if (connectMatrix[j] != 0) + delete connectMatrix[j]; + } + delete[] connectMatrix; + connectMatrix = 0; } - delete[] connectMatrix; - connectMatrix = 0; -} } // Write connectivity file headers bool Landscape::outConnectHeaders(int option) { -if (option == -999) { // close the file - if (outConnMat.is_open()) outConnMat.close(); - outConnMat.clear(); - return true; -} + if (option == -999) { // close the file + if (outConnMat.is_open()) outConnMat.close(); + outConnMat.clear(); + return true; + } -simParams sim = paramsSim->getSim(); + simParams sim = paramsSim->getSim(); -string name = paramsSim->getDir(2); -if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNum); -} -else - name += "Sim" + Int2Str(sim.simulation); -name += "_Connect.txt"; -outConnMat.open(name.c_str()); + string name = paramsSim->getDir(2); + if (sim.batchMode) { + name += "Batch" + Int2Str(sim.batchNum) + "_"; + name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNum); + } + else + name += "Sim" + Int2Str(sim.simulation); + name += "_Connect.txt"; + outConnMat.open(name.c_str()); -outConnMat << "Rep\tYear\tStartPatch\tEndPatch\tNinds" << endl; + outConnMat << "Rep\tYear\tStartPatch\tEndPatch\tNinds" << endl; -return outConnMat.is_open(); + return outConnMat.is_open(); } #if RS_RCPP @@ -2834,140 +2499,136 @@ void Landscape::outPathsHeaders(int rep, int option) string name = paramsSim->getDir(2); if (sim.batchMode) { name += "Batch" + Int2Str(sim.batchNum) - + "_Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNum) - + "_Rep" + Int2Str(rep); - } else { + + "_Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNum) + + "_Rep" + Int2Str(rep); + } + else { name += "Sim" + Int2Str(sim.simulation) - + "_Rep" + Int2Str(rep); + + "_Rep" + Int2Str(rep); } name += "_MovePaths.txt"; outMovePaths.open(name.c_str()); - if( outMovePaths.is_open() ){ + if (outMovePaths.is_open()) { outMovePaths << "Year\tIndID\tStep\tx\ty\tStatus" << endl; - }else{ - #if RSDEBUG + } + else { +#if RSDEBUG DEBUGLOG << "RunModel(): UNABLE TO OPEN MOVEMENT PATHS FILE" << endl; - #endif +#endif outMovePaths.clear(); } } } #endif -void Landscape::outConnect(int rep,int yr) +void Landscape::outConnect(int rep, int yr) { -int patchnum0,patchnum1; -int npatches = (int)patches.size(); -int *emigrants = new int[npatches]; // 1D array to hold emigrants from each patch -int *immigrants = new int[npatches]; // 1D array to hold immigrants to each patch + int patchnum0, patchnum1; + int npatches = (int)patches.size(); + int* emigrants = new int[npatches]; // 1D array to hold emigrants from each patch + int* immigrants = new int[npatches]; // 1D array to hold immigrants to each patch -for (int i = 0; i < npatches; i++) { - emigrants[i] = immigrants[i] = 0; -} + for (int i = 0; i < npatches; i++) { + emigrants[i] = immigrants[i] = 0; + } -for (int i = 0; i < npatches; i++) { - patchnum0 = patches[i]->getPatchNum(); - if (patchnum0 != 0) { - for (int j = 0; j < npatches; j++) { - patchnum1 = patches[j]->getPatchNum(); - if (patchnum1 != 0) { - emigrants[i] += connectMatrix[i][j]; - immigrants[j] += connectMatrix[i][j]; - if (connectMatrix[i][j] > 0) { - outConnMat << rep << "\t" << yr - << "\t" << patchnum0 << "\t" << patchnum1 - << "\t" << connectMatrix[i][j] << endl; + for (int i = 0; i < npatches; i++) { + patchnum0 = patches[i]->getPatchNum(); + if (patchnum0 != 0) { + for (int j = 0; j < npatches; j++) { + patchnum1 = patches[j]->getPatchNum(); + if (patchnum1 != 0) { + emigrants[i] += connectMatrix[i][j]; + immigrants[j] += connectMatrix[i][j]; + if (connectMatrix[i][j] > 0) { + outConnMat << rep << "\t" << yr + << "\t" << patchnum0 << "\t" << patchnum1 + << "\t" << connectMatrix[i][j] << endl; + } } } } } -} -for (int i = 0; i < npatches; i++) { - patchnum0 = patches[i]->getPatchNum(); - if (patchnum0 != 0) { - if (patches[i]->getK() > 0.0) - { // suitable patch - outConnMat << rep << "\t" << yr - << "\t" << patchnum0 << "\t-999\t" << emigrants[i] << endl; - outConnMat << rep << "\t" << yr - << "\t-999\t" << patchnum0 << "\t" << immigrants[i] << endl; + for (int i = 0; i < npatches; i++) { + patchnum0 = patches[i]->getPatchNum(); + if (patchnum0 != 0) { + if (patches[i]->getK() > 0.0) + { // suitable patch + outConnMat << rep << "\t" << yr + << "\t" << patchnum0 << "\t-999\t" << emigrants[i] << endl; + outConnMat << rep << "\t" << yr + << "\t-999\t" << patchnum0 << "\t" << immigrants[i] << endl; + } } } -} -delete[] emigrants; -delete[] immigrants; + delete[] emigrants; + delete[] immigrants; } //--------------------------------------------------------------------------- void Landscape::resetVisits(void) { -for(int y = dimY-1; y >= 0; y--){ - for (int x = 0; x < dimX; x++) { - if (cells[y][x] != 0) { // not a no-data cell - cells[y][x]->resetVisits(); + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] != 0) { // not a no-data cell + cells[y][x]->resetVisits(); + } } } } -} // Save SMS path visits map to raster text file void Landscape::outVisits(int rep, int landNr) { -string name; -simParams sim = paramsSim->getSim(); + string name; + simParams sim = paramsSim->getSim(); -if (sim.batchMode) { - name = paramsSim->getDir(3) + if (sim.batchMode) { + name = paramsSim->getDir(3) #if RS_RCPP - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_Land" + Int2Str(landNr) + "_Rep" + Int2Str(rep) #else - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) - + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) -#endif -// + "_yr" + Int2Str(yr) - + "_Visits.txt"; -} -else { - name = paramsSim->getDir(3) - + "Sim" + Int2Str(sim.simulation) - + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) -// + "_yr" + Int2Str(yr) - + "_Visits.txt"; -} -outvisits.open(name.c_str()); - -outvisits << "ncols " << dimX << endl; -outvisits << "nrows " << dimY << endl; -outvisits << "xllcorner " << minEast << endl; -outvisits << "yllcorner " << minNorth << endl; -outvisits << "cellsize " << resol << endl; -outvisits << "NODATA_value -9" << endl; - -for (int y = dimY-1; y >= 0; y--) { -#if RSDEBUG -//DebugGUI(("Landscape::drawLandscape(): y=" + Int2Str(y) -// + " cells[y]=" + Int2Str((int)cells[y])).c_str()); + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) #endif - for (int x = 0; x < dimX; x++) { - if (cells[y][x] == 0) { // no-data cell - outvisits << "-9 "; - } - else { - outvisits << cells[y][x]->getVisits() << " "; + + "_Visits.txt"; + } + else { + name = paramsSim->getDir(3) + + "Sim" + Int2Str(sim.simulation) + + "_land" + Int2Str(landNr) + "_rep" + Int2Str(rep) + + "_Visits.txt"; + } + outvisits.open(name.c_str()); + + outvisits << "ncols " << dimX << endl; + outvisits << "nrows " << dimY << endl; + outvisits << "xllcorner " << minEast << endl; + outvisits << "yllcorner " << minNorth << endl; + outvisits << "cellsize " << resol << endl; + outvisits << "NODATA_value -9" << endl; + + for (int y = dimY - 1; y >= 0; y--) { + for (int x = 0; x < dimX; x++) { + if (cells[y][x] == 0) { // no-data cell + outvisits << "-9 "; + } + else { + outvisits << cells[y][x]->getVisits() << " "; + } } + outvisits << endl; } - outvisits << endl; -} -outvisits.close(); outvisits.clear(); + outvisits.close(); outvisits.clear(); } //--------------------------------------------------------------------------- diff --git a/Landscape.h b/Landscape.h index a3d974d..2a414cc 100644 --- a/Landscape.h +++ b/Landscape.h @@ -71,12 +71,8 @@ Last updated: 2 December 2021 by Steve Palmer #ifndef LandscapeH #define LandscapeH -//#include -//#include #include #include -//#include -//#include #include using namespace std; @@ -144,7 +140,6 @@ class InitDist{ }; - //--------------------------------------------------------------------------- struct landParams { From 7b2f561ce1911ade67bc4d95a38b1347ddeef04c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 28 Nov 2023 16:00:47 +0000 Subject: [PATCH 19/46] rm commented out code and fix indent in Community --- Community.cpp | 2433 +++++++++++++++++++++++-------------------------- Community.h | 13 +- 2 files changed, 1143 insertions(+), 1303 deletions(-) diff --git a/Community.cpp b/Community.cpp index 12b190c..286dc6a 100644 --- a/Community.cpp +++ b/Community.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Community.h" @@ -28,574 +28,553 @@ ofstream outrange; -ofstream outoccup,outsuit; +ofstream outoccup, outsuit; ofstream outtraitsrows; //--------------------------------------------------------------------------- -Community::Community(Landscape *pLand) { -pLandscape = pLand; -indIx = 0; +Community::Community(Landscape* pLand) { + pLandscape = pLand; + indIx = 0; } Community::~Community(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - delete subComms[i]; -} -subComms.clear(); + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + delete subComms[i]; + } + subComms.clear(); } -SubCommunity* Community::addSubComm(Patch *pPch,int num) { -int nsubcomms = (int)subComms.size(); -subComms.push_back(new SubCommunity(pPch,num)); -return subComms[nsubcomms]; +SubCommunity* Community::addSubComm(Patch* pPch, int num) { + int nsubcomms = (int)subComms.size(); + subComms.push_back(new SubCommunity(pPch, num)); + return subComms[nsubcomms]; } -void Community::initialise(Species *pSpecies,int year) +void Community::initialise(Species* pSpecies, int year) { -int nsubcomms,npatches,ndistcells,spratio,patchnum,rr = 0; -locn distloc; -patchData pch; -patchLimits limits; -intptr ppatch,subcomm; -std::vector subcomms; -std::vector selected; -SubCommunity *pSubComm; -Patch *pPatch; -Cell *pCell; -landParams ppLand = pLandscape->getLandParams(); -initParams init = paramsInit->getInit(); + int nsubcomms, npatches, ndistcells, spratio, patchnum, rr = 0; + locn distloc; + patchData pch; + patchLimits limits; + intptr ppatch, subcomm; + std::vector subcomms; + std::vector selected; + SubCommunity* pSubComm; + Patch* pPatch; + Cell* pCell; + landParams ppLand = pLandscape->getLandParams(); + initParams init = paramsInit->getInit(); -nsubcomms = (int)subComms.size(); + nsubcomms = (int)subComms.size(); -spratio = ppLand.spResol / ppLand.resol; + spratio = ppLand.spResol / ppLand.resol; #if RSDEBUG -DEBUGLOG << endl << "Community::initialise(): this=" << this - << " seedType=" << init.seedType << " freeType=" << init.freeType - << " minSeedX=" << init.minSeedX << " minSeedY=" << init.minSeedY - << " maxSeedX=" << init.maxSeedX << " maxSeedY=" << init.maxSeedY - << " indsFile=" << init.indsFile - << " nsubcomms=" << nsubcomms << " spratio=" << spratio - << endl; + DEBUGLOG << endl << "Community::initialise(): this=" << this + << " seedType=" << init.seedType << " freeType=" << init.freeType + << " minSeedX=" << init.minSeedX << " minSeedY=" << init.minSeedY + << " maxSeedX=" << init.maxSeedX << " maxSeedY=" << init.maxSeedY + << " indsFile=" << init.indsFile + << " nsubcomms=" << nsubcomms << " spratio=" << spratio + << endl; #endif -switch (init.seedType) { - -case 0: // free initialisation - - switch (init.freeType) { - - case 0: // random - // determine no. of patches / cells within the specified initialisation limits - // and record their corresponding sub-communities in a list - // parallel list records which have been selected - npatches = pLandscape->patchCount(); - limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; - limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; - for (int i = 0; i < npatches; i++) { - pch = pLandscape->getPatchData(i); - if (pch.pPatch->withinLimits(limits)) { - if (ppLand.patchModel) { - if (pch.pPatch->getPatchNum() != 0) { - subcomms.push_back(pch.pPatch->getSubComm()); - selected.push_back(false); + switch (init.seedType) { + + case 0: // free initialisation + + switch (init.freeType) { + + case 0: // random + // determine no. of patches / cells within the specified initialisation limits + // and record their corresponding sub-communities in a list + // parallel list records which have been selected + npatches = pLandscape->patchCount(); + limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; + limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; + for (int i = 0; i < npatches; i++) { + pch = pLandscape->getPatchData(i); + if (pch.pPatch->withinLimits(limits)) { + if (ppLand.patchModel) { + if (pch.pPatch->getPatchNum() != 0) { + subcomms.push_back(pch.pPatch->getSubComm()); + selected.push_back(false); + } } - } - else { // cell-based model - is cell(patch) suitable - if (pch.pPatch->getK() > 0.0) - { - subcomms.push_back(pch.pPatch->getSubComm()); - selected.push_back(false); + else { // cell-based model - is cell(patch) suitable + if (pch.pPatch->getK() > 0.0) + { + subcomms.push_back(pch.pPatch->getSubComm()); + selected.push_back(false); + } } } } - } - // select specified no. of patches/cells at random - npatches = (int)subcomms.size(); - if (init.nSeedPatches > npatches/2) { // use backwards selection method - for (int i = 0; i < npatches; i++) selected[i] = true; - for (int i = 0; i < (npatches-init.nSeedPatches); i++) { - do { - rr = pRandom->IRandom(0,npatches-1); - } while (!selected[rr]); - selected[rr] = false; + // select specified no. of patches/cells at random + npatches = (int)subcomms.size(); + if (init.nSeedPatches > npatches / 2) { // use backwards selection method + for (int i = 0; i < npatches; i++) selected[i] = true; + for (int i = 0; i < (npatches - init.nSeedPatches); i++) { + do { + rr = pRandom->IRandom(0, npatches - 1); + } while (!selected[rr]); + selected[rr] = false; + } } - } - else { // use forwards selection method - for (int i = 0; i < init.nSeedPatches; i++) { - do { - rr = pRandom->IRandom(0,npatches-1); - } while (selected[rr]); - selected[rr] = true; + else { // use forwards selection method + for (int i = 0; i < init.nSeedPatches; i++) { + do { + rr = pRandom->IRandom(0, npatches - 1); + } while (selected[rr]); + selected[rr] = true; + } } - } - // selected sub-communities for initialisation - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->setInitial(false); - } - for (int i = 0; i < npatches; i++) { - if (selected[i]) { - pSubComm = (SubCommunity*)subcomms[i]; - pSubComm->setInitial(true); + // selected sub-communities for initialisation + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->setInitial(false); } - } - break; + for (int i = 0; i < npatches; i++) { + if (selected[i]) { + pSubComm = (SubCommunity*)subcomms[i]; + pSubComm->setInitial(true); + } + } + break; - case 1: // all suitable patches/cells - npatches = pLandscape->patchCount(); - limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; - limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; - for (int i = 0; i < npatches; i++) { - pch = pLandscape->getPatchData(i); - if (pch.pPatch->withinLimits(limits)) { - patchnum = pch.pPatch->getPatchNum(); - if (patchnum != 0) { - if (pch.pPatch->getK() > 0.0) - { // patch is suitable - subcomm = pch.pPatch->getSubComm(); - if (subcomm == 0) { - // create a sub-community in the patch - pSubComm = addSubComm(pch.pPatch,patchnum); - } - else { - pSubComm = (SubCommunity*)subcomm; + case 1: // all suitable patches/cells + npatches = pLandscape->patchCount(); + limits.xMin = init.minSeedX; limits.xMax = init.maxSeedX; + limits.yMin = init.minSeedY; limits.yMax = init.maxSeedY; + for (int i = 0; i < npatches; i++) { + pch = pLandscape->getPatchData(i); + if (pch.pPatch->withinLimits(limits)) { + patchnum = pch.pPatch->getPatchNum(); + if (patchnum != 0) { + if (pch.pPatch->getK() > 0.0) + { // patch is suitable + subcomm = pch.pPatch->getSubComm(); + if (subcomm == 0) { + // create a sub-community in the patch + pSubComm = addSubComm(pch.pPatch, patchnum); + } + else { + pSubComm = (SubCommunity*)subcomm; + } + pSubComm->setInitial(true); } - pSubComm->setInitial(true); } } } - } - - break; - - case 2: // manually selected patches/cells - break; - - } // end of switch (init.freeType) - nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->initialise(pLandscape,pSpecies); - } - break; -case 1: // from species distribution - if (ppLand.spDist) - { - // deselect all existing sub-communities - for (int i = 0; i < nsubcomms; i++) { - subComms[i]->setInitial(false); - } - // initialise from loaded species distribution - switch (init.spDistType) { - case 0: // all presence cells - pLandscape->setDistribution(pSpecies,0); // activate all patches - break; - case 1: // some randomly selected presence cells - pLandscape->setDistribution(pSpecies,init.nSpDistPatches); // activate random patches break; - case 2: // manually selected presence cells - // cells have already been identified - no further action here + + case 2: // manually selected patches/cells break; + + } // end of switch (init.freeType) + nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->initialise(pLandscape, pSpecies); } + break; - // THE FOLLOWING WILL HAVE TO BE CHANGED FOR MULTIPLE SPECIES... - ndistcells = pLandscape->distCellCount(0); - for (int i = 0; i < ndistcells; i++) { - distloc = pLandscape->getSelectedDistnCell(0,i); - if (distloc.x >= 0) { // distribution cell is selected - // process each landscape cell within the distribution cell - for (int x = 0; x < spratio; x++) { - for (int y = 0; y < spratio; y++) { - pCell = pLandscape->findCell(distloc.x*spratio+x,distloc.y*spratio+y); - if (pCell != 0) { // not a no-data cell - ppatch = pCell->getPatch(); - if (ppatch != 0) { - pPatch = (Patch*)ppatch; - if (pPatch->getSeqNum() != 0) { // not the matrix patch - subcomm = pPatch->getSubComm(); - if (subcomm != 0) { - pSubComm = (SubCommunity*)subcomm; - pSubComm->setInitial(true); - } - } + case 1: // from species distribution + if (ppLand.spDist) + { + // deselect all existing sub-communities + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->setInitial(false); + } + // initialise from loaded species distribution + switch (init.spDistType) { + case 0: // all presence cells + pLandscape->setDistribution(pSpecies, 0); // activate all patches + break; + case 1: // some randomly selected presence cells + pLandscape->setDistribution(pSpecies, init.nSpDistPatches); // activate random patches + break; + case 2: // manually selected presence cells + // cells have already been identified - no further action here + break; + } + + // THE FOLLOWING WILL HAVE TO BE CHANGED FOR MULTIPLE SPECIES... + ndistcells = pLandscape->distCellCount(0); + for (int i = 0; i < ndistcells; i++) { + distloc = pLandscape->getSelectedDistnCell(0, i); + if (distloc.x >= 0) { // distribution cell is selected + // process each landscape cell within the distribution cell + for (int x = 0; x < spratio; x++) { + for (int y = 0; y < spratio; y++) { + pCell = pLandscape->findCell(distloc.x * spratio + x, distloc.y * spratio + y); + if (pCell != 0) { // not a no-data cell + ppatch = pCell->getPatch(); + if (ppatch != 0) { + pPatch = (Patch*)ppatch; + if (pPatch->getSeqNum() != 0) { // not the matrix patch + subcomm = pPatch->getSubComm(); + if (subcomm != 0) { + pSubComm = (SubCommunity*)subcomm; + pSubComm->setInitial(true); + } + } + } } } } } } + + nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->initialise(pLandscape, pSpecies); + } } - - nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->initialise(pLandscape,pSpecies); + else { + // WHAT HAPPENS IF INITIAL DISTRIBUTION IS NOT LOADED ??? .... + // should not occur - take no action - no initialisation will occur } - } - else { - // WHAT HAPPENS IF INITIAL DISTRIBUTION IS NOT LOADED ??? .... - // should not occur - take no action - no initialisation will occur - } - break; + break; -case 2: // initial individuals in specified patches/cells - if (year < 0) { - // initialise matrix sub-community only - subComms[0]->initialise(pLandscape,pSpecies); - indIx = 0; // reset index for initial individuals - } - else { // add any initial individuals for the current year - initInd iind; iind.year = 0; - int ninds = paramsInit->numInitInds(); - while (indIx < ninds && iind.year <= year) { - iind = paramsInit->getInitInd(indIx); - while (iind.year == year) { -#if RSDEBUG -//DEBUGLOG << "Community::initialise(): year=" << year -// << " indIx=" << indIx << " iind.year=" << iind.year -// << " iind.patchID=" << iind.patchID << " iind.x=" << iind.x << " iind.y=" << iind.y -// << " iind.sex=" << iind.sex << " iind.age=" << iind.age << " iind.stage=" << iind.stage -// << endl; -#endif - if (ppLand.patchModel) { - if (pLandscape->existsPatch(iind.patchID)) { - pPatch = pLandscape->findPatch(iind.patchID); - if (pPatch->getK() > 0.0) - { // patch is suitable - subcomm = pPatch->getSubComm(); - if (subcomm == 0) { - // create a sub-community in the patch - pSubComm = addSubComm(pPatch,iind.patchID); - } - else { - pSubComm = (SubCommunity*)subcomm; - } - pSubComm->initialInd(pLandscape,pSpecies,pPatch,pPatch->getRandomCell(),indIx); - } - } - } - else { // cell-based model - pCell = pLandscape->findCell(iind.x,iind.y); - if (pCell != 0) { - intptr ppatch = pCell->getPatch(); - if (ppatch != 0) { - pPatch = (Patch*)ppatch; - if (pPatch->getK() > 0.0) + case 2: // initial individuals in specified patches/cells + if (year < 0) { + // initialise matrix sub-community only + subComms[0]->initialise(pLandscape, pSpecies); + indIx = 0; // reset index for initial individuals + } + else { // add any initial individuals for the current year + initInd iind; iind.year = 0; + int ninds = paramsInit->numInitInds(); + while (indIx < ninds && iind.year <= year) { + iind = paramsInit->getInitInd(indIx); + while (iind.year == year) { + if (ppLand.patchModel) { + if (pLandscape->existsPatch(iind.patchID)) { + pPatch = pLandscape->findPatch(iind.patchID); + if (pPatch->getK() > 0.0) { // patch is suitable subcomm = pPatch->getSubComm(); if (subcomm == 0) { // create a sub-community in the patch - pSubComm = addSubComm(pPatch,iind.patchID); + pSubComm = addSubComm(pPatch, iind.patchID); } else { pSubComm = (SubCommunity*)subcomm; } - pSubComm->initialInd(pLandscape,pSpecies,pPatch,pCell,indIx); + pSubComm->initialInd(pLandscape, pSpecies, pPatch, pPatch->getRandomCell(), indIx); } } } - } - indIx++; - if (indIx < ninds) { - iind = paramsInit->getInitInd(indIx); - } - else { - iind.year = 99999999; + else { // cell-based model + pCell = pLandscape->findCell(iind.x, iind.y); + if (pCell != 0) { + intptr ppatch = pCell->getPatch(); + if (ppatch != 0) { + pPatch = (Patch*)ppatch; + if (pPatch->getK() > 0.0) + { // patch is suitable + subcomm = pPatch->getSubComm(); + if (subcomm == 0) { + // create a sub-community in the patch + pSubComm = addSubComm(pPatch, iind.patchID); + } + else { + pSubComm = (SubCommunity*)subcomm; + } + pSubComm->initialInd(pLandscape, pSpecies, pPatch, pCell, indIx); + } + } + } + } + indIx++; + if (indIx < ninds) { + iind = paramsInit->getInitInd(indIx); + } + else { + iind.year = 99999999; + } } } } - } - break; + break; -case 3: // from file - // this condition cannot occur here, as init.seedType will have been changed to 0 or 1 - // when the initialisation file was read - break; + case 3: // from file + // this condition cannot occur here, as init.seedType will have been changed to 0 or 1 + // when the initialisation file was read + break; -} // end of switch (init.seedType) + } // end of switch (init.seedType) #if RSDEBUG -DEBUGLOG << "Community::initialise(): this=" << this - << " nsubcomms=" << nsubcomms - << endl; + DEBUGLOG << "Community::initialise(): this=" << this + << " nsubcomms=" << nsubcomms + << endl; #endif } // Add manually selected patches/cells to the selected set for initialisation void Community::addManuallySelected(void) { -int npatches; -intptr subcomm,patch; -locn initloc; -Cell *pCell; -Patch *pPatch; -SubCommunity *pSubComm; + int npatches; + intptr subcomm, patch; + locn initloc; + Cell* pCell; + Patch* pPatch; + SubCommunity* pSubComm; -landParams ppLand = pLandscape->getLandParams(); + landParams ppLand = pLandscape->getLandParams(); -npatches = pLandscape->initCellCount(); // no. of patches/cells specified + npatches = pLandscape->initCellCount(); // no. of patches/cells specified #if RSDEBUG -DEBUGLOG << "Community::addManuallySelected(): this = " << this - << " npatches = " << npatches << endl; + DEBUGLOG << "Community::addManuallySelected(): this = " << this + << " npatches = " << npatches << endl; #endif -// identify sub-communities to be initialised -if (ppLand.patchModel) { - for (int i = 0; i < npatches; i++) { - initloc = pLandscape->getInitCell(i); // patch number held in x-coord of list - pPatch = pLandscape->findPatch(initloc.x); - if (pPatch != 0) { - subcomm = pPatch->getSubComm(); - if (subcomm != 0) { - pSubComm = (SubCommunity*)subcomm; - pSubComm->setInitial(true); + // identify sub-communities to be initialised + if (ppLand.patchModel) { + for (int i = 0; i < npatches; i++) { + initloc = pLandscape->getInitCell(i); // patch number held in x-coord of list + pPatch = pLandscape->findPatch(initloc.x); + if (pPatch != 0) { + subcomm = pPatch->getSubComm(); + if (subcomm != 0) { + pSubComm = (SubCommunity*)subcomm; + pSubComm->setInitial(true); + } } } } -} -else { // cell-based model - for (int i = 0; i < npatches; i++) { - initloc = pLandscape->getInitCell(i); - if (initloc.x >= 0 && initloc.x < ppLand.dimX - && initloc.y >= 0 && initloc.y < ppLand.dimY) { - pCell = pLandscape->findCell(initloc.x,initloc.y); - if (pCell != 0) { // not no-data cell - patch = pCell->getPatch(); + else { // cell-based model + for (int i = 0; i < npatches; i++) { + initloc = pLandscape->getInitCell(i); + if (initloc.x >= 0 && initloc.x < ppLand.dimX + && initloc.y >= 0 && initloc.y < ppLand.dimY) { + pCell = pLandscape->findCell(initloc.x, initloc.y); + if (pCell != 0) { // not no-data cell + patch = pCell->getPatch(); #if RSDEBUG -DEBUGLOG << "Community::initialise(): i = " << i - << " x = " << initloc.x << " y = " << initloc.y - << " pCell = " << pCell << " patch = " << patch - << endl; + DEBUGLOG << "Community::initialise(): i = " << i + << " x = " << initloc.x << " y = " << initloc.y + << " pCell = " << pCell << " patch = " << patch + << endl; #endif - if (patch != 0) { - pPatch = (Patch*)patch; - subcomm = pPatch->getSubComm(); + if (patch != 0) { + pPatch = (Patch*)patch; + subcomm = pPatch->getSubComm(); #if RSDEBUG -DEBUGLOG << "Community::initialise(): i = " << i - << " pPatch = " << pPatch << " subcomm = " << subcomm - << endl; + DEBUGLOG << "Community::initialise(): i = " << i + << " pPatch = " << pPatch << " subcomm = " << subcomm + << endl; #endif - if (subcomm != 0) { - pSubComm = (SubCommunity*)subcomm; - pSubComm->setInitial(true); + if (subcomm != 0) { + pSubComm = (SubCommunity*)subcomm; + pSubComm->setInitial(true); #if RSDEBUG -DEBUGLOG << "Community::initialise(): i = " << i - << " pSubComm = " << pSubComm - << endl; + DEBUGLOG << "Community::initialise(): i = " << i + << " pSubComm = " << pSubComm + << endl; #endif + } } } } } } } -} void Community::resetPopns(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->resetPopns(); -} -// reset the individual ids to start from zero -Individual::indCounter = 0; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->resetPopns(); + } + // reset the individual ids to start from zero + Individual::indCounter = 0; } void Community::localExtinction(int option) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - if (subComms[i]->getNum() > 0) { // except in matrix - subComms[i]->localExtinction(option); + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + if (subComms[i]->getNum() > 0) { // except in matrix + subComms[i]->localExtinction(option); + } } } -} void Community::patchChanges(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - if (subComms[i]->getNum() > 0) { // except in matrix - subComms[i]->patchChange(); + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + if (subComms[i]->getNum() > 0) { // except in matrix + subComms[i]->patchChange(); + } } } -} void Community::reproduction(int yr) { -float eps = 0.0; // epsilon for environmental stochasticity -landParams land = pLandscape->getLandParams(); -envStochParams env = paramsStoch->getStoch(); -int nsubcomms = (int)subComms.size(); + float eps = 0.0; // epsilon for environmental stochasticity + landParams land = pLandscape->getLandParams(); + envStochParams env = paramsStoch->getStoch(); + int nsubcomms = (int)subComms.size(); #if RSDEBUG -DEBUGLOG << "Community::reproduction(): this=" << this - << " nsubcomms=" << nsubcomms << endl; + DEBUGLOG << "Community::reproduction(): this=" << this + << " nsubcomms=" << nsubcomms << endl; #endif -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - if (env.stoch) { - if (!env.local) { // global stochasticty - eps = pLandscape->getGlobalStoch(yr); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + if (env.stoch) { + if (!env.local) { // global stochasticty + eps = pLandscape->getGlobalStoch(yr); + } } + subComms[i]->reproduction(land.resol, eps, land.rasterType, land.patchModel); } - subComms[i]->reproduction(land.resol,eps,land.rasterType,land.patchModel); -} #if RSDEBUG -DEBUGLOG << "Community::reproduction(): finished" << endl; + DEBUGLOG << "Community::reproduction(): finished" << endl; #endif } -void Community::emigration(void) +void Community::emigration(void) { -int nsubcomms = (int)subComms.size(); + int nsubcomms = (int)subComms.size(); #if RSDEBUG -DEBUGLOG << "Community::emigration(): this=" << this - << " nsubcomms=" << nsubcomms << endl; + DEBUGLOG << "Community::emigration(): this=" << this + << " nsubcomms=" << nsubcomms << endl; #endif -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->emigration(); -} + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->emigration(); + } #if RSDEBUG -DEBUGLOG << "Community::emigration(): finished" << endl; + DEBUGLOG << "Community::emigration(): finished" << endl; #endif } #if RS_RCPP // included also SEASONAL -void Community::dispersal(short landIx,short nextseason) +void Community::dispersal(short landIx, short nextseason) #else void Community::dispersal(short landIx) #endif // SEASONAL || RS_RCPP { #if RSDEBUG -int t0,t1,t2; -t0 = time(0); + int t0, t1, t2; + t0 = time(0); #endif -simParams sim = paramsSim->getSim(); - -int nsubcomms = (int)subComms.size(); -// initiate dispersal - all emigrants leave their natal community and join matrix community -SubCommunity *matrix = subComms[0]; // matrix community is always the first -for (int i = 0; i < nsubcomms; i++) { // all populations - subComms[i]->initiateDispersal(matrix); -} -#if RSDEBUG -t1 = time(0); -DEBUGLOG << "Community::dispersal(): this=" << this - << " nsubcomms=" << nsubcomms << " initiation time=" << t1-t0 << endl; -#endif + simParams sim = paramsSim->getSim(); -// dispersal is undertaken by all individuals now in the matrix patch -// (even if not physically in the matrix) -int ndispersers = 0; -do { + int nsubcomms = (int)subComms.size(); + // initiate dispersal - all emigrants leave their natal community and join matrix community + SubCommunity* matrix = subComms[0]; // matrix community is always the first for (int i = 0; i < nsubcomms; i++) { // all populations - subComms[i]->resetPossSettlers(); + subComms[i]->initiateDispersal(matrix); } #if RSDEBUG -//DEBUGLOG << "Community::dispersal() 1111: ndispersers=" << ndispersers << endl; + t1 = time(0); + DEBUGLOG << "Community::dispersal(): this=" << this + << " nsubcomms=" << nsubcomms << " initiation time=" << t1 - t0 << endl; #endif + + // dispersal is undertaken by all individuals now in the matrix patch + // (even if not physically in the matrix) + int ndispersers = 0; + do { + for (int i = 0; i < nsubcomms; i++) { // all populations + subComms[i]->resetPossSettlers(); + } #if RS_RCPP // included also SEASONAL - ndispersers = matrix->transfer(pLandscape,landIx,nextseason); + ndispersers = matrix->transfer(pLandscape, landIx, nextseason); #else - ndispersers = matrix->transfer(pLandscape,landIx); + ndispersers = matrix->transfer(pLandscape, landIx); #endif // SEASONAL || RS_RCPP -#if RSDEBUG -//DEBUGLOG << "Community::dispersal() 2222: ndispersers=" << ndispersers << endl; -#endif - matrix->completeDispersal(pLandscape,sim.outConnect); -#if RSDEBUG -//DEBUGLOG << "Community::dispersal() 3333: ndispersers=" << ndispersers << endl; -#endif -} while (ndispersers > 0); - -#if RSDEBUG -DEBUGLOG << "Community::dispersal(): matrix=" << matrix << endl; -t2 = time(0); -DEBUGLOG << "Community::dispersal(): transfer time=" << t2-t1 << endl; -#endif + matrix->completeDispersal(pLandscape, sim.outConnect); + } while (ndispersers > 0); #if RSDEBUG -//int t3 = time(0); -//DEBUGLOG << "Community::dispersal(): completion time = " << t3-t2 << endl; + DEBUGLOG << "Community::dispersal(): matrix=" << matrix << endl; + t2 = time(0); + DEBUGLOG << "Community::dispersal(): transfer time=" << t2 - t1 << endl; #endif } -void Community::survival(short part,short option0,short option1) +void Community::survival(short part, short option0, short option1) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - subComms[i]->survival(part,option0,option1); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + subComms[i]->survival(part, option0, option1); + } } void Community::ageIncrement(void) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - subComms[i]->ageIncrement(); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + subComms[i]->ageIncrement(); + } } // Calculate total no. of individuals of all species int Community::totalInds(void) { -popStats p; -int total = 0; -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - p = subComms[i]->getPopStats(); - total += p.nInds; -} -return total; + popStats p; + int total = 0; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + p = subComms[i]->getPopStats(); + total += p.nInds; + } + return total; } // Find the population of a given species in a given patch -Population* Community::findPop(Species *pSp,Patch *pPch) { -Population *pPop = 0; -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) - pPop = subComms[i]->findPop(pSp,pPch); - if (pPop != 0) break; -} -return pPop; +Population* Community::findPop(Species* pSp, Patch* pPch) { + Population* pPop = 0; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all communities (including in matrix) + pPop = subComms[i]->findPop(pSp, pPch); + if (pPop != 0) break; + } + return pPop; } //--------------------------------------------------------------------------- -void Community::createOccupancy(int nrows,int reps) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { - subComms[i]->createOccupancy(nrows); -} -// Initialise array for occupancy of suitable cells/patches -occSuit = new float *[nrows]; -for (int i = 0; i < nrows; i++) -{ - occSuit[i] = new float[reps]; - for (int ii = 0; ii < reps; ii++) occSuit[i][ii] = 0.0; -} +void Community::createOccupancy(int nrows, int reps) { + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->createOccupancy(nrows); + } + // Initialise array for occupancy of suitable cells/patches + occSuit = new float* [nrows]; + for (int i = 0; i < nrows; i++) + { + occSuit[i] = new float[reps]; + for (int ii = 0; ii < reps; ii++) occSuit[i][ii] = 0.0; + } } -void Community::updateOccupancy(int row,int rep) +void Community::updateOccupancy(int row, int rep) { #if RSDEBUG -DEBUGLOG << "Community::updateOccupancy(): row=" << row << endl; + DEBUGLOG << "Community::updateOccupancy(): row=" << row << endl; #endif -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { - subComms[i]->updateOccupancy(row); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->updateOccupancy(row); + } -commStats s = getStats(); -occSuit[row][rep] = (float)s.occupied / (float)s.suitable; + commStats s = getStats(); + occSuit[row][rep] = (float)s.occupied / (float)s.suitable; } void Community::deleteOccupancy(int nrows) { -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { - subComms[i]->deleteOccupancy(); -} + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { + subComms[i]->deleteOccupancy(); + } -for(int i = 0; i < nrows; i++) - delete[] occSuit[i]; -delete[] occSuit; + for (int i = 0; i < nrows; i++) + delete[] occSuit[i]; + delete[] occSuit; } @@ -604,49 +583,33 @@ delete[] occSuit; // Determine range margins commStats Community::getStats(void) { -commStats s; -landParams ppLand = pLandscape->getLandParams(); -s.ninds = s.nnonjuvs = s.suitable = s.occupied = 0; -s.minX = ppLand.maxX; s.minY = ppLand.maxY; s.maxX = s.maxY = 0; -float localK; -popStats patchPop; -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - patchPop = subComms[i]->getPopStats(); - s.ninds += patchPop.nInds; - s.nnonjuvs += patchPop.nNonJuvs; -#if RSDEBUG -//DEBUGLOG << "Community::getStats(): i = " << i -// << " pSpecies = " << patchPop.pSpecies << " pPatch = " << patchPop.pPatch -// << " nInds = " << patchPop.nInds << endl; -#endif - if (patchPop.pPatch != 0) { // not the matrix patch -#if RSDEBUG -//DEBUGLOG << "Community::getStats(): i = " << i -// << " patchNum = " << patchPop.pPatch->getPatchNum() << endl; -#endif - if (patchPop.pPatch->getPatchNum() != 0) { // not matrix patch - localK = patchPop.pPatch->getK(); -#if RSDEBUG -//DEBUGLOG << "Community::getStats(): i= " << i -// << " pSpecies= " << patchPop.pSpecies << " pPatch= " << patchPop.pPatch -// << " patchNum= " << patchPop.pPatch->getPatchNum() << " localK= " << localK -// << " nInds= " << patchPop.nInds << " breeding= " << (int)patchPop.breeding -// << endl; -#endif - if (localK > 0.0) s.suitable++; - if (patchPop.nInds > 0 && patchPop.breeding) { - s.occupied++; - patchLimits pchlim = patchPop.pPatch->getLimits(); - if (pchlim.xMin < s.minX) s.minX = pchlim.xMin; - if (pchlim.xMax > s.maxX) s.maxX = pchlim.xMax; - if (pchlim.yMin < s.minY) s.minY = pchlim.yMin; - if (pchlim.yMax > s.maxY) s.maxY = pchlim.yMax; + commStats s; + landParams ppLand = pLandscape->getLandParams(); + s.ninds = s.nnonjuvs = s.suitable = s.occupied = 0; + s.minX = ppLand.maxX; s.minY = ppLand.maxY; s.maxX = s.maxY = 0; + float localK; + popStats patchPop; + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + patchPop = subComms[i]->getPopStats(); + s.ninds += patchPop.nInds; + s.nnonjuvs += patchPop.nNonJuvs; + if (patchPop.pPatch != 0) { // not the matrix patch + if (patchPop.pPatch->getPatchNum() != 0) { // not matrix patch + localK = patchPop.pPatch->getK(); + if (localK > 0.0) s.suitable++; + if (patchPop.nInds > 0 && patchPop.breeding) { + s.occupied++; + patchLimits pchlim = patchPop.pPatch->getLimits(); + if (pchlim.xMin < s.minX) s.minX = pchlim.xMin; + if (pchlim.xMax > s.maxX) s.maxX = pchlim.xMax; + if (pchlim.yMin < s.minY) s.minY = pchlim.yMin; + if (pchlim.yMax > s.maxY) s.maxY = pchlim.yMax; + } } } } -} -return s; + return s; } //--------------------------------------------------------------------------- @@ -654,650 +617,593 @@ return s; // Functions to control production of output files // Open population file and write header record -bool Community::outPopHeaders(Species *pSpecies,int option) { -return subComms[0]->outPopHeaders(pLandscape,pSpecies,option); +bool Community::outPopHeaders(Species* pSpecies, int option) { + return subComms[0]->outPopHeaders(pLandscape, pSpecies, option); } // Write records to population file -void Community::outPop(int rep,int yr,int gen) +void Community::outPop(int rep, int yr, int gen) { -// generate output for each sub-community (patch) in the community -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->outPop(pLandscape,rep,yr,gen); -} + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->outPop(pLandscape, rep, yr, gen); + } } // Write records to individuals file -void Community::outInds(int rep, int yr, int gen,int landNr) { +void Community::outInds(int rep, int yr, int gen, int landNr) { -if (landNr >= 0) { // open the file - subComms[0]->outInds(pLandscape,rep,yr,gen,landNr); - return; -} -if (landNr == -999) { // close the file - subComms[0]->outInds(pLandscape,rep,yr,gen,-999); - return; -} -// generate output for each sub-community (patch) in the community -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->outInds(pLandscape,rep,yr,gen,landNr); -} + if (landNr >= 0) { // open the file + subComms[0]->outInds(pLandscape, rep, yr, gen, landNr); + return; + } + if (landNr == -999) { // close the file + subComms[0]->outInds(pLandscape, rep, yr, gen, -999); + return; + } + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->outInds(pLandscape, rep, yr, gen, landNr); + } } // Write records to genetics file -void Community::outGenetics(int rep, int yr, int gen,int landNr) { -//landParams ppLand = pLandscape->getLandParams(); -if (landNr >= 0) { // open the file - subComms[0]->outGenetics(rep,yr,gen,landNr); - return; -} -if (landNr == -999) { // close the file - subComms[0]->outGenetics(rep,yr,gen,landNr); - return; -} -// generate output for each sub-community (patch) in the community -int nsubcomms = (int)subComms.size(); -for (int i = 0; i < nsubcomms; i++) { // all sub-communities - subComms[i]->outGenetics(rep,yr,gen,landNr); -} +void Community::outGenetics(int rep, int yr, int gen, int landNr) { + //landParams ppLand = pLandscape->getLandParams(); + if (landNr >= 0) { // open the file + subComms[0]->outGenetics(rep, yr, gen, landNr); + return; + } + if (landNr == -999) { // close the file + subComms[0]->outGenetics(rep, yr, gen, landNr); + return; + } + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + subComms[i]->outGenetics(rep, yr, gen, landNr); + } } // Open range file and write header record -bool Community::outRangeHeaders(Species *pSpecies,int landNr) +bool Community::outRangeHeaders(Species* pSpecies, int landNr) { -if (landNr == -999) { // close the file - if (outrange.is_open()) outrange.close(); - outrange.clear(); - return true; -} + if (landNr == -999) { // close the file + if (outrange.is_open()) outrange.close(); + outrange.clear(); + return true; + } -string name; -landParams ppLand = pLandscape->getLandParams(); -envStochParams env = paramsStoch->getStoch(); -simParams sim = paramsSim->getSim(); + string name; + landParams ppLand = pLandscape->getLandParams(); + envStochParams env = paramsStoch->getStoch(); + simParams sim = paramsSim->getSim(); -// NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER -// ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); + // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER + // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); #if RSDEBUG -DEBUGLOG << "Community::outRangeHeaders(): simulation=" << sim.simulation - << " sim.batchMode=" << sim.batchMode - << " landNr=" << landNr << endl; + DEBUGLOG << "Community::outRangeHeaders(): simulation=" << sim.simulation + << " sim.batchMode=" << sim.batchMode + << " landNr=" << landNr << endl; #endif -if (sim.batchMode) { - name = paramsSim->getDir(2) + if (sim.batchMode) { + name = paramsSim->getDir(2) #if RS_RCPP - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) #else - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" - + Int2Str(landNr) + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + + Int2Str(landNr) #endif - + "_Range.txt"; -} -else { - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Range.txt"; -} -outrange.open(name.c_str()); -outrange << "Rep\tYear\tRepSeason"; -if (env.stoch && !env.local) outrange << "\tEpsilon"; - -outrange << "\tNInds"; -if (dem.stageStruct) { - for (int i = 1; i < sstruct.nStages; i++) outrange << "\tNInd_stage" << i; - outrange << "\tNJuvs"; -} -if (ppLand.patchModel) outrange << "\tNOccupPatches"; -else outrange << "\tNOccupCells"; -outrange << "\tOccup/Suit\tmin_X\tmax_X\tmin_Y\tmax_Y"; - -if (emig.indVar) { - if (emig.sexDep) { - if (emig.densDep) { - outrange << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; - outrange << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; - outrange << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; - } - else { - outrange << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; - } + + "_Range.txt"; } else { - if (emig.densDep) { - outrange << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; - outrange << "\tmeanBeta\tstdBeta"; + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Range.txt"; + } + outrange.open(name.c_str()); + outrange << "Rep\tYear\tRepSeason"; + if (env.stoch && !env.local) outrange << "\tEpsilon"; + + outrange << "\tNInds"; + if (dem.stageStruct) { + for (int i = 1; i < sstruct.nStages; i++) outrange << "\tNInd_stage" << i; + outrange << "\tNJuvs"; + } + if (ppLand.patchModel) outrange << "\tNOccupPatches"; + else outrange << "\tNOccupCells"; + outrange << "\tOccup/Suit\tmin_X\tmax_X\tmin_Y\tmax_Y"; + + if (emig.indVar) { + if (emig.sexDep) { + if (emig.densDep) { + outrange << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; + outrange << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; + outrange << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + } + else { + outrange << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + } } else { - outrange << "\tmeanEP\tstdEP"; + if (emig.densDep) { + outrange << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; + outrange << "\tmeanBeta\tstdBeta"; + } + else { + outrange << "\tmeanEP\tstdEP"; + } } } -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outrange << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outrange << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; outrange << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; + } + if (trfr.moveType == 2) { + outrange << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + } } - if (trfr.moveType == 2) { - outrange << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; - } - } - else { - if (trfr.sexDep) { - outrange << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; - if (trfr.twinKern) - outrange << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" + else { + if (trfr.sexDep) { + outrange << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; + if (trfr.twinKern) + outrange << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" << "\tF_meanPfirstKernel\tF_stdPfirstKernel" << "\tM_meanPfirstKernel\tM_stdPfirstKernel"; + } + else { + outrange << "\tmean_distI\tstd_distI"; + if (trfr.twinKern) + outrange << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } + } + } + if (sett.indVar) { + if (sett.sexDep) { + outrange << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; + outrange << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; + outrange << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; + } else { - outrange << "\tmean_distI\tstd_distI"; - if (trfr.twinKern) - outrange << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + outrange << "\tmeanS0\tstdS0"; + outrange << "\tmeanAlphaS\tstdAlphaS"; + outrange << "\tmeanBetaS\tstdBetaS"; } } -} -if (sett.indVar) { - if (sett.sexDep) { - outrange << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; - outrange << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; - outrange << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; - - } - else { - outrange << "\tmeanS0\tstdS0"; - outrange << "\tmeanAlphaS\tstdAlphaS"; - outrange << "\tmeanBetaS\tstdBetaS"; - } -} -outrange << endl; + outrange << endl; #if RSDEBUG -DEBUGLOG << "Community::outRangeHeaders(): finished" << endl; + DEBUGLOG << "Community::outRangeHeaders(): finished" << endl; #endif -return outrange.is_open(); + return outrange.is_open(); } // Write record to range file -void Community::outRange(Species *pSpecies,int rep,int yr,int gen) +void Community::outRange(Species* pSpecies, int rep, int yr, int gen) { #if RSDEBUG -DEBUGLOG << "Community::outRange(): rep=" << rep - << " yr=" << yr << " gen=" << gen << endl; + DEBUGLOG << "Community::outRange(): rep=" << rep + << " yr=" << yr << " gen=" << gen << endl; #endif -landParams ppLand = pLandscape->getLandParams(); -envStochParams env = paramsStoch->getStoch(); - -// NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER -// ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); - -outrange << rep << "\t" << yr << "\t" << gen; -if (env.stoch && !env.local) // write global environmental stochasticity - outrange << "\t" << pLandscape->getGlobalStoch(yr); - -commStats s = getStats(); - -if (dem.stageStruct) { - outrange << "\t" << s.nnonjuvs; - int stagepop; - int nsubcomms = (int)subComms.size(); - // all non-juvenile stages - for (int stg = 1; stg < sstruct.nStages; stg++) { + landParams ppLand = pLandscape->getLandParams(); + envStochParams env = paramsStoch->getStoch(); + + // NEED TO REPLACE CONDITIONAL COLUMNS BASED ON ATTRIBUTES OF ONE SPECIES TO COVER + // ATTRIBUTES OF *ALL* SPECIES AS DETECTED AT MODEL LEVEL + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + + outrange << rep << "\t" << yr << "\t" << gen; + if (env.stoch && !env.local) // write global environmental stochasticity + outrange << "\t" << pLandscape->getGlobalStoch(yr); + + commStats s = getStats(); + + if (dem.stageStruct) { + outrange << "\t" << s.nnonjuvs; + int stagepop; + int nsubcomms = (int)subComms.size(); + // all non-juvenile stages + for (int stg = 1; stg < sstruct.nStages; stg++) { + stagepop = 0; + for (int i = 0; i < nsubcomms; i++) { // all sub-communities + stagepop += subComms[i]->stagePop(stg); + } + outrange << "\t" << stagepop; + } + // juveniles born in current reproductive season stagepop = 0; for (int i = 0; i < nsubcomms; i++) { // all sub-communities - stagepop += subComms[i]->stagePop(stg); + stagepop += subComms[i]->stagePop(0); } - outrange <<"\t" << stagepop; + outrange << "\t" << stagepop; } - // juveniles born in current reproductive season - stagepop = 0; - for (int i = 0; i < nsubcomms; i++) { // all sub-communities - stagepop += subComms[i]->stagePop(0); + else { // non-structured species + outrange << "\t" << s.ninds; } - outrange <<"\t" << stagepop; -} -else { // non-structured species - outrange << "\t" << s.ninds; -} -float occsuit = 0.0; -if (s.suitable > 0) occsuit = (float)s.occupied / (float)s.suitable; -outrange << "\t" << s.occupied << "\t" << occsuit; -// RANGE MINIMA AND MAXIMA NEED TO BECOME A PROPERTY OF THE SPECIES -if (s.ninds > 0) { - landOrigin origin = pLandscape->getOrigin(); - outrange << "\t" << (float)s.minX * (float)ppLand.resol + origin.minEast - << "\t" << (float)(s.maxX+1) * (float)ppLand.resol + origin.minEast - << "\t" << (float)s.minY * (float)ppLand.resol + origin.minNorth - << "\t" << (float)(s.maxY+1) * (float)ppLand.resol + origin.minNorth; -} -else - outrange <<"\t0\t0\t0\t0"; - -if (emig.indVar || trfr.indVar || sett.indVar) { // output trait means - traitsums ts; - traitsums scts; // sub-community traits - traitCanvas tcanv; - int ngenes,popsize; - - tcanv.pcanvas[0] = NULL; - - for (int i = 0; i < NSEXES; i++) { - ts.ninds[i] = 0; - ts.sumD0[i] = ts.ssqD0[i] = 0.0; - ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; - ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; - ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; - ts.sumDP[i] = ts.ssqDP[i] = 0.0; - ts.sumGB[i] = ts.ssqGB[i] = 0.0; - ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; - ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; - ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; - ts.sumS0[i] = ts.ssqS0[i] = 0.0; - ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + float occsuit = 0.0; + if (s.suitable > 0) occsuit = (float)s.occupied / (float)s.suitable; + outrange << "\t" << s.occupied << "\t" << occsuit; + // RANGE MINIMA AND MAXIMA NEED TO BECOME A PROPERTY OF THE SPECIES + if (s.ninds > 0) { + landOrigin origin = pLandscape->getOrigin(); + outrange << "\t" << (float)s.minX * (float)ppLand.resol + origin.minEast + << "\t" << (float)(s.maxX + 1) * (float)ppLand.resol + origin.minEast + << "\t" << (float)s.minY * (float)ppLand.resol + origin.minNorth + << "\t" << (float)(s.maxY + 1) * (float)ppLand.resol + origin.minNorth; } + else + outrange << "\t0\t0\t0\t0"; - int nsubcomms = (int)subComms.size(); - for (int i = 0; i < nsubcomms; i++) { // all sub-communities (incl. matrix) - scts = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,true); - for (int j = 0; j < NSEXES; j++) { - ts.ninds[j] += scts.ninds[j]; - ts.sumD0[j] += scts.sumD0[j]; ts.ssqD0[j] += scts.ssqD0[j]; - ts.sumAlpha[j] += scts.sumAlpha[j]; ts.ssqAlpha[j] += scts.ssqAlpha[j]; - ts.sumBeta[j] += scts.sumBeta[j]; ts.ssqBeta[j] += scts.ssqBeta[j]; - ts.sumDist1[j] += scts.sumDist1[j]; ts.ssqDist1[j] += scts.ssqDist1[j]; - ts.sumDist2[j] += scts.sumDist2[j]; ts.ssqDist2[j] += scts.ssqDist2[j]; - ts.sumProp1[j] += scts.sumProp1[j]; ts.ssqProp1[j] += scts.ssqProp1[j]; - ts.sumDP[j] += scts.sumDP[j]; ts.ssqDP[j] += scts.ssqDP[j]; - ts.sumGB[j] += scts.sumGB[j]; ts.ssqGB[j] += scts.ssqGB[j]; - ts.sumAlphaDB[j] += scts.sumAlphaDB[j]; ts.ssqAlphaDB[j] += scts.ssqAlphaDB[j]; - ts.sumBetaDB[j] += scts.sumBetaDB[j]; ts.ssqBetaDB[j] += scts.ssqBetaDB[j]; - ts.sumStepL[j] += scts.sumStepL[j]; ts.ssqStepL[j] += scts.ssqStepL[j]; - ts.sumRho[j] += scts.sumRho[j]; ts.ssqRho[j] += scts.ssqRho[j]; - ts.sumS0[j] += scts.sumS0[j]; ts.ssqS0[j] += scts.ssqS0[j]; - ts.sumAlphaS[j] += scts.sumAlphaS[j]; ts.ssqAlphaS[j] += scts.ssqAlphaS[j]; - ts.sumBetaS[j] += scts.sumBetaS[j]; ts.ssqBetaS[j] += scts.ssqBetaS[j]; -#if RSDEBUG -//DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j -// << " scts.ninds[j]=" << scts.ninds[j] -// << " scts.sumD0[j]=" << scts.sumD0[j] -// << " scts.ssqD0[j]=" << scts.ssqD0[j] -// << endl; -//DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j -// << " ts.ninds[j]=" << ts.ninds[j] -// << " ts.sumD0[j]=" << ts.sumD0[j] << " ts.ssqD0[j]=" << ts.ssqD0[j] -// << endl; -#endif - } - } + if (emig.indVar || trfr.indVar || sett.indVar) { // output trait means + traitsums ts; + traitsums scts; // sub-community traits + traitCanvas tcanv; + int ngenes, popsize; - if (emig.indVar) { - if (emig.sexDep) { // must be a sexual species - ngenes = 2; + tcanv.pcanvas[0] = NULL; + + for (int i = 0; i < NSEXES; i++) { + ts.ninds[i] = 0; + ts.sumD0[i] = ts.ssqD0[i] = 0.0; + ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; + ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; + ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; + ts.sumDP[i] = ts.ssqDP[i] = 0.0; + ts.sumGB[i] = ts.ssqGB[i] = 0.0; + ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; + ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; + ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; + ts.sumS0[i] = ts.ssqS0[i] = 0.0; + ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; - } - else { // sexual reproduction - ngenes = 1; + + int nsubcomms = (int)subComms.size(); + for (int i = 0; i < nsubcomms; i++) { // all sub-communities (incl. matrix) + scts = subComms[i]->outTraits(tcanv, pLandscape, rep, yr, gen, true); + for (int j = 0; j < NSEXES; j++) { + ts.ninds[j] += scts.ninds[j]; + ts.sumD0[j] += scts.sumD0[j]; ts.ssqD0[j] += scts.ssqD0[j]; + ts.sumAlpha[j] += scts.sumAlpha[j]; ts.ssqAlpha[j] += scts.ssqAlpha[j]; + ts.sumBeta[j] += scts.sumBeta[j]; ts.ssqBeta[j] += scts.ssqBeta[j]; + ts.sumDist1[j] += scts.sumDist1[j]; ts.ssqDist1[j] += scts.ssqDist1[j]; + ts.sumDist2[j] += scts.sumDist2[j]; ts.ssqDist2[j] += scts.ssqDist2[j]; + ts.sumProp1[j] += scts.sumProp1[j]; ts.ssqProp1[j] += scts.ssqProp1[j]; + ts.sumDP[j] += scts.sumDP[j]; ts.ssqDP[j] += scts.ssqDP[j]; + ts.sumGB[j] += scts.sumGB[j]; ts.ssqGB[j] += scts.ssqGB[j]; + ts.sumAlphaDB[j] += scts.sumAlphaDB[j]; ts.ssqAlphaDB[j] += scts.ssqAlphaDB[j]; + ts.sumBetaDB[j] += scts.sumBetaDB[j]; ts.ssqBetaDB[j] += scts.ssqBetaDB[j]; + ts.sumStepL[j] += scts.sumStepL[j]; ts.ssqStepL[j] += scts.ssqStepL[j]; + ts.sumRho[j] += scts.sumRho[j]; ts.ssqRho[j] += scts.ssqRho[j]; + ts.sumS0[j] += scts.sumS0[j]; ts.ssqS0[j] += scts.ssqS0[j]; + ts.sumAlphaS[j] += scts.sumAlphaS[j]; ts.ssqAlphaS[j] += scts.ssqAlphaS[j]; + ts.sumBetaS[j] += scts.sumBetaS[j]; ts.ssqBetaS[j] += scts.ssqBetaS[j]; } } - double mnD0[2],mnAlpha[2],mnBeta[2],sdD0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = ts.ninds[g]; - else popsize = ts.ninds[0] + ts.ninds[1]; - if (popsize > 0) { - mnD0[g] = ts.sumD0[g] / (double)popsize; - mnAlpha[g] = ts.sumAlpha[g] / (double)popsize; - mnBeta[g] = ts.sumBeta[g] / (double)popsize; - if (popsize > 1) { - sdD0[g] = ts.ssqD0[g]/(double)popsize - mnD0[g]*mnD0[g]; - if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; - sdAlpha[g] = ts.ssqAlpha[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = ts.ssqBeta[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + + if (emig.indVar) { + if (emig.sexDep) { // must be a sexual species + ngenes = 2; + } + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } -#if RSDEBUG -//DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g -// << " ts.ninds[g]=" << ts.ninds[g] -// << " ts.sumD0[g]=" << ts.sumD0[g] -// << " ts.ssqD0[g]=" << ts.ssqD0[g] -// << endl; -//DEBUGLOG << "Community::outRange(): popsize=" << popsize -// << " mnD0[g]" << mnD0[g] << " sdD0[g]" << sdD0[g] -// << endl; -#endif - } - if (emig.sexDep) { - outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; - outrange << "\t" << mnD0[1] << "\t" << sdD0[1]; - if (emig.densDep) { - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + double mnD0[2], mnAlpha[2], mnBeta[2], sdD0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = ts.ninds[g]; + else popsize = ts.ninds[0] + ts.ninds[1]; + if (popsize > 0) { + mnD0[g] = ts.sumD0[g] / (double)popsize; + mnAlpha[g] = ts.sumAlpha[g] / (double)popsize; + mnBeta[g] = ts.sumBeta[g] / (double)popsize; + if (popsize > 1) { + sdD0[g] = ts.ssqD0[g] / (double)popsize - mnD0[g] * mnD0[g]; + if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; + sdAlpha[g] = ts.ssqAlpha[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = ts.ssqBeta[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } + } } - } - else { // sex-independent - outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; - if (emig.densDep) { - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + if (emig.sexDep) { + outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; + outrange << "\t" << mnD0[1] << "\t" << sdD0[1]; + if (emig.densDep) { + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + } + else { // sex-independent + outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; + if (emig.densDep) { + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } } - } - if (trfr.indVar) { - if (trfr.moveModel) { - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ngenes = 1; - } - else { - if (trfr.sexDep) { // must be a sexual species - ngenes = 2; - } - else { + if (trfr.indVar) { + if (trfr.moveModel) { + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ngenes = 1; } - } - double mnDist1[2],mnDist2[2],mnProp1[2],mnStepL[2],mnRho[2]; - double sdDist1[2],sdDist2[2],sdProp1[2],sdStepL[2],sdRho[2]; - double mnDP[2],mnGB[2],mnAlphaDB[2],mnBetaDB[2]; - double sdDP[2],sdGB[2],sdAlphaDB[2],sdBetaDB[2]; - for (int g = 0; g < ngenes; g++) { - mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; - sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; - mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; - sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = ts.ninds[g]; - else popsize = ts.ninds[0] + ts.ninds[1]; - if (popsize > 0) { - mnDist1[g] = ts.sumDist1[g] / (double)popsize; - mnDist2[g] = ts.sumDist2[g] / (double)popsize; - mnProp1[g] = ts.sumProp1[g] / (double)popsize; - mnStepL[g] = ts.sumStepL[g] / (double)popsize; - mnRho[g] = ts.sumRho[g] / (double)popsize; - mnDP[g] = ts.sumDP[g] / (double)popsize; - mnGB[g] = ts.sumGB[g] / (double)popsize; - mnAlphaDB[g] = ts.sumAlphaDB[g] / (double)popsize; - mnBetaDB[g] = ts.sumBetaDB[g] / (double)popsize; - if (popsize > 1) { - sdDist1[g] = ts.ssqDist1[g]/(double)popsize - mnDist1[g]*mnDist1[g]; - if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; - sdDist2[g] = ts.ssqDist2[g]/(double)popsize - mnDist2[g]*mnDist2[g]; - if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; - sdProp1[g] = ts.ssqProp1[g]/(double)popsize - mnProp1[g]*mnProp1[g]; - if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; - sdStepL[g] = ts.ssqStepL[g]/(double)popsize - mnStepL[g]*mnStepL[g]; - if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; - sdRho[g] = ts.ssqRho[g]/(double)popsize - mnRho[g]*mnRho[g]; - if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; - sdDP[g] = ts.ssqDP[g]/(double)popsize - mnDP[g]*mnDP[g]; - if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; - sdGB[g] = ts.ssqGB[g]/(double)popsize - mnGB[g]*mnGB[g]; - if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; - sdAlphaDB[g] = ts.ssqAlphaDB[g]/(double)popsize - mnAlphaDB[g]*mnAlphaDB[g]; - if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; - sdBetaDB[g] = ts.ssqBetaDB[g]/(double)popsize - mnBetaDB[g]*mnBetaDB[g]; - if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + else { + if (trfr.sexDep) { // must be a sexual species + ngenes = 2; + } + else { + ngenes = 1; } } -#if RSDEBUG -//DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g -// << " ts.ninds[g]=" << ts.ninds[g] -// << " ts.sumDP[g]=" << ts.sumDP[g] << " ts.ssqDP[g]=" << ts.ssqDP[g] -// << " ts.sumGB[g]=" << ts.sumGB[g] << " ts.ssqGB[g]=" << ts.ssqGB[g] -// << endl; -//DEBUGLOG << "Community::outRange(): popsize=" << popsize -// << " mnDP[g]" << mnDP[g] << " sdDP[g]" << sdDP[g] -// << " mnGB[g]" << mnGB[g] << " sdGB[g]" << sdGB[g] -// << endl; -#endif - } - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outrange << "\t" << mnDP[0] << "\t" << sdDP[0]; - outrange << "\t" << mnGB[0] << "\t" << sdGB[0]; - outrange << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; - outrange << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; - } - if (trfr.moveType == 2) { - outrange << "\t" << mnStepL[0] << "\t" << sdStepL[0]; - outrange << "\t" << mnRho[0] << "\t" << sdRho[0]; + double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; + double sdDist1[2], sdDist2[2], sdProp1[2], sdStepL[2], sdRho[2]; + double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; + double sdDP[2], sdGB[2], sdAlphaDB[2], sdBetaDB[2]; + for (int g = 0; g < ngenes; g++) { + mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; + sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; + mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; + sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = ts.ninds[g]; + else popsize = ts.ninds[0] + ts.ninds[1]; + if (popsize > 0) { + mnDist1[g] = ts.sumDist1[g] / (double)popsize; + mnDist2[g] = ts.sumDist2[g] / (double)popsize; + mnProp1[g] = ts.sumProp1[g] / (double)popsize; + mnStepL[g] = ts.sumStepL[g] / (double)popsize; + mnRho[g] = ts.sumRho[g] / (double)popsize; + mnDP[g] = ts.sumDP[g] / (double)popsize; + mnGB[g] = ts.sumGB[g] / (double)popsize; + mnAlphaDB[g] = ts.sumAlphaDB[g] / (double)popsize; + mnBetaDB[g] = ts.sumBetaDB[g] / (double)popsize; + if (popsize > 1) { + sdDist1[g] = ts.ssqDist1[g] / (double)popsize - mnDist1[g] * mnDist1[g]; + if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; + sdDist2[g] = ts.ssqDist2[g] / (double)popsize - mnDist2[g] * mnDist2[g]; + if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; + sdProp1[g] = ts.ssqProp1[g] / (double)popsize - mnProp1[g] * mnProp1[g]; + if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; + sdStepL[g] = ts.ssqStepL[g] / (double)popsize - mnStepL[g] * mnStepL[g]; + if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; + sdRho[g] = ts.ssqRho[g] / (double)popsize - mnRho[g] * mnRho[g]; + if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; + sdDP[g] = ts.ssqDP[g] / (double)popsize - mnDP[g] * mnDP[g]; + if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; + sdGB[g] = ts.ssqGB[g] / (double)popsize - mnGB[g] * mnGB[g]; + if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; + sdAlphaDB[g] = ts.ssqAlphaDB[g] / (double)popsize - mnAlphaDB[g] * mnAlphaDB[g]; + if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; + sdBetaDB[g] = ts.ssqBetaDB[g] / (double)popsize - mnBetaDB[g] * mnBetaDB[g]; + if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + } + } } - } - else { - if (trfr.sexDep) { - outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - outrange << "\t" << mnDist1[1] << "\t" << sdDist1[1]; - if (trfr.twinKern) - { - outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outrange << "\t" << mnDist2[1] << "\t" << sdDist2[1]; - outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; - outrange << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outrange << "\t" << mnDP[0] << "\t" << sdDP[0]; + outrange << "\t" << mnGB[0] << "\t" << sdGB[0]; + outrange << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; + outrange << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; + } + if (trfr.moveType == 2) { + outrange << "\t" << mnStepL[0] << "\t" << sdStepL[0]; + outrange << "\t" << mnRho[0] << "\t" << sdRho[0]; } } - else { // sex-independent - outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - if (trfr.twinKern) - { - outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + else { + if (trfr.sexDep) { + outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + outrange << "\t" << mnDist1[1] << "\t" << sdDist1[1]; + if (trfr.twinKern) + { + outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outrange << "\t" << mnDist2[1] << "\t" << sdDist2[1]; + outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + outrange << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + } + } + else { // sex-independent + outrange << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + if (trfr.twinKern) + { + outrange << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outrange << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + } } } } - } - if (sett.indVar) { - if (sett.sexDep) { // must be a sexual species - ngenes = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; - } - else { // sexual reproduction - ngenes = 1; + if (sett.indVar) { + if (sett.sexDep) { // must be a sexual species + ngenes = 2; } - } - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - double mnS0[2],mnAlpha[2],mnBeta[2],sdS0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = ts.ninds[g]; - else popsize = ts.ninds[0] + ts.ninds[1]; - if (popsize > 0) { - mnS0[g] = ts.sumS0[g] / (double)popsize; - mnAlpha[g] = ts.sumAlphaS[g] / (double)popsize; - mnBeta[g] = ts.sumBetaS[g] / (double)popsize; - if (popsize > 1) { - sdS0[g] = ts.ssqS0[g]/(double)popsize - mnS0[g]*mnS0[g]; - if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; - sdAlpha[g] = ts.ssqAlphaS[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = ts.ssqBetaS[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = ts.ninds[g]; + else popsize = ts.ninds[0] + ts.ninds[1]; + if (popsize > 0) { + mnS0[g] = ts.sumS0[g] / (double)popsize; + mnAlpha[g] = ts.sumAlphaS[g] / (double)popsize; + mnBeta[g] = ts.sumBetaS[g] / (double)popsize; + if (popsize > 1) { + sdS0[g] = ts.ssqS0[g] / (double)popsize - mnS0[g] * mnS0[g]; + if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; + sdAlpha[g] = ts.ssqAlphaS[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = ts.ssqBetaS[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } + } + } + if (sett.sexDep) { + outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; + outrange << "\t" << mnS0[1] << "\t" << sdS0[1]; + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + else { + outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; + outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } - if (sett.sexDep) { - outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; - outrange << "\t" << mnS0[1] << "\t" << sdS0[1]; - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outrange << "\t" << mnBeta[1] << "\t" << sdBeta[1]; - } - else { - outrange << "\t" << mnS0[0] << "\t" << sdS0[0]; - outrange << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outrange << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - } - } -} + } -outrange << endl; + outrange << endl; } // Open occupancy file, write header record and set up occupancy array bool Community::outOccupancyHeaders(int option) { -if (option == -999) { // close the files - if (outsuit.is_open()) outsuit.close(); - if (outoccup.is_open()) outoccup.close(); - outsuit.clear(); outoccup.clear(); - return true; -} + if (option == -999) { // close the files + if (outsuit.is_open()) outsuit.close(); + if (outoccup.is_open()) outoccup.close(); + outsuit.clear(); outoccup.clear(); + return true; + } -string name, nameI; -simParams sim = paramsSim->getSim(); -//demogrParams dem = pSpecies->getDemogr(); -landParams ppLand = pLandscape->getLandParams(); -int outrows = (sim.years/sim.outIntOcc) + 1; + string name, nameI; + simParams sim = paramsSim->getSim(); + landParams ppLand = pLandscape->getLandParams(); + int outrows = (sim.years / sim.outIntOcc) + 1; -name = paramsSim->getDir(2); -if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); -} -else - name += "Sim" + Int2Str(sim.simulation); -name += "_Occupancy_Stats.txt"; -outsuit.open(name.c_str()); -outsuit << "Year\tMean_OccupSuit\tStd_error" << endl; - -name = paramsSim->getDir(2); -if (sim.batchMode) { - name += "Batch" + Int2Str(sim.batchNum) + "_"; - name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); -} -else - name += "Sim" + Int2Str(sim.simulation); -name += "_Occupancy.txt"; -outoccup.open(name.c_str()); -if (ppLand.patchModel) { - outoccup << "PatchID"; -} -else { - outoccup << "X\tY"; -} -for (int i = 0; i < outrows; i++) - outoccup << "\t" << "Year_" << i*sim.outIntOcc; -outoccup << endl; + name = paramsSim->getDir(2); + if (sim.batchMode) { + name += "Batch" + Int2Str(sim.batchNum) + "_"; + name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); + } + else + name += "Sim" + Int2Str(sim.simulation); + name += "_Occupancy_Stats.txt"; + outsuit.open(name.c_str()); + outsuit << "Year\tMean_OccupSuit\tStd_error" << endl; + + name = paramsSim->getDir(2); + if (sim.batchMode) { + name += "Batch" + Int2Str(sim.batchNum) + "_"; + name += "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum); + } + else + name += "Sim" + Int2Str(sim.simulation); + name += "_Occupancy.txt"; + outoccup.open(name.c_str()); + if (ppLand.patchModel) { + outoccup << "PatchID"; + } + else { + outoccup << "X\tY"; + } + for (int i = 0; i < outrows; i++) + outoccup << "\t" << "Year_" << i * sim.outIntOcc; + outoccup << endl; -// Initialise cells/patches occupancy array -createOccupancy(outrows,sim.reps); + // Initialise cells/patches occupancy array + createOccupancy(outrows, sim.reps); -return outsuit.is_open() && outoccup.is_open(); + return outsuit.is_open() && outoccup.is_open(); } void Community::outOccupancy(void) { -landParams ppLand = pLandscape->getLandParams(); -simParams sim = paramsSim->getSim(); -//streamsize prec = outoccup.precision(); -locn loc; + landParams ppLand = pLandscape->getLandParams(); + simParams sim = paramsSim->getSim(); + locn loc; -int nsubcomms = (int)subComms.size(); -for (int i = 1; i < nsubcomms; i++) { // all except matrix sub-community - if (ppLand.patchModel) { - outoccup << subComms[i]->getPatch()->getPatchNum(); - } - else { - loc = subComms[i]->getLocn(); - outoccup << loc.x << "\t" << loc.y; - } - for (int row = 0; row <= (sim.years/sim.outIntOcc); row++) - { - outoccup << "\t" << (double)subComms[i]->getOccupancy(row)/(double)sim.reps; + int nsubcomms = (int)subComms.size(); + for (int i = 1; i < nsubcomms; i++) { // all except matrix sub-community + if (ppLand.patchModel) { + outoccup << subComms[i]->getPatch()->getPatchNum(); + } + else { + loc = subComms[i]->getLocn(); + outoccup << loc.x << "\t" << loc.y; + } + for (int row = 0; row <= (sim.years / sim.outIntOcc); row++) + { + outoccup << "\t" << (double)subComms[i]->getOccupancy(row) / (double)sim.reps; + } + outoccup << endl; } - outoccup << endl; -} } void Community::outOccSuit(bool view) { -double sum,ss,mean,sd,se; -simParams sim = paramsSim->getSim(); -//streamsize prec = outsuit.precision(); - -#if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): sim.reps=" << sim.reps -// << " sim.years=" << sim.years << " sim.outInt=" << sim.outInt << endl; -#endif -for (int i = 0; i < (sim.years/sim.outIntOcc)+1; i++) { - sum = ss = 0.0; - for (int rep = 0; rep < sim.reps; rep++) { - sum += occSuit[i][rep]; - ss += occSuit[i][rep] * occSuit[i][rep]; -#if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): i=" << i << " rep=" << rep -// << " occSuit[i][rep]=" << occSuit[i][rep] -// << " sum=" << sum << " ss=" << ss -// << endl; -#endif + double sum, ss, mean, sd, se; + simParams sim = paramsSim->getSim(); + for (int i = 0; i < (sim.years / sim.outIntOcc) + 1; i++) { + sum = ss = 0.0; + for (int rep = 0; rep < sim.reps; rep++) { + sum += occSuit[i][rep]; + ss += occSuit[i][rep] * occSuit[i][rep]; + } + mean = sum / (double)sim.reps; + sd = (ss - (sum * sum / (double)sim.reps)) / (double)(sim.reps - 1); + if (sd > 0.0) sd = sqrt(sd); + else sd = 0.0; + se = sd / sqrt((double)(sim.reps)); + outsuit << i * sim.outIntOcc << "\t" << mean << "\t" << se << endl; + if (view) viewOccSuit(i * sim.outIntOcc, mean, se); } - mean = sum/(double)sim.reps; - sd = (ss - (sum*sum/(double)sim.reps)) / (double)(sim.reps-1); -#if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): i=" << i -// << " mean=" << mean << " sd=" << sd << endl; -#endif - if (sd > 0.0) sd = sqrt(sd); - else sd = 0.0; - se = sd / sqrt((double)(sim.reps)); -#if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): i=" << i -// << " sd=" << sd << " se=" << se << endl; -#endif - -// outsuit << i*sim.outInt << "\t" << mean << "\t" << se << endl; -// if (view) viewOccSuit(i*sim.outInt,mean,se); - outsuit << i*sim.outIntOcc << "\t" << mean << "\t" << se << endl; - if (view) viewOccSuit(i*sim.outIntOcc,mean,se); -} } // Open traits file and write header record -bool Community::outTraitsHeaders(Species *pSpecies,int landNr) { -return subComms[0]->outTraitsHeaders(pLandscape,pSpecies,landNr); +bool Community::outTraitsHeaders(Species* pSpecies, int landNr) { + return subComms[0]->outTraitsHeaders(pLandscape, pSpecies, landNr); } // Write records to traits file @@ -1306,366 +1212,306 @@ only, this function relies on the fact that subcommunities are created in the sa sequence as patches, which is in asecending order of x nested within descending order of y */ -//void Community::outTraits(emigCanvas ecanv,trfrCanvas tcanv,Species *pSpecies, -// int rep,int yr,int gen) -void Community::outTraits(traitCanvas tcanv,Species *pSpecies, - int rep,int yr,int gen) +void Community::outTraits(traitCanvas tcanv, Species* pSpecies, + int rep, int yr, int gen) { -simParams sim = paramsSim->getSim(); -simView v = paramsSim->getViews(); -landParams land = pLandscape->getLandParams(); -//demogrParams dem = pSpecies->getDemogr(); -//emigRules emig = pSpecies->getEmig(); -//trfrRules trfr = pSpecies->getTrfr(); -//locn loc; -traitsums *ts = 0; -traitsums sctraits; -if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) { - // create array of traits means, etc., one for each row - ts = new traitsums[land.dimY]; - for (int y = 0; y < land.dimY; y++) { - for (int i = 0; i < NSEXES; i++) { - ts[y].ninds[i] = 0; - ts[y].sumD0[i] = ts[y].ssqD0[i] = 0.0; - ts[y].sumAlpha[i] = ts[y].ssqAlpha[i] = 0.0; - ts[y].sumBeta[i] = ts[y].ssqBeta[i] = 0.0; - ts[y].sumDist1[i] = ts[y].ssqDist1[i] = 0.0; - ts[y].sumDist2[i] = ts[y].ssqDist2[i] = 0.0; - ts[y].sumProp1[i] = ts[y].ssqProp1[i] = 0.0; - ts[y].sumStepL[i] = ts[y].ssqStepL[i] = 0.0; - ts[y].sumRho[i] = ts[y].ssqRho[i] = 0.0; - ts[y].sumS0[i] = ts[y].ssqS0[i] = 0.0; - ts[y].sumAlphaS[i] = ts[y].ssqAlphaS[i] = 0.0; - ts[y].sumBetaS[i] = ts[y].ssqBetaS[i] = 0.0; + simParams sim = paramsSim->getSim(); + simView v = paramsSim->getViews(); + landParams land = pLandscape->getLandParams(); + traitsums* ts = 0; + traitsums sctraits; + if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { + // create array of traits means, etc., one for each row + ts = new traitsums[land.dimY]; + for (int y = 0; y < land.dimY; y++) { + for (int i = 0; i < NSEXES; i++) { + ts[y].ninds[i] = 0; + ts[y].sumD0[i] = ts[y].ssqD0[i] = 0.0; + ts[y].sumAlpha[i] = ts[y].ssqAlpha[i] = 0.0; + ts[y].sumBeta[i] = ts[y].ssqBeta[i] = 0.0; + ts[y].sumDist1[i] = ts[y].ssqDist1[i] = 0.0; + ts[y].sumDist2[i] = ts[y].ssqDist2[i] = 0.0; + ts[y].sumProp1[i] = ts[y].ssqProp1[i] = 0.0; + ts[y].sumStepL[i] = ts[y].ssqStepL[i] = 0.0; + ts[y].sumRho[i] = ts[y].ssqRho[i] = 0.0; + ts[y].sumS0[i] = ts[y].ssqS0[i] = 0.0; + ts[y].sumAlphaS[i] = ts[y].ssqAlphaS[i] = 0.0; + ts[y].sumBetaS[i] = ts[y].ssqBetaS[i] = 0.0; + } } } -} -if (v.viewTraits -|| ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr%sim.outIntTraitCell == 0) || - (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0))) -{ - // generate output for each sub-community (patch) in the community - int nsubcomms = (int)subComms.size(); - for (int i = 1; i < nsubcomms; i++) { // // all except matrix sub-community -// sctraits = subComms[i]->outTraits(ecanv,tcanv,pLandscape,rep,yr,gen); -// sctraits = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,v.viewGrad); - sctraits = subComms[i]->outTraits(tcanv,pLandscape,rep,yr,gen,false); - locn loc = subComms[i]->getLocn(); - int y = loc.y; - if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) - { - for (int s = 0; s < NSEXES; s++) { - ts[y].ninds[s] += sctraits.ninds[s]; - ts[y].sumD0[s] += sctraits.sumD0[s]; ts[y].ssqD0[s] += sctraits.ssqD0[s]; - ts[y].sumAlpha[s] += sctraits.sumAlpha[s]; ts[y].ssqAlpha[s] += sctraits.ssqAlpha[s]; - ts[y].sumBeta[s] += sctraits.sumBeta[s]; ts[y].ssqBeta[s] += sctraits.ssqBeta[s]; - ts[y].sumDist1[s] += sctraits.sumDist1[s]; ts[y].ssqDist1[s] += sctraits.ssqDist1[s]; - ts[y].sumDist2[s] += sctraits.sumDist2[s]; ts[y].ssqDist2[s] += sctraits.ssqDist2[s]; - ts[y].sumProp1[s] += sctraits.sumProp1[s]; ts[y].ssqProp1[s] += sctraits.ssqProp1[s]; - ts[y].sumStepL[s] += sctraits.sumStepL[s]; ts[y].ssqStepL[s] += sctraits.ssqStepL[s]; - ts[y].sumRho[s] += sctraits.sumRho[s]; ts[y].ssqRho[s] += sctraits.ssqRho[s]; - ts[y].sumS0[s] += sctraits.sumS0[s]; ts[y].ssqS0[s] += sctraits.ssqS0[s]; - ts[y].sumAlphaS[s] += sctraits.sumAlphaS[s]; ts[y].ssqAlphaS[s] += sctraits.ssqAlphaS[s]; - ts[y].sumBetaS[s] += sctraits.sumBetaS[s]; ts[y].ssqBetaS[s] += sctraits.ssqBetaS[s]; + if (v.viewTraits + || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || + (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0))) + { + // generate output for each sub-community (patch) in the community + int nsubcomms = (int)subComms.size(); + for (int i = 1; i < nsubcomms; i++) { // // all except matrix sub-community + sctraits = subComms[i]->outTraits(tcanv, pLandscape, rep, yr, gen, false); + locn loc = subComms[i]->getLocn(); + int y = loc.y; + if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) + { + for (int s = 0; s < NSEXES; s++) { + ts[y].ninds[s] += sctraits.ninds[s]; + ts[y].sumD0[s] += sctraits.sumD0[s]; ts[y].ssqD0[s] += sctraits.ssqD0[s]; + ts[y].sumAlpha[s] += sctraits.sumAlpha[s]; ts[y].ssqAlpha[s] += sctraits.ssqAlpha[s]; + ts[y].sumBeta[s] += sctraits.sumBeta[s]; ts[y].ssqBeta[s] += sctraits.ssqBeta[s]; + ts[y].sumDist1[s] += sctraits.sumDist1[s]; ts[y].ssqDist1[s] += sctraits.ssqDist1[s]; + ts[y].sumDist2[s] += sctraits.sumDist2[s]; ts[y].ssqDist2[s] += sctraits.ssqDist2[s]; + ts[y].sumProp1[s] += sctraits.sumProp1[s]; ts[y].ssqProp1[s] += sctraits.ssqProp1[s]; + ts[y].sumStepL[s] += sctraits.sumStepL[s]; ts[y].ssqStepL[s] += sctraits.ssqStepL[s]; + ts[y].sumRho[s] += sctraits.sumRho[s]; ts[y].ssqRho[s] += sctraits.ssqRho[s]; + ts[y].sumS0[s] += sctraits.sumS0[s]; ts[y].ssqS0[s] += sctraits.ssqS0[s]; + ts[y].sumAlphaS[s] += sctraits.sumAlphaS[s]; ts[y].ssqAlphaS[s] += sctraits.ssqAlphaS[s]; + ts[y].sumBetaS[s] += sctraits.sumBetaS[s]; ts[y].ssqBetaS[s] += sctraits.ssqBetaS[s]; + } } } - } - if (nsubcomms > 0 && sim.outTraitsRows - && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) { - for (int y = 0; y < land.dimY; y++) { - if ((ts[y].ninds[0]+ts[y].ninds[1]) > 0) { - writeTraitsRows(pSpecies,rep,yr,gen,y,ts[y]); + if (nsubcomms > 0 && sim.outTraitsRows + && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0) { + for (int y = 0; y < land.dimY; y++) { + if ((ts[y].ninds[0] + ts[y].ninds[1]) > 0) { + writeTraitsRows(pSpecies, rep, yr, gen, y, ts[y]); + } } } } -} -//if (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0) -//{ -// if (ts != 0) delete[] ts; -//} -if (ts != 0) { delete[] ts; ts = 0; } + if (ts != 0) { delete[] ts; ts = 0; } } // Write records to trait rows file -void Community::writeTraitsRows(Species *pSpecies,int rep,int yr,int gen,int y, +void Community::writeTraitsRows(Species* pSpecies, int rep, int yr, int gen, int y, traitsums ts) { -//simParams sim = paramsSim->getSim(); -//simView v = paramsSim->getViews(); -//landData land = pLandscape->getLandData(); -//landOrigin origin = pLandscape->getOrigin(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -double mn,sd; - -// calculate population size in case one phase is sex-dependent and the other is not -// (in which case numbers of individuals are recorded by sex) -int popsize = ts.ninds[0] + ts.ninds[1]; -outtraitsrows << rep << "\t" << yr << "\t" << gen - << "\t" << y; -// << "\t" << y*land.resol + origin.minNorth; -if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) - outtraitsrows << "\t" << ts.ninds[0] << "\t" << ts.ninds[1]; -else - outtraitsrows << "\t" << popsize; - -if (emig.indVar) { - if (emig.sexDep) { - if (ts.ninds[0] > 0) mn = ts.sumD0[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqD0[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumD0[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqD0[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (emig.densDep) { - if (ts.ninds[0] > 0) mn = ts.sumAlpha[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqAlpha[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumAlpha[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqAlpha[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[0] > 0) mn = ts.sumBeta[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqBeta[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumBeta[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqBeta[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - } - } - else { // no sex dependence in emigration - if (popsize > 0) mn = ts.sumD0[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqD0[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (emig.densDep) { - if (popsize > 0) mn = ts.sumAlpha[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqAlpha[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumBeta[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqBeta[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - } - } -} + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + double mn, sd; + + // calculate population size in case one phase is sex-dependent and the other is not + // (in which case numbers of individuals are recorded by sex) + int popsize = ts.ninds[0] + ts.ninds[1]; + outtraitsrows << rep << "\t" << yr << "\t" << gen + << "\t" << y; + if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) + outtraitsrows << "\t" << ts.ninds[0] << "\t" << ts.ninds[1]; + else + outtraitsrows << "\t" << popsize; -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 2) { // CRW - // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... - if (popsize > 0) mn = ts.sumStepL[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqStepL[0]/(double)popsize - mn*mn; else sd = 0.0; + if (emig.indVar) { + if (emig.sexDep) { + if (ts.ninds[0] > 0) mn = ts.sumD0[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqD0[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumRho[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqRho[0]/(double)popsize - mn*mn; else sd = 0.0; + if (ts.ninds[1] > 0) mn = ts.sumD0[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqD0[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumStepL[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqStepL[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumRho[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqRho[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; + if (emig.densDep) { + if (ts.ninds[0] > 0) mn = ts.sumAlpha[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqAlpha[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumAlpha[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqAlpha[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[0] > 0) mn = ts.sumBeta[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqBeta[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumBeta[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqBeta[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } } - } - else { // dispersal kernel - if (trfr.sexDep) { - if (ts.ninds[0] > 0) mn = ts.sumDist1[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqDist1[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumDist1[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqDist1[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + else { // no sex dependence in emigration + if (popsize > 0) mn = ts.sumD0[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqD0[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (trfr.twinKern) - { - if (ts.ninds[0] > 0) mn = ts.sumDist2[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqDist2[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + if (emig.densDep) { + if (popsize > 0) mn = ts.sumAlpha[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqAlpha[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumDist2[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqDist2[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumBeta[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqBeta[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[0] > 0) mn = ts.sumProp1[0]/(double)ts.ninds[0]; else mn = 0.0; - if (ts.ninds[0] > 1) sd = ts.ssqProp1[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; + } + } + } + + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 2) { // CRW + // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... + if (popsize > 0) mn = ts.sumStepL[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqStepL[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (ts.ninds[1] > 0) mn = ts.sumProp1[1]/(double)ts.ninds[1]; else mn = 0.0; - if (ts.ninds[1] > 1) sd = ts.ssqProp1[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumRho[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqRho[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; } } - else { // sex-independent - if (popsize > 0) mn = ts.sumDist1[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqDist1[0]/(double)popsize - mn*mn; else sd = 0.0; - if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; - outtraitsrows << "\t" << mn << "\t" << sd; - if (trfr.twinKern) - { - if (popsize > 0) mn = ts.sumDist2[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqDist2[0]/(double)popsize - mn*mn; else sd = 0.0; + else { // dispersal kernel + if (trfr.sexDep) { + if (ts.ninds[0] > 0) mn = ts.sumDist1[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqDist1[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumDist1[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqDist1[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumProp1[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqProp1[0]/(double)popsize - mn*mn; else sd = 0.0; + if (trfr.twinKern) + { + if (ts.ninds[0] > 0) mn = ts.sumDist2[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqDist2[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumDist2[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqDist2[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[0] > 0) mn = ts.sumProp1[0] / (double)ts.ninds[0]; else mn = 0.0; + if (ts.ninds[0] > 1) sd = ts.ssqProp1[0] / (double)ts.ninds[0] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (ts.ninds[1] > 0) mn = ts.sumProp1[1] / (double)ts.ninds[1]; else mn = 0.0; + if (ts.ninds[1] > 1) sd = ts.ssqProp1[1] / (double)ts.ninds[1] - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } + } + else { // sex-independent + if (popsize > 0) mn = ts.sumDist1[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqDist1[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; + if (trfr.twinKern) + { + if (popsize > 0) mn = ts.sumDist2[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqDist2[0] / (double)popsize - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + if (popsize > 0) mn = ts.sumProp1[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqProp1[0] / (double)popsize - mn * mn; else sd = 0.0; + if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; + outtraitsrows << "\t" << mn << "\t" << sd; + } } } } -} -if (sett.indVar) { - // NB - CURRENTLY CANNOT BE SEX-DEPENDENT... -// if (sett.sexDep) { -// if (ts.ninds[0] > 0) mn = ts.sumS0[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqS0[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[1] > 0) mn = ts.sumS0[1]/(double)ts.ninds[1]; else mn = 0.0; -// if (ts.ninds[1] > 1) sd = ts.ssqS0[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumAlphaS[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqAlphaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[1] > 0) mn = ts.sumAlphaS[1]/(double)ts.ninds[1]; else mn = 0.0; -// if (ts.ninds[1] > 1) sd = ts.ssqAlphaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[0] > 0) mn = ts.sumBetaS[0]/(double)ts.ninds[0]; else mn = 0.0; -// if (ts.ninds[0] > 1) sd = ts.ssqBetaS[0]/(double)ts.ninds[0] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// if (ts.ninds[1] > 0) mn = ts.sumBetaS[1]/(double)ts.ninds[1]; else mn = 0.0; -// if (ts.ninds[1] > 1) sd = ts.ssqBetaS[1]/(double)ts.ninds[1] - mn*mn; else sd = 0.0; -// if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; -// outtraitsrows << "\t" << mn << "\t" << sd; -// } -// else { // no sex dependence in settlement - if (popsize > 0) mn = ts.sumS0[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqS0[0]/(double)popsize - mn*mn; else sd = 0.0; + if (sett.indVar) { + if (popsize > 0) mn = ts.sumS0[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqS0[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumAlphaS[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqAlphaS[0]/(double)popsize - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumAlphaS[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqAlphaS[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; - if (popsize > 0) mn = ts.sumBetaS[0]/(double)popsize; else mn = 0.0; - if (popsize > 1) sd = ts.ssqBetaS[0]/(double)popsize - mn*mn; else sd = 0.0; + if (popsize > 0) mn = ts.sumBetaS[0] / (double)popsize; else mn = 0.0; + if (popsize > 1) sd = ts.ssqBetaS[0] / (double)popsize - mn * mn; else sd = 0.0; if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; outtraitsrows << "\t" << mn << "\t" << sd; -// } -} + // } + } -outtraitsrows << endl; + outtraitsrows << endl; } // Open trait rows file and write header record -bool Community::outTraitsRowsHeaders(Species *pSpecies,int landNr) { +bool Community::outTraitsRowsHeaders(Species* pSpecies, int landNr) { -if (landNr == -999) { // close file - if (outtraitsrows.is_open()) outtraitsrows.close(); - outtraitsrows.clear(); - return true; -} + if (landNr == -999) { // close file + if (outtraitsrows.is_open()) outtraitsrows.close(); + outtraitsrows.clear(); + return true; + } -string name; -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -simParams sim = paramsSim->getSim(); - -string DirOut = paramsSim->getDir(2); -if (sim.batchMode) { - name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_TraitsXrow.txt"; -} -else { - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXrow.txt"; -} -outtraitsrows.open(name.c_str()); - -outtraitsrows << "Rep\tYear\tRepSeason\ty"; -if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) - outtraitsrows << "\tN_females\tN_males"; -else - outtraitsrows << "\tN"; - -if (emig.indVar) { - if (emig.sexDep) { - if (emig.densDep) { - outtraitsrows << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; - outtraitsrows << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; - outtraitsrows << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; - } - else { - outtraitsrows << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; - } + string name; + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + simParams sim = paramsSim->getSim(); + + string DirOut = paramsSim->getDir(2); + if (sim.batchMode) { + name = DirOut + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + "_TraitsXrow.txt"; } else { - if (emig.densDep) { - outtraitsrows << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; - outtraitsrows << "\tmeanBeta\tstdBeta"; + name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXrow.txt"; + } + outtraitsrows.open(name.c_str()); + + outtraitsrows << "Rep\tYear\tRepSeason\ty"; + if ((emig.indVar && emig.sexDep) || (trfr.indVar && trfr.sexDep)) + outtraitsrows << "\tN_females\tN_males"; + else + outtraitsrows << "\tN"; + + if (emig.indVar) { + if (emig.sexDep) { + if (emig.densDep) { + outtraitsrows << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; + outtraitsrows << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; + outtraitsrows << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + } + else { + outtraitsrows << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + } } else { - outtraitsrows << "\tmeanEP\tstdEP"; + if (emig.densDep) { + outtraitsrows << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; + outtraitsrows << "\tmeanBeta\tstdBeta"; + } + else { + outtraitsrows << "\tmeanEP\tstdEP"; + } } } -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 2) { - outtraitsrows << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 2) { + outtraitsrows << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + } } - } - else { // dispersal kernel - if (trfr.sexDep) { - outtraitsrows << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; - if (trfr.twinKern) - outtraitsrows << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" + else { // dispersal kernel + if (trfr.sexDep) { + outtraitsrows << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; + if (trfr.twinKern) + outtraitsrows << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" << "\tF_meanPfirstKernel\tF_stdPfirstKernel" << "\tM_meanPfirstKernel\tM_stdPfirstKernel"; - } - else { - outtraitsrows << "\tmean_distI\tstd_distI"; - if (trfr.twinKern) - outtraitsrows << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } + else { + outtraitsrows << "\tmean_distI\tstd_distI"; + if (trfr.twinKern) + outtraitsrows << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } } } -} -if (sett.indVar) { -// if (sett.sexDep) { -// outtraitsrows << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; -// outtraitsrows << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; -// outtraitsrows << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; -// } -// else { + if (sett.indVar) { outtraitsrows << "\tmeanS0\tstdS0"; outtraitsrows << "\tmeanAlphaS\tstdAlphaS"; outtraitsrows << "\tmeanBetaS\tstdBetaS"; -// } -} -outtraitsrows << endl; + } + outtraitsrows << endl; -return outtraitsrows.is_open(); + return outtraitsrows.is_open(); } @@ -1673,42 +1519,41 @@ return outtraitsrows.is_open(); Rcpp::IntegerMatrix Community::addYearToPopList(int rep, int yr) { // TODO: define new simparams to control start and interval of output landParams ppLand = pLandscape->getLandParams(); - Rcpp::IntegerMatrix pop_map_year(ppLand.dimY,ppLand.dimX); + Rcpp::IntegerMatrix pop_map_year(ppLand.dimY, ppLand.dimX); intptr patch = 0; Patch* pPatch = 0; intptr subcomm = 0; - SubCommunity *pSubComm = 0; + SubCommunity* pSubComm = 0; popStats pop; - //pop.breeding = false; pop.nInds = pop.nAdults = pop.nNonJuvs = 0; for (int y = 0; y < ppLand.dimY; y++) { for (int x = 0; x < ppLand.dimX; x++) { - Cell *pCell = pLandscape->findCell(x,y); //if (pLandscape->cells[y][x] == 0) { + Cell* pCell = pLandscape->findCell(x, y); if (pCell == 0) { // no-data cell - pop_map_year(ppLand.dimY-1-y,x) = NA_INTEGER; - } else { + pop_map_year(ppLand.dimY - 1 - y, x) = NA_INTEGER; + } + else { patch = pCell->getPatch(); if (patch == 0) { // matrix cell - pop_map_year(ppLand.dimY-1-y,x) = 0; + pop_map_year(ppLand.dimY - 1 - y, x) = 0; } - else{ + else { pPatch = (Patch*)patch; subcomm = pPatch->getSubComm(); if (subcomm == 0) { // check if sub-community exists - pop_map_year(ppLand.dimY-1-y,x) = 0; - } else { + pop_map_year(ppLand.dimY - 1 - y, x) = 0; + } + else { pSubComm = (SubCommunity*)subcomm; pop = pSubComm->getPopStats(); - pop_map_year(ppLand.dimY-1-y,x) = pop.nInds; // use indices like this because matrix gets transposed upon casting it into a raster on R-level - //pop_map_year(ppLand.dimY-1-y,x) = pop.nAdults; + pop_map_year(ppLand.dimY - 1 - y, x) = pop.nInds; // use indices like this because matrix gets transposed upon casting it into a raster on R-level } } } } } - //list_outPop.push_back(pop_map_year, "rep" + std::to_string(rep) + "_year" + std::to_string(yr)); - return pop_map_year; + return pop_map_year; } #endif diff --git a/Community.h b/Community.h index 36a4a12..73f3ce1 100644 --- a/Community.h +++ b/Community.h @@ -56,9 +56,6 @@ using namespace std; #include "../Version.h" #endif -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif #include "SubCommunity.h" #include "Landscape.h" #include "Patch.h" @@ -103,12 +100,12 @@ class Community { void survival( short, // part: 0 = determine survival & development, - // 1 = apply survival changes to the population + // 1 = apply survival changes to the population short, // option0: 0 = stage 0 (juveniles) only ) - // 1 = all stages ) used by part 0 only - // 2 = stage 1 and above (all non-juvs) ) + // 1 = all stages ) used by part 0 only + // 2 = stage 1 and above (all non-juvs) ) short // option1: 0 - development only (when survival is annual) - // 1 - development and survival + // 1 - development and survival ); void ageIncrement(void); int totalInds(void); @@ -187,8 +184,6 @@ class Community { ); void outTraits( // Write records to traits file traitCanvas,// pointers to canvases for drawing variable traits -// emigCanvas, // pointers to canvases for drawing emigration traits -// trfrCanvas, // pointers to canvases for drawing emigration traits // see SubCommunity.h // in the batch version, these are replaced by integers set to zero Species*, // pointer to Species From 22f2e5b3839187329aedc4f8e0aa535f742e1637 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 28 Nov 2023 16:13:50 +0000 Subject: [PATCH 20/46] rm commented out code and fix indent in SubCommunity and Population --- Population.cpp | 3 - SubCommunity.cpp | 1700 ++++++++++++++++++++-------------------------- SubCommunity.h | 9 +- 3 files changed, 754 insertions(+), 958 deletions(-) diff --git a/Population.cpp b/Population.cpp index 4af1e84..3dbb6a2 100644 --- a/Population.cpp +++ b/Population.cpp @@ -1163,9 +1163,6 @@ void Population::survival0(float localK, short option0, short option1) for (int stg = 0; stg < nStages; stg++) { for (int sex = 0; sex < nsexes; sex++) { if (option1 != 2 && sstruct.devDens && stg > 0) { -#if RSDEBUG - // DEBUGLOG << "DD in DEVELOPMENT for stg=" << stg << " sex=" << sex << endl; -#endif // NB DD in development does NOT apply to juveniles, // which must develop to stage 1 if they survive float effect = 0.0; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 26685e3..d908892 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "SubCommunity.h" //--------------------------------------------------------------------------- @@ -30,22 +30,22 @@ ofstream outtraits; //--------------------------------------------------------------------------- SubCommunity::SubCommunity(Patch* pPch, int num) { -subCommNum = num; -pPatch = pPch; -// record the new sub-community no. in the patch -pPatch->setSubComm((intptr)this); -initial = false; -occupancy = 0; + subCommNum = num; + pPatch = pPch; + // record the new sub-community no. in the patch + pPatch->setSubComm((intptr)this); + initial = false; + occupancy = 0; } SubCommunity::~SubCommunity() { -pPatch->setSubComm(0); -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - delete popns[i]; -} -popns.clear(); -if (occupancy != 0) delete[] occupancy; + pPatch->setSubComm(0); + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + delete popns[i]; + } + popns.clear(); + if (occupancy != 0) delete[] occupancy; } intptr SubCommunity::getNum(void) { return subCommNum; } @@ -53,192 +53,142 @@ intptr SubCommunity::getNum(void) { return subCommNum; } Patch* SubCommunity::getPatch(void) { return pPatch; } locn SubCommunity::getLocn(void) { -locn loc = pPatch->getCellLocn(0); -return loc; + locn loc = pPatch->getCellLocn(0); + return loc; } void SubCommunity::setInitial(bool b) { initial = b; } -void SubCommunity::initialise(Landscape *pLandscape,Species *pSpecies) +void SubCommunity::initialise(Landscape* pLandscape, Species* pSpecies) { -//patchLimits limits; -//locn loc; -int ncells; -landParams ppLand = pLandscape->getLandParams(); -initParams init = paramsInit->getInit(); -#if RSDEBUG -//DEBUGLOG << "SubCommunity::initialise(): subCommNum=" << subCommNum -// << " seedType="<< init.seedType -// << " popns.size()="<< popns.size() -// << endl; -#endif -// determine size of initial population -//int hx,nInds; -int nInds = 0; -if (subCommNum == 0 // matrix patch -|| !initial) // not in initial region or distribution - nInds = 0; -else { - float k = pPatch->getK(); - if (k > 0.0) { // patch is currently suitable for this species - switch (init.initDens) { - case 0: // at carrying capacity - nInds = (int)k; - break; - case 1: // at half carrying capacity - nInds = (int)(k/2.0); - break; - case 2: // specified no. per cell or density - ncells = pPatch->getNCells(); - if (ppLand.patchModel) { - nInds = (int)(init.indsHa * (float)(ncells*ppLand.resol*ppLand.resol) / 10000.0); - } - else { - nInds = init.indsCell * ncells; + int ncells; + landParams ppLand = pLandscape->getLandParams(); + initParams init = paramsInit->getInit(); + // determine size of initial population + int nInds = 0; + if (subCommNum == 0 // matrix patch + || !initial) // not in initial region or distribution + nInds = 0; + else { + float k = pPatch->getK(); + if (k > 0.0) { // patch is currently suitable for this species + switch (init.initDens) { + case 0: // at carrying capacity + nInds = (int)k; + break; + case 1: // at half carrying capacity + nInds = (int)(k / 2.0); + break; + case 2: // specified no. per cell or density + ncells = pPatch->getNCells(); + if (ppLand.patchModel) { + nInds = (int)(init.indsHa * (float)(ncells * ppLand.resol * ppLand.resol) / 10000.0); + } + else { + nInds = init.indsCell * ncells; + } + break; } - break; } + else nInds = 0; + } + // create new population only if it is non-zero or the matrix popn + if (subCommNum == 0 || nInds > 0) { + newPopn(pLandscape, pSpecies, pPatch, nInds); } - else nInds = 0; -} - -// create new population (even if it has no individuals) -//popns.push_back(new Population(pSpecies,pPatch,nInds)); -//newPopn(pSpecies,pPatch,nInds); - -// create new population only if it is non-zero or the matrix popn -if (subCommNum == 0 || nInds > 0) { - newPopn(pLandscape,pSpecies,pPatch,nInds); -} - } // initialise a specified individual -void SubCommunity::initialInd(Landscape *pLandscape,Species *pSpecies, - Patch *pPatch,Cell *pCell,int ix) +void SubCommunity::initialInd(Landscape* pLandscape, Species* pSpecies, + Patch* pPatch, Cell* pCell, int ix) { -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -genomeData gen = pSpecies->getGenomeData(); -short stg,age,repInt; -Individual *pInd; -float probmale; -// bool movt; -// short moveType; - -// create new population if not already in existence -int npopns = (int)popns.size(); -if (npopns < 1) { - newPopn(pLandscape,pSpecies,pPatch,0); -} + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + genomeData gen = pSpecies->getGenomeData(); + short stg, age, repInt; + Individual* pInd; + float probmale; + + // create new population if not already in existence + int npopns = (int)popns.size(); + if (npopns < 1) { + newPopn(pLandscape, pSpecies, pPatch, 0); + } -// create new individual -initInd iind = paramsInit->getInitInd(ix); -if (dem.stageStruct) { - stg = iind.stage; age = iind.age; repInt = sstruct.repInterval; -} -else { - age = stg = 1; repInt = 0; -} -if (dem.repType == 0) { - probmale = 0.0; -} -else { - if (iind.sex == 1) probmale = 1.0; else probmale = 0.0; -} -//if (trfr.moveModel) { -// movt = true; -// if (trfr.moveType) { -// -// } -//} -pInd = new Individual(pCell,pPatch,stg,age,repInt,probmale,trfr.moveModel,trfr.moveType); - -// add new individual to the population -// NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... -popns[0]->recruit(pInd); - -if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) -{ - // individual variation - set up genetics - landData land = pLandscape->getLandData(); - pInd->setGenes(pSpecies,land.resol); -} + // create new individual + initInd iind = paramsInit->getInitInd(ix); + if (dem.stageStruct) { + stg = iind.stage; age = iind.age; repInt = sstruct.repInterval; + } + else { + age = stg = 1; repInt = 0; + } + if (dem.repType == 0) { + probmale = 0.0; + } + else { + if (iind.sex == 1) probmale = 1.0; else probmale = 0.0; + } + pInd = new Individual(pCell, pPatch, stg, age, repInt, probmale, trfr.moveModel, trfr.moveType); + + // add new individual to the population + // NB THIS WILL NEED TO BE CHANGED FOR MULTIPLE SPECIES... + popns[0]->recruit(pInd); + + if (emig.indVar || trfr.indVar || sett.indVar || gen.neutralMarkers) + { + // individual variation - set up genetics + landData land = pLandscape->getLandData(); + pInd->setGenes(pSpecies, land.resol); + } } // Create a new population, and return its address -Population* SubCommunity::newPopn(Landscape *pLandscape,Species *pSpecies, - Patch *pPatch,int nInds) +Population* SubCommunity::newPopn(Landscape* pLandscape, Species* pSpecies, + Patch* pPatch, int nInds) { -#if RSDEBUG -//DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum -// << " pPatch = " << pPatch << " nInds = "<< nInds << endl; -#endif -landParams land = pLandscape->getLandParams(); -int npopns = (int)popns.size(); -popns.push_back(new Population(pSpecies,pPatch,nInds,land.resol)); -#if RSDEBUG -//DEBUGLOG << "SubCommunity::newPopn(): subCommNum = " << subCommNum -// << " npopns = " << npopns << " popns[npopns] = " << popns[npopns] -// << endl; -#endif -return popns[npopns]; + landParams land = pLandscape->getLandParams(); + int npopns = (int)popns.size(); + popns.push_back(new Population(pSpecies, pPatch, nInds, land.resol)); + return popns[npopns]; } popStats SubCommunity::getPopStats(void) { -popStats p,pop; -p.pSpecies = 0; p.spNum = 0; p.nInds = p.nAdults = p.nNonJuvs = 0; p.breeding = false; -p.pPatch = pPatch; -// FOR SINGLE SPECIES IMPLEMENTATION, THERE IS ONLY ONE POPULATION IN THE PATCH -//p = popns[0]->getStats(); -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations -#if RSDEBUG -//DEBUGLOG << "SubCommunity::getPopStats(): npops = " << npops -// << " i = " << i -// << " popns[i] = " << popns[i] << endl; -#endif - pop = popns[i]->getStats(); - p.pSpecies = pop.pSpecies; - p.spNum = pop.spNum; - p.nInds += pop.nInds; - p.nNonJuvs += pop.nNonJuvs; - p.nAdults += pop.nAdults; - p.breeding = pop.breeding; -#if RSDEBUG -//DEBUGLOG << "SubCommunity::getPopStats():" -// << " p.pSpecies = " << p.pSpecies -// << " p.pPatch = " << p.pPatch -// << " p.spNum = " << p.spNum -// << " p.nInds = " << p.nInds -// << endl; -#endif -} -return p; + popStats p, pop; + p.pSpecies = 0; p.spNum = 0; p.nInds = p.nAdults = p.nNonJuvs = 0; p.breeding = false; + p.pPatch = pPatch; + // FOR SINGLE SPECIES IMPLEMENTATION, THERE IS ONLY ONE POPULATION IN THE PATCH + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + p.pSpecies = pop.pSpecies; + p.spNum = pop.spNum; + p.nInds += pop.nInds; + p.nNonJuvs += pop.nNonJuvs; + p.nAdults += pop.nAdults; + p.breeding = pop.breeding; + } + return p; } void SubCommunity::resetPopns(void) { -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - delete popns[i]; -} -popns.clear(); -// clear the list of populations in the corresponding patch -pPatch->resetPopn(); + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + delete popns[i]; + } + popns.clear(); + // clear the list of populations in the corresponding patch + pPatch->resetPopn(); } void SubCommunity::resetPossSettlers(void) { -if (subCommNum == 0) return; // not applicable in the matrix -//int npops = (int)popns.size(); -//for (int i = 0; i < npops; i++) { // all populations -// popns[i]->resetPossSettlers(); -//} -pPatch->resetPossSettlers(); + if (subCommNum == 0) return; // not applicable in the matrix + pPatch->resetPossSettlers(); } // Extirpate all populations according to @@ -246,225 +196,159 @@ pPatch->resetPossSettlers(); // option 1 - local extinction probability gradient // NB only applied for cell-based model void SubCommunity::localExtinction(int option) { -double pExtinct = 0.0; -if (option == 0) { - envStochParams env = paramsStoch->getStoch(); - if (env.localExt) pExtinct = env.locExtProb; -} -else { - envGradParams grad = paramsGrad->getGradient(); - Cell *pCell = pPatch->getRandomCell(); // get only cell in the patch - // extinction prob is complement of cell gradient value plus any non-zero prob at the optimum - pExtinct = 1.0 - pCell->getEnvVal() + grad.extProbOpt; - if (pExtinct > 1.0) pExtinct = 1.0; -} -if (pRandom->Bernoulli(pExtinct)) { - int npops = (int)popns.size(); - for (int i = 0; i < npops; i++) { // all populations - popns[i]->extirpate(); + double pExtinct = 0.0; + if (option == 0) { + envStochParams env = paramsStoch->getStoch(); + if (env.localExt) pExtinct = env.locExtProb; + } + else { + envGradParams grad = paramsGrad->getGradient(); + Cell* pCell = pPatch->getRandomCell(); // get only cell in the patch + // extinction prob is complement of cell gradient value plus any non-zero prob at the optimum + pExtinct = 1.0 - pCell->getEnvVal() + grad.extProbOpt; + if (pExtinct > 1.0) pExtinct = 1.0; + } + if (pRandom->Bernoulli(pExtinct)) { + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->extirpate(); + } } -} } // Action in event of patch becoming unsuitable owing to landscape change void SubCommunity::patchChange(void) { -if (subCommNum == 0) return; // no reproduction in the matrix -Species *pSpecies; -float localK = 0.0; -int npops = (int)popns.size(); -// THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... -if (npops < 1) return; -localK = pPatch->getK(); -if (localK <= 0.0) { // patch in dynamic landscape has become unsuitable - for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - if (dem.stageStruct) { - stageParams sstruct = pSpecies->getStage(); - if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); - else popns[i]->extirpate(); - } - else { // non-stage-structured species is destroyed - popns[i]->extirpate(); + if (subCommNum == 0) return; // no reproduction in the matrix + Species* pSpecies; + float localK = 0.0; + int npops = (int)popns.size(); + // THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... + if (npops < 1) return; + localK = pPatch->getK(); + if (localK <= 0.0) { // patch in dynamic landscape has become unsuitable + for (int i = 0; i < npops; i++) { // all populations + pSpecies = popns[i]->getSpecies(); + demogrParams dem = pSpecies->getDemogr(); + if (dem.stageStruct) { + stageParams sstruct = pSpecies->getStage(); + if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); + else popns[i]->extirpate(); + } + else { // non-stage-structured species is destroyed + popns[i]->extirpate(); + } } } } -} -void SubCommunity::reproduction(int resol,float epsGlobal,short rasterType,bool patchModel) +void SubCommunity::reproduction(int resol, float epsGlobal, short rasterType, bool patchModel) { -if (subCommNum == 0) return; // no reproduction in the matrix -float localK,envval; -//Species *pSpecies; -Cell *pCell; -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); - -int npops = (int)popns.size(); -// THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... -if (npops < 1) return; - -localK = pPatch->getK(); -if (localK > 0.0) { - if (patchModel) { - envval = 1.0; // environmental gradient is currently not applied for patch-based model - } - else { // cell-based model - if (grad.gradient && grad.gradType == 2) - { // gradient in fecundity - Cell *pCell = pPatch->getRandomCell(); // locate the only cell in the patch - envval = pCell->getEnvVal(); + if (subCommNum == 0) return; // no reproduction in the matrix + float localK, envval; + Cell* pCell; + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + + int npops = (int)popns.size(); + // THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... + if (npops < 1) return; + + localK = pPatch->getK(); + if (localK > 0.0) { + if (patchModel) { + envval = 1.0; // environmental gradient is currently not applied for patch-based model } - else envval = 1.0; - } - if (env.stoch && !env.inK) { // stochasticity in fecundity - if (env.local) { - if (!patchModel) { // only permitted for cell-based model - pCell = pPatch->getRandomCell(); - if (pCell != 0) envval += pCell->getEps(); + else { // cell-based model + if (grad.gradient && grad.gradType == 2) + { // gradient in fecundity + Cell* pCell = pPatch->getRandomCell(); // locate the only cell in the patch + envval = pCell->getEnvVal(); } + else envval = 1.0; } - else { // global stochasticity - envval += epsGlobal; - } - } - for (int i = 0; i < npops; i++) { // all populations - popns[i]->reproduction(localK,envval,resol); - popns[i]->fledge(); - } -} -/* -else { // patch in dynamic landscape has become unsuitable - // NB - THIS WILL NEED TO BE MADE SPECIES-SPECIFIC... - Species *pSpecies; - for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - if (dem.stageStruct) { - stageParams sstruct = pSpecies->getStage(); - if (sstruct.disperseOnLoss) popns[i]->allEmigrate(); - else popns[i]->extirpate(); + if (env.stoch && !env.inK) { // stochasticity in fecundity + if (env.local) { + if (!patchModel) { // only permitted for cell-based model + pCell = pPatch->getRandomCell(); + if (pCell != 0) envval += pCell->getEps(); + } + } + else { // global stochasticity + envval += epsGlobal; + } } - else { // non-stage-structured species is destroyed - popns[i]->extirpate(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->reproduction(localK, envval, resol); + popns[i]->fledge(); } } } -*/ - -/* -#if RSDEBUG -//if (npops > 0) { -// DEBUGLOG << "SubCommunity::reproduction(): this = " << this -// << " npops = " << npops << endl; -//} -#endif -#if RSDEBUG -//DEBUGLOG << "SubCommunity::reproduction(): patchNum = " << pPatch->getPatchNum() -// << " nCells " << pPatch->getNCells() -// << " localK = " << localK -// << endl; -#endif -*/ -} -void SubCommunity::emigration(void) +void SubCommunity::emigration(void) { -if (subCommNum == 0) return; // no emigration from the matrix -float localK; -int npops = (int)popns.size(); -// THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... -if (npops < 1) return; -localK = pPatch->getK(); -// NOTE that even if K is zero, it could have been >0 in previous time-step, and there -// might be emigrants if there is non-juvenile emigration -for (int i = 0; i < npops; i++) { // all populations -// localK = pPatch->getK(); - popns[i]->emigration(localK); -} + if (subCommNum == 0) return; // no emigration from the matrix + float localK; + int npops = (int)popns.size(); + // THE FOLLOWING MAY BE MORE EFFICIENT WHILST THERE IS ONLY ONE SPECIES ... + if (npops < 1) return; + localK = pPatch->getK(); + // NOTE that even if K is zero, it could have been >0 in previous time-step, and there + // might be emigrants if there is non-juvenile emigration + for (int i = 0; i < npops; i++) { // all populations + popns[i]->emigration(localK); + } } // Remove emigrants from their natal patch and add to patch 0 (matrix) void SubCommunity::initiateDispersal(SubCommunity* matrix) { -if (subCommNum == 0) return; // no dispersal initiation in the matrix -#if RSDEBUG -//DEBUGLOG << "SubCommunity::initiateDispersal(): this=" << this -// << " subCommNum=" << subCommNum -// << endl; -#endif -popStats pop; -disperser disp; + if (subCommNum == 0) return; // no dispersal initiation in the matrix + popStats pop; + disperser disp; -int npops = (int)popns.size(); -#if RSDEBUG -//DEBUGLOG << "SubCommunity::initiateDispersal(): patchNum = " << patchNum -// << " npops " << npops -// << endl; -#endif -for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); - for (int j = 0; j < pop.nInds; j++) { -#if RSDEBUG -//DEBUGLOG << "SubCommunity::initiateDispersal(): i = " << i -// << " j " << j -// << endl; -#endif - disp = popns[i]->extractDisperser(j); - if (disp.yes) { // disperser - has already been removed from natal population - // add to matrix population - matrix->recruit(disp.pInd,pop.pSpecies); + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + for (int j = 0; j < pop.nInds; j++) { + disp = popns[i]->extractDisperser(j); + if (disp.yes) { // disperser - has already been removed from natal population + // add to matrix population + matrix->recruit(disp.pInd, pop.pSpecies); + } } + // remove pointers to emigrants + popns[i]->clean(); } - // remove pointers to emigrants - popns[i]->clean(); -} } // Add an individual into the local population of its species in the patch -void SubCommunity::recruit(Individual *pInd,Species *pSpecies) { -#if RSDEBUG -//DEBUGLOG << "SubCommunity::recruit(): this=" << this -// << endl; -#endif -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - if (pSpecies == popns[i]->getSpecies()) { - popns[i]->recruit(pInd); +void SubCommunity::recruit(Individual* pInd, Species* pSpecies) { + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + if (pSpecies == popns[i]->getSpecies()) { + popns[i]->recruit(pInd); + } } } -} // Transfer through the matrix - run for the matrix sub-community only -#if RS_RCPP // included also SEASONAL -int SubCommunity::transfer(Landscape *pLandscape,short landIx,short nextseason) +#if RS_RCPP +int SubCommunity::transfer(Landscape* pLandscape, short landIx, short nextseason) #else -int SubCommunity::transfer(Landscape *pLandscape,short landIx) -#endif // SEASONAL || RS_RCPP +int SubCommunity::transfer(Landscape* pLandscape, short landIx) +#endif // RS_RCPP { -#if RSDEBUG -//DEBUGLOG << "SubCommunity::transfer(): this=" << this -// << endl; -#endif -int ndispersers = 0; -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations -#if RS_RCPP // included also SEASONAL - ndispersers += popns[i]->transfer(pLandscape,landIx,nextseason); + int ndispersers = 0; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations +#if RS_RCPP + ndispersers += popns[i]->transfer(pLandscape, landIx, nextseason); #else - ndispersers += popns[i]->transfer(pLandscape,landIx); -#endif // SEASONAL || RS_RCPP -#if RSDEBUG -//DEBUGLOG << "SubCommunity::transfer(): i = " << i -// << " this = " << this -// << " subCommNum = " << subCommNum -// << " npops = " << npops -// << " popns[i] = " << popns[i] -// << " ndispersers = " << ndispersers -// << endl; -#endif -} -return ndispersers; + ndispersers += popns[i]->transfer(pLandscape, landIx); +#endif // RS_RCPP + + } + return ndispersers; } //--------------------------------------------------------------------------- @@ -473,194 +357,130 @@ return ndispersers; // in which their destination co-ordinates fall // This function is executed for the matrix patch only -void SubCommunity::completeDispersal(Landscape *pLandscape,bool connect) +void SubCommunity::completeDispersal(Landscape* pLandscape, bool connect) { -#if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): this=" << this -// << endl; -#endif -//popStats pop; -//int popsize,subcomm; -int popsize; -disperser settler; -Species *pSpecies; -Population *pPop; -Patch *pPrevPatch; -Patch *pNewPatch; -Cell *pPrevCell; -SubCommunity *pSubComm; - -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - pSpecies = popns[i]->getSpecies(); - popsize = popns[i]->getNInds(); -#if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): i=" << i -// << " subCommNum=" << subCommNum -// << " pPatch=" << pPatch << " patchNum=" << pPatch->getPatchNum() -// << " npops=" << npops -// << " popns[i]=" << popns[i] -// << " popsize=" << popsize -// << endl; -#endif - for (int j = 0; j < popsize; j++) { - bool settled; - settler = popns[i]->extractSettler(j); - settled = settler.yes; - if (settled) { + int popsize; + disperser settler; + Species* pSpecies; + Population* pPop; + Patch* pPrevPatch; + Patch* pNewPatch; + Cell* pPrevCell; + SubCommunity* pSubComm; + + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + pSpecies = popns[i]->getSpecies(); + popsize = popns[i]->getNInds(); + for (int j = 0; j < popsize; j++) { + bool settled; + settler = popns[i]->extractSettler(j); + settled = settler.yes; + if (settled) { // settler - has already been removed from matrix population - // in popns[i]->extractSettler() -#if RSDEBUG -//locn loc = pNewCell->getLocn(); -//DEBUGLOG << "SubCommunity::completeDispersal(): j=" << j << " settled=" << settled; -//#if GROUPDISP -//if (emig.groupdisp) { -//DEBUGLOG << " groupID=" << groupsettler.pGroup->getGroupID() -// << " groupsize=" << groupsettler.groupsize -// << " status=" << groupsettler.pGroup->getStatus(); -//} -//else { -//DEBUGLOG << " settler.pInd=" << settler.pInd; -//} -//#else -//DEBUGLOG << " settler.pInd=" << settler.pInd; -//#endif // GROUPDISP -//DEBUGLOG << " loc.x=" << loc.x << " loc.y=" << loc.y << endl; -#endif // RSDEBUG // find new patch - pNewPatch = (Patch*)settler.pCell->getPatch(); - // find population within the patch (if there is one) -// subcomm = ppatch->getSubComm(); -// if (subcomm == 0) { // no sub-community has yet been set up -// // CANNOT SET UP A NEW ONE FROM WITHIN AN EXISTING ONE!!!!! -// } - pPop = (Population*)pNewPatch->getPopn((intptr)pSpecies); -#if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): j = " << j -// << " pCell = " << pCell << " ppatch = " << ppatch << " pPop = " << pPop -// << endl; -#endif - if (pPop == 0) { // settler is the first in a previously uninhabited patch - // create a new population in the corresponding sub-community - pSubComm = (SubCommunity*)pNewPatch->getSubComm(); -#if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): j = " << j -// << " pSubComm = " << pSubComm << endl; -#endif - pPop = pSubComm->newPopn(pLandscape,pSpecies,pNewPatch,0); -#if RSDEBUG -//DEBUGLOG << "SubCommunity::completeDispersal(): j=" << j -// << " pPop=" << pPop << endl; -#endif - } - pPop->recruit(settler.pInd); - if (connect) { // increment connectivity totals - int newpatch = pNewPatch->getSeqNum(); - pPrevCell = settler.pInd->getLocn(0); // previous cell - intptr patch = pPrevCell->getPatch(); - if (patch != 0) { - pPrevPatch = (Patch*)patch; - int prevpatch = pPrevPatch->getSeqNum(); - pLandscape->incrConnectMatrix(prevpatch,newpatch); + pNewPatch = (Patch*)settler.pCell->getPatch(); + // find population within the patch (if there is one) + pPop = (Population*)pNewPatch->getPopn((intptr)pSpecies); + if (pPop == 0) { // settler is the first in a previously uninhabited patch + // create a new population in the corresponding sub-community + pSubComm = (SubCommunity*)pNewPatch->getSubComm(); + pPop = pSubComm->newPopn(pLandscape, pSpecies, pNewPatch, 0); + } + pPop->recruit(settler.pInd); + if (connect) { // increment connectivity totals + int newpatch = pNewPatch->getSeqNum(); + pPrevCell = settler.pInd->getLocn(0); // previous cell + intptr patch = pPrevCell->getPatch(); + if (patch != 0) { + pPrevPatch = (Patch*)patch; + int prevpatch = pPrevPatch->getSeqNum(); + pLandscape->incrConnectMatrix(prevpatch, newpatch); + } } } + else { // for group dispersal only + } } - else { // for group dispersal only - } + // remove pointers in the matrix popn to settlers + popns[i]->clean(); } - // remove pointers in the matrix popn to settlers - popns[i]->clean(); -#if RSDEBUG -//pop = popns[i]->getStats(); -popsize = popns[i]->getNInds(); -//DEBUGLOG << "SubCommunity::completeDispersal(): i=" << i -// << " popns[i]=" << popns[i] -//// << " pop.pPatch = " << pop.pPatch -//// << " pop.nInds = " << pop.nInds -// << " popsize=" << popsize -// << endl; -#endif -} } //--------------------------------------------------------------------------- -void SubCommunity::survival(short part,short option0,short option1) +void SubCommunity::survival(short part, short option0, short option1) { -int npops = (int)popns.size(); -if (npops < 1) return; -if (part == 0) { - float localK = pPatch->getK(); - for (int i = 0; i < npops; i++) { // all populations - popns[i]->survival0(localK,option0,option1); + int npops = (int)popns.size(); + if (npops < 1) return; + if (part == 0) { + float localK = pPatch->getK(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->survival0(localK, option0, option1); + } } -} -else { - for (int i = 0; i < npops; i++) { // all populations - popns[i]->survival1(); + else { + for (int i = 0; i < npops; i++) { // all populations + popns[i]->survival1(); + } } } -} void SubCommunity::ageIncrement(void) { -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popns[i]->ageIncrement(); -} + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->ageIncrement(); + } } // Find the population of a given species in a given patch -Population* SubCommunity::findPop(Species *pSp,Patch *pPch) { +Population* SubCommunity::findPop(Species* pSp, Patch* pPch) { #if RSDEBUG -DEBUGLOG << "SubCommunity::findPop(): this=" << this - << endl; + DEBUGLOG << "SubCommunity::findPop(): this=" << this + << endl; #endif -Population *pPop = 0; -popStats pop; -int npops = (int)popns.size(); + Population* pPop = 0; + popStats pop; + int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - pop = popns[i]->getStats(); - if (pop.pSpecies == pSp && pop.pPatch == pPch) { // population located - pPop = popns[i]; - break; + for (int i = 0; i < npops; i++) { // all populations + pop = popns[i]->getStats(); + if (pop.pSpecies == pSp && pop.pPatch == pPch) { // population located + pPop = popns[i]; + break; + } + else pPop = 0; } - else pPop = 0; -} -return pPop; + return pPop; } //--------------------------------------------------------------------------- void SubCommunity::createOccupancy(int nrows) { -if (occupancy != 0) deleteOccupancy(); -if (nrows > 0) { - occupancy = new int[nrows]; - for (int i = 0; i < nrows; i++) occupancy[i] = 0; -} + if (occupancy != 0) deleteOccupancy(); + if (nrows > 0) { + occupancy = new int[nrows]; + for (int i = 0; i < nrows; i++) occupancy[i] = 0; + } } void SubCommunity::updateOccupancy(int row) { -#if RSDEBUG -//DEBUGLOG << "SubCommunity::updateOccupancy(): this=" << this -// << endl; -#endif -popStats pop; -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { - pop = popns[i]->getStats(); - if (pop.nInds > 0 && pop.breeding) { - occupancy[row]++; - i = npops; + popStats pop; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { + pop = popns[i]->getStats(); + if (pop.nInds > 0 && pop.breeding) { + occupancy[row]++; + i = npops; + } } } -} int SubCommunity::getOccupancy(int row) { -if (row >= 0) return occupancy[row]; -else return 0; + if (row >= 0) return occupancy[row]; + else return 0; } void SubCommunity::deleteOccupancy(void) { @@ -670,529 +490,513 @@ void SubCommunity::deleteOccupancy(void) { //--------------------------------------------------------------------------- // Open population file and write header record -bool SubCommunity::outPopHeaders(Landscape *pLandscape,Species *pSpecies,int option) +bool SubCommunity::outPopHeaders(Landscape* pLandscape, Species* pSpecies, int option) { -bool fileOK; -Population *pPop; -landParams land = pLandscape->getLandParams(); - -if (option == -999) { // close the file - // as all populations may have been deleted, set up a dummy one - // species is not necessary - pPop = new Population(); - fileOK = pPop->outPopHeaders(-999,land.patchModel); - delete pPop; -} -else { // open the file - // as no population has yet been created, set up a dummy one - // species is necessary, as columns depend on stage and sex structure - pPop = new Population(pSpecies,pPatch,0,land.resol); - fileOK = pPop->outPopHeaders(land.landNum,land.patchModel); - delete pPop; -} -return fileOK; + bool fileOK; + Population* pPop; + landParams land = pLandscape->getLandParams(); + + if (option == -999) { // close the file + // as all populations may have been deleted, set up a dummy one + // species is not necessary + pPop = new Population(); + fileOK = pPop->outPopHeaders(-999, land.patchModel); + delete pPop; + } + else { // open the file + // as no population has yet been created, set up a dummy one + // species is necessary, as columns depend on stage and sex structure + pPop = new Population(pSpecies, pPatch, 0, land.resol); + fileOK = pPop->outPopHeaders(land.landNum, land.patchModel); + delete pPop; + } + return fileOK; } // Write records to population file -void SubCommunity::outPop(Landscape *pLandscape,int rep,int yr,int gen) +void SubCommunity::outPop(Landscape* pLandscape, int rep, int yr, int gen) { -landParams land = pLandscape->getLandParams(); -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -bool writeEnv = false; -bool gradK = false; -if (grad.gradient) { - writeEnv = true; - if (grad.gradType == 1) gradK = true; // ... carrying capacity -} -if (env.stoch) writeEnv = true; - -// generate output for each population within the sub-community (patch) -// provided that the patch is suitable (i.e. non-zero carrying capacity) -// or the population is above zero (possible if there is stochasticity or a moving gradient) -// or it is the matrix patch in a patch-based model -int npops = (int)popns.size(); -int patchnum; -//Species* pSpecies; -Cell *pCell; -float localK; -float eps = 0.0; -if (env.stoch) { - if (env.local) { - pCell = pPatch->getRandomCell(); - if (pCell != 0) eps = pCell->getEps(); - } - else { - eps = pLandscape->getGlobalStoch(yr); + landParams land = pLandscape->getLandParams(); + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + bool writeEnv = false; + bool gradK = false; + if (grad.gradient) { + writeEnv = true; + if (grad.gradType == 1) gradK = true; // ... carrying capacity } -} + if (env.stoch) writeEnv = true; -patchnum = pPatch->getPatchNum(); -for (int i = 0; i < npops; i++) { // all populations -// pSpecies = popns[i]->getSpecies(); - localK = pPatch->getK(); - if (localK > 0.0 || (land.patchModel && patchnum == 0)) { - popns[i]->outPopulation(rep,yr,gen,eps,land.patchModel,writeEnv,gradK); + // generate output for each population within the sub-community (patch) + // provided that the patch is suitable (i.e. non-zero carrying capacity) + // or the population is above zero (possible if there is stochasticity or a moving gradient) + // or it is the matrix patch in a patch-based model + int npops = (int)popns.size(); + int patchnum; + Cell* pCell; + float localK; + float eps = 0.0; + if (env.stoch) { + if (env.local) { + pCell = pPatch->getRandomCell(); + if (pCell != 0) eps = pCell->getEps(); + } + else { + eps = pLandscape->getGlobalStoch(yr); + } } - else { - if (popns[i]->totalPop() > 0) { - popns[i]->outPopulation(rep,yr,gen,eps,land.patchModel,writeEnv,gradK); + + patchnum = pPatch->getPatchNum(); + for (int i = 0; i < npops; i++) { // all populations + localK = pPatch->getK(); + if (localK > 0.0 || (land.patchModel && patchnum == 0)) { + popns[i]->outPopulation(rep, yr, gen, eps, land.patchModel, writeEnv, gradK); + } + else { + if (popns[i]->totalPop() > 0) { + popns[i]->outPopulation(rep, yr, gen, eps, land.patchModel, writeEnv, gradK); + } } } } -} // Write records to individuals file -void SubCommunity::outInds(Landscape *pLandscape,int rep,int yr,int gen,int landNr) { -landParams ppLand = pLandscape->getLandParams(); -if (landNr >= 0) { // open the file - popns[0]->outIndsHeaders(rep,landNr,ppLand.patchModel); - return; -} -if (landNr == -999) { // close the file - popns[0]->outIndsHeaders(rep,-999,ppLand.patchModel); - return; -} -// generate output for each population within the sub-community (patch) -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popns[i]->outIndividual(pLandscape,rep,yr,gen,pPatch->getPatchNum()); -} +void SubCommunity::outInds(Landscape* pLandscape, int rep, int yr, int gen, int landNr) { + landParams ppLand = pLandscape->getLandParams(); + if (landNr >= 0) { // open the file + popns[0]->outIndsHeaders(rep, landNr, ppLand.patchModel); + return; + } + if (landNr == -999) { // close the file + popns[0]->outIndsHeaders(rep, -999, ppLand.patchModel); + return; + } + // generate output for each population within the sub-community (patch) + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->outIndividual(pLandscape, rep, yr, gen, pPatch->getPatchNum()); + } } // Write records to individuals file -void SubCommunity::outGenetics(int rep,int yr,int gen,int landNr) +void SubCommunity::outGenetics(int rep, int yr, int gen, int landNr) { -//landParams ppLand = pLandscape->getLandParams(); -if (landNr >= 0) { // open the file - popns[0]->outGenetics(rep,yr,landNr); - return; -} -if (landNr == -999) { // close the file - popns[0]->outGenetics(rep,yr,landNr); - return; -} -// generate output for each population within the sub-community (patch) -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popns[i]->outGenetics(rep,yr,landNr); -} + if (landNr >= 0) { // open the file + popns[0]->outGenetics(rep, yr, landNr); + return; + } + if (landNr == -999) { // close the file + popns[0]->outGenetics(rep, yr, landNr); + return; + } + // generate output for each population within the sub-community (patch) + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popns[i]->outGenetics(rep, yr, landNr); + } } // Population size of a specified stage int SubCommunity::stagePop(int stage) { -int popsize = 0; -int npops = (int)popns.size(); -for (int i = 0; i < npops; i++) { // all populations - popsize += popns[i]->stagePop(stage); -} -return popsize; + int popsize = 0; + int npops = (int)popns.size(); + for (int i = 0; i < npops; i++) { // all populations + popsize += popns[i]->stagePop(stage); + } + return popsize; } // Open traits file and write header record -bool SubCommunity::outTraitsHeaders(Landscape *pLandscape,Species *pSpecies,int landNr) +bool SubCommunity::outTraitsHeaders(Landscape* pLandscape, Species* pSpecies, int landNr) { -//Population *pPop; -landParams land = pLandscape->getLandParams(); -if (landNr == -999) { // close file - if (outtraits.is_open()) outtraits.close(); - outtraits.clear(); - return true; -} - -string name; -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -simParams sim = paramsSim->getSim(); - -string DirOut = paramsSim->getDir(2); -if (sim.batchMode) { - if (land.patchModel){ - name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) - + "_TraitsXpatch.txt"; + landParams land = pLandscape->getLandParams(); + if (landNr == -999) { // close file + if (outtraits.is_open()) outtraits.close(); + outtraits.clear(); + return true; } - else{ - name = DirOut - + "Batch" + Int2Str(sim.batchNum) + "_" - + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) - + "_TraitsXcell.txt"; - } -} -else { - if (land.patchModel){ - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXpatch.txt"; - } - else{ - name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXcell.txt"; - } -} -outtraits.open(name.c_str()); - -outtraits << "Rep\tYear\tRepSeason"; -if (land.patchModel) outtraits << "\tPatchID"; -else - outtraits << "\tx\ty"; - -if (emig.indVar) { - if (emig.sexDep) { - if (emig.densDep) { - outtraits << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; - outtraits << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; - outtraits << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + + string name; + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + simParams sim = paramsSim->getSim(); + + string DirOut = paramsSim->getDir(2); + if (sim.batchMode) { + if (land.patchModel) { + name = DirOut + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + + "_TraitsXpatch.txt"; } else { - outtraits << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + name = DirOut + + "Batch" + Int2Str(sim.batchNum) + "_" + + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(landNr) + + "_TraitsXcell.txt"; } } else { - if (emig.densDep) { - outtraits << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; - outtraits << "\tmeanBeta\tstdBeta"; + if (land.patchModel) { + name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXpatch.txt"; } else { - outtraits << "\tmeanEP\tstdEP"; + name = DirOut + "Sim" + Int2Str(sim.simulation) + "_TraitsXcell.txt"; } } -} -if (trfr.indVar) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outtraits << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; - outtraits << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; + outtraits.open(name.c_str()); + + outtraits << "Rep\tYear\tRepSeason"; + if (land.patchModel) outtraits << "\tPatchID"; + else + outtraits << "\tx\ty"; + + if (emig.indVar) { + if (emig.sexDep) { + if (emig.densDep) { + outtraits << "\tF_meanD0\tF_stdD0\tM_meanD0\tM_stdD0"; + outtraits << "\tF_meanAlpha\tF_stdAlpha\tM_meanAlpha\tM_stdAlpha"; + outtraits << "\tF_meanBeta\tF_stdBeta\tM_meanBeta\tM_stdBeta"; + } + else { + outtraits << "\tF_meanEP\tF_stdEP\tM_meanEP\tM_stdEP"; + } } - if (trfr.moveType == 2) { - outtraits << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + else { + if (emig.densDep) { + outtraits << "\tmeanD0\tstdD0\tmeanAlpha\tstdAlpha"; + outtraits << "\tmeanBeta\tstdBeta"; + } + else { + outtraits << "\tmeanEP\tstdEP"; + } } } - else { - if (trfr.sexDep) { - outtraits << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; - if (trfr.twinKern) - outtraits << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" + if (trfr.indVar) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outtraits << "\tmeanDP\tstdDP\tmeanGB\tstdGB"; + outtraits << "\tmeanAlphaDB\tstdAlphaDB\tmeanBetaDB\tstdBetaDB"; + } + if (trfr.moveType == 2) { + outtraits << "\tmeanStepLength\tstdStepLength\tmeanRho\tstdRho"; + } + } + else { + if (trfr.sexDep) { + outtraits << "\tF_mean_distI\tF_std_distI\tM_mean_distI\tM_std_distI"; + if (trfr.twinKern) + outtraits << "\tF_mean_distII\tF_std_distII\tM_mean_distII\tM_std_distII" << "\tF_meanPfirstKernel\tF_stdPfirstKernel" << "\tM_meanPfirstKernel\tM_stdPfirstKernel"; + } + else { + outtraits << "\tmean_distI\tstd_distI"; + if (trfr.twinKern) + outtraits << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + } + } + } + if (sett.indVar) { + if (sett.sexDep) { + outtraits << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; + outtraits << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; + outtraits << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; } else { - outtraits << "\tmean_distI\tstd_distI"; - if (trfr.twinKern) - outtraits << "\tmean_distII\tstd_distII\tmeanPfirstKernel\tstdPfirstKernel"; + outtraits << "\tmeanS0\tstdS0"; + outtraits << "\tmeanAlphaS\tstdAlphaS"; + outtraits << "\tmeanBetaS\tstdBetaS"; } } -} -if (sett.indVar) { - if (sett.sexDep) { - outtraits << "\tF_meanS0\tF_stdS0\tM_meanS0\tM_stdS0"; - outtraits << "\tF_meanAlphaS\tF_stdAlphaS\tM_meanAlphaS\tM_stdAlphaS"; - outtraits << "\tF_meanBetaS\tF_stdBetaS\tM_meanBetaS\tM_stdBetaS"; - } - else { - outtraits << "\tmeanS0\tstdS0"; - outtraits << "\tmeanAlphaS\tstdAlphaS"; - outtraits << "\tmeanBetaS\tstdBetaS"; - } -} -outtraits << endl; + outtraits << endl; -return outtraits.is_open(); + return outtraits.is_open(); } // Write records to traits file and return aggregated sums traitsums SubCommunity::outTraits(traitCanvas tcanv, - Landscape *pLandscape,int rep,int yr,int gen,bool commlevel) + Landscape* pLandscape, int rep, int yr, int gen, bool commlevel) { -int popsize,ngenes; -landParams land = pLandscape->getLandParams(); -simParams sim = paramsSim->getSim(); -bool writefile = false; -if (sim.outTraitsCells && yr%sim.outIntTraitCell == 0 && !commlevel) - writefile = true; -traitsums ts,poptraits; -for (int i = 0; i < NSEXES; i++) { - ts.ninds[i] = 0; - ts.sumD0[i] = ts.ssqD0[i] = 0.0; - ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; - ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; - ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; - ts.sumDP[i] = ts.ssqDP[i] = 0.0; - ts.sumGB[i] = ts.ssqGB[i] = 0.0; - ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; - ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; - ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; - ts.sumS0[i] = ts.ssqS0[i] = 0.0; - ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; -} + int popsize, ngenes; + landParams land = pLandscape->getLandParams(); + simParams sim = paramsSim->getSim(); + bool writefile = false; + if (sim.outTraitsCells && yr % sim.outIntTraitCell == 0 && !commlevel) + writefile = true; + traitsums ts, poptraits; + for (int i = 0; i < NSEXES; i++) { + ts.ninds[i] = 0; + ts.sumD0[i] = ts.ssqD0[i] = 0.0; + ts.sumAlpha[i] = ts.ssqAlpha[i] = 0.0; ts.sumBeta[i] = ts.ssqBeta[i] = 0.0; + ts.sumDist1[i] = ts.ssqDist1[i] = 0.0; ts.sumDist2[i] = ts.ssqDist2[i] = 0.0; + ts.sumProp1[i] = ts.ssqProp1[i] = 0.0; + ts.sumDP[i] = ts.ssqDP[i] = 0.0; + ts.sumGB[i] = ts.ssqGB[i] = 0.0; + ts.sumAlphaDB[i] = ts.ssqAlphaDB[i] = 0.0; + ts.sumBetaDB[i] = ts.ssqBetaDB[i] = 0.0; + ts.sumStepL[i] = ts.ssqStepL[i] = 0.0; ts.sumRho[i] = ts.ssqRho[i] = 0.0; + ts.sumS0[i] = ts.ssqS0[i] = 0.0; + ts.sumAlphaS[i] = ts.ssqAlphaS[i] = 0.0; ts.sumBetaS[i] = ts.ssqBetaS[i] = 0.0; + } -// generate output for each population within the sub-community (patch) -// provided that the patch is suitable (i.e. non-zero carrying capacity) -int npops = (int)popns.size(); -Species* pSpecies; -float localK; + // generate output for each population within the sub-community (patch) + // provided that the patch is suitable (i.e. non-zero carrying capacity) + int npops = (int)popns.size(); + Species* pSpecies; + float localK; -for (int i = 0; i < npops; i++) { // all populations - localK = pPatch->getK(); - if (localK > 0.0 && popns[i]->getNInds() > 0) { - pSpecies = popns[i]->getSpecies(); - demogrParams dem = pSpecies->getDemogr(); - emigRules emig = pSpecies->getEmig(); - trfrRules trfr = pSpecies->getTrfr(); - settleType sett = pSpecies->getSettle(); - poptraits = popns[i]->getTraits(pSpecies); - - if (writefile) { - outtraits << rep << "\t" << yr << "\t" << gen; - if (land.patchModel) { - outtraits << "\t" << pPatch->getPatchNum(); - } - else { - locn loc = pPatch->getCellLocn(0); - outtraits << "\t" << loc.x << "\t" << loc.y; - } - } + for (int i = 0; i < npops; i++) { // all populations + localK = pPatch->getK(); + if (localK > 0.0 && popns[i]->getNInds() > 0) { + pSpecies = popns[i]->getSpecies(); + demogrParams dem = pSpecies->getDemogr(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + poptraits = popns[i]->getTraits(pSpecies); - if (emig.indVar) { - if (emig.sexDep) { // must be a sexual species - ngenes = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; + if (writefile) { + outtraits << rep << "\t" << yr << "\t" << gen; + if (land.patchModel) { + outtraits << "\t" << pPatch->getPatchNum(); } - else { // sexual reproduction - ngenes = 1; + else { + locn loc = pPatch->getCellLocn(0); + outtraits << "\t" << loc.x << "\t" << loc.y; } } - double mnD0[2],mnAlpha[2],mnBeta[2],sdD0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; - if (popsize > 0) { - mnD0[g] = poptraits.sumD0[g] / (double)popsize; - mnAlpha[g] = poptraits.sumAlpha[g] / (double)popsize; - mnBeta[g] = poptraits.sumBeta[g] / (double)popsize; - if (popsize > 1) { - sdD0[g] = poptraits.ssqD0[g]/(double)popsize - mnD0[g]*mnD0[g]; - if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; - sdAlpha[g] = poptraits.ssqAlpha[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = poptraits.ssqBeta[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + + if (emig.indVar) { + if (emig.sexDep) { // must be a sexual species + ngenes = 2; + } + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } - } - if (writefile) { - if (emig.sexDep) { - outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; - outtraits << "\t" << mnD0[1] << "\t" << sdD0[1]; - if (emig.densDep) { - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + double mnD0[2], mnAlpha[2], mnBeta[2], sdD0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnD0[g] = mnAlpha[g] = mnBeta[g] = sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = poptraits.ninds[g]; + else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (popsize > 0) { + mnD0[g] = poptraits.sumD0[g] / (double)popsize; + mnAlpha[g] = poptraits.sumAlpha[g] / (double)popsize; + mnBeta[g] = poptraits.sumBeta[g] / (double)popsize; + if (popsize > 1) { + sdD0[g] = poptraits.ssqD0[g] / (double)popsize - mnD0[g] * mnD0[g]; + if (sdD0[g] > 0.0) sdD0[g] = sqrt(sdD0[g]); else sdD0[g] = 0.0; + sdAlpha[g] = poptraits.ssqAlpha[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = poptraits.ssqBeta[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } } } - else { // sex-independent - outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; - if (emig.densDep) { - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + if (writefile) { + if (emig.sexDep) { + outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; + outtraits << "\t" << mnD0[1] << "\t" << sdD0[1]; + if (emig.densDep) { + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + } + else { // sex-independent + outtraits << "\t" << mnD0[0] << "\t" << sdD0[0]; + if (emig.densDep) { + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } } } - } - if (trfr.indVar) { - if (trfr.moveModel) { - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT - ngenes = 1; - } - else { - if (trfr.sexDep) { // must be a sexual species - ngenes = 2; - } - else { + if (trfr.indVar) { + if (trfr.moveModel) { + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT ngenes = 1; } - } - double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; - double sdDist1[2],sdDist2[2],sdProp1[2],sdStepL[2],sdRho[2]; - double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; - double sdDP[2],sdGB[2],sdAlphaDB[2],sdBetaDB[2]; - for (int g = 0; g < ngenes; g++) { - mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; - sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; - mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; - sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; - if (popsize > 0) { - mnDist1[g] = poptraits.sumDist1[g] / (double)popsize; - mnDist2[g] = poptraits.sumDist2[g] / (double)popsize; - mnProp1[g] = poptraits.sumProp1[g] / (double)popsize; - mnStepL[g] = poptraits.sumStepL[g] / (double)popsize; - mnRho[g] = poptraits.sumRho[g] / (double)popsize; - mnDP[g] = poptraits.sumDP[g] / (double)popsize; - mnGB[g] = poptraits.sumGB[g] / (double)popsize; - mnAlphaDB[g] = poptraits.sumAlphaDB[g] / (double)popsize; - mnBetaDB[g] = poptraits.sumBetaDB[g] / (double)popsize; - if (popsize > 1) { - sdDist1[g] = poptraits.ssqDist1[g]/(double)popsize - mnDist1[g]*mnDist1[g]; - if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; - sdDist2[g] = poptraits.ssqDist2[g]/(double)popsize - mnDist2[g]*mnDist2[g]; - if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; - sdProp1[g] = poptraits.ssqProp1[g]/(double)popsize - mnProp1[g]*mnProp1[g]; - if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; - sdStepL[g] = poptraits.ssqStepL[g]/(double)popsize - mnStepL[g]*mnStepL[g]; - if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; - sdRho[g] = poptraits.ssqRho[g]/(double)popsize - mnRho[g]*mnRho[g]; - if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; - sdDP[g] = poptraits.ssqDP[g]/(double)popsize - mnDP[g]*mnDP[g]; - if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; - sdGB[g] = poptraits.ssqGB[g]/(double)popsize - mnGB[g]*mnGB[g]; - if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; - sdAlphaDB[g] = poptraits.ssqAlphaDB[g]/(double)popsize - mnAlphaDB[g]*mnAlphaDB[g]; - if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; - sdBetaDB[g] = poptraits.ssqBetaDB[g]/(double)popsize - mnBetaDB[g]*mnBetaDB[g]; - if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + else { + if (trfr.sexDep) { // must be a sexual species + ngenes = 2; } - } - } - if (writefile) { - if (trfr.moveModel) { - if (trfr.moveType == 1) { - outtraits << "\t" << mnDP[0] << "\t" << sdDP[0]; - outtraits << "\t" << mnGB[0] << "\t" << sdGB[0]; - outtraits << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; - outtraits << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; + else { + ngenes = 1; } - if (trfr.moveType == 2) { - outtraits << "\t" << mnStepL[0] << "\t" << sdStepL[0]; - outtraits << "\t" << mnRho[0] << "\t" << sdRho[0]; + } + double mnDist1[2], mnDist2[2], mnProp1[2], mnStepL[2], mnRho[2]; + double sdDist1[2], sdDist2[2], sdProp1[2], sdStepL[2], sdRho[2]; + double mnDP[2], mnGB[2], mnAlphaDB[2], mnBetaDB[2]; + double sdDP[2], sdGB[2], sdAlphaDB[2], sdBetaDB[2]; + for (int g = 0; g < ngenes; g++) { + mnDist1[g] = mnDist2[g] = mnProp1[g] = mnStepL[g] = mnRho[g] = 0.0; + sdDist1[g] = sdDist2[g] = sdProp1[g] = sdStepL[g] = sdRho[g] = 0.0; + mnDP[g] = mnGB[g] = mnAlphaDB[g] = mnBetaDB[g] = 0.0; + sdDP[g] = sdGB[g] = sdAlphaDB[g] = sdBetaDB[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = poptraits.ninds[g]; + else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (popsize > 0) { + mnDist1[g] = poptraits.sumDist1[g] / (double)popsize; + mnDist2[g] = poptraits.sumDist2[g] / (double)popsize; + mnProp1[g] = poptraits.sumProp1[g] / (double)popsize; + mnStepL[g] = poptraits.sumStepL[g] / (double)popsize; + mnRho[g] = poptraits.sumRho[g] / (double)popsize; + mnDP[g] = poptraits.sumDP[g] / (double)popsize; + mnGB[g] = poptraits.sumGB[g] / (double)popsize; + mnAlphaDB[g] = poptraits.sumAlphaDB[g] / (double)popsize; + mnBetaDB[g] = poptraits.sumBetaDB[g] / (double)popsize; + if (popsize > 1) { + sdDist1[g] = poptraits.ssqDist1[g] / (double)popsize - mnDist1[g] * mnDist1[g]; + if (sdDist1[g] > 0.0) sdDist1[g] = sqrt(sdDist1[g]); else sdDist1[g] = 0.0; + sdDist2[g] = poptraits.ssqDist2[g] / (double)popsize - mnDist2[g] * mnDist2[g]; + if (sdDist2[g] > 0.0) sdDist2[g] = sqrt(sdDist2[g]); else sdDist2[g] = 0.0; + sdProp1[g] = poptraits.ssqProp1[g] / (double)popsize - mnProp1[g] * mnProp1[g]; + if (sdProp1[g] > 0.0) sdProp1[g] = sqrt(sdProp1[g]); else sdProp1[g] = 0.0; + sdStepL[g] = poptraits.ssqStepL[g] / (double)popsize - mnStepL[g] * mnStepL[g]; + if (sdStepL[g] > 0.0) sdStepL[g] = sqrt(sdStepL[g]); else sdStepL[g] = 0.0; + sdRho[g] = poptraits.ssqRho[g] / (double)popsize - mnRho[g] * mnRho[g]; + if (sdRho[g] > 0.0) sdRho[g] = sqrt(sdRho[g]); else sdRho[g] = 0.0; + sdDP[g] = poptraits.ssqDP[g] / (double)popsize - mnDP[g] * mnDP[g]; + if (sdDP[g] > 0.0) sdDP[g] = sqrt(sdDP[g]); else sdDP[g] = 0.0; + sdGB[g] = poptraits.ssqGB[g] / (double)popsize - mnGB[g] * mnGB[g]; + if (sdGB[g] > 0.0) sdGB[g] = sqrt(sdGB[g]); else sdGB[g] = 0.0; + sdAlphaDB[g] = poptraits.ssqAlphaDB[g] / (double)popsize - mnAlphaDB[g] * mnAlphaDB[g]; + if (sdAlphaDB[g] > 0.0) sdAlphaDB[g] = sqrt(sdAlphaDB[g]); else sdAlphaDB[g] = 0.0; + sdBetaDB[g] = poptraits.ssqBetaDB[g] / (double)popsize - mnBetaDB[g] * mnBetaDB[g]; + if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; + } } } - else { - if (trfr.sexDep) { - outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - outtraits << "\t" << mnDist1[1] << "\t" << sdDist1[1]; - if (trfr.twinKern) - { - outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outtraits << "\t" << mnDist2[1] << "\t" << sdDist2[1]; - outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; - outtraits << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + if (writefile) { + if (trfr.moveModel) { + if (trfr.moveType == 1) { + outtraits << "\t" << mnDP[0] << "\t" << sdDP[0]; + outtraits << "\t" << mnGB[0] << "\t" << sdGB[0]; + outtraits << "\t" << mnAlphaDB[0] << "\t" << sdAlphaDB[0]; + outtraits << "\t" << mnBetaDB[0] << "\t" << sdBetaDB[0]; + } + if (trfr.moveType == 2) { + outtraits << "\t" << mnStepL[0] << "\t" << sdStepL[0]; + outtraits << "\t" << mnRho[0] << "\t" << sdRho[0]; } } - else { // sex-independent - outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; - if (trfr.twinKern) - { - outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; - outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + else { + if (trfr.sexDep) { + outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + outtraits << "\t" << mnDist1[1] << "\t" << sdDist1[1]; + if (trfr.twinKern) + { + outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outtraits << "\t" << mnDist2[1] << "\t" << sdDist2[1]; + outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + outtraits << "\t" << mnProp1[1] << "\t" << sdProp1[1]; + } + } + else { // sex-independent + outtraits << "\t" << mnDist1[0] << "\t" << sdDist1[0]; + if (trfr.twinKern) + { + outtraits << "\t" << mnDist2[0] << "\t" << sdDist2[0]; + outtraits << "\t" << mnProp1[0] << "\t" << sdProp1[0]; + } } } } } - } - if (sett.indVar) { - if (sett.sexDep) { // must be a sexual species - ngenes = 2; - } - else { - if (dem.repType == 0) { // asexual reproduction - ngenes = 1; - } - else { // sexual reproduction - ngenes = 1; + if (sett.indVar) { + if (sett.sexDep) { // must be a sexual species + ngenes = 2; } - } - // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT -// ngenes = 1; - double mnS0[2],mnAlpha[2],mnBeta[2],sdS0[2],sdAlpha[2],sdBeta[2]; - for (int g = 0; g < ngenes; g++) { - mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; - // individuals may have been counted by sex if there was - // sex dependency in another dispersal phase - if (ngenes == 2) popsize = poptraits.ninds[g]; - else popsize = poptraits.ninds[0] + poptraits.ninds[1]; - if (popsize > 0) { - mnS0[g] = poptraits.sumS0[g] / (double)popsize; - mnAlpha[g] = poptraits.sumAlphaS[g] / (double)popsize; - mnBeta[g] = poptraits.sumBetaS[g] / (double)popsize; - if (popsize > 1) { - sdS0[g] = poptraits.ssqS0[g]/(double)popsize - mnS0[g]*mnS0[g]; - if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; - sdAlpha[g] = poptraits.ssqAlphaS[g]/(double)popsize - mnAlpha[g]*mnAlpha[g]; - if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; - sdBeta[g] = poptraits.ssqBetaS[g]/(double)popsize - mnBeta[g]*mnBeta[g]; - if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + else { + if (dem.repType == 0) { // asexual reproduction + ngenes = 1; } - else { - sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + else { // sexual reproduction + ngenes = 1; } } - } - if (writefile) { - if (sett.sexDep) { - outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; - outtraits << "\t" << mnS0[1] << "\t" << sdS0[1]; - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; - outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT + double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; + for (int g = 0; g < ngenes; g++) { + mnS0[g] = mnAlpha[g] = mnBeta[g] = sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + // individuals may have been counted by sex if there was + // sex dependency in another dispersal phase + if (ngenes == 2) popsize = poptraits.ninds[g]; + else popsize = poptraits.ninds[0] + poptraits.ninds[1]; + if (popsize > 0) { + mnS0[g] = poptraits.sumS0[g] / (double)popsize; + mnAlpha[g] = poptraits.sumAlphaS[g] / (double)popsize; + mnBeta[g] = poptraits.sumBetaS[g] / (double)popsize; + if (popsize > 1) { + sdS0[g] = poptraits.ssqS0[g] / (double)popsize - mnS0[g] * mnS0[g]; + if (sdS0[g] > 0.0) sdS0[g] = sqrt(sdS0[g]); else sdS0[g] = 0.0; + sdAlpha[g] = poptraits.ssqAlphaS[g] / (double)popsize - mnAlpha[g] * mnAlpha[g]; + if (sdAlpha[g] > 0.0) sdAlpha[g] = sqrt(sdAlpha[g]); else sdAlpha[g] = 0.0; + sdBeta[g] = poptraits.ssqBetaS[g] / (double)popsize - mnBeta[g] * mnBeta[g]; + if (sdBeta[g] > 0.0) sdBeta[g] = sqrt(sdBeta[g]); else sdBeta[g] = 0.0; + } + else { + sdS0[g] = sdAlpha[g] = sdBeta[g] = 0.0; + } + } } - else { // sex-independent - outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; - outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; - outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + if (writefile) { + if (sett.sexDep) { + outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; + outtraits << "\t" << mnS0[1] << "\t" << sdS0[1]; + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnAlpha[1] << "\t" << sdAlpha[1]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + outtraits << "\t" << mnBeta[1] << "\t" << sdBeta[1]; + } + else { // sex-independent + outtraits << "\t" << mnS0[0] << "\t" << sdS0[0]; + outtraits << "\t" << mnAlpha[0] << "\t" << sdAlpha[0]; + outtraits << "\t" << mnBeta[0] << "\t" << sdBeta[0]; + } } } - } - if (writefile) outtraits << endl; - - for (int s = 0; s < NSEXES; s++) { - ts.ninds[s] += poptraits.ninds[s]; - ts.sumD0[s] += poptraits.sumD0[s]; ts.ssqD0[s] += poptraits.ssqD0[s]; - ts.sumAlpha[s] += poptraits.sumAlpha[s]; ts.ssqAlpha[s] += poptraits.ssqAlpha[s]; - ts.sumBeta[s] += poptraits.sumBeta[s]; ts.ssqBeta[s] += poptraits.ssqBeta[s]; - ts.sumDist1[s] += poptraits.sumDist1[s]; ts.ssqDist1[s] += poptraits.ssqDist1[s]; - ts.sumDist2[s] += poptraits.sumDist2[s]; ts.ssqDist2[s] += poptraits.ssqDist2[s]; - ts.sumProp1[s] += poptraits.sumProp1[s]; ts.ssqProp1[s] += poptraits.ssqProp1[s]; - ts.sumDP[s] += poptraits.sumDP[s]; ts.ssqDP[s] += poptraits.ssqDP[s]; - ts.sumGB[s] += poptraits.sumGB[s]; ts.ssqGB[s] += poptraits.ssqGB[s]; - ts.sumAlphaDB[s] += poptraits.sumAlphaDB[s]; ts.ssqAlphaDB[s] += poptraits.ssqAlphaDB[s]; - ts.sumBetaDB[s] += poptraits.sumBetaDB[s]; ts.ssqBetaDB[s] += poptraits.ssqBetaDB[s]; - ts.sumStepL[s] += poptraits.sumStepL[s]; ts.ssqStepL[s] += poptraits.ssqStepL[s]; - ts.sumRho[s] += poptraits.sumRho[s]; ts.ssqRho[s] += poptraits.ssqRho[s]; - ts.sumS0[s] += poptraits.sumS0[s]; ts.ssqS0[s] += poptraits.ssqS0[s]; - ts.sumAlphaS[s] += poptraits.sumAlphaS[s]; ts.ssqAlphaS[s] += poptraits.ssqAlphaS[s]; - ts.sumBetaS[s] += poptraits.sumBetaS[s]; ts.ssqBetaS[s] += poptraits.ssqBetaS[s]; -#if RSDEBUG -//DEBUGLOG << "SubCommunity::outTraits(): i=" << i << " popns[i]=" << popns[i] -// << " s=" << s -//// << " poptraits.sumRho[s]= " << poptraits.sumRho[s] -//// << " ts.sumRho[s]= " << ts.sumRho[s] -// << " poptraits.sumDP[s]= " << poptraits.sumDP[s] << " poptraits.ssqDP[s]= " << poptraits.ssqDP[s] -// << " ts.sumDP[s]= " << ts.sumDP[s] << " ts.ssqDP[s]= " << ts.ssqDP[s] -// << " poptraits.sumGB[s]= " << poptraits.sumGB[s] << " poptraits.ssqGB[s]= " << poptraits.ssqGB[s] -// << " ts.sumGB[s]= " << ts.sumGB[s] << " ts.ssqGB[s]= " << ts.ssqGB[s] -// << endl; -#endif + if (writefile) outtraits << endl; + + for (int s = 0; s < NSEXES; s++) { + ts.ninds[s] += poptraits.ninds[s]; + ts.sumD0[s] += poptraits.sumD0[s]; ts.ssqD0[s] += poptraits.ssqD0[s]; + ts.sumAlpha[s] += poptraits.sumAlpha[s]; ts.ssqAlpha[s] += poptraits.ssqAlpha[s]; + ts.sumBeta[s] += poptraits.sumBeta[s]; ts.ssqBeta[s] += poptraits.ssqBeta[s]; + ts.sumDist1[s] += poptraits.sumDist1[s]; ts.ssqDist1[s] += poptraits.ssqDist1[s]; + ts.sumDist2[s] += poptraits.sumDist2[s]; ts.ssqDist2[s] += poptraits.ssqDist2[s]; + ts.sumProp1[s] += poptraits.sumProp1[s]; ts.ssqProp1[s] += poptraits.ssqProp1[s]; + ts.sumDP[s] += poptraits.sumDP[s]; ts.ssqDP[s] += poptraits.ssqDP[s]; + ts.sumGB[s] += poptraits.sumGB[s]; ts.ssqGB[s] += poptraits.ssqGB[s]; + ts.sumAlphaDB[s] += poptraits.sumAlphaDB[s]; ts.ssqAlphaDB[s] += poptraits.ssqAlphaDB[s]; + ts.sumBetaDB[s] += poptraits.sumBetaDB[s]; ts.ssqBetaDB[s] += poptraits.ssqBetaDB[s]; + ts.sumStepL[s] += poptraits.sumStepL[s]; ts.ssqStepL[s] += poptraits.ssqStepL[s]; + ts.sumRho[s] += poptraits.sumRho[s]; ts.ssqRho[s] += poptraits.ssqRho[s]; + ts.sumS0[s] += poptraits.sumS0[s]; ts.ssqS0[s] += poptraits.ssqS0[s]; + ts.sumAlphaS[s] += poptraits.sumAlphaS[s]; ts.ssqAlphaS[s] += poptraits.ssqAlphaS[s]; + ts.sumBetaS[s] += poptraits.sumBetaS[s]; ts.ssqBetaS[s] += poptraits.ssqBetaS[s]; + } } } -} -return ts; + return ts; } //--------------------------------------------------------------------------- diff --git a/SubCommunity.h b/SubCommunity.h index ece9281..c795c8c 100644 --- a/SubCommunity.h +++ b/SubCommunity.h @@ -54,10 +54,6 @@ using namespace std; #include "../Version.h" #endif -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif - #include "Parameters.h" #include "Landscape.h" #include "Population.h" @@ -111,7 +107,7 @@ class SubCommunity { Individual*, // pointer to Individual Species* // pointer to Species ); -#if RS_RCPP // included also SEASONAL +#if RS_RCPP int transfer( // Transfer through matrix - run for matrix SubCommunity only Landscape*, // pointer to Landscape short, // landscape change index @@ -122,7 +118,7 @@ class SubCommunity { Landscape*, // pointer to Landscape short // landscape change index ); -#endif // SEASONAL || RS_RCPP +#endif // RS_RCPP // Remove emigrants from patch 0 (matrix) and transfer to SubCommunity in which // their destination co-ordinates fall (executed for the matrix patch only) void completeDispersal( @@ -200,7 +196,6 @@ class SubCommunity { private: intptr subCommNum; // SubCommunity number // 0 is reserved for the SubCommunity in the inter-patch matrix -// intptr *occupancy; // pointer to occupancy array Patch *pPatch; int *occupancy; // pointer to occupancy array std::vector popns; From d6d9db0b1fc0f328133d4e82b3ffde65dad154cd Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 28 Nov 2023 16:14:18 +0000 Subject: [PATCH 21/46] rm commented out code and fix indent in Species --- Species.cpp | 1985 ++++++++++++++++++++++++--------------------------- Species.h | 111 ++- 2 files changed, 1002 insertions(+), 1094 deletions(-) diff --git a/Species.cpp b/Species.cpp index 727e3c3..4459793 100644 --- a/Species.cpp +++ b/Species.cpp @@ -1,154 +1,152 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Species.h" //--------------------------------------------------------------------------- Species::Species(void) { -// initialise demographic parameters -repType = 0; nStages = 2; -stageStruct = false; -propMales = 0.5; harem = 1.0; bc = 1.0; lambda = 1.5; probRep = 1.0; -repSeasons = 1; -repInterval = 0; maxAge = 1000; survival = 1; -fecDens = false; fecStageDens = false; -devDens = false; devStageDens = false; -survDens = false; survStageDens = false; -disperseOnLoss = false; -for (int i = 0; i < NSTAGES; i++) { - for (int j = 0; j < NSEXES; j++) { - fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; - minAge[i][j] = 0; - } -} -devCoeff = survCoeff = 1.0; -ddwtFec = ddwtDev = ddwtSurv = 0; ddwtFecDim = ddwtDevDim = ddwtSurvDim = 0; -habK = 0; habDimK = 0; -minRK = 1.0; maxRK = 2.0; - -// initialise genome attributes -nChromosomes = nTraits = 0; -emigTrait[0] = 0; emigTrait[1] = 0; -movtTrait[0] = 0; movtTrait[1] = 0; -settTrait[0] = 0; settTrait[1] = 0; -//genomeCanRecombine = false; -diploid = true; -neutralMarkers = false; -pleiotropic = false; -trait1Chromosome = true; -probMutn = 0.0001f; -probCrossover = 0.0001f; -alleleSD = mutationSD = 0.1f; -nNLoci = 0; -nLoci = NULL; -traitdata = NULL; -traitnames = NULL; -nTraitNames = 0; - -// initialise emigration parameters -densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; -emigStage = 0; -for (int i = 0; i < NSTAGES; i++) { + // initialise demographic parameters + repType = 0; nStages = 2; + stageStruct = false; + propMales = 0.5; harem = 1.0; bc = 1.0; lambda = 1.5; probRep = 1.0; + repSeasons = 1; + repInterval = 0; maxAge = 1000; survival = 1; + fecDens = false; fecStageDens = false; + devDens = false; devStageDens = false; + survDens = false; survStageDens = false; + disperseOnLoss = false; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + fec[i][j] = 0.0; dev[i][j] = 0.0; surv[i][j] = 0.0; + minAge[i][j] = 0; + } + } + devCoeff = survCoeff = 1.0; + ddwtFec = ddwtDev = ddwtSurv = 0; ddwtFecDim = ddwtDevDim = ddwtSurvDim = 0; + habK = 0; habDimK = 0; + minRK = 1.0; maxRK = 2.0; + + // initialise genome attributes + nChromosomes = nTraits = 0; + emigTrait[0] = 0; emigTrait[1] = 0; + movtTrait[0] = 0; movtTrait[1] = 0; + settTrait[0] = 0; settTrait[1] = 0; + diploid = true; + neutralMarkers = false; + pleiotropic = false; + trait1Chromosome = true; + probMutn = 0.0001f; + probCrossover = 0.0001f; + alleleSD = mutationSD = 0.1f; + nNLoci = 0; + nLoci = NULL; + traitdata = NULL; + traitnames = NULL; + nTraitNames = 0; + + // initialise emigration parameters + densDepEmig = false; stgDepEmig = false; sexDepEmig = false; indVarEmig = false; + emigStage = 0; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; + } + } for (int j = 0; j < NSEXES; j++) { - d0[i][j] = 0.0; alphaEmig[i][j] = 0.0; betaEmig[i][j] = 1.0; + d0Mean[0][j] = 0.0; alphaMean[0][j] = 0.0; betaMean[0][j] = 1.0; + d0SD[0][j] = 0.0; alphaSD[0][j] = 0.0; betaSD[0][j] = 1.0; + } + d0Scale = alphaScale = betaScale = 0.0; + + // initialise transfer parameters + moveModel = false; stgDepTrfr = false; sexDepTrfr = false; distMort = false; + indVarTrfr = false; + twinKern = false; + habMort = false; + costMap = false; + moveType = 1; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; + } } -} -for (int j = 0; j < NSEXES; j++) { - d0Mean[0][j] = 0.0; alphaMean[0][j] = 0.0; betaMean[0][j] = 1.0; - d0SD[0][j] = 0.0; alphaSD[0][j] = 0.0; betaSD[0][j] = 1.0; -} -d0Scale = alphaScale = betaScale = 0.0; - -// initialise transfer parameters -moveModel = false; stgDepTrfr = false; sexDepTrfr = false; distMort = false; -indVarTrfr = false; -twinKern = false; -habMort = false; -costMap = false; -moveType = 1; -for (int i = 0; i < NSTAGES; i++) { for (int j = 0; j < NSEXES; j++) { - meanDist1[i][j] = 100.0f; meanDist2[i][j] = 1000.0f; probKern1[i][j] = 0.99f; - } -} -for (int j = 0; j < NSEXES; j++) { - dist1Mean[0][j] = 100.0; dist1SD[0][j] = 10.0; - dist2Mean[0][j] = 1000.0; dist2SD[0][j] = 100.0; - PKern1Mean[0][j] = 0.9f; PKern1SD[0][j] = 0.01f; - stepLgthMean[0][j] = 10.0; stepLgthSD[0][j] = 1.0; - rhoMean[0][j] = 0.9f; rhoSD[0][j] = 0.01f; - dpMean[0][j] = 1.0; dpSD[0][j] = 0.1f; - gbMean[0][j] = 1.0; gbSD[0][j] = 0.1f; - alphaDBMean[0][j] = 1.0; alphaDBSD[0][j] = 0.1f; - betaDBMean[0][j] = 10.0; betaDBSD[0][j] = 1.0; -} -pr = 1; prMethod = 1; memSize = 1; goalType = 0; -dp = 1.0; gb = 1.0; alphaDB = 1.0; betaDB = 100000; -stepMort = 0.0; stepLength = 10.0; rho = 0.9f; -habStepMort = 0; habCost = 0; -//costMapFile = "NULL"; -fixedMort = 0.0; mortAlpha = 0.0; mortBeta = 1.0; -dist1Scale = dist2Scale = PKern1Scale = stepLScale = rhoScale = 0.0; -dpScale = 0.1f; gbScale = 0.1f; alphaDBScale = 0.1f; betaDBScale = 1.0; -habDimTrfr = 0; -straigtenPath = false; -fullKernel = false; - -// initialise settlement parameters -stgDepSett = false; sexDepSett = false; indVarSett = false; -minSteps = 0; maxSteps = 99999999; -for (int i = 0; i < NSTAGES; i++) { + dist1Mean[0][j] = 100.0; dist1SD[0][j] = 10.0; + dist2Mean[0][j] = 1000.0; dist2SD[0][j] = 100.0; + PKern1Mean[0][j] = 0.9f; PKern1SD[0][j] = 0.01f; + stepLgthMean[0][j] = 10.0; stepLgthSD[0][j] = 1.0; + rhoMean[0][j] = 0.9f; rhoSD[0][j] = 0.01f; + dpMean[0][j] = 1.0; dpSD[0][j] = 0.1f; + gbMean[0][j] = 1.0; gbSD[0][j] = 0.1f; + alphaDBMean[0][j] = 1.0; alphaDBSD[0][j] = 0.1f; + betaDBMean[0][j] = 10.0; betaDBSD[0][j] = 1.0; + } + pr = 1; prMethod = 1; memSize = 1; goalType = 0; + dp = 1.0; gb = 1.0; alphaDB = 1.0; betaDB = 100000; + stepMort = 0.0; stepLength = 10.0; rho = 0.9f; + habStepMort = 0; habCost = 0; + fixedMort = 0.0; mortAlpha = 0.0; mortBeta = 1.0; + dist1Scale = dist2Scale = PKern1Scale = stepLScale = rhoScale = 0.0; + dpScale = 0.1f; gbScale = 0.1f; alphaDBScale = 0.1f; betaDBScale = 1.0; + habDimTrfr = 0; + straigtenPath = false; + fullKernel = false; + + // initialise settlement parameters + stgDepSett = false; sexDepSett = false; indVarSett = false; + minSteps = 0; maxSteps = 99999999; + for (int i = 0; i < NSTAGES; i++) { + for (int j = 0; j < NSEXES; j++) { + densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; + maxStepsYr[i][j] = 99999999; + s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; + } + } for (int j = 0; j < NSEXES; j++) { - densDepSett[i][j] = false; wait[i][j] = false; go2nbrLocn[i][j] = false; findMate[i][j] = false; - maxStepsYr[i][j] = 99999999; - s0[i][j] = 1.0; alphaS[i][j] = 0.0; betaS[i][j] = 1.0; + alphaSMean[0][j] = 0.0; alphaSSD[0][j] = 0.0; + betaSMean[0][j] = 0.0; betaSSD[0][j] = 0.0; + s0Mean[0][j] = 0.0; s0SD[0][j] = 0.0; } -} -for (int j = 0; j < NSEXES; j++) { - alphaSMean[0][j] = 0.0; alphaSSD[0][j] = 0.0; - betaSMean[0][j] = 0.0; betaSSD[0][j] = 0.0; - s0Mean[0][j] = 0.0; s0SD[0][j] = 0.0; -} -alphaSScale = 0.0; betaSScale = 0.0; s0Scale = 0.0; + alphaSScale = 0.0; betaSScale = 0.0; s0Scale = 0.0; -// initialise attributes -spNum = 0; + // initialise attributes + spNum = 0; } Species::~Species() { -// demographic parameters -if (habK != NULL) deleteHabK(); -if (ddwtFec != 0) deleteDDwtFec(); -if (ddwtDev != 0) deleteDDwtDev(); -if (ddwtSurv != 0) deleteDDwtSurv(); -// transfer parameters -if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); -if (nLoci != NULL) deleteLoci(); -if (traitdata != NULL) deleteTraitData(); -if (traitnames != NULL) deleteTraitNames(); + // demographic parameters + if (habK != NULL) deleteHabK(); + if (ddwtFec != 0) deleteDDwtFec(); + if (ddwtDev != 0) deleteDDwtDev(); + if (ddwtSurv != 0) deleteDDwtSurv(); + // transfer parameters + if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); + if (nLoci != NULL) deleteLoci(); + if (traitdata != NULL) deleteTraitData(); + if (traitnames != NULL) deleteTraitNames(); } short Species::getSpNum(void) { return spNum; } @@ -158,25 +156,25 @@ short Species::getSpNum(void) { return spNum; } // Demographic functions void Species::setDemogr(const demogrParams d) { -if (d.repType >= 0 && d.repType <= 2) repType = d.repType; -if (d.repSeasons >= 1) repSeasons = d.repSeasons; -stageStruct = d.stageStruct; -if (d.propMales > 0.0 && d.propMales < 1.0) propMales = d.propMales; -if (d.harem > 0.0) harem = d.harem; -if (d.bc > 0.0) bc = d.bc; -if (d.lambda > 0.0) lambda = d.lambda; + if (d.repType >= 0 && d.repType <= 2) repType = d.repType; + if (d.repSeasons >= 1) repSeasons = d.repSeasons; + stageStruct = d.stageStruct; + if (d.propMales > 0.0 && d.propMales < 1.0) propMales = d.propMales; + if (d.harem > 0.0) harem = d.harem; + if (d.bc > 0.0) bc = d.bc; + if (d.lambda > 0.0) lambda = d.lambda; } demogrParams Species::getDemogr(void) { -demogrParams d; -d.repType = repType; -d.repSeasons = repSeasons; -d.stageStruct = stageStruct; -d.propMales = propMales; -d.harem = harem; -d.bc = bc; -d.lambda = lambda; -return d; + demogrParams d; + d.repType = repType; + d.repSeasons = repSeasons; + d.stageStruct = stageStruct; + d.propMales = propMales; + d.harem = harem; + d.bc = bc; + d.lambda = lambda; + return d; } short Species::getRepType(void) { return repType; } @@ -184,237 +182,236 @@ short Species::getRepType(void) { return repType; } bool Species::stageStructured(void) { return stageStruct; } void Species::createHabK(short nhab) { -if (nhab >= 0) { - habDimK = nhab; - if (habK != 0) deleteHabK(); - habK = new float[nhab]; - for (int i = 0; i < nhab; i++) habK[i] = 0.0; -} + if (nhab >= 0) { + habDimK = nhab; + if (habK != 0) deleteHabK(); + habK = new float[nhab]; + for (int i = 0; i < nhab; i++) habK[i] = 0.0; + } } -void Species::setHabK(short hx,float k) { -if (hx >= 0 && hx < habDimK) { - if (k >= 0.0) habK[hx] = k; -} +void Species::setHabK(short hx, float k) { + if (hx >= 0 && hx < habDimK) { + if (k >= 0.0) habK[hx] = k; + } } float Species::getHabK(short hx) { -float k = 0.0; -if (hx >= 0 && hx < habDimK) k = habK[hx]; -return k; + float k = 0.0; + if (hx >= 0 && hx < habDimK) k = habK[hx]; + return k; } float Species::getMaxK(void) { -float k = 0.0; -for (int i = 0; i < habDimK; i++) { - if (habK[i] > k) k = habK[i]; -} -return k; + float k = 0.0; + for (int i = 0; i < habDimK; i++) { + if (habK[i] > k) k = habK[i]; + } + return k; } void Species::deleteHabK(void) { -if (habK != 0) { - delete[] habK; habK = 0; -} + if (habK != 0) { + delete[] habK; habK = 0; + } } void Species::setStage(const stageParams s) { -if (s.nStages > 1) nStages = s.nStages; -if (s.repInterval >= 0) repInterval = s.repInterval; -if (s.maxAge >= 1) maxAge = s.maxAge; -if (s.survival >= 0 && s.survival <= 2) survival = s.survival; -if (s.probRep > 0.0 && s.probRep <= 1.0) probRep = s.probRep; -fecDens = s.fecDens; fecStageDens = s.fecStageDens; -devDens = s.devDens; devStageDens = s.devStageDens; -survDens = s.survDens; survStageDens = s.survStageDens; -disperseOnLoss = s.disperseOnLoss; + if (s.nStages > 1) nStages = s.nStages; + if (s.repInterval >= 0) repInterval = s.repInterval; + if (s.maxAge >= 1) maxAge = s.maxAge; + if (s.survival >= 0 && s.survival <= 2) survival = s.survival; + if (s.probRep > 0.0 && s.probRep <= 1.0) probRep = s.probRep; + fecDens = s.fecDens; fecStageDens = s.fecStageDens; + devDens = s.devDens; devStageDens = s.devStageDens; + survDens = s.survDens; survStageDens = s.survStageDens; + disperseOnLoss = s.disperseOnLoss; } stageParams Species::getStage(void) { -stageParams s; -s.nStages = nStages; s.repInterval = repInterval; s.maxAge = maxAge; -s.survival = survival; s.probRep = probRep; -s.fecDens = fecDens; s.fecStageDens = fecStageDens; -s.devDens = devDens; s.devStageDens = devStageDens; -s.survDens = survDens; s.survStageDens = survStageDens; -s.disperseOnLoss = disperseOnLoss; -return s; + stageParams s; + s.nStages = nStages; s.repInterval = repInterval; s.maxAge = maxAge; + s.survival = survival; s.probRep = probRep; + s.fecDens = fecDens; s.fecStageDens = fecStageDens; + s.devDens = devDens; s.devStageDens = devStageDens; + s.survDens = survDens; s.survStageDens = survStageDens; + s.disperseOnLoss = disperseOnLoss; + return s; } -void Species::setFec(short stg,short sex,float f) { -// NB fecundity for stage 0 must always be zero -if (stg > 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && f >= 0) - fec[stg][sex] = f; +void Species::setFec(short stg, short sex, float f) { + // NB fecundity for stage 0 must always be zero + if (stg > 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && f >= 0) + fec[stg][sex] = f; } -float Species::getFec(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return fec[stg][sex]; -else return 0.0; +float Species::getFec(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return fec[stg][sex]; + else return 0.0; } float Species::getMaxFec(void) { -float maxfec = 0.0; -if (stageStruct) { - for (int stg = 1; stg < NSTAGES; stg++) { - if (fec[stg][0] > maxfec) maxfec = fec[stg][0]; + float maxfec = 0.0; + if (stageStruct) { + for (int stg = 1; stg < NSTAGES; stg++) { + if (fec[stg][0] > maxfec) maxfec = fec[stg][0]; + } } -} -else maxfec = lambda; -return maxfec; + else maxfec = lambda; + return maxfec; } -void Species::setDev(short stg,short sex,float d) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && d >= 0) - dev[stg][sex] = d; +void Species::setDev(short stg, short sex, float d) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && d >= 0) + dev[stg][sex] = d; } -float Species::getDev(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return dev[stg][sex]; -else return 0.0; +float Species::getDev(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return dev[stg][sex]; + else return 0.0; } -void Species::setSurv(short stg,short sex,float s) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && s >= 0) - surv[stg][sex] = s; +void Species::setSurv(short stg, short sex, float s) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES && s >= 0) + surv[stg][sex] = s; } -float Species::getSurv(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return surv[stg][sex]; -else return 0.0; +float Species::getSurv(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return surv[stg][sex]; + else return 0.0; } -void Species::setMinAge(short stg,short sex,int age) { -// NB min age for stages 0 & 1 must always be zero -if (stg > 1 && stg < NSTAGES && sex >= 0 && sex < NSEXES && age >= 0) - minAge[stg][sex] = age; +void Species::setMinAge(short stg, short sex, int age) { + // NB min age for stages 0 & 1 must always be zero + if (stg > 1 && stg < NSTAGES && sex >= 0 && sex < NSEXES && age >= 0) + minAge[stg][sex] = age; } -short Species::getMinAge(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) - return minAge[stg][sex]; -else return 0; +short Species::getMinAge(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) + return minAge[stg][sex]; + else return 0; } void Species::setDensDep(float d, float s) { -if (d > 0.0) devCoeff = d; -if (s > 0.0) survCoeff = s; + if (d > 0.0) devCoeff = d; + if (s > 0.0) survCoeff = s; } densDepParams Species::getDensDep(void) { -densDepParams d; -d.devCoeff = devCoeff; d.survCoeff = survCoeff; -return d; + densDepParams d; + d.devCoeff = devCoeff; d.survCoeff = survCoeff; + return d; } void Species::createDDwtFec(short mSize) { -if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { - if (ddwtFec != 0) deleteDDwtFec(); - ddwtFecDim = mSize; - ddwtFec = new float *[mSize]; - for (int i = 0; i < mSize; i++) { - ddwtFec[i] = new float[mSize]; - for (int j = 0; j < mSize; j++) ddwtFec[i][j] = 1.0; + if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (ddwtFec != 0) deleteDDwtFec(); + ddwtFecDim = mSize; + ddwtFec = new float* [mSize]; + for (int i = 0; i < mSize; i++) { + ddwtFec[i] = new float[mSize]; + for (int j = 0; j < mSize; j++) ddwtFec[i][j] = 1.0; + } } } -} -void Species::setDDwtFec(short row,short col,float f) { -if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) - ddwtFec[row][col] = f; +void Species::setDDwtFec(short row, short col, float f) { + if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) + ddwtFec[row][col] = f; } -float Species::getDDwtFec(short row,short col) { -if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) - return ddwtFec[row][col]; -else return 0.0; +float Species::getDDwtFec(short row, short col) { + if (row >= 0 && row < ddwtFecDim && col >= 0 && col < ddwtFecDim) + return ddwtFec[row][col]; + else return 0.0; } void Species::deleteDDwtFec(void) { -if (ddwtFec != 0) { - for (int i = 0; i < ddwtFecDim; i++) if (ddwtFec[i] != 0) { - delete[] ddwtFec[i]; + if (ddwtFec != 0) { + for (int i = 0; i < ddwtFecDim; i++) if (ddwtFec[i] != 0) { + delete[] ddwtFec[i]; + } + delete[] ddwtFec; ddwtFec = 0; } - delete[] ddwtFec; ddwtFec = 0; -} } void Species::createDDwtDev(short mSize) { -if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { - if (ddwtDev != 0) deleteDDwtDev(); - ddwtDevDim = mSize; - ddwtDev = new float *[mSize]; - for (int i = 0; i < mSize; i++) { - ddwtDev[i] = new float[mSize]; - for (int j = 0; j < mSize; j++) ddwtDev[i][j] = 1.0; + if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (ddwtDev != 0) deleteDDwtDev(); + ddwtDevDim = mSize; + ddwtDev = new float* [mSize]; + for (int i = 0; i < mSize; i++) { + ddwtDev[i] = new float[mSize]; + for (int j = 0; j < mSize; j++) ddwtDev[i][j] = 1.0; + } } } -} -void Species::setDDwtDev(short row,short col,float f) { -if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) - ddwtDev[row][col] = f; +void Species::setDDwtDev(short row, short col, float f) { + if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) + ddwtDev[row][col] = f; } -float Species::getDDwtDev(short row,short col) { -if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) - return ddwtDev[row][col]; -else return 0.0; +float Species::getDDwtDev(short row, short col) { + if (row >= 0 && row < ddwtDevDim && col >= 0 && col < ddwtDevDim) + return ddwtDev[row][col]; + else return 0.0; } void Species::deleteDDwtDev(void) { -if (ddwtDev != 0) { - for (int i = 0; i < ddwtDevDim; i++) if (ddwtDev[i] != 0) { - delete[] ddwtDev[i]; + if (ddwtDev != 0) { + for (int i = 0; i < ddwtDevDim; i++) if (ddwtDev[i] != 0) { + delete[] ddwtDev[i]; + } + delete[] ddwtDev; ddwtDev = 0; } - delete[] ddwtDev; ddwtDev = 0; -} } void Species::createDDwtSurv(short mSize) { -if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { - if (ddwtSurv != 0) deleteDDwtSurv(); - ddwtSurvDim = mSize; - ddwtSurv = new float *[mSize]; - for (int i = 0; i < mSize; i++) { - ddwtSurv[i] = new float[mSize] ; - for (int j = 0; j < mSize; j++) ddwtSurv[i][j] = 1.0; + if (mSize >= 0 && mSize < (NSTAGES * NSEXES)) { + if (ddwtSurv != 0) deleteDDwtSurv(); + ddwtSurvDim = mSize; + ddwtSurv = new float* [mSize]; + for (int i = 0; i < mSize; i++) { + ddwtSurv[i] = new float[mSize]; + for (int j = 0; j < mSize; j++) ddwtSurv[i][j] = 1.0; + } } } -} -void Species::setDDwtSurv(short row,short col, float f) { -if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) - ddwtSurv[row][col] = f; +void Species::setDDwtSurv(short row, short col, float f) { + if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) + ddwtSurv[row][col] = f; } -float Species::getDDwtSurv(short row,short col) { -if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) - return ddwtSurv[row][col]; -else return 0.0; +float Species::getDDwtSurv(short row, short col) { + if (row >= 0 && row < ddwtSurvDim && col >= 0 && col < ddwtSurvDim) + return ddwtSurv[row][col]; + else return 0.0; } void Species::deleteDDwtSurv(void) { -if (ddwtSurv != 0) { - for (int i = 0; i < ddwtSurvDim; i++) if (ddwtSurv[i] != 0) { - delete[] ddwtSurv[i]; + if (ddwtSurv != 0) { + for (int i = 0; i < ddwtSurvDim; i++) if (ddwtSurv[i] != 0) { + delete[] ddwtSurv[i]; + } + delete[] ddwtSurv; ddwtSurv = 0; } - delete[] ddwtSurv; ddwtSurv = 0; -} } // Functions to handle min/max R or K (under environmental stochasticity) -//void Species::setMinMax(float min,float max) { -void Species::setMinMax(float min, float max) { -if (min >= 0.0 && max > min) { - minRK = min; maxRK = max; -} +void Species::setMinMax(float min, float max) { + if (min >= 0.0 && max > min) { + minRK = min; maxRK = max; + } } float Species::getMinMax(short opt) { -if (opt == 0) return minRK; -else return maxRK; + if (opt == 0) return minRK; + else return maxRK; } //--------------------------------------------------------------------------- @@ -422,31 +419,31 @@ else return maxRK; // Genome functions void Species::setGenomeData(genomeData d) { -diploid = d.diploid; -neutralMarkers = d.neutralMarkers; -trait1Chromosome = d.trait1Chromosome; -if (trait1Chromosome) { - if (d.nLoci > 0) nLoci[0] = d.nLoci; -} -if (d.probMutn >= 0.0 && d.probMutn <= 1.0) probMutn = d.probMutn; -if (d.probCrossover >= 0.0 && d.probCrossover <= 1.0) probCrossover = d.probCrossover; -if (d.alleleSD > 0.0) alleleSD = d.alleleSD; -if (d.mutationSD > 0.0) mutationSD = d.mutationSD; + diploid = d.diploid; + neutralMarkers = d.neutralMarkers; + trait1Chromosome = d.trait1Chromosome; + if (trait1Chromosome) { + if (d.nLoci > 0) nLoci[0] = d.nLoci; + } + if (d.probMutn >= 0.0 && d.probMutn <= 1.0) probMutn = d.probMutn; + if (d.probCrossover >= 0.0 && d.probCrossover <= 1.0) probCrossover = d.probCrossover; + if (d.alleleSD > 0.0) alleleSD = d.alleleSD; + if (d.mutationSD > 0.0) mutationSD = d.mutationSD; } genomeData Species::getGenomeData(void) { -genomeData d; -d.diploid = diploid; -d.neutralMarkers = neutralMarkers; -d.pleiotropic = pleiotropic; -d.trait1Chromosome = trait1Chromosome; -if (nLoci != NULL) d.nLoci = nLoci[0]; -else d.nLoci = 0; -d.probMutn = probMutn; -d.probCrossover = probCrossover; -d.alleleSD = alleleSD; -d.mutationSD = mutationSD; -return d; + genomeData d; + d.diploid = diploid; + d.neutralMarkers = neutralMarkers; + d.pleiotropic = pleiotropic; + d.trait1Chromosome = trait1Chromosome; + if (nLoci != NULL) d.nLoci = nLoci[0]; + else d.nLoci = 0; + d.probMutn = probMutn; + d.probCrossover = probCrossover; + d.alleleSD = alleleSD; + d.mutationSD = mutationSD; + return d; } bool Species::isDiploid(void) { return diploid; } @@ -454,42 +451,42 @@ bool Species::isDiploid(void) { return diploid; } // Chromosome functions void Species::setNChromosomes(int c) { -if (nLoci != NULL) deleteLoci(); -if (c > 0) { - nChromosomes = nNLoci = c; - nLoci = new short [c]; - for (int i = 0; i < nNLoci; i++) nLoci[i] = 0; -} -else nChromosomes = nNLoci = 0; + if (nLoci != NULL) deleteLoci(); + if (c > 0) { + nChromosomes = nNLoci = c; + nLoci = new short[c]; + for (int i = 0; i < nNLoci; i++) nLoci[i] = 0; + } + else nChromosomes = nNLoci = 0; } int Species::getNChromosomes(void) { return nChromosomes; } -void Species::setNLoci(const short chr,const short nloc) { -if (chr >= 0 && chr < nNLoci) { - if (nloc > 0) nLoci[chr] = nloc; - else nLoci[chr] = 0; -} +void Species::setNLoci(const short chr, const short nloc) { + if (chr >= 0 && chr < nNLoci) { + if (nloc > 0) nLoci[chr] = nloc; + else nLoci[chr] = 0; + } } int Species::getNLoci(const short chr) { -if (chr >= 0 && chr < nChromosomes) return nLoci[chr]; -else return 0; + if (chr >= 0 && chr < nChromosomes) return nLoci[chr]; + else return 0; } void Species::deleteLoci(void) { -if (nLoci != NULL) { delete[] nLoci; nLoci = NULL; } + if (nLoci != NULL) { delete[] nLoci; nLoci = NULL; } } // Trait functions // Set 1:1 mapping of trait to chromosome void Species::set1ChromPerTrait(const int nloc) { -nChromosomes = nTraits; -if (nLoci != NULL) deleteLoci(); -nLoci = new short [1]; -if (nloc > 0) nLoci[0] = nloc; -else nLoci[0] = 1; + nChromosomes = nTraits; + if (nLoci != NULL) deleteLoci(); + nLoci = new short[1]; + if (nloc > 0) nLoci[0] = nloc; + else nLoci[0] = 1; } bool Species::has1ChromPerTrait(void) { return trait1Chromosome; } @@ -497,458 +494,393 @@ bool Species::has1ChromPerTrait(void) { return trait1Chromosome; } // Set trait attributes for the species void Species::setTraits(void) { -emigTrait[0] = 0; emigTrait[1] = 0; -movtTrait[0] = 0; movtTrait[1] = 0; -settTrait[0] = 0; settTrait[1] = 0; -nTraits = 0; + emigTrait[0] = 0; emigTrait[1] = 0; + movtTrait[0] = 0; movtTrait[1] = 0; + settTrait[0] = 0; settTrait[1] = 0; + nTraits = 0; #if RSDEBUG -DebugGUI("Species::setTraits(): 0000 nChromosomes=" + Int2Str(nChromosomes) - + " nTraits=" + Int2Str(nTraits) - + " indVarEmig=" + Int2Str((int)indVarEmig) - + " indVarTrfr=" + Int2Str((int)indVarTrfr) - + " indVarSett=" + Int2Str((int)indVarSett) + DebugGUI("Species::setTraits(): 0000 nChromosomes=" + Int2Str(nChromosomes) + + " nTraits=" + Int2Str(nTraits) + + " indVarEmig=" + Int2Str((int)indVarEmig) + + " indVarTrfr=" + Int2Str((int)indVarTrfr) + + " indVarSett=" + Int2Str((int)indVarSett) ); #endif -if (indVarEmig) { - if (sexDepEmig) { - if (densDepEmig) nTraits += 6; else nTraits += 2; - } - else { - if (densDepEmig) nTraits += 3; else nTraits += 1; - } - emigTrait[0] = 0; emigTrait[1] = nTraits; -} -#if RSDEBUG -//DebugGUI("Species::setTraits(): 1111 nTraits=" + Int2Str(nTraits)); -#endif - -int movttraits = 0; -if (indVarTrfr) { - if (moveModel) { - if (moveType == 1) { // SMS - movttraits = 1; // in contain batch 2 - if (goalType == 2) movttraits += 3; //in contain batch 2 + if (indVarEmig) { + if (sexDepEmig) { + if (densDepEmig) nTraits += 6; else nTraits += 2; } - if (moveType == 2) movttraits = 2; + else { + if (densDepEmig) nTraits += 3; else nTraits += 1; + } + emigTrait[0] = 0; emigTrait[1] = nTraits; } - else { - if (sexDepTrfr) { - if (twinKern) movttraits = 6; else movttraits = 2; + + int movttraits = 0; + if (indVarTrfr) { + if (moveModel) { + if (moveType == 1) { // SMS + movttraits = 1; // in contain batch 2 + if (goalType == 2) movttraits += 3; //in contain batch 2 + } + if (moveType == 2) movttraits = 2; } else { - if (twinKern) movttraits = 3; else movttraits = 1; + if (sexDepTrfr) { + if (twinKern) movttraits = 6; else movttraits = 2; + } + else { + if (twinKern) movttraits = 3; else movttraits = 1; + } } + movtTrait[0] = nTraits; movtTrait[1] = movttraits; + nTraits += movttraits; } - movtTrait[0] = nTraits; movtTrait[1] = movttraits; - nTraits += movttraits; -} -#if RSDEBUG -//DebugGUI("Species::setTraits(): 2222 nTraits=" + Int2Str(nTraits)); -#endif -int setttraits = 0; -if (indVarSett) { - if (sexDepSett) setttraits = 6; else setttraits = 3; - settTrait[0] = nTraits; settTrait[1] = setttraits; - nTraits += setttraits; -} + int setttraits = 0; + if (indVarSett) { + if (sexDepSett) setttraits = 6; else setttraits = 3; + settTrait[0] = nTraits; settTrait[1] = setttraits; + nTraits += setttraits; + } -setTraitNames(); + setTraitNames(); -//if (trait1Chromosome) { -// nChromosomes = nTraits; -//} #if RSDEBUG -DebugGUI("Species::setTraits(): 9999 nChromosomes=" + Int2Str(nChromosomes) - + " nTraits=" + Int2Str(nTraits)); + DebugGUI("Species::setTraits(): 9999 nChromosomes=" + Int2Str(nChromosomes) + + " nTraits=" + Int2Str(nTraits)); #endif } void Species::setTraitNames(void) { -#if RSDEBUG -//DebugGUI("Species::setTraitNames(): nTraits=" + Int2Str(nTraits) -// + " nTraitNames=" + Int2Str(nTraitNames) -// + " traitnames=" + Int2Str((int)traitnames) -// ); -//if (traitnames != NULL) { -// DebugGUI("Species::setTraitNames(): traitnames[0]=" + traitnames[0] -// ); -// if (nTraits > 1) { -// DebugGUI("Species::setTraitNames(): traitnames[1]=" + traitnames[1] -// ); -// } -//} -#endif -deleteTraitNames(); -nTraitNames = nTraits; -traitnames = new string [nTraitNames]; -int trait = 0; -if (indVarEmig) { - if (sexDepEmig) { - if (densDepEmig) { - traitnames[trait++] = "d0_F"; - traitnames[trait++] = "d0_M"; - traitnames[trait++] = "alpha_F"; - traitnames[trait++] = "alpha_M"; - traitnames[trait++] = "beta_F"; - traitnames[trait++] = "beta_M"; + deleteTraitNames(); + nTraitNames = nTraits; + traitnames = new string[nTraitNames]; + int trait = 0; + if (indVarEmig) { + if (sexDepEmig) { + if (densDepEmig) { + traitnames[trait++] = "d0_F"; + traitnames[trait++] = "d0_M"; + traitnames[trait++] = "alpha_F"; + traitnames[trait++] = "alpha_M"; + traitnames[trait++] = "beta_F"; + traitnames[trait++] = "beta_M"; + } + else { + traitnames[trait++] = "d0_F"; + traitnames[trait++] = "d0_M"; + } } else { - traitnames[trait++] = "d0_F"; - traitnames[trait++] = "d0_M"; - } - } - else { - traitnames[trait++] = "d0"; - if (densDepEmig) { - traitnames[trait++] = "alpha"; - traitnames[trait++] = "beta"; - } - } -} - -if (indVarTrfr) { - if (moveModel) { - if (moveType == 1) { // SMS - traitnames[trait++] = "DP"; - if (goalType == 2) { - traitnames[trait++] = "GB"; - traitnames[trait++] = "alphaDB"; - traitnames[trait++] = "betaDB"; + traitnames[trait++] = "d0"; + if (densDepEmig) { + traitnames[trait++] = "alpha"; + traitnames[trait++] = "beta"; } } - if (moveType == 2) { // CRW - traitnames[trait++] = "stepL"; - traitnames[trait++] = "rho"; - } } - else { - if (sexDepTrfr) { - if (twinKern) - { - traitnames[trait++] = "meanDistI_F"; - traitnames[trait++] = "meanDistI_M"; - traitnames[trait++] = "meanDistII_F"; - traitnames[trait++] = "meanDistII_M"; - traitnames[trait++] = "probKernI_F"; - traitnames[trait++] = "probKernI_M"; + + if (indVarTrfr) { + if (moveModel) { + if (moveType == 1) { // SMS + traitnames[trait++] = "DP"; + if (goalType == 2) { + traitnames[trait++] = "GB"; + traitnames[trait++] = "alphaDB"; + traitnames[trait++] = "betaDB"; + } } - else { - traitnames[trait++] = "meanDistI_F"; - traitnames[trait++] = "meanDistI_M"; + if (moveType == 2) { // CRW + traitnames[trait++] = "stepL"; + traitnames[trait++] = "rho"; } } else { - traitnames[trait++] = "meanDistI"; - if (twinKern) - { - traitnames[trait++] = "meanDistII"; - traitnames[trait++] = "probKernI"; + if (sexDepTrfr) { + if (twinKern) + { + traitnames[trait++] = "meanDistI_F"; + traitnames[trait++] = "meanDistI_M"; + traitnames[trait++] = "meanDistII_F"; + traitnames[trait++] = "meanDistII_M"; + traitnames[trait++] = "probKernI_F"; + traitnames[trait++] = "probKernI_M"; + } + else { + traitnames[trait++] = "meanDistI_F"; + traitnames[trait++] = "meanDistI_M"; + } + } + else { + traitnames[trait++] = "meanDistI"; + if (twinKern) + { + traitnames[trait++] = "meanDistII"; + traitnames[trait++] = "probKernI"; + } } } } -} -if (indVarSett) { - if (sexDepSett) { - traitnames[trait++] = "s0_F"; - traitnames[trait++] = "s0_M"; - traitnames[trait++] = "alphaS_F"; - traitnames[trait++] = "alphaS_M"; - traitnames[trait++] = "betaS_F"; - traitnames[trait++] = "betaS_M"; - } - else { - traitnames[trait++] = "s0"; - traitnames[trait++] = "alphaS"; - traitnames[trait++] = "betaS"; + if (indVarSett) { + if (sexDepSett) { + traitnames[trait++] = "s0_F"; + traitnames[trait++] = "s0_M"; + traitnames[trait++] = "alphaS_F"; + traitnames[trait++] = "alphaS_M"; + traitnames[trait++] = "betaS_F"; + traitnames[trait++] = "betaS_M"; + } + else { + traitnames[trait++] = "s0"; + traitnames[trait++] = "alphaS"; + traitnames[trait++] = "betaS"; + } } } -} void Species::deleteTraitNames(void) { -if (traitnames != NULL) { -#if RSDEBUG -//DebugGUI("Species::deleteTraitNames(): traitnames=" + Int2Str((int)traitnames) -// ); -#endif - delete[] traitnames; - traitnames = NULL; -} + if (traitnames != NULL) { + delete[] traitnames; + traitnames = NULL; + } } string Species::getTraitName(const int trait) { -string name = "not used"; -if (traitnames != NULL) { - if (trait >= 0 && trait < nTraits) { - name = traitnames[trait]; + string name = "not used"; + if (traitnames != NULL) { + if (trait >= 0 && trait < nTraits) { + name = traitnames[trait]; + } } -} -return name; + return name; } int Species::getNTraits(void) { return nTraits; } void Species::setTraitData(const int ntraits) { -#if RSDEBUG -//DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) -// + " ntraits=" + Int2Str(ntraits) -// ).c_str()); -#endif -deleteTraitData(); -traitdata = new traitData; -if (ntraits > 0) { - traitdata->nTraitMaps = ntraits; - traitdata->traitmaps = new traitMap *[ntraits]; - for (int i = 0; i < ntraits; i++) { - traitdata->traitmaps[i] = new traitMap; + deleteTraitData(); + traitdata = new traitData; + if (ntraits > 0) { + traitdata->nTraitMaps = ntraits; + traitdata->traitmaps = new traitMap * [ntraits]; + for (int i = 0; i < ntraits; i++) { + traitdata->traitmaps[i] = new traitMap; + } } -} -else { // neutral markers only - traitdata->nTraitMaps = 0; -} -traitdata->neutralloci = new traitMap; -traitdata->neutralloci->nAlleles = 0; -#if RSDEBUG -//DebugGUI(("Species::setTraitData(): traitdata=" + Int2Str((int)traitdata) -// + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) -// ).c_str()); -#endif + else { // neutral markers only + traitdata->nTraitMaps = 0; + } + traitdata->neutralloci = new traitMap; + traitdata->neutralloci->nAlleles = 0; } void Species::deleteTraitData(void) { -if (traitdata != NULL) { -#if RSDEBUG -//DebugGUI(("Species::deleteTraitData(): traitdata=" + Int2Str((int)traitdata) -// + " nTraitMaps=" + Int2Str(traitdata->nTraitMaps) -// ).c_str()); -#endif - for (int i = 0; i < traitdata->nTraitMaps; i++) { - if (traitdata->traitmaps[i]->traitalleles != 0) { - for (int j = 0; j < traitdata->traitmaps[i]->nAlleles; j++) { - delete traitdata->traitmaps[i]->traitalleles[j]; + if (traitdata != NULL) { + for (int i = 0; i < traitdata->nTraitMaps; i++) { + if (traitdata->traitmaps[i]->traitalleles != 0) { + for (int j = 0; j < traitdata->traitmaps[i]->nAlleles; j++) { + delete traitdata->traitmaps[i]->traitalleles[j]; + } } + delete[] traitdata->traitmaps[i]; } - delete[] traitdata->traitmaps[i]; + deleteNeutralLoci(); + delete traitdata; + traitdata = NULL; } - deleteNeutralLoci(); - delete traitdata; - traitdata = NULL; -} } int Species::getNTraitMaps(void) { -if (traitdata == NULL) return 0; -else return traitdata->nTraitMaps; + if (traitdata == NULL) return 0; + else return traitdata->nTraitMaps; } -void Species::setTraitMap(const short trait,const short nalleles) { -traitdata->traitmaps[trait]->nAlleles = nalleles; -traitdata->traitmaps[trait]->traitalleles = new traitAllele *[nalleles]; -for (int i = 0; i < nalleles; i++) { - traitdata->traitmaps[trait]->traitalleles[i] = new traitAllele; -} +void Species::setTraitMap(const short trait, const short nalleles) { + traitdata->traitmaps[trait]->nAlleles = nalleles; + traitdata->traitmaps[trait]->traitalleles = new traitAllele * [nalleles]; + for (int i = 0; i < nalleles; i++) { + traitdata->traitmaps[trait]->traitalleles[i] = new traitAllele; + } } int Species::getNTraitAlleles(const int trait) { -int nalleles = 0; -if (traitdata != NULL) { - if (trait >= 0 && trait < traitdata->nTraitMaps) { - nalleles = traitdata->traitmaps[trait]->nAlleles; + int nalleles = 0; + if (traitdata != NULL) { + if (trait >= 0 && trait < traitdata->nTraitMaps) { + nalleles = traitdata->traitmaps[trait]->nAlleles; + } } -} -return nalleles; + return nalleles; } -void Species::setTraitAllele(const short trait,const short allele, - const short chr,const short loc) +void Species::setTraitAllele(const short trait, const short allele, + const short chr, const short loc) { -traitdata->traitmaps[trait]->traitalleles[allele] = new traitAllele; -if (chr >= 0 && loc >= 0) { - traitdata->traitmaps[trait]->traitalleles[allele]->chromo = chr; - traitdata->traitmaps[trait]->traitalleles[allele]->locus = loc; -} -else { - traitdata->traitmaps[trait]->traitalleles[allele]->chromo = 0; - traitdata->traitmaps[trait]->traitalleles[allele]->locus = 0; -} + traitdata->traitmaps[trait]->traitalleles[allele] = new traitAllele; + if (chr >= 0 && loc >= 0) { + traitdata->traitmaps[trait]->traitalleles[allele]->chromo = chr; + traitdata->traitmaps[trait]->traitalleles[allele]->locus = loc; + } + else { + traitdata->traitmaps[trait]->traitalleles[allele]->chromo = 0; + traitdata->traitmaps[trait]->traitalleles[allele]->locus = 0; + } } -traitAllele Species::getTraitAllele(const short trait,const short allele) { -traitAllele a; a.chromo = 0; a.locus = 0; -if (traitdata != NULL) { - if (trait >= 0 && trait < traitdata->nTraitMaps) { - if (allele >= 0 && allele < traitdata->traitmaps[trait]->nAlleles) { - a = *traitdata->traitmaps[trait]->traitalleles[allele]; +traitAllele Species::getTraitAllele(const short trait, const short allele) { + traitAllele a; a.chromo = 0; a.locus = 0; + if (traitdata != NULL) { + if (trait >= 0 && trait < traitdata->nTraitMaps) { + if (allele >= 0 && allele < traitdata->traitmaps[trait]->nAlleles) { + a = *traitdata->traitmaps[trait]->traitalleles[allele]; + } } } -} -return a; + return a; } // Neutral loci functions // Identify neutral loci and determine whether there is pleiotropy void Species::setNeutralLoci(bool neutralMarkersOnly) { -bool neutral; -int nneutral = 0; -// find minimum of no. of defined / applied traits -int ntraits; -if (traitdata == 0 ) ntraits = 0; -else ntraits = traitdata->nTraitMaps; -if (ntraits > nTraits) ntraits = nTraits; -#if RSDEBUG -//DebugGUI("Species::setNeutralLoci(): neutralMarkersOnly=" + Int2Str((int)neutralMarkersOnly) -// + " nNLoci=" + Int2Str(nNLoci) -// + " nTraits=" + Int2Str(nTraits) + " ntraits=" + Int2Str(ntraits) -//); -#endif + bool neutral; + int nneutral = 0; + // find minimum of no. of defined / applied traits + int ntraits; + if (traitdata == 0) ntraits = 0; + else ntraits = traitdata->nTraitMaps; + if (ntraits > nTraits) ntraits = nTraits; // determine no. of neutral loci -deleteNeutralLoci(); -for (int i = 0; i < nNLoci; i++) { // each chromosome - for (int j = 0; j < nLoci[i]; j++) { // each locus - neutral = true; - for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { -#if RSDEBUG -//DebugGUI("Species::setNeutralLoci(): i=" + Int2Str(i) -// + " j=" + Int2Str(j) + " t=" + Int2Str(t) + " a=" + Int2Str(a) -// + " chromo=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->chromo) -// + " locus=" + Int2Str(traitdata->traitmaps[t]->traitalleles[a]->locus) -//); -#endif - if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo - && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { -#if RSDEBUG -//DebugGUI("Species::setNeutralLoci(): FALSE"); -#endif - neutral = false; // as locus contributes to a trait - a = 999999; + deleteNeutralLoci(); + for (int i = 0; i < nNLoci; i++) { // each chromosome + for (int j = 0; j < nLoci[i]; j++) { // each locus + neutral = true; + for (int t = 0; t < ntraits; t++) { // each trait + for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { +#if + if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo + && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { + neutral = false; // as locus contributes to a trait + a = 999999; + } } + if (!neutral) t = 999999; } - if (!neutral) t = 999999; + if (neutral) nneutral++; } - if (neutral) nneutral++; - } -} - -traitdata->neutralloci = new traitMap; -traitdata->neutralloci->nAlleles = nneutral; -if (nneutral < 1) return; - -// record neutral markers -traitdata->neutralloci->traitalleles = new traitAllele *[nneutral]; -nneutral = 0; -for (int i = 0; i < nNLoci; i++) { // each chromosome - for (int j = 0; j < nLoci[i]; j++) { // each locus - neutral = true; - for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { - if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo - && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { - neutral = false; // as locus contributes to a trait - a = 999999; + } + + traitdata->neutralloci = new traitMap; + traitdata->neutralloci->nAlleles = nneutral; + if (nneutral < 1) return; + + // record neutral markers + traitdata->neutralloci->traitalleles = new traitAllele * [nneutral]; + nneutral = 0; + for (int i = 0; i < nNLoci; i++) { // each chromosome + for (int j = 0; j < nLoci[i]; j++) { // each locus + neutral = true; + for (int t = 0; t < ntraits; t++) { // each trait + for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { + if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo + && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { + neutral = false; // as locus contributes to a trait + a = 999999; + } } + if (!neutral) t = 999999; + } + if (neutral) { + traitdata->neutralloci->traitalleles[nneutral] = new traitAllele; + traitdata->neutralloci->traitalleles[nneutral]->chromo = i; + traitdata->neutralloci->traitalleles[nneutral]->locus = j; + nneutral++; } - if (!neutral) t = 999999; - } - if (neutral) { - traitdata->neutralloci->traitalleles[nneutral] = new traitAllele; - traitdata->neutralloci->traitalleles[nneutral]->chromo = i; - traitdata->neutralloci->traitalleles[nneutral]->locus = j; - nneutral++; } } -} -pleiotropic = false; -if (neutralMarkersOnly) return; // pleiotropy cannot apply + pleiotropic = false; + if (neutralMarkersOnly) return; // pleiotropy cannot apply -// determine whether there is pleiotropy -int chr,loc; -int nloci = 0; // maximum no. of loci on any one chromosome -for (int i = 0; i < nNLoci; i++) { - if (nloci < nLoci[i]) nloci = nLoci[i]; -} -int ***locfreq; -locfreq = new int **[nNLoci]; -for (int i = 0; i < nNLoci; i++) { - locfreq[i] = new int *[nloci]; - for (int j = 0; j < nloci; j++) { - locfreq[i][j] = new int[ntraits]; - for (int t = 0; t < ntraits; t++) locfreq[i][j][t] = 0; + // determine whether there is pleiotropy + int chr, loc; + int nloci = 0; // maximum no. of loci on any one chromosome + for (int i = 0; i < nNLoci; i++) { + if (nloci < nLoci[i]) nloci = nLoci[i]; } -} -for (int t = 0; t < ntraits; t++) { // each trait - for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { - chr = traitdata->traitmaps[t]->traitalleles[a]->chromo; - loc = traitdata->traitmaps[t]->traitalleles[a]->locus; - locfreq[chr][loc][t]++; + int*** locfreq; + locfreq = new int** [nNLoci]; + for (int i = 0; i < nNLoci; i++) { + locfreq[i] = new int* [nloci]; + for (int j = 0; j < nloci; j++) { + locfreq[i][j] = new int[ntraits]; + for (int t = 0; t < ntraits; t++) locfreq[i][j][t] = 0; + } } -} -#if RSDEBUG -//for (int i = 0; i < nNLoci; i++) { -// for (int j = 0; j < nloci; j++) -// for (int t = 0; t < ntraits; t++) -// DebugGUI("locfreq[" + Int2Str(i) + "][" + Int2Str(j) + "][" + Int2Str(t) -// + "]=" + Int2Str(locfreq[i][j][t])); -//} -#endif -for (int i = 0; i < nNLoci; i++) { - for (int j = 0; j < nloci; j++) { - // remove multiple contributions of a locus to a particular trait - // (i.e. prevent recording of pseudo-pleiotropy) - for (int t = 0; t < ntraits; t++) { - if (locfreq[i][j][t] > 0) locfreq[i][j][t] = 1; + for (int t = 0; t < ntraits; t++) { // each trait + for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { + chr = traitdata->traitmaps[t]->traitalleles[a]->chromo; + loc = traitdata->traitmaps[t]->traitalleles[a]->locus; + locfreq[chr][loc][t]++; } - // sum at level of chromosome/locus - for (int t = 1; t < ntraits; t++) { - locfreq[i][j][0] += locfreq[i][j][t]; + } + for (int i = 0; i < nNLoci; i++) { + for (int j = 0; j < nloci; j++) { + // remove multiple contributions of a locus to a particular trait + // (i.e. prevent recording of pseudo-pleiotropy) + for (int t = 0; t < ntraits; t++) { + if (locfreq[i][j][t] > 0) locfreq[i][j][t] = 1; + } + // sum at level of chromosome/locus + for (int t = 1; t < ntraits; t++) { + locfreq[i][j][0] += locfreq[i][j][t]; + } + if (locfreq[i][j][0] > 1) pleiotropic = true; } - if (locfreq[i][j][0] > 1) pleiotropic = true; } -} -for (int i = 0; i < nNLoci; i++) { - for (int j = 0; j < nloci; j++) { - delete[] locfreq[i][j]; + for (int i = 0; i < nNLoci; i++) { + for (int j = 0; j < nloci; j++) { + delete[] locfreq[i][j]; + } + delete[] locfreq[i]; } - delete[] locfreq[i]; -} -delete[] locfreq; + delete[] locfreq; } void Species::deleteNeutralLoci(void) { -if (traitdata->neutralloci != NULL) { - for (int i = 0; i < traitdata->neutralloci->nAlleles; i++) { - delete traitdata->neutralloci->traitalleles[i]; + if (traitdata->neutralloci != NULL) { + for (int i = 0; i < traitdata->neutralloci->nAlleles; i++) { + delete traitdata->neutralloci->traitalleles[i]; + } + delete[] traitdata->neutralloci; } - delete[] traitdata->neutralloci; -} -traitdata->neutralloci = NULL; + traitdata->neutralloci = NULL; } int Species::getNNeutralLoci(void) { -int nn = 0; -if (traitdata != NULL) { - if (traitdata->neutralloci != NULL) { - nn = traitdata->neutralloci->nAlleles; + int nn = 0; + if (traitdata != NULL) { + if (traitdata->neutralloci != NULL) { + nn = traitdata->neutralloci->nAlleles; + } } -} -return nn; + return nn; } traitAllele Species::getNeutralAllele(const short allele) { -traitAllele a; a.chromo = 0; a.locus = 0; -if (traitdata != NULL) { - if (allele >= 0 && allele < traitdata->neutralloci->nAlleles) { - a = *traitdata->neutralloci->traitalleles[allele]; + traitAllele a; a.chromo = 0; a.locus = 0; + if (traitdata != NULL) { + if (allele >= 0 && allele < traitdata->neutralloci->nAlleles) { + a = *traitdata->neutralloci->traitalleles[allele]; + } } -} -return a; + return a; } //--------------------------------------------------------------------------- @@ -956,97 +888,88 @@ return a; // Emigration functions void Species::setEmig(const emigRules e) { -#if RSDEBUG -//DebugGUI("Species::setEmig(): e.indVar=" + Int2Str((int)e.indVar)); -#endif -densDepEmig = e.densDep; stgDepEmig = e.stgDep; sexDepEmig = e.sexDep; -indVarEmig = e.indVar; -if (e.emigStage >= 0) emigStage = e.emigStage; -//setGenome(); + densDepEmig = e.densDep; stgDepEmig = e.stgDep; sexDepEmig = e.sexDep; + indVarEmig = e.indVar; + if (e.emigStage >= 0) emigStage = e.emigStage; } emigRules Species::getEmig(void) { -emigRules e; -e.densDep = densDepEmig; e.stgDep = stgDepEmig; e.sexDep = sexDepEmig; -e.indVar = indVarEmig; e.emigStage = emigStage; -e.emigTrait[0] = emigTrait[0]; e.emigTrait[1] = emigTrait[1]; -return e; + emigRules e; + e.densDep = densDepEmig; e.stgDep = stgDepEmig; e.sexDep = sexDepEmig; + e.indVar = indVarEmig; e.emigStage = emigStage; + e.emigTrait[0] = emigTrait[0]; e.emigTrait[1] = emigTrait[1]; + return e; } -void Species::setEmigTraits(const short stg,const short sex,const emigTraits e) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; - alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; -} +void Species::setEmigTraits(const short stg, const short sex, const emigTraits e) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (e.d0 >= 0.0 && e.d0 <= 1.0) d0[stg][sex] = e.d0; + alphaEmig[stg][sex] = e.alpha; betaEmig[stg][sex] = e.beta; + } } -emigTraits Species::getEmigTraits(short stg,short sex) { -emigTraits e; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; -} -else { - e.d0 = e.alpha = e.beta = 0.0; -} -return e; +emigTraits Species::getEmigTraits(short stg, short sex) { + emigTraits e; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + e.d0 = d0[stg][sex]; e.alpha = alphaEmig[stg][sex]; e.beta = betaEmig[stg][sex]; + } + else { + e.d0 = e.alpha = e.beta = 0.0; + } + return e; } -float Species::getEmigD0(short stg,short sex) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - return d0[stg][sex]; -} -else { - return 0.0; -} +float Species::getEmigD0(short stg, short sex) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + return d0[stg][sex]; + } + else { + return 0.0; + } } -void Species::setEmigParams(const short stg,const short sex,const emigParams e) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - if (e.d0Mean >= 0.0 && e.d0Mean < 1.0) d0Mean[stg][sex] = e.d0Mean; - if (e.d0SD > 0.0 && e.d0SD < 1.0) d0SD[stg][sex] = e.d0SD; -// if (e.d0MutnSize > 0.0 && e.d0MutnSize < 1.0) d0MutnSize = e.d0MutnSize; - alphaMean[stg][sex] = e.alphaMean; - if (e.alphaSD > 0.0) alphaSD[stg][sex] = e.alphaSD; -// if (e.alphaMutnSize > 0.0) alphaMutnSize = e.alphaMutnSize; - betaMean[stg][sex] = e.betaMean; - if (e.betaSD > 0.0) betaSD[stg][sex] = e.betaSD; -// if (e.betaMutnSize > 0.0) betaMutnSize = e.betaMutnSize; -} -} - -emigParams Species::getEmigParams(short stg,short sex) { -emigParams e; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - e.d0Mean = d0Mean[stg][sex]; e.d0SD = d0SD[stg][sex]; - e.d0Scale = d0Scale; - e.alphaMean = alphaMean[stg][sex]; e.alphaSD = alphaSD[stg][sex]; - e.alphaScale = alphaScale; - e.betaMean = betaMean[stg][sex]; e.betaSD = betaSD[stg][sex]; - e.betaScale = betaScale; -} -else { - e.d0Mean = e.alphaMean = e.betaMean = e.d0SD = e.alphaSD = e.betaSD = 0.0; - e.d0Scale = d0Scale; - e.alphaScale = alphaScale; - e.betaScale = betaScale; +void Species::setEmigParams(const short stg, const short sex, const emigParams e) { + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + if (e.d0Mean >= 0.0 && e.d0Mean < 1.0) d0Mean[stg][sex] = e.d0Mean; + if (e.d0SD > 0.0 && e.d0SD < 1.0) d0SD[stg][sex] = e.d0SD; + alphaMean[stg][sex] = e.alphaMean; + if (e.alphaSD > 0.0) alphaSD[stg][sex] = e.alphaSD; + betaMean[stg][sex] = e.betaMean; + if (e.betaSD > 0.0) betaSD[stg][sex] = e.betaSD; + } } -return e; + +emigParams Species::getEmigParams(short stg, short sex) { + emigParams e; + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + e.d0Mean = d0Mean[stg][sex]; e.d0SD = d0SD[stg][sex]; + e.d0Scale = d0Scale; + e.alphaMean = alphaMean[stg][sex]; e.alphaSD = alphaSD[stg][sex]; + e.alphaScale = alphaScale; + e.betaMean = betaMean[stg][sex]; e.betaSD = betaSD[stg][sex]; + e.betaScale = betaScale; + } + else { + e.d0Mean = e.alphaMean = e.betaMean = e.d0SD = e.alphaSD = e.betaSD = 0.0; + e.d0Scale = d0Scale; + e.alphaScale = alphaScale; + e.betaScale = betaScale; + } + return e; } void Species::setEmigScales(const emigScales s) { -if (s.d0Scale >= 0.0 && s.d0Scale < 1.0 ) d0Scale = s.d0Scale; -if (s.alphaScale >= 0.0) alphaScale = s.alphaScale; -if (s.betaScale >= 0.0) betaScale = s.betaScale; + if (s.d0Scale >= 0.0 && s.d0Scale < 1.0) d0Scale = s.d0Scale; + if (s.alphaScale >= 0.0) alphaScale = s.alphaScale; + if (s.betaScale >= 0.0) betaScale = s.betaScale; } emigScales Species::getEmigScales(void) { -emigScales s; -s.d0Scale = d0Scale; s.alphaScale = alphaScale; s.betaScale = betaScale; -return s; + emigScales s; + s.d0Scale = d0Scale; s.alphaScale = alphaScale; s.betaScale = betaScale; + return s; } //--------------------------------------------------------------------------- @@ -1054,278 +977,268 @@ return s; // Transfer functions void Species::setTrfr(const trfrRules t) { -#if RSDEBUG -//DebugGUI("Species::setTrfr(): t.indVar=" + Int2Str((int)t.indVar)); -#endif -moveModel = t.moveModel; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; -distMort = t.distMort; indVarTrfr = t.indVar; -twinKern = t.twinKern; -habMort = t.habMort; -moveType = t.moveType; costMap = t.costMap; -//setGenome(); + moveModel = t.moveModel; stgDepTrfr = t.stgDep; sexDepTrfr = t.sexDep; + distMort = t.distMort; indVarTrfr = t.indVar; + twinKern = t.twinKern; + habMort = t.habMort; + moveType = t.moveType; costMap = t.costMap; } trfrRules Species::getTrfr(void) { -trfrRules t; -t.moveModel = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; -t.distMort = distMort; t.indVar = indVarTrfr; -t.twinKern = twinKern; -t.habMort = habMort; -t.moveType = moveType; t.costMap = costMap; -t.movtTrait[0] = movtTrait[0]; t.movtTrait[1] = movtTrait[1]; -return t; + trfrRules t; + t.moveModel = moveModel; t.stgDep = stgDepTrfr; t.sexDep = sexDepTrfr; + t.distMort = distMort; t.indVar = indVarTrfr; + t.twinKern = twinKern; + t.habMort = habMort; + t.moveType = moveType; t.costMap = costMap; + t.movtTrait[0] = movtTrait[0]; t.movtTrait[1] = movtTrait[1]; + return t; } void Species::setFullKernel(bool k) { -fullKernel = k; + fullKernel = k; } bool Species::useFullKernel(void) { return fullKernel; } -void Species::setKernTraits(const short stg,const short sex, - const trfrKernTraits k,const int resol) +void Species::setKernTraits(const short stg, const short sex, + const trfrKernTraits k, const int resol) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; - if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; - if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; -} + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (k.meanDist1 > 0.0 && k.meanDist1 >= (float)resol) meanDist1[stg][sex] = k.meanDist1; + if (k.meanDist2 >= (float)resol) meanDist2[stg][sex] = k.meanDist2; + if (k.probKern1 > 0.0 && k.probKern1 < 1.0) probKern1[stg][sex] = k.probKern1; + } } -trfrKernTraits Species::getKernTraits(short stg,short sex) { -trfrKernTraits k; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - k.meanDist1 = meanDist1[stg][sex]; - k.meanDist2 = meanDist2[stg][sex]; - k.probKern1 = probKern1[stg][sex]; -} -else { - k.meanDist1 = 0.0; k.meanDist2 = 0.0; k.probKern1 = 1.0; -} -return k; +trfrKernTraits Species::getKernTraits(short stg, short sex) { + trfrKernTraits k; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + k.meanDist1 = meanDist1[stg][sex]; + k.meanDist2 = meanDist2[stg][sex]; + k.probKern1 = probKern1[stg][sex]; + } + else { + k.meanDist1 = 0.0; k.meanDist2 = 0.0; k.probKern1 = 1.0; + } + return k; } void Species::setMortParams(const trfrMortParams m) { -if (m.fixedMort >= 0.0 && m.fixedMort < 1.0) fixedMort = m.fixedMort; -mortAlpha = m.mortAlpha; -mortBeta = m.mortBeta; + if (m.fixedMort >= 0.0 && m.fixedMort < 1.0) fixedMort = m.fixedMort; + mortAlpha = m.mortAlpha; + mortBeta = m.mortBeta; } trfrMortParams Species::getMortParams(void) { -trfrMortParams m; -m.fixedMort = fixedMort; m.mortAlpha = mortAlpha; m.mortBeta = mortBeta; -return m; + trfrMortParams m; + m.fixedMort = fixedMort; m.mortAlpha = mortAlpha; m.mortBeta = mortBeta; + return m; } void Species::setMovtTraits(const trfrMovtTraits m) { -if (m.pr >= 1) pr = m.pr; -if (m.prMethod >= 1 && m.prMethod <= 3) prMethod = m.prMethod; -if (m.memSize >= 1 && m.memSize <= 14) memSize = m.memSize; -if (m.goalType >= 0 && m.goalType <= 2) goalType = m.goalType; -if (m.dp >= 1.0) dp = m.dp; -if (m.gb >= 1.0) gb = m.gb; -if (m.alphaDB > 0.0) alphaDB = m.alphaDB; -if (m.betaDB > 0) betaDB = m.betaDB; -if (m.stepMort >= 0.0 && m.stepMort < 1.0) stepMort = m.stepMort; -if (m.stepLength > 0.0) stepLength = m.stepLength; -if (m.rho > 0.0 && m.rho < 1.0) rho = m.rho; -straigtenPath = m.straigtenPath; + if (m.pr >= 1) pr = m.pr; + if (m.prMethod >= 1 && m.prMethod <= 3) prMethod = m.prMethod; + if (m.memSize >= 1 && m.memSize <= 14) memSize = m.memSize; + if (m.goalType >= 0 && m.goalType <= 2) goalType = m.goalType; + if (m.dp >= 1.0) dp = m.dp; + if (m.gb >= 1.0) gb = m.gb; + if (m.alphaDB > 0.0) alphaDB = m.alphaDB; + if (m.betaDB > 0) betaDB = m.betaDB; + if (m.stepMort >= 0.0 && m.stepMort < 1.0) stepMort = m.stepMort; + if (m.stepLength > 0.0) stepLength = m.stepLength; + if (m.rho > 0.0 && m.rho < 1.0) rho = m.rho; + straigtenPath = m.straigtenPath; } trfrMovtTraits Species::getMovtTraits(void) { -trfrMovtTraits m; -m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; -m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; -m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; -return m; + trfrMovtTraits m; + m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; + m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; + m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; + return m; } trfrCRWTraits Species::getCRWTraits(void) { -trfrCRWTraits m; -m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; -m.straigtenPath = straigtenPath; -return m; + trfrCRWTraits m; + m.stepMort = stepMort; m.stepLength = stepLength; m.rho = rho; + m.straigtenPath = straigtenPath; + return m; } trfrSMSTraits Species::getSMSTraits(void) { -trfrSMSTraits m; -m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; -m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; m.stepMort = stepMort; -m.straigtenPath = straigtenPath; -return m; + trfrSMSTraits m; + m.pr = pr; m.prMethod = prMethod; m.memSize = memSize; m.goalType = goalType; + m.dp = dp; m.gb = gb; m.alphaDB = alphaDB; m.betaDB = betaDB; m.stepMort = stepMort; + m.straigtenPath = straigtenPath; + return m; } -void Species::setKernParams(const short stg,const short sex, - const trfrKernParams k,const double resol) -{ -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only +void Species::setKernParams(const short stg, const short sex, + const trfrKernParams k, const double resol) { - if (k.dist1Mean > 0.0 && k.dist1Mean >= resol && k.dist1SD > 0.0) { - dist1Mean[stg][sex] = k.dist1Mean; dist1SD[stg][sex] = k.dist1SD; + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + if (k.dist1Mean > 0.0 && k.dist1Mean >= resol && k.dist1SD > 0.0) { + dist1Mean[stg][sex] = k.dist1Mean; dist1SD[stg][sex] = k.dist1SD; + } + if (k.dist2Mean > 0.0 && k.dist2Mean >= resol && k.dist2SD > 0.0) { + dist2Mean[stg][sex] = k.dist2Mean; dist2SD[stg][sex] = k.dist2SD; + } + if (k.PKern1Mean > 0.0 && k.PKern1Mean < 1.0 && k.PKern1SD > 0.0 && k.PKern1SD < 1.0) { + PKern1Mean[stg][sex] = k.PKern1Mean; PKern1SD[stg][sex] = k.PKern1SD; + } } - if (k.dist2Mean > 0.0 && k.dist2Mean >= resol && k.dist2SD > 0.0) { - dist2Mean[stg][sex] = k.dist2Mean; dist2SD[stg][sex] = k.dist2SD; +} + +trfrKernParams Species::getKernParams(short stg, short sex) { + trfrKernParams k; + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + k.dist1Mean = dist1Mean[stg][sex]; k.dist1SD = dist1SD[stg][sex]; + k.dist2Mean = dist2Mean[stg][sex]; k.dist2SD = dist2SD[stg][sex]; + k.PKern1Mean = PKern1Mean[stg][sex]; k.PKern1SD = PKern1SD[stg][sex]; + k.dist1Scale = dist1Scale; k.dist2Scale = dist2Scale; k.PKern1Scale = PKern1Scale; } - if (k.PKern1Mean > 0.0 && k.PKern1Mean < 1.0 && k.PKern1SD > 0.0 && k.PKern1SD < 1.0 ) { - PKern1Mean[stg][sex] = k.PKern1Mean; PKern1SD[stg][sex] = k.PKern1SD; + else { + k.dist1Mean = 100000.0; k.dist1SD = 0.001f; k.dist1Scale = 1.0; + k.dist2Mean = 100000.0; k.dist2SD = 0.001f; k.dist2Scale = 1.0; + k.PKern1Mean = 0.5; k.PKern1SD = 0.1f; k.PKern1Scale = 0.1f; } -} + return k; } -trfrKernParams Species::getKernParams(short stg,short sex) { -trfrKernParams k; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - k.dist1Mean = dist1Mean[stg][sex]; k.dist1SD = dist1SD[stg][sex]; - k.dist2Mean = dist2Mean[stg][sex]; k.dist2SD = dist2SD[stg][sex]; - k.PKern1Mean = PKern1Mean[stg][sex]; k.PKern1SD = PKern1SD[stg][sex]; - k.dist1Scale = dist1Scale; k.dist2Scale = dist2Scale; k.PKern1Scale = PKern1Scale; -} -else { - k.dist1Mean = 100000.0; k.dist1SD = 0.001f; k.dist1Scale = 1.0; - k.dist2Mean = 100000.0; k.dist2SD = 0.001f; k.dist2Scale = 1.0; - k.PKern1Mean = 0.5; k.PKern1SD = 0.1f; k.PKern1Scale = 0.1f; -} -return k; +void Species::setSMSParams(const short stg, const short sex, const trfrSMSParams s) { + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + if (s.dpMean >= 1.0 && s.dpSD > 0.0) { + dpMean[stg][sex] = s.dpMean; dpSD[stg][sex] = s.dpSD; + } + if (s.gbMean >= 1.0 && s.gbSD > 0.0) { + gbMean[stg][sex] = s.gbMean; gbSD[stg][sex] = s.gbSD; + } + if (s.alphaDBMean > 0.0 && s.alphaDBSD > 0.0) { + alphaDBMean[stg][sex] = s.alphaDBMean; alphaDBSD[stg][sex] = s.alphaDBSD; + } + if (s.betaDBMean >= 1.0 && s.betaDBSD > 0.0) { + betaDBMean[stg][sex] = s.betaDBMean; betaDBSD[stg][sex] = s.betaDBSD; + } + } } -void Species::setSMSParams(const short stg,const short sex,const trfrSMSParams s) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - if (s.dpMean >= 1.0 && s.dpSD > 0.0) { - dpMean[stg][sex] = s.dpMean; dpSD[stg][sex] = s.dpSD; - } - if (s.gbMean >= 1.0 && s.gbSD > 0.0) { - gbMean[stg][sex] = s.gbMean; gbSD[stg][sex] = s.gbSD; +trfrSMSParams Species::getSMSParams(short stg, short sex) { + trfrSMSParams s; + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + s.dpMean = dpMean[stg][sex]; s.dpSD = dpSD[stg][sex]; + s.gbMean = gbMean[stg][sex]; s.gbSD = gbSD[stg][sex]; + s.alphaDBMean = alphaDBMean[stg][sex]; s.alphaDBSD = alphaDBSD[stg][sex]; + s.betaDBMean = betaDBMean[stg][sex]; s.betaDBSD = betaDBSD[stg][sex]; + s.dpScale = dpScale; s.gbScale = gbScale; + s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; } - if (s.alphaDBMean > 0.0 && s.alphaDBSD > 0.0) { - alphaDBMean[stg][sex] = s.alphaDBMean; alphaDBSD[stg][sex] = s.alphaDBSD; - } - if (s.betaDBMean >= 1.0 && s.betaDBSD > 0.0) { - betaDBMean[stg][sex] = s.betaDBMean; betaDBSD[stg][sex] = s.betaDBSD; + else { + s.dpMean = 1.0; s.dpSD = 0.1f; s.dpScale = 0.1f; + s.gbMean = 1.0; s.gbSD = 0.1f; s.gbScale = 0.1f; + s.alphaDBMean = 1.0; s.alphaDBSD = 0.1f; s.alphaDBScale = 0.1f; + s.betaDBMean = 10.0; s.betaDBSD = 1.0; s.betaDBScale = 1.0; } -} + return s; } -trfrSMSParams Species::getSMSParams(short stg,short sex) { -trfrSMSParams s; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - s.dpMean = dpMean[stg][sex]; s.dpSD = dpSD[stg][sex]; - s.gbMean = gbMean[stg][sex]; s.gbSD = gbSD[stg][sex]; - s.alphaDBMean = alphaDBMean[stg][sex]; s.alphaDBSD = alphaDBSD[stg][sex]; - s.betaDBMean = betaDBMean[stg][sex]; s.betaDBSD = betaDBSD[stg][sex]; - s.dpScale = dpScale; s.gbScale = gbScale; - s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; -} -else { - s.dpMean = 1.0; s.dpSD = 0.1f; s.dpScale = 0.1f; - s.gbMean = 1.0; s.gbSD = 0.1f; s.gbScale = 0.1f; - s.alphaDBMean = 1.0; s.alphaDBSD = 0.1f; s.alphaDBScale = 0.1f; - s.betaDBMean = 10.0; s.betaDBSD = 1.0; s.betaDBScale = 1.0; -} -return s; +void Species::setCRWParams(const short stg, const short sex, const trfrCRWParams m) { + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + if (m.stepLgthMean > 0.0 && m.stepLgthSD > 0.0) { + stepLgthMean[stg][sex] = m.stepLgthMean; stepLgthSD[stg][sex] = m.stepLgthSD; + } + if (m.rhoMean > 0.0 && m.rhoMean < 1.0 && m.rhoSD > 0.0 && m.rhoSD < 1.0) { + rhoMean[stg][sex] = m.rhoMean; rhoSD[stg][sex] = m.rhoSD; + } + } } -void Species::setCRWParams(const short stg,const short sex,const trfrCRWParams m) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - if (m.stepLgthMean > 0.0 && m.stepLgthSD > 0.0) { - stepLgthMean[stg][sex] = m.stepLgthMean; stepLgthSD[stg][sex] = m.stepLgthSD; +trfrCRWParams Species::getCRWParams(short stg, short sex) { + trfrCRWParams m; + if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only + { + m.stepLgthMean = stepLgthMean[stg][sex]; m.stepLgthSD = stepLgthSD[stg][sex]; + m.rhoMean = rhoMean[stg][sex]; m.rhoSD = rhoSD[stg][sex]; + m.stepLScale = stepLScale; m.rhoScale = rhoScale; } - if (m.rhoMean > 0.0 && m.rhoMean < 1.0 && m.rhoSD > 0.0 && m.rhoSD < 1.0 ) { - rhoMean[stg][sex] = m.rhoMean; rhoSD[stg][sex] = m.rhoSD; + else { + m.stepLgthMean = 1.0; m.stepLgthSD = 0.1f; m.stepLScale = 0.1f; + m.rhoMean = 0.5; m.rhoSD = 0.1f; m.rhoScale = 0.1f; } -} -} - -trfrCRWParams Species::getCRWParams(short stg,short sex) { -trfrCRWParams m; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < 1) // implemented for stage 0 & sex 0 only -{ - m.stepLgthMean = stepLgthMean[stg][sex]; m.stepLgthSD = stepLgthSD[stg][sex]; - m.rhoMean = rhoMean[stg][sex]; m.rhoSD = rhoSD[stg][sex]; - m.stepLScale = stepLScale; m.rhoScale = rhoScale; -} -else { - m.stepLgthMean = 1.0; m.stepLgthSD = 0.1f; m.stepLScale = 0.1f; - m.rhoMean = 0.5; m.rhoSD = 0.1f; m.rhoScale = 0.1f; -} -return m; + return m; } void Species::setTrfrScales(const trfrScales s) { -if (s.dist1Scale >= 0.0) dist1Scale = s.dist1Scale; -if (s.dist2Scale >= 0.0) dist2Scale = s.dist2Scale; -if (s.PKern1Scale > 0.0 && s.PKern1Scale < 1.0) PKern1Scale = s.PKern1Scale; -if (s.dpScale > 0.0) dpScale = s.dpScale; -if (s.gbScale > 0.0) gbScale = s.gbScale; -if (s.alphaDBScale > 0.0) alphaDBScale = s.alphaDBScale; -if (s.betaDBScale > 0.0) betaDBScale = s.betaDBScale; -if (s.stepLScale > 0.0) stepLScale = s.stepLScale; -if (s.rhoScale > 0.0 && s.rhoScale < 1.0) rhoScale = s.rhoScale; + if (s.dist1Scale >= 0.0) dist1Scale = s.dist1Scale; + if (s.dist2Scale >= 0.0) dist2Scale = s.dist2Scale; + if (s.PKern1Scale > 0.0 && s.PKern1Scale < 1.0) PKern1Scale = s.PKern1Scale; + if (s.dpScale > 0.0) dpScale = s.dpScale; + if (s.gbScale > 0.0) gbScale = s.gbScale; + if (s.alphaDBScale > 0.0) alphaDBScale = s.alphaDBScale; + if (s.betaDBScale > 0.0) betaDBScale = s.betaDBScale; + if (s.stepLScale > 0.0) stepLScale = s.stepLScale; + if (s.rhoScale > 0.0 && s.rhoScale < 1.0) rhoScale = s.rhoScale; } trfrScales Species::getTrfrScales(void) { -trfrScales s; -s.dist1Scale = dist1Scale; s.dist2Scale = dist2Scale; s.PKern1Scale = PKern1Scale; -s.dpScale = dpScale; s.gbScale = gbScale; -s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; -s.stepLScale = stepLScale; s.rhoScale = rhoScale; -return s; + trfrScales s; + s.dist1Scale = dist1Scale; s.dist2Scale = dist2Scale; s.PKern1Scale = PKern1Scale; + s.dpScale = dpScale; s.gbScale = gbScale; + s.alphaDBScale = alphaDBScale; s.betaDBScale = betaDBScale; + s.stepLScale = stepLScale; s.rhoScale = rhoScale; + return s; } short Species::getMovtHabDim() { return habDimTrfr; } void Species::createHabCostMort(short nhab) { -if (nhab >= 0) { - habDimTrfr = nhab; - if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); - habCost = new int[nhab]; - habStepMort = new double[nhab]; - for (int i = 0; i < nhab; i++) { - habCost[i] = 1; habStepMort[i] = 0.0; + if (nhab >= 0) { + habDimTrfr = nhab; + if (habCost != 0 || habStepMort != 0) deleteHabCostMort(); + habCost = new int[nhab]; + habStepMort = new double[nhab]; + for (int i = 0; i < nhab; i++) { + habCost[i] = 1; habStepMort[i] = 0.0; + } } } -} -void Species::setHabCost(short hab,int cost) { -if (hab >= 0 && hab < habDimTrfr) { - if (cost >= 1) habCost[hab] = cost; -} +void Species::setHabCost(short hab, int cost) { + if (hab >= 0 && hab < habDimTrfr) { + if (cost >= 1) habCost[hab] = cost; + } } -void Species::setHabMort(short hab,double mort) { -if (hab >= 0 && hab < habDimTrfr) { - if (mort >= 0.0 && mort < 1.0) habStepMort[hab] = mort; -} +void Species::setHabMort(short hab, double mort) { + if (hab >= 0 && hab < habDimTrfr) { + if (mort >= 0.0 && mort < 1.0) habStepMort[hab] = mort; + } } int Species::getHabCost(short hab) { -int cost = 0; -if (hab >= 0 && hab < habDimTrfr) cost = habCost[hab]; -return cost; + int cost = 0; + if (hab >= 0 && hab < habDimTrfr) cost = habCost[hab]; + return cost; } double Species::getHabMort(short hab) { -double pmort = 0.0; -if (hab >= 0 && hab < habDimTrfr) pmort = habStepMort[hab]; -return pmort; + double pmort = 0.0; + if (hab >= 0 && hab < habDimTrfr) pmort = habStepMort[hab]; + return pmort; } void Species::deleteHabCostMort(void) { -if (habCost != 0) { - delete[] habCost; habCost = 0; -} -if (habStepMort != 0) { - delete[] habStepMort; habStepMort = 0; -} + if (habCost != 0) { + delete[] habCost; habCost = 0; + } + if (habStepMort != 0) { + delete[] habStepMort; habStepMort = 0; + } } //--------------------------------------------------------------------------- @@ -1333,120 +1246,118 @@ if (habStepMort != 0) { // Settlement functions void Species::setSettle(const settleType s) { -stgDepSett = s.stgDep; sexDepSett = s.sexDep; indVarSett = s.indVar; + stgDepSett = s.stgDep; sexDepSett = s.sexDep; indVarSett = s.indVar; } settleType Species::getSettle(void) { -settleType s; -s.stgDep = stgDepSett; s.sexDep = sexDepSett; s.indVar = indVarSett; -s.settTrait[0] = settTrait[0]; s.settTrait[1] = settTrait[1]; -return s; + settleType s; + s.stgDep = stgDepSett; s.sexDep = sexDepSett; s.indVar = indVarSett; + s.settTrait[0] = settTrait[0]; s.settTrait[1] = settTrait[1]; + return s; } -void Species::setSettRules(const short stg,const short sex,const settleRules s) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - densDepSett[stg][sex] = s.densDep; wait[stg][sex] = s.wait; - go2nbrLocn[stg][sex] = s.go2nbrLocn; findMate[stg][sex] = s.findMate; -} +void Species::setSettRules(const short stg, const short sex, const settleRules s) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + densDepSett[stg][sex] = s.densDep; wait[stg][sex] = s.wait; + go2nbrLocn[stg][sex] = s.go2nbrLocn; findMate[stg][sex] = s.findMate; + } } -settleRules Species::getSettRules(short stg,short sex) { -settleRules s; -s.densDep = false; -s.findMate = false; -s.go2nbrLocn = false; -s.wait = false; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - s.densDep = densDepSett[stg][sex]; s.wait = wait[stg][sex]; - s.go2nbrLocn = go2nbrLocn[stg][sex]; s.findMate = findMate[stg][sex]; -} -return s; +settleRules Species::getSettRules(short stg, short sex) { + settleRules s; + s.densDep = false; + s.findMate = false; + s.go2nbrLocn = false; + s.wait = false; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + s.densDep = densDepSett[stg][sex]; s.wait = wait[stg][sex]; + s.go2nbrLocn = go2nbrLocn[stg][sex]; s.findMate = findMate[stg][sex]; + } + return s; } -void Species::setSteps(const short stg,const short sex,const settleSteps s) { -if (stg == 0 && sex == 0) { - if (s.minSteps >= 0) minSteps = s.minSteps; - else minSteps = 0; - if (s.maxSteps >= 1) maxSteps = s.maxSteps; - else maxSteps = 99999999; -} -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (s.maxStepsYr >= 1) maxStepsYr[stg][sex] = s.maxStepsYr; - else maxStepsYr[stg][sex] = 99999999; -} +void Species::setSteps(const short stg, const short sex, const settleSteps s) { + if (stg == 0 && sex == 0) { + if (s.minSteps >= 0) minSteps = s.minSteps; + else minSteps = 0; + if (s.maxSteps >= 1) maxSteps = s.maxSteps; + else maxSteps = 99999999; + } + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (s.maxStepsYr >= 1) maxStepsYr[stg][sex] = s.maxStepsYr; + else maxStepsYr[stg][sex] = 99999999; + } } -settleSteps Species::getSteps(short stg,short sex) { -settleSteps s; -s.minSteps = minSteps; -s.maxSteps = maxSteps; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) s.maxStepsYr = maxStepsYr[stg][sex]; -else s.maxStepsYr = 99999999; -return s; +settleSteps Species::getSteps(short stg, short sex) { + settleSteps s; + s.minSteps = minSteps; + s.maxSteps = maxSteps; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) s.maxStepsYr = maxStepsYr[stg][sex]; + else s.maxStepsYr = 99999999; + return s; } -void Species::setSettTraits(const short stg,const short sex,const settleTraits dd) { -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - if (dd.s0 > 0.0 && dd.s0 <= 1.0 ) s0[stg][sex] = dd.s0; - alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; -} +void Species::setSettTraits(const short stg, const short sex, const settleTraits dd) { + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + if (dd.s0 > 0.0 && dd.s0 <= 1.0) s0[stg][sex] = dd.s0; + alphaS[stg][sex] = dd.alpha; betaS[stg][sex] = dd.beta; + } } -settleTraits Species::getSettTraits(short stg,short sex) { -settleTraits dd; -if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { - dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; -} -else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } -return dd; +settleTraits Species::getSettTraits(short stg, short sex) { + settleTraits dd; + if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) { + dd.s0 = s0[stg][sex]; dd.alpha = alphaS[stg][sex]; dd.beta = betaS[stg][sex]; + } + else { dd.s0 = 1.0; dd.alpha = dd.beta = 0.0; } + return dd; +} + +void Species::setSettParams(const short stg, const short sex, const settParams s) { + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + if (s.s0Mean >= 0.0 && s.s0Mean < 1.0) s0Mean[stg][sex] = s.s0Mean; + if (s.s0SD > 0.0 && s.s0SD < 1.0) s0SD[stg][sex] = s.s0SD; + alphaSMean[stg][sex] = s.alphaSMean; + if (s.alphaSSD > 0.0) alphaSSD[stg][sex] = s.alphaSSD; + betaSMean[stg][sex] = s.betaSMean; + if (s.betaSSD > 0.0) betaSSD[stg][sex] = s.betaSSD; + if (sex == 0) { + if (s.s0Scale > 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; + if (s.alphaSScale > 0.0) alphaSScale = s.alphaSScale; + if (s.betaSScale > 0.0) betaSScale = s.betaSScale; + } + } } -void Species::setSettParams(const short stg,const short sex,const settParams s) { -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - if (s.s0Mean >= 0.0 && s.s0Mean < 1.0) s0Mean[stg][sex] = s.s0Mean; - if (s.s0SD > 0.0 && s.s0SD < 1.0) s0SD[stg][sex] = s.s0SD; - alphaSMean[stg][sex] = s.alphaSMean; - if (s.alphaSSD > 0.0) alphaSSD[stg][sex] = s.alphaSSD; - betaSMean[stg][sex] = s.betaSMean; - if (s.betaSSD > 0.0) betaSSD[stg][sex] = s.betaSSD; - if (sex == 0) { - if (s.s0Scale > 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; - if (s.alphaSScale > 0.0) alphaSScale = s.alphaSScale; - if (s.betaSScale > 0.0) betaSScale = s.betaSScale; - } -} -} - -settParams Species::getSettParams(short stg,short sex) { -settParams s; -//if (stg >= 0 && stg < NSTAGES && sex >= 0 && sex < NSEXES) -if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only -{ - s.s0Mean = s0Mean[stg][sex]; s.s0SD = s0SD[stg][sex]; - s.alphaSMean = alphaSMean[stg][sex]; s.alphaSSD = alphaSSD[stg][sex]; - s.betaSMean = betaSMean[stg][sex]; s.betaSSD = betaSSD[stg][sex]; -} -else { - s.s0Mean = s.alphaSMean = s.betaSMean = s.s0SD = s.alphaSSD = s.betaSSD = 0.0; -} -s.s0Scale = s0Scale; -s.alphaSScale = alphaSScale; -s.betaSScale = betaSScale; -return s; +settParams Species::getSettParams(short stg, short sex) { + settParams s; + if (stg >= 0 && stg < 1 && sex >= 0 && sex < NSEXES) // implemented for stage 0 only + { + s.s0Mean = s0Mean[stg][sex]; s.s0SD = s0SD[stg][sex]; + s.alphaSMean = alphaSMean[stg][sex]; s.alphaSSD = alphaSSD[stg][sex]; + s.betaSMean = betaSMean[stg][sex]; s.betaSSD = betaSSD[stg][sex]; + } + else { + s.s0Mean = s.alphaSMean = s.betaSMean = s.s0SD = s.alphaSSD = s.betaSSD = 0.0; + } + s.s0Scale = s0Scale; + s.alphaSScale = alphaSScale; + s.betaSScale = betaSScale; + return s; } void Species::setSettScales(const settScales s) { -if (s.s0Scale >= 0.0 && s.s0Scale < 1.0 ) s0Scale = s.s0Scale; -if (s.alphaSScale >= 0.0) alphaSScale = s.alphaSScale; -if (s.betaSScale >= 0.0) betaSScale = s.betaSScale; + if (s.s0Scale >= 0.0 && s.s0Scale < 1.0) s0Scale = s.s0Scale; + if (s.alphaSScale >= 0.0) alphaSScale = s.alphaSScale; + if (s.betaSScale >= 0.0) betaSScale = s.betaSScale; } settScales Species::getSettScales(void) { -settScales s; -s.s0Scale = s0Scale; s.alphaSScale = alphaSScale; s.betaSScale = betaSScale; -return s; + settScales s; + s.s0Scale = s0Scale; s.alphaSScale = alphaSScale; s.betaSScale = betaSScale; + return s; } //--------------------------------------------------------------------------- diff --git a/Species.h b/Species.h index 55dbacf..cdfd38c 100644 --- a/Species.h +++ b/Species.h @@ -1,46 +1,46 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -/*------------------------------------------------------------------------------ -RangeShifter v2.0 Species -Implements the Species class + /*------------------------------------------------------------------------------ -There is ONE instance of a Species for each species within the Community -AND THIS IS CURRENTLY LIMITED TO A SINGLE SPECIES. -The class holds all the demographic and dispersal parameters of the species. + RangeShifter v2.0 Species -For full details of RangeShifter, please see: -Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. -and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial -eco-evolutionary dynamics and species’ responses to environmental changes. -Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 + Implements the Species class -Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + There is ONE instance of a Species for each species within the Community + AND THIS IS CURRENTLY LIMITED TO A SINGLE SPECIES. + The class holds all the demographic and dispersal parameters of the species. -Last updated: 28 July 2021 by Greta Bocedi + For full details of RangeShifter, please see: + Bocedi G., Palmer S.C.F., Pe’er G., Heikkinen R.K., Matsinos Y.G., Watts K. + and Travis J.M.J. (2014). RangeShifter: a platform for modelling spatial + eco-evolutionary dynamics and species’ responses to environmental changes. + Methods in Ecology and Evolution, 5, 388-396. doi: 10.1111/2041-210X.12162 -------------------------------------------------------------------------------*/ + Authors: Greta Bocedi & Steve Palmer, University of Aberdeen + + Last updated: 28 July 2021 by Greta Bocedi + + ------------------------------------------------------------------------------*/ #ifndef SpeciesH #define SpeciesH @@ -49,15 +49,12 @@ Last updated: 28 July 2021 by Greta Bocedi #include "../Version.h" #endif -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif #include "Parameters.h" // structures for demographic parameters struct demogrParams { - short repType; + short repType; short repSeasons; float propMales; float harem; float bc; float lambda; bool stageStruct; @@ -77,23 +74,23 @@ struct densDepParams { struct genomeData { int nLoci; bool diploid; bool neutralMarkers; bool pleiotropic; bool trait1Chromosome; - double probMutn,probCrossover,alleleSD,mutationSD; -} ; + double probMutn, probCrossover, alleleSD, mutationSD; +}; struct traitAllele { short chromo; short locus; -} ; +}; struct traitMap { short nAlleles; - traitAllele **traitalleles; -} ; + traitAllele** traitalleles; +}; struct traitData { short nTraitMaps; - traitMap **traitmaps; - traitMap *neutralloci; -} ; + traitMap** traitmaps; + traitMap* neutralloci; +}; // structures for emigration parameters @@ -117,10 +114,10 @@ struct emigScales { // structures for transfer parameters struct trfrRules { - bool moveModel; bool stgDep; bool sexDep; + bool moveModel; bool stgDep; bool sexDep; bool distMort; bool indVar; - bool twinKern; - bool habMort; + bool twinKern; + bool habMort; short moveType; bool costMap; short movtTrait[2]; }; @@ -171,7 +168,7 @@ struct settleType { short settTrait[2]; }; struct settleRules { - bool densDep; bool wait; bool go2nbrLocn; bool findMate; + bool densDep; bool wait; bool go2nbrLocn; bool findMate; }; struct settleSteps { int minSteps; int maxSteps; int maxStepsYr; @@ -227,7 +224,7 @@ class Species { float // survival coefficient ); densDepParams getDensDep(void); // Get development and survival coefficients - + void setFec( // Set fecundity short, // stage (must be > 0) short, // sex @@ -255,7 +252,7 @@ class Species { short, // stage short // sex ); - + float getMaxFec(void); // Get highest fecundity of any stage void setMinAge( // Set minimum age short, // stage @@ -561,14 +558,14 @@ class Species { bool survDens; bool survStageDens; bool disperseOnLoss; // individuals disperse on complete loss of patch - // (otherwise they die) + // (otherwise they die) short habDimK; // dimension of carrying capacities matrix - float *habK; // habitat-specific carrying capacities (inds/cell) + float* habK; // habitat-specific carrying capacities (inds/cell) float devCoeff; // density-dependent development coefficient float survCoeff; // density-dependent survival coefficient - float **ddwtFec; // density-dependent weights matrix for fecundity - float **ddwtDev; // density-dependent weights matrix for development - float **ddwtSurv; // density-dependent weights matrix for survival + float** ddwtFec; // density-dependent weights matrix for fecundity + float** ddwtDev; // density-dependent weights matrix for development + float** ddwtSurv; // density-dependent weights matrix for survival // NB for the following arrays, sex 0 is females, sex 1 is males float fec[NSTAGES][NSEXES]; // fecundities float dev[NSTAGES][NSEXES]; // development probabilities @@ -599,10 +596,10 @@ class Species { double alleleSD; // s.d. of initial allelic values around phenotypic value double mutationSD; // s.d. of mutation magnitude short nNLoci; // no. of nLoci set - short *nLoci; // no. of loci per chromosome + short* nLoci; // no. of loci per chromosome short nTraitNames; // no. of trait names set - traitData *traitdata; // for mapping of chromosome loci to traits - string *traitnames; // trait names for parameter output + traitData* traitdata; // for mapping of chromosome loci to traits + string* traitnames; // trait names for parameter output // emigration parameters @@ -611,8 +608,8 @@ class Species { bool sexDepEmig; // sex-dependent emigration bool indVarEmig; // individual variation in emigration short emigStage; // stage which emigrates (used for stage-strucutred population - // having individual variability in emigration probability) - // NB for the following arrays, sex 0 is females, sex 1 is males + // having individual variability in emigration probability) +// NB for the following arrays, sex 0 is females, sex 1 is males float d0[NSTAGES][NSEXES]; // maximum emigration probability float alphaEmig[NSTAGES][NSEXES]; // slope of density-dependent reaction norm float betaEmig[NSTAGES][NSEXES]; // inflection point of reaction norm (in terms of N/K) @@ -662,7 +659,7 @@ class Species { short moveType; // 1 = SMS, 2 = CRW short pr; // SMS perceptual range (cells) short prMethod; // SMS perceptual range evaluation method: - // 1 = arith. mean, 2 = harmonic mean, 3 = inverse weighted arith. mean + // 1 = arith. mean, 2 = harmonic mean, 3 = inverse weighted arith. mean short memSize; // SMS memory size (1-14 steps) short goalType; // SMS goal bias type: 0 = none, 1 = towards goal, 2 = dispersal bias float dp; // SMS directional persistence @@ -670,7 +667,7 @@ class Species { float alphaDB; // SMS dispersal bias decay rate int betaDB; // SMS dispersal bias decay inflection point (no. of steps) float stepMort; // constant per-step mortality probability for movement models - double *habStepMort; // habitat-dependent per-step mortality probability + double* habStepMort; // habitat-dependent per-step mortality probability float stepLength; // CRW step length (m) float rho; // CRW correlation coefficient double dpMean[1][NSEXES]; // mean of initial SMS directional persistence @@ -692,14 +689,14 @@ class Species { float stepLScale; // scaling factor for step length (m) float rhoScale; // scaling factor for correlation coefficient short habDimTrfr; // dimension of habitat-dependent step mortality and costs matrices - int *habCost; // habitat costs + int* habCost; // habitat costs bool costMap; // import cost map from file? bool straigtenPath; // straighten path after decision not to settle bool fullKernel; // used to indicate special case when density-independent emigration - // is 1.0, and kernel-based movement within the natal cell is used - // to determine philopatry + // is 1.0, and kernel-based movement within the natal cell is used + // to determine philopatry - // settlement parameters +// settlement parameters bool stgDepSett; bool sexDepSett; From b141874272f08590b797dc55b4aba99c23705dfa Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 28 Nov 2023 16:15:16 +0000 Subject: [PATCH 22/46] fix indentation Model --- Individual.cpp | 26 +- Model.cpp | 3438 +++++++++++++++++++++++------------------------- Parameters.cpp | 446 +++---- RandomCheck.h | 3 - 4 files changed, 1862 insertions(+), 2051 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index cc7bf6e..8af79d2 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -62,8 +62,10 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep smsData = new smsdata; smsData->dp = smsData->gb = smsData->alphaDB = 1.0; smsData->betaDB = 1; - smsData->prev.x = loc.x; smsData->prev.y = loc.y; // previous location - smsData->goal.x = loc.x; smsData->goal.y = loc.y; // goal location - initialised for dispersal bias + smsData->prev.x = loc.x; + smsData->prev.y = loc.y; // previous location + smsData->goal.x = loc.x; + smsData->goal.y = loc.y; // goal location - initialised for dispersal bias } else smsData = 0; if (moveType == 2) { // CRW @@ -168,7 +170,6 @@ void Individual::setGenes(Species* pSpecies, int resol) { } } - //int trfrposn = 0; if (trfr.indVar) { // set transfer genes int trfrposn = gposn; if (trfr.sexDep) { // must be a sexual species @@ -854,7 +855,8 @@ void Individual::moveto(Cell* newCell) { double d = sqrt(((double)currloc.x - (double)newloc.x) * ((double)currloc.x - (double)newloc.x) + ((double)currloc.y - (double)newloc.y) * ((double)currloc.y - (double)newloc.y)); if (d >= 1.0 && d < 1.5) { // ok - pCurrCell = newCell; status = 5; + pCurrCell = newCell; + status = 5; } } @@ -1829,14 +1831,14 @@ void testIndividual() { short moveType = 1; Individual ind(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); - // An individual... - { - std::vector inds; - for (int i = 0; i < 2; i++) - { - inds.push_back(new Individual(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType)); - } - } + // An individual can move to a neighbouring cell + ind.moveto(); + + // Gets its sex drawn from pmale + + // Can age or develop + + // // Reproduces // depending on whether it is sexual or not diff --git a/Model.cpp b/Model.cpp index 64b5d87..fc4fac9 100644 --- a/Model.cpp +++ b/Model.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Model.h" @@ -29,89 +29,68 @@ ofstream outPar; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #if RS_RCPP && !R_CMD -Rcpp::List RunModel(Landscape *pLandscape,int seqsim) +Rcpp::List RunModel(Landscape* pLandscape, int seqsim) #else -int RunModel(Landscape *pLandscape,int seqsim) +int RunModel(Landscape* pLandscape, int seqsim) #endif { -//int Nsuit,yr,totalInds; -int yr,totalInds; -//float gradval,gradmin,gradmax; -bool filesOK; -//int t0,t1; - -landParams ppLand = pLandscape->getLandParams(); -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -//emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -initParams init = paramsInit->getInit(); -simParams sim = paramsSim->getSim(); -simView v = paramsSim->getViews(); - -//t0 = time(0); - -#if RSDEBUG -landPix p = pLandscape->getLandPix(); -DEBUGLOG << "RunModel(): reps=" << sim.reps - << " ppLand.nHab=" << ppLand.nHab - << " p.pix=" << p.pix - << endl; -//DEBUGLOG << "RunModel(): random integers:"; -//for (int i = 0; i < 5; i++) { -// int rrrr = pRandom->IRandom(1000,2000); DEBUGLOG << " " << rrrr; -//} -DEBUGLOG << endl; -#endif + int yr, totalInds; + bool filesOK; + + landParams ppLand = pLandscape->getLandParams(); + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + trfrRules trfr = pSpecies->getTrfr(); + initParams init = paramsInit->getInit(); + simParams sim = paramsSim->getSim(); + simView v = paramsSim->getViews(); -if (!ppLand.generated) { - if (!ppLand.patchModel) { // cell-based landscape - // create patches for suitable cells, adding unsuitable cells to the matrix - // NB this is an overhead here, but is necessary in case the identity of - // suitable habitats has been changed from one simulation to another (GUI or batch) - // substantial time savings may result during simulation in certain landscapes - pLandscape->allocatePatches(pSpecies); - } - pComm = new Community(pLandscape); // set up community - // set up a sub-community associated with each patch (incl. the matrix) - pLandscape->updateCarryingCapacity(pSpecies,0,0); -// if (ppLand.rasterType <= 2 && ppLand.dmgLoaded) -// pLandscape->updateDamageIndices(); - patchData ppp; - int npatches = pLandscape->patchCount(); - for (int i = 0; i < npatches; i++) { - ppp = pLandscape->getPatchData(i); #if RSDEBUG -//DEBUGLOG << "RunModel(): i = " << i -// << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum -// << endl; -#endif - pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES -// if (i == 0 || ppp.pPatch->getK() > 0.0) { -// // SET UP SUB-COMMUNITY FOR MATRIX PATCH AND ANY PATCH HAVING NON-ZERO CARRYING CAPACITY -// pComm->addSubComm(ppp.pPatch,ppp.patchNum); -// } - } - if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { - // restrict available landscape to initialised region - pLandscape->setLandLimits(init.minSeedX,init.minSeedY, - init.maxSeedX,init.maxSeedY); - } - else { - pLandscape->resetLandLimits(); + landPix p = pLandscape->getLandPix(); + DEBUGLOG << "RunModel(): reps=" << sim.reps + << " ppLand.nHab=" << ppLand.nHab + << " p.pix=" << p.pix + << endl; + DEBUGLOG << endl; +#endif + + if (!ppLand.generated) { + if (!ppLand.patchModel) { // cell-based landscape + // create patches for suitable cells, adding unsuitable cells to the matrix + // NB this is an overhead here, but is necessary in case the identity of + // suitable habitats has been changed from one simulation to another (GUI or batch) + // substantial time savings may result during simulation in certain landscapes + pLandscape->allocatePatches(pSpecies); + } + pComm = new Community(pLandscape); // set up community + // set up a sub-community associated with each patch (incl. the matrix) + pLandscape->updateCarryingCapacity(pSpecies, 0, 0); + patchData ppp; + int npatches = pLandscape->patchCount(); + for (int i = 0; i < npatches; i++) { + ppp = pLandscape->getPatchData(i); + pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + } + if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { + // restrict available landscape to initialised region + pLandscape->setLandLimits(init.minSeedX, init.minSeedY, + init.maxSeedX, init.maxSeedY); + } + else { + pLandscape->resetLandLimits(); + } } -} #if RS_RCPP && !R_CMD -Rcpp::List list_outPop; + Rcpp::List list_outPop; #endif -// Loop through replicates -for (int rep = 0; rep < sim.reps; rep++) { + // Loop through replicates + for (int rep = 0; rep < sim.reps; rep++) { #if RSDEBUG -DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation << " rep=" << rep << endl; + DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation << " rep=" << rep << endl; #endif #if RS_RCPP && !R_CMD Rcpp::Rcout << endl << "starting replicate " << rep << endl; @@ -121,757 +100,666 @@ DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation << " re #endif #endif - MemoLine(("Running replicate " + Int2Str(rep) + "...").c_str()); + MemoLine(("Running replicate " + Int2Str(rep) + "...").c_str()); - if (sim.saveVisits && !ppLand.generated) { - pLandscape->resetVisits(); - } + if (sim.saveVisits && !ppLand.generated) { + pLandscape->resetVisits(); + } - patchChange patchchange; - costChange costchange; - int npatchchanges = pLandscape->numPatchChanges(); - int ncostchanges = pLandscape->numCostChanges(); - int ixpchchg = 0; - int ixcostchg = 0; + patchChange patchchange; + costChange costchange; + int npatchchanges = pLandscape->numPatchChanges(); + int ncostchanges = pLandscape->numCostChanges(); + int ixpchchg = 0; + int ixcostchg = 0; #if RSDEBUG -DEBUGLOG << "RunModel(): npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges << endl; + DEBUGLOG << "RunModel(): npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges << endl; #endif - if (ppLand.generated) { + if (ppLand.generated) { #if RSDEBUG -DEBUGLOG << endl << "RunModel(): generating new landscape ..." << endl; -#endif - // delete previous community (if any) - // Note: this must be BEFORE the landscape is reset (as a sub-community accesses - // its corresponding patch upon deletion) - if (pComm != 0) delete pComm; - // generate new cell-based landscape - MemoLine("...generating new landscape..."); - pLandscape->resetLand(); -#if RSDEBUG -DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; -#endif - pLandscape->generatePatches(); - if (v.viewLand || sim.saveMaps) { - pLandscape->setLandMap(); - pLandscape->drawLandscape(rep,0,ppLand.landNum); - } + DEBUGLOG << endl << "RunModel(): generating new landscape ..." << endl; +#endif + // delete previous community (if any) + // Note: this must be BEFORE the landscape is reset (as a sub-community accesses + // its corresponding patch upon deletion) + if (pComm != 0) delete pComm; + // generate new cell-based landscape + MemoLine("...generating new landscape..."); + pLandscape->resetLand(); #if RSDEBUG -DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; + DEBUGLOG << "RunModel(): finished resetting landscape" << endl << endl; #endif - pComm = new Community(pLandscape); // set up community - // set up a sub-community associated with each patch (incl. the matrix) -// pLandscape->updateCarryingCapacity(pSpecies,0); - pLandscape->updateCarryingCapacity(pSpecies,0,0); - patchData ppp; - int npatches = pLandscape->patchCount(); + pLandscape->generatePatches(); + if (v.viewLand || sim.saveMaps) { + pLandscape->setLandMap(); + pLandscape->drawLandscape(rep, 0, ppLand.landNum); + } #if RSDEBUG -DEBUGLOG << "RunModel(): patch count is " << npatches << endl; + DEBUGLOG << endl << "RunModel(): finished generating patches" << endl; #endif - for (int i = 0; i < npatches; i++) { - ppp = pLandscape->getPatchData(i); + pComm = new Community(pLandscape); // set up community + // set up a sub-community associated with each patch (incl. the matrix) + pLandscape->updateCarryingCapacity(pSpecies, 0, 0); + patchData ppp; + int npatches = pLandscape->patchCount(); #if RSDEBUG -//DEBUGLOG << "RunModel(): i = " << i -// << " ppp.pPatch = " << ppp.pPatch << " ppp.patchNum = " << ppp.patchNum -// << endl; + DEBUGLOG << "RunModel(): patch count is " << npatches << endl; #endif + for (int i = 0; i < npatches; i++) { + ppp = pLandscape->getPatchData(i); #if RSWIN64 #if LINUX_CLUSTER - pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #else - SubCommunity *pSubComm = pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + SubCommunity* pSubComm = pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #endif -// if (ppp.y >= 9995) { -// DEBUGLOG << "RunModel(): i=" << i << " pSubComm=" << pSubComm -// << endl; -// } #else - pComm->addSubComm(ppp.pPatch,ppp.patchNum); // SET UP ALL SUB-COMMUNITIES + pComm->addSubComm(ppp.pPatch, ppp.patchNum); // SET UP ALL SUB-COMMUNITIES #endif -// if (i == 0 || ppp.pPatch->getK() > 0.0) { -// // SET UP SUB-COMMUNITY FOR MATRIX PATCH AND ANY PATCH HAVING NON-ZERO CARRYING CAPACITY -// pComm->addSubComm(ppp.pPatch,ppp.patchNum); -// } - } - MemoLine("...completed..."); + } + MemoLine("...completed..."); #if RSDEBUG -DEBUGLOG << endl << "RunModel(): finished generating populations" << endl; + DEBUGLOG << endl << "RunModel(): finished generating populations" << endl; #endif - } - if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { - // restrict available landscape to initialised region - pLandscape->setLandLimits(init.minSeedX,init.minSeedY, - init.maxSeedX,init.maxSeedY); - } - else { - pLandscape->resetLandLimits(); - } - - filesOK = true; - if (rep == 0) { - // open output files - if (sim.outRange) { // open Range file - if (!pComm->outRangeHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN RANGE FILE"); - filesOK = false; - } } - if (sim.outOccup && sim.reps > 1) - if (!pComm->outOccupancyHeaders(0)) { - MemoLine("UNABLE TO OPEN OCCUPANCY FILE(S)"); - filesOK = false; - } - if (sim.outPop) { - // open Population file - if (!pComm->outPopHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN POPULATION FILE"); - filesOK = false; - } + if (init.seedType == 0 && init.freeType < 2 && init.initFrzYr > 0) { + // restrict available landscape to initialised region + pLandscape->setLandLimits(init.minSeedX, init.minSeedY, + init.maxSeedX, init.maxSeedY); } - if (sim.outTraitsCells) - if (!pComm->outTraitsHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN TRAITS FILE"); - filesOK = false; - } - if (sim.outTraitsRows) - if (!pComm->outTraitsRowsHeaders(pSpecies,ppLand.landNum)) { - MemoLine("UNABLE TO OPEN TRAITS ROWS FILE"); - filesOK = false; + else { + pLandscape->resetLandLimits(); + } + + filesOK = true; + if (rep == 0) { + // open output files + if (sim.outRange) { // open Range file + if (!pComm->outRangeHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN RANGE FILE"); + filesOK = false; + } } - if (sim.outConnect && ppLand.patchModel) // open Connectivity file - if (!pLandscape->outConnectHeaders(0)) { - MemoLine("UNABLE TO OPEN CONNECTIVITY FILE"); - filesOK = false; + if (sim.outOccup && sim.reps > 1) + if (!pComm->outOccupancyHeaders(0)) { + MemoLine("UNABLE TO OPEN OCCUPANCY FILE(S)"); + filesOK = false; + } + if (sim.outPop) { + // open Population file + if (!pComm->outPopHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN POPULATION FILE"); + filesOK = false; + } } - } + if (sim.outTraitsCells) + if (!pComm->outTraitsHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN TRAITS FILE"); + filesOK = false; + } + if (sim.outTraitsRows) + if (!pComm->outTraitsRowsHeaders(pSpecies, ppLand.landNum)) { + MemoLine("UNABLE TO OPEN TRAITS ROWS FILE"); + filesOK = false; + } + if (sim.outConnect && ppLand.patchModel) // open Connectivity file + if (!pLandscape->outConnectHeaders(0)) { + MemoLine("UNABLE TO OPEN CONNECTIVITY FILE"); + filesOK = false; + } + } #if RSDEBUG -DEBUGLOG << "RunModel(): completed opening output files" << endl; + DEBUGLOG << "RunModel(): completed opening output files" << endl; #endif - if (!filesOK) { + if (!filesOK) { #if RSDEBUG -DEBUGLOG << "RunModel(): PROBLEM - closing output files" << endl; + DEBUGLOG << "RunModel(): PROBLEM - closing output files" << endl; #endif - // close any files which may be open - if (sim.outRange) { - pComm->outRangeHeaders(pSpecies,-999); - } - if (sim.outOccup && sim.reps > 1) - pComm->outOccupancyHeaders(-999); - if (sim.outPop) { - pComm->outPopHeaders(pSpecies,-999); - } - if (sim.outTraitsCells) - pComm->outTraitsHeaders(pSpecies,-999); - if (sim.outTraitsRows) - pComm->outTraitsRowsHeaders(pSpecies,-999); - if (sim.outConnect && ppLand.patchModel) - pLandscape->outConnectHeaders(-999); + // close any files which may be open + if (sim.outRange) { + pComm->outRangeHeaders(pSpecies, -999); + } + if (sim.outOccup && sim.reps > 1) + pComm->outOccupancyHeaders(-999); + if (sim.outPop) { + pComm->outPopHeaders(pSpecies, -999); + } + if (sim.outTraitsCells) + pComm->outTraitsHeaders(pSpecies, -999); + if (sim.outTraitsRows) + pComm->outTraitsRowsHeaders(pSpecies, -999); + if (sim.outConnect && ppLand.patchModel) + pLandscape->outConnectHeaders(-999); #if RS_RCPP && !R_CMD - return Rcpp::List::create(Rcpp::Named("Errors") = 666); + return Rcpp::List::create(Rcpp::Named("Errors") = 666); #else - return 666; + return 666; #endif - } + } - if (env.stoch && !env.local) { - // create time series in case of global environmental stochasticity - pLandscape->setGlobalStoch(sim.years+1); - } + if (env.stoch && !env.local) { + // create time series in case of global environmental stochasticity + pLandscape->setGlobalStoch(sim.years + 1); + } - if (grad.gradient) { // set up environmental gradient - pLandscape->setEnvGradient(pSpecies,true); - } + if (grad.gradient) { // set up environmental gradient + pLandscape->setEnvGradient(pSpecies, true); + } - if (sim.outConnect && ppLand.patchModel) - pLandscape->createConnectMatrix(); + if (sim.outConnect && ppLand.patchModel) + pLandscape->createConnectMatrix(); - // variables to control dynamic landscape - landChange landChg; landChg.chgnum = 0; landChg.chgyear = 999999; - if (!ppLand.generated && ppLand.dynamic) { - landChg = pLandscape->getLandChange(0); // get first change year - } + // variables to control dynamic landscape + landChange landChg; landChg.chgnum = 0; landChg.chgyear = 999999; + if (!ppLand.generated && ppLand.dynamic) { + landChg = pLandscape->getLandChange(0); // get first change year + } - // set up populations in the community - pLandscape->updateCarryingCapacity(pSpecies,0,0); + // set up populations in the community + pLandscape->updateCarryingCapacity(pSpecies, 0, 0); #if RSDEBUG -DEBUGLOG << "RunModel(): completed updating carrying capacity" << endl; + DEBUGLOG << "RunModel(): completed updating carrying capacity" << endl; #endif -// if (init.seedType != 2) { - pComm->initialise(pSpecies,-1); -// } - bool updateland = false; - int landIx = 0; // landscape change index + // if (init.seedType != 2) { + pComm->initialise(pSpecies, -1); + // } + bool updateland = false; + int landIx = 0; // landscape change index #if RSDEBUG -DEBUGLOG << "RunModel(): completed initialisation, rep=" << rep - << " pSpecies=" << pSpecies << endl; + DEBUGLOG << "RunModel(): completed initialisation, rep=" << rep + << " pSpecies=" << pSpecies << endl; #endif #if BATCH && RS_RCPP && !R_CMD - Rcpp::Rcout << "RunModel(): completed initialisation " << endl; -#endif - - // open a new individuals file for each replicate - if (sim.outInds) - pComm->outInds(rep,0,0,ppLand.landNum); - // open a new genetics file for each replicate - if (sim.outGenetics) { - pComm->outGenetics(rep,0,0,ppLand.landNum); - if (!dem.stageStruct && sim.outStartGenetic == 0) { - // write genetic data for initialised individuals of non-strucutred population - pComm->outGenetics(rep,0,0,-1); + Rcpp::Rcout << "RunModel(): completed initialisation " << endl; +#endif + + // open a new individuals file for each replicate + if (sim.outInds) + pComm->outInds(rep, 0, 0, ppLand.landNum); + // open a new genetics file for each replicate + if (sim.outGenetics) { + pComm->outGenetics(rep, 0, 0, ppLand.landNum); + if (!dem.stageStruct && sim.outStartGenetic == 0) { + // write genetic data for initialised individuals of non-strucutred population + pComm->outGenetics(rep, 0, 0, -1); + } } - } #if RSDEBUG - // output initialised Individuals - if (sim.outInds) - pComm->outInds(rep,-1,-1,-1); + // output initialised Individuals + if (sim.outInds) + pComm->outInds(rep, -1, -1, -1); #endif #if RS_RCPP // open a new movement paths file for each replicate if (sim.outPaths) - pLandscape->outPathsHeaders(rep,0); + pLandscape->outPathsHeaders(rep, 0); #endif - // years loop - MemoLine("...running..."); - for (yr = 0; yr < sim.years; yr++) { + // years loop + MemoLine("...running..."); + for (yr = 0; yr < sim.years; yr++) { #if RSDEBUG -DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation - << " rep=" << rep << " yr=" << yr << endl; + DEBUGLOG << endl << "RunModel(): starting simulation=" << sim.simulation + << " rep=" << rep << " yr=" << yr << endl; #endif #if RS_RCPP && !R_CMD - Rcpp::checkUserInterrupt(); -#endif - bool updateCC = false; - if (yr < 4 - || (yr < 31 && yr%10 == 0) - || (yr < 301 && yr%100 == 0) - || (yr < 3001 && yr%1000 == 0) - || (yr < 30001 && yr%10000 == 0) - || (yr < 300001 && yr%100000 == 0) - || (yr < 3000001 && yr%1000000 == 0) - ) { + Rcpp::checkUserInterrupt(); +#endif + bool updateCC = false; + if (yr < 4 + || (yr < 31 && yr % 10 == 0) + || (yr < 301 && yr % 100 == 0) + || (yr < 3001 && yr % 1000 == 0) + || (yr < 30001 && yr % 10000 == 0) + || (yr < 300001 && yr % 100000 == 0) + || (yr < 3000001 && yr % 1000000 == 0) + ) { #if RS_RCPP && !R_CMD - Rcpp::Rcout << "starting year " << yr << "..." << endl; + Rcpp::Rcout << "starting year " << yr << "..." << endl; #else - cout << "starting year " << yr << endl; + cout << "starting year " << yr << endl; #endif - } - if (init.seedType == 0 && init.freeType < 2) { - // apply any range restrictions - if (yr == init.initFrzYr) { - // release initial frozen range - reset landscape to its full extent - pLandscape->resetLandLimits(); - updateCC = true; } - if (init.restrictRange) { - if (yr > init.initFrzYr && yr < init.finalFrzYr) { - if ((yr-init.initFrzYr)%init.restrictFreq == 0) { - // apply dynamic range restriction + if (init.seedType == 0 && init.freeType < 2) { + // apply any range restrictions + if (yr == init.initFrzYr) { + // release initial frozen range - reset landscape to its full extent + pLandscape->resetLandLimits(); + updateCC = true; + } + if (init.restrictRange) { + if (yr > init.initFrzYr && yr < init.finalFrzYr) { + if ((yr - init.initFrzYr) % init.restrictFreq == 0) { + // apply dynamic range restriction + commStats s = pComm->getStats(); + int minY = s.maxY - init.restrictRows; + if (minY < 0) minY = 0; +#if RSDEBUG + DEBUGLOG << "RunModel(): restriction yr=" << yr + << " s.minY=" << s.minY << " s.maxY=" << s.maxY + << " init.restrictRows=" << init.restrictRows + << " minY=" << minY + << endl; +#endif + pLandscape->setLandLimits(ppLand.minX, minY, ppLand.maxX, ppLand.maxY); + updateCC = true; + } + } + if (yr == init.finalFrzYr) { + // apply final range restriction commStats s = pComm->getStats(); - int minY = s.maxY-init.restrictRows; - if (minY < 0) minY = 0; #if RSDEBUG -DEBUGLOG << "RunModel(): restriction yr=" << yr - << " s.minY=" << s.minY << " s.maxY=" << s.maxY - << " init.restrictRows=" << init.restrictRows - << " minY=" << minY - << endl; + DEBUGLOG << "RunModel(): final restriction yr=" << yr + << " s.minY=" << s.minY << " s.maxY=" << s.maxY + << endl; #endif - pLandscape->setLandLimits(ppLand.minX,minY,ppLand.maxX,ppLand.maxY); + pLandscape->setLandLimits(ppLand.minX, s.minY, ppLand.maxX, s.maxY); updateCC = true; -#if RSDEBUG -//landData d = pLandscape->getLandData(); -//DEBUGLOG << "RunModel(): landscape yr=" << yr -// << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY -// << endl; -#endif } } - if (yr == init.finalFrzYr) { - // apply final range restriction - commStats s = pComm->getStats(); -#if RSDEBUG -DEBUGLOG << "RunModel(): final restriction yr=" << yr - << " s.minY=" << s.minY << " s.maxY=" << s.maxY - << endl; -#endif - pLandscape->setLandLimits(ppLand.minX,s.minY,ppLand.maxX,s.maxY); + } + // environmental gradient, stochasticity & local extinction + // or dynamic landscape + updateland = false; + if (env.stoch || grad.gradient || ppLand.dynamic) { + if (grad.shifting && yr > grad.shift_begin && yr < grad.shift_stop) { + paramsGrad->incrOptY(); + pLandscape->setEnvGradient(pSpecies, false); updateCC = true; -#if RSDEBUG -//landData d = pLandscape->getLandData(); -//DEBUGLOG << "RunModel(): landscape yr=" << yr -// << " minX=" << d.minX << " minY=" << d.minY << " maxX=" << d.maxX << " maxY=" << d.maxY -// << endl; -#endif } - } - } - // environmental gradient, stochasticity & local extinction - // or dynamic landscape - updateland = false; - if (env.stoch || grad.gradient || ppLand.dynamic) { - if (grad.shifting && yr > grad.shift_begin && yr < grad.shift_stop) { - paramsGrad->incrOptY(); - pLandscape->setEnvGradient(pSpecies,false); - updateCC = true; - } -#if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " shift_begin=" << grad.shift_begin -// << " shift_stop=" << grad.shift_stop << " opt_y=" << grad.opt_y << endl; -#endif - if (env.stoch) { - if (env.local) pLandscape->updateLocalStoch(); - updateCC = true; - } - if (ppLand.dynamic) { -#if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " landChg.chgnum=" << landChg.chgnum - << " landChg.chgyear=" << landChg.chgyear - << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges - << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg - << endl; -#endif - if (yr == landChg.chgyear) { // apply landscape change - landIx = landChg.chgnum; - updateland = updateCC = true; - if (ppLand.patchModel) { // apply any patch changes - Patch *pPatch; - Cell *pCell; - patchchange = pLandscape->getPatchChange(ixpchchg++); - while (patchchange.chgnum <= landIx && ixpchchg <= npatchchanges) { + if (env.stoch) { + if (env.local) pLandscape->updateLocalStoch(); + updateCC = true; + } + if (ppLand.dynamic) { #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx -// << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg -// << " patchchange.chgnum=" << patchchange.chgnum -// << " .oldpatch=" << patchchange.oldpatch -// << " .newpatch=" << patchchange.newpatch -// << " .x=" << patchchange.x << " .y=" << patchchange.y -// << endl; -#endif + DEBUGLOG << "RunModel(): yr=" << yr << " landChg.chgnum=" << landChg.chgnum + << " landChg.chgyear=" << landChg.chgyear + << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges + << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg + << endl; +#endif + if (yr == landChg.chgyear) { // apply landscape change + landIx = landChg.chgnum; + updateland = updateCC = true; + if (ppLand.patchModel) { // apply any patch changes + Patch* pPatch; + Cell* pCell; + patchchange = pLandscape->getPatchChange(ixpchchg++); + while (patchchange.chgnum <= landIx && ixpchchg <= npatchchanges) { + // move cell from original patch to new patch - pCell = pLandscape->findCell(patchchange.x,patchchange.y); - if (patchchange.oldpatch != 0) { // not matrix - pPatch = pLandscape->findPatch(patchchange.oldpatch); - pPatch->removeCell(pCell); - } - if (patchchange.newpatch == 0) { // matrix - pPatch = 0; - } - else { - pPatch = pLandscape->findPatch(patchchange.newpatch); - pPatch->addCell(pCell,patchchange.x,patchchange.y); + pCell = pLandscape->findCell(patchchange.x, patchchange.y); + if (patchchange.oldpatch != 0) { // not matrix + pPatch = pLandscape->findPatch(patchchange.oldpatch); + pPatch->removeCell(pCell); + } + if (patchchange.newpatch == 0) { // matrix + pPatch = 0; + } + else { + pPatch = pLandscape->findPatch(patchchange.newpatch); + pPatch->addCell(pCell, patchchange.x, patchchange.y); + } + pCell->setPatch((intptr)pPatch); + // get next patch change + patchchange = pLandscape->getPatchChange(ixpchchg++); } - pCell->setPatch((intptr)pPatch); - // get next patch change - patchchange = pLandscape->getPatchChange(ixpchchg++); + ixpchchg--; + pLandscape->resetPatches(); // reset patch limits } - ixpchchg--; - pLandscape->resetPatches(); // reset patch limits - } - if (landChg.costfile != "NULL") { // apply any SMS cost changes -#if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " landChg.costfile=" << landChg.costfile << endl; -#endif - Cell *pCell; - costchange = pLandscape->getCostChange(ixcostchg++); - while (costchange.chgnum <= landIx && ixcostchg <= ncostchanges) { + if (landChg.costfile != "NULL") { // apply any SMS cost changes #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx -// << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg -// << " costchange.chgnum=" << costchange.chgnum -// << " .x=" << costchange.x << " .y=" << costchange.y -// << " .oldcost=" << costchange.oldcost -// << " .newcost=" << costchange.newcost -// << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " landChg.costfile=" << landChg.costfile << endl; #endif - pCell = pLandscape->findCell(costchange.x,costchange.y); - if (pCell != 0) { - pCell->setCost(costchange.newcost); - } + Cell* pCell; costchange = pLandscape->getCostChange(ixcostchg++); + while (costchange.chgnum <= landIx && ixcostchg <= ncostchanges) { + pCell = pLandscape->findCell(costchange.x, costchange.y); + if (pCell != 0) { + pCell->setCost(costchange.newcost); + } + costchange = pLandscape->getCostChange(ixcostchg++); + } + ixcostchg--; + pLandscape->resetEffCosts(); + } + if (landIx < pLandscape->numLandChanges()) { // get next change + landChg = pLandscape->getLandChange(landIx); + } + else { + landChg.chgyear = 9999999; } - ixcostchg--; - pLandscape->resetEffCosts(); - } - if (landIx < pLandscape->numLandChanges()) { // get next change - landChg = pLandscape->getLandChange(landIx); - } - else { - landChg.chgyear = 9999999; } } + } // end of environmental gradient, etc. + + if (updateCC) { + pLandscape->updateCarryingCapacity(pSpecies, yr, landIx); } - } // end of environmental gradient, etc. - if (updateCC) { - pLandscape->updateCarryingCapacity(pSpecies,yr,landIx); - } - - if (sim.outConnect && ppLand.patchModel) - pLandscape->resetConnectMatrix(); + if (sim.outConnect && ppLand.patchModel) + pLandscape->resetConnectMatrix(); - if (ppLand.dynamic && updateland) { -// trfrRules trfr = pSpecies->getTrfr(); - if (trfr.moveModel && trfr.moveType == 1) { // SMS - if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed - } - // apply effects of landscape change to species present in changed patches - pComm->patchChanges(); + if (ppLand.dynamic && updateland) { + if (trfr.moveModel && trfr.moveType == 1) { // SMS + if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed + } + // apply effects of landscape change to species present in changed patches + pComm->patchChanges(); #if RS_RCPP - pComm->dispersal(landIx,yr); + pComm->dispersal(landIx, yr); #else - pComm->dispersal(landIx); + pComm->dispersal(landIx); #endif // RS_RCPP - } - if (init.restrictRange) { - // remove any population from region removed from restricted range - if (yr > init.initFrzYr && yr < init.finalFrzYr) { - if ((yr-init.initFrzYr)%init.restrictFreq == 0) { - pComm->patchChanges(); + } + if (init.restrictRange) { + // remove any population from region removed from restricted range + if (yr > init.initFrzYr && yr < init.finalFrzYr) { + if ((yr - init.initFrzYr) % init.restrictFreq == 0) { + pComm->patchChanges(); + } } } - } - if (init.seedType == 2) { - // add any new initial individuals for the current year - pComm->initialise(pSpecies,yr); - } + if (init.seedType == 2) { + // add any new initial individuals for the current year + pComm->initialise(pSpecies, yr); + } - for(int gen = 0; gen < dem.repSeasons; gen++) // generation loop - { + for (int gen = 0; gen < dem.repSeasons; gen++) // generation loop + { #if RSDEBUG -// TEMPORARY RANDOM STREAM CHECK -//if (yr%1 == 0 && gen == 0) -if (yr%1 == 0) -{ -DEBUGLOG << endl << "RunModel(): start of gen " << gen << " in year " << yr - << " for rep " << rep << " ("; -for (int i = 0; i < 5; i++) { - int rrrr = pRandom->IRandom(1000,2000); - DEBUGLOG << " " << rrrr; -} -DEBUGLOG << " )" << endl; -} + // TEMPORARY RANDOM STREAM CHECK + if (yr % 1 == 0) + { + DEBUGLOG << endl << "RunModel(): start of gen " << gen << " in year " << yr + << " for rep " << rep << " ("; + for (int i = 0; i < 5; i++) { + int rrrr = pRandom->IRandom(1000, 2000); + DEBUGLOG << " " << rrrr; + } + DEBUGLOG << " )" << endl; + } #endif - if (v.viewPop || (sim.saveMaps && yr%sim.mapInt == 0)) { - if (updateland && gen == 0) { - pLandscape->drawLandscape(rep,landIx,ppLand.landNum); + if (v.viewPop || (sim.saveMaps && yr % sim.mapInt == 0)) { + if (updateland && gen == 0) { + pLandscape->drawLandscape(rep, landIx, ppLand.landNum); + } + pComm->draw(rep, yr, gen, ppLand.landNum); } - pComm->draw(rep,yr,gen,ppLand.landNum); - } - // Output and pop. visualisation before reproduction - if (v.viewPop || v.viewTraits || sim.outOccup - || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) - PreReproductionOutput(pLandscape,pComm,rep,yr,gen); - // for non-structured population, also produce range and population output now - if (!dem.stageStruct && (sim.outRange || sim.outPop)) - RangePopOutput(pComm,rep,yr,gen); + // Output and pop. visualisation before reproduction + if (v.viewPop || v.viewTraits || sim.outOccup + || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) + PreReproductionOutput(pLandscape, pComm, rep, yr, gen); + // for non-structured population, also produce range and population output now + if (!dem.stageStruct && (sim.outRange || sim.outPop)) + RangePopOutput(pComm, rep, yr, gen); #if RS_RCPP && !R_CMD - if ( sim.ReturnPopRaster && sim.outPop && yr >= sim.outStartPop && yr%sim.outIntPop == 0) { - list_outPop.push_back(pComm->addYearToPopList(rep,yr), "rep" + std::to_string(rep) + "_year" + std::to_string(yr)); - } -#endif - -#if RSDEBUG -//DEBUGLOG << "RunModel(): completed RangePopOutput()" -// << " Total_Size = " << Total_Size << endl; + if (sim.ReturnPopRaster && sim.outPop && yr >= sim.outStartPop && yr % sim.outIntPop == 0) { + list_outPop.push_back(pComm->addYearToPopList(rep, yr), "rep" + std::to_string(rep) + "_year" + std::to_string(yr)); + } #endif - // apply local extinction for generation 0 only // CHANGED TO *BEFORE* RANGE & POPN OUTPUT PRODUCTION IN v1.1, // SO THAT NOS. OF JUVENILES BORN CAN BE REPORTED - if (!ppLand.patchModel && gen == 0) { - if (env.localExt) pComm->localExtinction(0); - if (grad.gradient && grad.gradType == 3) pComm->localExtinction(1); - } + if (!ppLand.patchModel && gen == 0) { + if (env.localExt) pComm->localExtinction(0); + if (grad.gradient && grad.gradType == 3) pComm->localExtinction(1); + } - // reproduction - pComm->reproduction(yr); + // reproduction + pComm->reproduction(yr); - if (dem.stageStruct) { - if (sstruct.survival == 0) { // at reproduction - pComm->survival(0,2,1); // survival of all non-juvenile stages + if (dem.stageStruct) { + if (sstruct.survival == 0) { // at reproduction + pComm->survival(0, 2, 1); // survival of all non-juvenile stages + } } - } - // Output and pop. visualisation AFTER reproduction - if (dem.stageStruct && (sim.outRange || sim.outPop)) - RangePopOutput(pComm,rep,yr,gen); + // Output and pop. visualisation AFTER reproduction + if (dem.stageStruct && (sim.outRange || sim.outPop)) + RangePopOutput(pComm, rep, yr, gen); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed reproduction" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed reproduction" << endl; #endif - // Dispersal + // Dispersal - pComm->emigration(); + pComm->emigration(); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed emigration" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed emigration" << endl; #endif #if RS_RCPP - pComm->dispersal(landIx,yr); + pComm->dispersal(landIx, yr); #else - pComm->dispersal(landIx); + pComm->dispersal(landIx); #endif // RS_RCPP #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed dispersal" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed dispersal" << endl; #endif - // survival part 0 - if (dem.stageStruct) { - if (sstruct.survival == 0) { // at reproduction - pComm->survival(0,0,1); // survival of juveniles only - } - if (sstruct.survival == 1) { // between reproduction events - pComm->survival(0,1,1); // survival of all stages + // survival part 0 + if (dem.stageStruct) { + if (sstruct.survival == 0) { // at reproduction + pComm->survival(0, 0, 1); // survival of juveniles only + } + if (sstruct.survival == 1) { // between reproduction events + pComm->survival(0, 1, 1); // survival of all stages + } + if (sstruct.survival == 2) { // annually + pComm->survival(0, 1, 0); // development only of all stages + } } - if (sstruct.survival == 2) { // annually - pComm->survival(0,1,0); // development only of all stages -// pComm->survival(0,1,0); // development only of all stages + else { // non-structured population + pComm->survival(0, 1, 1); } - } - else { // non-structured population - pComm->survival(0,1,1); - } #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 0" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 0" << endl; #endif // output Individuals - if (sim.outInds && yr >= sim.outStartInd && yr%sim.outIntInd == 0) - pComm->outInds(rep,yr,gen,-1); + if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) + pComm->outInds(rep, yr, gen, -1); // output Genetics - if (sim.outGenetics && yr >= sim.outStartGenetic && yr%sim.outIntGenetic == 0) - pComm->outGenetics(rep,yr,gen,-1); + if (sim.outGenetics && yr >= sim.outStartGenetic && yr % sim.outIntGenetic == 0) + pComm->outGenetics(rep, yr, gen, -1); - // survival part 1 - if (dem.stageStruct) { -// if (sstruct.survival != 2) { // at reproduction or between reproduction events - pComm->survival(1,0,1); -// } - } - else { // non-structured population - pComm->survival(1,0,1); - } + // survival part 1 + if (dem.stageStruct) { + pComm->survival(1, 0, 1); + } + else { // non-structured population + pComm->survival(1, 0, 1); + } #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 1" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " gen=" << gen << " completed survival part 1" << endl; #endif - } // end of the generation loop + } // end of the generation loop #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed generation loop" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed generation loop" << endl; #endif - totalInds = pComm->totalInds(); - if (totalInds <= 0) { yr++; break; } + totalInds = pComm->totalInds(); + if (totalInds <= 0) { yr++; break; } - // Connectivity Matrix - if (sim.outConnect && ppLand.patchModel - && yr >= sim.outStartConn && yr%sim.outIntConn == 0) - pLandscape->outConnect(rep,yr); + // Connectivity Matrix + if (sim.outConnect && ppLand.patchModel + && yr >= sim.outStartConn && yr % sim.outIntConn == 0) + pLandscape->outConnect(rep, yr); - if (dem.stageStruct && sstruct.survival == 2) { // annual survival - all stages - pComm->survival(0,1,2); - pComm->survival(1,0,1); + if (dem.stageStruct && sstruct.survival == 2) { // annual survival - all stages + pComm->survival(0, 1, 2); + pComm->survival(1, 0, 1); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed annual survival" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed annual survival" << endl; #endif - } + } - if (dem.stageStruct) { - pComm->ageIncrement(); // increment age of all individuals - if (sim.outInds && yr >= sim.outStartInd && yr%sim.outIntInd == 0) - pComm->outInds(rep,yr,-1,-1); // list any individuals dying having reached maximum age - pComm->survival(1,0,1); // delete any such individuals + if (dem.stageStruct) { + pComm->ageIncrement(); // increment age of all individuals + if (sim.outInds && yr >= sim.outStartInd && yr % sim.outIntInd == 0) + pComm->outInds(rep, yr, -1, -1); // list any individuals dying having reached maximum age + pComm->survival(1, 0, 1); // delete any such individuals #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed Age_increment and final survival" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed Age_increment and final survival" << endl; #endif - totalInds = pComm->totalInds(); - if (totalInds <= 0) { yr++; break; } - } + totalInds = pComm->totalInds(); + if (totalInds <= 0) { yr++; break; } + } - } // end of the years loop + } // end of the years loop - // Final output and popn. visualisation + // Final output and popn. visualisation #if BATCH - if (sim.saveMaps && yr%sim.mapInt == 0) { - if (updateland) { - pLandscape->drawLandscape(rep,landIx,ppLand.landNum); + if (sim.saveMaps && yr % sim.mapInt == 0) { + if (updateland) { + pLandscape->drawLandscape(rep, landIx, ppLand.landNum); + } + pComm->draw(rep, yr, 0, ppLand.landNum); } - pComm->draw(rep,yr,0,ppLand.landNum); - } #endif // produce final summary output if (v.viewPop || v.viewTraits || sim.outOccup - || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) - PreReproductionOutput(pLandscape,pComm,rep,yr,0); + || sim.outTraitsCells || sim.outTraitsRows || sim.saveMaps) + PreReproductionOutput(pLandscape, pComm, rep, yr, 0); if (sim.outRange || sim.outPop) - RangePopOutput(pComm,rep,yr,0); + RangePopOutput(pComm, rep, yr, 0); #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed final summary output" << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed final summary output" << endl; #endif - pComm->resetPopns(); + pComm->resetPopns(); -// if (batchMode) { -// // delete the community of species using the landscape -// pComm->resetPopns(); -// } + //Reset the gradient optimum + if (grad.gradient) paramsGrad->resetOptY(); - //Reset the gradient optimum - if (grad.gradient) paramsGrad->resetOptY(); - - pLandscape->resetLandLimits(); -#if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" - << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges - << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg - << endl; -#endif - if (ppLand.patchModel && ppLand.dynamic && ixpchchg > 0) { - // apply any patch changes to reset landscape to original configuration - // (provided that at least one has already occurred) - patchChange patchchange; - Patch *pPatch; - Cell *pCell; - patchchange = pLandscape->getPatchChange(ixpchchg++); - while (patchchange.chgnum <= 666666 && ixpchchg <= npatchchanges) { + pLandscape->resetLandLimits(); #if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" -// << " npatchchanges=" << npatchchanges << " ixpchchg=" << ixpchchg -// << " patchchange.chgnum=" << patchchange.chgnum -// << " .oldpatch=" << patchchange.oldpatch -// << " .newpatch=" << patchchange.newpatch -// << " .x=" << patchchange.x << " .y=" << patchchange.y -// << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << "reset" + << " npatchchanges=" << npatchchanges << " ncostchanges=" << ncostchanges + << " ixpchchg=" << ixpchchg << " ixcostchg=" << ixcostchg + << endl; #endif + if (ppLand.patchModel && ppLand.dynamic && ixpchchg > 0) { + // apply any patch changes to reset landscape to original configuration + // (provided that at least one has already occurred) + patchChange patchchange; + Patch* pPatch; + Cell* pCell; + patchchange = pLandscape->getPatchChange(ixpchchg++); + while (patchchange.chgnum <= 666666 && ixpchchg <= npatchchanges) { + // move cell from original patch to new patch - pCell = pLandscape->findCell(patchchange.x,patchchange.y); - if (patchchange.oldpatch != 0) { // not matrix - pPatch = pLandscape->findPatch(patchchange.oldpatch); - pPatch->removeCell(pCell); - } - if (patchchange.newpatch == 0) { // matrix - pPatch = 0; - } - else { - pPatch = pLandscape->findPatch(patchchange.newpatch); - pPatch->addCell(pCell,patchchange.x,patchchange.y); + pCell = pLandscape->findCell(patchchange.x, patchchange.y); + if (patchchange.oldpatch != 0) { // not matrix + pPatch = pLandscape->findPatch(patchchange.oldpatch); + pPatch->removeCell(pCell); + } + if (patchchange.newpatch == 0) { // matrix + pPatch = 0; + } + else { + pPatch = pLandscape->findPatch(patchchange.newpatch); + pPatch->addCell(pCell, patchchange.x, patchchange.y); + } + pCell->setPatch((intptr)pPatch); + // get next patch change + patchchange = pLandscape->getPatchChange(ixpchchg++); } - pCell->setPatch((intptr)pPatch); - // get next patch change - patchchange = pLandscape->getPatchChange(ixpchchg++); + ixpchchg--; + pLandscape->resetPatches(); } - ixpchchg--; - pLandscape->resetPatches(); - } - if (ppLand.dynamic) { - trfrRules trfr = pSpecies->getTrfr(); - if (trfr.moveModel && trfr.moveType == 1) { // SMS - if (ixcostchg > 0) { - // apply any cost changes to reset landscape to original configuration - // (provided that at least one has already occurred) - Cell *pCell; - costchange = pLandscape->getCostChange(ixcostchg++); - while (costchange.chgnum <= 666666 && ixcostchg <= ncostchanges) { -#if RSDEBUG -//DEBUGLOG << "RunModel(): yr=" << yr << " landIx=" << landIx -// << " ncostchanges=" << ncostchanges << " ixcostchg=" << ixcostchg -// << " costchange.chgnum=" << costchange.chgnum -// << " .x=" << costchange.x << " .y=" << costchange.y -// << " .oldcost=" << costchange.oldcost -// << " .newcost=" << costchange.newcost -// << endl; -#endif - pCell = pLandscape->findCell(costchange.x,costchange.y); - if (pCell != 0) { - pCell->setCost(costchange.newcost); - } - costchange = pLandscape->getCostChange(ixcostchg++); + if (ppLand.dynamic) { + trfrRules trfr = pSpecies->getTrfr(); + if (trfr.moveModel && trfr.moveType == 1) { // SMS + if (ixcostchg > 0) { + // apply any cost changes to reset landscape to original configuration + // (provided that at least one has already occurred) + Cell* pCell; + costchange = pLandscape->getCostChange(ixcostchg++); + while (costchange.chgnum <= 666666 && ixcostchg <= ncostchanges) { + + pCell = pLandscape->findCell(costchange.x, costchange.y); + if (pCell != 0) { + pCell->setCost(costchange.newcost); } - ixcostchg--; - pLandscape->resetEffCosts(); + costchange = pLandscape->getCostChange(ixcostchg++); + } + ixcostchg--; + pLandscape->resetEffCosts(); + } + if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed } - if (!trfr.costMap) pLandscape->resetCosts(); // in case habitats have changed } - } -// if (landIx < pLandscape->numLandChanges()) { // get next change -// landChg = pLandscape->getLandChange(landIx); -// } -// else { -// landChg.chgyear = 9999999; -// } #if RSDEBUG -DEBUGLOG << "RunModel(): yr=" << yr << " completed reset" - << endl; + DEBUGLOG << "RunModel(): yr=" << yr << " completed reset" + << endl; #endif - if (sim.outConnect && ppLand.patchModel) - pLandscape->resetConnectMatrix(); // set connectivity matrix to zeroes + if (sim.outConnect && ppLand.patchModel) + pLandscape->resetConnectMatrix(); // set connectivity matrix to zeroes - if (sim.outInds) // close Individuals output file - pComm->outInds(rep,0,0,-999); - if (sim.outGenetics) // close Genetics output file - pComm->outGenetics(rep,0,0,-999); + if (sim.outInds) // close Individuals output file + pComm->outInds(rep, 0, 0, -999); + if (sim.outGenetics) // close Genetics output file + pComm->outGenetics(rep, 0, 0, -999); - if (sim.saveVisits) { - pLandscape->outVisits(rep,ppLand.landNum); - pLandscape->resetVisits(); - } + if (sim.saveVisits) { + pLandscape->outVisits(rep, ppLand.landNum); + pLandscape->resetVisits(); + } #if RS_RCPP - if (sim.outPaths) - pLandscape->outPathsHeaders(rep,-999); + if (sim.outPaths) + pLandscape->outPathsHeaders(rep, -999); #endif #if RSDEBUG -DEBUGLOG << endl << "RunModel(): finished rep=" << rep << endl; + DEBUGLOG << endl << "RunModel(): finished rep=" << rep << endl; #endif -} // end of the replicates loop + } // end of the replicates loop -if (sim.outConnect && ppLand.patchModel) { - pLandscape->deleteConnectMatrix(); - pLandscape->outConnectHeaders(-999); // close Connectivity Matrix file -} + if (sim.outConnect && ppLand.patchModel) { + pLandscape->deleteConnectMatrix(); + pLandscape->outConnectHeaders(-999); // close Connectivity Matrix file + } -// Occupancy outputs -if (sim.outOccup && sim.reps > 1) { - MemoLine("Writing final occupancy output..."); - pComm->outOccupancy(); - pComm->outOccSuit(v.viewGraph); -// pComm->deleteOccupancy((sim.years/sim.outInt)+1); - pComm->deleteOccupancy((sim.years/sim.outIntOcc)+1); - pComm->outOccupancyHeaders(-999); - MemoLine("...finished"); -} + // Occupancy outputs + if (sim.outOccup && sim.reps > 1) { + MemoLine("Writing final occupancy output..."); + pComm->outOccupancy(); + pComm->outOccSuit(v.viewGraph); + pComm->deleteOccupancy((sim.years / sim.outIntOcc) + 1); + pComm->outOccupancyHeaders(-999); + MemoLine("...finished"); + } -if (sim.outRange) { - pComm->outRangeHeaders(pSpecies,-999); // close Range file -} -if (sim.outPop) { - pComm->outPopHeaders(pSpecies,-999); // close Population file -} -if (sim.outTraitsCells) - pComm->outTraitsHeaders(pSpecies,-999); // close Traits file -if (sim.outTraitsRows) - pComm->outTraitsRowsHeaders(pSpecies,-999); // close Traits rows file -// close Individuals & Genetics output files if open -// they can still be open if the simulation was stopped by the user -if (sim.outInds) pComm->outInds(0,0,0,-999); -if (sim.outGenetics) pComm->outGenetics(0,0,0,-999); - -MemoLine("Deleting community..."); -delete pComm; pComm = 0; -MemoLine("...finished"); - -// Write performance data -//t1 = time(0); -//RSlog << "Simulation," << sim.simulation << "," << sim.reps << "," << sim.years -// << "," << t1-t0 << endl; + if (sim.outRange) { + pComm->outRangeHeaders(pSpecies, -999); // close Range file + } + if (sim.outPop) { + pComm->outPopHeaders(pSpecies, -999); // close Population file + } + if (sim.outTraitsCells) + pComm->outTraitsHeaders(pSpecies, -999); // close Traits file + if (sim.outTraitsRows) + pComm->outTraitsRowsHeaders(pSpecies, -999); // close Traits rows file + // close Individuals & Genetics output files if open + // they can still be open if the simulation was stopped by the user + if (sim.outInds) pComm->outInds(0, 0, 0, -999); + if (sim.outGenetics) pComm->outGenetics(0, 0, 0, -999); + + MemoLine("Deleting community..."); + delete pComm; pComm = 0; + MemoLine("...finished"); #if RS_RCPP && !R_CMD return list_outPop; @@ -883,197 +771,169 @@ MemoLine("...finished"); #if RS_EMBARCADERO || LINUX_CLUSTER || RS_RCPP // Check whether a specified directory path exists -bool is_directory(const char *pathname) { -struct stat info; -if (stat(pathname, &info) != 0) return false; // path does not exist -if (S_ISDIR(info.st_mode)) return true; -return false; +bool is_directory(const char* pathname) { + struct stat info; + if (stat(pathname, &info) != 0) return false; // path does not exist + if (S_ISDIR(info.st_mode)) return true; + return false; } #endif //--------------------------------------------------------------------------- bool CheckDirectory(void) { -bool errorfolder = false; + bool errorfolder = false; -string subfolder; + string subfolder; -subfolder = paramsSim->getDir(0) + "Inputs"; -const char *inputs = subfolder.c_str(); -if (!is_directory(inputs)) errorfolder = true; -subfolder = paramsSim->getDir(0) + "Outputs"; -const char *outputs = subfolder.c_str(); -if (!is_directory(outputs)) errorfolder = true; -subfolder = paramsSim->getDir(0) + "Output_Maps"; -const char *outputmaps = subfolder.c_str(); -if (!is_directory(outputmaps)) errorfolder = true; + subfolder = paramsSim->getDir(0) + "Inputs"; + const char* inputs = subfolder.c_str(); + if (!is_directory(inputs)) errorfolder = true; + subfolder = paramsSim->getDir(0) + "Outputs"; + const char* outputs = subfolder.c_str(); + if (!is_directory(outputs)) errorfolder = true; + subfolder = paramsSim->getDir(0) + "Output_Maps"; + const char* outputmaps = subfolder.c_str(); + if (!is_directory(outputmaps)) errorfolder = true; -return errorfolder; + return errorfolder; } //--------------------------------------------------------------------------- //For outputs and population visualisations pre-reproduction -void PreReproductionOutput(Landscape *pLand,Community *pComm,int rep,int yr,int gen) +void PreReproductionOutput(Landscape* pLand, Community* pComm, int rep, int yr, int gen) { #if RSDEBUG -landParams ppLand = pLand->getLandParams(); -#endif -simParams sim = paramsSim->getSim(); -simView v = paramsSim->getViews(); - -#if RSDEBUG -DEBUGLOG << "PreReproductionOutput(): 11111 rep=" << rep << " yr=" << yr << " gen=" << gen - << " landNum=" << ppLand.landNum << " maxX=" << ppLand.maxX << " maxY=" << ppLand.maxY - << endl; -DEBUGLOG << "PreReproductionOutput(): 11112 outRange=" << sim.outRange - << " outIntRange=" << sim.outIntRange - << " outPop=" << sim.outPop << " outIntPop=" << sim.outIntPop - << endl; + landParams ppLand = pLand->getLandParams(); #endif + simParams sim = paramsSim->getSim(); + simView v = paramsSim->getViews(); #if RSDEBUG -//DEBUGLOG << "PreReproductionOutput(): 22222 " << endl; + DEBUGLOG << "PreReproductionOutput(): 11111 rep=" << rep << " yr=" << yr << " gen=" << gen + << " landNum=" << ppLand.landNum << " maxX=" << ppLand.maxX << " maxY=" << ppLand.maxY + << endl; + DEBUGLOG << "PreReproductionOutput(): 11112 outRange=" << sim.outRange + << " outIntRange=" << sim.outIntRange + << " outPop=" << sim.outPop << " outIntPop=" << sim.outIntPop + << endl; #endif -//emigCanvas ecanv; -//trfrCanvas tcanv; -traitCanvas tcanv; -//for (int i = 0; i < 6; i++) { -// ecanv.pcanvas[i] = 0; tcanv.pcanvas[i] = 0; -//} -for (int i = 0; i < NTRAITS; i++) { + traitCanvas tcanv; + for (int i = 0; i < NTRAITS; i++) { tcanv.pcanvas[i] = 0; -} - -// trait outputs and visualisation - -if (v.viewTraits) { -// ecanv = SetupEmigCanvas(); -// tcanv = SetupTrfrCanvas(); -// tcanv = SetupTraitCanvas(v.viewGrad); - tcanv = SetupTraitCanvas(); -} - -if (v.viewTraits -|| ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr%sim.outIntTraitCell == 0) || - (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr%sim.outIntTraitRow == 0))) -{ -// pComm->outTraits(ecanv,tcanv,pSpecies,rep,yr,gen); - pComm->outTraits(tcanv,pSpecies,rep,yr,gen); -} - -#if RSDEBUG -//DEBUGLOG << "PreReproductionOutput(): 33333 " << endl; -#endif - -if (sim.outOccup && yr%sim.outIntOcc == 0 && gen == 0) - pComm->updateOccupancy(yr/sim.outIntOcc,rep); + } -#if RSDEBUG -//DEBUGLOG << "PreReproductionOutput(): 88888 " << endl; -#endif + // trait outputs and visualisation -// Remaining graphical output actions are performed for GUI only + if (v.viewTraits) { + tcanv = SetupTraitCanvas(); + } -#if RSDEBUG -//DEBUGLOG << "PreReproductionOutput(): finished " << endl; -#endif + if (v.viewTraits + || ((sim.outTraitsCells && yr >= sim.outStartTraitCell && yr % sim.outIntTraitCell == 0) || + (sim.outTraitsRows && yr >= sim.outStartTraitRow && yr % sim.outIntTraitRow == 0))) + { + pComm->outTraits(tcanv, pSpecies, rep, yr, gen); + } + if (sim.outOccup && yr % sim.outIntOcc == 0 && gen == 0) + pComm->updateOccupancy(yr / sim.outIntOcc, rep); } //For outputs and population visualisations pre-reproduction -void RangePopOutput(Community *pComm,int rep,int yr,int gen) +void RangePopOutput(Community* pComm, int rep, int yr, int gen) { -simParams sim = paramsSim->getSim(); + simParams sim = paramsSim->getSim(); -if (sim.outRange && (yr%sim.outIntRange == 0 || pComm->totalInds() <= 0)) - pComm->outRange(pSpecies,rep,yr,gen); + if (sim.outRange && (yr % sim.outIntRange == 0 || pComm->totalInds() <= 0)) + pComm->outRange(pSpecies, rep, yr, gen); -if (sim.outPop && yr >= sim.outStartPop && yr%sim.outIntPop == 0) - pComm->outPop(rep,yr,gen); + if (sim.outPop && yr >= sim.outStartPop && yr % sim.outIntPop == 0) + pComm->outPop(rep, yr, gen); } //--------------------------------------------------------------------------- -void OutParameters(Landscape *pLandscape) +void OutParameters(Landscape* pLandscape) { -double k; -//int nrows,ncols,nsexes,nstages; -int nsexes,nstages; - -landParams ppLand = pLandscape->getLandParams(); -genLandParams ppGenLand = pLandscape->getGenLandParams(); -envGradParams grad = paramsGrad->getGradient(); -envStochParams env = paramsStoch->getStoch(); -demogrParams dem = pSpecies->getDemogr(); -stageParams sstruct = pSpecies->getStage(); -emigRules emig = pSpecies->getEmig(); -trfrRules trfr = pSpecies->getTrfr(); -settleType sett = pSpecies->getSettle(); -settleRules srules; -settleSteps ssteps; -settleTraits settleDD; -simParams sim = paramsSim->getSim(); - -string name; -if (sim.batchMode) - name = paramsSim->getDir(2) + double k; + //int nrows,ncols,nsexes,nstages; + int nsexes, nstages; + + landParams ppLand = pLandscape->getLandParams(); + genLandParams ppGenLand = pLandscape->getGenLandParams(); + envGradParams grad = paramsGrad->getGradient(); + envStochParams env = paramsStoch->getStoch(); + demogrParams dem = pSpecies->getDemogr(); + stageParams sstruct = pSpecies->getStage(); + emigRules emig = pSpecies->getEmig(); + trfrRules trfr = pSpecies->getTrfr(); + settleType sett = pSpecies->getSettle(); + settleRules srules; + settleSteps ssteps; + settleTraits settleDD; + simParams sim = paramsSim->getSim(); + + string name; + if (sim.batchMode) + name = paramsSim->getDir(2) + "Batch" + Int2Str(sim.batchNum) + "_" + "Sim" + Int2Str(sim.simulation) + "_Land" + Int2Str(ppLand.landNum) + "_Parameters.txt"; -else - name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Parameters.txt"; -outPar.open(name.c_str()); + else + name = paramsSim->getDir(2) + "Sim" + Int2Str(sim.simulation) + "_Parameters.txt"; + outPar.open(name.c_str()); -outPar << "RangeShifter 2.0 "; + outPar << "RangeShifter 2.0 "; #if !RS_RCPP #if RSWIN64 -outPar << " - 64 bit implementation"; + outPar << " - 64 bit implementation"; #else -outPar << " - 32 bit implementation"; + outPar << " - 32 bit implementation"; #endif #endif -outPar << endl; + outPar << endl; -outPar << "================ "; + outPar << "================ "; -outPar << " ====================="; -outPar << endl << endl; + outPar << " ====================="; + outPar << endl << endl; -outPar << "BATCH MODE \t"; -if (sim.batchMode) outPar << "yes" << endl; else outPar << "no" << endl; + outPar << "BATCH MODE \t"; + if (sim.batchMode) outPar << "yes" << endl; else outPar << "no" << endl; #if RS_RCPP -outPar << "SEED \t" << RS_random_seed << endl; + outPar << "SEED \t" << RS_random_seed << endl; #endif -outPar << "REPLICATES \t" << sim.reps << endl; -outPar << "YEARS \t" << sim.years << endl; -outPar << "REPRODUCTIVE SEASONS / YEAR\t" << dem.repSeasons << endl; -if (ppLand.patchModel){ - outPar << "PATCH-BASED MODEL" << endl; - outPar << "No. PATCHES \t" << pLandscape->patchCount()-1 << endl; -} -else - outPar << "CELL-BASED MODEL" << endl; -outPar << "BOUNDARIES \t"; -if (sim.absorbing) outPar << "absorbing" << endl; -else outPar << "reflective" << endl; -outPar << endl; - -outPar << "LANDSCAPE:\t"; -if (ppLand.generated) { - outPar << "artificially generated map" << endl; - outPar << "TYPE: \t"; - if (ppGenLand.continuous) outPar << "continuous \t"; - else outPar << "discrete \t"; - if (ppGenLand.fractal) outPar << "fractal"; - else outPar << "random"; - outPar << endl << "PROPORTION OF SUITABLE HABITAT (p)\t" << ppGenLand.propSuit <patchCount() - 1 << endl; + } + else + outPar << "CELL-BASED MODEL" << endl; + outPar << "BOUNDARIES \t"; + if (sim.absorbing) outPar << "absorbing" << endl; + else outPar << "reflective" << endl; + outPar << endl; + + outPar << "LANDSCAPE:\t"; + if (ppLand.generated) { + outPar << "artificially generated map" << endl; + outPar << "TYPE: \t"; + if (ppGenLand.continuous) outPar << "continuous \t"; + else outPar << "discrete \t"; + if (ppGenLand.fractal) outPar << "fractal"; + else outPar << "random"; + outPar << endl << "PROPORTION OF SUITABLE HABITAT (p)\t" << ppGenLand.propSuit << endl; + if (ppGenLand.fractal) outPar << "HURST EXPONENT\t" << ppGenLand.hurst << endl; + } + else { + outPar << "imported map" << endl; + outPar << "TYPE: \t"; + switch (ppLand.rasterType) { case 0: outPar << "habitat codes" << endl; break; @@ -1083,165 +943,162 @@ else { case 2: outPar << "habitat quality" << endl; break; - } - outPar << "FILE NAME: "; + } + outPar << "FILE NAME: "; #if RS_RCPP - if (ppLand.dynamic) { - outPar << name_landscape << endl; - } - else{ - outPar << name_landscape << endl; - } - if (ppLand.patchModel) { - outPar << "PATCH FILE: " << name_patch << endl; - } - if (trfr.costMap) { - outPar << "COSTS FILE: " << name_costfile << endl; - } -#else - if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; - else { - outPar << habmapname << endl; - if (ppLand.rasterType == 1) { // habitat % cover - list additional layers - for (int i = 0; i < ppLand.nHab-1; i++) { - outPar << " "<< hfnames[i] << endl; - } + if (ppLand.dynamic) { + outPar << name_landscape << endl; } - if (ppLand.patchModel) { - outPar << "PATCH FILE: " << patchmapname << endl; + else { + outPar << name_landscape << endl; } - } -#endif - outPar << "No. HABITATS:\t" << ppLand.nHab << endl; -} -outPar << "RESOLUTION (m): \t" << ppLand.resol << endl; -outPar << "DIMENSIONS: X " << ppLand.dimX << " Y " << ppLand.dimY << endl; -outPar << "AVAILABLE: min.X " << ppLand.minX << " min.Y " << ppLand.minY - << " max.X " << ppLand.maxX << " max.Y " << ppLand.maxY << endl; -if (!ppLand.generated && ppLand.dynamic) { - landChange chg; - outPar << "DYNAMIC LANDSCAPE: " << endl; - int nchanges = pLandscape->numLandChanges(); - for (int i = 0; i < nchanges; i++) { - chg = pLandscape->getLandChange(i); - outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear << endl; - outPar << "Landscape: " << chg.habfile << endl; if (ppLand.patchModel) { - outPar << "Patches : " << chg.pchfile << endl; + outPar << "PATCH FILE: " << name_patch << endl; } - if (chg.costfile != "none" && chg.costfile != "NULL") { - outPar << "Costs : " << chg.costfile << endl; + if (trfr.costMap) { + outPar << "COSTS FILE: " << name_costfile << endl; + } +#else + if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; + else { + outPar << habmapname << endl; + if (ppLand.rasterType == 1) { // habitat % cover - list additional layers + for (int i = 0; i < ppLand.nHab - 1; i++) { + outPar << " " << hfnames[i] << endl; + } + } + if (ppLand.patchModel) { + outPar << "PATCH FILE: " << patchmapname << endl; + } + } +#endif + outPar << "No. HABITATS:\t" << ppLand.nHab << endl; + } + outPar << "RESOLUTION (m): \t" << ppLand.resol << endl; + outPar << "DIMENSIONS: X " << ppLand.dimX << " Y " << ppLand.dimY << endl; + outPar << "AVAILABLE: min.X " << ppLand.minX << " min.Y " << ppLand.minY + << " max.X " << ppLand.maxX << " max.Y " << ppLand.maxY << endl; + if (!ppLand.generated && ppLand.dynamic) { + landChange chg; + outPar << "DYNAMIC LANDSCAPE: " << endl; + int nchanges = pLandscape->numLandChanges(); + for (int i = 0; i < nchanges; i++) { + chg = pLandscape->getLandChange(i); + outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear << endl; + outPar << "Landscape: " << chg.habfile << endl; + if (ppLand.patchModel) { + outPar << "Patches : " << chg.pchfile << endl; + } + if (chg.costfile != "none" && chg.costfile != "NULL") { + outPar << "Costs : " << chg.costfile << endl; + } } -// outPar << "Change no. " << chg.chgnum << " in year " << chg.chgyear -// << " habitat map: " << chg.habfile << endl; } -} -outPar << endl << "SPECIES DISTRIBUTION LOADED: \t"; -//if (sim.initDistLoaded) -if (ppLand.spDist) -{ - outPar << "yes" << endl; - outPar << "RESOLUTION (m)\t" << ppLand.spResol << endl; - outPar << "FILE NAME: "; + outPar << endl << "SPECIES DISTRIBUTION LOADED: \t"; + if (ppLand.spDist) + { + outPar << "yes" << endl; + outPar << "RESOLUTION (m)\t" << ppLand.spResol << endl; + outPar << "FILE NAME: "; #if !RS_RCPP - if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; - else { - outPar << distnmapname << endl; - } + if (sim.batchMode) outPar << " (see batch file) " << landFile << endl; + else { + outPar << distnmapname << endl; + } #else - outPar << name_sp_dist << endl; + outPar << name_sp_dist << endl; #endif -} -else outPar << "no" << endl; - -outPar << endl << "ENVIRONMENTAL GRADIENT:\t "; -if (grad.gradient) -{ - switch (grad.gradType) { - case 1: - if (dem.stageStruct) outPar << "Density dependence strength (1/b)" << endl; - else outPar << "Carrying capacity (K)" << endl; - break; - case 2: - if (dem.stageStruct) outPar << "Fecundity" << endl; - else outPar << "Intrinsic growth rate (r)" << endl; - break; - case 3: - outPar << "Local extinction probability" << endl; - break; - default: - outPar << "ERROR ERROR ERROR" << endl; - ; } - outPar << "G:\t\t " << grad.grad_inc << endl; - outPar << "optimum Y:\t " << grad.opt_y << endl; - outPar << "f:\t\t " << grad.factor << endl; - if (grad.gradType == 3) outPar << "Local extinction prob. at optimum:\t " - << grad.extProbOpt << endl; - outPar << "GRADIENT SHIFTING:\t "; - if (grad.shifting) + else outPar << "no" << endl; + + outPar << endl << "ENVIRONMENTAL GRADIENT:\t "; + if (grad.gradient) { - outPar << "yes" << endl; - outPar << "SHIFTING RATE (rows/year):\t " << grad.shift_rate << endl; - outPar << "SHIFTING START (year):\t\t " << grad.shift_begin << endl; - outPar << "SHIFTING STOP (year):\t\t " << grad.shift_stop << endl; - } - else outPar << "no" << endl; -} -else outPar << "no"; -outPar << endl; -outPar << "ENVIRONMENTAL STOCHASTICITY:\t"; -if (env.stoch) { - outPar << "yes" << endl; - outPar << "TYPE\t in "; - if (dem.stageStruct) { - if (env.inK) outPar << "1/b" << endl; - else outPar << "fecundity" << endl; - } - else{ - if (env.inK) outPar << "K" << endl; - else outPar << "R" << endl; + switch (grad.gradType) { + case 1: + if (dem.stageStruct) outPar << "Density dependence strength (1/b)" << endl; + else outPar << "Carrying capacity (K)" << endl; + break; + case 2: + if (dem.stageStruct) outPar << "Fecundity" << endl; + else outPar << "Intrinsic growth rate (r)" << endl; + break; + case 3: + outPar << "Local extinction probability" << endl; + break; + default: + outPar << "ERROR ERROR ERROR" << endl; + ; + } + outPar << "G:\t\t " << grad.grad_inc << endl; + outPar << "optimum Y:\t " << grad.opt_y << endl; + outPar << "f:\t\t " << grad.factor << endl; + if (grad.gradType == 3) outPar << "Local extinction prob. at optimum:\t " + << grad.extProbOpt << endl; + outPar << "GRADIENT SHIFTING:\t "; + if (grad.shifting) + { + outPar << "yes" << endl; + outPar << "SHIFTING RATE (rows/year):\t " << grad.shift_rate << endl; + outPar << "SHIFTING START (year):\t\t " << grad.shift_begin << endl; + outPar << "SHIFTING STOP (year):\t\t " << grad.shift_stop << endl; + } + else outPar << "no" << endl; } - outPar << "SPATIAL AUTOCORRELATION\t "; - if (env.local) outPar << "local" << endl; - else outPar << "global" << endl; - outPar << "TEMPORAL AUTOCORRELATION (ac)\t" << env.ac << endl; - outPar << "AMPLITUDE (std)\t" << env.std << endl; - if (dem.stageStruct) { - if (env.inK) { - outPar << "MIN. 1/b\t" << pSpecies->getMinMax(0) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; - outPar << "MAX. 1/b\t" << pSpecies->getMinMax(1) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; + else outPar << "no"; + outPar << endl; + outPar << "ENVIRONMENTAL STOCHASTICITY:\t"; + if (env.stoch) { + outPar << "yes" << endl; + outPar << "TYPE\t in "; + if (dem.stageStruct) { + if (env.inK) outPar << "1/b" << endl; + else outPar << "fecundity" << endl; } else { - outPar << "MIN. fecundity\t" << pSpecies->getMinMax(0) << endl; - outPar << "MAX. fecundity\t" << pSpecies->getMinMax(1) << endl; - } - } - else { - if (env.inK) { - outPar << "MIN. K\t" << pSpecies->getMinMax(0) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; - outPar << "MAX. K\t" << pSpecies->getMinMax(1) - * (10000.0/(float)(ppLand.resol*ppLand.resol)) << endl; + if (env.inK) outPar << "K" << endl; + else outPar << "R" << endl; + } + outPar << "SPATIAL AUTOCORRELATION\t "; + if (env.local) outPar << "local" << endl; + else outPar << "global" << endl; + outPar << "TEMPORAL AUTOCORRELATION (ac)\t" << env.ac << endl; + outPar << "AMPLITUDE (std)\t" << env.std << endl; + if (dem.stageStruct) { + if (env.inK) { + outPar << "MIN. 1/b\t" << pSpecies->getMinMax(0) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + outPar << "MAX. 1/b\t" << pSpecies->getMinMax(1) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + } + else { + outPar << "MIN. fecundity\t" << pSpecies->getMinMax(0) << endl; + outPar << "MAX. fecundity\t" << pSpecies->getMinMax(1) << endl; + } } else { - outPar << "MIN. r\t" << pSpecies->getMinMax(0) << endl; - outPar << "MAX. r\t" << pSpecies->getMinMax(1) << endl; + if (env.inK) { + outPar << "MIN. K\t" << pSpecies->getMinMax(0) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + outPar << "MAX. K\t" << pSpecies->getMinMax(1) + * (10000.0 / (float)(ppLand.resol * ppLand.resol)) << endl; + } + else { + outPar << "MIN. r\t" << pSpecies->getMinMax(0) << endl; + outPar << "MAX. r\t" << pSpecies->getMinMax(1) << endl; + } } } -} -else outPar << "no" << endl; -outPar << "LOCAL EXTINCTION PROBABILITY:\t"; -if (env.localExt) outPar << env.locExtProb << endl; -else outPar << "0.0" << endl; - -outPar << endl << "SPECIES' PARAMETERS." << endl; -outPar << "REPRODUCTION:" << endl; -outPar << "TYPE: "; -switch (dem.repType) { + else outPar << "no" << endl; + outPar << "LOCAL EXTINCTION PROBABILITY:\t"; + if (env.localExt) outPar << env.locExtProb << endl; + else outPar << "0.0" << endl; + + outPar << endl << "SPECIES' PARAMETERS." << endl; + outPar << "REPRODUCTION:" << endl; + outPar << "TYPE: "; + switch (dem.repType) { case 0: outPar << "Asexual / Only female model" << endl; break; @@ -1254,838 +1111,814 @@ switch (dem.repType) { outPar << "Sexual model (explicit mating system)" << endl; outPar << "PROP. of MALES\t" << dem.propMales << endl; outPar << "MAX. HAREM SIZE (h)\t" << dem.harem << endl; - break; -} -outPar << "STAGE STRUCTURE:\t"; -if (dem.stageStruct){ - outPar << "yes" << endl; - outPar << "PROBABILITY OF REPRODUCING IN SUBSEQUENT SEASONS\t" << sstruct.probRep << endl; - outPar << "No. OF REP. SEASONS BEFORE SUBSEQUENT REPRODUCTIONS\t" << sstruct.repInterval << endl; - if (!ppLand.generated && ppLand.dynamic) { - outPar << "ACTION AFTER POPULATION DESTRUCTION: all individuals "; - if (sstruct.disperseOnLoss) outPar << "disperse" << endl; - else outPar << "die" << endl; - } - outPar << "No. STAGES\t" << sstruct.nStages << endl; - outPar << "MAX. AGE\t" << sstruct.maxAge << endl; - // no sex-specific demographic parameters - if (dem.repType != 2) { - outPar << "MIN. AGES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getMinAge(i,0) << "\tyears"<< endl; - } - outPar << "FECUNDITIES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getFec(i,0) << endl; - } - outPar << "DEVELOPMENT PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getDev(i,0) << endl; - } - outPar << "SURVIVAL PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage\t" << i << ":\t" << pSpecies->getSurv(i,0) << endl; - } - } - // sex-specific demographic parameters - else { - outPar << "MIN. AGES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getMinAge(i,1) << " years;\t"; - outPar << "females " << i << ":\t" << pSpecies->getMinAge(i,0) << " years" << endl; - } - outPar << "FECUNDITIES:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getFec(i,1) << endl; - outPar << "females " << i << ":\t" << pSpecies->getFec(i,0) << endl; - } - outPar << "DEVELOPMENT PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getDev(i,1) << endl; - outPar << "females " << i << ":\t" << pSpecies->getDev(i,0) << endl; - } - outPar << "SURVIVAL PROB.:" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "males " << i << ":\t" << pSpecies->getSurv(i,1) << endl; - outPar << "females " << i << ":\t" << pSpecies->getSurv(i,0) << endl; - } + break; } -/* -#if RSDEBUG - outPar << endl << "TRANSITION MATRIX AS ENTERED:" << endl; - if (batchMode) { - DEBUGLOG << "outParameters(): matrix = " << matrix - << " matrix[1][1] = " << matrix[1][1] - << endl; - if (dem.repType == 2) { - nrows = sstruct.nStages*2-1; ncols = sstruct.nStages*2; + outPar << "STAGE STRUCTURE:\t"; + if (dem.stageStruct) { + outPar << "yes" << endl; + outPar << "PROBABILITY OF REPRODUCING IN SUBSEQUENT SEASONS\t" << sstruct.probRep << endl; + outPar << "No. OF REP. SEASONS BEFORE SUBSEQUENT REPRODUCTIONS\t" << sstruct.repInterval << endl; + if (!ppLand.generated && ppLand.dynamic) { + outPar << "ACTION AFTER POPULATION DESTRUCTION: all individuals "; + if (sstruct.disperseOnLoss) outPar << "disperse" << endl; + else outPar << "die" << endl; + } + outPar << "No. STAGES\t" << sstruct.nStages << endl; + outPar << "MAX. AGE\t" << sstruct.maxAge << endl; + // no sex-specific demographic parameters + if (dem.repType != 2) { + outPar << "MIN. AGES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getMinAge(i, 0) << "\tyears" << endl; + } + outPar << "FECUNDITIES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getFec(i, 0) << endl; + } + outPar << "DEVELOPMENT PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getDev(i, 0) << endl; + } + outPar << "SURVIVAL PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage\t" << i << ":\t" << pSpecies->getSurv(i, 0) << endl; + } } + // sex-specific demographic parameters else { - nrows = sstruct.nStages; ncols = sstruct.nStages; - } - for (int i = 0; i < nrows; i++) { - for (int j = 0; j < ncols; j++) { - outPar << matrix[j][i] << "\t"; + outPar << "MIN. AGES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getMinAge(i, 1) << " years;\t"; + outPar << "females " << i << ":\t" << pSpecies->getMinAge(i, 0) << " years" << endl; + } + outPar << "FECUNDITIES:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getFec(i, 1) << endl; + outPar << "females " << i << ":\t" << pSpecies->getFec(i, 0) << endl; + } + outPar << "DEVELOPMENT PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getDev(i, 1) << endl; + outPar << "females " << i << ":\t" << pSpecies->getDev(i, 0) << endl; + } + outPar << "SURVIVAL PROB.:" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "males " << i << ":\t" << pSpecies->getSurv(i, 1) << endl; + outPar << "females " << i << ":\t" << pSpecies->getSurv(i, 0) << endl; } - outPar << endl; } - } - outPar << endl; -#endif -*/ - outPar << "SCHEDULING OF SURVIVAL: "; - switch (sstruct.survival) { - case 0: - outPar << "At reproduction" << endl; - break; - case 1: - outPar << "Between reproductive events" << endl; - break; - case 2: - outPar << "Annually" << endl; - break; - } - - int mSize; // index for weights matrices - if (dem.repType == 2) mSize = sstruct.nStages * NSEXES; - else mSize = sstruct.nStages; + outPar << "SCHEDULING OF SURVIVAL: "; + switch (sstruct.survival) { + case 0: + outPar << "At reproduction" << endl; + break; + case 1: + outPar << "Between reproductive events" << endl; + break; + case 2: + outPar << "Annually" << endl; + break; + } - outPar << "DENSITY-DEPENDENCE IN FECUNDITY:\t"; - if (sstruct.fecDens) { - outPar << "yes" << endl; - if (sstruct.fecStageDens) { - outPar << "STAGE'S WEIGHTS:" << endl; - for (int i = 0; i < mSize; i++) { - if (dem.repType == 2) { - outPar << "stage " << i/NSEXES << " "; - if (i%NSEXES == 0) outPar << "males : \t"; - else outPar << "females: \t"; + int mSize; // index for weights matrices + if (dem.repType == 2) mSize = sstruct.nStages * NSEXES; + else mSize = sstruct.nStages; + + outPar << "DENSITY-DEPENDENCE IN FECUNDITY:\t"; + if (sstruct.fecDens) { + outPar << "yes" << endl; + if (sstruct.fecStageDens) { + outPar << "STAGE'S WEIGHTS:" << endl; + for (int i = 0; i < mSize; i++) { + if (dem.repType == 2) { + outPar << "stage " << i / NSEXES << " "; + if (i % NSEXES == 0) outPar << "males : \t"; + else outPar << "females: \t"; + } + else outPar << "stage " << i << ": \t"; + for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtFec(j, i) << "\t"; + outPar << endl; } - else outPar << "stage " << i << ": \t"; - for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtFec(j,i) << "\t"; - outPar << endl; } - } - else outPar << "not stage-dependent" << endl; - } - else outPar << "no" << endl; - - densDepParams ddparams = pSpecies->getDensDep(); - - outPar << "DENSITY-DEPENDENCE IN DEVELOPMENT:\t"; - if (sstruct.devDens) { - outPar << "yes - coefficient: " << ddparams.devCoeff << endl; - if (sstruct.devStageDens) { - outPar << "STAGE'S WEIGHTS:" << endl; - for (int i = 0; i < mSize; i++) { - if (dem.repType == 2) { - outPar << "stage " << i/NSEXES << " "; - if (i%NSEXES == 0) outPar << "males : \t"; - else outPar << "females: \t"; + else outPar << "not stage-dependent" << endl; + } + else outPar << "no" << endl; + + densDepParams ddparams = pSpecies->getDensDep(); + + outPar << "DENSITY-DEPENDENCE IN DEVELOPMENT:\t"; + if (sstruct.devDens) { + outPar << "yes - coefficient: " << ddparams.devCoeff << endl; + if (sstruct.devStageDens) { + outPar << "STAGE'S WEIGHTS:" << endl; + for (int i = 0; i < mSize; i++) { + if (dem.repType == 2) { + outPar << "stage " << i / NSEXES << " "; + if (i % NSEXES == 0) outPar << "males : \t"; + else outPar << "females: \t"; + } + else outPar << "stage " << i << ": \t"; + for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtDev(j, i) << "\t"; + outPar << endl; } - else outPar << "stage " << i << ": \t"; - for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtDev(j,i) << "\t"; - outPar << endl; } - } - else outPar << "not stage-dependent" << endl; - } - else outPar << "no" << endl; - - outPar << "DENSITY-DEPENDENCE IN SURVIVAL:\t\t"; - if (sstruct.survDens) { - outPar << "yes - coefficient: " << ddparams.survCoeff << endl; - if (sstruct.survStageDens) { - outPar << "STAGE'S WEIGHTS:" << endl; - for (int i = 0; i < mSize; i++) { - if (dem.repType == 2) { - outPar << "stage " << i/NSEXES << " "; - if (i%NSEXES == 0) outPar << "males : \t"; - else outPar << "females: \t"; + else outPar << "not stage-dependent" << endl; + } + else outPar << "no" << endl; + + outPar << "DENSITY-DEPENDENCE IN SURVIVAL:\t\t"; + if (sstruct.survDens) { + outPar << "yes - coefficient: " << ddparams.survCoeff << endl; + if (sstruct.survStageDens) { + outPar << "STAGE'S WEIGHTS:" << endl; + for (int i = 0; i < mSize; i++) { + if (dem.repType == 2) { + outPar << "stage " << i / NSEXES << " "; + if (i % NSEXES == 0) outPar << "males : \t"; + else outPar << "females: \t"; + } + else outPar << "stage " << i << ": \t"; + for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtSurv(j, i) << "\t"; + outPar << endl; } - else outPar << "stage " << i << ": \t"; - for (int j = 0; j < mSize; j++) outPar << pSpecies->getDDwtSurv(j,i) << "\t"; - outPar << endl; } + else outPar << "not stage-dependent" << endl; } - else outPar << "not stage-dependent" << endl; + else outPar << "no" << endl; + } // end of if (dem.stageStruct) + else { // not stage-strutured + outPar << "no" << endl; + outPar << "Rmax\t" << dem.lambda << endl; + outPar << "bc\t" << dem.bc << endl; } - else outPar << "no" << endl; -} // end of if (dem.stageStruct) -else { // not stage-strutured - outPar << "no" << endl; - outPar << "Rmax\t" << dem.lambda << endl; - outPar << "bc\t" << dem.bc << endl; -} -if (dem.stageStruct) { - outPar << endl << "HABITAT SPECIFIC 1/b:" << endl; -} -else { - outPar << endl << "CARRYING CAPACITIES:" << endl; -} -int nhab = ppLand.nHab; -if (ppLand.generated) { - if (ppGenLand.continuous) nhab = 1; -} -for (int i = 0; i < nhab; i++) { - k = pSpecies->getHabK(i) * (10000.0/(float)(ppLand.resol*ppLand.resol)); - if (!ppLand.generated && ppLand.rasterType == 0) { // imported & habitat codes - outPar << "Habitat " << pLandscape->getHabCode(i) << ": \t"; + if (dem.stageStruct) { + outPar << endl << "HABITAT SPECIFIC 1/b:" << endl; } else { - outPar << "Habitat " << i << ": "; + outPar << endl << "CARRYING CAPACITIES:" << endl; } - if (dem.stageStruct) outPar << "1/b "; - else outPar << "K "; - outPar << k << endl; -} - -emigTraits ep0,ep1; -emigParams eparams0,eparams1; -string sexdept = "SEX-DEPENDENT: "; -string stgdept = "STAGE-DEPENDENT: "; -string indvar = "INDIVIDUAL VARIABILITY: "; -string emigstage = "EMIGRATION STAGE: "; - -outPar << endl << "DISPERSAL - EMIGRATION:\t"; -if (emig.densDep) { - outPar << "density-dependent" << endl; - - if (emig.sexDep) { - outPar << sexdept << "yes" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ":" << endl; - ep0 = pSpecies->getEmigTraits(i,0); - ep1 = pSpecies->getEmigTraits(i,1); - outPar << "D0: females "<< ep0.d0 << " males " << ep1.d0 << endl; - outPar << "alpha: females "<< ep0.alpha << " males " << ep1.alpha << endl; - outPar << "beta: females "<< ep0.beta << " males " << ep1.beta << endl; - } - } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - eparams1 = pSpecies->getEmigParams(0,1); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; + int nhab = ppLand.nHab; + if (ppLand.generated) { + if (ppGenLand.continuous) nhab = 1; + } + for (int i = 0; i < nhab; i++) { + k = pSpecies->getHabK(i) * (10000.0 / (float)(ppLand.resol * ppLand.resol)); + if (!ppLand.generated && ppLand.rasterType == 0) { // imported & habitat codes + outPar << "Habitat " << pLandscape->getHabCode(i) << ": \t"; + } + else { + outPar << "Habitat " << i << ": "; + } + if (dem.stageStruct) outPar << "1/b "; + else outPar << "K "; + outPar << k << endl; + } + + emigTraits ep0, ep1; + emigParams eparams0, eparams1; + string sexdept = "SEX-DEPENDENT: "; + string stgdept = "STAGE-DEPENDENT: "; + string indvar = "INDIVIDUAL VARIABILITY: "; + string emigstage = "EMIGRATION STAGE: "; + + outPar << endl << "DISPERSAL - EMIGRATION:\t"; + if (emig.densDep) { + outPar << "density-dependent" << endl; + + if (emig.sexDep) { + outPar << sexdept << "yes" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ":" << endl; + ep0 = pSpecies->getEmigTraits(i, 0); + ep1 = pSpecies->getEmigTraits(i, 1); + outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; + outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; + outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; } - outPar << "D0 females: mean " << eparams0.d0Mean << " s.d. " << eparams0.d0SD - << " scaling factor " << eparams0.d0Scale << endl; - outPar << "D0 males: mean " << eparams1.d0Mean << " s.d. " << eparams1.d0SD - << " scaling factor " << eparams1.d0Scale << endl; - outPar << "Alpha females: mean " << eparams0.alphaMean << " s.d. " << eparams0.alphaSD - << " scaling factor " << eparams0.alphaScale << endl; - outPar << "Alpha males: mean " << eparams1.alphaMean << " s.d. " << eparams1.alphaSD - << " scaling factor " << eparams1.alphaScale << endl; - outPar << "Beta females: mean " << eparams0.betaMean << " s.d. " << eparams0.betaSD - << " scaling factor " << eparams0.betaScale << endl; - outPar << "Beta males: mean " << eparams1.betaMean << " s.d. " << eparams1.betaSD - << " scaling factor " << eparams1.betaScale << endl; } - else { - outPar << "no" << endl; - ep0 = pSpecies->getEmigTraits(0,0); - ep1 = pSpecies->getEmigTraits(0,1); - outPar << "D0: females "<< ep0.d0 << " males " << ep1.d0 << endl; - outPar << "alpha: females "<< ep0.alpha << " males " << ep1.alpha << endl; - outPar << "beta: females "<< ep0.beta << " males " << ep1.beta << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + eparams1 = pSpecies->getEmigParams(0, 1); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << "D0 females: mean " << eparams0.d0Mean << " s.d. " << eparams0.d0SD + << " scaling factor " << eparams0.d0Scale << endl; + outPar << "D0 males: mean " << eparams1.d0Mean << " s.d. " << eparams1.d0SD + << " scaling factor " << eparams1.d0Scale << endl; + outPar << "Alpha females: mean " << eparams0.alphaMean << " s.d. " << eparams0.alphaSD + << " scaling factor " << eparams0.alphaScale << endl; + outPar << "Alpha males: mean " << eparams1.alphaMean << " s.d. " << eparams1.alphaSD + << " scaling factor " << eparams1.alphaScale << endl; + outPar << "Beta females: mean " << eparams0.betaMean << " s.d. " << eparams0.betaSD + << " scaling factor " << eparams0.betaScale << endl; + outPar << "Beta males: mean " << eparams1.betaMean << " s.d. " << eparams1.betaSD + << " scaling factor " << eparams1.betaScale << endl; + } + else { + outPar << "no" << endl; + ep0 = pSpecies->getEmigTraits(0, 0); + ep1 = pSpecies->getEmigTraits(0, 1); + outPar << "D0: females " << ep0.d0 << " males " << ep1.d0 << endl; + outPar << "alpha: females " << ep0.alpha << " males " << ep1.alpha << endl; + outPar << "beta: females " << ep0.beta << " males " << ep1.beta << endl; + } } } - } - else { // !emig.sexDep - outPar << sexdept << "no" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - ep0 = pSpecies->getEmigTraits(i,0); - outPar << "stage " << i << ": \t" << "D0: " << ep0.d0; - outPar<< " \talpha: " << ep0.alpha << " \tbeta: " << ep0.beta << endl; - } - } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; + else { // !emig.sexDep + outPar << sexdept << "no" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + ep0 = pSpecies->getEmigTraits(i, 0); + outPar << "stage " << i << ": \t" << "D0: " << ep0.d0; + outPar << " \talpha: " << ep0.alpha << " \tbeta: " << ep0.beta << endl; } - outPar << "D0 mean: " << eparams0.d0Mean << " s.d.: " << eparams0.d0SD - << " scaling factor: " << scale.d0Scale << endl; - outPar << "Alpha mean: " << eparams0.alphaMean << " s.d.: " << eparams0.alphaSD - << " scaling factor: " << scale.alphaScale << endl; - outPar << "Beta mean: " << eparams0.betaMean << " s.d.: " << eparams0.betaSD - << " scaling factor: " << scale.betaScale << endl; } - else{ - outPar << "no" << endl; - ep0 = pSpecies->getEmigTraits(0,0); - outPar << "D0: " << ep0.d0 << endl; - outPar << "alpha: " << ep0.alpha << endl; - outPar << "beta: " << ep0.beta << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + emigScales scale = pSpecies->getEmigScales(); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << "D0 mean: " << eparams0.d0Mean << " s.d.: " << eparams0.d0SD + << " scaling factor: " << scale.d0Scale << endl; + outPar << "Alpha mean: " << eparams0.alphaMean << " s.d.: " << eparams0.alphaSD + << " scaling factor: " << scale.alphaScale << endl; + outPar << "Beta mean: " << eparams0.betaMean << " s.d.: " << eparams0.betaSD + << " scaling factor: " << scale.betaScale << endl; + } + else { + outPar << "no" << endl; + ep0 = pSpecies->getEmigTraits(0, 0); + outPar << "D0: " << ep0.d0 << endl; + outPar << "alpha: " << ep0.alpha << endl; + outPar << "beta: " << ep0.beta << endl; + } } } } -} -else { // not density-dependent - string initprob = "INITIAL EMIGRATION PROB. "; - outPar << "density-independent" << endl; - if (!trfr.moveModel) { // transfer by kernel - outPar << "USE FULL KERNEL TO DETERMINE EMIGRATION: "; - if (pSpecies->useFullKernel()) outPar << "yes"; - else outPar << "no"; - outPar << endl; - } + else { // not density-dependent + string initprob = "INITIAL EMIGRATION PROB. "; + outPar << "density-independent" << endl; + if (!trfr.moveModel) { // transfer by kernel + outPar << "USE FULL KERNEL TO DETERMINE EMIGRATION: "; + if (pSpecies->useFullKernel()) outPar << "yes"; + else outPar << "no"; + outPar << endl; + } - if (emig.sexDep) { - outPar << sexdept << "yes" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: \tfemales " - << pSpecies->getEmigD0(i,0) <<" \tmales "<< pSpecies->getEmigD0(i,1) << endl; - } - } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - eparams1 = pSpecies->getEmigParams(0,1); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; + if (emig.sexDep) { + outPar << sexdept << "yes" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: \tfemales " + << pSpecies->getEmigD0(i, 0) << " \tmales " << pSpecies->getEmigD0(i, 1) << endl; } - outPar << initprob << "mean: " << "females " << eparams0.d0Mean - << " males " << eparams1.d0Mean << endl; - outPar << initprob << "s.d.: " << "females " << eparams0.d0SD - << " males " << eparams1.d0SD << endl; - outPar << initprob << "scaling factor: " << scale.d0Scale - << endl; - } - else{ - outPar << "no" << endl; - outPar << "EMIGRATION PROB.: \tfemales "<< pSpecies->getEmigD0(0,0) - <<"\t males " << pSpecies->getEmigD0(0,1) << endl; } - } - } - else { // !emig.sexDep - outPar << sexdept << "no" << endl; - if (emig.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: " - << pSpecies->getEmigD0(i,0) << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + eparams1 = pSpecies->getEmigParams(0, 1); + emigScales scale = pSpecies->getEmigScales(); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << initprob << "mean: " << "females " << eparams0.d0Mean + << " males " << eparams1.d0Mean << endl; + outPar << initprob << "s.d.: " << "females " << eparams0.d0SD + << " males " << eparams1.d0SD << endl; + outPar << initprob << "scaling factor: " << scale.d0Scale + << endl; + } + else { + outPar << "no" << endl; + outPar << "EMIGRATION PROB.: \tfemales " << pSpecies->getEmigD0(0, 0) + << "\t males " << pSpecies->getEmigD0(0, 1) << endl; + } } } - else { // !emig.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (emig.indVar) { - eparams0 = pSpecies->getEmigParams(0,0); - emigScales scale = pSpecies->getEmigScales(); - outPar << "yes" << endl; - if (dem.stageStruct) { - outPar << emigstage << emig.emigStage << endl; + else { // !emig.sexDep + outPar << sexdept << "no" << endl; + if (emig.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ": \t" << "EMIGRATION PROB.: " + << pSpecies->getEmigD0(i, 0) << endl; } - outPar << initprob << "mean: " << eparams0.d0Mean << endl; - outPar << initprob << "s.d.: " << eparams0.d0SD << endl; - outPar << initprob << "scaling factor: " << scale.d0Scale << endl; } - else { - outPar << "no" << endl; - outPar << "EMIGRATION PROB.:\t" << pSpecies->getEmigD0(0,0) << endl; + else { // !emig.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (emig.indVar) { + eparams0 = pSpecies->getEmigParams(0, 0); + emigScales scale = pSpecies->getEmigScales(); + outPar << "yes" << endl; + if (dem.stageStruct) { + outPar << emigstage << emig.emigStage << endl; + } + outPar << initprob << "mean: " << eparams0.d0Mean << endl; + outPar << initprob << "s.d.: " << eparams0.d0SD << endl; + outPar << initprob << "scaling factor: " << scale.d0Scale << endl; + } + else { + outPar << "no" << endl; + outPar << "EMIGRATION PROB.:\t" << pSpecies->getEmigD0(0, 0) << endl; + } } } } -} -// Transfer + // Transfer -outPar << endl << "DISPERSAL - TRANSFER: \t"; + outPar << endl << "DISPERSAL - TRANSFER: \t"; -if (trfr.moveModel) { - bool straigtenPath; - if (trfr.moveType == 1) { // SMS - trfrSMSTraits move = pSpecies->getSMSTraits(); - straigtenPath = move.straigtenPath; - if (trfr.costMap) { - outPar << "SMS\tcosts from imported cost map" << endl; + if (trfr.moveModel) { + bool straigtenPath; + if (trfr.moveType == 1) { // SMS + trfrSMSTraits move = pSpecies->getSMSTraits(); + straigtenPath = move.straigtenPath; + if (trfr.costMap) { + outPar << "SMS\tcosts from imported cost map" << endl; #if !RS_RCPP - outPar << "FILE NAME: " << costmapname << endl; + outPar << "FILE NAME: " << costmapname << endl; #endif - } - else { - outPar << "SMS\tcosts:" << endl; - if (!ppLand.generated && ppLand.rasterType == 0) { - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" - << pSpecies->getHabCost(i) << endl; } else { - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << i << "\t" + outPar << "SMS\tcosts:" << endl; + if (!ppLand.generated && ppLand.rasterType == 0) { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" << pSpecies->getHabCost(i) << endl; + } + else { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << i << "\t" + << pSpecies->getHabCost(i) << endl; + } } - } - string pr = "PERCEPTUAL RANGE"; - outPar << pr << ": " << move.pr << endl; - outPar << pr << " METHOD: " << move.prMethod << endl; - if (!trfr.indVar) outPar << "DIRECTIONAL PERSISTENCE: " << move.dp << endl; - outPar << "MEMORY SIZE: " << move.memSize << endl; - //if (!trfr.indVar) outPar << "GOAL BIAS: " << move.gb << endl; - outPar << "GOAL TYPE: " << move.goalType << endl; - if (!trfr.indVar) { - if (move.goalType == 2) { // dispersal bias - outPar << "GOAL BIAS: " << move.gb << endl; - outPar << "ALPHA DB: " << move.alphaDB << endl; - outPar << "BETA DB: " << move.betaDB << endl; - } - } - if (trfr.indVar) { - trfrSMSParams s = pSpecies->getSMSParams(0,0); - outPar << indvar << "yes " << endl; - outPar << "DP mean: " << s.dpMean << " s.d.: " << s.dpSD - << " scaling factor: " << s.dpScale << endl; - outPar << "GB mean: " << s.gbMean << " s.d.: " << s.gbSD - << " scaling factor: " << s.gbScale << endl; - if (move.goalType == 2) { // dispersal bias - outPar << "Alpha DB mean: " << s.alphaDBMean << " s.d.: " << s.alphaDBSD - << " scaling factor: " << s.alphaDBScale << endl; - outPar << "Beta DB mean: " << s.betaDBMean << " s.d.: " << s.betaDBSD - << " scaling factor: " << s.betaDBScale << endl; + string pr = "PERCEPTUAL RANGE"; + outPar << pr << ": " << move.pr << endl; + outPar << pr << " METHOD: " << move.prMethod << endl; + if (!trfr.indVar) outPar << "DIRECTIONAL PERSISTENCE: " << move.dp << endl; + outPar << "MEMORY SIZE: " << move.memSize << endl; + outPar << "GOAL TYPE: " << move.goalType << endl; + if (!trfr.indVar) { + if (move.goalType == 2) { // dispersal bias + outPar << "GOAL BIAS: " << move.gb << endl; + outPar << "ALPHA DB: " << move.alphaDB << endl; + outPar << "BETA DB: " << move.betaDB << endl; + } + } + if (trfr.indVar) { + trfrSMSParams s = pSpecies->getSMSParams(0, 0); + outPar << indvar << "yes " << endl; + outPar << "DP mean: " << s.dpMean << " s.d.: " << s.dpSD + << " scaling factor: " << s.dpScale << endl; + outPar << "GB mean: " << s.gbMean << " s.d.: " << s.gbSD + << " scaling factor: " << s.gbScale << endl; + if (move.goalType == 2) { // dispersal bias + outPar << "Alpha DB mean: " << s.alphaDBMean << " s.d.: " << s.alphaDBSD + << " scaling factor: " << s.alphaDBScale << endl; + outPar << "Beta DB mean: " << s.betaDBMean << " s.d.: " << s.betaDBSD + << " scaling factor: " << s.betaDBScale << endl; + } + } + else { + outPar << indvar << "no " << endl; } } - else { - outPar << indvar << "no " << endl; - } - } - else { // CRW - trfrCRWTraits move = pSpecies->getCRWTraits(); - straigtenPath = move.straigtenPath; - outPar << "CRW" << endl; - string lgth = "STEP LENGTH (m) "; - string corr = "STEP CORRELATION"; - if (trfr.indVar) { - trfrCRWParams m = pSpecies->getCRWParams(0,0); - outPar << indvar << "yes" << endl; - outPar << lgth << " mean: " << m.stepLgthMean; - outPar << " s.d.: " << m.stepLgthSD; - outPar << " scaling factor: " << m.stepLScale << endl; - outPar << corr << " mean: " << m.rhoMean; - outPar << " s.d.: " << m.rhoSD; - outPar << " scaling factor: " << m.rhoScale << endl; - } - else { - outPar << indvar << "no" << endl; - outPar << lgth << ": " << move.stepLength << endl; - outPar << corr << ": " << move.rho << endl; + else { // CRW + trfrCRWTraits move = pSpecies->getCRWTraits(); + straigtenPath = move.straigtenPath; + outPar << "CRW" << endl; + string lgth = "STEP LENGTH (m) "; + string corr = "STEP CORRELATION"; + if (trfr.indVar) { + trfrCRWParams m = pSpecies->getCRWParams(0, 0); + outPar << indvar << "yes" << endl; + outPar << lgth << " mean: " << m.stepLgthMean; + outPar << " s.d.: " << m.stepLgthSD; + outPar << " scaling factor: " << m.stepLScale << endl; + outPar << corr << " mean: " << m.rhoMean; + outPar << " s.d.: " << m.rhoSD; + outPar << " scaling factor: " << m.rhoScale << endl; + } + else { + outPar << indvar << "no" << endl; + outPar << lgth << ": " << move.stepLength << endl; + outPar << corr << ": " << move.rho << endl; + } } - } - outPar << "STRAIGHTEN PATH AFTER DECISION NOT TO SETTLE: "; - if (straigtenPath) outPar << "yes" << endl; - else outPar << "no" << endl; - outPar << "STEP MORTALITY:\t" << endl; - if (trfr.habMort) - { - outPar << "habitat dependent:\t" << endl; - if (!ppLand.generated && ppLand.rasterType == 0) { - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" + outPar << "STRAIGHTEN PATH AFTER DECISION NOT TO SETTLE: "; + if (straigtenPath) outPar << "yes" << endl; + else outPar << "no" << endl; + outPar << "STEP MORTALITY:\t" << endl; + if (trfr.habMort) + { + outPar << "habitat dependent:\t" << endl; + if (!ppLand.generated && ppLand.rasterType == 0) { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << pLandscape->getHabCode(i) << "\t" << pSpecies->getHabMort(i) << endl; - } - else{ - for (int i = 0; i < ppLand.nHab; i++) - outPar << "\thab. " << i << "\t" + } + else { + for (int i = 0; i < ppLand.nHab; i++) + outPar << "\thab. " << i << "\t" << pSpecies->getHabMort(i) << endl; - } - } - else - { - trfrCRWTraits move = pSpecies->getCRWTraits(); - outPar << "constant " << move.stepMort << endl; - } -} // end of movement process -else { // kernel - string meandist = "MEAN DISTANCE"; - string probkern = "PROB. KERNEL I"; - trfrKernTraits kern0,kern1; - trfrKernParams k0,k1; - outPar << "dispersal kernel" << endl << "TYPE: \t"; - if (trfr.twinKern) outPar << "double "; - outPar << "negative exponential" << endl; - - if (trfr.sexDep) { - outPar << sexdept << "yes" << endl; - if (trfr.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - outPar << "stage " << i << ":" << endl; - kern0 = pSpecies->getKernTraits(i,0); - kern1 = pSpecies->getKernTraits(i,1); - outPar << meandist << " I: \tfemales "<< kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; - if (trfr.twinKern) - { - outPar << meandist << " II: \tfemales "<< kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; - outPar << probkern << ": \tfemales "<< kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; - } } } - else { // !trfr.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (trfr.indVar) { - k0 = pSpecies->getKernParams(0,0); - k1 = pSpecies->getKernParams(0,1); - outPar << "yes" << endl; - outPar << meandist << " I (mean): \tfemales " << k0.dist1Mean - << " \tmales " << k1.dist1Mean << endl; - outPar << meandist << " I (s.d.): \tfemales " << k0.dist1SD - << " \tmales " << k1.dist1SD << endl; - outPar << meandist << " I (scaling factor): \tfemales " << k0.dist1Scale - << " \tmales " << k1.dist1Scale << endl; - if (trfr.twinKern) - { - outPar << meandist << " II (mean): \tfemales " << k0.dist2Mean - << " \tmales " << k1.dist2Mean << endl; - outPar << meandist << " II (s.d.): \tfemales " << k0.dist2SD - << " \tmales " << k1.dist2SD << endl; - outPar << meandist << " II (scaling factor): \tfemales " << k0.dist2Scale - << " \tmales " << k1.dist2Scale << endl; - outPar << probkern << " (mean): \tfemales " << k0.PKern1Mean - << " \tmales " << k1.PKern1Mean << endl; - outPar << probkern << " (s.d.): \tfemales " << k0.PKern1SD - << " \tmales " << k1.PKern1SD << endl; - outPar << probkern << " (scaling factor): \tfemales " << k0.PKern1Scale - << " \tmales " << k1.PKern1Scale << endl; + else + { + trfrCRWTraits move = pSpecies->getCRWTraits(); + outPar << "constant " << move.stepMort << endl; + } + } // end of movement process + else { // kernel + string meandist = "MEAN DISTANCE"; + string probkern = "PROB. KERNEL I"; + trfrKernTraits kern0, kern1; + trfrKernParams k0, k1; + outPar << "dispersal kernel" << endl << "TYPE: \t"; + if (trfr.twinKern) outPar << "double "; + outPar << "negative exponential" << endl; + + if (trfr.sexDep) { + outPar << sexdept << "yes" << endl; + if (trfr.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + outPar << "stage " << i << ":" << endl; + kern0 = pSpecies->getKernTraits(i, 0); + kern1 = pSpecies->getKernTraits(i, 1); + outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \tfemales " << kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; + outPar << probkern << ": \tfemales " << kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; + } } } - else { - outPar << "no" << endl; - kern0 = pSpecies->getKernTraits(0,0); - kern1 = pSpecies->getKernTraits(0,1); - outPar << meandist << " I: \tfemales "<< kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; - if (trfr.twinKern) - { - outPar << meandist << " II: \tfemales "<< kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; - outPar << probkern << ": \tfemales "<< kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; + else { // !trfr.stgDep + outPar << stgdept << "no" << endl; + outPar << indvar; + if (trfr.indVar) { + k0 = pSpecies->getKernParams(0, 0); + k1 = pSpecies->getKernParams(0, 1); + outPar << "yes" << endl; + outPar << meandist << " I (mean): \tfemales " << k0.dist1Mean + << " \tmales " << k1.dist1Mean << endl; + outPar << meandist << " I (s.d.): \tfemales " << k0.dist1SD + << " \tmales " << k1.dist1SD << endl; + outPar << meandist << " I (scaling factor): \tfemales " << k0.dist1Scale + << " \tmales " << k1.dist1Scale << endl; + if (trfr.twinKern) + { + outPar << meandist << " II (mean): \tfemales " << k0.dist2Mean + << " \tmales " << k1.dist2Mean << endl; + outPar << meandist << " II (s.d.): \tfemales " << k0.dist2SD + << " \tmales " << k1.dist2SD << endl; + outPar << meandist << " II (scaling factor): \tfemales " << k0.dist2Scale + << " \tmales " << k1.dist2Scale << endl; + outPar << probkern << " (mean): \tfemales " << k0.PKern1Mean + << " \tmales " << k1.PKern1Mean << endl; + outPar << probkern << " (s.d.): \tfemales " << k0.PKern1SD + << " \tmales " << k1.PKern1SD << endl; + outPar << probkern << " (scaling factor): \tfemales " << k0.PKern1Scale + << " \tmales " << k1.PKern1Scale << endl; + } } - } - } - } - else { // !trfr.sexDep - outPar << sexdept << "no" << endl; - if (trfr.stgDep) { - outPar << stgdept << "yes" << endl; - outPar << indvar << "no" << endl; - for (int i = 0; i < sstruct.nStages; i++) { - kern0 = pSpecies->getKernTraits(i,0); - outPar << "stage " << i << ": \t" << meandist << " I: " << kern0.meanDist1; - if (trfr.twinKern) - { - outPar << " \t" << meandist << " II: " << kern0.meanDist2; - outPar << " \t" << probkern << ": " << kern0.probKern1; + else { + outPar << "no" << endl; + kern0 = pSpecies->getKernTraits(0, 0); + kern1 = pSpecies->getKernTraits(0, 1); + outPar << meandist << " I: \tfemales " << kern0.meanDist1 << " \tmales " << kern1.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \tfemales " << kern0.meanDist2 << " \tmales " << kern1.meanDist2 << endl; + outPar << probkern << ": \tfemales " << kern0.probKern1 << " \tmales " << kern1.probKern1 << endl; + } } - outPar << endl; } } - else { // !trfr.stgDep - outPar << stgdept << "no" << endl; - outPar << indvar; - if (trfr.indVar) { - k0 = pSpecies->getKernParams(0,0); - outPar << "yes" << endl; - outPar << meandist << " I (mean): " << k0.dist1Mean - << " \t(s.d.): " << k0.dist1SD - << " \t(scaling factor): " << k0.dist1Scale << endl; - if (trfr.twinKern) - { - outPar << meandist << " II (mean): " << k0.dist2Mean - << " \t(s.d.): " << k0.dist2SD - << " \t(scaling factor): " << k0.dist2Scale << endl; - outPar << probkern << " (mean): " << k0.PKern1Mean - << " \t(s.d.): " << k0.PKern1SD - << " \t(scaling factor): " << k0.PKern1Scale << endl; + else { // !trfr.sexDep + outPar << sexdept << "no" << endl; + if (trfr.stgDep) { + outPar << stgdept << "yes" << endl; + outPar << indvar << "no" << endl; + for (int i = 0; i < sstruct.nStages; i++) { + kern0 = pSpecies->getKernTraits(i, 0); + outPar << "stage " << i << ": \t" << meandist << " I: " << kern0.meanDist1; + if (trfr.twinKern) + { + outPar << " \t" << meandist << " II: " << kern0.meanDist2; + outPar << " \t" << probkern << ": " << kern0.probKern1; + } + outPar << endl; } } - else{ - outPar << "no" << endl; - kern0 = pSpecies->getKernTraits(0,0); - outPar << meandist << " I: \t" << kern0.meanDist1 <getKernParams(0, 0); + outPar << "yes" << endl; + outPar << meandist << " I (mean): " << k0.dist1Mean + << " \t(s.d.): " << k0.dist1SD + << " \t(scaling factor): " << k0.dist1Scale << endl; + if (trfr.twinKern) + { + outPar << meandist << " II (mean): " << k0.dist2Mean + << " \t(s.d.): " << k0.dist2SD + << " \t(scaling factor): " << k0.dist2Scale << endl; + outPar << probkern << " (mean): " << k0.PKern1Mean + << " \t(s.d.): " << k0.PKern1SD + << " \t(scaling factor): " << k0.PKern1Scale << endl; + } + } + else { + outPar << "no" << endl; + kern0 = pSpecies->getKernTraits(0, 0); + outPar << meandist << " I: \t" << kern0.meanDist1 << endl; + if (trfr.twinKern) + { + outPar << meandist << " II: \t" << kern0.meanDist2 << endl; + outPar << probkern << ": \t" << kern0.probKern1 << endl; + } } } } - } - outPar << "DISPERSAL MORTALITY: "; - trfrMortParams mort = pSpecies->getMortParams(); - if (trfr.distMort) { - outPar << "distance-dependent" << endl; - outPar << "SLOPE: " << mort.mortAlpha << " \tINFLECTION POINT: " << mort.mortBeta << endl; - } - else { - outPar << "constant" << endl << "MORTALITY PROBABILITY: " << mort.fixedMort << endl; - } -} // end of kernel transfer + outPar << "DISPERSAL MORTALITY: "; + trfrMortParams mort = pSpecies->getMortParams(); + if (trfr.distMort) { + outPar << "distance-dependent" << endl; + outPar << "SLOPE: " << mort.mortAlpha << " \tINFLECTION POINT: " << mort.mortBeta << endl; + } + else { + outPar << "constant" << endl << "MORTALITY PROBABILITY: " << mort.fixedMort << endl; + } + } // end of kernel transfer -// Settlement + // Settlement -outPar << endl << "DISPERSAL - SETTLEMENT:" << endl; + outPar << endl << "DISPERSAL - SETTLEMENT:" << endl; -if (trfr.moveModel) { - string plusmating = "+ mating requirements"; - ssteps = pSpecies->getSteps(0,0); + if (trfr.moveModel) { + string plusmating = "+ mating requirements"; + ssteps = pSpecies->getSteps(0, 0); - outPar << "MIN. No. OF STEPS:\t " << ssteps.minSteps << endl; - outPar << "MAX. No. OF STEPS:\t "; - if (ssteps.maxSteps == 99999999) outPar << "not applied" << endl; - else outPar << ssteps.maxSteps << endl; + outPar << "MIN. No. OF STEPS:\t " << ssteps.minSteps << endl; + outPar << "MAX. No. OF STEPS:\t "; + if (ssteps.maxSteps == 99999999) outPar << "not applied" << endl; + else outPar << ssteps.maxSteps << endl; - if (sett.sexDep) { - nsexes = 2; - outPar << sexdept << "yes" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - } - else { // !sett.stgDep - nstages = 1; - outPar << stgdept << "no" << endl; - } - } - else { // !sett.sexDep - nsexes = 1; - outPar << sexdept << "no" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - } - else { // !sett.stgDep - nstages = 1; - outPar << stgdept << "no" << endl; - } - } - for (int sx = 0; sx < nsexes; sx++) { if (sett.sexDep) { - if (sx == 0) outPar << "FEMALES:" << endl; - else outPar << "MALES:" << endl; - } - outPar << "SETTLE IF: "; - for (int i = 0; i < nstages; i++) { - if (dem.stageStruct && nstages > 1) outPar << "stage " << i << ": " << endl; - outPar << "find a suitable cell/patch "; - srules = pSpecies->getSettRules(i,sx); - if (srules.densDep) { - settleDD = pSpecies->getSettTraits(i,sx); - outPar << "+ density dependence "; - if (srules.findMate) outPar << plusmating; - outPar << endl; - if (!sett.indVar) { - outPar << "S0: " << settleDD.s0 << " AlphaS: " << settleDD.alpha - << " BetaS: " << settleDD.beta << endl; - } + nsexes = 2; + outPar << sexdept << "yes" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; } - else { - if (srules.findMate) outPar << plusmating << endl; - else outPar << "(not the natal one)" << endl; + else { // !sett.stgDep + nstages = 1; + outPar << stgdept << "no" << endl; } - if (dem.stageStruct) { - ssteps = pSpecies->getSteps(i,sx); - outPar << "MAX. No. OF STEPS/YEAR:\t "; - if (ssteps.maxStepsYr == 99999999) outPar << "not applied" << endl; - else outPar << ssteps.maxStepsYr << endl; + } + else { // !sett.sexDep + nsexes = 1; + outPar << sexdept << "no" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; + } + else { // !sett.stgDep + nstages = 1; + outPar << stgdept << "no" << endl; } } - } - if (sett.indVar) { - settParams sparams0; - outPar << "DENSITY DEPENDENCE + " << indvar << "yes" << endl; - for (int sex = 0; sex < nsexes; sex++) { + for (int sx = 0; sx < nsexes; sx++) { if (sett.sexDep) { - if (sex == 0) outPar << "FEMALES:" << endl; + if (sx == 0) outPar << "FEMALES:" << endl; else outPar << "MALES:" << endl; } - sparams0 = pSpecies->getSettParams(0,sex); - settScales scale = pSpecies->getSettScales(); - outPar << "S0 - mean: " << sparams0.s0Mean << " s.d.: " << sparams0.s0SD - << " scaling factor: " << scale.s0Scale << endl; - outPar << "AlphaS - mean: " << sparams0.alphaSMean << " s.d.: " << sparams0.alphaSSD - << " scaling factor: " << scale.alphaSScale << endl; - outPar << "BetaS - mean: " << sparams0.betaSMean << " s.d.: " << sparams0.betaSSD - << " scaling factor: " << scale.betaSScale << endl; - } - } -} -else { // kernel-based transfer - string notsuit = "IF THE ARRIVAL CELL/PATCH IS UNSUITABLE: "; - string rchoose = " randomly choose a suitable neighb. cell/patch or "; - string matereq = "MATING REQUIREMENTS: "; - if (sett.sexDep) { - nsexes = 2; - outPar << sexdept << "yes" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - outPar << notsuit << endl; + outPar << "SETTLE IF: "; + for (int i = 0; i < nstages; i++) { + if (dem.stageStruct && nstages > 1) outPar << "stage " << i << ": " << endl; + outPar << "find a suitable cell/patch "; + srules = pSpecies->getSettRules(i, sx); + if (srules.densDep) { + settleDD = pSpecies->getSettTraits(i, sx); + outPar << "+ density dependence "; + if (srules.findMate) outPar << plusmating; + outPar << endl; + if (!sett.indVar) { + outPar << "S0: " << settleDD.s0 << " AlphaS: " << settleDD.alpha + << " BetaS: " << settleDD.beta << endl; + } + } + else { + if (srules.findMate) outPar << plusmating << endl; + else outPar << "(not the natal one)" << endl; + } + if (dem.stageStruct) { + ssteps = pSpecies->getSteps(i, sx); + outPar << "MAX. No. OF STEPS/YEAR:\t "; + if (ssteps.maxStepsYr == 99999999) outPar << "not applied" << endl; + else outPar << ssteps.maxStepsYr << endl; + } + } } - else { - nstages = 1; - outPar << stgdept << "no" << endl; + if (sett.indVar) { + settParams sparams0; + outPar << "DENSITY DEPENDENCE + " << indvar << "yes" << endl; + for (int sex = 0; sex < nsexes; sex++) { + if (sett.sexDep) { + if (sex == 0) outPar << "FEMALES:" << endl; + else outPar << "MALES:" << endl; + } + sparams0 = pSpecies->getSettParams(0, sex); + settScales scale = pSpecies->getSettScales(); + outPar << "S0 - mean: " << sparams0.s0Mean << " s.d.: " << sparams0.s0SD + << " scaling factor: " << scale.s0Scale << endl; + outPar << "AlphaS - mean: " << sparams0.alphaSMean << " s.d.: " << sparams0.alphaSSD + << " scaling factor: " << scale.alphaSScale << endl; + outPar << "BetaS - mean: " << sparams0.betaSMean << " s.d.: " << sparams0.betaSSD + << " scaling factor: " << scale.betaSScale << endl; + } } } - else { - nsexes = 1; - outPar << sexdept << "no" << endl; - if (sett.stgDep) { - nstages = sstruct.nStages; - outPar << stgdept << "yes" << endl; - outPar << notsuit << endl; + else { // kernel-based transfer + string notsuit = "IF THE ARRIVAL CELL/PATCH IS UNSUITABLE: "; + string rchoose = " randomly choose a suitable neighb. cell/patch or "; + string matereq = "MATING REQUIREMENTS: "; + if (sett.sexDep) { + nsexes = 2; + outPar << sexdept << "yes" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; + outPar << notsuit << endl; + } + else { + nstages = 1; + outPar << stgdept << "no" << endl; + } } else { - nstages = 1; - outPar << stgdept << "no" << endl; - outPar << notsuit; - } - } - for (int i = 0; i < nstages; i++) { - if (sett.stgDep) { - outPar << "stage " << i << ":" << endl; - } - for (int sx = 0; sx < nsexes; sx++) { - if (sett.sexDep) { - if (sx == 0) outPar << "FEMALES: "; - else outPar << "MALES: "; - if (!sett.stgDep) outPar << notsuit; - } - srules = pSpecies->getSettRules(i,sx); - if (srules.go2nbrLocn) { - outPar << rchoose; - if (srules.wait) outPar << "wait" << endl; - else outPar << "die" << endl; + nsexes = 1; + outPar << sexdept << "no" << endl; + if (sett.stgDep) { + nstages = sstruct.nStages; + outPar << stgdept << "yes" << endl; + outPar << notsuit << endl; } else { - if (srules.wait) outPar << "wait" << endl; - else outPar << "die" << endl; + nstages = 1; + outPar << stgdept << "no" << endl; + outPar << notsuit; + } + } + for (int i = 0; i < nstages; i++) { + if (sett.stgDep) { + outPar << "stage " << i << ":" << endl; + } + for (int sx = 0; sx < nsexes; sx++) { + if (sett.sexDep) { + if (sx == 0) outPar << "FEMALES: "; + else outPar << "MALES: "; + if (!sett.stgDep) outPar << notsuit; + } + srules = pSpecies->getSettRules(i, sx); + if (srules.go2nbrLocn) { + outPar << rchoose; + if (srules.wait) outPar << "wait" << endl; + else outPar << "die" << endl; + } + else { + if (srules.wait) outPar << "wait" << endl; + else outPar << "die" << endl; + } + outPar << matereq; + if (srules.findMate) outPar << "yes" << endl; + else outPar << "no" << endl; } - outPar << matereq; - if (srules.findMate) outPar << "yes" <getNTraits(); -outPar << "No. of variable traits: " << nspptraits << endl; + outPar << endl << "GENETICS:" << endl; + int nspptraits = pSpecies->getNTraits(); + outPar << "No. of variable traits: " << nspptraits << endl; -genomeData d = pSpecies->getGenomeData(); -if (emig.indVar || trfr.indVar || sett.indVar || d.neutralMarkers) -{ - if (d.diploid) outPar << "DIPLOID" << endl; else outPar << "HAPLOID" << endl; - int nchromosomes = pSpecies->getNChromosomes(); - outPar << "No. of chromosomes: " << nchromosomes; - if (d.trait1Chromosome) { - outPar << endl << "No. of loci/chromosome: " << d.nLoci << endl; - } - else { - outPar << " (chrom:loci)"; - for (int i = 0; i < nchromosomes; i++) { - outPar << " " << i << ":" << pSpecies->getNLoci(i); + genomeData d = pSpecies->getGenomeData(); + if (emig.indVar || trfr.indVar || sett.indVar || d.neutralMarkers) + { + if (d.diploid) outPar << "DIPLOID" << endl; else outPar << "HAPLOID" << endl; + int nchromosomes = pSpecies->getNChromosomes(); + outPar << "No. of chromosomes: " << nchromosomes; + if (d.trait1Chromosome) { + outPar << endl << "No. of loci/chromosome: " << d.nLoci << endl; } - outPar << endl; - } - outPar << "Mutation probability: " << d.probMutn << endl; - outPar << "Crossover probability: " << d.probCrossover << endl; - outPar << "Initial allele s.d.: " << d.alleleSD << endl; - outPar << "Mutation s.d.: " << d.mutationSD << endl; - if (d.neutralMarkers) { - outPar << "NEUTRAL MARKERS ONLY" << endl; - } - else { - if (!d.trait1Chromosome) { - traitAllele allele; - outPar << "TRAIT MAPPING:" << endl; - outPar << "Architecture file: " << genfilename << endl; - int ntraitmaps = pSpecies->getNTraitMaps(); - outPar << "No. of traits defined: " << ntraitmaps << endl; - for (int i = 0; i < ntraitmaps; i++) { - int nalleles = pSpecies->getNTraitAlleles(i); - outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) - << ") alleles: " << nalleles << " (chrom:locus)"; - for (int j = 0; j < nalleles; j++) { - allele = pSpecies->getTraitAllele(i,j); - outPar << " " << allele.chromo << ":" << allele.locus; - } - outPar << endl; + else { + outPar << " (chrom:loci)"; + for (int i = 0; i < nchromosomes; i++) { + outPar << " " << i << ":" << pSpecies->getNLoci(i); } - if (ntraitmaps < nspptraits) { // list undefined traits - outPar << "WARNING - the following traits were not defined" - << " in the genetic architecture file:" << endl; - for (int i = ntraitmaps; i < nspptraits; i++) { + outPar << endl; + } + outPar << "Mutation probability: " << d.probMutn << endl; + outPar << "Crossover probability: " << d.probCrossover << endl; + outPar << "Initial allele s.d.: " << d.alleleSD << endl; + outPar << "Mutation s.d.: " << d.mutationSD << endl; + if (d.neutralMarkers) { + outPar << "NEUTRAL MARKERS ONLY" << endl; + } + else { + if (!d.trait1Chromosome) { + traitAllele allele; + outPar << "TRAIT MAPPING:" << endl; + outPar << "Architecture file: " << genfilename << endl; + int ntraitmaps = pSpecies->getNTraitMaps(); + outPar << "No. of traits defined: " << ntraitmaps << endl; + for (int i = 0; i < ntraitmaps; i++) { + int nalleles = pSpecies->getNTraitAlleles(i); outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) - << ") all individuals have mean phenotype" << endl; + << ") alleles: " << nalleles << " (chrom:locus)"; + for (int j = 0; j < nalleles; j++) { + allele = pSpecies->getTraitAllele(i, j); + outPar << " " << allele.chromo << ":" << allele.locus; + } + outPar << endl; } - } - int nneutral = pSpecies->getNNeutralLoci(); - if (nneutral > 0) { - outPar << "Neutral loci: " << nneutral << " (chrom:locus)"; - for (int i = 0; i < nneutral; i++) { - allele = pSpecies->getNeutralAllele(i); - outPar << " " << allele.chromo << ":" << allele.locus; + if (ntraitmaps < nspptraits) { // list undefined traits + outPar << "WARNING - the following traits were not defined" + << " in the genetic architecture file:" << endl; + for (int i = ntraitmaps; i < nspptraits; i++) { + outPar << "Trait " << i << ": (" << pSpecies->getTraitName(i) + << ") all individuals have mean phenotype" << endl; + } } - outPar << endl; + int nneutral = pSpecies->getNNeutralLoci(); + if (nneutral > 0) { + outPar << "Neutral loci: " << nneutral << " (chrom:locus)"; + for (int i = 0; i < nneutral; i++) { + allele = pSpecies->getNeutralAllele(i); + outPar << " " << allele.chromo << ":" << allele.locus; + } + outPar << endl; + } + if (d.pleiotropic) + outPar << "Genome exhibits pleiotropy" << endl; } - if (d.pleiotropic) - outPar << "Genome exhibits pleiotropy" << endl; } } -} -// Initialisation + // Initialisation -initParams init = paramsInit->getInit(); -outPar << endl << "INITIALISATION CONDITIONS:" << endl; -switch (init.seedType) { -case 0: - outPar << "Free initialisation: \t" ; - switch (init.freeType) { + initParams init = paramsInit->getInit(); + outPar << endl << "INITIALISATION CONDITIONS:" << endl; + switch (init.seedType) { case 0: - outPar << "Random \t" ; - outPar << "No. of cells/patches: " << init.nSeedPatches << endl; + outPar << "Free initialisation: \t"; + switch (init.freeType) { + case 0: + outPar << "Random \t"; + outPar << "No. of cells/patches: " << init.nSeedPatches << endl; + break; + case 1: + outPar << "all suitable cells/patches" << endl; + break; + case 2: + outPar << "manually selected cells/patches" << endl; + break; + } break; case 1: - outPar << "all suitable cells/patches" << endl; - break; - case 2: - outPar << "manually selected cells/patches" << endl; - break; - } - break; -case 1: - outPar << "From species distribution: \t" << endl; - switch (init.spDistType) { + outPar << "From species distribution: \t" << endl; + switch (init.spDistType) { case 0: outPar << "all presence cells/patches" << endl; break; @@ -2095,139 +1928,134 @@ case 1: case 2: outPar << "all cells/patches within selected distribution cells" << endl; break; - } - break; -case 2: - outPar << "From initial individuals file: " << paramsSim->getDir(1) + init.indsFile << endl; - break; -case 3: - outPar << "From file" << endl; - break; -} -if (init.seedType != 2) { - outPar << "INITIAL NO. OF INDIVIDUALS: \t"; - switch (init.initDens) { - case 0: - outPar << "at carrying capacity" << endl; - break; - case 1: - outPar << "at half carrying capacity" << endl; + } break; case 2: - if (ppLand.patchModel) { - outPar << init.indsHa << " individuals per ha" << endl; - } - else { - outPar << init.indsCell << " individuals per cell" << endl; - } + outPar << "From initial individuals file: " << paramsSim->getDir(1) + init.indsFile << endl; + break; + case 3: + outPar << "From file" << endl; break; } - if (dem.stageStruct) { - outPar << "INITIAL STAGE PROPORTIONS:" << endl; - for (int i = 1; i < sstruct.nStages; i++) { - outPar << "stage " << i << ": " << paramsInit->getProp(i) << " \t"; - } - outPar << endl; - outPar << "Initial age distribution: "; - switch (init.initAge) { + if (init.seedType != 2) { + outPar << "INITIAL NO. OF INDIVIDUALS: \t"; + switch (init.initDens) { case 0: - outPar << "lowest possible age"; + outPar << "at carrying capacity" << endl; break; case 1: - outPar << "randomised"; + outPar << "at half carrying capacity" << endl; break; case 2: - outPar << "quasi-equilibrium"; + if (ppLand.patchModel) { + outPar << init.indsHa << " individuals per ha" << endl; + } + else { + outPar << init.indsCell << " individuals per cell" << endl; + } break; } - outPar << endl; - } - outPar << "GEOGRAPHICAL CONSTRAINTS (cell numbers): " << endl; - outPar << "min X: " << init.minSeedX << " max X: " << init.maxSeedX << endl; - outPar << "min Y: " << init.minSeedY << " max Y: " << init.maxSeedY << endl; -// if (init.seedType != 1 && init.freeType < 2 && init.initFrzYr > 0) { -// outPar << "Freeze initial range until year " << init.initFrzYr << endl; -// } - if (init.seedType == 0 && init.freeType < 2) { - if (init.initFrzYr > 0) { - outPar << "Freeze initial range until year " << init.initFrzYr << endl; - } - if (init.restrictRange) { - outPar << "Restrict range to northern " << init.restrictRows - << " rows every " << init.restrictFreq << " years" << endl; - if (init.finalFrzYr < sim.years) { - outPar << "Freeze range at year " << init.finalFrzYr << endl; + if (dem.stageStruct) { + outPar << "INITIAL STAGE PROPORTIONS:" << endl; + for (int i = 1; i < sstruct.nStages; i++) { + outPar << "stage " << i << ": " << paramsInit->getProp(i) << " \t"; + } + outPar << endl; + outPar << "Initial age distribution: "; + switch (init.initAge) { + case 0: + outPar << "lowest possible age"; + break; + case 1: + outPar << "randomised"; + break; + case 2: + outPar << "quasi-equilibrium"; + break; + } + outPar << endl; + } + outPar << "GEOGRAPHICAL CONSTRAINTS (cell numbers): " << endl; + outPar << "min X: " << init.minSeedX << " max X: " << init.maxSeedX << endl; + outPar << "min Y: " << init.minSeedY << " max Y: " << init.maxSeedY << endl; + if (init.seedType == 0 && init.freeType < 2) { + if (init.initFrzYr > 0) { + outPar << "Freeze initial range until year " << init.initFrzYr << endl; + } + if (init.restrictRange) { + outPar << "Restrict range to northern " << init.restrictRows + << " rows every " << init.restrictFreq << " years" << endl; + if (init.finalFrzYr < sim.years) { + outPar << "Freeze range at year " << init.finalFrzYr << endl; + } } } } -} -outPar << endl << "OUTPUTS:" << endl; -if (sim.outRange) { - outPar << "Range - every " << sim.outIntRange << " year"; - if (sim.outIntRange > 1) outPar << "s"; -// if (sim.outStartRange > 0) outPar << " starting year " << sim.outStartRange; - outPar << endl; -} -if (sim.outOccup) { - outPar << "Occupancy - every " << sim.outIntOcc << " year"; - if (sim.outIntOcc > 1) outPar << "s"; -// if (sim.outStartOcc > 0) outPar << " starting year " << sim.outStartOcc; - outPar << endl; -} -if (sim.outPop) { - outPar << "Populations - every " << sim.outIntPop << " year"; - if (sim.outIntPop > 1) outPar << "s"; - if (sim.outStartPop > 0) outPar << " starting year " << sim.outStartPop; - outPar << endl; -} -if (sim.outInds) { - outPar << "Individuals - every " << sim.outIntInd << " year"; - if (sim.outIntInd > 1) outPar << "s"; - if (sim.outStartInd > 0) outPar << " starting year " << sim.outStartInd; - outPar << endl; -} -if (sim.outGenetics) { - outPar << "Genetics - every " << sim.outIntGenetic << " year"; - if (sim.outIntGenetic > 1) outPar << "s"; - if (sim.outStartGenetic > 0) outPar << " starting year " << sim.outStartGenetic; - if (dem.stageStruct) { - switch (sim.outGenType) { - case 0: - outPar << " - juveniles only"; - break; - case 1: - outPar << " - all individuals"; - break; - case 2: - outPar << " - adults only"; - break; + outPar << endl << "OUTPUTS:" << endl; + if (sim.outRange) { + outPar << "Range - every " << sim.outIntRange << " year"; + if (sim.outIntRange > 1) outPar << "s"; + outPar << endl; + } + if (sim.outOccup) { + outPar << "Occupancy - every " << sim.outIntOcc << " year"; + if (sim.outIntOcc > 1) outPar << "s"; + outPar << endl; + } + if (sim.outPop) { + outPar << "Populations - every " << sim.outIntPop << " year"; + if (sim.outIntPop > 1) outPar << "s"; + if (sim.outStartPop > 0) outPar << " starting year " << sim.outStartPop; + outPar << endl; + } + if (sim.outInds) { + outPar << "Individuals - every " << sim.outIntInd << " year"; + if (sim.outIntInd > 1) outPar << "s"; + if (sim.outStartInd > 0) outPar << " starting year " << sim.outStartInd; + outPar << endl; + } + if (sim.outGenetics) { + outPar << "Genetics - every " << sim.outIntGenetic << " year"; + if (sim.outIntGenetic > 1) outPar << "s"; + if (sim.outStartGenetic > 0) outPar << " starting year " << sim.outStartGenetic; + if (dem.stageStruct) { + switch (sim.outGenType) { + case 0: + outPar << " - juveniles only"; + break; + case 1: + outPar << " - all individuals"; + break; + case 2: + outPar << " - adults only"; + break; + } } + if (sim.outGenXtab) outPar << " (as cross table)"; + outPar << endl; } - if (sim.outGenXtab) outPar << " (as cross table)"; - outPar << endl; -} -if (sim.outTraitsCells) { - outPar << "Traits per "; - if (ppLand.patchModel) outPar << "patch"; else outPar << "cell"; - outPar << " - every " << sim.outIntTraitCell << " year"; - if (sim.outIntTraitCell > 1) outPar << "s"; - if (sim.outStartTraitCell > 0) outPar << " starting year " << sim.outStartTraitCell; - outPar << endl; -} -if (sim.outTraitsRows) { - outPar << "Traits per row - every " << sim.outIntTraitRow << " year"; - if (sim.outIntTraitRow > 1) outPar << "s"; - if (sim.outStartTraitRow > 0) outPar << " starting year " << sim.outStartTraitRow; - outPar << endl; -} -if (sim.outConnect) { - outPar << "Connectivity matrix - every " << sim.outIntConn << " year"; - if (sim.outIntConn > 1) outPar << "s"; - if (sim.outStartConn > 0) outPar << " starting year " << sim.outStartConn; - outPar << endl; -} + if (sim.outTraitsCells) { + outPar << "Traits per "; + if (ppLand.patchModel) outPar << "patch"; else outPar << "cell"; + outPar << " - every " << sim.outIntTraitCell << " year"; + if (sim.outIntTraitCell > 1) outPar << "s"; + if (sim.outStartTraitCell > 0) outPar << " starting year " << sim.outStartTraitCell; + outPar << endl; + } + if (sim.outTraitsRows) { + outPar << "Traits per row - every " << sim.outIntTraitRow << " year"; + if (sim.outIntTraitRow > 1) outPar << "s"; + if (sim.outStartTraitRow > 0) outPar << " starting year " << sim.outStartTraitRow; + outPar << endl; + } + if (sim.outConnect) { + outPar << "Connectivity matrix - every " << sim.outIntConn << " year"; + if (sim.outIntConn > 1) outPar << "s"; + if (sim.outStartConn > 0) outPar << " starting year " << sim.outStartConn; + outPar << endl; + } #if RS_RCPP if (sim.outPaths) { outPar << "SMS paths - every " << sim.outIntPaths << " year"; @@ -2236,27 +2064,27 @@ if (sim.outConnect) { outPar << endl; } #endif -outPar << "SAVE MAPS: "; -if (sim.saveMaps) { - outPar << "yes - every " << sim.mapInt << " year"; - if (sim.mapInt > 1) outPar << "s"; - outPar << endl; -} -else outPar << "no" << endl; -outPar << "SAVE TRAITS MAPS: "; -if (sim.saveTraitMaps) { - outPar << "yes - every " << sim.traitInt << " year"; - if (sim.traitInt > 1) outPar << "s"; - outPar << endl; -} -else outPar << "no" << endl; -if (trfr.moveModel && trfr.moveType == 1) { - outPar << "SMS HEAT MAPS: "; - if (sim.saveVisits) outPar << "yes" << endl; + outPar << "SAVE MAPS: "; + if (sim.saveMaps) { + outPar << "yes - every " << sim.mapInt << " year"; + if (sim.mapInt > 1) outPar << "s"; + outPar << endl; + } else outPar << "no" << endl; -} + outPar << "SAVE TRAITS MAPS: "; + if (sim.saveTraitMaps) { + outPar << "yes - every " << sim.traitInt << " year"; + if (sim.traitInt > 1) outPar << "s"; + outPar << endl; + } + else outPar << "no" << endl; + if (trfr.moveModel && trfr.moveType == 1) { + outPar << "SMS HEAT MAPS: "; + if (sim.saveVisits) outPar << "yes" << endl; + else outPar << "no" << endl; + } -outPar.close(); outPar.clear(); + outPar.close(); outPar.clear(); } diff --git a/Parameters.cpp b/Parameters.cpp index b7c6a34..5cfb3d7 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -1,26 +1,26 @@ /*---------------------------------------------------------------------------- - * - * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell - * + * + * Copyright (C) 2020 Greta Bocedi, Stephen C.F. Palmer, Justin M.J. Travis, Anne-Kathleen Malchow, Damaris Zurell + * * This file is part of RangeShifter. - * + * * RangeShifter is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RangeShifter is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with RangeShifter. If not, see . - * + * --------------------------------------------------------------------------*/ - - -//--------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------- #include "Parameters.h" //--------------------------------------------------------------------------- @@ -30,34 +30,34 @@ // Environmental gradient parameters paramGrad::paramGrad(void) { -gradient = false; gradType = 0; grad_inc = 0.05f; -opt_y0 = opt_y = factor = extProbOpt = 0.0; -shifting = false; shift_rate = 0.5; shift_begin = 0; shift_stop = 100; + gradient = false; gradType = 0; grad_inc = 0.05f; + opt_y0 = opt_y = factor = extProbOpt = 0.0; + shifting = false; shift_rate = 0.5; shift_begin = 0; shift_stop = 100; } paramGrad::~paramGrad() { } void paramGrad::setGradient(int gtype, float inc, float y, float f, float p) { -if (gtype > 0 && gtype < 4) -{ // valid gradient type - gradient = true; gradType = gtype; - if (inc >= 0.0 && inc <= 1.0) grad_inc = inc; - if (y >= 0.0) opt_y0 = opt_y = y; - if (f >= 0.0) factor = f; - if (p > 0.0 && p < 1.0) extProbOpt = p; -} -else { - gradient = false; gradType = 0; -} + if (gtype > 0 && gtype < 4) + { // valid gradient type + gradient = true; gradType = gtype; + if (inc >= 0.0 && inc <= 1.0) grad_inc = inc; + if (y >= 0.0) opt_y0 = opt_y = y; + if (f >= 0.0) factor = f; + if (p > 0.0 && p < 1.0) extProbOpt = p; + } + else { + gradient = false; gradType = 0; + } } void paramGrad::setShifting(float r, int begin, int end) { -shifting = true; -if (r > 0.0) shift_rate = r; -if (begin >= 0) shift_begin = begin; -if (end > 0) shift_stop = end; + shifting = true; + if (r > 0.0) shift_rate = r; + if (begin >= 0) shift_begin = begin; + if (end > 0) shift_stop = end; } void paramGrad::noGradient(void) { gradient = false; gradType = 0; } @@ -65,16 +65,18 @@ void paramGrad::noGradient(void) { gradient = false; gradType = 0; } void paramGrad::noShifting(void) { shifting = false; } envGradParams paramGrad::getGradient(void) { -envGradParams g; -g.gradient = gradient; g.gradType = gradType; g.grad_inc = grad_inc; -g.opt_y = opt_y; g.factor = factor; g.extProbOpt = extProbOpt; -g.shifting = shifting; g.shift_rate = shift_rate; -g.shift_begin = shift_begin; g.shift_stop = shift_stop; -return g; + envGradParams g; + g.gradient = gradient; g.gradType = gradType; g.grad_inc = grad_inc; + g.opt_y = opt_y; g.factor = factor; g.extProbOpt = extProbOpt; + g.shifting = shifting; g.shift_rate = shift_rate; + g.shift_begin = shift_begin; g.shift_stop = shift_stop; + return g; } void paramGrad::incrOptY(void) -{ if (gradient && shifting) opt_y += shift_rate; } +{ + if (gradient && shifting) opt_y += shift_rate; +} void paramGrad::resetOptY(void) { opt_y = opt_y0; } @@ -83,9 +85,9 @@ void paramGrad::resetOptY(void) { opt_y = opt_y0; } // Environmental stochasticity parameters paramStoch::paramStoch(void) { -stoch = false; local = false; inK = false; localExt = false; -ac = 0.0; std = 0.25; -locExtProb = 0.1; + stoch = false; local = false; inK = false; localExt = false; + ac = 0.0; std = 0.25; + locExtProb = 0.1; } paramStoch::~paramStoch(void) {} @@ -93,21 +95,21 @@ paramStoch::~paramStoch(void) {} void paramStoch::setStoch(envStochParams e) { -stoch = e.stoch; local = e.local; inK = e.inK; localExt = e.localExt; -if (e.ac >= 0.0 && e.ac < 1.0) ac = e.ac; -if (e.std > 0.0 && e.std <= 1.0) std = e.std; -locExtProb = e.locExtProb; + stoch = e.stoch; local = e.local; inK = e.inK; localExt = e.localExt; + if (e.ac >= 0.0 && e.ac < 1.0) ac = e.ac; + if (e.std > 0.0 && e.std <= 1.0) std = e.std; + locExtProb = e.locExtProb; } bool paramStoch::envStoch(void) { return stoch; } envStochParams paramStoch::getStoch(void) { -envStochParams e; -e.stoch = stoch; e.local = local; e.inK = inK; e.localExt = localExt; -e.ac = ac; e.std = std; -e.locExtProb = locExtProb; -return e; + envStochParams e; + e.stoch = stoch; e.local = local; e.inK = inK; e.localExt = localExt; + e.ac = ac; e.std = std; + e.locExtProb = locExtProb; + return e; } @@ -116,100 +118,87 @@ return e; // Initialisation (seeding) parameters paramInit::paramInit(void) { -seedType = freeType = spDistType = initDens = 0; -initAge = initFrzYr = 0; -restrictRange = false; -restrictRows = 100; -restrictFreq = 10; -finalFrzYr = 99999999; -indsCell = 1; indsHa = 0.0; -minSeedX = 0; maxSeedX = 99999999; minSeedY = 0; maxSeedY = 99999999; -nSeedPatches = 1; nSpDistPatches = 1; -indsFile = "NULL"; -for (int i = 0; i < NSTAGES; i++) { - initProp[i] = 0.0; -} + seedType = freeType = spDistType = initDens = 0; + initAge = initFrzYr = 0; + restrictRange = false; + restrictRows = 100; + restrictFreq = 10; + finalFrzYr = 99999999; + indsCell = 1; indsHa = 0.0; + minSeedX = 0; maxSeedX = 99999999; minSeedY = 0; maxSeedY = 99999999; + nSeedPatches = 1; nSpDistPatches = 1; + indsFile = "NULL"; + for (int i = 0; i < NSTAGES; i++) { + initProp[i] = 0.0; + } } paramInit::~paramInit(void) { -initinds.clear(); + initinds.clear(); } void paramInit::setInit(initParams i) { -if (i.seedType >= 0 && i.seedType <= 3) seedType = i.seedType; -if (i.freeType >= 0 && i.freeType <= 2) freeType = i.freeType; -if (i.spDistType >= 0 && i.spDistType <= 2) spDistType = i.spDistType; -initDens = i.initDens; -initAge = i.initAge; -if (i.initFrzYr >= 0) initFrzYr = i.initFrzYr; -restrictRange = i.restrictRange; -if (i.restrictRows > 0) restrictRows = i.restrictRows; -if (i.restrictFreq > 0) restrictFreq = i.restrictFreq; -if (i.finalFrzYr > 0) finalFrzYr = i.finalFrzYr; -if (i.indsCell >= 1) indsCell = i.indsCell; -if (i.indsHa > 0.0) indsHa = i.indsHa; -if (i.minSeedX >= 0) minSeedX = i.minSeedX; -if (i.maxSeedX >= 0) maxSeedX = i.maxSeedX; -if (i.minSeedY >= 0) minSeedY = i.minSeedY; -if (i.maxSeedY >= 0) maxSeedY = i.maxSeedY; -if (i.nSeedPatches >= 1) nSeedPatches = i.nSeedPatches; -if (i.nSpDistPatches >= 1) nSpDistPatches = i.nSpDistPatches; -indsFile = i.indsFile; + if (i.seedType >= 0 && i.seedType <= 3) seedType = i.seedType; + if (i.freeType >= 0 && i.freeType <= 2) freeType = i.freeType; + if (i.spDistType >= 0 && i.spDistType <= 2) spDistType = i.spDistType; + initDens = i.initDens; + initAge = i.initAge; + if (i.initFrzYr >= 0) initFrzYr = i.initFrzYr; + restrictRange = i.restrictRange; + if (i.restrictRows > 0) restrictRows = i.restrictRows; + if (i.restrictFreq > 0) restrictFreq = i.restrictFreq; + if (i.finalFrzYr > 0) finalFrzYr = i.finalFrzYr; + if (i.indsCell >= 1) indsCell = i.indsCell; + if (i.indsHa > 0.0) indsHa = i.indsHa; + if (i.minSeedX >= 0) minSeedX = i.minSeedX; + if (i.maxSeedX >= 0) maxSeedX = i.maxSeedX; + if (i.minSeedY >= 0) minSeedY = i.minSeedY; + if (i.maxSeedY >= 0) maxSeedY = i.maxSeedY; + if (i.nSeedPatches >= 1) nSeedPatches = i.nSeedPatches; + if (i.nSpDistPatches >= 1) nSpDistPatches = i.nSpDistPatches; + indsFile = i.indsFile; } initParams paramInit::getInit(void) { -initParams i; -i.seedType = seedType; i.freeType = freeType; i.spDistType = spDistType; -i.initDens = initDens; i.initAge = initAge; -i.initFrzYr = initFrzYr; -i.restrictRange = restrictRange; -i.restrictRows = restrictRows; i.restrictFreq = restrictFreq; -i.finalFrzYr = finalFrzYr; -i.indsCell = indsCell; i.indsHa = indsHa; -i.minSeedX = minSeedX; i.minSeedY = minSeedY; -i.maxSeedX = maxSeedX; i.maxSeedY = maxSeedY; -i.nSeedPatches = nSeedPatches; i.nSpDistPatches = nSpDistPatches; -i.indsFile = indsFile; -return i; + initParams i; + i.seedType = seedType; i.freeType = freeType; i.spDistType = spDistType; + i.initDens = initDens; i.initAge = initAge; + i.initFrzYr = initFrzYr; + i.restrictRange = restrictRange; + i.restrictRows = restrictRows; i.restrictFreq = restrictFreq; + i.finalFrzYr = finalFrzYr; + i.indsCell = indsCell; i.indsHa = indsHa; + i.minSeedX = minSeedX; i.minSeedY = minSeedY; + i.maxSeedX = maxSeedX; i.maxSeedY = maxSeedY; + i.nSeedPatches = nSeedPatches; i.nSpDistPatches = nSpDistPatches; + i.indsFile = indsFile; + return i; } -void paramInit::setProp(short stg,float p) { -if (stg >= 0 && stg < NSTAGES && p >= 0.0 && p <= 1.0) initProp[stg] = p; +void paramInit::setProp(short stg, float p) { + if (stg >= 0 && stg < NSTAGES && p >= 0.0 && p <= 1.0) initProp[stg] = p; } float paramInit::getProp(short stg) { -float p = 0.0; -if (stg >= 0 && stg < NSTAGES) p = initProp[stg]; -return p; + float p = 0.0; + if (stg >= 0 && stg < NSTAGES) p = initProp[stg]; + return p; } void paramInit::addInitInd(initInd iind) { -#if RSDEBUG -//DebugGUI(("paramInit::addInitInd(): iind.patchID=" + Int2Str(iind.patchID) -// + " iind.x=" + Int2Str(iind.x) -// + " iind.y=" + Int2Str(iind.y) -// ).c_str()); -#endif -initinds.push_back(iind); + initinds.push_back(iind); } initInd paramInit::getInitInd(int ix) { -initInd iind; -if (ix >= 0 && ix < (int)initinds.size()) { - iind = initinds[ix]; -} -else { - iind.year = iind.patchID = iind.x = iind.y = iind.sex = iind.age = iind.stage = 0; - iind.species = -1; -} -#if RSDEBUG -//DEBUGLOG << "paramInit::getInitInd(): ix=" << ix << " size()=" << initinds.size() -// << " iind.patchID=" << iind.patchID -// << " iind.x=" << iind.x -// << " iind.y=" << iind.y -// << endl; -#endif -return iind; + initInd iind; + if (ix >= 0 && ix < (int)initinds.size()) { + iind = initinds[ix]; + } + else { + iind.year = iind.patchID = iind.x = iind.y = iind.sex = iind.age = iind.stage = 0; + iind.species = -1; + } + return iind; } void paramInit::resetInitInds(void) { initinds.clear(); } @@ -225,7 +214,6 @@ paramSim::paramSim(void) { simulation = 0; reps = years = 1; outIntRange = 1; -// outStartRange = outStartOcc = outStartPop = outStartInd = 0; outStartPop = outStartInd = outStartGenetic = 0; outStartTraitCell = outStartTraitRow = outStartConn = 0; outIntOcc = outIntPop = outIntInd = outIntGenetic = 10; @@ -251,140 +239,136 @@ paramSim::paramSim(void) { paramSim::~paramSim(void) { } void paramSim::setSim(simParams s) { -if (s.batchNum >= 0) batchNum = s.batchNum; -if (s.simulation >= 0) simulation = s.simulation; -if (s.reps >= 1) reps = s.reps; -if (s.years >= 1) years = s.years; -if (s.mapInt >= 1) mapInt = s.mapInt; -if (s.traitInt >= 1) traitInt = s.traitInt; -batchMode = s.batchMode; absorbing = s.absorbing; -outRange = s.outRange; outOccup = s.outOccup; -outPop = s.outPop; outInds = s.outInds; -outGenetics = s.outGenetics; -if (s.outGenType >= 0 && s.outGenType <= 2) { - outGenType = s.outGenType; -} -outGenXtab = s.outGenXtab; -outTraitsCells = s.outTraitsCells; outTraitsRows = s.outTraitsRows; -outConnect = s.outConnect; -//if (s.outStartRange >= 0) outStartRange = s.outStartRange; -//if (s.outStartOcc >= 0) outStartOcc = s.outStartOcc; -if (s.outStartPop >= 0) outStartPop = s.outStartPop; -if (s.outStartInd >= 0) outStartInd = s.outStartInd; -if (s.outStartGenetic >= 0) outStartGenetic = s.outStartGenetic; -if (s.outStartTraitCell >= 0) outStartTraitCell = s.outStartTraitCell; -if (s.outStartTraitRow >= 0) outStartTraitRow = s.outStartTraitRow; -if (s.outStartConn >= 0) outStartConn = s.outStartConn; -if (s.outIntRange >= 1) outIntRange = s.outIntRange; -if (s.outIntOcc >= 1) outIntOcc = s.outIntOcc; -if (s.outIntPop >= 1) outIntPop = s.outIntPop; -if (s.outIntInd >= 1) outIntInd = s.outIntInd; -if (s.outIntGenetic >= 1) outIntGenetic = s.outIntGenetic; -if (s.outIntTraitCell >= 1) outIntTraitCell = s.outIntTraitCell; -if (s.outIntTraitRow >= 1) outIntTraitRow = s.outIntTraitRow; -if (s.outIntConn >= 1) outIntConn = s.outIntConn; -saveMaps = s.saveMaps; saveTraitMaps = s.saveTraitMaps; -saveVisits = s.saveVisits; + if (s.batchNum >= 0) batchNum = s.batchNum; + if (s.simulation >= 0) simulation = s.simulation; + if (s.reps >= 1) reps = s.reps; + if (s.years >= 1) years = s.years; + if (s.mapInt >= 1) mapInt = s.mapInt; + if (s.traitInt >= 1) traitInt = s.traitInt; + batchMode = s.batchMode; absorbing = s.absorbing; + outRange = s.outRange; outOccup = s.outOccup; + outPop = s.outPop; outInds = s.outInds; + outGenetics = s.outGenetics; + if (s.outGenType >= 0 && s.outGenType <= 2) { + outGenType = s.outGenType; + } + outGenXtab = s.outGenXtab; + outTraitsCells = s.outTraitsCells; outTraitsRows = s.outTraitsRows; + outConnect = s.outConnect; + if (s.outStartPop >= 0) outStartPop = s.outStartPop; + if (s.outStartInd >= 0) outStartInd = s.outStartInd; + if (s.outStartGenetic >= 0) outStartGenetic = s.outStartGenetic; + if (s.outStartTraitCell >= 0) outStartTraitCell = s.outStartTraitCell; + if (s.outStartTraitRow >= 0) outStartTraitRow = s.outStartTraitRow; + if (s.outStartConn >= 0) outStartConn = s.outStartConn; + if (s.outIntRange >= 1) outIntRange = s.outIntRange; + if (s.outIntOcc >= 1) outIntOcc = s.outIntOcc; + if (s.outIntPop >= 1) outIntPop = s.outIntPop; + if (s.outIntInd >= 1) outIntInd = s.outIntInd; + if (s.outIntGenetic >= 1) outIntGenetic = s.outIntGenetic; + if (s.outIntTraitCell >= 1) outIntTraitCell = s.outIntTraitCell; + if (s.outIntTraitRow >= 1) outIntTraitRow = s.outIntTraitRow; + if (s.outIntConn >= 1) outIntConn = s.outIntConn; + saveMaps = s.saveMaps; saveTraitMaps = s.saveTraitMaps; + saveVisits = s.saveVisits; #if RS_RCPP -outStartPaths = s.outStartPaths; -outIntPaths = s.outIntPaths; -outPaths = s.outPaths; -ReturnPopRaster = s.ReturnPopRaster; -CreatePopFile = s.CreatePopFile; + outStartPaths = s.outStartPaths; + outIntPaths = s.outIntPaths; + outPaths = s.outPaths; + ReturnPopRaster = s.ReturnPopRaster; + CreatePopFile = s.CreatePopFile; #endif -drawLoaded = s.drawLoaded; + drawLoaded = s.drawLoaded; } simParams paramSim::getSim(void) { -simParams s; -s.batchNum = batchNum; -s.simulation = simulation; s.reps = reps; s.years = years; -s.outRange = outRange; s.outOccup = outOccup; s.outPop = outPop; s.outInds = outInds; -s.outGenetics = outGenetics; s.outGenType = outGenType; s.outGenXtab = outGenXtab; -s.outTraitsCells = outTraitsCells; s.outTraitsRows = outTraitsRows; s.outConnect = outConnect; -//s.outStartRange = outStartRange; -//s.outStartOcc = outStartOcc; -s.outStartPop = outStartPop; s.outStartInd = outStartInd; s.outStartGenetic = outStartGenetic; -s.outStartTraitCell = outStartTraitCell; s.outStartTraitRow = outStartTraitRow; -s.outStartConn = outStartConn; -s.outIntRange = outIntRange; -s.outIntOcc = outIntOcc; s.outIntPop = outIntPop; -s.outIntInd = outIntInd; s.outIntGenetic = outIntGenetic; -s.outIntTraitCell = outIntTraitCell; -s.outIntTraitRow = outIntTraitRow; -s.outIntConn = outIntConn; -s.batchMode = batchMode; -s.absorbing = absorbing; -s.saveMaps = saveMaps; s.saveTraitMaps = saveTraitMaps; -s.saveVisits = saveVisits; -s.mapInt = mapInt; s.traitInt = traitInt; + simParams s; + s.batchNum = batchNum; + s.simulation = simulation; s.reps = reps; s.years = years; + s.outRange = outRange; s.outOccup = outOccup; s.outPop = outPop; s.outInds = outInds; + s.outGenetics = outGenetics; s.outGenType = outGenType; s.outGenXtab = outGenXtab; + s.outTraitsCells = outTraitsCells; s.outTraitsRows = outTraitsRows; s.outConnect = outConnect; + s.outStartPop = outStartPop; s.outStartInd = outStartInd; s.outStartGenetic = outStartGenetic; + s.outStartTraitCell = outStartTraitCell; s.outStartTraitRow = outStartTraitRow; + s.outStartConn = outStartConn; + s.outIntRange = outIntRange; + s.outIntOcc = outIntOcc; s.outIntPop = outIntPop; + s.outIntInd = outIntInd; s.outIntGenetic = outIntGenetic; + s.outIntTraitCell = outIntTraitCell; + s.outIntTraitRow = outIntTraitRow; + s.outIntConn = outIntConn; + s.batchMode = batchMode; + s.absorbing = absorbing; + s.saveMaps = saveMaps; s.saveTraitMaps = saveTraitMaps; + s.saveVisits = saveVisits; + s.mapInt = mapInt; s.traitInt = traitInt; #if RS_RCPP -s.outStartPaths = outStartPaths; -s.outIntPaths = outIntPaths; -s.outPaths = outPaths; -s.ReturnPopRaster = ReturnPopRaster; -s.CreatePopFile = CreatePopFile; + s.outStartPaths = outStartPaths; + s.outIntPaths = outIntPaths; + s.outPaths = outPaths; + s.ReturnPopRaster = ReturnPopRaster; + s.CreatePopFile = CreatePopFile; #endif -s.drawLoaded = drawLoaded; -return s; + s.drawLoaded = drawLoaded; + return s; } int paramSim::getSimNum(void) { return simulation; } void paramSim::setViews(simView v) { -viewLand = v.viewLand; viewPatch = v.viewPatch; -viewGrad = v.viewGrad; viewCosts = v.viewCosts; -viewPop = v.viewPop; viewTraits = v.viewTraits; -viewPaths = v.viewPaths; viewGraph = v.viewGraph; -if (v.slowFactor > 0) slowFactor = v.slowFactor; + viewLand = v.viewLand; viewPatch = v.viewPatch; + viewGrad = v.viewGrad; viewCosts = v.viewCosts; + viewPop = v.viewPop; viewTraits = v.viewTraits; + viewPaths = v.viewPaths; viewGraph = v.viewGraph; + if (v.slowFactor > 0) slowFactor = v.slowFactor; } simView paramSim::getViews(void) { -simView v; -v.viewLand = viewLand; v.viewPatch = viewPatch; -v.viewGrad = viewGrad; v.viewCosts = viewCosts; -v.viewPop = viewPop; v.viewTraits = viewTraits; -v.viewPaths = viewPaths; v.viewGraph = viewGraph; -v.slowFactor = slowFactor; -return v; + simView v; + v.viewLand = viewLand; v.viewPatch = viewPatch; + v.viewGrad = viewGrad; v.viewCosts = viewCosts; + v.viewPop = viewPop; v.viewTraits = viewTraits; + v.viewPaths = viewPaths; v.viewGraph = viewGraph; + v.slowFactor = slowFactor; + return v; } void paramSim::setDir(string s) { -dir = s; + dir = s; } // return directory name depending on option specified string paramSim::getDir(int option) { -string s; -switch (option) { -case 0: // working directory - s = dir; - break; + string s; + switch (option) { + case 0: // working directory + s = dir; + break; #if LINUX_CLUSTER || RS_RCPP -case 1: // Inputs folder - s = dir + "Inputs/"; - break; -case 2: // Outputs folder - s = dir + "Outputs/"; - break; -case 3: // Maps folder - s = dir + "Output_Maps/"; - break; + case 1: // Inputs folder + s = dir + "Inputs/"; + break; + case 2: // Outputs folder + s = dir + "Outputs/"; + break; + case 3: // Maps folder + s = dir + "Output_Maps/"; + break; #else -case 1: // Inputs folder - s = dir + "Inputs\\"; - break; -case 2: // Outputs folder - s = dir + "Outputs\\"; - break; -case 3: // Maps folder - s = dir + "Output_Maps\\"; - break; + case 1: // Inputs folder + s = dir + "Inputs\\"; + break; + case 2: // Outputs folder + s = dir + "Outputs\\"; + break; + case 3: // Maps folder + s = dir + "Output_Maps\\"; + break; #endif -default: - s = "ERROR_ERROR_ERROR"; -} -return s; + default: + s = "ERROR_ERROR_ERROR"; + } + return s; } #if RS_RCPP diff --git a/RandomCheck.h b/RandomCheck.h index 45c6b82..7c0ae77 100644 --- a/RandomCheck.h +++ b/RandomCheck.h @@ -32,9 +32,6 @@ using namespace std; #include "../Version.h" #endif -//#if !RS_RCPP && R_CMD -//#include "../../Batch/Version.h" -//#endif #include "Parameters.h" #include "RSrandom.h" From c8b40539c52d7a45c78902d44fd69d10a79af5d6 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 28 Nov 2023 16:32:57 +0000 Subject: [PATCH 23/46] fix leftover #if --- Individual.cpp | 2 +- Species.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Individual.cpp b/Individual.cpp index 8af79d2..cb6c5f8 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -1832,7 +1832,7 @@ void testIndividual() { Individual ind(pCell, pPatch, stg, age, repInt, probmale, uses_movt_process, moveType); // An individual can move to a neighbouring cell - ind.moveto(); + //ind.moveto(); // Gets its sex drawn from pmale diff --git a/Species.cpp b/Species.cpp index 4459793..0be29ca 100644 --- a/Species.cpp +++ b/Species.cpp @@ -762,7 +762,6 @@ void Species::setNeutralLoci(bool neutralMarkersOnly) { neutral = true; for (int t = 0; t < ntraits; t++) { // each trait for (int a = 0; a < traitdata->traitmaps[t]->nAlleles; a++) { -#if if (i == traitdata->traitmaps[t]->traitalleles[a]->chromo && j == traitdata->traitmaps[t]->traitalleles[a]->locus) { neutral = false; // as locus contributes to a trait From 01a61710639ed3be05567971a1487cc66786b6b5 Mon Sep 17 00:00:00 2001 From: JetteReeg <47744741+JetteReeg@users.noreply.github.com> Date: Mon, 11 Dec 2023 08:41:22 +0100 Subject: [PATCH 24/46] Update CONTRIBUTING.md minor changes (references to other repositories, added roles of maintainers (Theo RScore + batch & Jette RScore + R package), emphasized contacting developer team for new features --- CONTRIBUTING.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd66c7f..7cfa3b7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,14 +17,16 @@ RangeShifter is distributed with three user interfaces, each living in their own All three share the same source code for the core simulation (i.e., the actual model), which lives in this repo (RScore). Each of the interfaces keeps a copy of this core code in a subfolder called RScore, kept in sync with the RScore repo via a git subtree (see Git subtree usage section). +âš ï¸ If you wish to propose a change to one of the interfaces, please do so in the corresponding repo: [RangeShifter batch mode](https://github.com/RangeShifter/RangeShifter_batch_dev), [RangeShiftR package](https://github.com/RangeShifter/RangeShiftR-package-dev). + *The RangeShifter GUI is currently being rewritten, and is not open source yet. ## Roles #### Maintainers -- [@JetteReeg](https://github.com/JetteReeg) -- [@TheoPannetier](https://github.com/TheoPannetier) +- [@JetteReeg](https://github.com/JetteReeg): RScore repo and lead in R package +- [@TheoPannetier](https://github.com/TheoPannetier): RScore repo and lead in batch mode Maintainers are responsible for coordinating development efforts and ensuring that RangeShifter keeps building continuously. @@ -65,15 +67,21 @@ Any changes regarding the RangeShifter core code should be done in this reposito #### Bugs To report a bug, please [open an issue](https://github.com/RangeShifter/RangeShiftR-package-dev/issues/new), using the Bug Report template. -Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch/issues) for the batch interface). +Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch/issues) for the batch interface or [here](https://github.com/RangeShifter/RangeShiftR-package-dev) for the R package interface). To propose a bug fix (thank you!!), please create and work on your own branch or fork, from either `main` or `develop` (preferred), and open a pull request when your fix is ready to be merged into the original branch. +As a prerequisite for merging, please ensure that your version passes status check (that is, RangeShifter can still build and run as intended). This can be seen in the Actions panel for every commit and at the bottom of the pull request. + Maintainers will review the pull request, possibly request changes, and eventually integrate the bug fix into RScore, and update the subtrees to bring the fix to all interfaces. #### New features Do you have an idea of a new feature in the RangeShifter platform that should be integrated and is of use for other RangeShifter users? -Please get in touch with the RangeShifter development team (rangeshiftr@uni-potsdam.de (*or other mail?*) to discuss a collaboration. +Please get in touch with the RangeShifter development team (rangeshiftr@uni-potsdam.de*) to discuss a collaboration. + +*Mail address needs to be discussed + +âš ï¸ We advise to contact the developer team as early as possible if you plan on implementing a new feature. This could prevent simultaneous development of the same feature and coordinate potential joint development. Alternatively*, proceed as with the bug fix above: create your own branch or fork _from `develop`_ and work from there, and submit a pull request when your new features are ready to join the core code. We recommend that you update your branch regularly to new changes on `develop` (using `git merge develop`) to reduce the risk of merge conflicts or your version getting out-of-touch in the late stages of development. From 50dc6b44a2cb19efbccb00205182de394d79b164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Mon, 11 Dec 2023 13:47:42 +0000 Subject: [PATCH 25/46] moved status check requirement to branch `unit_test` Status check is not deployed on `development-guidelines`, I would postpone the requirement until `unit_test` is merged. --- CONTRIBUTING.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7cfa3b7..021876d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,23 +42,20 @@ Anyone who whishes to make changes to RangeShifter's code, including regular dev ![](branches.png) +*Check out the [Git cheatsheet](https://github.com/RangeShifter/RScore/blob/development-guidelines/git_cheatsheet.md) for a reminder on the main git commands* + This policy applies to RScore and all three RangeShifter interfaces. RangeShifter uses the following branching structure: - `main` is the default branch, where stable releases live. Because it contains the version of RangeShifter that users normally interact with, it must be stable and build at all times. - Only maintainers should make significant changes to `main`, normally by merging `develop` into `main` to make newly developed features available to users, and marking a release while doing so. +Only maintainers should make significant changes to `main`, normally by merging `develop` into `main` to make newly developed features available to users, and marking a release while doing so. - `develop` is the development branch containing new, in-development features. It is the reference branch for all developers. Contributors may make small changes directly to `develop` but should ensure that new changes do not break the build. If one happens to break `develop`, it should be their top priority to fix it as this will disrupt the work of all other contributors. - Larger changes should instead be developed on feature branches. +Larger changes should instead be developed on feature branches. - Larger changes should be first developed on feature (e.g. `cmake`, `mutualism`, etc.) or contributor (e.g., `theo`) branches. Contributors are welcome to experiment and break such branches at any time, as this will not impact users or other contributors. - When progress is deemed satisfactory, changes can be brought to `develop`. Please open a pull request on GitHub, and assign at least one maintainer as a reviewer. As a pre-requisite, RangeShifter must build on the branch before merging. Please enter a descriptive title and use the description field to describe what you have changed. - - In the meantime, we encourage contributors to work in small and frequent commits, and to merge `develop` into their branch often to update their branch with newest changes. - +When progress is deemed satisfactory, changes can be brought to `develop`. Please open a pull request on GitHub, and assign at least one maintainer as a reviewer. As a pre-requisite, RangeShifter must build on the branch before merging. Please enter a descriptive title and use the description field to describe what you have changed. - - -If you need a reminder on the main git commands related to committing and branching, head to the [Git cheatsheet](https://github.com/RangeShifter/RScore/blob/development-guidelines/git_cheatsheet.md). +In the meantime, we encourage contributors to work in small and frequent commits, and to merge `develop` into their branch often to update their branch with newest changes. ### Contributing to RangeShifter core code @@ -70,8 +67,6 @@ To report a bug, please [open an issue](https://github.com/RangeShifter/RangeShi Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch/issues) for the batch interface or [here](https://github.com/RangeShifter/RangeShiftR-package-dev) for the R package interface). To propose a bug fix (thank you!!), please create and work on your own branch or fork, from either `main` or `develop` (preferred), and open a pull request when your fix is ready to be merged into the original branch. -As a prerequisite for merging, please ensure that your version passes status check (that is, RangeShifter can still build and run as intended). This can be seen in the Actions panel for every commit and at the bottom of the pull request. - Maintainers will review the pull request, possibly request changes, and eventually integrate the bug fix into RScore, and update the subtrees to bring the fix to all interfaces. #### New features From b19330ae58d11a6ef75c630f9ba469a03bb0112a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Mon, 11 Dec 2023 14:05:42 +0000 Subject: [PATCH 26/46] added Maintainers section --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 22611a5..3056fe0 100644 --- a/README.md +++ b/README.md @@ -65,3 +65,8 @@ git subtree add --prefix src/RScore RScore ## Contributing to RangeShifter core code See [CONTRIBUTING](https://github.com/RangeShifter/RScore/blob/main/CONTRIBUTING.md). + +## Maintainers + +- [@JetteReeg](https://github.com/JetteReeg) +- [@TheoPannetier](https://github.com/TheoPannetier) From 34e84dfd938f4dc34f197e79ecdceae999ddff42 Mon Sep 17 00:00:00 2001 From: JetteReeg <47744741+JetteReeg@users.noreply.github.com> Date: Tue, 12 Dec 2023 09:24:26 +0100 Subject: [PATCH 27/46] Update CONTRIBUTING.md Changed link to git subtree usage section - should be changed when merging into main --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 021876d..b11fb90 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,7 +59,7 @@ In the meantime, we encourage contributors to work in small and frequent commits ### Contributing to RangeShifter core code -Any changes regarding the RangeShifter core code should be done in this repository and can afterwards be synced with all interfaces using the git subtree feature (see [Git subtree](https://github.com/RangeShifter/RScore/tree/main#usage-git-subtrees) section in the README). +Any changes regarding the RangeShifter core code should be done in this repository and can afterwards be synced with all interfaces using the git subtree feature (see [Git subtree](https://github.com/RangeShifter/RScore/tree/development-guidelines#usage-git-subtrees) section in the README). #### Bugs From 73b972a9153939c36334862e3f58c10eb1cb21e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Thu, 1 Feb 2024 16:29:37 +0000 Subject: [PATCH 28/46] removed remaining questions that have been addressed --- CONTRIBUTING.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b11fb90..8055ccd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,14 +72,10 @@ Maintainers will review the pull request, possibly request changes, and eventual #### New features Do you have an idea of a new feature in the RangeShifter platform that should be integrated and is of use for other RangeShifter users? -Please get in touch with the RangeShifter development team (rangeshiftr@uni-potsdam.de*) to discuss a collaboration. - -*Mail address needs to be discussed +Please get in touch with the RangeShifter development team (rangeshiftr@uni-potsdam.de) to discuss a collaboration. âš ï¸ We advise to contact the developer team as early as possible if you plan on implementing a new feature. This could prevent simultaneous development of the same feature and coordinate potential joint development. -Alternatively*, proceed as with the bug fix above: create your own branch or fork _from `develop`_ and work from there, and submit a pull request when your new features are ready to join the core code. +Alternatively, proceed as with the bug fix above: create your own branch or fork _from `develop`_ and work from there, and submit a pull request when your new features are ready to join the core code. We recommend that you update your branch regularly to new changes on `develop` (using `git merge develop`) to reduce the risk of merge conflicts or your version getting out-of-touch in the late stages of development. We also recommend that you work in small commits, as this makes the code easier to debug, and makes it easier for maintainers to understand your contributions when reviewing a pull request. - -*Do we welcome independent contributions? From c3b0a4ca5f9842fc9926ddc5c86b5a6d7d481f60 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 5 Feb 2024 20:11:30 +0100 Subject: [PATCH 29/46] fix missing include fields --- RSrandom.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/RSrandom.h b/RSrandom.h index b48c29a..9767245 100644 --- a/RSrandom.h +++ b/RSrandom.h @@ -38,6 +38,8 @@ Last updated: 12 January 2021 by Steve Palmer #include #include +#include +#include "Utils.h" using namespace std; @@ -45,13 +47,8 @@ using namespace std; extern ofstream DEBUGLOG; #endif - - #if !RS_RCPP - //--------------- 2.) New version of RSrandom.cpp - - #include #include #if !LINUX_CLUSTER From 6b0a6c37f6e34de5d3369e0e1059ba28a71df4fd Mon Sep 17 00:00:00 2001 From: JetteReeg <47744741+JetteReeg@users.noreply.github.com> Date: Wed, 7 Feb 2024 07:44:37 +0100 Subject: [PATCH 30/46] Update CONTRIBUTING.md Updated referenced links --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8055ccd..4b180d3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,7 +42,7 @@ Anyone who whishes to make changes to RangeShifter's code, including regular dev ![](branches.png) -*Check out the [Git cheatsheet](https://github.com/RangeShifter/RScore/blob/development-guidelines/git_cheatsheet.md) for a reminder on the main git commands* +*Check out the [Git cheatsheet](https://github.com/RangeShifter/RScore/git_cheatsheet.md) for a reminder on the main git commands* This policy applies to RScore and all three RangeShifter interfaces. RangeShifter uses the following branching structure: @@ -59,12 +59,12 @@ In the meantime, we encourage contributors to work in small and frequent commits ### Contributing to RangeShifter core code -Any changes regarding the RangeShifter core code should be done in this repository and can afterwards be synced with all interfaces using the git subtree feature (see [Git subtree](https://github.com/RangeShifter/RScore/tree/development-guidelines#usage-git-subtrees) section in the README). +Any changes regarding the RangeShifter core code should be done in this repository and can afterwards be synced with all interfaces using the git subtree feature (see [Git subtree](https://github.com/RangeShifter/RScore/tree/main?tab=readme-ov-file#usage-git-subtree) section in the README). #### Bugs To report a bug, please [open an issue](https://github.com/RangeShifter/RangeShiftR-package-dev/issues/new), using the Bug Report template. -Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch/issues) for the batch interface or [here](https://github.com/RangeShifter/RangeShiftR-package-dev) for the R package interface). +Please do check if a related issue has already open on one of the other interfaces ([here](https://github.com/RangeShifter/RangeShifter_batch-dev/issues) for the batch interface or [here](https://github.com/RangeShifter/RangeShiftR-package-dev) for the R package interface). To propose a bug fix (thank you!!), please create and work on your own branch or fork, from either `main` or `develop` (preferred), and open a pull request when your fix is ready to be merged into the original branch. Maintainers will review the pull request, possibly request changes, and eventually integrate the bug fix into RScore, and update the subtrees to bring the fix to all interfaces. From ab907611a12ad709eb809d1adf704a418a578e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Pannetier?= Date: Wed, 7 Feb 2024 11:29:27 +0100 Subject: [PATCH 31/46] fix link to logo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3056fe0..f8dcbb9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This repo contains the core simulation code for RangeShifter v2.0 and is not meant to be compiled or run on its own. - + If you are only interested in using RangeShifter, you can ignore this and head to the repo of one of the interfaces: From 239a795b91b34c6002a3af60e49b3eab212dfa6e Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 9 Feb 2024 12:33:09 +0100 Subject: [PATCH 32/46] update CMake --- CMakeLists.txt | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a100830..d8fe69f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,30 @@ # Config file for compilation with CMake -# Only relevant for Batch mode, but this file needs to live in the RScore folder -add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SubCommunity.cpp) +if (NOT batchmode) # that is, RScore as a standalone + cmake_minimum_required(VERSION 3.10) + # set the project name and version + project(RScore VERSION 2.1.0) + # specify the C++ standard + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED True) + add_executable(RScore Main.cpp Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) +else() # that is, RScore compiled as library within RangeShifter_batch + add_library(RScore Species.cpp Cell.cpp Community.cpp FractalGenerator.cpp GeneticLoad.cpp Individual.cpp Landscape.cpp Model.cpp NeutralStatsManager.cpp Parameters.cpp Patch.cpp Population.cpp QTLTrait.cpp RSrandom.cpp SNPTrait.cpp SpeciesTrait.cpp SubCommunity.cpp Utils.cpp) +endif() # pass config definitions to compiler +target_compile_definitions(RScore PRIVATE RSWIN64) + +# enable LINUX_CLUSTER macro on Linux + macOS if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64" "LINUX_CLUSTER") -else() # Windows - target_compile_definitions(RScore PRIVATE "RSDEBUG" "RSWIN64") + add_compile_definitions("LINUX_CLUSTER") endif() + +# Debug Mode by default, unless "release" is passed +if(NOT DEFINED release) + add_compile_definitions(RSDEBUG) +endif() + +if(NOT batchmode) + target_include_directories(RScore PUBLIC "${PROJECT_BINARY_DIR}") +endif() \ No newline at end of file From 3a02aab50c6dd2e9df4475de228e4e87d5667183 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 9 Feb 2024 12:33:30 +0100 Subject: [PATCH 33/46] rm DEBUGLOG blobs --- Cell.cpp | 12 - Community.cpp | 87 -------- FractalGenerator.cpp | 10 - Individual.cpp | 516 ++----------------------------------------- Landscape.cpp | 364 +----------------------------- 5 files changed, 16 insertions(+), 973 deletions(-) diff --git a/Cell.cpp b/Cell.cpp index 2f8c1b3..fac40c8 100644 --- a/Cell.cpp +++ b/Cell.cpp @@ -59,18 +59,12 @@ Cell::Cell(int xx, int yy, intptr patch, float hab) } Cell::~Cell() { -#if RSDEBUG - //DEBUGLOG << "Cell::~Cell(): this = " << this << " smsData = " << smsData << endl; -#endif habIxx.clear(); habitats.clear(); if (smsData != 0) { if (smsData->effcosts != 0) delete smsData->effcosts; delete smsData; } -#if RSDEBUG - //DEBUGLOG << "Cell::~Cell(): deleted" << endl; -#endif } void Cell::setHabIndex(short hx) { @@ -118,12 +112,6 @@ void Cell::setPatch(intptr p) { } intptr Cell::getPatch(void) { -#if RSDEBUG - //DebugGUI(("Cell::getPatch(): this=" + Int2Str((int)this) - // + " x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " habIxx[0]=" + Int2Str(habIxx[0]) + " pPatch=" + Int2Str(pPatch) - //).c_str()); -#endif return pPatch; } diff --git a/Community.cpp b/Community.cpp index c05e023..7ffc8ed 100644 --- a/Community.cpp +++ b/Community.cpp @@ -262,13 +262,6 @@ void Community::initialise(Species* pSpecies, int year) while (indIx < ninds && iind.year <= year) { iind = paramsInit->getInitInd(indIx); while (iind.year == year) { -#if RSDEBUG - //DEBUGLOG << "Community::initialise(): year=" << year - // << " indIx=" << indIx << " iind.year=" << iind.year - // << " iind.patchID=" << iind.patchID << " iind.x=" << iind.x << " iind.y=" << iind.y - // << " iind.sex=" << iind.sex << " iind.age=" << iind.age << " iind.stage=" << iind.stage - // << endl; -#endif if (ppLand.patchModel) { if (pLandscape->existsPatch(iind.patchID)) { pPatch = pLandscape->findPatch(iind.patchID); @@ -537,21 +530,12 @@ void Community::dispersal(short landIx) for (int i = 0; i < nsubcomms; i++) { // all populations subComms[i]->resetPossSettlers(); } -#if RSDEBUG - //DEBUGLOG << "Community::dispersal() 1111: ndispersers=" << ndispersers << endl; -#endif #if RS_RCPP // included also SEASONAL ndispersers = matrix->transfer(pLandscape, landIx, nextseason); #else ndispersers = matrix->transfer(pLandscape, landIx); #endif // SEASONAL || RS_RCPP -#if RSDEBUG - //DEBUGLOG << "Community::dispersal() 2222: ndispersers=" << ndispersers << endl; -#endif matrix->completeDispersal(pLandscape, sim.outConnect); -#if RSDEBUG - //DEBUGLOG << "Community::dispersal() 3333: ndispersers=" << ndispersers << endl; -#endif } while (ndispersers > 0); #if RSDEBUG @@ -560,11 +544,6 @@ void Community::dispersal(short landIx) DEBUGLOG << "Community::dispersal(): transfer time=" << t2 - t1 << endl; #endif -#if RSDEBUG - //int t3 = time(0); - //DEBUGLOG << "Community::dispersal(): completion time = " << t3-t2 << endl; -#endif - } void Community::survival(short part, short option0, short option1) @@ -663,25 +642,9 @@ commStats Community::getStats(void) patchPop = subComms[i]->getPopStats(); s.ninds += patchPop.nInds; s.nnonjuvs += patchPop.nNonJuvs; -#if RSDEBUG - //DEBUGLOG << "Community::getStats(): i = " << i - // << " pSpecies = " << patchPop.pSpecies << " pPatch = " << patchPop.pPatch - // << " nInds = " << patchPop.nInds << endl; -#endif if (patchPop.pPatch != 0) { // not the matrix patch -#if RSDEBUG - //DEBUGLOG << "Community::getStats(): i = " << i - // << " patchNum = " << patchPop.pPatch->getPatchNum() << endl; -#endif if (patchPop.pPatch->getPatchNum() != 0) { // not matrix patch localK = patchPop.pPatch->getK(); -#if RSDEBUG - //DEBUGLOG << "Community::getStats(): i= " << i - // << " pSpecies= " << patchPop.pSpecies << " pPatch= " << patchPop.pPatch - // << " patchNum= " << patchPop.pPatch->getPatchNum() << " localK= " << localK - // << " nInds= " << patchPop.nInds << " breeding= " << (int)patchPop.breeding - // << endl; -#endif if (localK > 0.0) s.suitable++; if (patchPop.nInds > 0 && patchPop.breeding) { s.occupied++; @@ -962,17 +925,6 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) ts.sumS0[j] += scts.sumS0[j]; ts.ssqS0[j] += scts.ssqS0[j]; ts.sumAlphaS[j] += scts.sumAlphaS[j]; ts.ssqAlphaS[j] += scts.ssqAlphaS[j]; ts.sumBetaS[j] += scts.sumBetaS[j]; ts.ssqBetaS[j] += scts.ssqBetaS[j]; -#if RSDEBUG - //DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j - // << " scts.ninds[j]=" << scts.ninds[j] - // << " scts.sumD0[j]=" << scts.sumD0[j] - // << " scts.ssqD0[j]=" << scts.ssqD0[j] - // << endl; - //DEBUGLOG << "Community::outRange(): i=" << i << " j=" << j - // << " ts.ninds[j]=" << ts.ninds[j] - // << " ts.sumD0[j]=" << ts.sumD0[j] << " ts.ssqD0[j]=" << ts.ssqD0[j] - // << endl; -#endif } } @@ -1011,16 +963,6 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) sdD0[g] = sdAlpha[g] = sdBeta[g] = 0.0; } } -#if RSDEBUG - //DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g - // << " ts.ninds[g]=" << ts.ninds[g] - // << " ts.sumD0[g]=" << ts.sumD0[g] - // << " ts.ssqD0[g]=" << ts.ssqD0[g] - // << endl; - //DEBUGLOG << "Community::outRange(): popsize=" << popsize - // << " mnD0[g]" << mnD0[g] << " sdD0[g]" << sdD0[g] - // << endl; -#endif } if (emig.sexDep) { outrange << "\t" << mnD0[0] << "\t" << sdD0[0]; @@ -1098,17 +1040,6 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) if (sdBetaDB[g] > 0.0) sdBetaDB[g] = sqrt(sdBetaDB[g]); else sdBetaDB[g] = 0.0; } } -#if RSDEBUG - //DEBUGLOG << "Community::outRange(): ngenes=" << ngenes << " g=" << g - // << " ts.ninds[g]=" << ts.ninds[g] - // << " ts.sumDP[g]=" << ts.sumDP[g] << " ts.ssqDP[g]=" << ts.ssqDP[g] - // << " ts.sumGB[g]=" << ts.sumGB[g] << " ts.ssqGB[g]=" << ts.ssqGB[g] - // << endl; - //DEBUGLOG << "Community::outRange(): popsize=" << popsize - // << " mnDP[g]" << mnDP[g] << " sdDP[g]" << sdDP[g] - // << " mnGB[g]" << mnGB[g] << " sdGB[g]" << sdGB[g] - // << endl; -#endif } if (trfr.moveModel) { if (trfr.moveType == 1) { @@ -1282,35 +1213,17 @@ void Community::outOccSuit(bool view) { simParams sim = paramsSim->getSim(); //streamsize prec = outsuit.precision(); -#if RSDEBUG -//DEBUGLOG << "Community::outOccSuit(): sim.reps=" << sim.reps -// << " sim.years=" << sim.years << " sim.outInt=" << sim.outInt << endl; -#endif for (int i = 0; i < (sim.years / sim.outIntOcc) + 1; i++) { sum = ss = 0.0; for (int rep = 0; rep < sim.reps; rep++) { sum += occSuit[i][rep]; ss += occSuit[i][rep] * occSuit[i][rep]; -#if RSDEBUG - //DEBUGLOG << "Community::outOccSuit(): i=" << i << " rep=" << rep - // << " occSuit[i][rep]=" << occSuit[i][rep] - // << " sum=" << sum << " ss=" << ss - // << endl; -#endif } mean = sum / (double)sim.reps; sd = (ss - (sum * sum / (double)sim.reps)) / (double)(sim.reps - 1); -#if RSDEBUG - //DEBUGLOG << "Community::outOccSuit(): i=" << i - // << " mean=" << mean << " sd=" << sd << endl; -#endif if (sd > 0.0) sd = sqrt(sd); else sd = 0.0; se = sd / sqrt((double)(sim.reps)); -#if RSDEBUG - //DEBUGLOG << "Community::outOccSuit(): i=" << i - // << " sd=" << sd << " se=" << se << endl; -#endif // outsuit << i*sim.outInt << "\t" << mean << "\t" << se << endl; // if (view) viewOccSuit(i*sim.outInt,mean,se); diff --git a/FractalGenerator.cpp b/FractalGenerator.cpp index 9dda608..c0a0392 100644 --- a/FractalGenerator.cpp +++ b/FractalGenerator.cpp @@ -211,17 +211,7 @@ vector& fractal_landscape(int X, int Y, double Hurst, double prop, } if (arena != NULL) { -#if RSDEBUG - //DebugGUI(("fractal_landscape(): arena=" + Int2Str((int)arena) - // + " X=" + Int2Str(X) + " Y=" + Int2Str(Y) - // ).c_str()); -#endif for (ii = 0; ii < X; ii++) { -#if RSDEBUG - //DebugGUI(("fractal_landscape(): ii=" + Int2Str(ii) - // + " arena[ii]=" + Int2Str((int)arena[ii]) - // ).c_str()); -#endif delete[] arena[ii]; } delete[] arena; diff --git a/Individual.cpp b/Individual.cpp index 25dc99f..d4d6d53 100644 --- a/Individual.cpp +++ b/Individual.cpp @@ -35,11 +35,6 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep float probmale, bool movt, short moveType) { indId = indCounter; indCounter++; // unique identifier for each individual -#if RSDEBUG - //DEBUGLOG << "Individual::Individual(): indId=" << indId - // << " stg=" << stg << " a=" << a << " probmale=" << probmale - // << endl; -#endif fitness = 1.0; stage = stg; if (probmale <= 0.0) sex = FEM; @@ -80,13 +75,6 @@ Individual::Individual(Cell* pCell, Patch* pPatch, short stg, short a, short rep } //pEmigTraits = make_unique(nullptr); //pSettleTraits = make_unique(nullptr); -#if RSDEBUG -//locn currloc = pCurrCell->getLocn(); -//DEBUGLOG << "Individual::Individual(): indId=" << indId -// << " x=" << currloc.x << " y=" << currloc.y -//// << " smsData=" << smsData << " dp=" << smsData->dp -// << endl; -#endif } Individual::~Individual(void) { @@ -281,35 +269,12 @@ void Individual::setSettlementTraits(Species* pSpecies, bool sexDep) { s.beta = getTrait(S_BETA_F)->express(); } -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta - // << endl; -#endif -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " sparams.s0Mean=" << sparams.s0Mean << " sparams.s0SD=" << sparams.s0SD - // << " sparams.s0Scale=" << sparams.s0Scale - // << endl; -#endif pSettleTraits = make_unique(); pSettleTraits->s0 = (float)(s.s0); pSettleTraits->alpha = (float)(s.alpha); pSettleTraits->beta = (float)(s.beta); -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " setttraits->s0=" << setttraits->s0 - // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta - // << endl; -#endif if (pSettleTraits->s0 < 0.0) pSettleTraits->s0 = 0.0; if (pSettleTraits->s0 > 1.0) pSettleTraits->s0 = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::setSettTraits(): indId=" << indId - // << " setttraits->s0=" << setttraits->s0 - // << " setttraits->alpha=" << setttraits->alpha << " setttraits->beta=" << setttraits->beta - // << endl; -#endif return; } @@ -371,11 +336,6 @@ void Individual::setYearSteps(int t) { if (t >= 0) path->year = t; else path->year = 666; } -#if RSDEBUG - //DEBUGLOG << "Individual::setYearSteps(): indId=" << indId - // << " t=" << t << " path->year=" << path->year - // << endl; -#endif } pathSteps Individual::getSteps(void) { @@ -429,51 +389,23 @@ void Individual::setEmigTraits(Species* pSpecies, bool sexDep, bool densityDep) } } -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " eparams.betaMean=" << eparams.betaMean << " eparams.betaSD=" << eparams.betaSD - // << " eparams.betaScale=" << eparams.betaScale - // << endl; -#endif pEmigTraits = make_unique(); pEmigTraits->d0 = (float)(e.d0); pEmigTraits->alpha = (float)(e.alpha); pEmigTraits->beta = (float)(e.beta); -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " emigtraits->d0=" << emigtraits->d0 - // << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta - // << endl; -#endif if (pEmigTraits->d0 < 0.0) pEmigTraits->d0 = 0.0; if (pEmigTraits->d0 > 1.0) pEmigTraits->d0 = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::setEmigTraits(): indId=" << indId - // << " emigtraits->d0=" << emigtraits->d0 - // << " emigtraits->alpha=" << emigtraits->alpha << " emigtraits->beta=" << emigtraits->beta - // << endl; -#endif return; } // Get phenotypic emigration traits emigTraits Individual::getEmigTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId - // << endl; -#endif emigTraits e; e.d0 = e.alpha = e.beta = 0.0; if (pEmigTraits != 0) { e.d0 = pEmigTraits->d0; e.alpha = pEmigTraits->alpha; e.beta = pEmigTraits->beta; } -#if RSDEBUG - //DEBUGLOG << "Individual::getEmigTraits(): indId=" << indId - // << " e.d0=" << e.d0 << " e.alpha=" << e.alpha << " e.beta=" << e.beta - // << endl; -#endif - return e; } // Set phenotypic transfer by kernel traits @@ -502,13 +434,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel float meanDist2 = (float)(k.meanDist2); float probKern1 = (float)(k.probKern1); -#if RSDEBUG - //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId - // << " kerntraits->meanDist1=" << kerntraits->meanDist1 - // << " kerntraits->meanDist2=" << kerntraits->meanDist2 - // << " kerntraits->probKern1=" << kerntraits->probKern1 - // << endl; -#endif if (!pSpecies->useFullKernel()) { // kernel mean(s) may not be less than landscape resolution if (meanDist1 < resol) meanDist1 = (float)resol; @@ -516,13 +441,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel } if (probKern1 < 0.0) probKern1 = 0.0; if (probKern1 > 1.0) probKern1 = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::setKernTraits(): indId=" << indId - // << " kerntraits->meanDist1=" << kerntraits->meanDist1 - // << " kerntraits->meanDist2=" << kerntraits->meanDist2 - // << " kerntraits->probKern1=" << kerntraits->probKern1 - // << endl; -#endif auto& pKernel = dynamic_cast(*pTrfrData); pKernel.meanDist1 = meanDist1; pKernel.meanDist2 = meanDist2; @@ -535,10 +453,6 @@ void Individual::setKernelTraits(Species* pSpecies, bool sexDep, bool twinKernel // Get phenotypic emigration traits trfrKernTraits Individual::getKernTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getKernTraits(): indId=" << indId - // << endl; -#endif trfrKernTraits k; k.meanDist1 = k.meanDist2 = k.probKern1 = 0.0; if (pTrfrData != 0) { @@ -548,12 +462,6 @@ trfrKernTraits Individual::getKernTraits(void) { k.meanDist2 = pKernel.meanDist2; k.probKern1 = pKernel.probKern1; } -#if RSDEBUG - //DEBUGLOG << "Individual::getKernTraits(): indId=" << indId - // << " k.meanDist1=" << k.meanDist1 << " k.meanDist2=" << k.meanDist1 - // << " k.probKern1=" << k.probKern1 - // << endl; -#endif return k; } @@ -571,12 +479,6 @@ void Individual::setSMSTraits(Species* pSpecies) { betaDB = getTrait(SMS_BETADB)->express(); } -#if RSDEBUG - //DEBUGLOG << "Individual::setSMSTraits(): indId=" << indId - // << " dp=" << dp << " gb=" << gb - // << " alphaDB=" << alphaDB << " betaDB=" << betaDB - // << endl; -#endif auto& pSMS = dynamic_cast(*pTrfrData); pSMS.dp = (float)(dp); pSMS.gb = (float)(gb); @@ -588,22 +490,10 @@ void Individual::setSMSTraits(Species* pSpecies) { pSMS.alphaDB = s.alphaDB; pSMS.betaDB = s.betaDB; } -#if RSDEBUG - //DEBUGLOG << "Individual::setSMSTraits() 1111: indId=" << indId - // << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb - // << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB - // << endl; -#endif if (pSMS.dp < 1.0) pSMS.dp = 1.0; if (pSMS.gb < 1.0) pSMS.gb = 1.0; if (pSMS.alphaDB <= 0.0) pSMS.alphaDB = 0.000001f; if (pSMS.betaDB < 1) pSMS.betaDB = 1; -#if RSDEBUG - //DEBUGLOG << "Individual::setSMSTraits() 2222: indId=" << indId - // << " smsData->dp=" << smsData->dp << " smsData->gb=" << smsData->gb - // << " smsData->alphaDB=" << smsData->alphaDB << " smsData->betaDB=" << smsData->betaDB - // << endl; -#endif return; } @@ -613,10 +503,7 @@ trfrData* Individual::getTrfrData(void) { // Get phenotypic transfer by SMS traits trfrSMSTraits Individual::getSMSTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId << " smsData=" << smsData - // << endl; -#endif + trfrSMSTraits s; s.dp = s.gb = s.alphaDB = 1.0; s.betaDB = 1; if (pTrfrData != 0) { @@ -625,12 +512,7 @@ trfrSMSTraits Individual::getSMSTraits(void) { s.dp = pSMS.dp; s.gb = pSMS.gb; s.alphaDB = pSMS.alphaDB; s.betaDB = pSMS.betaDB; } -#if RSDEBUG - //DEBUGLOG << "Individual::getSMSTraits(): indId=" << indId - // << " s.dp=" << s.dp << " s.gb=" << s.gb - // << " s.alphaDB=" << s.alphaDB << " s.betaDB=" << s.betaDB - // << endl; -#endif + return s; } @@ -647,37 +529,17 @@ void Individual::setCRWTraits(Species* pSpecies, bool sexDep) { c.rho = getTrait(CRW_STEPCORRELATION_F)->express(); } -#if RSDEBUG - //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId - // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho - // << endl; -#endif - auto& pCRW = dynamic_cast(*pTrfrData); pCRW.stepLength = (float)(c.stepLength); pCRW.rho = (float)(c.rho); -#if RSDEBUG - //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId - // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho - // << endl; -#endif if (pCRW.stepLength < 1.0) pCRW.stepLength = 1.0; if (pCRW.rho < 0.0) pCRW.rho = 0.0; if (pCRW.rho > 0.999) pCRW.rho = 0.999f; -#if RSDEBUG - //DEBUGLOG << "Individual::setCRWTraits(): indId=" << indId - // << " crw->stepL=" << crw->stepL << " crw->rho=" << crw->rho - // << endl; -#endif return; } // Get phenotypic transfer by CRW traits trfrCRWTraits Individual::getCRWTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId - // << endl; -#endif trfrCRWTraits c; c.stepLength = c.rho = 0.0; @@ -688,11 +550,6 @@ trfrCRWTraits Individual::getCRWTraits(void) { c.stepLength = pCRW.stepLength; c.rho = pCRW.rho; } -#if RSDEBUG - //DEBUGLOG << "Individual::getCRWTraits(): indId=" << indId - // << " c.stepLength=" << c.stepLength << " c.rho=" << c.rho - // << endl; -#endif return c; @@ -700,21 +557,12 @@ trfrCRWTraits Individual::getCRWTraits(void) { // Get phenotypic settlement traits settleTraits Individual::getSettTraits(void) { -#if RSDEBUG - //DEBUGLOG << "Individual::getSettTraits(): indId=" << indId - // << endl; -#endif settleTraits s; s.s0 = s.alpha = s.beta = 0.0; if (pSettleTraits != 0) { s.s0 = pSettleTraits->s0; s.alpha = pSettleTraits->alpha; s.beta = pSettleTraits->beta; } -#if RSDEBUG - //DEBUGLOG << "Individual::getSettTraits(): indId=" << indId - // << " s.s0=" << s.s0 << " s.alpha=" << s.alpha << " s.beta=" << s.beta - // << endl; -#endif return s; } @@ -827,19 +675,8 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, } } } -#if RSDEBUG - //Patch *startPatch = (Patch*)startpatch; - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " x=" << loc.x << " y=" << loc.y - //// << " natalPatch = " << natalPatch - //// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() - // << " kern.meanDist1=" << kern.meanDist1; - //if (trfr.twinKern) { - // DEBUGLOG << " meanDist2=" << kern.meanDist2 << " probKern1=" << kern.probKern1; - //} - //DEBUGLOG << endl; -#endif -// scale the appropriate kernel mean to the cell size + // scale the appropriate kernel mean to the cell size if (trfr.twinKern) { if (pRandom->Bernoulli(kern.probKern1)) @@ -849,27 +686,9 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, } else meandist = kern.meanDist1 / (float)land.resol; -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; -#endif -// scaled mean may not be less than 1 unless emigration derives from the kernel -// (i.e. the 'use full kernel' option is applied) + // scaled mean may not be less than 1 unless emigration derives from the kernel + // (i.e. the 'use full kernel' option is applied) if (!usefullkernel && meandist < 1.0) meandist = 1.0; -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " meandist=" << meandist << endl; -#endif - -#if RSDEBUG -//Patch *startPatch = (Patch*)startpatch; -//DEBUGLOG << "Individual::moveKernel(): indId = " << indId << " x = " << x << " y = " << y -// << " natalPatch = " << natalPatch -//// << " startpatch = " << startpatch << " patchNum = " << startPatch->getPatchNum() -// << " meanDist1 = " << kern.meanDist1; -//if (trfr.twinKern) { -// DEBUGLOG << " probKern1 = " << kern.probKern1 << " meanDist2 = " << kern.meanDist2; -//} -//DEBUGLOG << " meandist = " << meandist << endl; -#endif int loopsteps = 0; // new counter to prevent infinite loop added 14/8/15 do { @@ -904,12 +723,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, if (path != 0) (path->year)++; #endif loopsteps++; -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status - // << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY - // << " loc.x=" << loc.x << " loc.y=" << loc.y - // << endl; -#endif } while (loopsteps < 1000 && ((!absorbing && (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)) @@ -945,12 +758,6 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, patch = 0; patchNum = -1; } -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId << " status=" << status - // << " loopsteps=" << loopsteps << " newX=" << newX << " newY=" << newY - // << " pCell=" << pCell << " patch=" << patch << " patchNum=" << patchNum - // << endl; -#endif } while (!absorbing && patchNum < 0 && loopsteps < 1000); // in a no-data region } while (!usefullkernel && pPatch == pNatalPatch && loopsteps < 1000); // still in the original (natal) patch @@ -987,15 +794,8 @@ int Individual::moveKernel(Landscape* pLandscape, Species* pSpecies, status = 6; dispersing = 0; } -#if RSDEBUG - //DEBUGLOG << "Individual::moveKernel(): indId=" << indId - // << " newX=" << newX << " newY=" << newY - // << " patch=" << patch - // << " patchNum=" << patchNum << " status=" << status; - //DEBUGLOG << endl; -#endif -// apply dispersal-related mortality, which may be distance-dependent + // apply dispersal-related mortality, which may be distance-dependent dist *= (float)land.resol; // re-scale distance moved to landscape scale if (status < 7) { double dispmort; @@ -1044,11 +844,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, settleSteps settsteps = pSpecies->getSteps(stage, sex); patch = pCurrCell->getPatch(); -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep() AAAA: indId=" << indId - // << " pCurrCell=" << pCurrCell << " patch=" << patch - // << endl; -#endif if (patch == 0) { // matrix pPatch = 0; @@ -1066,35 +861,12 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, mortprob = 1.0; } else mortprob = pSpecies->getHabMort(h); -#if RSDEBUG - //locn temploc = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep(): x=" << temploc.x << " y=" << temploc.x - // << " landIx=" << landIx << " h=" << h << " mortprob=" << mortprob - // << endl; -#endif } else mortprob = movt.stepMort; // ... unless individual has not yet left natal patch in emigration year if (pPatch == pNatalPatch && path->out == 0 && path->year == path->total) { mortprob = 0.0; } -#if RSDEBUG - locn loc0, loc1, loc2; - //loc0 = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep() BBBB: indId=" << indId << " status=" << status - // << " path->year=" << path->year << " path->out=" << path->out - // << " settleStatus=" << path->settleStatus - // << " x=" << loc0.x << " y=" << loc0.y - //// << " patch=" << patch - // << " pPatch=" << pPatch - // << " patchNum=" << patchNum; - //// << " natalPatch=" << natalPatch; - ////if (crw != 0) { - //// DEBUGLOG << " xc=" << crw->xc << " yc=" << crw->yc; - //// DEBUGLOG << " rho=" << movt.rho << " stepLength=" << movt.stepLength; - ////} - //DEBUGLOG << endl; -#endif if (pRandom->Bernoulli(mortprob)) { // individual dies status = 7; dispersing = 0; @@ -1113,23 +885,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, switch (trfr.moveType) { case 1: // SMS -#if RSDEBUG - //loc1 = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep() FFFF: indId=" << indId << " status=" << status - //// << " path->year=" << path->year - // << " path->season=" << path->season - // << " x=" << loc1.x << " y=" << loc1.y - // << " smsData->goalType=" << smsData->goalType - // << " goal.x=" << smsData->goal.x - // << " goal.y=" << smsData->goal.y - // << endl; -#endif move = smsMove(pLandscape, pSpecies, landIx, pPatch == pNatalPatch, trfr.indVar, absorbing); -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep() GGGG: indId=" << indId << " status=" << status - // << " move.dist=" << move.dist - // << endl; -#endif if (move.dist < 0.0) { // either INTERNAL ERROR CONDITION - INDIVIDUAL IS IN NO-DATA SQUARE // or individual has crossed absorbing boundary ... @@ -1138,16 +894,8 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, dispersing = 0; } else { -#if RSDEBUG - //loc1 = pCurrCell->getLocn(); - //DEBUGLOG << "Individual::moveStep() HHHH: indId=" << indId << " status=" << status - // << " path->year=" << path->year - // << " x=" << loc1.x << " y=" << loc1.y - //// << " smsData = " << smsData - // << endl; -#endif - // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... + // WOULD IT BE MORE EFFICIENT FOR smsMove TO RETURN A POINTER TO THE NEW CELL? ... patch = pCurrCell->getPatch(); //int patchnum; @@ -1169,7 +917,7 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, auto & pCRW = dynamic_cast(*pTrfrData); - if (trfr.indVar) { + if (trfr.indVar) { movt.stepLength = pCRW.stepLength; movt.rho = pCRW.rho; } @@ -1203,13 +951,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, if (xcnew < 0.0) newX = -1; else newX = (int)xcnew; if (ycnew < 0.0) newY = -1; else newY = (int)ycnew; loopsteps++; -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep(): indId=" << indId - // << " xc=" << crw->xc << " yc=" << crw->yc << " pCurrCell=" << pCurrCell - // << " steps=" << path->year << " loopsteps=" << loopsteps - // << " steplen=" << steplen << " rho=" << rho << " angle=" << angle - // << " xcnew=" << xcnew << " ycnew=" << ycnew << " newX=" << newX << " newY=" << newY << endl; -#endif } while (!absorbing && loopsteps < 1000 && (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY)); if (newX < land.minX || newX > land.maxX || newY < land.minY || newY > land.maxY) @@ -1222,11 +963,6 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, } else patch = pCurrCell->getPatch(); -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep(): indId=" << indId - // << " loopsteps=" << loopsteps << " absorbed=" << absorbed - // << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; -#endif } while (!absorbing && pCurrCell == 0 && loopsteps < 1000); pCRW.prevdrn = (float)angle; pCRW.xc = (float)xcnew; pCRW.yc = (float)ycnew; @@ -1246,36 +982,10 @@ int Individual::moveStep(Landscape* pLandscape, Species* pSpecies, pCurrCell = pPrevCell; } } -#if RSDEBUG - //DEBUGLOG << "Individual::moveStep(): indId=" << indId - // << " status=" << status - // << " pCurrCell=" << pCurrCell << " patch=" << patch << endl; -#endif break; } // end of switch (trfr.moveType) -#if RSDEBUG -//locn loc2; -//if (pCurrCell > 0) { -// loc2 = pCurrCell->getLocn(); -//} -//else { -// loc2.x = -9999; loc2.y = -9999; -//} -//DEBUGLOG << "Individual::moveStep() ZZZZ: indId=" << indId -// << " status=" << status -// << " path->total=" << path->total -// << " x=" << loc2.x << " y=" << loc2.y -// << " patch=" << patch; -//if (patch > 0) { -// pPatch = (Patch*)patch; -// DEBUGLOG << " patchNum=" << pPatch->getPatchNum() -// << " getK()=" << pPatch->getK() -// << " popn=" << pPatch->getPopn((int)pSpecies); -//} -// DEBUGLOG << endl; -#endif if (patch > 0 // not no-data area or matrix && path->total >= settsteps.minSteps) { pPatch = (Patch*)patch; @@ -1324,12 +1034,6 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, locn current; auto& pSMS = dynamic_cast(*pTrfrData); - //if (write_out) { - // out<findCell(x,y); if (pCurrCell == 0) { // x,y is a NODATA square - this should not occur here @@ -1338,16 +1042,11 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, return move; } -#if RSDEBUG - //DEBUGLOG << "Individual::smsMove(): this=" << this << endl; -#endif - landData land = pLand->getLandData(); trfrSMSTraits movt = pSpecies->getSMSTraits(); current = pCurrCell->getLocn(); //get weights for directional persistence.... - //if ((path->out > 0 && path->out < 10 && path->out < 2*movt.pr) if ((path->out > 0 && path->out <= (movt.pr + 1)) || natalPatch || (movt.straigtenPath && path->settleStatus > 0)) { @@ -1360,25 +1059,8 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, else nbr = getSimDir(current.x, current.y, movt.dp); } if (natalPatch || path->settleStatus > 0) path->out = 0; - //if (natalPatch) path->out = 0; -#if RSDEBUG -//DEBUGLOG << "Individual::smsMove() 0000: nbr matrix" << endl; -//for (y2 = 2; y2 > -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; -// DEBUGLOG << endl; -//} -#endif -//if (write_out) { -// out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << hab.cell[x2][y2] << " "; - // DEBUGLOG << endl; - //} -#endif pCurrCell->setEffCosts(hab); } else { // they have already been calculated - no action required - // if (write_out) { - // out<<"*** using previous effective costs ***"< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) { - // out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; - // DEBUGLOG << endl; - //} -#endif -// determine reciprocal of effective cost for the 8 neighbours -//if (write_out) out<<"reciprocal weighted effective costs:"< -1; y2--) { for (x2 = 0; x2 < 3; x2++) { if (nbr.cell[x2][y2] > 0.0) nbr.cell[x2][y2] = 1.0f / nbr.cell[x2][y2]; - // if (write_out) { - // out< -1; y2--) { -// for (x2 = 0; x2 < 3; x2++) { -// temp.cell[x2][y2] = nbr.cell[x2][y2]; -// if (current.x == 488 && current.y == 422) { -// pCell = pLand->findCell((current.x+x2-1),(current.y+y2-1)); -// DEBUGLOG << "Individual::smsMove(): this=" << this -// << " IN THE PROBLEM CELL" -// << " y=" << current.y << " x=" << current.x -// << " y2=" << y2 << " x2=" << x2 -// << " pCell=" << pCell; -// if (pCell != 0) DEBUGLOG << " pCell->getCost=" << pCell->getCost(); -// DEBUGLOG << endl; -// } -// } -//} -#endif - for (y2 = 2; y2 > -1; y2--) { for (x2 = 0; x2 < 3; x2++) { if (!absorbing) { @@ -1537,44 +1135,20 @@ movedata Individual::smsMove(Landscape* pLand, Species* pSpecies, if (pCell == 0) nbr.cell[x2][y2] = 0.0; // no-data cell } } -#if RSDEBUG - //DEBUGLOG << "Individual::smsMove(): this=" << this - // << " y=" << current.y << " x=" << current.x - // << " y2=" << y2 << " x2=" << x2 - // << " pCell=" << pCell - // << endl; -#endif -// if (write_out) { -// out< 0.0) { // should always be the case, but safest to check... for (y2 = 2; y2 > -1; y2--) { for (x2 = 0; x2 < 3; x2++) { nbr.cell[x2][y2] = nbr.cell[x2][y2] / (float)sum_nbrs; - // if (write_out) { - // out< -1; y2--) { - // for (x2 = 0; x2 < 3; x2++) DEBUGLOG << nbr.cell[x2][y2] << " "; - // DEBUGLOG << endl; - //} -#endif -// set up cell selection probabilities -//if (write_out) out<<"rnd = "<findCell(newX, newY); } } while (!absorbing && pNewCell == 0 && loopsteps < 1000); // no-data cell -#if RSDEBUG - //DEBUGLOG << "Individual::smsMove() 8888: pNewCell=" << pNewCell - // << " loopsteps=" << loopsteps - // << " current.x=" << current.x << " current.y=" << current.y - // << " newX=" << newX << " newY=" << newY - // << " land.minX=" << land.minX << " land.minY=" << land.minY - // << " land.maxX=" << land.maxX << " land.maxY=" << land.maxY - // << endl; -#endif if (loopsteps >= 1000 || pNewCell == 0) { // unable to make a move or crossed absorbing boundary // flag individual to die @@ -1688,15 +1240,12 @@ array3x3d Individual::getSimDir(const int x, const int y, const float dp) if ((x - prev.x) == 0 && (y - prev.y) == 0) { // back to 'square 1' (first memory location) - use previous step drn only prev = memory.back(); - // if (write_out) out<<"step 3"<getHabIndex(landIx); cost = pSpecies->getHabCost(h); -#if RSDEBUG - //DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 - // << " landIx=" << landIx << " h=" << h << " cost=" << cost - // << endl; -#endif pCell->setCost(cost); } else { -#if RSDEBUG - //DEBUGLOG << "Individual::getHabMatrix(): x4=" << x4 << " y4=" << y4 - // << " cost=" << cost - // << endl; -#endif - + // nothing? } } } @@ -1938,26 +1464,14 @@ array3x3f Individual::getHabMatrix(Landscape* pLand, Species* pSpecies, ncells++; sumweights += weight; } } - // if (write_out2) out2<get_target() > 50) targetseen++; - // } - //#endif } //end of y3 loop } //end of x3 loop - // if (write_out) out<<"ncells in PR = "<avail=" << iter->avail - // << " iter->value=" << iter->value << endl; -#endif pCell = findCell(x, y); if (continuous) { if (iter->value > 0.0) { // habitat @@ -722,12 +615,6 @@ void Landscape::generatePatches(void) else { // random landscape int hab = 0; ncells = (int)((float)(dimX) * (float)(dimY)*propSuit + 0.00001); // no. of cells to initialise -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches(): dimX=" << dimX << " dimY=" << dimY - // << " propSuit=" << propSuit - // << " PRODUCT=" << ((float)(dimX) * (float)(dimY) * propSuit + 0.00001) - // << " ncells=" << ncells << endl; -#endif int i = 0; do { do { @@ -735,11 +622,6 @@ void Landscape::generatePatches(void) pCell = findCell(x, y); hab = pCell->getHabIndex(0); } while (hab > 0); -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches() 00000: y=" << y << " x=" << x - // << " i=" << i << " hab=" << hab << " patchnum=" << patchnum - // << endl; -#endif patchnums.push_back(patchnum); pPatch = newPatch(patchnum++); pCell = findCell(x, y); @@ -764,10 +646,6 @@ void Landscape::generatePatches(void) } else { // discrete if (pCell->getHabIndex(0) == 0) { -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches() 11111: yy=" << yy << " xx=" << xx - // << endl; -#endif addCellToPatch(pCell, patches[0], x); } } @@ -775,11 +653,6 @@ void Landscape::generatePatches(void) } } -#if RSDEBUG - //DEBUGLOG << "Landscape::generatePatches(): finished, no. of patches = " - // << patchCount() << endl; -#endif - simParams sim = paramsSim->getSim(); if (pSpecies->getNumberOfNeutralLoci() > 0 && (sim.outputWCFstat || sim.outputPairwiseFst)) { @@ -802,10 +675,6 @@ void Landscape::generatePatches(void) habitat cells are added to the matrix patch) */ void Landscape::allocatePatches(Species* pSpecies) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): pSpecies=" << pSpecies - // << " N patches=" << (int)patches.size() << endl; -#endif //int hx; float habK; Patch* pPatch; @@ -814,10 +683,6 @@ void Landscape::allocatePatches(Species* pSpecies) // delete all existing patches int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): i=" << i - // << " patches[i]=" << patches[i] << endl; -#endif if (patches[i] != NULL) delete patches[i]; } patches.clear(); @@ -825,10 +690,6 @@ void Landscape::allocatePatches(Species* pSpecies) patches.push_back(new Patch(0, 0)); Patch* matrixPatch = patches[0]; patchnums.push_back(0); -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): npatches=" << npatches - // << " N patches=" << (int)patches.size() << endl; -#endif int patchnum = 1; switch (rasterType) { @@ -836,10 +697,6 @@ void Landscape::allocatePatches(Species* pSpecies) case 0: // habitat codes for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " cells=" << cells[y][x] << endl; -#endif if (cells[y][x] != 0) { // not no-data cell pCell = cells[y][x]; // hx = pCell->getHabIndex(); @@ -848,13 +705,6 @@ void Landscape::allocatePatches(Species* pSpecies) int nhab = pCell->nHabitats(); for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(pCell->getHabIndex(i)); -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " i=" << i - // << " cells[y][x]=" << cells[y][x] - // << " pCell=" << pCell - // << " habK=" << habK << endl; -#endif } if (habK > 0.0) { // cell is suitable - create a patch for it patchnums.push_back(patchnum); @@ -872,10 +722,6 @@ void Landscape::allocatePatches(Species* pSpecies) case 1: // habitat cover for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " cells=" << cells[y][x] << endl; -#endif if (cells[y][x] != 0) { // not no-data cell pCell = cells[y][x]; habK = 0.0; @@ -884,13 +730,6 @@ void Landscape::allocatePatches(Species* pSpecies) for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(i) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " i=" << i - // << " cells[y][x]=" << cells[y][x] - // << " pCell=" << pCell - // << " habK=" << habK << endl; -#endif } if (habK > 0.0) { // cell is suitable - create a patch for it patchnums.push_back(patchnum); @@ -908,25 +747,13 @@ void Landscape::allocatePatches(Species* pSpecies) case 2: // habitat quality for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " cells=" << cells[y][x] << endl; -#endif if (cells[y][x] != 0) { // not no-data cell pCell = cells[y][x]; habK = 0.0; int nhab = pCell->nHabitats(); - // for (int i = 0; i < nHab; i++) for (int i = 0; i < nhab; i++) { habK += pSpecies->getHabK(0) * pCell->getHabitat(i) / 100.0f; -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): x=" << x << " y=" << y - // << " i=" << i - // << " cells[y][x]=" << cells[y][x] - // << " pCell=" << pCell - // << " habK=" << habK << endl; -#endif } if (habK > 0.0) { // cell is suitable (at some time) - create a patch for it patchnums.push_back(patchnum); @@ -955,12 +782,6 @@ void Landscape::allocatePatches(Species* pSpecies) pSpecies->setSamplePatchList(patchesToSample); } - - -#if RSDEBUG - //DEBUGLOG << "Landscape::allocatePatches(): finished, N patches = " << (int)patches.size() << endl; -#endif - } Patch* Landscape::newPatch(int num) @@ -1118,12 +939,6 @@ void Landscape::updateCarryingCapacity(Species* pSpecies, int yr, short landIx) patchLimits landlimits; landlimits.xMin = minX; landlimits.xMax = maxX; landlimits.yMin = minY; landlimits.yMax = maxY; -#if RSDEBUG - //DEBUGLOG << "Landscape::updateCarryingCapacity(): yr=" << yr - // << " xMin=" << landlimits.xMin << " yMin=" << landlimits.yMin - // << " xMax=" << landlimits.xMax << " yMax=" << landlimits.yMax - // << endl; -#endif int npatches = (int)patches.size(); for (int i = 0; i < npatches; i++) { if (patches[i]->getPatchNum() != 0) { // not matrix patch @@ -1181,13 +996,6 @@ int Landscape::checkTotalCover(void) { float sumCover = 0.0; for (int i = 0; i < nHab; i++) { sumCover += cells[y][x]->getHabitat(i); -#if RSDEBUG - //DebugGUI(("Landscape::checkTotalCover(): y=" + Int2Str(y) - // + " x=" + Int2Str(x) - // + " i=" + Int2Str(i) - // + " sumCover=" + Float2Str(sumCover) - // ).c_str()); -#endif } if (sumCover > 100.00001) nCells++; // decimal part to allow for floating point error if (sumCover <= 0.0) // cell is a matrix cell @@ -1209,28 +1017,13 @@ void Landscape::updateHabitatIndices(void) { // convert codes in landscape int h; int changes = (int)landchanges.size(); -#if RSDEBUG - //DebugGUI(("Landscape::updateHabitatIndices(): nHab=" + Int2Str(nHab) - // + " changes=" + Int2Str(changes) - // ).c_str()); -#endif for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not a no-data cell for (int c = 0; c <= changes; c++) { h = cells[y][x]->getHabIndex(c); -#if RSDEBUG - //DebugGUI(("Landscape::updateHabitatIndices() 00000: y=" + Int2Str(y) - // + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) - // ).c_str()); -#endif if (h >= 0) { h = findHabCode(h); -#if RSDEBUG - //DebugGUI(("Landscape::updateHabitatIndices() 11111: y=" + Int2Str(y) - // + " x=" + Int2Str(x) + " c=" + Int2Str(c) + " h=" + Int2Str(h) - // ).c_str()); -#endif cells[y][x]->changeHabIndex(c, h); } } @@ -1248,11 +1041,6 @@ void Landscape::setEnvGradient(Species* pSpecies, bool initial) double envval; // gradient parameters envGradParams grad = paramsGrad->getGradient(); -#if RSDEBUG - //DEBUGLOG << "Landscape::setEnvGradient(): grad.opt_y = " << grad.opt_y - // << " grad.grad_inc = " << grad.grad_inc << " grad.factor " << grad.factor - // << endl; -#endif for (int y = dimY - 1; y >= 0; y--) { for (int x = 0; x < dimX; x++) { // NB: gradient lies in range 0-1 for all types, and is applied when necessary... @@ -1273,11 +1061,6 @@ void Landscape::setEnvGradient(Species* pSpecies, bool initial) break; } } -#if RSDEBUG - //DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x - // << " dist_from_opt=" << dist_from_opt << " rasterType=" << rasterType << " hab=" << hab - // << endl; -#endif if (habK > 0.0) { // suitable cell if (initial) { // set local environmental deviation cells[y][x]->setEnvDev((float)pRandom->Random() * (2.0f) - 1.0f); @@ -1285,11 +1068,6 @@ void Landscape::setEnvGradient(Species* pSpecies, bool initial) dist_from_opt = (float)(fabs((double)grad.opt_y - (double)y)); dev = cells[y][x]->getEnvDev(); envval = 1.0 - dist_from_opt * grad.grad_inc + dev * grad.factor; -#if RSDEBUG - //DEBUGLOG << "Landscape::setEnvGradient(): y=" << y << " x=" << x - // << " dist_from_opt=" << dist_from_opt << " dev=" << dev << " p=" << p - // << endl; -#endif if (envval < 0.000001) envval = 0.0; if (envval > 1.0) envval = 1.0; } @@ -1325,11 +1103,6 @@ void Landscape::updateLocalStoch(void) { for (int x = 0; x < dimX; x++) { if (cells[y][x] != 0) { // not a no-data cell randpart = (float)(pRandom->Normal(0.0, env.std) * sqrt(1.0 - (env.ac * env.ac))); -#if RSDEBUG - //DEBUGLOG << "Landscape::updateLocalStoch(): y=" << y << " x=" << x - // << " env.std= " << env.std << " env.ac= " << env.ac << " randpart= " << randpart - // << endl; -#endif cells[y][x]->updateEps((float)env.ac, randpart); } } @@ -1364,11 +1137,6 @@ void Landscape::resetEffCosts(void) { void Landscape::setDynamicLand(bool dyn) { dynamic = dyn; } void Landscape::addLandChange(landChange c) { -#if RSDEBUG - //DebugGUI(("Landscape::addLandChange(): chgnum=" + Int2Str(c.chgnum) - // + " chgyear=" + Int2Str(c.chgyear) - // ).c_str()); -#endif landchanges.push_back(c); } @@ -1413,12 +1181,6 @@ int Landscape::readLandChange(int filenum, bool costs) if (filenum < 0) return 19; - //if (patchModel && (rasterType == 0 || rasterType == 2)) { - // if (filenum == 0) { // first change - // createPatchChgMatrix(); - // } - // pchseq = patchCount(); - //} if (patchModel) pchseq = patchCount(); #if !RS_RCPP @@ -1543,11 +1305,6 @@ int Landscape::readLandChange(int filenum, bool costs) } #endif } -#if RSDEBUG - //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " h=" + Int2Str(h) + " p=" + Int2Str(p) - //).c_str()); -#endif if (cells[y][x] != 0) { // not a no data cell (in initial landscape) if (h == habnodata) { // invalid no data cell in change map hfile.close(); hfile.clear(); @@ -1687,10 +1444,6 @@ int Landscape::readLandChange(int filenum, bool costs) } #endif } -#if RSDEBUG - //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) - // + " p=" + Int2Str(p)).c_str()); -#endif if (cells[y][x] != 0) { // not a no data cell (in initial landscape) if (h == habnodata) { // invalid no data cell in change map hfile.close(); hfile.clear(); @@ -1795,14 +1548,6 @@ void Landscape::createPatchChgMatrix(void) } } patchChgMatrix[y][x][2] = 0; -#if RSDEBUG - //DebugGUI(("Landscape::createPatchChgMatrix(): y=" + Int2Str(y) - // + " x=" + Int2Str(x) - // + " patchChgMatrix[y][x][0]=" + Int2Str(patchChgMatrix[y][x][0]) - // + " [1]=" + Int2Str(patchChgMatrix[y][x][1]) - // + " [2]=" + Int2Str(patchChgMatrix[y][x][2]) - // ).c_str()); -#endif } } } @@ -1820,15 +1565,6 @@ void Landscape::recordPatchChanges(int landIx) { chg.oldpatch = patchChgMatrix[y][x][2]; chg.newpatch = patchChgMatrix[y][x][0]; patchchanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldpatch=" + Int2Str(chg.oldpatch) - // + " chg.newpatch=" + Int2Str(chg.newpatch) - // ).c_str()); -#endif } } else { // any other change @@ -1838,15 +1574,6 @@ void Landscape::recordPatchChanges(int landIx) { chg.oldpatch = patchChgMatrix[y][x][1]; chg.newpatch = patchChgMatrix[y][x][2]; patchchanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordPatchChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldpatch=" + Int2Str(chg.oldpatch) - // + " chg.newpatch=" + Int2Str(chg.newpatch) - // ).c_str()); -#endif } } // reset cell for next landscape change @@ -1897,14 +1624,6 @@ void Landscape::createCostsChgMatrix(void) costsChgMatrix[y][x][0] = costsChgMatrix[y][x][1] = pCell->getCost(); } costsChgMatrix[y][x][2] = 0; -#if RSDEBUG - //DebugGUI(("Landscape::createCostsChgMatrix(): y=" + Int2Str(y) - // + " x=" + Int2Str(x) - // + " costsChgMatrix[y][x][0]=" + Int2Str(costsChgMatrix[y][x][0]) - // + " [1]=" + Int2Str(costsChgMatrix[y][x][1]) - // + " [2]=" + Int2Str(costsChgMatrix[y][x][2]) - // ).c_str()); -#endif } } } @@ -1925,42 +1644,15 @@ void Landscape::recordCostChanges(int landIx) { chg.oldcost = costsChgMatrix[y][x][2]; chg.newcost = costsChgMatrix[y][x][0]; costschanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldcost=" + Int2Str(chg.oldcost) - // + " chg.newcost=" + Int2Str(chg.newcost) - // ).c_str()); -#endif } } else { // any other change -#if RSDEBUG - //if (x < 20 && y == 0) { - // DEBUGLOG << "Landscape::recordCostChanges(): x=" << x << " y=" << y - // << " costsChgMatrix[y][x][0]=" << costsChgMatrix[y][x][0] - // << " costsChgMatrix[y][x][1]=" << costsChgMatrix[y][x][1] - // << " costsChgMatrix[y][x][2]=" << costsChgMatrix[y][x][2] - // << endl; - //} -#endif if (costsChgMatrix[y][x][2] != costsChgMatrix[y][x][1]) { // record change of cost for current cell chg.chgnum = landIx; chg.x = x; chg.y = y; chg.oldcost = costsChgMatrix[y][x][1]; chg.newcost = costsChgMatrix[y][x][2]; costschanges.push_back(chg); -#if RSDEBUG - //DebugGUI(("Landscape::recordCostsChanges(): landIx=" + Int2Str(landIx) - // + " chg.chgnum=" + Int2Str(chg.chgnum) - // + " chg.x=" + Int2Str(chg.x) - // + " chg.y=" + Int2Str(chg.y) - // + " chg.oldcost=" + Int2Str(chg.oldcost) - // + " chg.newcost=" + Int2Str(chg.newcost) - // ).c_str()); -#endif } } // reset cell for next landscape change @@ -2267,12 +1959,6 @@ int Landscape::readLandscape(int fileNum, string habfile, string pchfile, string return 135; } #endif - -#if RSDEBUG - //DebugGUI(("Landscape::readLandscape(): x=" + Int2Str(x) + " y=" + Int2Str(y) - // + " h=" + Int2Str(h) + " p=" + Int2Str(p) - //).c_str()); -#endif if (h == habnodata) addNewCellToLand(x, y, -1); // add cell only to landscape else { @@ -2374,10 +2060,6 @@ if (patchModel) #endif } //end if patchmodel -#if RSDEBUG -//MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) -// + " p=" + Int2Str(p)).c_str()); -#endif if (h == habnodata) { addNewCellToLand(x, y, -1); // add cell only to landscape } @@ -2526,10 +2208,6 @@ else { // couldn't read from hfile } #endif } -#if RSDEBUG - //MemoLine(("y=" + Int2Str(y) + " x=" + Int2Str(x) + " hfloat=" + Float2Str(hfloat) - // + " p=" + Int2Str(p)).c_str()); -#endif if (h == habnodata) { addNewCellToLand(x, y, -1); // add cell only to landscape } @@ -2635,7 +2313,7 @@ int Landscape::readCosts(string fname) #if !RS_RCPP simView v = paramsSim->getViews(); #endif - +#endif int maxcost = 0; #if RSDEBUG @@ -2710,19 +2388,10 @@ int Landscape::readCosts(string fname) } #endif if (hc < 1 && hc != NODATACost) { -#if RSDEBUG -#if BATCH - // DEBUGLOG << "Landscape::readCosts(): x=" << x << " y=" << y - // << " fcost=" << fcost << " hc=" << hc - // << endl; -#endif -#endif #if RS_RCPP && !R_CMD Rcpp::Rcout << "Cost map my only contain values of 1 or higher, but found " << fcost << "." << endl; #endif // error - zero / negative cost not allowed -// MessageDlg("Error in the costs map file : zero or negative cost detected." -// , mtError, TMsgDlgButtons() << mbOK,0); costs.close(); costs.clear(); return -999; } @@ -2767,40 +2436,16 @@ rasterdata CheckRasterFile(string fname) infile.open(fname.c_str()); if (infile.is_open()) { infile >> header >> r.ncols; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.ncols=" + Int2Str(r.ncols) - ).c_str()); -#endif if (header != "ncols" && header != "NCOLS") r.errors++; infile >> header >> r.nrows; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.nrows=" + Int2Str(r.nrows) - ).c_str()); -#endif if (header != "nrows" && header != "NROWS") r.errors++; infile >> header >> r.xllcorner; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.xllcorner=" + Float2Str(r.xllcorner) - ).c_str()); -#endif if (header != "xllcorner" && header != "XLLCORNER") r.errors++; infile >> header >> r.yllcorner; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.yllcorner=" + Float2Str(r.yllcorner) - ).c_str()); -#endif if (header != "yllcorner" && header != "YLLCORNER") r.errors++; infile >> header >> r.cellsize; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " r.cellsize=" + Int2Str(r.cellsize) - ).c_str()); -#endif if (header != "cellsize" && header != "CELLSIZE") r.errors++; infile >> header >> inint; -#if RSDEBUG - DebugGUI(("CheckRasterFile(): header=" + header + " inint=" + Int2Str(inint) - ).c_str()); -#endif if (header != "NODATA_value" && header != "NODATA_VALUE") r.errors++; infile.close(); infile.clear(); @@ -2823,9 +2468,6 @@ void Landscape::createConnectMatrix(void) { if (connectMatrix != 0) deleteConnectMatrix(); int npatches = (int)patches.size(); -#if RSDEBUG - //DEBUGLOG << "Landscape::createConnectMatrix(): npatches=" << npatches << endl; -#endif connectMatrix = new int* [npatches]; for (int i = 0; i < npatches; i++) { connectMatrix[i] = new int[npatches]; @@ -3025,10 +2667,6 @@ void Landscape::outVisits(int rep, int landNr) { outvisits << "NODATA_value -9" << endl; for (int y = dimY - 1; y >= 0; y--) { -#if RSDEBUG - //DebugGUI(("Landscape::drawLandscape(): y=" + Int2Str(y) - // + " cells[y]=" + Int2Str((int)cells[y])).c_str()); -#endif for (int x = 0; x < dimX; x++) { if (cells[y][x] == 0) { // no-data cell outvisits << "-9 "; From 10ecad7e4466dd7f6cded335b23398b691c5d7f7 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Fri, 9 Feb 2024 12:34:09 +0100 Subject: [PATCH 34/46] fix missing argument --- Landscape.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Landscape.cpp b/Landscape.cpp index b1e3663..bee1045 100644 --- a/Landscape.cpp +++ b/Landscape.cpp @@ -547,7 +547,7 @@ void Landscape::addPatchNum(int p) { /* Create an artificial landscape (random or fractal), which can be either binary (habitat index 0 is the matrix, 1 is suitable habitat) or continuous (0 is the matrix, >0 is suitable habitat) */ -void Landscape::generatePatches(void) +void Landscape::generatePatches(Species* pSpecies) { int x, y, ncells; double p; From f1a63780bb2bcbc3893638a9beef593c0878873a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 11:07:58 +0100 Subject: [PATCH 35/46] fix default constructor --- NeutralStatsManager.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/NeutralStatsManager.h b/NeutralStatsManager.h index 23ce1bb..4b269e0 100644 --- a/NeutralStatsManager.h +++ b/NeutralStatsManager.h @@ -15,9 +15,7 @@ struct PatchMatrix public: - PatchMatrix() {}; - - PatchMatrix(unsigned int rows, unsigned int cols) : _rows(0), _cols(0), _length(0), _val(0) { + PatchMatrix(int rows = 0, int cols = 0) : _rows(0), _cols(0), _length(0), _val(0) { _length = rows * cols; _val.resize(_length); _rows = rows; _cols = cols; From 3fedb66680b5e766bb6054d969d16bc6d7151080 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 14:23:46 +0000 Subject: [PATCH 36/46] fix a few warnings --- Species.cpp | 4 ++-- Species.h | 28 +++++++++++++--------------- SpeciesTrait.cpp | 5 ++++- SpeciesTrait.h | 2 ++ 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Species.cpp b/Species.cpp index 03d0da7..a32c814 100644 --- a/Species.cpp +++ b/Species.cpp @@ -756,8 +756,8 @@ void Species::setSettTraits(const short stg, const short sex, const settleTraits } } -void Species::setGeneticParameters(const set& chromosomeEnds, const int genomeSize, const float recombinationRate, - const set& samplePatchList, const string nIndsToSample, const set& stagesToSampleFrom, string nSampleCellsFst) +void Species::setGeneticParameters(const std::set& chromosomeEnds, const int genomeSize, const float recombinationRate, + const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst) { this->genomeSize = genomeSize; for (auto position : chromosomeEnds) { diff --git a/Species.h b/Species.h index 9cd6377..fc4a79c 100644 --- a/Species.h +++ b/Species.h @@ -49,6 +49,8 @@ #include "SpeciesTrait.h" #include "TTrait.h" #include +#include +#include // structures for demographic parameters @@ -280,7 +282,7 @@ class Species { short // option: 0 = return minimum, otherwise = return maximum ); - set& getSamplePatches() { + std::set& getSamplePatches() { return samplePatchList; }; @@ -288,7 +290,7 @@ class Species { return nIndsToSample; }; - set& getStagesToSample() { + std::set& getStagesToSample() { return stagesToSampleFrom; } @@ -419,19 +421,16 @@ class Species { //map>& getTraitTable(void); //return by reference so ensure variable recieving is const - set getTraitTypes(); + std::set getTraitTypes(); int getNTraits() const; int getNPositionsForTrait(const TraitType trait) const; int getGenomeSize() const; - void setGenomeSize(int); float getRecombinationRate() const; - void setRecombinationRate(float); - set getChromosomeEnds() const; - void setChromosomeEnds(const set& ends); - void setGeneticParameters(const set& chromosomeEnds, const int genomeSize, const float recombinationRate, - const set& samplePatchList, const string nIndsToSample, const set& stagesToSampleFrom, string nSampleCellsFst); - void setSamplePatchList(const set& samplePatchList); + std::set getChromosomeEnds() const; + void setGeneticParameters(const std::set& chromosomeEnds, const int genomeSize, const float recombinationRate, + const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst); + void setSamplePatchList(const std::set& samplePatchList); private: @@ -484,17 +483,17 @@ class Species { // genome parameters /**The traits table.*/ - map> spTraitTable; - set chromosomeEnds; + std::map> spTraitTable; + std::set chromosomeEnds; int genomeSize; bool diploid; bool mutationsOn; int numberOfNeutralLoci; int numberOfAdaptiveTraits; float recombinationRate; - set samplePatchList; + std::set samplePatchList; string nSampleCellsFst; //for cell based landscape - set stagesToSampleFrom; + std::set stagesToSampleFrom; string nIndsToSample; //could be integer or 'all', all means in in selected patches not necessarily all in population // emigration parameters @@ -569,7 +568,6 @@ class Species { float betaS[NSTAGES][NSEXES]; // inflection point of the settlement reaction norm to density // other attributes - int spNum; }; diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 7d5264a..6ce6354 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -1,6 +1,5 @@ #include "SpeciesTrait.h" -#include "Species.h" //could be handled in header file but here for now for flexibility SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { @@ -53,6 +52,7 @@ TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) con else if (str == "kernel_probability") return KERNEL_PROBABILITY_M; else if (str == "crw_stepLength") return CRW_STEPLENGTH_M; else if (str == "crw_stepCorrelation") return CRW_STEPCORRELATION_M; + else throw logic_error(str + " is not a valid trait type."); } else { if (str == "emigration_d0") return E_D0_F; else if (str == "emigration_alpha") return E_ALPHA_F; @@ -71,6 +71,7 @@ TraitType SpeciesTrait::stringToTraitType(const std::string& str, sex_t sex) con else if (str == "sms_betaDB") return SMS_BETADB; else if (str == "neutral") return SNP; else if (str == "adaptive") return ADAPTIVE; + else throw logic_error(str + " is not a valid trait type."); } } @@ -79,6 +80,7 @@ ExpressionType SpeciesTrait::stringToExpressionType(const std::string& str) cons else if (str == "additive") return ADDITIVE; else if (str == "multiplicative") return MULTIPLICATIVE; else if (str == "#") return NEUTRAL; + else throw logic_error(str + " is not a valid gene expression type."); } DistributionType SpeciesTrait::stringToDistributionType(const std::string& str) const @@ -91,6 +93,7 @@ DistributionType SpeciesTrait::stringToDistributionType(const std::string& str) else if (str == "negExp") return NEGEXP; else if (str == "KAM") return KAM; else if (str == "SSM") return SSM; + else throw logic_error(str + " is not a valid distribution type."); } map SpeciesTrait::stringToParameterMap(string parameters) const { diff --git a/SpeciesTrait.h b/SpeciesTrait.h index 3894207..c31b21e 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -2,6 +2,8 @@ #define SPECIESTRAITH #include "Parameters.h" +#include "Species.h" + #include #include #include From 6ec8a760dd3c45126f4cb114e4cdddf02cfae8a1 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 16:30:49 +0000 Subject: [PATCH 37/46] fix undefined function call --- Parameters.h | 2 -- SpeciesTrait.cpp | 55 ++++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Parameters.h b/Parameters.h index 23d8bda..dab5a56 100644 --- a/Parameters.h +++ b/Parameters.h @@ -159,9 +159,7 @@ typedef enum { KERNEL, SMS, CRW} movement_t; //GeneType convertToGeneType(const string& ); -float convertParameters(string, string); bool iequals(std::string_view lhs, std::string_view rhs); -set convertStringToSet(string); set convertStringToPatches(string, int, Landscape*); set convertStringToStages(string); set convertStringToChromosomeEnds(string, int); diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 6ce6354..9f02d2c 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -138,29 +138,38 @@ set SpeciesTrait::stringToLoci(string pos, string nLoci, Species* pSpecies) set positions; if (pos != "random") { - //stringstream ss(pos); - - //string value, valueWithin; - //while (std::getline(ss, value, ',')) { - // stringstream sss(value); - // vector minMax; - // while (std::getline(sss, valueWithin, '-')) { - // minMax.push_back(stoi(valueWithin)); - // } - // if (minMax[0] > pSpecies->getGenomeSize() || minMax[1] > pSpecies->getGenomeSize()) { - // cout << endl << "Traits file: ERROR - trait positions must not exceed genome size" << endl; - // } - // else { - // if (minMax.size() > 1) { - // for (int i = minMax[0]; i < minMax[1] + 1; ++i) { - // positions.insert(i); - // } - // } - // else - // positions.insert(minMax[0]); - // } - //} - positions = convertStringToSet(pos); + + // Parse comma-separated list from input string + stringstream ss(pos); + string value, valueWithin; + // Read comma-separated positions + while (std::getline(ss, value, ',')) { + stringstream sss(value); + vector positionRange; + // Read single positions and dash-separated ranges + while (std::getline(sss, valueWithin, '-')) { + positionRange.push_back(stoi(valueWithin)); + } + switch (positionRange.size()) + { + case 1: // single position + if (positionRange[0] > pSpecies->getGenomeSize()) + throw logic_error("Traits file: ERROR - trait positions must not exceed genome size"); + positions.insert(positionRange[0]); + break; + case 2: // dash-separated range + if (positionRange[0] > pSpecies->getGenomeSize() || positionRange[1] > pSpecies->getGenomeSize()) { + throw logic_error("Traits file: ERROR - trait positions must not exceed genome size"); + } + for (int i = positionRange[0]; i < positionRange[1] + 1; ++i) { + positions.insert(i); + } + break; + default: // zero or more than 2 values between commas: error + throw logic_error("Traits file: ERROR - incorrectly formatted position range."); + break; + } + } for (auto position : positions) { if (position > pSpecies->getGenomeSize()) From 3c7f1536262aee7939b866dbd3dfde60e266184a Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 16:37:37 +0000 Subject: [PATCH 38/46] define undefined stringToSex functiono --- Parameters.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Parameters.cpp b/Parameters.cpp index 9275e29..1f27f13 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -395,6 +395,12 @@ string paramSim::getDir(int option) { return s; } +const sex_t stringToSex(const std::string& str) { + if (str == "female") return FEM; + else if (str == "male") return MAL; + else throw logic_error("Traits file: ERROR - sex can either be 'female' or 'male'."); +} + #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } bool paramSim::getCreatePopFile(void) { return CreatePopFile; } From d8c910fa4914bbf3cf7f1b940cb9260984fcc97c Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Mon, 12 Feb 2024 17:54:11 +0000 Subject: [PATCH 39/46] add definition for undefined function convertStringToChromosomeEnds --- Parameters.cpp | 27 +++++++++++++++++++++++++++ Species.cpp | 4 ---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Parameters.cpp b/Parameters.cpp index 1f27f13..2a0b114 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -401,6 +401,33 @@ const sex_t stringToSex(const std::string& str) { else throw logic_error("Traits file: ERROR - sex can either be 'female' or 'male'."); } +set convertStringToPatches(string str, int nb_patches, Landscape* pLandscape) { + +} + +set convertStringToChromosomeEnds(string str, int genomeSize) { + set chromosomeEnds; + if (str == "#") + chromosomeEnds.insert(genomeSize - 1); // last position in genome + else { + // Parse comma-separated list from input string + stringstream ss(str); + string strPos; + int pos; + // Read comma-separated positions + while (std::getline(ss, strPos, ',')) { + pos = std::stoi(strPos); + if (pos > genomeSize) + throw logic_error("Genetics file: ERROR - chromosome ends must not exceed genome size."); + else { + chromosomeEnds.insert(pos); + } + } + } + return chromosomeEnds; +} + + #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } bool paramSim::getCreatePopFile(void) { return CreatePopFile; } diff --git a/Species.cpp b/Species.cpp index a32c814..ca68b90 100644 --- a/Species.cpp +++ b/Species.cpp @@ -760,10 +760,6 @@ void Species::setGeneticParameters(const std::set& chromosomeEnds, const in const std::set& samplePatchList, const string nIndsToSample, const std::set& stagesToSampleFrom, string nSampleCellsFst) { this->genomeSize = genomeSize; - for (auto position : chromosomeEnds) { - if (position > this->getGenomeSize() - 1) - cout << endl << "Genetics file: ERROR - chromosome ends " << position << " must not exceed genome size" << endl; - } this->chromosomeEnds = chromosomeEnds; this->recombinationRate = recombinationRate; this->samplePatchList = samplePatchList; From 1641aff7eb853fcabbc54814c19de333adcbba7f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 11:42:39 +0000 Subject: [PATCH 40/46] defined missing functions convertStringToStages and convertStringToPatches --- Landscape.h | 1 + Parameters.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- Parameters.h | 8 +++--- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/Landscape.h b/Landscape.h index cda6cee..4ef9231 100644 --- a/Landscape.h +++ b/Landscape.h @@ -234,6 +234,7 @@ class Landscape { void setCellArray(void); void addPatchNum(int); + std::vector getPatchNums() const { return patchnums; } void generatePatches(Species*); // create an artificial landscape void allocatePatches(Species*); // create patches for a cell-based landscape Patch* newPatch( diff --git a/Parameters.cpp b/Parameters.cpp index 2a0b114..4138822 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -401,8 +401,44 @@ const sex_t stringToSex(const std::string& str) { else throw logic_error("Traits file: ERROR - sex can either be 'female' or 'male'."); } -set convertStringToPatches(string str, int nb_patches, Landscape* pLandscape) { - +set convertStringToPatches(const string& str, const int& nb_rnd_patches, const vector& existingPatches) { + + set patches; + + if (str == "random") { + if (nb_rnd_patches > existingPatches.size()) { + throw logic_error("Genetics file: ERROR - Nb of patches to randomly sample exceeds nb of existing patches."); + } else { + // Sample without replacement + std::sample( + existingPatches.begin(), + existingPatches.end(), + patches.begin(), + nb_rnd_patches, + pRandom->getRNG() + ); + } + } else if (str == "all") { + // Copy all patches into sampled patches + for (int pch : existingPatches) patches.insert(pch); + } else { + // comma-separated list of patches + stringstream ss(str); + string strPch; + int pch; + bool patchExists; + // Read comma-separated values + while (std::getline(ss, strPch, ',')) { + pch = std::stoi(strPch); + patchExists = std::find(existingPatches.begin(), existingPatches.end(), pch) != existingPatches.end(); + if (!patchExists) + throw logic_error("Genetics file: ERROR - sampled patch does not exist."); + else { + patches.insert(pch); + } + } + } + return patches; } set convertStringToChromosomeEnds(string str, int genomeSize) { @@ -427,6 +463,32 @@ set convertStringToChromosomeEnds(string str, int genomeSize) { return chromosomeEnds; } +set convertStringToStages(const string& str, const int& nbStages) { + set stages; + if (str == "all") { + for (int stg = 0; stg < nbStages; ++stg) { + stages.insert(stg); + } + } + else { + // Parse comma-separated list from input string + stringstream ss(str); + string strStg; + int stg; + // Read comma-separated values + while (std::getline(ss, strStg, ',')) { + stg = std::stoi(strStg); + if (stg > nbStages - 1) + throw logic_error("Genetics file: ERROR - sampled stage exceeds number of stages."); + else { + stages.insert(stg); + } + } + } + return stages; +} + + #if RS_RCPP bool paramSim::getReturnPopRaster(void) { return ReturnPopRaster; } diff --git a/Parameters.h b/Parameters.h index dab5a56..01009a3 100644 --- a/Parameters.h +++ b/Parameters.h @@ -64,8 +64,6 @@ using namespace std; #include "RSrandom.h" -class Landscape; - #define NODATACOST 100000 // cost to use in place of nodata value for SMS; #define ABSNODATACOST 100 // cost to use in place of nodata value for SMS; // when boundaries are absorbing @@ -160,8 +158,8 @@ typedef enum { KERNEL, SMS, CRW} movement_t; //GeneType convertToGeneType(const string& ); bool iequals(std::string_view lhs, std::string_view rhs); -set convertStringToPatches(string, int, Landscape*); -set convertStringToStages(string); +set convertStringToPatches(const string&, const int&, const vector&); +set convertStringToStages(const string&, const int&); set convertStringToChromosomeEnds(string, int); //sex types @@ -449,5 +447,7 @@ extern ofstream DEBUGLOG; void DebugGUI(string); #endif +extern RSrandom* pRandom; + //--------------------------------------------------------------------------- #endif From fc7c3f4db4216c18c4c7c7650ad44f69d41ce106 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 12:47:41 +0000 Subject: [PATCH 41/46] rm iequals() --- Parameters.h | 1 - SpeciesTrait.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Parameters.h b/Parameters.h index 01009a3..344f8ac 100644 --- a/Parameters.h +++ b/Parameters.h @@ -157,7 +157,6 @@ typedef enum { KERNEL, SMS, CRW} movement_t; //GeneType convertToGeneType(const string& ); -bool iequals(std::string_view lhs, std::string_view rhs); set convertStringToPatches(const string&, const int&, const vector&); set convertStringToStages(const string&, const int&); set convertStringToChromosomeEnds(string, int); diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index 9f02d2c..aa56340 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -19,7 +19,7 @@ SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { if (traitType == SNP || traitType == ADAPTIVE) this->inherited = true; else - this->inherited = iequals(parameters[10], "true") ? true : false; + this->inherited = (parameters[10] == "true") ? true : false; if (this->isInherited()) { this->mutationDistribution = stringToDistributionType(parameters[11]); From c7c95da1b421b838ffad54ab820d4bad73ad4e93 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 13:38:32 +0000 Subject: [PATCH 42/46] fwd declaration to fix circular dependency issue --- Species.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Species.h b/Species.h index fc4a79c..bedfcb7 100644 --- a/Species.h +++ b/Species.h @@ -52,6 +52,8 @@ #include #include +class SpeciesTrait; + // structures for demographic parameters struct demogrParams { From ce60603783568ad0f2e3a625bc8bf61e9d416d25 Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 13:43:50 +0000 Subject: [PATCH 43/46] clarify chromosome switch; compiler mistakes it for bitwise operation --- GeneticLoad.cpp | 4 ++-- SNPTrait.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 7e45c19..4fd5588 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -319,7 +319,7 @@ void GeneticLoad::inheritDiploid(sex_t whichChromosome, map nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; - parentChromosome = !parentChromosome; // switch to the other one + parentChromosome = 1 - parentChromosome; // switch to the other one } if (locus <= nextBreakpoint) { diff --git a/SNPTrait.cpp b/SNPTrait.cpp index c144715..167cb84 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -199,7 +199,7 @@ void SNPTrait::inheritDiploid(sex_t whichChromosome, map nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; - parentChromosome = !parentChromosome; //switch chromosome + parentChromosome = 1 - parentChromosome; //switch chromosome } if (locus <= nextBreakpoint) { From d6aba0df44dc6ba1bb30586a98fbaa362fad5fbb Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 14:06:41 +0000 Subject: [PATCH 44/46] fix set iterators --- Parameters.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Parameters.cpp b/Parameters.cpp index 4138822..6e25de6 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -413,14 +413,17 @@ set convertStringToPatches(const string& str, const int& nb_rnd_patches, co std::sample( existingPatches.begin(), existingPatches.end(), - patches.begin(), - nb_rnd_patches, + std::inserter(patches, patches.end()), + nb_rnd_patches, pRandom->getRNG() ); } } else if (str == "all") { // Copy all patches into sampled patches - for (int pch : existingPatches) patches.insert(pch); + std::copy(existingPatches.begin(), + existingPatches.end(), + std::inserter(patches, patches.end()) + ); } else { // comma-separated list of patches stringstream ss(str); From bf735ccb3a59cd02601c1131769edb45334d9c6f Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 15:26:55 +0000 Subject: [PATCH 45/46] fix a bunch of warnings and messages --- Allele.h | 2 +- GeneticLoad.cpp | 68 ++++++++++++++++++++--------------------- Individual.h | 6 ++-- NeutralStatsManager.cpp | 14 ++++----- Population.cpp | 6 ++-- QTLTrait.cpp | 36 +++++++++++----------- SNPTrait.cpp | 7 ++--- Species.cpp | 2 +- SpeciesTrait.cpp | 2 +- SpeciesTrait.h | 2 +- SubCommunity.cpp | 3 -- 11 files changed, 72 insertions(+), 76 deletions(-) diff --git a/Allele.h b/Allele.h index 7f8a0a8..1b00706 100644 --- a/Allele.h +++ b/Allele.h @@ -11,6 +11,6 @@ class Allele { ~Allele() {} float getAlleleValue() const { return value; }; float getDominanceCoef() const { return dominance; }; - float getId() const { return id; } + int getId() const { return id; } }; #endif \ No newline at end of file diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index 4fd5588..b467c9a 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -21,39 +21,39 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) switch (mutationDistribution) { case UNIFORM: { - if (!mutationParameters.count(MAX)) - cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain max value (e.g. max= ) \n"); + if (mutationParameters.count(MAX) != 1) + cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain one max value (e.g. max= ) \n"); - if (!mutationParameters.count(MIN)) - cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain min value (e.g. min= ) \n"); + if (mutationParameters.count(MIN) != 1) + cout << endl << ("Error:: adaptive mutation uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { - if (!mutationParameters.count(MEAN)) - cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + if (mutationParameters.count(MEAN) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - if (!mutationParameters.count(SDEV)) - cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + if (mutationParameters.count(SDEV) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { - if (!mutationParameters.count(SHAPE)) - cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain shape value (e.g. shape= ) \n"); + if (mutationParameters.count(SHAPE) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); - if (!mutationParameters.count(SCALE)) - cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain scale value (e.g. scale= ) \n"); + if (mutationParameters.count(SCALE) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { - if (!mutationParameters.count(MEAN)) - cout << endl << ("Error:: adaptive mutation distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); + if (mutationParameters.count(MEAN) != 1) + cout << endl << ("Error:: adaptive mutation distribution set to negative exponential (negative decay) so parameters must contain one mean value (e.g. mean= ) \n"); break; } @@ -70,38 +70,38 @@ GeneticLoad::GeneticLoad(SpeciesTrait* P) switch (dominanceDistribution) { case UNIFORM: { - if (!dominanceParameters.count(MAX)) - cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain max value (e.g. max= ) \n"); + if (dominanceParameters.count(MAX) != 1) + cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain one max value (e.g. max= ) \n"); - if (!dominanceParameters.count(MIN)) - cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain min value (e.g. min= ) \n"); + if (dominanceParameters.count(MIN) != 1) + cout << endl << ("Error:: adaptive dominance uniform distribution parameter must contain one min value (e.g. min= ) \n"); break; } case NORMAL: { - if (!dominanceParameters.count(MEAN)) - cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); + if (dominanceParameters.count(MEAN) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain one mean value (e.g. mean= ) \n"); - if (!dominanceParameters.count(SDEV)) - cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); + if (dominanceParameters.count(SDEV) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to normal so parameters must contain one sdev value (e.g. sdev= ) \n"); break; } case GAMMA: { - if (!dominanceParameters.count(SHAPE)) - cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain shape value (e.g. shape= ) \n"); + if (dominanceParameters.count(SHAPE) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain one shape value (e.g. shape= ) \n"); - if (!dominanceParameters.count(SCALE)) - cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain scale value (e.g. scale= ) \n"); + if (dominanceParameters.count(SCALE) != 1) + cout << endl << ("Error:: adaptive dominance distribution set to gamma so parameters must contain one scale value (e.g. scale= ) \n"); break; } case NEGEXP: { - if (!dominanceParameters.count(MEAN)) + if (dominanceParameters.count(MEAN) != 1) cout << endl << ("Error:: adaptive dominance distribution set to negative exponential (negative decay) so parameters must contain mean value (e.g. mean= ) \n"); break; @@ -363,8 +363,8 @@ float GeneticLoad::express() { for (auto const& [locus, pAllelePair] : genes) { - auto pAlleleLeft = (!pAllelePair[0]) ? wildType : pAllelePair[0]; - auto pAlleleRight = (!pAllelePair[1]) ? wildType : pAllelePair[1]; + shared_ptr pAlleleLeft = (!pAllelePair[0]) ? wildType : pAllelePair[0]; + shared_ptr pAlleleRight = (!pAllelePair[1]) ? wildType : pAllelePair[1]; if (pAlleleLeft.get()->getId() != pAlleleRight.get()->getId()) // heterozygote { @@ -391,9 +391,9 @@ bool GeneticLoad::isHeterozygoteAtLocus(int locus) const { if (it == genes.end()) //not found so must be wildtype homozygous return false; else { - auto a = (!it->second[0]) ? wildType : it->second[0]; - auto b = (!it->second[1]) ? wildType : it->second[1]; - return a != b; + shared_ptr alleleRight = (!it->second[0]) ? wildType : it->second[0]; + shared_ptr alleleLeft = (!it->second[1]) ? wildType : it->second[1]; + return alleleRight != alleleLeft; } } @@ -407,8 +407,8 @@ int GeneticLoad::countHeterozygoteLoci() const { int count = 0; for (auto const& [locus, allelePair] : genes) { - auto alleleLeft = (!allelePair[0]) ? wildType : allelePair[0]; - auto alleleRight = (!allelePair[1]) ? wildType : allelePair[1]; + shared_ptr alleleLeft = (!allelePair[0]) ? wildType : allelePair[0]; + shared_ptr alleleRight = (!allelePair[1]) ? wildType : allelePair[1]; count += alleleLeft != alleleRight; } return count; diff --git a/Individual.h b/Individual.h index 2245c1a..71d986a 100644 --- a/Individual.h +++ b/Individual.h @@ -123,7 +123,7 @@ struct crwData : trfrData { // to hold data for CRW movement model void clone(const trfrData& copyFrom) { - auto pCopy = dynamic_cast(copyFrom); + const crwData& pCopy = dynamic_cast(copyFrom); stepLength = pCopy.stepLength; rho = pCopy.rho; @@ -154,7 +154,7 @@ struct smsData : trfrData { //static float stepMort; //static bool straigtenPath; - smsData(locn prevA, locn goalA) : prev(prevA), goal(goalA), dp(0.0), gb(0.0), alphaDB(0.0), betaDB(0.0) {} + smsData(locn prevA, locn goalA) : prev(prevA), goal(goalA), dp(0.0), gb(0.0), alphaDB(0.0), betaDB(0) {} ~smsData() {} @@ -206,7 +206,7 @@ struct kernelData : trfrData { movement_t getType() { return KERNEL; } void clone(const trfrData& copyFrom) { - auto pCopy = dynamic_cast(copyFrom); + const kernelData& pCopy = dynamic_cast(copyFrom); meanDist1 = pCopy.meanDist1; meanDist2 = pCopy.meanDist2; probKern1 = pCopy.probKern1; diff --git a/NeutralStatsManager.cpp b/NeutralStatsManager.cpp index de578c5..3c0b15a 100644 --- a/NeutralStatsManager.cpp +++ b/NeutralStatsManager.cpp @@ -29,7 +29,7 @@ // ---------------------------------------------------------------------------------------- NeutralStatsManager::NeutralStatsManager(set const& patchList, const int nLoci) { - this->_fst_matrix = PatchMatrix(patchList.size(), patchList.size()); + this->_fst_matrix = PatchMatrix(static_cast(patchList.size()), static_cast(patchList.size())); globalAlleleTable.reserve(nLoci); //don't have to be pointers, not shared or moved } @@ -282,17 +282,17 @@ void NeutralStatsManager::calculateFstatWC(set const& patchList, const int int patchSize = pPop->sampleSize(); if (patchSize) { extantPs++; - sum_weights += (patchSize * patchSize / nInds); + sum_weights += (patchSize * patchSize / static_cast(nInds)); } } _n_extantPopulations = extantPs; _n_individuals = nInds; - n_bar = nInds / extantPs; + n_bar = nInds / static_cast(extantPs); n_c = (nInds - sum_weights) / (extantPs - 1); - inverse_n_bar = 1 / (n_bar - 1); - inverse_n_total = 1 / nInds; + inverse_n_bar = 1.0 / (n_bar - 1); + inverse_n_total = 1.0 / nInds; double var; double s2, p_bar, h_bar; @@ -359,7 +359,7 @@ void NeutralStatsManager::calculateFstatWC_MS(set const& patchList, const i int patchSize = pPop->sampleSize(); if (patchSize) { extantPs++; - sum_weights += (patchSize * patchSize / nInds); + sum_weights += (patchSize * patchSize / static_cast(nInds)); } } @@ -550,7 +550,7 @@ void NeutralStatsManager::setFstMatrix(set const& patchList, const int nInd copy(patchList.begin(), patchList.end(), std::back_inserter(patchVect)); //needs to be in vector to iterate over, copy preserves order - int nPatches = patchList.size(); + int nPatches = static_cast(patchList.size()); //initialise diff --git a/Population.cpp b/Population.cpp index 199e3c6..4615951 100644 --- a/Population.cpp +++ b/Population.cpp @@ -378,7 +378,7 @@ void Population::updateAlleleTable() { std::for_each(alleleTable.begin(), alleleTable.end(), [&](NeutralData& v) -> void { - v.setFrequencies(sampledInds.size() * 2); + v.setFrequencies(static_cast(sampledInds.size()) * 2); //v->divideHeteros(sampledInds.size()); //weir and cockerham doesn't need this division?? }); } @@ -926,7 +926,7 @@ void Population::fledge(void) } Individual* Population::sampleInd() const { - int index = pRandom->IRandom(0, inds.size() - 1); + int index = pRandom->IRandom(0, static_cast(inds.size() - 1)); return inds[index]; } @@ -953,7 +953,7 @@ void Population::sampleIndsWithoutReplacement(string n, const set& sampleSt } int Population::sampleSize() const { - return sampledInds.size(); + return static_cast(sampledInds.size()); } set Population::getIndividualsInStage(int stage) { diff --git a/QTLTrait.cpp b/QTLTrait.cpp index 6c9d451..1b38fee 100644 --- a/QTLTrait.cpp +++ b/QTLTrait.cpp @@ -20,10 +20,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) switch (mutationDistribution) { case UNIFORM: { - if (!mutationParameters.count(MAX)) + if (mutationParameters.count(MAX) != 1) cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); - if (!mutationParameters.count(MIN)) + if (mutationParameters.count(MIN) != 1) cout << endl << ("Error:: mutation uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); _mutate_func_ptr = &QTLTrait::mutateUniform; @@ -31,10 +31,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } case NORMAL: { - if (!mutationParameters.count(MEAN)) + if (mutationParameters.count(MEAN) != 1) cout << endl << ("Error:: qtl mutation distribution set to normal so parameters must contain mean value (e.g. mean= ) \n"); - if (!mutationParameters.count(SDEV)) + if (mutationParameters.count(SDEV) != 1) cout << endl << ("Error::qtl mutation distribution set to normal so parameters must contain sdev value (e.g. sdev= ) \n"); _mutate_func_ptr = &QTLTrait::mutateNormal; @@ -55,10 +55,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) switch (initialDistribution) { case UNIFORM: { - if (!initialParameters.count(MAX)) + if (initialParameters.count(MAX) != 1) cout << endl << ("Error:: initial uniform qtl distribution parameter must contain max value (e.g. max= ) \n"); - if (!initialParameters.count(MIN)) + if (initialParameters.count(MIN) != 1) cout << endl << ("Error:: initial uniform qtl distribution parameter must contain min value (e.g. min= ) \n"); float maxD = initialParameters.find(MAX)->second; @@ -69,10 +69,10 @@ QTLTrait::QTLTrait(SpeciesTrait* P) } case NORMAL: { - if (!initialParameters.count(MEAN)) + if (initialParameters.count(MEAN) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain mean value (e.g. mean= ) \n"); - if (!initialParameters.count(SDEV)) + if (initialParameters.count(SDEV) != 1) cout << endl << ("Error:: initial normal qtl distribution parameter must contain sdev value (e.g. sdev= ) \n"); float mean = initialParameters.find(MEAN)->second; @@ -209,18 +209,18 @@ void QTLTrait::inheritDiploid(sex_t whichChromosome, mapfirst); - unsigned int nextBreakpoint = *it; + int nextBreakpoint = *it; auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) - parentChromosome = !parentChromosome; //switch chromosome + parentChromosome = 1 - parentChromosome; //switch chromosome for (auto const& [locus, allelePair] : parentGenes) { while (locus > nextBreakpoint) { std::advance(it, 1); nextBreakpoint = *it; - parentChromosome = !parentChromosome; //switch chromosome + parentChromosome = 1 - parentChromosome; //switch chromosome } if (locus <= nextBreakpoint) { @@ -258,10 +258,10 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapsecond; @@ -273,10 +273,10 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapsecond; @@ -303,7 +303,7 @@ void QTLTrait::inheritInitialParameters(sex_t whichChromosome, mapgetPositions(); + const set positions = pSpeciesTrait->getPositions(); short ploidy = pSpeciesTrait->getPloidy(); for (auto position : positions) { @@ -318,7 +318,7 @@ void QTLTrait::initialiseNormal(float mean, float sd) { void QTLTrait::initialiseUniform(float min, float max) { - const auto positions = pSpeciesTrait->getPositions(); + const set positions = pSpeciesTrait->getPositions(); short ploidy = pSpeciesTrait->getPloidy(); for (auto position : positions) { @@ -341,7 +341,7 @@ float QTLTrait::expressAdditive() { for (auto const& [locus, allelePair] : genes) { - for (auto m : allelePair) + for (const std::shared_ptr m : allelePair) phenotype += m->getAlleleValue(); } return phenotype; diff --git a/SNPTrait.cpp b/SNPTrait.cpp index 167cb84..102d9cf 100644 --- a/SNPTrait.cpp +++ b/SNPTrait.cpp @@ -21,7 +21,7 @@ SNPTrait::SNPTrait(SpeciesTrait* P) if (mutationDistribution != SSM && mutationDistribution != KAM) cout << endl << ("Error:: wrong mutation distribution for neutral markers, must be KAM or SSM \n"); - if (!mutationParameters.count(MAX)) + if (mutationParameters.count(MAX) != 1) cout << endl << ("Error:: KAM or SSM mutation distribution parameter must contain max value (e.g. max= ), max cannot exceed 256 \n"); if (wildType == -999) @@ -39,8 +39,8 @@ SNPTrait::SNPTrait(SpeciesTrait* P) switch (initialDistribution) { case UNIFORM: { - if (!initialParameters.count(MAX)) - cout << endl << "Error:: initial SNP/Microsat distribution parameter must contain max value if set to UNIFORM (e.g. max= ), max cannot exceed " << maxSNPAlleles << "\n"; + if (initialParameters.count(MAX) != 1) + cout << endl << "Error:: initial SNP/Microsat distribution parameter must contain one max value if set to UNIFORM (e.g. max= ), max cannot exceed " << maxSNPAlleles << "\n"; float maxD = initialParameters.find(MAX)->second; if (maxD > maxSNPAlleles) { @@ -83,7 +83,6 @@ SNPTrait::SNPTrait(const SNPTrait& T) : // ---------------------------------------------------------------------------------------- void SNPTrait::mutate_KAM() { - const int positionsSize = pProtoTrait->getPositionsSize(); const auto& positions = pProtoTrait->getPositions(); const short ploidy = pProtoTrait->getPloidy(); diff --git a/Species.cpp b/Species.cpp index ca68b90..459c3d3 100644 --- a/Species.cpp +++ b/Species.cpp @@ -478,7 +478,7 @@ set Species::getTraitTypes() { } int Species::getNTraits() const { - return spTraitTable.size(); + return static_cast(spTraitTable.size()); } int Species::getNPositionsForTrait(const TraitType trait) const { diff --git a/SpeciesTrait.cpp b/SpeciesTrait.cpp index aa56340..f8c5d8a 100644 --- a/SpeciesTrait.cpp +++ b/SpeciesTrait.cpp @@ -34,7 +34,7 @@ SpeciesTrait::SpeciesTrait(vector parameters, Species* pSpecies) { if (pSpecies->getNumberOfNeutralLoci() > 0) cout << endl << "Traits file: WARNING - can only have one set of neutral markers, overwriting previous" << endl; - else pSpecies->setNumberOfNeutralLoci(positions.size()); + else pSpecies->setNumberOfNeutralLoci(static_cast(positions.size())); } } diff --git a/SpeciesTrait.h b/SpeciesTrait.h index c31b21e..9a634cb 100644 --- a/SpeciesTrait.h +++ b/SpeciesTrait.h @@ -36,7 +36,7 @@ class SpeciesTrait { float getMutationRate() const { return mutationRate; } short getPloidy() const { return ploidy; } set& getPositions() { return positions; } // returning by reference, make sure receiver is const - int getPositionsSize() const { return positions.size(); } + int getPositionsSize() const { return static_cast(positions.size()); } bool isInherited() const { return inherited; } DistributionType getMutationDistribution() const { return mutationDistribution; }; map getMutationParameters() const { return mutationParameters; }; diff --git a/SubCommunity.cpp b/SubCommunity.cpp index 67dbebf..5164444 100644 --- a/SubCommunity.cpp +++ b/SubCommunity.cpp @@ -1111,9 +1111,6 @@ traitsums SubCommunity::outTraits(traitCanvas tcanv, } // CURRENTLY INDIVIDUAL VARIATION CANNOT BE SEX-DEPENDENT -// ngenes = 1; - double mnS0[2], mnAlpha[2], mnBeta[2], sdS0[2], sdAlpha[2], sdBeta[2]; - if (writefile) outtraits << endl; for (int s = 0; s < NSEXES; s++) { From ab4dc2cb0b2d165d439415271d01d798ae72afea Mon Sep 17 00:00:00 2001 From: Theo Pannetier Date: Tue, 13 Feb 2024 16:14:41 +0000 Subject: [PATCH 46/46] more warnings and messages fixes --- Community.cpp | 17 +++++++++-------- GeneticLoad.cpp | 18 +++++++++--------- Population.cpp | 20 ++++++++++++-------- Population.h | 1 - 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Community.cpp b/Community.cpp index 38d991b..a8f7673 100644 --- a/Community.cpp +++ b/Community.cpp @@ -64,7 +64,7 @@ void Community::initialise(Species* pSpecies, int year) int nsubcomms, npatches, ndistcells, spratio, patchnum, rr = 0; locn distloc; patchData pch; - patchLimits limits; + patchLimits limits = patchLimits(); intptr ppatch, subcomm; std::vector subcomms; std::vector selected; @@ -257,7 +257,8 @@ void Community::initialise(Species* pSpecies, int year) indIx = 0; // reset index for initial individuals } else { // add any initial individuals for the current year - initInd iind; iind.year = 0; + initInd iind = initInd(); + iind.year = 0; int ninds = paramsInit->numInitInds(); while (indIx < ninds && iind.year <= year) { iind = paramsInit->getInitInd(indIx); @@ -505,7 +506,7 @@ void Community::dispersal(short landIx) #endif // SEASONAL || RS_RCPP { #if RSDEBUG - int t0, t1, t2; + time_t t0, t1, t2; t0 = time(0); #endif @@ -631,7 +632,7 @@ void Community::deleteOccupancy(int nrows) { // Determine range margins commStats Community::getStats(void) { - commStats s; + commStats s = commStats(); landParams ppLand = pLandscape->getLandParams(); s.ninds = s.nnonjuvs = s.suitable = s.occupied = 0; s.minX = ppLand.maxX; s.minY = ppLand.maxY; s.maxX = s.maxY = 0; @@ -883,9 +884,9 @@ void Community::outRange(Species* pSpecies, int rep, int yr, int gen) outrange << "\t0\t0\t0\t0"; if (emig.indVar || trfr.indVar || sett.indVar) { // output trait means - traitsums ts; + traitsums ts = traitsums(); traitsums scts; // sub-community traits - traitCanvas tcanv; + traitCanvas tcanv = traitCanvas(); int ngenes, popsize; tcanv.pcanvas[0] = NULL; @@ -1889,8 +1890,8 @@ void Community::writeWCPerLocusFstatFile(Species* pSpecies, const int yr, const const auto pPop = (Population*)patch->getPopn((intptr)pSpecies); int popSize = pPop->sampleSize(); int het = 0; - for (unsigned int a = 0; a < nAlleles; ++a) { - het += pPop->getHetero(thisLocus, a); + for (int a = 0; a < nAlleles; ++a) { + het += static_cast(pPop->getHetero(thisLocus, a)); // not sure why this returns a double } outperlocusfstat << "\t" << het / (2.0 * popSize); } diff --git a/GeneticLoad.cpp b/GeneticLoad.cpp index b467c9a..aa93e8d 100644 --- a/GeneticLoad.cpp +++ b/GeneticLoad.cpp @@ -211,27 +211,27 @@ float GeneticLoad::drawDominance(float selCoef) { { const float mean = dominanceParameters.find(MEAN)->second; const float sd = dominanceParameters.find(SDEV)->second; - h = pRandom->Normal(mean, sd); + h = static_cast(pRandom->Normal(mean, sd)); break; } case GAMMA: { const float shape = dominanceParameters.find(SHAPE)->second; const float scale = dominanceParameters.find(SCALE)->second; - h = pRandom->Gamma(shape, scale); + h = static_cast(pRandom->Gamma(shape, scale)); break; } case NEGEXP: { const float mean = dominanceParameters.find(MEAN)->second; - h = pRandom->NegExp(mean); + h = static_cast(pRandom->NegExp(mean)); break; } case SCALED: { const float min = 0; - const float max = exp((-log(2 * 0.36) / 0.05) * selCoef); - h = pRandom->FRandom(min, max); + const float max = static_cast(exp((-log(2 * 0.36) / 0.05) * selCoef)); + h = static_cast(pRandom->FRandom(min, max)); break; } @@ -270,7 +270,7 @@ float GeneticLoad::drawSelectionCoef() { { const float mean = mutationParameters.find(MEAN)->second; const float sd = mutationParameters.find(SDEV)->second; - s = pRandom->Normal(mean, sd); + s = static_cast(pRandom->Normal(mean, sd)); break; } @@ -278,13 +278,13 @@ float GeneticLoad::drawSelectionCoef() { { const float shape = mutationParameters.find(SHAPE)->second; const float scale = mutationParameters.find(SCALE)->second; - s = pRandom->Gamma(shape, scale); + s = static_cast(pRandom->Gamma(shape, scale)); break; } case NEGEXP: { const float mean = mutationParameters.find(MEAN)->second; - s = pRandom->NegExp(mean); + s = static_cast(pRandom->NegExp(mean)); break; } default: @@ -315,7 +315,7 @@ void GeneticLoad::inheritDiploid(sex_t whichChromosome, mapfirst); - unsigned int nextBreakpoint = *it; + int nextBreakpoint = *it; auto distance = std::distance(recomPositions.begin(), it); if (distance % 2 != 0) diff --git a/Population.cpp b/Population.cpp index 4615951..aec1141 100644 --- a/Population.cpp +++ b/Population.cpp @@ -56,7 +56,7 @@ Population::Population(Species* pSp, Patch* pPch, int ninds, int resol) pSpecies = pSp; pPatch = pPch; // record the new population in the patch - patchPopn pp; + patchPopn pp = patchPopn(); pp.pSp = (intptr)pSpecies; pp.pPop = (intptr)this; pPatch->addPopn(pp); #if RSDEBUG @@ -229,7 +229,7 @@ Population::~Population(void) { traitsums Population::getTraits(Species* pSpecies) { int g; - traitsums ts; + traitsums ts = traitsums(); for (int i = 0; i < NSEXES; i++) { ts.ninds[i] = 0; ts.sumD0[i] = ts.ssqD0[i] = 0.0; @@ -456,10 +456,10 @@ double Population::computeHs() { popStats Population::getStats(void) { - popStats p; + popStats p = popStats(); int ninds; float fec; - bool breeders[2]; breeders[0] = breeders[1] = false; + bool breeders[2] = { false, false }; demogrParams dem = pSpecies->getDemogr(); p.pSpecies = pSpecies; p.pPatch = pPatch; @@ -1147,7 +1147,7 @@ void Population::allEmigrate(void) { // If an Individual has been identified as an emigrant, remove it from the Population disperser Population::extractDisperser(int ix) { - disperser d; + disperser d = disperser(); indStats ind = inds[ix]->getStats(); if (ind.status == 1) { // emigrant d.pInd = inds[ix]; d.yes = true; @@ -1190,7 +1190,7 @@ void Population::addSettleTraitsForInd(int ix, settleTraits& avgSettleTraits) { // if it is a settler, return its new location and remove it from the current population // otherwise, leave it in the matrix population for possible reporting before deletion disperser Population::extractSettler(int ix) { - disperser d; + disperser d = disperser(); Cell* pCell; //Patch* pPatch; @@ -1232,7 +1232,8 @@ int Population::transfer(Landscape* pLandscape, short landIx) Cell* pCell = 0; indStats ind; Population* pNewPopn = 0; - locn newloc, nbrloc; + locn newloc = locn(); + locn nbrloc = locn(); landData ppLand = pLandscape->getLandData(); short reptype = pSpecies->getRepType(); @@ -1716,6 +1717,9 @@ void Population::survival0(float localK, short option0, short option1) if ((ind.stage == 0 && option0 < 2) || (ind.stage > 0 && option0 > 0)) { // condition for processing the stage is met... if (ind.status < 6) { // not already doomed + if (ind.sex < sex_t::FEM || ind.sex > sex_t::MAL) + // ?? MSVC believes it's important to bound check ind.sex + throw runtime_error("Individual sex is out of bounds"); double probsurv = surv[ind.stage][ind.sex]; // does the individual survive? if (pRandom->Bernoulli(probsurv)) { // survives @@ -2129,7 +2133,7 @@ void Population::outIndividual(Landscape* pLandscape, int rep, int yr, int gen, outInds << "\t" << ind.status; } pCell = inds[i]->getLocn(1); - locn loc; + locn loc = locn(); if (pCell == 0) loc.x = loc.y = -1; // beyond boundary or in no-data cell else loc = pCell->getLocn(); pCell = inds[i]->getLocn(0); diff --git a/Population.h b/Population.h index 3c7d438..dae449a 100644 --- a/Population.h +++ b/Population.h @@ -235,7 +235,6 @@ class Population { int countHeterozygoteLoci(); vector countLociHeterozyotes(); double computeHs(); - void updateHeteroTable(); private: short nStages;