#!/usr/bin/env python3

import json
import jsonschema
import os
import re
import sys
import yaml

from argparse import ArgumentParser


# Path to JSON schema file:
SCHEMA_FILE = 'util/schema/registry_schema.json'

# The metadata grid to be generated:
metadata_grid = {}


def main(args):
  global metadata_grid
  parser = ArgumentParser(description='''
  Validate registry metadata in the given YAML file yaml_infile and produce two output files:
  1) violations_outfile: a CSV, TSV, or TXT file which contain all metadata violations, and
  2) grid_outfile: a CSV, TSV, or TXT file which will contain a custom sorted metadata grid''')
  parser.add_argument('yaml_infile', type=str, help='YAML file containing registry data')
  parser.add_argument('violations_outfile', type=str,
                      help='Output file (CSV, TSV, or TXT) to contain metadata violations')
  parser.add_argument('grid_outfile', type=str,
                      help='Output file (CSV, TSV, or TXT) to contain custom sorted metadata grid')
  args = parser.parse_args()

  yaml_infile = args.yaml_infile
  violations_outfile = args.violations_outfile
  grid_outfile = args.grid_outfile

  # Load in the YAML and the JSON schemas that we will need:
  data = load_data(yaml_infile)
  schema = get_schema()

  results = {'error': [], 'warn': [], 'info': []}

  # Validate each object
  for item in data["ontologies"]:
    add = validate_metadata(item, schema)
    results = update_results(results, add)

  # save the metadata-grid with ALL results
  headers = []
  for s in schema['properties']:
    if 'level' in s:
      headers.append(s)
  save_grid(metadata_grid, headers, grid_outfile)

  # print and save the results that did not pass
  print_results(results)
  save_results(results, violations_outfile)
  if results['error']:
    print('Metadata validation failed with %d errors - see %s for details'
          % (len(results['error']), violations_outfile))
    sys.exit(1)
  else:
    print('Metadata validation passed - see %s for warnings' % violations_outfile)
    sys.exit(0)


def load_data(yaml_infile):
  '''Given a YAML data file, load the data to validate.'''
  with open(yaml_infile, 'r') as stream:
    data = yaml.load(stream, Loader=yaml.SafeLoader)
  return data


def get_schema():
  '''Return a schema from the master schema directory.'''
  schema = None
  try:
    file = SCHEMA_FILE
    with open(file, 'r') as s:
      schema = json.load(s)
  except Exception as e:
    print('Unable to load %s: %s' % (f, str(e)))
  return schema


def validate_metadata(item, schema):
  '''Given an item and a schema, validate the item against the
  schema. Add the full results to the metadata_grid and return a map of
  errors, warnings, and infos for any active ontologies.'''
  global metadata_grid

  ont_id = item['id']
  # these lists will be displayed on the console:
  errors = []
  warnings = []
  infos = []
  # these results are put into the metadata grid:
  results = {}

  # determine how to sort this item in the grid:
  results['foundry'] = True if item.get('in_foundry_order') == 1 else False
  results['obsolete'] = True if item.get('is_obsolete') is True else False
  # if there is no status, put them at the bottom with inactive:
  results['ontology_status'] = item['activity_status'] if 'activity_status' in item else 'inactive'

  has_error = False
  has_warn = False
  has_info = False
  try:
    jsonschema.validate(item, schema)
  except jsonschema.exceptions.ValidationError as ve:
      title = list(ve.absolute_schema_path)[0]  # Find the named section within the schema
      if title == "required":
        field_names = re.findall(r"\'(.*?)\'", ve.message)  # Rather get which field
        if len(field_names) > 0:
          title = field_names[0]
      if title == "properties":
        title = list(ve.absolute_schema_path)[1] # Get which field
      # Get the schema "level" for this field dynamically, if we can
      if title in list(ve.absolute_schema_path) or title in schema['properties']:
        if title in list(ve.absolute_schema_path):
          title_index = list(ve.absolute_schema_path).index(title)
          path = list(ve.absolute_schema_path)[0:(title_index+1)]
        else:
          path = ['properties',title]
        abs_schema = schema
        for schema_item in path:
          if schema_item in abs_schema:
            if 'level' in abs_schema[schema_item]:
              level = abs_schema[schema_item]['level']
            abs_schema = abs_schema[schema_item]

      # add to the results map
      results[title] = level

      # flag for errors, warnings, and infos
      # without adding results to the lists that are logged
      if level == 'error':
        has_error = True
      elif level == 'warning':
        has_warn = True
      elif level == 'info':
        has_info = True

      # these cases will not cause test failure and will not be logged
      # the results are just added to the metadata grid:
      # - orphaned ontology on contact or license check
      # - inactive ontology
      # - obsolete ontology
      # - ontology annotated with `validate: false`
      if not ( (item.get('activity_status') == 'orphaned' and \
              title in ['contact', 'license', 'license-lite']) or \
              (item.get('is_obsolete') is True or item.get('activity_status') == 'inactive' or \
                 item.get('validate') is False) ):
          # get a message for displaying on terminal
          msg = ve.message
          if title in ['license', 'license-lite']:
            # license error message can show up in a few different ways
            search = re.search('\'(.+?)\' is not one of', msg)
            if search:
              msg = '\'%s\' is not a recommended license' % search.group(1)
            else:
              search = re.search('({\'label\'.+?\'url\'.+?}) is not valid', msg)
              if search:
                msg = format_license_msg(search.group(1))
              else:
                search = re.search('({\'url\'.+?\'label\'.+?}) is not valid', msg)
                if search:
                  msg = format_license_msg(search.group(1))

          # format the message with the ontology ID
          msg = '%s %s: %s' % (ont_id.upper(), title, msg)

          # append to correct set of warnings
          if level == 'error':
            errors.append(msg)
          elif level == 'warning':
            # warnings are recommended fixes, not required
            if 'required' in msg:
              msg = msg.replace('required', 'recommended')
            warnings.append(msg)
          elif level == 'info':
            infos.append(msg)

  # add an overall validation status to the grid entry
  if has_error:
    results['validation_status'] = 'FAIL'
  elif has_warn:
    results['validation_status'] = 'WARN'
  elif has_info:
    results['validation_status'] = 'INFO'
  else:
    results['validation_status'] = 'PASS'
  metadata_grid[ont_id] = results

  return {'error': errors, 'warn': warnings, 'info': infos}


def format_license_msg(substr):
  '''Format an exception message for a license issue.'''
  # process to dict
  d = json.loads(substr.replace('\'', '"'))
  url = d['url']
  label = d['label']
  return '\'{0}\' <{1}> is not a recommended license'.format(label, url)


def update_results(results, add):
  '''Given a map of results for all ontologies and a map of results to add,
  append the results to the lists in the map.'''
  results['error'] = results['error'] + add['error']
  results['warn'] = results['warn'] + add['warn']
  results['info'] = results['info'] + add['info']
  return results


def sort_grid(metadata_grid):
  """
  Given a metadata grid as a map, sort the grid based on:
  1. Foundry status
  2. Ontology activity status
  3. Validation status
  4. Alphabetical
  Return a sorted list of IDs.
  """
  foundry = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  active = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  orphaned = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  inactive = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  obsolete = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}

  for ont_id, results in metadata_grid.items():
    # get the info about the ontology to sort on
    ontology_status = results['ontology_status']
    validation_status = results['validation_status']

    # foundry ontologies are displayed first
    # they must be active
    if results['foundry']:
      foundry[validation_status].append(ont_id)
      continue

    # obsolete ontologies are displayed last
    # they are always inactive
    # (inactive does not mean obsolete)
    if results['obsolete']:
      obsolete[validation_status].append(ont_id)
      continue

    # finally, sort by: active, orphaned, inactive
    if ontology_status == 'active':
      active[validation_status].append(ont_id)
    elif ontology_status == 'orphaned':
      orphaned[validation_status].append(ont_id)
    elif ontology_status == 'inactive':
      inactive[validation_status].append(ont_id)

  # concatenate everything to a sorted list:
  def sort_list(arr):
    arr.sort(key=str.lower)
    if not arr:
      return []
    return arr

  sort = []
  for ont_type in [foundry, active, orphaned, inactive, obsolete]:
    for v_status in ['PASS', 'INFO', 'WARN', 'FAIL']:
      sort = sort + sort_list(ont_type[v_status])

  return sort


def save_grid(metadata_grid, headers, grid_outfile):
  '''Given a metadata grid of all results and a grid file to write to, create
  a sorted table of the full results.'''
  if '.csv' in grid_outfile:
    separator = ','
  elif '.tsv' or '.txt' in grid_outfile:
    separator = '\t'
  else:
    print('Grid file must be CSV, TSV, or TXT', file=sys.stderr)
    return

  # Determine order of ontologies based on statuses
  sort_order = sort_grid(metadata_grid)

  # First three help to see overall details
  header = 'Ontology{0}Activity Status{0}Validation Status'.format(separator)
  # After that, we show the results of each check
  for h in headers:
    header += separator + h
  header += '\n'

  with open(grid_outfile, 'w') as f:
    f.write(header)
    for ont_id in sort_order:
      results = metadata_grid[ont_id]
      s = '{1}{0}{2}{0}{3}'.format(separator, ont_id, results['ontology_status'],
                                   results['validation_status'])
      for h in headers:
        if h == 'license':
          # license has two checks
          # so the license entry will be the more severe violation
          all_res = [results['license'], results['license-lite']]
          if 'error' in all_res:
            s += separator + 'error'
          elif 'warning' in all_res:
            s += separator + 'warning'
          elif 'info' in all_res:
            s += separator + 'info'
          else:
            s += separator + 'pass'
          continue
        s += separator + results[h]
      s += '\n'
      f.write(s)

  print('Full validation results written to %s' % grid_outfile)


def print_results(results):
  '''Given a map of results, log results on the console.'''
  for level, messages in results.items():
    for m in messages:
      print('%s\t%s' % (level.upper(), m))


def save_results(results, violations_outfile):
  '''Given a map of results and an output file to write to, write each result
  on a line.'''
  if '.csv' in violations_outfile:
    separator = ','
  elif '.tsv' or '.txt' in violations_outfile:
    separator = '\t'
  else:
    print('Output file must be CSV, TSV, or TXT', file=sys.stderr)
    return
  with open(violations_outfile, 'w') as f:
    f.write('Level%sMessage\n' % separator)
    for level, messages in results.items():
      for m in messages:
        f.write('%s%s%s\n' % (level.upper(), separator, m))


if __name__ == '__main__':
  main(sys.argv)

util/validate-metadata.py
#!/usr/bin/env python3

import json
import jsonschema
import os
import re
import sys
import yaml

from argparse import ArgumentParser


# Path to JSON schema file:
SCHEMA_FILE = 'util/schema/registry_schema.json'

# The metadata grid to be generated:
metadata_grid = {}


def main(args):
  global metadata_grid
  parser = ArgumentParser(description='''
  Validate registry metadata in the given YAML file yaml_infile and produce two output files:
  1) violations_outfile: a CSV, TSV, or TXT file which contain all metadata violations, and
  2) grid_outfile: a CSV, TSV, or TXT file which will contain a custom sorted metadata grid''')
  parser.add_argument('yaml_infile', type=str, help='YAML file containing registry data')
  parser.add_argument('violations_outfile', type=str,
                      help='Output file (CSV, TSV, or TXT) to contain metadata violations')
  parser.add_argument('grid_outfile', type=str,
                      help='Output file (CSV, TSV, or TXT) to contain custom sorted metadata grid')
  args = parser.parse_args()

  yaml_infile = args.yaml_infile
  violations_outfile = args.violations_outfile
  grid_outfile = args.grid_outfile

  # Load in the YAML and the JSON schemas that we will need:
  data = load_data(yaml_infile)
  schema = get_schema()

  results = {'error': [], 'warn': [], 'info': []}

  # Validate each object
  for item in data["ontologies"]:
    add = validate_metadata(item, schema)
    results = update_results(results, add)

  # save the metadata-grid with ALL results
  headers = []
  for s in schema['properties']:
    if 'level' in s:
      headers.append(s)
  save_grid(metadata_grid, headers, grid_outfile)

  # print and save the results that did not pass
  print_results(results)
  save_results(results, violations_outfile)
  if results['error']:
    print('Metadata validation failed with %d errors - see %s for details'
          % (len(results['error']), violations_outfile))
    sys.exit(1)
  else:
    print('Metadata validation passed - see %s for warnings' % violations_outfile)
    sys.exit(0)


def load_data(yaml_infile):
  '''Given a YAML data file, load the data to validate.'''
  with open(yaml_infile, 'r') as stream:
    data = yaml.load(stream, Loader=yaml.SafeLoader)
  return data


def get_schema():
  '''Return a schema from the master schema directory.'''
  schema = None
  try:
    file = SCHEMA_FILE
    with open(file, 'r') as s:
      schema = json.load(s)
  except Exception as e:
    print('Unable to load %s: %s' % (file, str(e)))
  return schema


def validate_metadata(item, schema):
  '''Given an item and a schema, validate the item against the
  schema. Add the full results to the metadata_grid and return a map of
  errors, warnings, and infos for any active ontologies.'''
  global metadata_grid

  ont_id = item['id']
  # these lists will be displayed on the console:
  errors = []
  warnings = []
  infos = []
  # these results are put into the metadata grid:
  results = {}

  # determine how to sort this item in the grid:
  results['foundry'] = True if item.get('in_foundry_order') == 1 else False
  results['obsolete'] = True if item.get('is_obsolete') is True else False
  # if there is no status, put them at the bottom with inactive:
  results['ontology_status'] = item['activity_status'] if 'activity_status' in item else 'inactive'

  has_error = False
  has_warn = False
  has_info = False
  try:
    jsonschema.validate(item, schema)
  except jsonschema.exceptions.ValidationError as ve:
      title = list(ve.absolute_schema_path)[0]  # Find the named section within the schema
      if title == "required":
        field_names = re.findall(r"\'(.*?)\'", ve.message)  # Rather get which field
        if len(field_names) > 0:
          title = field_names[0]
      if title == "properties":
        title = list(ve.absolute_schema_path)[1] # Get which field
      # Get the schema "level" for this field dynamically, if we can
      if title in list(ve.absolute_schema_path) or title in schema['properties']:
        if title in list(ve.absolute_schema_path):
          title_index = list(ve.absolute_schema_path).index(title)
          path = list(ve.absolute_schema_path)[0:(title_index+1)]
        else:
          path = ['properties',title]
        abs_schema = schema
        for schema_item in path:
          if schema_item in abs_schema:
            if 'level' in abs_schema[schema_item]:
              level = abs_schema[schema_item]['level']
            abs_schema = abs_schema[schema_item]

      # add to the results map
      results[title] = level

      # flag for errors, warnings, and infos
      # without adding results to the lists that are logged
      if level == 'error':
        has_error = True
      elif level == 'warning':
        has_warn = True
      elif level == 'info':
        has_info = True

      # these cases will not cause test failure and will not be logged
      # the results are just added to the metadata grid:
      # - orphaned ontology on contact or license check
      # - inactive ontology
      # - obsolete ontology
      # - ontology annotated with `validate: false`
      if not ( (item.get('activity_status') == 'orphaned' and \
              title in ['contact', 'license', 'license-lite']) or \
              (item.get('is_obsolete') is True or item.get('activity_status') == 'inactive' or \
                 item.get('validate') is False) ):
          # get a message for displaying on terminal
          msg = ve.message
          if title in ['license', 'license-lite']:
            # license error message can show up in a few different ways
            search = re.search('\'(.+?)\' is not one of', msg)
            if search:
              msg = '\'%s\' is not a recommended license' % search.group(1)
            else:
              search = re.search('({\'label\'.+?\'url\'.+?}) is not valid', msg)
              if search:
                msg = format_license_msg(search.group(1))
              else:
                search = re.search('({\'url\'.+?\'label\'.+?}) is not valid', msg)
                if search:
                  msg = format_license_msg(search.group(1))

          # format the message with the ontology ID
          msg = '%s %s: %s' % (ont_id.upper(), title, msg)

          # append to correct set of warnings
          if level == 'error':
            errors.append(msg)
          elif level == 'warning':
            # warnings are recommended fixes, not required
            if 'required' in msg:
              msg = msg.replace('required', 'recommended')
            warnings.append(msg)
          elif level == 'info':
            infos.append(msg)

  # add an overall validation status to the grid entry
  if has_error:
    results['validation_status'] = 'FAIL'
  elif has_warn:
    results['validation_status'] = 'WARN'
  elif has_info:
    results['validation_status'] = 'INFO'
  else:
    results['validation_status'] = 'PASS'
  metadata_grid[ont_id] = results

  return {'error': errors, 'warn': warnings, 'info': infos}


def format_license_msg(substr):
  '''Format an exception message for a license issue.'''
  # process to dict
  d = json.loads(substr.replace('\'', '"'))
  url = d['url']
  label = d['label']
  return '\'{0}\' <{1}> is not a recommended license'.format(label, url)


def update_results(results, add):
  '''Given a map of results for all ontologies and a map of results to add,
  append the results to the lists in the map.'''
  results['error'] = results['error'] + add['error']
  results['warn'] = results['warn'] + add['warn']
  results['info'] = results['info'] + add['info']
  return results


def sort_grid(metadata_grid):
  """
  Given a metadata grid as a map, sort the grid based on:
  1. Foundry status
  2. Ontology activity status
  3. Validation status
  4. Alphabetical
  Return a sorted list of IDs.
  """
  foundry = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  active = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  orphaned = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  inactive = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}
  obsolete = {'PASS': [], 'INFO': [], 'WARN': [], 'FAIL': []}

  for ont_id, results in metadata_grid.items():
    # get the info about the ontology to sort on
    ontology_status = results['ontology_status']
    validation_status = results['validation_status']

    # foundry ontologies are displayed first
    # they must be active
    if results['foundry']:
      foundry[validation_status].append(ont_id)
      continue

    # obsolete ontologies are displayed last
    # they are always inactive
    # (inactive does not mean obsolete)
    if results['obsolete']:
      obsolete[validation_status].append(ont_id)
      continue

    # finally, sort by: active, orphaned, inactive
    if ontology_status == 'active':
      active[validation_status].append(ont_id)
    elif ontology_status == 'orphaned':
      orphaned[validation_status].append(ont_id)
    elif ontology_status == 'inactive':
      inactive[validation_status].append(ont_id)

  # concatenate everything to a sorted list:
  def sort_list(arr):
    arr.sort(key=str.lower)
    if not arr:
      return []
    return arr

  sort = []
  for ont_type in [foundry, active, orphaned, inactive, obsolete]:
    for v_status in ['PASS', 'INFO', 'WARN', 'FAIL']:
      sort = sort + sort_list(ont_type[v_status])

  return sort


def save_grid(metadata_grid, headers, grid_outfile):
  '''Given a metadata grid of all results and a grid file to write to, create
  a sorted table of the full results.'''
  if '.csv' in grid_outfile:
    separator = ','
  elif '.tsv' or '.txt' in grid_outfile:
    separator = '\t'
  else:
    print('Grid file must be CSV, TSV, or TXT', file=sys.stderr)
    return

  # Determine order of ontologies based on statuses
  sort_order = sort_grid(metadata_grid)

  # First three help to see overall details
  header = 'Ontology{0}Activity Status{0}Validation Status'.format(separator)
  # After that, we show the results of each check
  for h in headers:
    header += separator + h
  header += '\n'

  with open(grid_outfile, 'w') as f:
    f.write(header)
    for ont_id in sort_order:
      results = metadata_grid[ont_id]
      s = '{1}{0}{2}{0}{3}'.format(separator, ont_id, results['ontology_status'],
                                   results['validation_status'])
      for h in headers:
        if h == 'license':
          # license has two checks
          # so the license entry will be the more severe violation
          all_res = [results['license'], results['license-lite']]
          if 'error' in all_res:
            s += separator + 'error'
          elif 'warning' in all_res:
            s += separator + 'warning'
          elif 'info' in all_res:
            s += separator + 'info'
          else:
            s += separator + 'pass'
          continue
        s += separator + results[h]
      s += '\n'
      f.write(s)

  print('Full validation results written to %s' % grid_outfile)


def print_results(results):
  '''Given a map of results, log results on the console.'''
  for level, messages in results.items():
    for m in messages:
      print('%s\t%s' % (level.upper(), m))


def save_results(results, violations_outfile):
  '''Given a map of results and an output file to write to, write each result
  on a line.'''
  if '.csv' in violations_outfile:
    separator = ','
  elif '.tsv' or '.txt' in violations_outfile:
    separator = '\t'
  else:
    print('Output file must be CSV, TSV, or TXT', file=sys.stderr)
    return
  with open(violations_outfile, 'w') as f:
    f.write('Level%sMessage\n' % separator)
    for level, messages in results.items():
      for m in messages:
        f.write('%s%s%s\n' % (level.upper(), separator, m))


if __name__ == '__main__':
  main(sys.argv)

util/validate-metadata.py
diff --git a/_layouts/ontology_detail.html b/_layouts/ontology_detail.html
index 8b62ddcb6..cf74772e6 100644
--- a/_layouts/ontology_detail.html
+++ b/_layouts/ontology_detail.html
@@ -2,10 +2,10 @@
 layout: default
 ---
 {% include navbar.html %}
-<div class="content">    
+<div class="content">
 
 
-  <div>	
+  <div>
     <div class="page-header">
       <h1>
         {% if page.depicted_by %}
@@ -13,15 +13,15 @@ <h1>
         {% endif %}
         {{ page.title }}
         <small>{{ page.tagline }}</small>
-      </h1>      
+      </h1>
       <p>
         {{page.description}}
       </p>
       {% if page.twitter %}
-      <iframe style="position: static; visibility: visible; width: 190px; height: 20px;" 
-              data-twttr-rendered="true" title="Twitter Follow Button" 
-              class="twitter-follow-button twitter-follow-button" 
-              src="http://platform.twitter.com/widgets/follow_button.a64cf823bcb784855b86e2970134bd2a.en.html#_=1438577078419&amp;dnt=false&amp;id=twitter-widget-0&amp;lang=en&amp;screen_name={{page.twitter}}&amp;show_count=true&amp;show_screen_name=true&amp;size=m" 
+      <iframe style="position: static; visibility: visible; width: 190px; height: 20px;"
+              data-twttr-rendered="true" title="Twitter Follow Button"
+              class="twitter-follow-button twitter-follow-button"
+              src="http://platform.twitter.com/widgets/follow_button.a64cf823bcb784855b86e2970134bd2a.en.html#_=1438577078419&amp;dnt=false&amp;id=twitter-widget-0&amp;lang=en&amp;screen_name={{page.twitter}}&amp;show_count=true&amp;show_screen_name=true&amp;size=m"
               allowtransparency="true" scrolling="no" id="twitter-widget-0" frameborder="0">
       </iframe>
       {% endif %}
@@ -106,16 +106,55 @@ <h2>Products</h2>
             </tbody>
           </table>
         </div>
-        
+        {% if page.usages %}
+        <div>
+          <h2>Usages</h2>
+          {% for p in page.usages %}
+          <dl class="dl-horizontal">
+            <dt>User</dt> <dd><a href="{{p.user}}">{{p.user}}</a></dd>
+            <dt>Description</dt><dd>{{p.description}}</dd>
+            {% if p.type %}
+            <dt>Type</dt> <dd>{{p.type}}</dd>
+            {% endif %}
+            {% if p.seeAlso %}
+            <dt>See also</dt> <dd><a href="{{p.seeAlso}}">{{p.seeAlso}}</a></dd>
+            {% endif %}
+            {% if p.examples %}
+            <dt>Examples</dt>
+            <dd>
+              <ul style="padding-left: 20px">
+              {% for example in p.examples %}
+                <li><a href="{{example.url}}">{{example.description}}</a></li>
+              {% endfor %}
+              </ul>
+            </dd>
+            {% endif %}
+            {% if p.publications %}
+            <dt>Publications</dt>
+            <dd>
+              <ul style="padding-left: 20px">
+              {% for publication in p.publications %}
+                <li><a href="{{publication.id}}">{{publication.title}}</a></li>
+              {% endfor %}
+              </ul>
+            </dd>
+            {% endif %}
+          </dl>
+          {% endfor %}
+        </div>
+        {% endif %}
+
 
       </div>
+
+
       <div class="col-md-4">
         <dl class="dl-horizontal" style="dd { margin-left: 0 }">
 
           <dt>
             ID Space
-            <span data-toggle="tooltip" 
-                  title="ID prefix" 
+            <span data-toggle="tooltip"
+                  title="ID prefix"
                   html="true">
             </span>
           </dt>
@@ -166,7 +205,7 @@ <h2>Products</h2>
 						{% endif %}
 					<dd>
 					{% endif %}
-					
+
           <dt>Homepage</dt>
           <dd>
             <a href="{{page.homepage}}">{{page.homepage}}</a>
@@ -185,7 +224,7 @@ <h2>Products</h2>
 
           <dt>Contact</dt>
           <dd>
-            <a href="mailto:{{page.contact.email}}">{{page.contact.label}}</a> 
+            <a href="mailto:{{page.contact.email}}">{{page.contact.label}}</a>
           </dd>
 
           <dt>Trackers</dt>
@@ -197,7 +236,7 @@ <h2>Products</h2>
           <dd>
             <a href="/domain/{{page.domain}}.html">{{page.domain}}</a>
           </dd>
-					
+
           {% if page.mailing_list %}
           <dt>Mail List</dt>
           <dd>
@@ -271,14 +310,16 @@ <h2>Products</h2>
           {% endif %}
 
 
+
+
         </dl>
-        
+
 
         <div class="btn-group" role="group" aria-label="Source">
           <a href="https://github.com/OBOFoundry/OBOFoundry.github.io/blob/master/ontology/{{page.id}}.md">
-            <button type="button" 
-                    data-toggle="tooltip" 
-                    title="See FAQ entry: How is metadata stored?" 
+            <button type="button"
+                    data-toggle="tooltip"
+                    title="See FAQ entry: How is metadata stored?"
                     html="true"
                     class="btn btn-default">
               View
@@ -286,18 +327,18 @@ <h2>Products</h2>
           </a>
           <a href="https://github.com/OBOFoundry/OBOFoundry.github.io/edit/master/ontology/{{page.id}}.md">
 
-            <button type="button" 
-                    data-toggle="tooltip" 
-                    title="See FAQ entry: How I do edit my metadata?" 
+            <button type="button"
+                    data-toggle="tooltip"
+                    title="See FAQ entry: How I do edit my metadata?"
                     html="true"
                     class="btn btn-default">
               Edit</button>
           </a>
           <a href="https://github.com/OBOFoundry/purl.obolibrary.org/blob/master/config/{{page.id}}.yml">
 
-            <button type="button" 
-                    data-toggle="tooltip" 
-                    title="See FAQ entry: How I do edit my PURL?" 
+            <button type="button"
+                    data-toggle="tooltip"
+                    title="See FAQ entry: How I do edit my PURL?"
                     html="true"
                     class="btn btn-default">
               PURL</button>
@@ -326,10 +367,10 @@ <h2>Products</h2>
     </div>
 
     {% if page.comments %}
-    <div>	
-      <div >    
+    <div>
+      <div >
         <h2>Comments Section</h2>
-        <p>Feel free to comment on the post but keep it clean and on topic.</p>	
+        <p>Feel free to comment on the post but keep it clean and on topic.</p>
         <div id="disqus_thread"></div>
         <script type="text/javascript">
           /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
@@ -347,9 +388,8 @@ <h2>Comments Section</h2>
       </div>
     </div>
     {% endif %}
-    
+
     <!-- Twitter -->
     <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
 
   </div>
-  
diff --git a/ontology/cl.md b/ontology/cl.md
index f23ddf4cf..72b3a616c 100644
--- a/ontology/cl.md
+++ b/ontology/cl.md
@@ -62,7 +62,9 @@ usages:
     seeAlso: https://www.biosharing.org/biodbcore-000034
     type: annotation
     description: The National Human Genome Research Institute (NHGRI) launched a public research consortium named ENCODE, the Encyclopedia Of DNA Elements, in September 2003, to carry out a project to identify all functional elements in the human genome sequence. The ENCODE DCC users Uberon to annotate samples
-    reference: https://doi.org/10.1093/database/bav010
+    publications:
+      - id: https://doi.org/10.1093/database/bav010
+        title: "Ontology application and use at the ENCODE DCC"
   - user: http://fantom5-collaboration.gsc.riken.jp/
     type: annotation
     description: FANTOM5 is using Uberon and CL to annotate samples allowing for transcriptome analyses with cell-type and tissue-level specificity.
diff --git a/ontology/dpo.md b/ontology/dpo.md
index 739b4d52f..4240ca2f7 100644
--- a/ontology/dpo.md
+++ b/ontology/dpo.md
@@ -34,7 +34,7 @@ publications:
 usages:
   - user: http://flybase.org
     description: FlyBase uses dpo for phenotype data annotation in Drosophila
-    example:
+    examples:
       - url: "http://flybase.org/cgi-bin/cvreport.html?rel=is_a&id=FBcv:0002030"
         description: "alleles and constructs annotated to pupal lethal in FlyBase"
 activity_status: active
diff --git a/ontology/eco.md b/ontology/eco.md
index 749f18bd0..8e730e6cf 100644
--- a/ontology/eco.md
+++ b/ontology/eco.md
@@ -42,8 +42,11 @@ usages:
     type: annotation
     description: ECO is used by the Monarch Initiative for evidence types for disease to phenotype annotations.
     examples:
-      - url: https://monarchinitiative.org/phenotype/HP%3A0001300#diseases
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      - url: https://monarchinitiative.org/phenotype/HP%3A0001300#disease
+        description: "Parkinsonism: Characteristic neurologic anomaly resulting form degeneration of dopamine-generating cells in the substantia nigra, a region of the midbrain, characterized clinically by shaking, rigidity, slowness of movement and difficulty with walking and gait."
+    publications:
+      - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+        title: "The Monarch Initiative: an integrative data and analytic platform connecting phenotypes to genotypes across species"
 activity_status: active
 ---
 
@@ -53,7 +56,7 @@ The Evidence & Conclusion Ontology (ECO) describes types of scientific evidence
 
 ECO comprises two high-level classes, evidence and assertion method, where evidence is defined as “a type of information that is used to support an assertion,” and assertion method is defined as “a means by which a statement is made about an entity.” Together evidence and assertion method can be combined to describe both the support for an assertion and whether that assertion was made by a human being or a computer. However, ECO is _not_ used to make the assertion itself; for that, one would use another ontology, free text description, or some other means.
 
-ECO was originally created around the year 2000 to support gene product annotation by the Gene Ontology, which now displays ECO in AmiGO 2. Today ECO is used by many groups concerned with evidence in scientific research. 
+ECO was originally created around the year 2000 to support gene product annotation by the Gene Ontology, which now displays ECO in AmiGO 2. Today ECO is used by many groups concerned with evidence in scientific research.
 
 ***
 For **advice on requesting new terms**, please see **[the Evidence & Conclusion Ontology wiki](https://github.com/evidenceontology/evidenceontology/wiki/New-term-request-how-to)**.
diff --git a/ontology/envo.md b/ontology/envo.md
index 40226da4c..4bdd3ab9d 100644
--- a/ontology/envo.md
+++ b/ontology/envo.md
@@ -42,40 +42,32 @@ dependencies:
   - id: po
   - id: go
 usages:
-  - type: data-annotation
+  - user: http://eol.org
+    type: data-annotation
     description: "describing species habitats"
     examples:
-      url: http://eol.org/pages/211700/data
-    resources:
-      url: http://eol.org
-      label: EOL
-  - type: data-annotation
+      - url: http://eol.org/pages/211700/data
+        description: "Pseudobarbus burchelli (Tradou Redfin) is a species of bony fishes in the family Cyprinidae. They are associated with freshwater habitat. Individuals can grow to 13.5 cm. They have sexual reproduction."
+  - user: http://globalbioticinteractions.org
+    type: data-annotation
     description: "describing stomach contents"
-    datasets:
-      url: https://s3.amazonaws.com/globi/snapshot/target/data/taxa/interactions.csv.gz
-    resources:
-      url: http://globalbioticinteractions.org
-      label: GloBI
-  - type: dataset-description
+  - user: http://www.nature.com/sdata/
+    type: dataset-description
     description: "annotating datasets in data repositories"
     seeAlso: http://blogs.nature.com/scientificdata/2015/12/17/isa-explorer/
-    search: http://scientificdata.isa-explorer.org/
-    resources:
-      url: http://www.nature.com/sdata/
-      label: Nature Scientific Data
   - user: http://oceans.taraexpeditions.org/en/
     description: Samples collected during Tara Oceans expedition are annotated with ENVO
-    example:
+    examples:
       - url: https://www.ebi.ac.uk/metagenomics/projects/ERP001736/samples/ERS487899
         description: "Sample collected during the Tara Oceans expedition (2009-2013) at station TARA_004 (latitudeN=36.5533, longitudeE=-6.5669)"
   - user: https://www.ncbi.nlm.nih.gov/
     description: Annotation of habitats of microbes
-    example:
+    examples:
       - url: https://www.ncbi.nlm.nih.gov/nuccore/NC_016642
         description: "Annotation of habitat of Pseudovibrio sp. FO-BEG1 to marine environment"
   - user: https://www.planetmicrobe.org/project/
     description: Annotation and semantic search over microbial data sets
-    example:
+    examples:
       - url: https://www.planetmicrobe.org/project/#/samples/200
         description: "Example metadata of a sample of marine water near Lisboa, taken as part of the Ocean Sampling Day Project (https://www.microb3.eu/osd.html). ENVO is used for the fields environmental feature, material, and biome."
 jobs:
diff --git a/ontology/fbbt.md b/ontology/fbbt.md
index 259b8e644..80cc3d004 100644
--- a/ontology/fbbt.md
+++ b/ontology/fbbt.md
@@ -55,7 +55,7 @@ usages:
         description: "genes expressed in ring neuron R2 in VFB"
   - user: http://flybase.org
     description: Flybase uses FBbt for expression and phenotype data annotation in Drosophila
-    example:
+    examples:
       - url: "http://flybase.org/cgi-bin/cvreport.html?rel=is_a&id=FBbt:00005106"
         description: "alleles, constructs and insertions annotated to neuron in FlyBase"
 activity_status: active
diff --git a/ontology/fbcv.md b/ontology/fbcv.md
index 82605a6e9..3596283c3 100644
--- a/ontology/fbcv.md
+++ b/ontology/fbcv.md
@@ -28,7 +28,7 @@ browsers:
 usages:
   - user: http://flybase.org
     description: FlyBase uses FBcv for phenotype data annotation in Drosophila
-    example:
+    examples:
       - url: "http://flybase.org/cgi-bin/cvreport.html?rel=is_a&id=FBcv:0000391"
         description: "alleles and constructs annotated to bang sensitive in FlyBase"
 activity_status: active
diff --git a/ontology/fypo.md b/ontology/fypo.md
index f62dfcdd6..86924def8 100644
--- a/ontology/fypo.md
+++ b/ontology/fypo.md
@@ -30,7 +30,7 @@ depicted_by: https://github.com/pombase/website/blob/master/src/assets/FYPO_logo
 usages:
   - user: https://www.pombase.org
     description: Pombase uses fypo for phenotype data annotation in fission yeast
-    example:
+    examples:
       - url: https://www.pombase.org/term/FYPO:0000059
         description: "genotypes annotated to abnormal mitotic cell cycle in fission yeast"
 activity_status: active
diff --git a/ontology/hancestro.md b/ontology/hancestro.md
index cf1bcea6e..1bc922b71 100644
--- a/ontology/hancestro.md
+++ b/ontology/hancestro.md
@@ -22,19 +22,25 @@ license:
 usages:
   - user: http://www.ebi.ac.uk/efo
     description: The Experimental Factor Ontology (EFO) provides a systematic description of many experimental variables available in EBI databases, and for external projects such as the NHGRI GWAS catalogue. It combines parts of several biological ontologies, such as anatomy, disease and chemical compounds.
-    example: https://www.ebi.ac.uk/ols/ontologies/efo/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+    examples:
+      - url: https://www.ebi.ac.uk/ols/ontologies/efo/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+        description: Population category defined using ancestry informative markers (AIMs) based on genetic/genomic data
   - user: https://genepio.org/
     description: The Genomic Epidemiology Ontology (GenEpiO) covers vocabulary necessary to identify, document and research foodborne pathogens and associated outbreaks.
-    example: https://www.ebi.ac.uk/ols/ontologies/genepio/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+    examples:
+      - url: https://www.ebi.ac.uk/ols/ontologies/genepio/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+        description: Population category defined using ancestry informative markers (AIMs) based on genetic/genomic data
   - user: http://foodon.org
     description: FoodOn (http://foodon.org) is a consortium-driven project to build a comprehensive and easily accessible global farm-to-fork ontology about food, that accurately and consistently describes foods commonly known in cultures from around the world.
-    example: https://www.ebi.ac.uk/ols/ontologies/foodon/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+    examples:
+      - url: https://www.ebi.ac.uk/ols/ontologies/foodon/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+        description: Population category defined using ancestry informative markers (AIMs) based on genetic/genomic data
 activity_status: active
 ---
 
 # Summary
 
-The Human Ancestry Ontology (HANCESTRO) provides a systematic description of the ancestry concepts used in the NHGRI-EBI Catalog of published genome-wide association studies. 
+The Human Ancestry Ontology (HANCESTRO) provides a systematic description of the ancestry concepts used in the NHGRI-EBI Catalog of published genome-wide association studies.
 
 * Home: [https://github.com/EBISPOT/ancestro](https://github.com/EBISPOT/ancestro)  
 
@@ -43,7 +49,7 @@ The Human Ancestry Ontology (HANCESTRO) provides a systematic description of the
 Use the following URI to download this ontology
 
 * [http://purl.obolibrary.org/obo/hancestro.owl](http://purl.obolibrary.org/obo/hancestro.owl)
-* This should point to: [https://raw.githubusercontent.com/EBISPOT/ancestro/master/hancestro_inferred.owl](https://raw.githubusercontent.com/EBISPOT/ancestro/master/hancestro_inferred.owl) 
+* This should point to: [https://raw.githubusercontent.com/EBISPOT/ancestro/master/hancestro_inferred.owl](https://raw.githubusercontent.com/EBISPOT/ancestro/master/hancestro_inferred.owl)
 
 A non-reasoned version of the ontology is available at [https://raw.githubusercontent.com/EBISPOT/ancestro/master/hancestro.owl](https://raw.githubusercontent.com/EBISPOT/ancestro/master/hancestro.owl)
 
diff --git a/ontology/mondo.md b/ontology/mondo.md
index deca96159..b4def9064 100644
--- a/ontology/mondo.md
+++ b/ontology/mondo.md
@@ -45,8 +45,11 @@ usages:
     type: annotation
     description: Mondo is used by the Monarch Initiative for disease annotations.
     examples:
-      - url: https://monarchinitiative.org/phenotype/HP:0001300#diseases
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      - url: https://monarchinitiative.org/phenotype/HP:0001300#disease
+        description: "Parkinsonism: Characteristic neurologic anomaly resulting form degeneration of dopamine-generating cells in the substantia nigra, a region of the midbrain, characterized clinically by shaking, rigidity, slowness of movement and difficulty with walking and gait."
+    publications:
+      - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+        title: "The Monarch Initiative: an integrative data and analytic platform connecting phenotypes to genotypes across species "
 activity_status: active
 ---
 
@@ -59,7 +62,7 @@ These precise mappings are available in three ways depending on the format:
  - the [mondo-with-equivalent](http://purl.obolibrary.org/obo/mondo/mondo-with-equivalents.owl) edition uses OWL equivalence axioms directly in the ontology. Note this makes it harder to browse in some portals, but this edition may be preferable for computational use. The owl edition also includes axiomatization using CL, Uberon, GO, HP, RO, NCBITaxon.
  - the primary release versions (mondo.owl, mondo.obo) are simpler, lacking owl equivalence axioms from Mondo classes to terms from other databases; instead, xrefs are used for linking these terms. If the ID is one of Orphanet, OMIM, DOID or EFO then the xref precisely shadows the equivalence axiom.
 - The [mondo-with-equivalents json edition](http://purl.obolibrary.org/obo/mondo/mondo-with-equivalents.json) has all owl equivalencies as well as all xrefs to other disease sources.
-  
+
 Tracker
 
  - https://github.com/monarch-initiative/mondo/issues
diff --git a/ontology/mro.md b/ontology/mro.md
index d4f44ac13..e4a7c6840 100644
--- a/ontology/mro.md
+++ b/ontology/mro.md
@@ -21,7 +21,10 @@ usages:
     description: MRO is used by the The Immune Epitope Database (IEDB) annotations
     examples:
       - url: https://www.iedb.org/assay/1357035
-    reference: DOI:10.1093/nar/gky1006
+        description: "Epitope ID: 59611 based on reference 1003499"
+    publications:
+      - id: https://doi.org/10.1093/nar/gky1006
+        title: "The Immune Epitope Database (IEDB): 2018 update"
 activity_status: active
 ---
 
diff --git a/ontology/nomen.md b/ontology/nomen.md
index 899a3d125..04ace8435 100644
--- a/ontology/nomen.md
+++ b/ontology/nomen.md
@@ -24,8 +24,8 @@ build:
   system: git
 usages:
   - user: https://taxonworks.org
-    label: TaxonWorks
     seeAlso: https://github.com/SpeciesFileGroup/taxonworks
+    description: TaxonWorks is an integrated web-based workbench for taxonomists and biodiversity scientists.
     type: application
 mailing_list: https://groups.google.com/forum/#!forum/nomen-discuss
 tracker: https://github.com/SpeciesFileGroup/nomen/issues
diff --git a/ontology/obi.md b/ontology/obi.md
index f2e36e18e..a978329a8 100644
--- a/ontology/obi.md
+++ b/ontology/obi.md
@@ -41,12 +41,12 @@ browsers:
 usages:
   - user: http://upibi.org/turbo/
     description: PennTURBO accelerates the processes of finding and connecting key information from clinical records, via semantic modeling of the processes that generated the data. This makes the discovery of previously unappreciated relations between the data possible for research and for operational tasks.
-    example:
+    examples:
       - url: https://github.com/PennTURBO/Turbo-Documentation/blob/master/IBI_CIC_TURBO_MAM_20190102.pdf
         description: "CYP2C1*2/*2 MI patient taking Clopidogrel"
   - user: http://evidenceontology.org/
     description: The Evidence & Conclusion Ontology (ECO) describes types of scientific evidence within the biological research domain. ECO uses OBI to logically describe how the evidence arises from an investigation.
-    example:
+    examples:
       - url: http://purl.obolibrary.org/obo/ECO_0001820
         description: "rapid amplification of cDNA ends polymerase chain reaction evidence"
 activity_status: active
diff --git a/ontology/pato.md b/ontology/pato.md
index 0b28b236b..e2da3cc2e 100644
--- a/ontology/pato.md
+++ b/ontology/pato.md
@@ -40,7 +40,10 @@ usages:
     description: PATO is used by the Human Phenotype Ontology (HPO) for logical definitions of phenotypes that facilitate cross-species integration.
     examples:
       - url: https://www.ebi.ac.uk/ols/ontologies/hp/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHP_0011017&viewMode=All&siblings=false
-    reference: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6324074/
+        description: An abnormality in a cellular process.
+    publications:
+      - id: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6324074/
+        title: "Expansion of the Human Phenotype Ontology (HPO) knowledge base and resources"
 activity_status: active
 ---
 
diff --git a/ontology/po.md b/ontology/po.md
index e740d669b..fa7cbbd8e 100644
--- a/ontology/po.md
+++ b/ontology/po.md
@@ -54,10 +54,12 @@ usages:
     description: Maize CELL genomics DB uses PO to annotate images
     examples:
       - url: http://maize.jcvi.org/cellgenomics/geneDB_list.php?filter=3
+        description: LhG4 Promoter Drivers
   - user: http://maizegdb.org/
     description: MaizeGDB uses PO for annotation of genes
     examples:
       - url: http://maizegdb.org/gene_center/gene/GRMZM5G863962
+        description: Introduced in gene model set 5b in assembly version RefGen_v2.
   - user: http://gramene.org/
     description: Gramene uses PO for the annotation of plant genes
     examples:
diff --git a/ontology/ro.md b/ontology/ro.md
index 1226cc4dc..ca263f155 100644
--- a/ontology/ro.md
+++ b/ontology/ro.md
@@ -53,13 +53,13 @@ license:
 usages:
   - user: http://geneontology.org
     type: annotation
-    description: RO is used for annotation extensions in the GO
-    reference: https://doi.org/10.1186/1471-2105-15-155
-  - user: http://geneontology.org
-    type: annotation
-    description: RO is used for GO Causal Activity Models
+    description: RO is used for annotation extensions in the GO and GO Causal Activity Models.
+    publications:
+      - id: https://doi.org/10.1186/1471-2105-15-155
+        title: "A method for increasing expressivity of Gene Ontology annotations using a compositional approach"
     examples:
-      - http://model.geneontology.org/56d1143000003402
+      - url: http://model.geneontology.org/56d1143000003402
+        description: wg_biogenesis_FlyBase
 activity_status: active
 ---
 
diff --git a/ontology/uberon.md b/ontology/uberon.md
index 7c40c3c77..7693a6317 100644
--- a/ontology/uberon.md
+++ b/ontology/uberon.md
@@ -31,7 +31,9 @@ usages:
     seeAlso: https://www.biosharing.org/biodbcore-000034
     type: annotation
     description: The National Human Genome Research Institute (NHGRI) launched a public research consortium named ENCODE, the Encyclopedia Of DNA Elements, in September 2003, to carry out a project to identify all functional elements in the human genome sequence. The ENCODE DCC users Uberon to annotate samples
-    reference: https://doi.org/10.1093/database/bav010
+    publications:
+      - id: https://doi.org/10.1093/database/bav010
+        title: "Ontology application and use at the ENCODE DCC"
   - user: http://fantom5-collaboration.gsc.riken.jp/
     type: annotation
     description: FANTOM5 is using Uberon and CL to annotate samples allowing for transcriptome analyses with cell-type and tissue-level specificity.
@@ -42,30 +44,31 @@ usages:
     type: query
     description: Querying expression and phenotype data
   - user: https://geneontology.org/
-    label: GO Database
     type: query
-    description: Querying for functional annotations relevant to a tissue
+    description: GO Database is used for querying for functional annotations relevant to a tissue
     examples:
       - url: http://amigo.geneontology.org/amigo/term/UBERON:0000955
         description: GO annotations relevant to the uberon class for brain
   - user: http://phenoscape.org
-    label: Phenoscape
     description: The Phenoscape project is both a major driver of and contributor to Uberon, contibuting thousands of terms. The teleost (bony fishes) component of Uberon was derived from the Teleost Anatomy Ontology, developed by the Phenoscape group. Most of the high level design of the skeletal system comes from the Vertebrate Skeletal Anatomy Ontology (VSAO), also created by the Phenoscape group. Phenoscape curators continue to extend the ontology, covering a wide variety of tetrapod structures, with an emphasis on the appendicular system.
-  - url: https://neuinfo.org/
-    label: Neuroscience Information Framework
+  - user: https://neuinfo.org/
+    description: Searchable collection of neuroscience data and ontology for neuroscience
     type: Database
-  - url: https://scicrunch.org/
-    label: SciCrunch
+  - user: https://scicrunch.org/
+    description: "cooperative data platform to be used by diverse communities in making data more FAIR."
     type: Database
-  - url: http://single-cell.clst.riken.jp/
-    label: SCPortalen
-    reference: https://doi.org/10.1093/nar/gkx949
+  - user: http://single-cell.clst.riken.jp/
+    description: SCPortalen
+    publications:
+      - id: https://doi.org/10.1093/nar/gkx949
+        title: "SCPortalen: human and mouse single-cell centric database"
     type: Database
-  - url: https://www.ebi.ac.uk/chembl/
-    label: ChEMBL
+  - user: https://www.ebi.ac.uk/chembl/
     description: "ChEMBL uses Uberon to describe organ/tissue information in assays"
-    reference: https://doi.org/10.1093/nar/gky1075
     type: Database
+    publications:
+      - id: https://doi.org/10.1093/nar/gky1075
+        title: "ChEMBL: towards direct deposition of bioassay data"
 funded_by:
   - "NIH R24OD011883"
   - "NIH R01HG004838"
diff --git a/ontology/upheno.md b/ontology/upheno.md
index 73c33fb7b..8fcf39aaa 100644
--- a/ontology/upheno.md
+++ b/ontology/upheno.md
@@ -24,8 +24,11 @@ usages:
     type: analysis
     description: uPheno is used by the Monarch Initiative for cross-species inference.
     examples:
-      - url: https://monarchinitiative.org/phenotype/HP:0001300#diseases
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      - url: https://monarchinitiative.org/phenotype/HP:0001300#disease
+        description: "Characteristic neurologic anomaly resulting form degeneration of dopamine-generating cells in the substantia nigra, a region of the midbrain, characterized clinically by shaking, rigidity, slowness of movement and difficulty with walking and gait."
+    publications:
+      - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+        title: "The Monarch Initiative: an integrative data and analytic platform connecting phenotypes to genotypes across species "
 build:
   source_url: http://build.berkeleybop.org/job/build-pheno-ontologies/lastSuccessfulBuild/artifact/*zip*/archive.zip
   path: archive/ontology
diff --git a/ontology/wbbt.md b/ontology/wbbt.md
index c61284b40..e62740d63 100644
--- a/ontology/wbbt.md
+++ b/ontology/wbbt.md
@@ -32,7 +32,10 @@ usages:
     description: WormBase uses WBbt to curate anatomical expression patterns and anatomy function annotations, and to allow search and indexing on the WormBase site
     examples:
       - url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
-    reference: https://academic.oup.com/nar/article/48/D1/D762/5603222
+        description: "Expression for gene daf-16 with WormBase ID WBGene00000912"
+    publications:
+      - id: https://academic.oup.com/nar/article/48/D1/D762/5603222
+        title: "WormBase: a modern Model Organism Information Resource"
 activity_status: active
 ---
 
diff --git a/ontology/wbls.md b/ontology/wbls.md
index 5645d0887..ff6f7a639 100644
--- a/ontology/wbls.md
+++ b/ontology/wbls.md
@@ -32,7 +32,10 @@ usages:
     description: WormBase uses WBls to curate temporal expression patterns, and to allow search and indexing on the WormBase site
     examples:
       - url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
-    reference: https://academic.oup.com/nar/article/48/D1/D762/5603222
+        description: Expression for daf-16 gene with WormBase ID WBGene00000912.
+    publications:
+      - id: https://academic.oup.com/nar/article/48/D1/D762/5603222
+        title: "WormBase: a modern Model Organism Information Resource"
 activity_status: active
 ---
 
diff --git a/ontology/wbphenotype.md b/ontology/wbphenotype.md
index 54fd7d788..e78ab35ee 100644
--- a/ontology/wbphenotype.md
+++ b/ontology/wbphenotype.md
@@ -32,14 +32,20 @@ usages:
     type: annotation
     description: WormBase uses WBPhenotype to curate worm phenotypes, and to allow search and indexing on the WormBase site
     examples:
-      - url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=phenotype
-    reference: https://academic.oup.com/nar/article/48/D1/D762/5603222
+      - url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
+        description: Expression for daf-16 gene with WormBase ID WBGene00000912.
+    publications:
+      - id: https://academic.oup.com/nar/article/48/D1/D762/5603222
+        title: "WormBase: a modern Model Organism Information Resource"
   - user: https://monarchinitiative.org/
     type: annotation
     description: Monarch integrates phenotype annotations from sources such as WormBase, and allows for querying using the WBPhenotype ontology.
     examples:
       - url: https://monarchinitiative.org/phenotype/WBPhenotype%3A0000370
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+        description: "Egg long: The fertilized oocytes have a greater than standard length measured end to end compared to control."
+    publications:
+      - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+        title: "The Monarch Initiative: an integrative data and analytic platform connecting phenotypes to genotypes across species "
 activity_status: active
 ---
 
diff --git a/ontology/zp.md b/ontology/zp.md
index 1d6afe3e8..bb461cec9 100644
--- a/ontology/zp.md
+++ b/ontology/zp.md
@@ -36,6 +36,9 @@ usages:
     description: Monarch integrates phenotype annotations from sources such as ZFIIN, and allows for querying using the ZP ontology.
     examples:
       - url: https://monarchinitiative.org/phenotype/ZP:0005692
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+        description: "adaxial cell absent, abnormal: Abnormal(ly) absent (of) adaxial cell."
+    publications:
+      - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+        title: "The Monarch Initiative: an integrative data and analytic platform connecting phenotypes to genotypes across species"
 activity_status: active
 ---
diff --git a/registry/ontologies.yml b/registry/ontologies.yml
index b3ebcb348..6a2571901 100644
--- a/registry/ontologies.yml
+++ b/registry/ontologies.yml
@@ -330,14 +330,14 @@ ontologies:
       information from clinical records, via semantic modeling of the processes that
       generated the data. This makes the discovery of previously unappreciated relations
       between the data possible for research and for operational tasks.
-    example:
+    examples:
     - description: CYP2C1*2/*2 MI patient taking Clopidogrel
       url: https://github.com/PennTURBO/Turbo-Documentation/blob/master/IBI_CIC_TURBO_MAM_20190102.pdf
     user: http://upibi.org/turbo/
   - description: The Evidence & Conclusion Ontology (ECO) describes types of scientific
       evidence within the biological research domain. ECO uses OBI to logically describe
       how the evidence arises from an investigation.
-    example:
+    examples:
     - description: rapid amplification of cDNA ends polymerase chain reaction evidence
       url: http://purl.obolibrary.org/obo/ECO_0001820
     user: http://evidenceontology.org/
@@ -388,8 +388,11 @@ ontologies:
   - description: PATO is used by the Human Phenotype Ontology (HPO) for logical definitions
       of phenotypes that facilitate cross-species integration.
     examples:
-    - url: https://www.ebi.ac.uk/ols/ontologies/hp/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHP_0011017&viewMode=All&siblings=false
-    reference: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6324074/
+    - description: An abnormality in a cellular process.
+      url: https://www.ebi.ac.uk/ols/ontologies/hp/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHP_0011017&viewMode=All&siblings=false
+    publications:
+    - id: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6324074/
+      title: Expansion of the Human Phenotype Ontology (HPO) knowledge base and resources
     type: annotation
     user: https://hpo.jax.org/app/
 - activity_status: active
@@ -455,11 +458,13 @@ ontologies:
     user: http://planteome.org/
   - description: Maize CELL genomics DB uses PO to annotate images
     examples:
-    - url: http://maize.jcvi.org/cellgenomics/geneDB_list.php?filter=3
+    - description: LhG4 Promoter Drivers
+      url: http://maize.jcvi.org/cellgenomics/geneDB_list.php?filter=3
     user: http://maize.jcvi.org/
   - description: MaizeGDB uses PO for annotation of genes
     examples:
-    - url: http://maizegdb.org/gene_center/gene/GRMZM5G863962
+    - description: Introduced in gene model set 5b in assembly version RefGen_v2.
+      url: http://maizegdb.org/gene_center/gene/GRMZM5G863962
     user: http://maizegdb.org/
   - description: Gramene uses PO for the annotation of plant genes
     examples:
@@ -1027,6 +1032,27 @@ ontologies:
     ontology_purl: http://purl.obolibrary.org/obo/cido.owl
   title: Coronavirus Infectious Disease Ontology
   tracker: https://github.com/cido-ontology/cido/issues
+- activity_status: active
+  contact:
+    email: bgee@sib.swiss
+    github: fbastian
+    label: Frederic Bastian
+  description: An ontology to capture confidence information about annotations.
+  homepage: https://github.com/BgeeDB/confidence-information-ontology
+  id: cio
+  layout: ontology_detail
+  license:
+    label: CC0
+    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/cc-zero.png
+    url: https://creativecommons.org/publicdomain/zero/1.0/
+  ontology_purl: http://purl.obolibrary.org/obo/cio.owl
+  products:
+  - id: cio.owl
+    ontology_purl: http://purl.obolibrary.org/obo/cio.owl
+  - id: cio.obo
+    ontology_purl: http://purl.obolibrary.org/obo/cio.obo
+  title: Confidence Information Ontology
+  tracker: https://github.com/BgeeDB/confidence-information-ontology
 - activity_status: active
   build:
     checkout: git clone https://github.com/obophenotype/cell-ontology.git
@@ -1105,7 +1131,9 @@ ontologies:
       research consortium named ENCODE, the Encyclopedia Of DNA Elements, in September
       2003, to carry out a project to identify all functional elements in the human
       genome sequence. The ENCODE DCC users Uberon to annotate samples
-    reference: https://doi.org/10.1093/database/bav010
+    publications:
+    - id: https://doi.org/10.1093/database/bav010
+      title: Ontology application and use at the ENCODE DCC
     seeAlso: https://www.biosharing.org/biodbcore-000034
     type: annotation
     user: https://www.encodeproject.org/
@@ -1486,7 +1514,7 @@ ontologies:
   tracker: https://github.com/FlyBase/drosophila-phenotype-ontology/issues
   usages:
   - description: FlyBase uses dpo for phenotype data annotation in Drosophila
-    example:
+    examples:
     - description: alleles and constructs annotated to pupal lethal in FlyBase
       url: http://flybase.org/cgi-bin/cvreport.html?rel=is_a&id=FBcv:0002030
     user: http://flybase.org
@@ -1622,8 +1650,15 @@ ontologies:
   - description: ECO is used by the Monarch Initiative for evidence types for disease
       to phenotype annotations.
     examples:
-    - url: https://monarchinitiative.org/phenotype/HP%3A0001300#diseases
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+    - description: 'Parkinsonism: Characteristic neurologic anomaly resulting form
+        degeneration of dopamine-generating cells in the substantia nigra, a region
+        of the midbrain, characterized clinically by shaking, rigidity, slowness of
+        movement and difficulty with walking and gait.'
+      url: https://monarchinitiative.org/phenotype/HP%3A0001300#disease
+    publications:
+    - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      title: 'The Monarch Initiative: an integrative data and analytic platform connecting
+        phenotypes to genotypes across species'
     type: annotation
     user: https://monarchinitiative.org/
 - activity_status: active
@@ -1839,39 +1874,33 @@ ontologies:
   usages:
   - description: describing species habitats
     examples:
+    - description: Pseudobarbus burchelli (Tradou Redfin) is a species of bony fishes
+        in the family Cyprinidae. They are associated with freshwater habitat. Individuals
+        can grow to 13.5 cm. They have sexual reproduction.
       url: http://eol.org/pages/211700/data
-    resources:
-      label: EOL
-      url: http://eol.org
     type: data-annotation
-  - datasets:
-      url: https://s3.amazonaws.com/globi/snapshot/target/data/taxa/interactions.csv.gz
-    description: describing stomach contents
-    resources:
-      label: GloBI
-      url: http://globalbioticinteractions.org
+    user: http://eol.org
+  - description: describing stomach contents
     type: data-annotation
+    user: http://globalbioticinteractions.org
   - description: annotating datasets in data repositories
-    resources:
-      label: Nature Scientific Data
-      url: http://www.nature.com/sdata/
-    search: http://scientificdata.isa-explorer.org/
     seeAlso: http://blogs.nature.com/scientificdata/2015/12/17/isa-explorer/
     type: dataset-description
+    user: http://www.nature.com/sdata/
   - description: Samples collected during Tara Oceans expedition are annotated with
       ENVO
-    example:
+    examples:
     - description: Sample collected during the Tara Oceans expedition (2009-2013)
         at station TARA_004 (latitudeN=36.5533, longitudeE=-6.5669)
       url: https://www.ebi.ac.uk/metagenomics/projects/ERP001736/samples/ERS487899
     user: http://oceans.taraexpeditions.org/en/
   - description: Annotation of habitats of microbes
-    example:
+    examples:
     - description: Annotation of habitat of Pseudovibrio sp. FO-BEG1 to marine environment
       url: https://www.ncbi.nlm.nih.gov/nuccore/NC_016642
     user: https://www.ncbi.nlm.nih.gov/
   - description: Annotation and semantic search over microbial data sets
-    example:
+    examples:
     - description: Example metadata of a sample of marine water near Lisboa, taken
         as part of the Ocean Sampling Day Project (https://www.microb3.eu/osd.html).
         ENVO is used for the fields environmental feature, material, and biome.
@@ -1931,6 +1960,7 @@ ontologies:
     url: https://creativecommons.org/licenses/by/4.0/
   ontology_purl: http://purl.obolibrary.org/obo/exo.owl
   page: http://ctdbase.org/downloads/#exposures
+  preferredPrefix: ExO
   products:
   - id: exo.owl
     ontology_purl: http://purl.obolibrary.org/obo/exo.owl
@@ -2048,18 +2078,15 @@ ontologies:
   tracker: http://purl.obolibrary.org/obo/fbbt/tracker
   usages:
   - description: VFB uses FBbt to annotate brain images
-    example:
+    examples:
     - description: Ring neuron R2 in VFB
       url: http://www.virtualflybrain.org/site/stacks/index.htm?id=FBbt_00003651
-    user: http://www.virtualflybrain.org/
-  - description: VFB uses FBbt to annotate brain images
-    example:
     - description: genes expressed in ring neuron R2 in VFB
       url: http://www.virtualflybrain.org/do/gene_list.html?action=geneex&id=FBbt:00003651
     user: http://www.virtualflybrain.org/
   - description: Flybase uses FBbt for expression and phenotype data annotation in
       Drosophila
-    example:
+    examples:
     - description: alleles, constructs and insertions annotated to neuron in FlyBase
       url: http://flybase.org/cgi-bin/cvreport.html?rel=is_a&id=FBbt:00005106
     user: http://flybase.org
@@ -2098,7 +2125,7 @@ ontologies:
   tracker: https://github.com/FlyBase/flybase-controlled-vocabulary/issues
   usages:
   - description: FlyBase uses FBcv for phenotype data annotation in Drosophila
-    example:
+    examples:
     - description: alleles and constructs annotated to bang sensitive in FlyBase
       url: http://flybase.org/cgi-bin/cvreport.html?rel=is_a&id=FBcv:0000391
     user: http://flybase.org
@@ -2346,7 +2373,7 @@ ontologies:
   tracker: https://github.com/pombase/fypo/issues
   usages:
   - description: Pombase uses fypo for phenotype data annotation in fission yeast
-    example:
+    examples:
     - description: genotypes annotated to abnormal mitotic cell cycle in fission yeast
       url: https://www.pombase.org/term/FYPO:0000059
     user: https://www.pombase.org
@@ -2550,17 +2577,26 @@ ontologies:
       of many experimental variables available in EBI databases, and for external
       projects such as the NHGRI GWAS catalogue. It combines parts of several biological
       ontologies, such as anatomy, disease and chemical compounds.
-    example: https://www.ebi.ac.uk/ols/ontologies/efo/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+    examples:
+    - description: Population category defined using ancestry informative markers
+        (AIMs) based on genetic/genomic data
+      url: https://www.ebi.ac.uk/ols/ontologies/efo/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
     user: http://www.ebi.ac.uk/efo
   - description: The Genomic Epidemiology Ontology (GenEpiO) covers vocabulary necessary
       to identify, document and research foodborne pathogens and associated outbreaks.
-    example: https://www.ebi.ac.uk/ols/ontologies/genepio/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+    examples:
+    - description: Population category defined using ancestry informative markers
+        (AIMs) based on genetic/genomic data
+      url: https://www.ebi.ac.uk/ols/ontologies/genepio/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
     user: https://genepio.org/
   - description: FoodOn (http://foodon.org) is a consortium-driven project to build
       a comprehensive and easily accessible global farm-to-fork ontology about food,
       that accurately and consistently describes foods commonly known in cultures
       from around the world.
-    example: https://www.ebi.ac.uk/ols/ontologies/foodon/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
+    examples:
+    - description: Population category defined using ancestry informative markers
+        (AIMs) based on genetic/genomic data
+      url: https://www.ebi.ac.uk/ols/ontologies/foodon/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FHANCESTRO_0004&viewMode=All&siblings=false
     user: http://foodon.org
 - activity_status: active
   build:
@@ -2608,9 +2644,9 @@ ontologies:
   id: hom
   layout: ontology_detail
   license:
-    label: CC-BY
-    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
-    url: http://creativecommons.org/licenses/by/3.0/
+    label: CC0
+    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/cc-zero.png
+    url: https://creativecommons.org/publicdomain/zero/1.0/
   ontology_purl: http://purl.obolibrary.org/obo/hom.owl
   products:
   - id: hom.owl
@@ -2635,6 +2671,7 @@ ontologies:
     url: http://creativecommons.org/licenses/by/3.0/
   ontology_purl: http://purl.obolibrary.org/obo/hsapdv.owl
   page: https://github.com/obophenotype/developmental-stage-ontologies
+  preferredPrefix: HsapDv
   products:
   - id: hsapdv.owl
     ontology_purl: http://purl.obolibrary.org/obo/hsapdv.owl
@@ -3205,6 +3242,7 @@ ontologies:
     url: http://creativecommons.org/licenses/by/3.0/
   ontology_purl: http://purl.obolibrary.org/obo/mmusdv.owl
   page: https://github.com/obophenotype/developmental-stage-ontologies
+  preferredPrefix: MmusDv
   products:
   - id: mmusdv.owl
     ontology_purl: http://purl.obolibrary.org/obo/mmusdv.owl
@@ -3299,8 +3337,15 @@ ontologies:
   usages:
   - description: Mondo is used by the Monarch Initiative for disease annotations.
     examples:
-    - url: https://monarchinitiative.org/phenotype/HP:0001300#diseases
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+    - description: 'Parkinsonism: Characteristic neurologic anomaly resulting form
+        degeneration of dopamine-generating cells in the substantia nigra, a region
+        of the midbrain, characterized clinically by shaking, rigidity, slowness of
+        movement and difficulty with walking and gait.'
+      url: https://monarchinitiative.org/phenotype/HP:0001300#disease
+    publications:
+    - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      title: 'The Monarch Initiative: an integrative data and analytic platform connecting
+        phenotypes to genotypes across species '
     type: annotation
     user: https://monarchinitiative.org/
 - activity_status: active
@@ -3459,10 +3504,50 @@ ontologies:
   usages:
   - description: MRO is used by the The Immune Epitope Database (IEDB) annotations
     examples:
-    - url: https://www.iedb.org/assay/1357035
-    reference: DOI:10.1093/nar/gky1006
+    - description: 'Epitope ID: 59611 based on reference 1003499'
+      url: https://www.iedb.org/assay/1357035
+    publications:
+    - id: https://doi.org/10.1093/nar/gky1006
+      title: 'The Immune Epitope Database (IEDB): 2018 update'
     type: annotation
     user: https://www.iedb.org/
+- activity_status: active
+  build:
+    method: obo2owl
+    source_url: https://raw.githubusercontent.com/HUPO-PSI/psi-ms-CV/master/psi-ms.obo
+  contact:
+    email: gerhard.mayer@rub.de
+    label: Gerhard Mayer
+  createdWith: http://oboedit.org
+  dependencies:
+  - id: pato
+  - id: uo
+  description: A structured controlled vocabulary for the annotation of experiments
+    concerned with proteomics mass spectrometry.
+  domain: MS experiments
+  homepage: http://www.psidev.info/groups/controlled-vocabularies
+  id: ms
+  integration_server: https://raw.githubusercontent.com/HUPO-PSI/psi-ms-CV/master
+  label: MS
+  layout: ontology_detail
+  license:
+    label: CC-BY
+    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
+    url: https://creativecommons.org/licenses/by/3.0/
+  mailing_list: psidev-ms-vocab@lists.sourceforge.net
+  ontology_purl: http://purl.obolibrary.org/obo/ms.owl
+  page: http://www.psidev.info/groups/controlled-vocabularies
+  products:
+  - id: ms.obo
+    ontology_purl: http://purl.obolibrary.org/obo/ms.obo
+  - id: ms.owl
+    ontology_purl: http://purl.obolibrary.org/obo/ms.owl
+  publications:
+  - id: http://www.ncbi.nlm.nih.gov/pubmed/23482073
+    title: The HUPO proteomics standards initiative- mass spectrometry controlled
+      vocabulary.
+  title: Mass spectrometry ontology
+  tracker: https://github.com/HUPO-PSI/psi-ms-CV/issues
 - activity_status: active
   browsers:
   - label: BioPortal
@@ -3643,7 +3728,8 @@ ontologies:
   tracker: https://github.com/SpeciesFileGroup/nomen/issues
   type: owl:Ontology
   usages:
-  - label: TaxonWorks
+  - description: TaxonWorks is an integrated web-based workbench for taxonomists and
+      biodiversity scientists.
     seeAlso: https://github.com/SpeciesFileGroup/taxonworks
     type: application
     user: https://taxonworks.org
@@ -3926,6 +4012,7 @@ ontologies:
     url: http://creativecommons.org/licenses/by/3.0/
   ontology_purl: http://purl.obolibrary.org/obo/olatdv.owl
   page: https://github.com/obophenotype/developmental-stage-ontologies
+  preferredPrefix: OlatDv
   products:
   - id: olatdv.obo
     ontology_purl: http://purl.obolibrary.org/obo/olatdv.obo
@@ -4097,6 +4184,7 @@ ontologies:
   domain: nutrition, nutritional studies, nutrition professionals
   homepage: https://github.com/enpadasi/Ontology-for-Nutritional-Studies
   id: ons
+  label: Ontology for Nutritional Studies
   layout: ontology_detail
   license:
     label: CC-BY
@@ -4108,7 +4196,7 @@ ontologies:
   - id: ons.owl
     ontology_purl: http://purl.obolibrary.org/obo/ons.owl
     title: ONS latest release
-  title: ONS
+  title: Ontology for Nutritional Studies
   tracker: https://github.com/enpadasi/Ontology-for-Nutritional-Studies/issues
 - activity_status: active
   browsers:
@@ -4322,6 +4410,7 @@ ontologies:
     url: http://creativecommons.org/licenses/by/3.0/
   ontology_purl: http://purl.obolibrary.org/obo/pdumdv.owl
   page: https://github.com/obophenotype/developmental-stage-ontologies
+  preferredPrefix: PdumDv
   products:
   - id: pdumdv.owl
     ontology_purl: http://purl.obolibrary.org/obo/pdumdv.owl
@@ -4671,13 +4760,15 @@ ontologies:
   title: Relation Ontology
   tracker: https://github.com/oborel/obo-relations/issues
   usages:
-  - description: RO is used for annotation extensions in the GO
-    reference: https://doi.org/10.1186/1471-2105-15-155
-    type: annotation
-    user: http://geneontology.org
-  - description: RO is used for GO Causal Activity Models
+  - description: RO is used for annotation extensions in the GO and GO Causal Activity
+      Models.
     examples:
-    - http://model.geneontology.org/56d1143000003402
+    - description: wg_biogenesis_FlyBase
+      url: http://model.geneontology.org/56d1143000003402
+    publications:
+    - id: https://doi.org/10.1186/1471-2105-15-155
+      title: A method for increasing expressivity of Gene Ontology annotations using
+        a compositional approach
     type: annotation
     user: http://geneontology.org
 - activity_status: active
@@ -4853,6 +4944,31 @@ ontologies:
     ontology_purl: http://purl.obolibrary.org/obo/stato.owl
   title: The Statistical Methods Ontology
   tracker: https://github.com/ISA-tools/stato/issues
+- activity_status: active
+  build:
+    method: owl2obo
+    source_url: https://raw.githubusercontent.com/allysonlister/swo/master/release/swo_inferred.owl
+  contact:
+    email: allyson.lister@oerc.ox.ac.uk
+    label: Allyson Lister
+  description: The Software Ontology (SWO) is a resource for describing software tools,
+    their types, tasks, versions, provenance and associated data. It contains detailed
+    information on licensing and formats as well as software applications themselves,
+    mainly (but not limited) to the bioinformatics community.
+  domain: software
+  homepage: https://github.com/allysonlister/swo
+  id: swo
+  layout: ontology_detail
+  license:
+    label: CC BY 4.0
+    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
+    url: https://creativecommons.org/licenses/by/4.0/
+  ontology_purl: http://purl.obolibrary.org/obo/swo.owl
+  products:
+  - id: swo.owl
+    ontology_purl: http://purl.obolibrary.org/obo/swo.owl
+  title: Software ontology
+  tracker: https://github.com/allysonlister/swo/issues
 - activity_status: active
   build:
     infallible: 1
@@ -5191,7 +5307,9 @@ ontologies:
       research consortium named ENCODE, the Encyclopedia Of DNA Elements, in September
       2003, to carry out a project to identify all functional elements in the human
       genome sequence. The ENCODE DCC users Uberon to annotate samples
-    reference: https://doi.org/10.1093/database/bav010
+    publications:
+    - id: https://doi.org/10.1093/database/bav010
+      title: Ontology application and use at the ENCODE DCC
     seeAlso: https://www.biosharing.org/biodbcore-000034
     type: annotation
     user: https://www.encodeproject.org/
@@ -5205,11 +5323,11 @@ ontologies:
   - description: Querying expression and phenotype data
     type: query
     user: https://monarchinitiative.org/
-  - description: Querying for functional annotations relevant to a tissue
+  - description: GO Database is used for querying for functional annotations relevant
+      to a tissue
     examples:
     - description: GO annotations relevant to the uberon class for brain
       url: http://amigo.geneontology.org/amigo/term/UBERON:0000955
-    label: GO Database
     type: query
     user: https://geneontology.org/
   - description: The Phenoscape project is both a major driver of and contributor
@@ -5219,23 +5337,26 @@ ontologies:
       Skeletal Anatomy Ontology (VSAO), also created by the Phenoscape group. Phenoscape
       curators continue to extend the ontology, covering a wide variety of tetrapod
       structures, with an emphasis on the appendicular system.
-    label: Phenoscape
     user: http://phenoscape.org
-  - label: Neuroscience Information Framework
+  - description: Searchable collection of neuroscience data and ontology for neuroscience
     type: Database
-    url: https://neuinfo.org/
-  - label: SciCrunch
+    user: https://neuinfo.org/
+  - description: cooperative data platform to be used by diverse communities in making
+      data more FAIR.
     type: Database
-    url: https://scicrunch.org/
-  - label: SCPortalen
-    reference: https://doi.org/10.1093/nar/gkx949
+    user: https://scicrunch.org/
+  - description: SCPortalen
+    publications:
+    - id: https://doi.org/10.1093/nar/gkx949
+      title: 'SCPortalen: human and mouse single-cell centric database'
     type: Database
-    url: http://single-cell.clst.riken.jp/
+    user: http://single-cell.clst.riken.jp/
   - description: ChEMBL uses Uberon to describe organ/tissue information in assays
-    label: ChEMBL
-    reference: https://doi.org/10.1093/nar/gky1075
+    publications:
+    - id: https://doi.org/10.1093/nar/gky1075
+      title: 'ChEMBL: towards direct deposition of bioassay data'
     type: Database
-    url: https://www.ebi.ac.uk/chembl/
+    user: https://www.ebi.ac.uk/chembl/
   wikidata_template: https://en.wikipedia.org/wiki/Template:Uberon
 - activity_status: active
   build:
@@ -5293,8 +5414,15 @@ ontologies:
   usages:
   - description: uPheno is used by the Monarch Initiative for cross-species inference.
     examples:
-    - url: https://monarchinitiative.org/phenotype/HP:0001300#diseases
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+    - description: Characteristic neurologic anomaly resulting form degeneration of
+        dopamine-generating cells in the substantia nigra, a region of the midbrain,
+        characterized clinically by shaking, rigidity, slowness of movement and difficulty
+        with walking and gait.
+      url: https://monarchinitiative.org/phenotype/HP:0001300#disease
+    publications:
+    - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      title: 'The Monarch Initiative: an integrative data and analytic platform connecting
+        phenotypes to genotypes across species '
     type: analysis
     user: https://monarchinitiative.org/
 - activity_status: active
@@ -5318,6 +5446,28 @@ ontologies:
     ontology_purl: http://purl.obolibrary.org/obo/vo.owl
   title: Vaccine Ontology
   tracker: https://github.com/vaccineontology/VO/issues
+- activity_status: active
+  build:
+    checkout: svn co http://phenotype-ontologies.googlecode.com/svn/trunk/src/ontology/vt
+    method: vcs
+    system: svn
+  contact:
+    email: caripark@iastate.edu
+    label: Carissa Park
+  description: An ontology of traits covering vertebrates
+  homepage: https://github.com/AnimalGenome/vertebrate-trait-ontology
+  id: vt
+  layout: ontology_detail
+  license:
+    label: CC BY 4.0
+    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
+    url: https://creativecommons.org/licenses/by/4.0/
+  ontology_purl: http://purl.obolibrary.org/obo/vt.owl
+  products:
+  - id: vt.owl
+    ontology_purl: http://purl.obolibrary.org/obo/vt.owl
+  title: Vertebrate trait ontology
+  tracker: https://github.com/AnimalGenome/vertebrate-trait-ontology/issues
 - activity_status: active
   contact:
     email: balhoff@renci.org
@@ -5381,8 +5531,11 @@ ontologies:
   - description: WormBase uses WBbt to curate anatomical expression patterns and anatomy
       function annotations, and to allow search and indexing on the WormBase site
     examples:
-    - url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
-    reference: https://academic.oup.com/nar/article/48/D1/D762/5603222
+    - description: Expression for gene daf-16 with WormBase ID WBGene00000912
+      url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
+    publications:
+    - id: https://academic.oup.com/nar/article/48/D1/D762/5603222
+      title: 'WormBase: a modern Model Organism Information Resource'
     type: annotation
     user: https://www.wormbase.org/
 - activity_status: active
@@ -5422,8 +5575,11 @@ ontologies:
   - description: WormBase uses WBls to curate temporal expression patterns, and to
       allow search and indexing on the WormBase site
     examples:
-    - url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
-    reference: https://academic.oup.com/nar/article/48/D1/D762/5603222
+    - description: Expression for daf-16 gene with WormBase ID WBGene00000912.
+      url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
+    publications:
+    - id: https://academic.oup.com/nar/article/48/D1/D762/5603222
+      title: 'WormBase: a modern Model Organism Information Resource'
     type: annotation
     user: https://www.wormbase.org/
 - activity_status: active
@@ -5466,15 +5622,23 @@ ontologies:
   - description: WormBase uses WBPhenotype to curate worm phenotypes, and to allow
       search and indexing on the WormBase site
     examples:
-    - url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=phenotype
-    reference: https://academic.oup.com/nar/article/48/D1/D762/5603222
+    - description: Expression for daf-16 gene with WormBase ID WBGene00000912.
+      url: http://www.wormbase.org/db/get?name=WBGene00000912;class=Gene;widget=expression
+    publications:
+    - id: https://academic.oup.com/nar/article/48/D1/D762/5603222
+      title: 'WormBase: a modern Model Organism Information Resource'
     type: annotation
     user: https://www.wormbase.org/
   - description: Monarch integrates phenotype annotations from sources such as WormBase,
       and allows for querying using the WBPhenotype ontology.
     examples:
-    - url: https://monarchinitiative.org/phenotype/WBPhenotype%3A0000370
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+    - description: 'Egg long: The fertilized oocytes have a greater than standard
+        length measured end to end compared to control.'
+      url: https://monarchinitiative.org/phenotype/WBPhenotype%3A0000370
+    publications:
+    - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      title: 'The Monarch Initiative: an integrative data and analytic platform connecting
+        phenotypes to genotypes across species '
     type: annotation
     user: https://monarchinitiative.org/
 - activity_status: active
@@ -5512,6 +5676,34 @@ ontologies:
       ontologies: expansion, improvements and new applications.'
   title: Experimental condition ontology
   tracker: https://github.com/rat-genome-database/XCO-experimental-condition-ontology/issues
+- activity_status: active
+  build:
+    method: obo2owl
+    source_url: https://raw.githubusercontent.com/HUPO-PSI/mzIdentML/master/cv/XLMOD.obo
+  contact:
+    email: gerhard.mayer@rub.de
+    label: Gerhard Mayer
+  createdWith: http://oboedit.org
+  description: A structured controlled vocabulary for cross-linking reagents used
+    with proteomics mass spectrometry.
+  domain: MS cross-linker reagents
+  homepage: http://www.psidev.info/groups/controlled-vocabularies
+  id: xlmod
+  integration_server: https://raw.githubusercontent.com/HUPO-PSI/mzIdentML/tree/master/cv
+  label: xlmod
+  layout: ontology_detail
+  license:
+    label: CC-BY
+    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
+    url: https://creativecommons.org/licenses/by/3.0/
+  mailing_list: psidev-ms-vocab@lists.sourceforge.net
+  ontology_purl: http://purl.obolibrary.org/obo/xlmod.owl
+  page: http://www.psidev.info/groups/controlled-vocabularies
+  products:
+  - id: xlmod.obo
+    ontology_purl: http://purl.obolibrary.org/obo/xlmod.obo
+  title: HUPO-PSI cross-linking and derivatization reagents controlled vocabulary
+  tracker: https://github.com/HUPO-PSI/mzIdentML/issues
 - activity_status: active
   build:
     checkout: git clone https://github.com/obophenotype/xenopus-phenotype-ontology.git
@@ -5625,30 +5817,15 @@ ontologies:
   - description: Monarch integrates phenotype annotations from sources such as ZFIIN,
       and allows for querying using the ZP ontology.
     examples:
-    - url: https://monarchinitiative.org/phenotype/ZP:0005692
-    reference: https://academic.oup.com/nar/article/45/D1/D712/2605791
+    - description: 'adaxial cell absent, abnormal: Abnormal(ly) absent (of) adaxial
+        cell.'
+      url: https://monarchinitiative.org/phenotype/ZP:0005692
+    publications:
+    - id: https://academic.oup.com/nar/article/45/D1/D712/2605791
+      title: 'The Monarch Initiative: an integrative data and analytic platform connecting
+        phenotypes to genotypes across species'
     type: annotation
     user: https://monarchinitiative.org/
-- activity_status: active
-  contact:
-    email: bgee@sib.swiss
-    github: fbastian
-    label: Frederic Bastian
-  description: An ontology to capture confidence information about annotations.
-  homepage: https://github.com/BgeeDB/confidence-information-ontology
-  id: cio
-  layout: ontology_detail
-  license:
-    label: GNU GPL 3.0
-    url: https://www.gnu.org/licenses/gpl-3.0.en.html
-  ontology_purl: http://purl.obolibrary.org/obo/cio.owl
-  products:
-  - id: cio.owl
-    ontology_purl: http://purl.obolibrary.org/obo/cio.owl
-  - id: cio.obo
-    ontology_purl: http://purl.obolibrary.org/obo/cio.obo
-  title: Confidence Information Ontology
-  tracker: https://github.com/BgeeDB/confidence-information-ontology
 - activity_status: active
   build:
     method: owl2obo
@@ -5832,42 +6009,6 @@ ontologies:
     ontology_purl: http://purl.obolibrary.org/obo/mamo.owl
   title: Mathematical modeling ontology
   tracker: http://sourceforge.net/p/mamo-ontology/tickets/
-- activity_status: active
-  build:
-    method: obo2owl
-    source_url: https://raw.githubusercontent.com/HUPO-PSI/psi-ms-CV/master/psi-ms.obo
-  contact:
-    email: gerhard.mayer@rub.de
-    label: Gerhard Mayer
-  createdWith: http://oboedit.org
-  dependencies:
-  - id: pato
-  - id: uo
-  description: A structured controlled vocabulary for the annotation of experiments
-    concerned with proteomics mass spectrometry.
-  domain: MS experiments
-  homepage: http://www.psidev.info/groups/controlled-vocabularies
-  id: ms
-  integration_server: https://raw.githubusercontent.com/HUPO-PSI/psi-ms-CV/master
-  label: MS
-  layout: ontology_detail
-  license:
-    label: CC-BY
-    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
-    url: https://creativecommons.org/licenses/by/3.0/
-  mailing_list: psidev-ms-vocab@lists.sourceforge.net
-  ontology_purl: http://purl.obolibrary.org/obo/ms.owl
-  page: http://www.psidev.info/groups/controlled-vocabularies
-  products:
-  - id: ms.obo
-    ontology_purl: http://purl.obolibrary.org/obo/ms.obo
-  - id: ms.owl
-    ontology_purl: http://purl.obolibrary.org/obo/ms.owl
-  publications:
-  - id: http://www.ncbi.nlm.nih.gov/pubmed/23482073
-    title: The HUPO proteomics standards initiative- mass spectrometry controlled
-      vocabulary.
-  title: Mass spectrometry ontology
 - activity_status: active
   build:
     insert_ontology_id: true
@@ -5891,30 +6032,6 @@ ontologies:
     ontology_purl: http://purl.obolibrary.org/obo/sbo.owl
   title: Systems Biology Ontology
   tracker: https://sourceforge.net/p/sbo/term-request/
-- activity_status: active
-  build:
-    method: owl2obo
-    source_url: https://raw.githubusercontent.com/allysonlister/swo/master/release/swo_inferred.owl
-  contact:
-    email: allyson.lister@oerc.ox.ac.uk
-    label: Allyson Lister
-  description: The Software Ontology (SWO) is a resource for describing software tools,
-    their types, tasks, versions, provenance and associated data. It contains detailed
-    information on licensing and formats as well as software applications themselves,
-    mainly (but not limited) to the bioinformatics community.
-  domain: software
-  homepage: https://github.com/allysonlister/swo
-  id: swo
-  layout: ontology_detail
-  license:
-    label: CC BY 4.0
-    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
-    url: https://creativecommons.org/licenses/by/4.0/
-  ontology_purl: http://purl.obolibrary.org/obo/swo.owl
-  products:
-  - id: swo.owl
-    ontology_purl: http://purl.obolibrary.org/obo/swo.owl
-  title: Software ontology
 - activity_status: active
   browsers:
   - label: BioPortal
@@ -5937,61 +6054,13 @@ ontologies:
   license:
     label: CC-BY version 3.0
     logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
-    url: http://creativecommons.org/licenses/by/3.0/
+    url: https://creativecommons.org/licenses/by/3.0/
   ontology_purl: http://purl.obolibrary.org/obo/txpo.owl
   products:
   - id: txpo.owl
     ontology_purl: http://purl.obolibrary.org/obo/txpo.owl
   title: Toxic Process Ontology
   tracker: https://github.com/txpo-ontology/TXPO/issues
-- activity_status: active
-  build:
-    checkout: svn co http://phenotype-ontologies.googlecode.com/svn/trunk/src/ontology/vt
-    method: vcs
-    system: svn
-  contact:
-    email: caripark@iastate.edu
-    label: Carissa Park
-  description: An ontology of traits covering vertebrates
-  homepage: https://github.com/AnimalGenome/vertebrate-trait-ontology
-  id: vt
-  layout: ontology_detail
-  license:
-    label: CC BY 4.0
-    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
-    url: https://creativecommons.org/licenses/by/4.0/
-  ontology_purl: http://purl.obolibrary.org/obo/vt.owl
-  products:
-  - id: vt.owl
-    ontology_purl: http://purl.obolibrary.org/obo/vt.owl
-  title: Vertebrate trait ontology
-- activity_status: active
-  build:
-    method: obo2owl
-    source_url: https://raw.githubusercontent.com/HUPO-PSI/mzIdentML/master/cv/XLMOD.obo
-  contact:
-    email: gerhard.mayer@rub.de
-    label: Gerhard Mayer
-  createdWith: http://oboedit.org
-  description: A structured controlled vocabulary for cross-linking reagents used
-    with proteomics mass spectrometry.
-  domain: MS cross-linker reagents
-  homepage: http://www.psidev.info/groups/controlled-vocabularies
-  id: xlmod
-  integration_server: https://raw.githubusercontent.com/HUPO-PSI/mzIdentML/tree/master/cv
-  label: xlmod
-  layout: ontology_detail
-  license:
-    label: CC-BY
-    logo: http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png
-    url: https://creativecommons.org/licenses/by/3.0/
-  mailing_list: psidev-ms-vocab@lists.sourceforge.net
-  ontology_purl: http://purl.obolibrary.org/obo/xlmod.owl
-  page: http://www.psidev.info/groups/controlled-vocabularies
-  products:
-  - id: xlmod.obo
-    ontology_purl: http://purl.obolibrary.org/obo/xlmod.obo
-  title: HUPO-PSI cross-linking and derivatization reagents controlled vocabulary
 - activity_status: active
   build:
     infallible: 1
diff --git a/util/schema/registry_schema.json b/util/schema/registry_schema.json
index 54f09e2dc..4f7b8595a 100644
--- a/util/schema/registry_schema.json
+++ b/util/schema/registry_schema.json
@@ -415,7 +415,60 @@
 			"suggest": false
 		},
 		"usages": {
-			"suggest": false
+			"suggest": false,
+      			"level": "error",
+      			"description": "Information on usage of particular ontology.",
+			"type": "array",
+			"items": {
+        			"type": "object",
+				"additionalProperties" : false,
+        			"properties": {
+					"user": {
+          			      		"type": "string",
+          					"format": "uri"
+       				 	},
+					"type": { "type": "string" },
+					"description": {"type":"string"},
+					"seeAlso": {
+                                                "description": "secondary link to the user, such as a FAIR Sharing entry",
+						"type": "string", 
+						"format": "uri" 
+						},
+        				"examples": {
+						"description": "specific page showing how the ontology is used by that user/resource",
+						"type": "array",
+						"items": {
+          						"type": "object",
+      							"additionalProperties" : false,
+          						"properties": {
+          							"url": {
+            								"type": "string",
+            								"format": "uri"
+          							},
+          							"description": {"type": "string"}
+       							},
+         						"required": ["url", "description"]
+						}
+        				},
+					"publications": {
+						"description": "how the user uses the ontology, not specific examples of use",
+						"type": "array",
+						"items": {
+							"type": "object",
+							"additionalProperties" : false,
+							"properties": {
+								"id": { 
+									"type": "string",
+									"format": "uri"
+								},
+								"title": {"type": "string"}
+							},
+							"required": ["id", "title"]
+						}
+					}  
+      				},
+      				"required": ["user", "description"]
+			}
 		},
 		"used_by": {
 			"suggest": false
@@ -438,4 +491,3 @@
 				 "title", "tracker"],
 	"level": "error"
 }
-
diff --git a/util/validate-metadata.py b/util/validate-metadata.py
index a0f74806e..0e60754fb 100755
--- a/util/validate-metadata.py
+++ b/util/validate-metadata.py
@@ -79,7 +79,7 @@ def get_schema():
     with open(file, 'r') as s:
       schema = json.load(s)
   except Exception as e:
-    print('Unable to load %s: %s' % (f, str(e)))
+    print('Unable to load %s: %s' % (file, str(e)))
   return schema
 
 

Implement schema for usages
Issue #1179 asks to add usage information to the ontology detail pages. Before we can do that, we need to standardize that information. #1008 points out that there are different formats in the registry right now. The current schema just allows the `usages` key without any constraint:

https://github.com/OBOFoundry/OBOFoundry.github.io/blob/master/util/schema/registry_schema.json#L417

So the steps are:

- [ ] implement a JSON Schema for usages based on @beckyjackson's suggestion in #1008 
- [ ] update all registry entries to conform to the new schema
- [ ] update [ontology_detail.html](https://github.com/OBOFoundry/OBOFoundry.github.io/blob/master/_layouts/ontology_detail.html) layout to add the usages #1179 
