diff options
author | Sam | 2013-10-30 19:53:09 -0500 |
---|---|---|
committer | Sam | 2013-10-30 19:53:09 -0500 |
commit | 74d803b0de60edf324b1a6ce589d12a055ef312b (patch) | |
tree | f14022873a7f898e7b9258b01a0ac1a9c30a2cdf /wqflask/wqflask | |
parent | de7abc1d2ac9fef87796baa7330cbaaaadbbec2a (diff) | |
download | genenetwork2-74d803b0de60edf324b1a6ce589d12a055ef312b.tar.gz |
More work on collections
Diffstat (limited to 'wqflask/wqflask')
-rw-r--r-- | wqflask/wqflask/collect.py | 36 | ||||
-rw-r--r-- | wqflask/wqflask/do_search.py | 120 | ||||
-rw-r--r-- | wqflask/wqflask/model.py | 12 | ||||
-rw-r--r-- | wqflask/wqflask/static/packages/bootstrap/css/docs.css | 16 | ||||
-rw-r--r-- | wqflask/wqflask/templates/admin/ind_user_manager.html | 6 | ||||
-rw-r--r-- | wqflask/wqflask/templates/collections/list.html | 50 | ||||
-rw-r--r-- | wqflask/wqflask/templates/collections/view.html | 105 |
7 files changed, 206 insertions, 139 deletions
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 @@ <td>Confirmed</td> {% if user.confirmed_at %} - <td>{{ timeago(user.confirmed_at) }}</td> + <td>{{ timeago(user.confirmed_at + "Z") }}</td> {% else %} <td><span class="label label-warning">Unconfirmed</span></td> {% endif %} @@ -55,7 +55,7 @@ <tr> <td>Most recent login</td> {% if user.most_recent_login %} - <td>{{ timeago(user.most_recent_login.timestamp) }} from {{ user.most_recent_login.ip_address }}</td> + <td>{{ timeago(user.most_recent_login.timestamp.isoformat() + "Z") }} from {{ user.most_recent_login.ip_address }}</td> {% else %} <td><span class="label label-warning">Never</span></td> {% endif %} @@ -86,5 +86,5 @@ <script> $('body').timeago(); </script> - + {% 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 %} +<!-- Start of body --> + {{ header("Your Collections", + 'You have {}.'.format(numify(user_collections|count, "collection", "collections"))) }} + + <div class="container"> + <div class="page-header"> + <h1>Collections owned by {{ g.user_session.user_ob.full_name }}</h1> + </div> + + <div class="bs-docs-example"> + <table class="table table-hover" id='trait_table'> + <thead> + <tr> + <th>Name</th> + <th>Created</th> + <th>Last Changed</th> + <th># Records</th> + </tr> + </thead> + + <tbody> + {% for uc in user_collections %} + <tr> + <td><a href="{{ url_for('view_collection', uc_id=uc.id) }}">{{ uc.name }}</a></td> + <td>{{ timeago(uc.created_timestamp.isoformat() + "Z") }}</td> + <td>{{ timeago(uc.changed_timestamp.isoformat() + "Z") }}</td> + <td>{{ uc.num_members }}</td> + </tr> + {% endfor %} + </tbody> + </table> + + </div> + </div> + +<!-- End of body --> + +{% endblock %} + +{% block js %} + + <script type="text/javascript" src="/static/packages/smart-time-ago/lib/timeago.js"></script> + <script> + $('body').timeago(); + </script> + +{% 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 %} <!-- Start of body --> {{ header(uc.name, - 'This collection has {}.'.format(numify(results|count, "record", "records"))) }} + 'This collection has {}.'.format(numify(trait_obs|count, "record", "records"))) }} - <div class="bs-docs-example"> - <table class="table table-hover" id='trait_table'> - <thead> - <tr> - <th>Dataset</th> - <th>Traid ID</th> - <th>Symbol</th> - <th>Description</th> - <th>Location</th> - <th>Mean</th> - <th>N</th> - <th>Max LRS</th> - <th>Max LRS Location</th> - </tr> - </thead> + <div class="container"> + <div class="page-header"> + <h1>Your Collection</h1> + </div> - <tbody> - {% for this_trait in trait_obs %} - <TR id="trait:{{ this_trait.name }}:{{ this_trait.dataset.name }}"> - <TD> - <INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" - VALUE="{{ data_hmac('{}:{}'.format(this_trait.name, this_trait.dataset.name)) }}"> - </TD> - <TD> - <a href="{{ url_for('show_trait_page', - trait_id = this_trait.name, - dataset = this_trait.dataset.name - )}}"> - {{ this_trait.name }} - </a> - </TD> - {% if this_trait.dataset.type == 'ProbeSet' %} - <TD>{{ this_trait.symbol }}</TD> - <TD>{{ this_trait.description_display }}</TD> - <TD>{{ this_trait.location_repr }}</TD> - <TD>{{ this_trait.mean }}</TD> - <TD>{{ this_trait.LRS_score_repr }}</TD> - <TD>{{ this_trait.LRS_location_repr }}</TD> - {% elif this_trait.dataset.type == 'Publish' %} - <TD>{{ this_trait.description_display }}</TD> - <TD>{{ this_trait.authors }}</TD> + <div class="bs-docs-example"> + <table class="table table-hover" id='trait_table'> + <thead> + <tr> + <th></th> + <th>Record</th> + <th>Description</th> + <th>Location</th> + <th>Mean</th> + <th>Max LRS</th> + <th>Max LRS Location</th> + </tr> + </thead> + + <tbody> + {% for this_trait in trait_obs %} + <TR id="trait:{{ this_trait.name }}:{{ this_trait.dataset.name }}"> <TD> - <a href="{{ this_trait.pubmed_link }}"> - {{ this_trait.pubmed_text }} + <INPUT TYPE="checkbox" NAME="searchResult" class="checkbox trait_checkbox" + VALUE="{{ data_hmac('{}:{}'.format(this_trait.name, this_trait.dataset.name)) }}"> + </TD> + <TD> + <a href="{{ url_for('show_trait_page', + trait_id = this_trait.name, + dataset = this_trait.dataset.name + )}}"> + {{ this_trait.name }} </a> </TD> + + <TD>{{ this_trait.description_display }}</TD> + <TD>{{ this_trait.location_repr }}</TD> + <TD>{{ this_trait.mean }}</TD> <TD>{{ this_trait.LRS_score_repr }}</TD> <TD>{{ this_trait.LRS_location_repr }}</TD> - {% elif this_trait.dataset.type == 'Geno' %} - <TD>{{ this_trait.location_repr }}</TD> - {% endif %} - </TR> - {% endfor %} - </tbody> - </table> + </TR> + {% endfor %} + </tbody> + + </table> - <br /> + <br /> - <button class="btn" id="select_all"><i class="icon-ok"></i> Select All</button> - <button class="btn" id="deselect_all"><i class="icon-remove"></i> Deselect All</button> - <button class="btn" id="invert"><i class="icon-resize-vertical"></i> Invert</button> - <button class="btn" id="add"><i class="icon-plus-sign"></i> Add</button> - <button class="btn btn-primary pull-right"><i class="icon-download icon-white"></i> Download Table</button> -</div> + <button class="btn" id="select_all"><i class="icon-ok"></i> Select All</button> + <button class="btn" id="deselect_all"><i class="icon-remove"></i> Deselect All</button> + <button class="btn" id="invert"><i class="icon-resize-vertical"></i> Invert</button> + <button class="btn" id="add"><i class="icon-plus-sign"></i> Add</button> + <button class="btn btn-primary pull-right"><i class="icon-download icon-white"></i> Download Table</button> + </div> + </div> <!-- End of body --> |