Configuration Guide

This guide discusses how to configure Wildbook to fit the branding, messaging, and study design of your project. We highly recommend tracking changes you make to Wildbook in source control, such as with Github.com. Source control prevents your changes from being lost when you upgrade Wildbook in the future.

Wildbook Configuration Structure

By default Wildbook configuration options are stored as name-value pairs in properties files in:

<tomcat_install_dir>/wildbook/WEB-INF/classes/bundles

You can edit these files with a text editor, and after making changes, restart Tomcat to see the new configurations take effect.

You also have the option of overriding Tomcat's base configurations with your own copies of properties files. In contexts.properties, you can find by default:

defaultContext = context0
context0DataDir = wildbook_data_dir
context0Name = Wildbook 

The entry “context0DataDir = wildbook_data_dir” defines an additional directory structure in which Wildbook will place submitted images and data files. In this example, the directory would be:

<tomcat_install_dir>/wildbook_data_dir/WEB-INF/classes/bundles

where it is a peer of the wildbook installation directory. Copies of properties files placed in:

<tomcat_install_dir>/wildbook_data_dir/WEB-INF/classes/bundles

will override their counterparts in the base “wildbook” directory.

Properties files placed in language-specific folders, such as “en” (English), “es” (Spanish), etc. represent translated files of the Wildbook user interface (UI).

Changing the database and persistence behavior

Wildbook uses the DataNucleus Access Platform, which allows it to use a number of different databases and database types.

We strongly recommend using PostgreSQL for Wildbook, which is the default database configuration and the only database used by Wild Me. Out of the box, Wildbook looks for PostgreSQL at localhost:5432/wildbook with username 'shepherd' and password 'shepherd'. You must have PostgreSQL installed and running, the 'wildbook' database created, and user 'shepherd' defined. Wildbook can automatically create the necessary tables and columns when it is first started. You do not need to create these yourself.

Database configuration is defined in the file jdoconfig.properties. An example of DataNucleus persistence properties is shown below.

# The following lines can be used for PostgreSQL data storage.
# You will also need to add the JDBC JAR file for your PostgreSQL version to /WEB-INF/lib.
datanucleus.ConnectionDriverName=org.postgresql.Driver
datanucleus.ConnectionURL = jdbc:postgresql://localhost:5432/wildbook
javax.jdo.PersistenceManagerFactoryClass = org.datanucleus.api.jdo.JDOPersistenceManagerFactory           
datanucleus.ConnectionUserName = shepherd              
datanucleus.ConnectionPassword = shepherd
datanucleus.autoCreateSchema = true
datanucleus.NontransactionalRead = true        
datanucleus.Multithreaded = true
datanucleus.RestoreValues = true
datanucleus.storeManagerType = rdbms
datanucleus.maxFetchDepth = -1
datanucleus.cache.collections.lazy = false

You can control Wildbook's database behavior by changing the values of these properties and by adding others, as defined in the DataNucleus documentation.

Running Multiple Projects in One Wildbook

You can run multiple, distinct wildlife projects in a single Wildbook. Each project is a called a Wildbook “context” and can be distinctly configured in contexts.properties. Each project will have its own database and set of configuration files.

Here is an example from context.properties of three distinct projects configured in context.properties.

#project-related variables
defaultContext = context0

context0DataDir = hectors_data_dir
context0Name = Hector's Dolphins
context0DomainName0 = hectors
#context0DomainName1 = myotherdomain.com

context1DataDir = narw_data_dir
context1Name = NARW
context1DomainName0 = narw

context2DataDir = shepherd_data_dir
context2Name = Latest GeneGIS
context2DomainName0 = latestgenegis

Notice how each context has sequential numbering. This is required by Wildbook to determine the number of contexts.

Each distinct context has three configured properties:

  • context0DataDir - This is the data directory for the context in which its properties files are defined, especially jdoconfig.properties and commonConfiguration.properties.
  • context0Name - A readable name for the context, which is displayed in the pulldown menu of Wildbook that allows users to switch between contexts.
  • context0DomainName0 - A domain name string that the request URL is inspected for to help “guess” the intended context if it has not been explicitly set in cookie set by the pulldown menu in Wildbook.

Once multiple contexts in Wildbook are configured, and Tomcat has been restarted, Wildbook displays a pulldown menu to allow users to explicitly set their desired context.

Note that users in Wildbook must have roles per context, and a user in one context might be an admin but only have basic or no permissions in another. Administrators in context0 set the permissions in each context for every user.

Multi-context Example

The OSU MMU Wildbook is a good example of a multi-context Wildbook:

OSU Marine Mammal Unit Wildbook

Changing Wildbook's Appearance

The following sections describe how to change Wildbook's appearance.

Overview

At its core, Wildbook uses Bootstrap for its mobile, responsive design. Most changes to display and design can be performed by changing:

  • header.jsp - This file defines the standard JavaScript and CSS imports used by Wildbook and implements any header graphics and navigation at the top of the pages.
  • footer.jsp - This file defines any HTML to display at the bottom of the page, such as copyright information.
  • commonConfiguration.properties - This file contains many configuration options for Wildbook, and it includes options for search engine optimization (SEO), page titles, and other basic HTML fields.

Changing the HTML header

The HTML header for web pages in Wildbook is pulled from the file header.jsp. This file retrieves additional values from commonConfiguration.properties.

CSS changes

By default, Wildbook loads the following CSS files:

Wildbook uses Less to create the manta.css file at build time. You'll need to modify the .less files in cust/mantamatcher/styles to make your custom changes.

Changing the top banner graphic

To change the top banner graphic with your project's logo directly in Wildbook, change the file specified in the .navbar-brand class background attribute in manta.css, which is located in:

wildbook/cust/mantamatcher/css/manta.css

Here is the relevant section from that file:

.navbar-brand {
  	height: 60px;
  	width: 243px;
  	margin-bottom: 10px;
  	margin-left: auto;
  	margin-right: auto;
  	text-indent: -999em;
  	clear: both;
  	float: none;
  	display: block;
  	 background: url(../img/wildbook_logo_white.svg) no-repeat; 
	}

In the above example, you would change wildbook_logo_white.svg to the file of your choice.

If you want to change this in your branch of Wildbook's source code (recommended), you can change it in the file:

src/main/webapp/cust/mantamatcher/styles/_bootstrap_overrides.less

Encounter Configuration

Most Wildbook project configuration occurs in the commonConfiguration.properties file. This file is located in the following location in your Wildbook installation:

wildbook/WEB-INF/classes/bundles/commonConfiguration.properties

You can alter important Wildbook Encounter parameters in this file, such as:

  • Number and type of measurements (e.g., weight, length, salinity, temperature, etc.)
  • Number of life stages (e.g., juvenile, sub-adult, adult)
  • Project species
  • Physical patterning codes
  • Physical tag parameters (SAT, PAT, tags, etc.)
  • tissue sample parameters, such as:
    • number of alleles
    • tissue sample storage method
    • haplotypes
    • biochemical measurements (13C, 15N, etc.)
  • and more…

When you modify configuration parameters in this file, you may have to restart the Tomcat web server for the changes to take effect.

Supporting multiple species

By default, Wildbook assumes that information added to the database is for only one species of animal. You can configure Wildbook to support multiple species by setting the genusSpecies fields, and setting the showTaxonomy parameter to true in commonConfiguration.properties. The following example shows how to set these properties to differentiate between three species of large cats.

#show taxonomy
showTaxonomy = true

#for multi-species libraries, fill out the genus and species for each supported animal type, starting with genusSpecies0
genusSpecies0 = Panthera leo
genusSpecies1= Panthera tigris
genusSpecies2 = Panthera pardus

Additional species can be set by incrementing the properties, such as genusSpecies3, genusSpecies4, etc.

Once these fields are set, the Taxonomy field appears when you edit an Encounter.

If you click Edit on the Taxonomy field, the Reset Genus and Species dialog box appears, allowing you to set or reset the genus and species for the Encounter.

Configuring encounter states for workflow

Encounters can be assigned to particular states, often reflecting critical parts of a project workflow. For example, states can be used to define what data has been 'approved' for use in your study or is 'unidentifiable' due to poor quality. By default, new data in Wildbook is put into an 'unapproved' state that represents its status as unreviewed and of uncertain quality.

The available states are defined in the following section of commonConfiguration.properties.

#encounterState options, the precursors to future workflow
encounterState0=unapproved
encounterState1=approved
encounterState2=unidentifiable

Additional states can be set by incrementing the properties, such as encounterState3, encounterState4, etc.

Configuring location IDs (study sites)

Defining the boundaries of study areas is an important aspect of mark-recapture study design. Wildbook allows you to configure study areas as an attribute that can be assigned to each Encounter, categorizing data by where it occurred. Encounter.locationID is one of three ways of defining location in Wildbook. The three ways are:

  • Encounter.locationID - assigns an Encounter to a human-defined study area
  • Encounter.decimalLatitude/decimalLongitude - assigns an Encounter to precisley measured GPS coodinates
  • Encounter.verbatimLocality - a general description of location provided by the data submitter from which locationID may be determined.

Encounter.locationID may be the most valuable form of location identifier in Wildbook. GPS location may not be known, and verbatim descriptions of location may vary significantly by submitter. LocationID is powerful because it specifically defines whether a data point should be included or excluded from a study area during mark-recapture analysis.

To configure the list of study sites in your Wildbook, provide sequential name-value pairs for locationID in commonConfiguration.properties.

#limit Encounter.locationID to these values
locationID0 = Study Site 1
locationID1 = Study Site 2
locationID2 = Study Site 3

Restart Tomcat after making changes.

Default GPS coordinates for study sites

While a locationID may be known for a data point, GPS coordinates may not be. However, sometimes it is valuable to associate a study site with a generic set of coordinates (e.g., the center point of the study area) and display it on a map. Wildbook allows you to associate a comma-separated pairs of decimal latitude and longitude points with each locationID in locationIDGPS.properties.

Study Site 1 = 38.9364,-74.8
Study Site 2 = 40.5,-75.65
Study Site 3 = 40.5,-76.2

Configuring encounter measurements

You can configure reported encounters to have multiple recorded measurement observations (e.g., length, width, height). The measurement types are defined in commonConfiguration.properties, starting with the number 0 and incrementing by one for each new measurement type.

For each measurement, you must define a measurement name, the corresponding units, and the general sampling protocols applied to measurements in your study. You can turn and off measurements altogether with the showMeasurements entry, which can be set to true or false.

#show measurements
showMeasurements = true

#Measurements
measurement0=weight
measurement1=length
measurement2=height

measurementUnits0=kilograms
measurementUnits1=meters
measurementUnits2=meters

#Sampling Protocol for all Measurement types
samplingProtocol0=estimate
samplingProtocol1=measure

Configuring and localizing measurement labels

The names of measurements, their units, and sampling protocols can be localized into multiple languages in Wildbook in the language-specific copies of commonConfigurationLabes.properties. Notice the .label extension added to the base name of the measurement-related property from commonConfiguration.properties (see above).

#Labels for Measurements
weight.label=Weight
length.label=Length
height.label=Height
13C.label=13C
15N.label=15N
34S.label=34S
celsius.label = Celsius
salinity.label = Salinity
WaterTemperature.label = Water Temperature
kilograms.label=Kilograms
meters.label=Meters
ppm.label=ppm

samplingProtocol0.label=Estimated Value
samplingProtocol1.label=Directly Measured

After making changes, restart Tomcat to see them take effect.

Configuring life stages

Observations of animals are often categorized by their life stage, such as adult, sub-adult, juvenile, hatchling, etc. You can configure the life stages for your project with the following settings.

#show lifeStage
showLifestage = true

#defined life stages
lifeStage0=juvenile
lifeStage1=sub-adult
lifeStage2=adult

Additional stages can be set by incrementing the properties, such as lifeStage3, lifeStage4, etc.

Configuring physical tag metadata

If you're using physical tags (SAT, PAT, marker, etc.) during your research, you can record metadata about those tags and associate it with an Encounter recorded at tag deployment. The following attributes (examples below) are available to configure:

  • showMetalTags - whether physical marker tags are used in your study should be shown on the Encounter page in Wildbook. Values are true/false.
  • metalTagLocationX - The list of placement locations for the tag on the body of the animal
  • showAcousticTag - whether acoustic tags are used in your study should be shown on the Encounter page in Wildbook. Values are true/false.

* showSatelliteTag - whether satelite tags are used in your study should be shown on the Encounter page in Wildbook. Values are true/false.

  • satelliteTageNameX - The list of satellite tag manufacturers/providers to help identify the type of tag.
#tag parameters
showMetalTags=true
metalTagLocation0=left
metalTagLocation1=right

showAcousticTag=true

showSatelliteTag=true
satelliteTagName0=Wild Life Computers
satelliteTagName1=SirTack

Configuring visual patterning codes

Often times, the visual coloration of species can be divided into categories to allow for easier filtering for individual identification. For example, humpback whales can be individually identified by their flukes and have a graded fluke coloration system, ranging from 1-5.

Wildbook allows each Encounter to be assigned a patterning code to match the observed visual features of the animal in the Encounter.

You can configure pre-defined patterning codes for your project in commonConfiguration.properties. The property showPatterningCode must be set to true, and then a sequentially numbered set of patterningCodeX names and values must be defined.

Here is a configuration example of giant manta patterning codes from MantaMatcher.org.

#defined patterningCodes for distinct visual marking types for individuals identified with photo-identification
showPatterningCode = true
patterningCode0 = normal pigmentation
patterningCode1 = black pigmentation - melanistic
patterningCode2 = white pigmentation - leucistic

Configuring elevation and depth

You can configure whether elevation or depth are recorded in your study as Encounter properties in the commonConfiguration.properties file. Set maximumElevationInMeters to true to make elevation a measurement of your study. Set maximumDepthInMeters to true to make depth an measurement of your study.

#show elevation/depth
maximumElevationInMeters = false
maximumDepthInMeters = true

Restart Tomcat after making changes.

Configuring tissue samples and analyses

Wildbook allows you to add one ore more records for biological samples collected during an Encounter with an individual animal. Biological samples have the following attributes defined in commonConfiguration.properties:

  • tissueTypeX - a sequential definition of the types of tissues that can be collected in your study (e.g., fecal, blood, skin, biopsy, etc.)
  • biologicalMeasurementTypeX - a sequential definition of the types of chemical measurements that can be analyzed and determined from tissue samples in your study (e.g., fatty acid Carbon and Nitrogen measurements)
    • biologicalMeasurementUnitsX - a sequential definition of the units of measurement for chemical measurments on tissue samples
    • biologicalMeasurementSamplingProtocolX - a sequential definition of the protocols used to determine the measurements
  • numLoci - the number of loci to provide allele values for if genotyping is performed as an analysis on the tissue sample
  • numPloids - leave at 2 per loci
  • alleleRelaxMaxValue - the value difference allowed between allele values to consider them a “match” when looking for other genotypes that might match or be similar.
#tissue sample types
tissueType0 = Tissue sample
tissueType1 = Fecal sample
tissueType2 = Mucus sample
tissueType3 = Blood sample
tissueType4 = Parasite sample

#biological measurement types
biologicalMeasurementType0 = 13C
biologicalMeasurementType1 = 15N
biologicalMeasurementType2 = 34S

#corresponding biological measurement units
biologicalMeasurementUnits0 = ppm
biologicalMeasurementUnits1 = ppm
biologicalMeasurementUnits2 = ppm

#corresponding biological measurement sampling protocols
biologicalMeasurementSamplingProtocols0 = Lipids extracted
biologicalMeasurementSamplingProtocols1 = No lipids extracted, corrected
biologicalMeasurementSamplingProtocols2 = No lipids extracted, uncorrected

#genetic parameters
numLoci = 14
numPloids = 2
alleleRelaxMaxValue = 5

Restart Tomcat after making changes.

Custom content display

You can import custom functionality into each Encounter's display in encounter.jsp. For example, spot pattern matching-related functions are imported from file spotMatchingAlgorithm.jsp (see example below).

importjsp.jpg

Import definitions are found in file encounter.properties file in the localized directory (e.g., WEB-INF/classes/bundles/en/encounter.properties).

#define the module JSP files to import
#files must be placed in the encounters directory of the Wildbook webapp (i.e., in the same directory as encounter.jsp)
jspImport0=spotMatchingAlgorithm.jsp
#jspImport1=myFile.jsp

Restart Tomcat after changing values.

Marked Individuals

The following aspects of Marked Individual data records can be configured in Wildbook.

Allowing nicknames

You can allow for Marked Individual in your study to have searchable nicknames. Unlike MarkedIndividual.individualID, MarkedIndividual.nickname does not have to be unique.

To allow nicknames (default), set allowNicknames to true in commonConfiguration.properties. Allowed values are true and false.

#nicknames
allowNicknames=true

Social relationships

Marked Individuals in Wildbook can have Relationship associations between them. These are meant for more long-term types of relationships, such as “mother-calf” or social group “member”. Relationships and their roles can be set in the UI on the Marked Individual page individuals.jsp.

To configure the types of social relationships in your Wildbook and the roles that Marked Individuals can play in them, change the following fields in commonConfiguration.properties:

  • relationshipTypeX - a sequentially numbered set of relationship types to be recorded in your study.
  • relationshipRoleX - the role that an individual can play in a Relationship.

Here are some example configurations:

#social relationships-related data
relationshipType0 = social grouping
relationshipType1 = familial

relationshipRole0 = member
relationshipRole1 = mother
relationshipRole2 = calf

Restart Tomcat after making changes.

Email Notifications

The following email addresses are sent messages when important events occur in Wildbook. These email addresses are specific to your project.

  1. sendEmailNotifications - Defines whether Wildbook should send any emails at all. Set to true, this parameter instructs Wildbook to send email updates for several events, such as:
    • new Encounter submission reports
    • new marked individual identifications to adopters ad submitters
    • marked individual resights to adopted and submitters
  2. autoEmailAddress - The email address from which Wildbook messages will be sent. If you have a secured mailhost, it's important to configure the mailhost to allow emails to be sent from this address.
  3. newSubmissionEmail - The email address to send notices of new Encounter reports submitted to Wildbook.
  4. mailHost - The email server through which Wildbook can send automated emails.
  5. removeEmailString - This is the message that will be appended to outbound emails in Wildbook. This message and the link that is dynamically attached to it allow users to stop receiving emails from Wildbook.
#email addresses and parameters
sendEmailNotifications=true
autoEmailAddress=webmaster@someplace.org
newSubmissionEmail=submissions@someplace.org
mailHost=localhost
removeEmailString=Do you want to REMOVE your email address from this database? Click the link below to remove it. You will no longer receive updates on your encounters.

I18N

Wildbook is a web-based application with an internationalization (I18N) foundation in its code base. Wildbook is not yet fully translated. Most of the JSP files are localized but none of the servlets are yet. Work is underway to complete localization.

Wildbook loads translated strings from the standard Java properties files, which reside in Wildbook's WEB-INF/classes/bundles directory or can be overridden (on a file-by-file basis) in the equivalent path in the data directory.

Setting the supported languages

You can set the default language for Wildbook in commonConfiguration.properties with the defaultLanguage attribute, which takes a two-letter code for input. The full list of supported language, which must include the default in position 0, is configured with sequential languageX name-value pairs. Corresponding localized Strings could be found in the appropriate language directory of Wildbook, such as WEB-INF/classes/bundles/es for 'es' (Spanish).

In the example below, English is set as the default language “en”, and Wildbook is configured to provide the user with English and Spanish options for display.

defaultLanguage = en

language0 = en
language1 = es
#language2 = fr
#language3 = de

The name displayed for each language can also be configured in commonConfiguration.properties.

en = English
es = espa\u00f1ol
fr = fran&#231;ais

With languages configured and Tomcat restarted, Wildbook displays configured languages as flag options.

It looks for a correspinding flag icon in the images directory. Examples:

  • flag_es.gif
  • flag_en.gif
  • flag_fr.gif

If your language flag is not present in Wildbook, you may need to add it.

Translating text

Most pieces of text in Wildbook pages (HTML and JSP files) are contained in translatable properties files. For example, the page for an Encounter (encounter.jsp) pulls its strings from WEB-INF/classes/bundles/en/encounter.properties (English text). Here is an example of the contents of encounter.properties.

encounter = Encounter
unidentifiable_title = Unidentifiable Encounter Number
unapproved_title = UNAPPROVED Encounter Number
title = Encounter
identified_as = Identified as:
workflowState = Workflow state:
setWorkflowState = Set Workflow State
matched_by = Matched by
status = Status
...

New name-value pairs can be added to these files as needed and loaded with Java logic like the following:

#loading the contents of a properties file
String context=ServletUtilities.getContext(request);
String langCode=ServletUtilities.getLanguageCode(request);
Properties encprops = ShepherdProperties.getProperties("encounter.properties", langCode, context);

#loading a specific property and embedding it in a JSP file's HTML
<p><%=encprops.getProperty("myCustomString")</p>

Adding a wiki

When you deploy Wildbook to a web server for use by researchers on the internet, you can set the wikiLocation parameter to the URL of an integrated wiki on your site. The wiki can act as an information delivery engine for detailed instructions specific to your application, or a place to add details about your organization's mission and goals, or for any other information you feel your customers need to know.

To set the wiki location, follow these steps:

  1. Edit commonConfiguration.properties.
  2. Modify the wikiLocation field to point to your internet domain.
  3. # set wikiLocation to point to your wiki to enable integration, e.g.
    wikiLocation=http://myWebSiteDomain:8080/wiki/doku.php?id=
    

  4. Save commonConfiguration.properties.
  5. Restart your J2EE container.

Biodiversity Data Export

The following configuration options allow you to export data to popular biodiversity data frameworks.

GBIF IPT

The Global Biodiversity Information Facility (GBIF) was established by governments in 2001 to encourage free and open access to biodiversity data across the Internet. Wildbook allows you to share data with GBIF. Complete information on GBIF is here:

http://www.gbif.org/

The Integrated Publishing Toolkit (IPT) is a Java web application that allows you to directly expose biodiversity data in a relational database to an external parser at the GBIF. The GBIF periodically collects the data and incorporates it into a larger biodiversity database.

Wildbook allows you to specify a link to the IPT that corresponds to your Wildbook instance and display that in the Administration menu. The user has to consult the IPT documentation for instructions on how to map IPT into Wildbook database (specifically to the Encounter table). It's the same process for TapirLink as well.

To integrate Wildbook with IPT, follow these steps:

  1. Download The Integrated Publishing Toolkit from the following location.

    IPT Provider

  2. Follow the provider instructions to build a servlet containing the IPT provider.
  3. Use the iptURL property in commonConfiguration.properties to set the launch URL for the provider.

    #GBIF IPT-related settings
    iptURL = http://localhost:8080/ipt-2.0.2
    

  4. Follow the provider instructions to expose the Encounter Table data in the Shepherd Database to GBIF.

When the iptURL property is set, the Administer menu displays a GBIF IPT menu item. To launch the IPT provider from Wildbook, choose AdministerGBIF IPT.

Static Library

The isCatalogEditable option allows you to create a dynamic (true) or static (false) mark-recapture catalog. A dynamic catalog allows users who log in to add/remove/update data in Wildbook. A static catalog represents a completed, unchanging set of mark-recapture data that is historical in nature, such as a fixed duration initiative.

#library editing
isCatalogEditable = true

Changing Wildbook Code

Because you are using Wildbook as an open source platform, you have the right and the ability to modify Wildbook yourself. The open source repository for Wildbook can be found at:

https://github.com/holmbergius/wildbook

Wildbook primarily uses Java and JavaScript, and you'll need a background in these languages to make your changes. If you need significant changes and cannot make them yourself, you can engage Wild Me Professional Services to help.

Legacy Spot Matching

Wildbook was originally developed for use with whale sharks (Rhincodon typus) and other spotted species. The internal spot pattern recognition system is highly accurate and had scaled well to over 25000 patterns on whaleshark.org. While our newer pattern recognition efforts connect to WIldbook as IBEIS Image Analysis servers, the legacy spot pattern recognition system is still highly accurate and usable in Wildbook.

By default, the spot pattern recognition system is turned off. It can be turned back on in commonConfiguration.properties by setting the useSpotPatternRecognition value to true.

#pattern recognition
useSpotPatternRecognition=true

Using Spot Pattern Recognition

TBD

Configuring the Grid Client

TBD

Limitations of spot pattern recognition

Spot pattern recognition in the Modified Groth and I3S algorithms - used by Wildbook for spotted species - is two-dimensional. While both algorithms have some tolerance for skew, it's important to define a standard angle of photography and documented data collection procedures to ensure you get comparable images. Specifically, you must standardize the angle between the camera lens of the observer and the body of the animal, allowing the photographed pattern to approximate a consistent flat surface. Deviation from that angle reduces the matching power of both algorithms as the relationships between the spots become distorted in comparison to reference images.

This page provides a good example of a photographic data standard for whale sharks: http://www.whaleshark.org/photographing.jsp

Here is a good reference standard for ragged tooth sharks: http://www.spotashark.com/photographing.jsp

Your standards may vary.

Further reading