From 6fc0b92ad14bfbc8c752b7730f70c6b22294f667 Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Fri, 25 Oct 2013 18:16:54 -0500
Subject: Began working on color coding bar chart by extra attributes
---
wqflask/base/data_set.py | 1 +
wqflask/base/trait.py | 6 ++++--
2 files changed, 5 insertions(+), 2 deletions(-)
(limited to 'wqflask/base')
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index f25e7974..cd8c1ac1 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -224,6 +224,7 @@ class DatasetGroup(object):
"""
def __init__(self, dataset):
"""This sets self.group and self.group_id"""
+ print("dataset name:", dataset.name)
self.name, self.id = g.db.execute(dataset.query_for_group).fetchone()
if self.name == 'BXD300':
self.name = "BXD"
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index 6a64eeaf..77e451a1 100755
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -382,6 +382,7 @@ class GeneralTrait(object):
#trait_qtl = self.cursor.fetchone()
if trait_qtl:
self.locus, self.lrs, self.pvalue, self.mean = trait_qtl
+ print("self.locus:", self.locus)
if self.locus:
query = """
select Geno.Chr, Geno.Mb from Geno, Species
@@ -390,8 +391,9 @@ class GeneralTrait(object):
Geno.SpeciesId = Species.Id
""".format(self.dataset.group.species, self.locus)
result = g.db.execute(query).fetchone()
- self.locus_chr = result[0]
- self.locus_mb = result[1]
+ if result:
+ self.locus_chr = result[0]
+ self.locus_mb = result[1]
else:
self.locus = self.locus_chr = self.locus_mb = self.lrs = self.pvalue = self.mean = ""
--
cgit v1.2.3
From 74d803b0de60edf324b1a6ce589d12a055ef312b Mon Sep 17 00:00:00 2001
From: Sam
Date: Wed, 30 Oct 2013 19:53:09 -0500
Subject: More work on collections
---
wqflask/base/trait.py | 37 ++++---
wqflask/wqflask/collect.py | 36 ++++++-
wqflask/wqflask/do_search.py | 120 ++++++++++-----------
wqflask/wqflask/model.py | 12 ++-
.../wqflask/static/packages/bootstrap/css/docs.css | 16 ---
.../wqflask/templates/admin/ind_user_manager.html | 6 +-
wqflask/wqflask/templates/collections/list.html | 50 +++++++++
wqflask/wqflask/templates/collections/view.html | 105 +++++++++---------
8 files changed, 227 insertions(+), 155 deletions(-)
create mode 100644 wqflask/wqflask/templates/collections/list.html
(limited to 'wqflask/base')
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index 6a64eeaf..aea1f9a9 100755
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -33,6 +33,7 @@ class GeneralTrait(object):
assert bool(kw.get('dataset')) != bool(kw.get('dataset_name')), "Needs dataset ob. or name";
if kw.get('dataset_name'):
self.dataset = create_dataset(kw.get('dataset_name'))
+ print(" in GeneralTrait created dataset:", self.dataset)
else:
self.dataset = kw.get('dataset')
self.name = kw.get('name') # Trait ID, ProbeSet ID, Published ID, etc.
@@ -41,14 +42,14 @@ class GeneralTrait(object):
self.haveinfo = kw.get('haveinfo', False)
self.sequence = kw.get('sequence') # Blat sequence, available for ProbeSet
self.data = kw.get('data', {})
-
+
# Sets defaultst
self.locus = None
self.lrs = None
self.pvalue = None
self.mean = None
self.num_overlap = None
-
+
if kw.get('fullname'):
name2 = value.split("::")
@@ -57,13 +58,17 @@ class GeneralTrait(object):
# self.cellid is set to None above
elif len(name2) == 3:
self.dataset, self.name, self.cellid = name2
-
+
# Todo: These two lines are necessary most of the time, but perhaps not all of the time
# So we could add a simple if statement to short-circuit this if necessary
self.retrieve_info(get_qtl_info=get_qtl_info)
self.retrieve_sample_data()
-
+ def get_info(self):
+ """For lots of traits just use get_trait_info in dataset instead...that will be way
+ more efficient"""
+ self.dataset.get_trait_info([self],
+ webqtlDatabaseFunction.retrieve_species(self.dataset.group.name))
def get_name(self):
stringy = ""
@@ -77,20 +82,20 @@ class GeneralTrait(object):
def get_given_name(self):
- """
+ """
when user enter a trait or GN generate a trait, user want show the name
not the name that generated by GN randomly, the two follow function are
used to give the real name and the database. displayName() will show the
database also, getGivenName() just show the name.
For other trait, displayName() as same as getName(), getGivenName() as
same as self.name
-
+
Hongqiang 11/29/07
-
+
"""
stringy = self.name
if self.dataset and self.name:
- desc = self.dataset.get_desc()
+ desc = self.dataset.get_desc()
if desc:
#desc = self.handle_pca(desc)
stringy = desc
@@ -132,7 +137,7 @@ class GeneralTrait(object):
"""
export data according to samplelist
mostly used in calculating correlation
-
+
"""
result = []
for sample in samplelist:
@@ -153,7 +158,7 @@ class GeneralTrait(object):
"""
export informative sample
mostly used in qtl regression
-
+
"""
samples = []
vals = []
@@ -198,9 +203,9 @@ class GeneralTrait(object):
def retrieve_sample_data(self, samplelist=None):
if samplelist == None:
samplelist = []
-
+
#assert self.dataset
-
+
#if self.cellid:
# #Probe Data
# query = '''
@@ -223,7 +228,7 @@ class GeneralTrait(object):
# Order BY
# Strain.Name
# ''' % (self.cellid, self.name, self.dataset.name)
- #
+ #
#else:
results = self.dataset.retrieve_sample_data(self.name)
@@ -330,7 +335,7 @@ class GeneralTrait(object):
self.confidential = 1
self.homologeneid = None
-
+
#print("self.geneid is:", self.geneid)
#print(" type:", type(self.geneid))
#print("self.dataset.group.name is:", self.dataset.group.name)
@@ -394,8 +399,8 @@ class GeneralTrait(object):
self.locus_mb = result[1]
else:
self.locus = self.locus_chr = self.locus_mb = self.lrs = self.pvalue = self.mean = ""
-
-
+
+
if self.dataset.type == 'Publish':
trait_qtl = g.db.execute("""
SELECT
diff --git a/wqflask/wqflask/collect.py b/wqflask/wqflask/collect.py
index 39a63a1f..ef7b37df 100644
--- a/wqflask/wqflask/collect.py
+++ b/wqflask/wqflask/collect.py
@@ -40,6 +40,7 @@ from utility import Bunch, Struct
from wqflask import user_manager
+from base import trait
@@ -116,4 +117,37 @@ def create_new():
db_session.add(uc)
db_session.commit()
- return "Created: " + uc.name
+ print("Created: " + uc.name)
+ return redirect(url_for('view_collection', uc_id=uc.id))
+
+@app.route("/collections/list")
+def list_collections():
+ user_collections = g.user_session.user_ob.user_collections
+ return render_template("collections/list.html",
+ user_collections = user_collections,
+ )
+
+
+
+@app.route("/collections/view")
+def view_collection():
+ params = request.args
+ uc_id = params['uc_id']
+ uc = model.UserCollection.query.get(uc_id)
+ traits = json.loads(uc.members)
+
+ print("in view_collection traits are:", traits)
+
+ trait_obs = []
+
+ for atrait in traits:
+ name, dataset_name = atrait.split(':')
+
+ trait_ob = trait.GeneralTrait(name=name, dataset_name=dataset_name)
+ trait_ob.get_info()
+ trait_obs.append(trait_ob)
+
+ return render_template("collections/view.html",
+ trait_obs=trait_obs,
+ uc = uc,
+ )
diff --git a/wqflask/wqflask/do_search.py b/wqflask/wqflask/do_search.py
index 5eb09aa1..31f96ced 100644
--- a/wqflask/wqflask/do_search.py
+++ b/wqflask/wqflask/do_search.py
@@ -26,12 +26,12 @@ class DoSearch(object):
assert search_operator in (None, "=", "<", ">", "<=", ">="), "Bad search operator"
self.search_operator = search_operator
self.dataset = dataset
-
+
if self.dataset:
print("self.dataset is boo: ", type(self.dataset), pf(self.dataset))
print("self.dataset.group is: ", pf(self.dataset.group))
#Get group information for dataset and the species id
- self.species_id = webqtlDatabaseFunction.retrieve_species_id(self.dataset.group.name)
+ self.species_id = webqtlDatabaseFunction.retrieve_species_id(self.dataset.group.name)
def execute(self, query):
"""Executes query and returns results"""
@@ -44,7 +44,7 @@ class DoSearch(object):
#def escape(self, stringy):
# """Shorter name than self.db_conn.escape_string"""
# return escape(str(stringy))
-
+
def mescape(self, *items):
"""Multiple escape"""
escaped = [escape(item) for item in items]
@@ -63,9 +63,9 @@ class DoSearch(object):
class QuickMrnaAssaySearch(DoSearch):
"""A general search for mRNA assays"""
-
+
DoSearch.search_types['quick_mrna_assay'] = "QuickMrnaAssaySearch"
-
+
base_query = """SELECT ProbeSet.Name as ProbeSet_Name,
ProbeSet.Symbol as ProbeSet_Symbol,
ProbeSet.description as ProbeSet_Description,
@@ -73,9 +73,9 @@ class QuickMrnaAssaySearch(DoSearch):
ProbeSet.Mb as ProbeSet_Mb,
ProbeSet.name_num as ProbeSet_name_num
FROM ProbeSet """
-
+
header_fields = ['',
- 'Record ID',
+ 'Record',
'Symbol',
'Location']
@@ -112,7 +112,7 @@ class MrnaAssaySearch(DoSearch):
FROM ProbeSetXRef, ProbeSet """
header_fields = ['',
- 'Record ID',
+ 'Record',
'Symbol',
'Description',
'Location',
@@ -122,7 +122,7 @@ class MrnaAssaySearch(DoSearch):
def compile_final_query(self, from_clause = '', where_clause = ''):
"""Generates the final query string"""
-
+
from_clause = self.normalize_spaces(from_clause)
query = (self.base_query +
@@ -132,7 +132,7 @@ class MrnaAssaySearch(DoSearch):
and ProbeSetXRef.ProbeSetFreezeId = %s
""" % (escape(from_clause),
where_clause,
- escape(self.dataset.id)))
+ escape(self.dataset.id)))
#print("query is:", pf(query))
@@ -149,9 +149,9 @@ class MrnaAssaySearch(DoSearch):
GenbankId,
UniGeneId,
Probe_Target_Description)
- AGAINST ('%s' IN BOOLEAN MODE))
+ AGAINST ('%s' IN BOOLEAN MODE))
and ProbeSet.Id = ProbeSetXRef.ProbeSetId
- and ProbeSetXRef.ProbeSetFreezeId = %s
+ and ProbeSetXRef.ProbeSetFreezeId = %s
""" % (escape(self.search_term[0]),
escape(str(self.dataset.id)))
@@ -159,7 +159,7 @@ class MrnaAssaySearch(DoSearch):
return self.execute(query)
-
+
class PhenotypeSearch(DoSearch):
"""A search within a phenotype dataset"""
@@ -181,9 +181,9 @@ class PhenotypeSearch(DoSearch):
'Publication.Title',
'Publication.Authors',
'PublishXRef.Id')
-
+
header_fields = ['',
- 'Record ID',
+ 'Record',
'Description',
'Authors',
'Year',
@@ -237,9 +237,9 @@ class PhenotypeSearch(DoSearch):
class QuickPhenotypeSearch(PhenotypeSearch):
"""A search across all phenotype datasets"""
-
+
DoSearch.search_types['quick_phenotype'] = "QuickPhenotypeSearch"
-
+
base_query = """SELECT Species.Name as Species_Name,
PublishFreeze.FullName as Dataset_Name,
PublishFreeze.Name,
@@ -262,8 +262,8 @@ class QuickPhenotypeSearch(PhenotypeSearch):
'Publication.PubMed_ID',
'Publication.Abstract',
'Publication.Title',
- 'Publication.Authors')
-
+ 'Publication.Authors')
+
def compile_final_query(self, where_clause = ''):
"""Generates the final query string"""
@@ -277,7 +277,7 @@ class QuickPhenotypeSearch(PhenotypeSearch):
print("query is:", pf(query))
return query
-
+
def run(self):
"""Generates and runs a search across all phenotype datasets"""
@@ -299,10 +299,10 @@ class GenotypeSearch(DoSearch):
FROM GenoXRef, GenoFreeze, Geno """
search_fields = ('Name', 'Chr')
-
+
header_fields = ['',
- 'Record ID',
- 'Location']
+ 'Record',
+ 'Location']
def get_fields_clause(self):
"""Generate clause for part of the WHERE portion of query"""
@@ -310,7 +310,7 @@ class GenotypeSearch(DoSearch):
# This adds a clause to the query that matches the search term
# against each field in search_fields (above)
fields_clause = []
-
+
if "'" not in self.search_term[0]:
self.search_term = "[[:<:]]" + self.search_term[0] + "[[:>:]]"
@@ -419,13 +419,13 @@ class LrsSearch(MrnaAssaySearch):
"""
DoSearch.search_types['LRS'] = 'LrsSearch'
-
+
def run(self):
-
+
self.search_term = [float(value) for value in self.search_term]
-
+
self.from_clause = ", Geno"
-
+
if self.search_operator == "=":
assert isinstance(self.search_term, (list, tuple))
self.lrs_min, self.lrs_max = self.search_term[:2]
@@ -444,8 +444,8 @@ class LrsSearch(MrnaAssaySearch):
self.sub_clause += """ Geno.Mb > %s and
Geno.Mb < %s and
""" % self.mescape(min(self.mb_low, self.mb_high),
- max(self.mb_low, self.mb_high))
- print("self.sub_clause is:", pf(self.sub_clause))
+ max(self.mb_low, self.mb_high))
+ print("self.sub_clause is:", pf(self.sub_clause))
else:
# Deal with >, <, >=, and <=
self.sub_clause = """ %sXRef.LRS %s %s and """ % self.mescape(self.dataset.type,
@@ -474,20 +474,20 @@ class CisTransLrsSearch(LrsSearch):
print("self.search_term is:", self.search_term)
self.search_term = [float(value) for value in self.search_term]
self.mb_buffer = 5 # default
-
+
self.from_clause = ", Geno "
if self.search_operator == "=":
if len(self.search_term) == 2:
self.lrs_min, self.lrs_max = self.search_term
#[int(value) for value in self.search_term]
-
+
elif len(self.search_term) == 3:
self.lrs_min, self.lrs_max, self.mb_buffer = self.search_term
-
+
else:
SomeError
-
+
self.sub_clause = """ %sXRef.LRS > %s and
%sXRef.LRS < %s and """ % (
escape(self.dataset.type),
@@ -510,12 +510,12 @@ class CisTransLrsSearch(LrsSearch):
%s.Chr = Geno.Chr""" % (
escape(self.dataset.type),
the_operator,
- escape(self.mb_buffer),
+ escape(self.mb_buffer),
escape(self.dataset.type),
escape(self.species_id),
escape(self.dataset.type)
)
-
+
print("where_clause is:", pf(self.where_clause))
self.query = self.compile_final_query(self.from_clause, self.where_clause)
@@ -560,7 +560,7 @@ class TransLrsSearch(CisTransLrsSearch):
(where the area is determined by the mb_buffer that the user can choose). Opposite of cis-eQTL.
"""
-
+
DoSearch.search_types['TRANSLRS'] = "TransLrsSearch"
def run(self):
@@ -573,7 +573,7 @@ class MeanSearch(MrnaAssaySearch):
DoSearch.search_types['MEAN'] = "MeanSearch"
def run(self):
-
+
self.search_term = [float(value) for value in self.search_term]
if self.search_operator == "=":
@@ -599,11 +599,11 @@ class MeanSearch(MrnaAssaySearch):
class RangeSearch(MrnaAssaySearch):
"""Searches for genes with a range of expression varying between two values"""
-
+
DoSearch.search_types['RANGE'] = "RangeSearch"
-
+
def run(self):
-
+
self.search_term = [float(value) for value in self.search_term]
if self.search_operator == "=":
@@ -632,10 +632,10 @@ class RangeSearch(MrnaAssaySearch):
class PositionSearch(DoSearch):
"""Searches for genes/markers located within a specified range on a specified chromosome"""
-
+
for search_key in ('POSITION', 'POS', 'MB'):
- DoSearch.search_types[search_key] = "PositionSearch"
-
+ DoSearch.search_types[search_key] = "PositionSearch"
+
def setup(self):
self.search_term = [float(value) for value in self.search_term]
self.chr, self.mb_min, self.mb_max = self.search_term[:3]
@@ -646,24 +646,24 @@ class PositionSearch(DoSearch):
self.dataset.type,
min(self.mb_min, self.mb_max),
self.dataset.type,
- max(self.mb_min, self.mb_max))
-
+ max(self.mb_min, self.mb_max))
+
def real_run(self):
self.query = self.compile_final_query(where_clause = self.where_clause)
- return self.execute(self.query)
+ return self.execute(self.query)
class MrnaPositionSearch(MrnaAssaySearch, PositionSearch):
"""Searches for genes located within a specified range on a specified chromosome"""
-
+
def run(self):
self.setup()
self.query = self.compile_final_query(where_clause = self.where_clause)
return self.execute(self.query)
-
+
class GenotypePositionSearch(GenotypeSearch, PositionSearch):
"""Searches for genes located within a specified range on a specified chromosome"""
@@ -673,12 +673,12 @@ class GenotypePositionSearch(GenotypeSearch, PositionSearch):
self.query = self.compile_final_query(where_clause = self.where_clause)
return self.execute(self.query)
-
+
class PvalueSearch(MrnaAssaySearch):
"""Searches for traits with a permutationed p-value between low and high"""
-
+
def run(self):
-
+
self.search_term = [float(value) for value in self.search_term]
if self.search_operator == "=":
@@ -703,19 +703,19 @@ class PvalueSearch(MrnaAssaySearch):
self.query = self.compile_final_query(where_clause = self.where_clause)
return self.execute(self.query)
-
+
class AuthorSearch(PhenotypeSearch):
"""Searches for phenotype traits with specified author(s)"""
-
- DoSearch.search_types["NAME"] = "AuthorSearch"
-
+
+ DoSearch.search_types["NAME"] = "AuthorSearch"
+
def run(self):
self.where_clause = """ Publication.Authors REGEXP "[[:<:]]%s[[:>:]]" and
""" % (self.search_term[0])
-
+
self.query = self.compile_final_query(where_clause = self.where_clause)
-
+
return self.execute(self.query)
@@ -741,7 +741,7 @@ if __name__ == "__main__":
dataset_name = "HC_M2_0606_P"
dataset = create_dataset(db_conn, dataset_name)
-
+
#cursor.execute("""
# SELECT ProbeSet.Name as TNAME, 0 as thistable,
# ProbeSetXRef.Mean as TMEAN, ProbeSetXRef.LRS as TLRS,
@@ -769,4 +769,4 @@ if __name__ == "__main__":
#results = GenotypeSearch("rs13475699", dataset, cursor, db_conn).run()
#results = GoSearch("0045202", dataset, cursor, db_conn).run()
- print("results are:", pf(results))
\ No newline at end of file
+ print("results are:", pf(results))
diff --git a/wqflask/wqflask/model.py b/wqflask/wqflask/model.py
index c1ad0a78..cf9e58e1 100644
--- a/wqflask/wqflask/model.py
+++ b/wqflask/wqflask/model.py
@@ -10,7 +10,8 @@ from flask.ext.sqlalchemy import SQLAlchemy
from wqflask import app
-from sqlalchemy import Column, Integer, String, Table, ForeignKey, Unicode, Boolean, DateTime, Text
+from sqlalchemy import (Column, Integer, String, Table, ForeignKey, Unicode, Boolean, DateTime,
+ Text, Index)
from sqlalchemy.orm import relationship, backref
from wqflask.database import Base, init_db
@@ -98,10 +99,17 @@ class UserCollection(Base):
__tablename__ = "user_collection"
id = Column(Unicode(36), primary_key=True, default=lambda: unicode(uuid.uuid4()))
user = Column(Unicode(36), ForeignKey('user.id'))
- name = Column(Text)
+
+ # I'd prefer this to not have a length, but for the index below it needs one
+ name = Column(Unicode(50))
created_timestamp = Column(DateTime(), default=lambda: datetime.datetime.utcnow())
changed_timestamp = Column(DateTime(), default=lambda: datetime.datetime.utcnow())
members = Column(Text) # We're going to store them as a json list
# This index ensures a user doesn't have more than one collection with the same name
__table_args__ = (Index('usercollection_index', "user", "name"), )
+
+ @property
+ def num_members(self):
+ print("members are:", json.loads(self.members))
+ return len(json.loads(self.members))
diff --git a/wqflask/wqflask/static/packages/bootstrap/css/docs.css b/wqflask/wqflask/static/packages/bootstrap/css/docs.css
index 7efd72cd..967989a7 100644
--- a/wqflask/wqflask/static/packages/bootstrap/css/docs.css
+++ b/wqflask/wqflask/static/packages/bootstrap/css/docs.css
@@ -558,22 +558,6 @@ h2 + .row {
border-radius: 4px;
}
-/* Echo out a label for the example */
-.bs-docs-example:after {
- content: "Results";
- position: absolute;
- top: -1px;
- left: -1px;
- padding: 3px 7px;
- font-size: 12px;
- font-weight: bold;
- background-color: #f5f5f5;
- border: 1px solid #ddd;
- color: #9da0a4;
- -webkit-border-radius: 4px 0 4px 0;
- -moz-border-radius: 4px 0 4px 0;
- border-radius: 4px 0 4px 0;
-}
/* Remove spacing between an example and it's code */
.bs-docs-example + .prettyprint {
diff --git a/wqflask/wqflask/templates/admin/ind_user_manager.html b/wqflask/wqflask/templates/admin/ind_user_manager.html
index f99243ac..03a86e63 100644
--- a/wqflask/wqflask/templates/admin/ind_user_manager.html
+++ b/wqflask/wqflask/templates/admin/ind_user_manager.html
@@ -46,7 +46,7 @@
Confirmed |
{% if user.confirmed_at %}
- {{ timeago(user.confirmed_at) }} |
+ {{ timeago(user.confirmed_at + "Z") }} |
{% else %}
Unconfirmed |
{% endif %}
@@ -55,7 +55,7 @@
Most recent login |
{% if user.most_recent_login %}
- {{ timeago(user.most_recent_login.timestamp) }} from {{ user.most_recent_login.ip_address }} |
+ {{ timeago(user.most_recent_login.timestamp.isoformat() + "Z") }} from {{ user.most_recent_login.ip_address }} |
{% else %}
Never |
{% endif %}
@@ -86,5 +86,5 @@
-
+
{% endblock %}
diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html
new file mode 100644
index 00000000..111d761f
--- /dev/null
+++ b/wqflask/wqflask/templates/collections/list.html
@@ -0,0 +1,50 @@
+{% extends "base.html" %}
+{% block title %}Your Collections{% endblock %}
+{% block content %}
+
+ {{ header("Your Collections",
+ 'You have {}.'.format(numify(user_collections|count, "collection", "collections"))) }}
+
+
+
+
+
+
+
+
+ Name |
+ Created |
+ Last Changed |
+ # Records |
+
+
+
+
+ {% for uc in user_collections %}
+
+ {{ uc.name }} |
+ {{ timeago(uc.created_timestamp.isoformat() + "Z") }} |
+ {{ timeago(uc.changed_timestamp.isoformat() + "Z") }} |
+ {{ uc.num_members }} |
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+{% endblock %}
+
+{% block js %}
+
+
+
+
+{% endblock %}
diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html
index 3fa83d4a..0ab004d9 100644
--- a/wqflask/wqflask/templates/collections/view.html
+++ b/wqflask/wqflask/templates/collections/view.html
@@ -3,73 +3,64 @@
{% block content %}
{{ header(uc.name,
- 'This collection has {}.'.format(numify(results|count, "record", "records"))) }}
+ 'This collection has {}.'.format(numify(trait_obs|count, "record", "records"))) }}
-
-
-
-
- Dataset |
- Traid ID |
- Symbol |
- Description |
- Location |
- Mean |
- N |
- Max LRS |
- Max LRS Location |
-
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
--
cgit v1.2.3