Wildbook is an open source software framework to support mark-recapture, molecular ecology, and social ecology studies. The biological and statistical communities already support a number of excellent tools, such as Program MARK,GenAlEx, and SOCPROG for use in analyzing wildlife data. Wildbook is a complementary software application that:
provides a scalable and collaborative platform for intelligent wildlife data storage and management, including advanced, consolidated searching
provides an easy-to-use software suite of functionality that can be extended to meet the needs of wildlife projects, especially where individual identification is used
provides an API to support the easy export of data to cross-disciplinary analysis applications (e.g., GenePop ) and other software (e.g., Google Earth)
provides a platform that supports the exposure of data in biodiversity databases (e.g., GBIF and OBIS)
provides a platform for animal biometrics that supports easy data access and facilitates matching application deployment for multiple species
Wildbook is a long-standing tool that support a wide variety of researchers and species. The Wild Me team is working on revamping the tool as a true open source project, so if you have ideas and are excited to help, reach out to us on the Wild Me Development Discord!
All contributions should be made from a fork off of the Wildbook repo. While there are a number of repositories for specific Wildbook communities, large scale development is driven from the main repository.
To start, you will need to be signed in to your GitHub account, have admin access to your OS’s terminal, and have Git installed.
git clone https://github.com/USERNAME/Wildbook
cd Wildbook
git remote add upstream https://github.com/WildMeOrg/Wildbook
git fetch upstream
You will want to work in a branch when doing any feature development you want to provide to the original project.
git checkout main
git branch ISSUENUMBER-FEATUREBRANCHNAME
git checkout ISSUENUMBER-FEATUREBRANCHNAME
For easiest development, you will need to set up your development environment to work with Docker. See devops/README.md
for detailed instructions.
To setup frontend, we need to deploy the React build to Wildbook, please follow the detailed instructions provided in the frontend/README.md
file within the project directory.
Make the code changes necessary for the issue you’re working on. The following git commands may prove useful.
git log
: lastest commits of current branchgit status
: current staged and unstaged modificationsgit diff --staged
: the differences between the staging area and the last commitgit commit
: commits the stagged files, opens a text editor for you to write a commit logUp to this point, all changes have been done to your local copy of Wildbook. You need to push the new commits to a remote branch to start the PR process.
At this point, it’s on us to get you feedback on your submission! Someone from the Wild Me team will review the project and provide any feedback that may be necessary. If changes are recommended, you’ll need to checkout the branch you were working from, update the branch, and make these changes locally.
git checkout ISSUENUMBER-FEATUREBRANCHNAME
git pull upstream main
git add <filename>
for all files impacted by changesgit commit --ammend
if the changes are small stylistic changesgit commit
if the changes involved significant rework and require additional detailsWildbook leverages Wildbook IA (WBIA) as the machine learning engine, which pulls data from Wildbook servers to detect features in images and identify individual animals. WBIA brings massive-scale computer vision to wildlife research.
Wild Me (wildme.org) engineering staff provide support for Wildbook. You can contact us at: opensource@wildme.org
We provide support during regular office hours on Mondays and Tuesdays.
Spell out how .jsp files relate to servlet files relate to java files, etc. Someone new to the codebase should be able to orient themselves based on your notes.
Initialize variables and type signatures at the abstract/interface level when possible.
Instead of:
ArrayList encounters = new ArrayList<Encounter>();
...
public int getMax(ArrayList<int> numbers) {
Try:
List encounters = new ArrayList<Encounter>();
...
public int getMax(Collection<int> numbers) {
It’s easier to read and more intuitive for a function to take a Map or List than a HashMap or ArrayList.
The List interface defines how we want that variable to behave, and whether it’s an ArrayList or LinkedList is incidental. Keeping the variable and method signatures abstract means we can change the implementation later (eg swapping ArrayList->LinkedList) without changing the rest of our code. https://stackoverflow.com/questions/2279030/type-list-vs-type-arraylist-in-java
Related: when writing utility methods, making the input type as abstract as possible makes the method versatile. See Util.asSortedList in Wildbook: since the input is an abstract Collection, it can accept a List, Set, PriorityQueue, or Vector as input, and return a sorted List.
Runtime (not style): Use Sets (not Lists or arrays) if you’re only keeping track of collection membership / item uniqueness.
Instead of:
List<MarkedIndividual> uniqueIndividuals = new ArrayList<MarkedIndividual>();
for(Encounter currentEncounter: encounters){
MarkedIndividual currentInd = enc.getIndividual();
if !(uniqueIndividuals.contains(currentInd) {
uniqueIndividuals.add(currentInd);
doStuff();
Try:
Set<MarkedIndividual> uniqueIndividuals = new HashSet<MarkedIndividual>();
for(Encounter currentEncounter: encounters){
MarkedIndividual currentInd = enc.getIndividual();
if !(uniqueIndividuals.contains(currentInd) {
uniqueIndividuals.add(currentInd);
doStuff();
The reason is a little deep in the data types. Sets are defined as unordered collections of unique elements; and Lists/arrays are ordered collections with no bearing on element-uniqueness. If the order of a collection doesn’t matter and you’re just checking membership, you’ll have faster runtime using a Set.
Sets implement contains, add, and remove methods much faster than lists [contains is O(log(n)) vs O(n) runtime]. A list has to iterate through the entire list every time it runs contains (it checks each item once at a time) while a set (especially a HashSet) keeps track of an item index for quick lookup.
Use for-each loops aka “enhanced for loops” to make loops more concise and readable.
Instead of:
for (int i=0; i<encounters.length(); i++) {
Encounter enc = encounters.get(i)
doStuff();
try:
for (Encounter enc: encounters) {
doStuff();
Note that in both cases you might want to check if encounters == null
if relevant, but you rarely need to check if encounters.length()>0
because the for-loops take care of that.
Also note that if you want access to the i
variable for logging or otherwise, the classic for-loop is best.
Util.stringExists
is shorthand for a common string check:
Instead of:
if (str!=Null && !str.equals("")) {
doStuff();
Try:
if (Util.stringExists(str)) {
doStuff();
This method also checks for the strings “none” and “unknown” which have given us trouble in displays in the past.
Wildbook started as a collaborative software platform for globally-coordinated whale shark (Rhincodon typus ) research as deployed in the Wildbook for Whale Sharks (now part of http://www.sharkbook.ai). After many requests to use our software outside of whale shark research, it is now an open source, community-maintained standard for mark-recapture studies.
Wildbook is a trademark of Conservation X Labs, a 501(c)(3) non-profit organization, and is supported by the Wild Me team.