about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--wqflask/base/data_set/dataset.py90
-rw-r--r--wqflask/wqflask/correlation/rust_correlation.py4
-rw-r--r--wqflask/wqflask/correlation/show_corr_results.py27
-rw-r--r--wqflask/wqflask/database.py8
-rw-r--r--wqflask/wqflask/db_info.py128
-rw-r--r--wqflask/wqflask/metadata_edits.py9
-rw-r--r--wqflask/wqflask/static/new/css/show_trait.css17
-rw-r--r--wqflask/wqflask/static/new/javascript/dataset_select_menu.js169
-rw-r--r--wqflask/wqflask/static/new/javascript/dataset_select_menu_edit_trait.js253
-rw-r--r--wqflask/wqflask/templates/correlation_page.html4
-rw-r--r--wqflask/wqflask/templates/edit_probeset.html33
-rw-r--r--wqflask/wqflask/templates/search_result_page.html6
-rw-r--r--wqflask/wqflask/templates/show_metadata_details.html186
-rw-r--r--wqflask/wqflask/templates/show_trait.html14
-rw-r--r--wqflask/wqflask/views.py15
16 files changed, 406 insertions, 559 deletions
diff --git a/README.md b/README.md
index 5c587fec..e4a96a13 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,7 @@ env GN2_PROFILE=~/opt/gn-latest SERVER_PORT=5300 \
     GENENETWORK_FILES=~/data/gn2_data/ \
     GN_PROXY_URL="http://localhost:8080"\
     GN3_LOCAL_URL="http://localhost:8081"\
+	SPARQL_ENDPOINT=http://localhost:8892/sparql\
     ./bin/genenetwork2 ./etc/default_settings.py -gunicorn-dev
 ```
 
@@ -182,6 +183,7 @@ env HOME=/home/frederick \
     GN2_PROFILE=~/opt/gn2-latest \
     GN3_DEV_REPO_PATH=~/genenetwork/genenetwork3 \
     SQL_URI="mysql://username:password@host-ip:host-port/db_webqtl" \
+	SPARQL_ENDPOINT=http://localhost:8892/sparql\
     SERVER_PORT=5001 \
     bin/genenetwork2 ../gn2_settings.py \
     -cli python3 -m scripts.profile_corrs \
diff --git a/wqflask/base/data_set/dataset.py b/wqflask/base/data_set/dataset.py
index 69c842ad..dfe09921 100644
--- a/wqflask/base/data_set/dataset.py
+++ b/wqflask/base/data_set/dataset.py
@@ -2,13 +2,15 @@
 
 import math
 import collections
-
+import itertools
 
 from redis import Redis
 
-
+from MySQLdb.cursors import DictCursor
 from base import species
 from utility import chunks
+from gn3.monads import MonadicDict, query_sql
+from pymonad.maybe import Maybe, Nothing
 from .datasetgroup import DatasetGroup
 from wqflask.database import database_connection
 from utility.db_tools import escape, mescape, create_in_clause
@@ -30,7 +32,7 @@ class DataSet:
         self.fullname = None
         self.type = None
         self.data_scale = None  # ZS: For example log2
-        self.accession_id = None
+        self.accession_id = Nothing
 
         self.setup()
 
@@ -47,50 +49,58 @@ class DataSet:
             self.group.get_samplelist(redis_conn)
         self.species = species.TheSpecies(dataset=self)
 
-    def as_dict(self):
-        return {
+    def as_monadic_dict(self):
+        _result = MonadicDict({
             'name': self.name,
             'shortname': self.shortname,
             'fullname': self.fullname,
             'type': self.type,
             'data_scale': self.data_scale,
-            'group': self.group.name,
-            'accession_id': self.accession_id
-        }
-
-    def get_accession_id(self):
-        results = None
-        with database_connection() as conn, conn.cursor() as cursor:
+            'group': self.group.name
+        })
+        _result["accession_id"] = self.accession_id
+        return _result
+
+    def get_accession_id(self) -> Maybe[str]:
+        """Get the accession_id of this dataset depending on the
+        dataset type."""
+        __accession_id_dict = MonadicDict()
+        with database_connection() as conn:
             if self.type == "Publish":
-                cursor.execute(
-                    "SELECT InfoFiles.GN_AccesionId FROM "
-                    "InfoFiles, PublishFreeze, InbredSet "
-                    "WHERE InbredSet.Name = %s AND "
-                    "PublishFreeze.InbredSetId = InbredSet.Id "
-                    "AND InfoFiles.InfoPageName = PublishFreeze.Name "
-                    "AND PublishFreeze.public > 0 AND "
-                    "PublishFreeze.confidentiality < 1 "
-                    "ORDER BY PublishFreeze.CreateTime DESC",
-                    (self.group.name,)
-                )
-                results = cursor.fetchone()
+                __accession_id_dict, = itertools.islice(
+                    query_sql(conn,
+                        ("SELECT InfoFiles.GN_AccesionId AS accession_id FROM "
+                        "InfoFiles, PublishFreeze, InbredSet "
+                        f"WHERE InbredSet.Name = '{conn.escape_string(self.group.name).decode()}' "
+                        "AND PublishFreeze.InbredSetId = InbredSet.Id "
+                        "AND InfoFiles.InfoPageName = PublishFreeze.Name "
+                        "AND PublishFreeze.public > 0 AND "
+                        "PublishFreeze.confidentiality < 1 "
+                        "ORDER BY PublishFreeze.CreateTime DESC")
+                    ), 1)
             elif self.type == "Geno":
-                cursor.execute(
-                    "SELECT InfoFiles.GN_AccesionId FROM "
-                    "InfoFiles, GenoFreeze, InbredSet "
-                    "WHERE InbredSet.Name = %s AND "
-                    "GenoFreeze.InbredSetId = InbredSet.Id "
-                    "AND InfoFiles.InfoPageName = GenoFreeze.ShortName "
-                    "AND GenoFreeze.public > 0 AND "
-                    "GenoFreeze.confidentiality < 1 "
-                    "ORDER BY GenoFreeze.CreateTime DESC",
-                    (self.group.name,)
-                )
-                results = cursor.fetchone()
-
-        if results:
-            return str(results[0])
-        return "None"
+                __accession_id_dict, = itertools.islice(
+                    query_sql(conn,
+                        ("SELECT InfoFiles.GN_AccesionId AS accession_id FROM "
+                        "InfoFiles, GenoFreeze, InbredSet "
+                        f"WHERE InbredSet.Name = '{conn.escape_string(self.group.name).decode()}' AND "
+                        "GenoFreeze.InbredSetId = InbredSet.Id "
+                        "AND InfoFiles.InfoPageName = GenoFreeze.ShortName "
+                        "AND GenoFreeze.public > 0 AND "
+                        "GenoFreeze.confidentiality < 1 "
+                        "ORDER BY GenoFreeze.CreateTime DESC")
+                    ), 1)
+            elif self.type == "ProbeSet":
+                __accession_id_dict, = itertools.islice(
+                    query_sql(conn,
+                        ("SELECT InfoFiles.GN_AccesionId AS accession_id "
+                        f"FROM InfoFiles WHERE InfoFiles.InfoPageName = '{conn.escape_string(self.name).decode()}' "
+                        f"AND InfoFiles.DB_Name = '{conn.escape_string(self.fullname).decode()}' "
+                        f"OR InfoFiles.DB_Name = '{conn.escape_string(self.shortname).decode()}'")
+                    ), 1)
+            else:  # The Value passed is not present
+                raise LookupError
+        return __accession_id_dict["accession_id"]
 
     def retrieve_other_names(self):
         """This method fetches the the dataset names in search_result.
diff --git a/wqflask/wqflask/correlation/rust_correlation.py b/wqflask/wqflask/correlation/rust_correlation.py
index 3245d037..c57171c6 100644
--- a/wqflask/wqflask/correlation/rust_correlation.py
+++ b/wqflask/wqflask/correlation/rust_correlation.py
@@ -244,8 +244,8 @@ def __compute_sample_corr__(
         sample_type=start_vars["corr_samples_group"],
         sample_data= json.loads(start_vars["sample_vals"]),
         all_samples=this_dataset.group.all_samples_ordered(),
-        dataset_samples=this_dataset.group.samplelist)
-    
+        dataset_samples=this_dataset.group.all_samples_ordered())
+
     if not bool(sample_data):
         return {}
 
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index d3e50972..5da8a6b9 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -19,15 +19,9 @@
 # This module is used by GeneNetwork project (www.genenetwork.org)
 
 import json
-import os
-from pathlib import Path
 
 from base.trait import create_trait, jsonable
 from base.data_set import create_dataset
-from base.webqtlConfig import TMPDIR
-
-from wqflask.correlation.pre_computes import fetch_all_cached_metadata
-from wqflask.correlation.pre_computes import cache_new_traits_metadata
 
 from utility import hmac
 from utility.type_checking import get_float, get_int, get_string
@@ -46,16 +40,17 @@ def set_template_vars(start_vars, correlation_data):
                               name=start_vars['trait_id'])
 
     correlation_data['this_trait'] = jsonable(this_trait, this_dataset_ob)
-    correlation_data['this_dataset'] = this_dataset_ob.as_dict()
+    correlation_data['this_dataset'] = this_dataset_ob.as_monadic_dict().data
 
     target_dataset_ob = create_dataset(correlation_data['target_dataset'])
-    correlation_data['target_dataset'] = target_dataset_ob.as_dict()
-    correlation_data['table_json'] = correlation_json_for_table(
-        start_vars,
-        correlation_data,
-        correlation_data['this_trait'],
-        correlation_data['this_dataset'],
-        target_dataset_ob)
+    correlation_data['target_dataset'] = target_dataset_ob.as_monadic_dict().data
+
+    table_json = correlation_json_for_table(correlation_data,
+                                            correlation_data['this_trait'],
+                                            correlation_data['this_dataset'],
+                                            target_dataset_ob)
+
+    correlation_data['table_json'] = table_json
 
     if target_dataset_ob.type == "ProbeSet":
         filter_cols = [7, 6]
@@ -80,12 +75,12 @@ def correlation_json_for_table(start_vars, correlation_data, this_trait, this_da
     Keyword arguments:
     correlation_data -- Correlation results
     this_trait -- Trait being correlated against a dataset, as a dict
-    this_dataset -- Dataset of this_trait, as a dict
+    this_dataset -- Dataset of this_trait, as a monadic dict
     target_dataset_ob - Target dataset, as a Dataset ob
     """
     this_trait = correlation_data['this_trait']
     this_dataset = correlation_data['this_dataset']
-    target_dataset = target_dataset_ob.as_dict()
+    target_dataset = target_dataset_ob.as_monadic_dict().data
 
     corr_results = correlation_data['correlation_results']
     results_list = []
diff --git a/wqflask/wqflask/database.py b/wqflask/wqflask/database.py
index 663e2ebf..d2929488 100644
--- a/wqflask/wqflask/database.py
+++ b/wqflask/wqflask/database.py
@@ -1,6 +1,7 @@
 # Module to initialize sqlalchemy with flask
 import os
 import sys
+from SPARQLWrapper import JSON, SPARQLWrapper
 from typing import Tuple, Protocol, Any, Iterator
 from urllib.parse import urlparse
 import importlib
@@ -60,3 +61,10 @@ def database_connection() -> Iterator[Connection]:
         yield connection
     finally:
         connection.close()
+
+
+def sparql_connection():
+    """Create a sparql objection that is used to query RDF"""
+    return SPARQLWrapper(
+        get_setting("SPARQL_ENDPOINT")
+    )
diff --git a/wqflask/wqflask/db_info.py b/wqflask/wqflask/db_info.py
index 376ce14c..3dff422f 100644
--- a/wqflask/wqflask/db_info.py
+++ b/wqflask/wqflask/db_info.py
@@ -1,11 +1,12 @@
-import http.client
 import urllib.request
 import urllib.error
 import urllib.parse
 import re
 
+from MySQLdb.cursors import DictCursor
 from wqflask.database import database_connection
 
+
 class InfoPage:
     def __init__(self, start_vars):
         self.info = None
@@ -18,39 +19,70 @@ class InfoPage:
         self.get_datasets_list()
 
     def get_info(self, create=False):
-        query_base = ("SELECT InfoPageName, GN_AccesionId, Species.MenuName, Species.TaxonomyId, Tissue.Name, InbredSet.Name, "
-                      "GeneChip.GeneChipName, GeneChip.GeoPlatform, AvgMethod.Name, Datasets.DatasetName, Datasets.GeoSeries, "
-                      "Datasets.PublicationTitle, DatasetStatus.DatasetStatusName, Datasets.Summary, Datasets.AboutCases, "
-                      "Datasets.AboutTissue, Datasets.AboutDataProcessing, Datasets.Acknowledgment, Datasets.ExperimentDesign, "
-                      "Datasets.Contributors, Datasets.Citation, Datasets.Notes, Investigators.FirstName, Investigators.LastName, "
-                      "Investigators.Address, Investigators.City, Investigators.State, Investigators.ZipCode, Investigators.Country, "
-                      "Investigators.Phone, Investigators.Email, Investigators.Url, Organizations.OrganizationName, "
-                      "InvestigatorId, DatasetId, DatasetStatusId, Datasets.AboutPlatform, InfoFileTitle, Specifics "
-                      "FROM InfoFiles "
-                      "LEFT JOIN Species USING (SpeciesId) "
-                      "LEFT JOIN Tissue USING (TissueId) "
-                      "LEFT JOIN InbredSet USING (InbredSetId) "
-                      "LEFT JOIN GeneChip USING (GeneChipId) "
-                      "LEFT JOIN AvgMethod USING (AvgMethodId) "
-                      "LEFT JOIN Datasets USING (DatasetId) "
-                      "LEFT JOIN Investigators USING (InvestigatorId) "
-                      "LEFT JOIN Organizations USING (OrganizationId) "
-                      "LEFT JOIN DatasetStatus USING (DatasetStatusId) WHERE ")
+        query_base = (
+            "SELECT InfoPageName AS info_page_name, "
+            "GN_AccesionId AS accession_id, "
+            "Species.MenuName AS menu_name, "
+            "Species.TaxonomyId AS taxonomy_id, "
+            "Tissue.Name AS tissue_name, "
+            "InbredSet.Name AS group_name, "
+            "GeneChip.GeneChipName AS gene_chip_name, "
+            "GeneChip.GeoPlatform AS geo_platform, "
+            "AvgMethod.Name AS avg_method_name, "
+            "Datasets.DatasetName AS dataset_name, "
+            "Datasets.GeoSeries AS geo_series, "
+            "Datasets.PublicationTitle AS publication_title, "
+            "DatasetStatus.DatasetStatusName AS dataset_status_name, "
+            "Datasets.Summary AS dataset_summary, "
+            "Datasets.AboutCases AS about_cases, "
+            "Datasets.AboutTissue AS about_tissue, "
+            "Datasets.AboutDataProcessing AS about_data_processing, "
+            "Datasets.Acknowledgment AS acknowledgement, "
+            "Datasets.ExperimentDesign AS experiment_design, "
+            "Datasets.Contributors AS contributors, "
+            "Datasets.Citation AS citation, "
+            "Datasets.Notes AS notes, "
+            "Investigators.FirstName AS investigator_firstname, "
+            "Investigators.LastName AS investigator_lastname, "
+            "Investigators.Address AS investigator_address, "
+            "Investigators.City AS investigator_city, "
+            "Investigators.State AS investigator_state, "
+            "Investigators.ZipCode AS investigator_zipcode, "
+            "Investigators.Country AS investigator_country, "
+            "Investigators.Phone AS investigator_phone, "
+            "Investigators.Email AS investigator_email, "
+            "Investigators.Url AS investigator_url, "
+            "Organizations.OrganizationName AS organization_name, "
+            "InvestigatorId AS investigator_id, "
+            "DatasetId AS dataset_id, "
+            "DatasetStatusId AS dataset_status_id, "
+            "Datasets.AboutPlatform AS about_platform, "
+            "InfoFileTitle AS info_file_title, "
+            "Specifics AS specifics"
+            "FROM InfoFiles "
+            "LEFT JOIN Species USING (SpeciesId) "
+            "LEFT JOIN Tissue USING (TissueId) "
+            "LEFT JOIN InbredSet USING (InbredSetId) "
+            "LEFT JOIN GeneChip USING (GeneChipId) "
+            "LEFT JOIN AvgMethod USING (AvgMethodId) "
+            "LEFT JOIN Datasets USING (DatasetId) "
+            "LEFT JOIN Investigators USING (InvestigatorId) "
+            "LEFT JOIN Organizations USING (OrganizationId) "
+            "LEFT JOIN DatasetStatus USING (DatasetStatusId) WHERE "
+        )
         if not all([self.gn_accession_id, self.info_page_name]):
             raise ValueError('No correct parameter found')
 
-        results = None
-        with database_connection() as conn, conn.cursor() as cursor:
+        results = {}
+        with database_connection() as conn, conn.cursor(DictCursor) as cursor:
             if self.gn_accession_id:
                 cursor.execute(f"{query_base}GN_AccesionId = %s",
                                (self.gn_accession_id,))
-                results = cursor.fetchone()
             elif self.info_page_name:
                 cursor.execute(f"{query_base}InfoPageName = %s",
                                (self.info_page_name,))
-                results = cursor.fetchone()
-        if results:
-            self.info = process_query_results(results)
+            if (results := cursor.fetchone()):
+                self.info = results
         if ((not results or len(results) < 1)
             and self.info_page_name and create):
             return self.get_info()
@@ -80,49 +112,3 @@ class InfoPage:
                 self.filelist.append([filename, filedate, filesize])
         except Exception as e:
             pass
-
-
-def process_query_results(results):
-    info_ob = {
-        'info_page_name': results[0],
-        'accession_id': results[1],
-        'menu_name': results[2],
-        'taxonomy_id': results[3],
-        'tissue_name': results[4],
-        'group_name': results[5],
-        'gene_chip_name': results[6],
-        'geo_platform': results[7],
-        'avg_method_name': results[8],
-        'dataset_name': results[9],
-        'geo_series': results[10],
-        'publication_title': results[11],
-        'dataset_status_name': results[12],
-        'dataset_summary': results[13],
-        'about_cases': results[14],
-        'about_tissue': results[15],
-        'about_data_processing': results[16],
-        'acknowledgement': results[17],
-        'experiment_design': results[18],
-        'contributors': results[19],
-        'citation': results[20],
-        'notes': results[21],
-        'investigator_firstname': results[22],
-        'investigator_lastname': results[23],
-        'investigator_address': results[24],
-        'investigator_city': results[25],
-        'investigator_state': results[26],
-        'investigator_zipcode': results[27],
-        'investigator_country': results[28],
-        'investigator_phone': results[29],
-        'investigator_email': results[30],
-        'investigator_url': results[31],
-        'organization_name': results[32],
-        'investigator_id': results[33],
-        'dataset_id': results[34],
-        'dataset_status_is': results[35],
-        'about_platform': results[36],
-        'info_file_title': results[37],
-        'specifics': results[38]
-    }
-
-    return info_ob
diff --git a/wqflask/wqflask/metadata_edits.py b/wqflask/wqflask/metadata_edits.py
index 0840d4dd..383316e4 100644
--- a/wqflask/wqflask/metadata_edits.py
+++ b/wqflask/wqflask/metadata_edits.py
@@ -447,6 +447,15 @@ def update_probeset(name: str):
                     json_data=json.dumps(diff_data),
                 ),
             )
+            edited_values = {k: v for (k, v) in diff_data['Probeset'].items() if k not in {"id_", "timestamp", "author"}}
+            changes = []
+            for k in edited_values.keys():
+                changes.append(f"<b><span data-message-id='{k}'></span></b>")
+            message = f"You successfully updated the following entries \
+            at {diff_data['timestamp']}: {', '.join(changes)}"
+            flash(f"You successfully edited: {message}", "success")
+        else:
+            flash("No edits were made!", "warning")
         return redirect(
             f"/datasets/traits/{name}"
             f"?resource-id={request.args.get('resource-id')}"
diff --git a/wqflask/wqflask/static/new/css/show_trait.css b/wqflask/wqflask/static/new/css/show_trait.css
index 3780a8f1..2ce07fec 100644
--- a/wqflask/wqflask/static/new/css/show_trait.css
+++ b/wqflask/wqflask/static/new/css/show_trait.css
@@ -6,6 +6,23 @@ table.dataTable tbody tr.selected {
   background-color: #ffee99;
 }
 
+table.metadata {
+    table-layout: fixed;
+}
+
+table.metadata td:nth-child(1) {
+    width: 10%;
+}
+
+table summary b {
+    cursor: pointer;
+    text-decoration: underline;
+}
+
+table details[open] {
+    width: 80%;
+}
+
 #bar_chart_container {
   overflow-x:scroll;
 }
diff --git a/wqflask/wqflask/static/new/javascript/dataset_select_menu.js b/wqflask/wqflask/static/new/javascript/dataset_select_menu.js
deleted file mode 100644
index 9ad38102..00000000
--- a/wqflask/wqflask/static/new/javascript/dataset_select_menu.js
+++ /dev/null
@@ -1,169 +0,0 @@
-$(function() {
-  var gndata;  // loaded once for all to use
-  process_json = function(data) {
-      populate_species();
-      return apply_default();
-  };
-  $.getJSON(gn_server_url+"int/menu/main.json",
-  function(data) {
-    gndata = data;
-    console.log("***** GOT DATA from GN_SERVER ****");
-    console.log(gndata);
-    populate_species();
-  }).error(function() {
-    console.log("ERROR: GN_SERVER not responding");
-    alert("ERROR: GN_SERVER internal REST API is not responding");
-  });
-
-  var populate_species = function() {
-    var species_list = Object.keys(gndata.menu).map(function(species) {
-      var mitem = gndata.menu[species].menu
-      // console.log("Species menu:",species,mitem)
-      return [species,mitem];
-    });
-    redo_dropdown($('#species'), species_list);
-    return populate_group();
-  };
-  window.populate_species = populate_species;
-
-  var populate_group = function() {
-    var species = $('#species').val();
-    var groups = gndata.groups[species].map(function(item) {
-        console.log("group:",item);
-        return item.slice(1,3);
-    })
-    redo_dropdown($('#group'), groups);
-    return populate_type();
-  };
-  window.populate_group = populate_group;
-
-  var populate_type = function() {
-    var species = $('#species').val();
-    var group = $('#group').val();
-    var type_list = gndata.menu[species].types[group].map(function(item) {
-        return [item,item];
-    });
-
-    redo_dropdown($('#type'), type_list);
-    return populate_dataset();
-  };
-  window.populate_type = populate_type;
-
-  var populate_dataset = function() {
-    var species = $('#species').val();
-    var group = $('#group').val();
-    var type = $('#type').val();
-    var dataset_list = gndata.datasets[species][group][type].map(function(item) {
-        return item.slice(1,3);
-    })
-
-    return redo_dropdown($('#dataset'), dataset_list);
-  };
-  window.populate_dataset = populate_dataset;
-
-  var redo_dropdown = function(dropdown, items) {
-    var item, _i, _len, _results;
-    console.log("in redo:", dropdown, items);
-    dropdown.empty();
-    _results = [];
-    for (_i = 0, _len = items.length; _i < _len; _i++) {
-      item = items[_i];
-      if (item.length > 2){
-        _results.push(dropdown.append($("<option data-id=\""+item[0]+"\" />").val(item[1]).text(item[2])));
-      } else {
-        _results.push(dropdown.append($("<option />").val(item[0]).text(item[1])));
-      }
-    }
-    return _results;
-  };
-  $('#species').change((function(_this) {
-    return function() {
-      return populate_group();
-    };
-  })(this));
-  $('#group').change((function(_this) {
-    return function() {
-      return populate_type();
-    };
-  })(this));
-  $('#type').change((function(_this) {
-    return function() {
-      return populate_dataset();
-    };
-  })(this));
-  open_window = function(url, name) {
-    var options;
-    options = "menubar=1,toolbar=1,location=1,resizable=1,status=1,scrollbars=1,directories=1,width=900";
-    return open(url, name, options).focus();
-  };
-  var group_info = function() {
-    var group, species, url;
-    species = $('#species').val();
-    group = $('#group').val();
-    url = "/" + species + "Cross.html#" + group;
-    return open_window(url, "Group Info");
-  };
-  $('#group_info').click(group_info);
-  var dataset_info = function() {
-    var dataset, url;
-    accession_id = $('#dataset option:selected').data("id");
-    url = "http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&GN_AccessionId=" + accession_id;
-    return open_window(url, "Dataset Info");
-  };
-  $('#dataset_info').click(dataset_info);
-  var make_default = function() {
-    var holder, item, jholder, _i, _len, _ref;
-    alert("The current settings are now your default.")
-    holder = {};
-    _ref = ['species', 'group', 'type', 'dataset'];
-    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-      item = _ref[_i];
-      holder[item] = $("#" + item).val();
-    }
-    jholder = JSON.stringify(holder);
-    return $.cookie('search_defaults', jholder, {
-      expires: 365
-    });
-  };
-  var apply_default = function() {
-    var defaults, item, populate_function, _i, _len, _ref, _results;
-    defaults = $.cookie('search_defaults');
-    if (defaults) {
-      defaults = $.parseJSON(defaults);
-    } else {
-      defaults = {
-        species: "mouse",
-        group: "BXD",
-        type: "Hippocampus mRNA",
-        dataset: "HC_M2_0606_P"
-      };
-    }
-    _ref = [['species', 'group'], ['group', 'type'], ['type', 'dataset'], ['dataset', null]];
-    _results = [];
-    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-      item = _ref[_i];
-      $("#" + item[0]).val(defaults[item[0]]);
-      if (item[1]) {
-        populate_function = "populate_" + item[1];
-        console.log("Calling:", populate_function);
-        _results.push(window[populate_function]());
-      } else {
-        _results.push(void 0);
-      }
-    }
-    return _results;
-  };
-  var check_search_term = function() {
-    var or_search_term, and_search_term;
-    or_search_term = $('#or_search').val();
-    and_search_term = $('#and_search').val();
-    console.log("or_search_term:", or_search_term);
-    console.log("and_search_term:", and_search_term);
-    if (or_search_term === "" && and_search_term === "") {
-      alert("Please enter one or more search terms or search equations.");
-      return false;
-    }
-  };
-  $("#make_default").click(make_default);
-  return $("#btsearch").click(check_search_term);
-});
diff --git a/wqflask/wqflask/static/new/javascript/dataset_select_menu_edit_trait.js b/wqflask/wqflask/static/new/javascript/dataset_select_menu_edit_trait.js
deleted file mode 100644
index 1d4a94d9..00000000
--- a/wqflask/wqflask/static/new/javascript/dataset_select_menu_edit_trait.js
+++ /dev/null
@@ -1,253 +0,0 @@
-var apply_default, check_search_term, dataset_info, group_info, make_default, open_window, populate_dataset, populate_group, populate_species, populate_type, process_json, redo_dropdown;
-process_json = function(data) {
-  window.jdata = data;
-  populate_species();
-  if ($('#type').length > 0) { //This is to determine if it's the index page or the submit_trait page (which only has species and group selection and no make default option)
-    return apply_default();
-  }
-};
-
-$.ajax('/api/v_pre1/gen_dropdown', {
-  dataType: 'json',
-  success: process_json
-});
-
-populate_species = function() {
-  var species_list;
-  species_list = this.jdata.species;
-  redo_dropdown($('#species'), species_list);
-  return populate_group();
-};
-window.populate_species = populate_species;
-populate_group = function() {
-  var group_list, species;
-  console.log("in populate group");
-  species = $('#species').val();
-  group_list = this.jdata.groups[species];
-  for (_i = 0, _len = group_list.length; _i < (_len - 1); _i++) {
-     if (group_list[_i][0] == "BXD300"){
-         group_list.splice(_i, 1)
-     }
-  }
-  redo_dropdown($('#group'), group_list);
-  if ($('#type').length > 0) { //This is to determine if it's the index page or the submit_trait page (which only has species and group selection and no make default option)
-    return populate_type();
-  }
-};
-window.populate_group = populate_group;
-populate_type = function() {
-  var group, species, type_list;
-  console.log("in populate type");
-  species = $('#species').val();
-  group = $('#group').val();
-  type_list = this.jdata.types[species][group];
-  redo_dropdown($('#type'), type_list);
-  return populate_dataset();
-};
-window.populate_type = populate_type;
-populate_dataset = function() {
-  var dataset_list, group, species, type;
-  console.log("in populate dataset");
-  species = $('#species').val();
-  group = $('#group').val();
-  type = $('#type').val();
-  console.log("sgt:", species, group, type);
-  dataset_list = this.jdata.datasets[species][group][type];
-  console.log("pop_dataset:", dataset_list);
-  return redo_dropdown($('#dataset'), dataset_list);
-};
-window.populate_dataset = populate_dataset;
-redo_dropdown = function(dropdown, items) {
-  var item, _i, _len, _results;
-  console.log("in redo:", dropdown, items);
-  dropdown.empty();
-  _results = [];
-
-  if (dropdown.attr('id') == "group"){
-    group_family_list = [];
-    for (_i = 0, _len = items.length; _i < _len; _i++) {
-      item = items[_i];
-      group_family = item[2].toString().split(":")[1]
-      group_family_list.push([item[0], item[1], group_family])
-    }
-
-    current_family = ""
-    this_opt_group = null
-    for (_i = 0, _len = group_family_list.length; _i < _len; _i++) {
-      item = group_family_list[_i];
-      if (item[2] != "None" && current_family == ""){
-        current_family = item[2]
-        this_opt_group = $("<optgroup label=\"" + item[2] + "\">")
-        this_opt_group.append($("<option />").val(item[0]).text(item[1]));
-      } else if (current_family != "" && item[2] == current_family){
-        this_opt_group.append($("<option />").val(item[0]).text(item[1]));
-        if (_i == group_family_list.length - 1){
-          _results.push(dropdown.append(this_opt_group))
-        }
-      } else if (current_family != "" && item[2] != current_family && item[2] != "None"){
-        current_family = item[2]
-        _results.push(dropdown.append(this_opt_group))
-        this_opt_group = $("<optgroup label=\"" + current_family + "\">")
-        this_opt_group.append($("<option />").val(item[0]).text(item[1]));
-        if (_i == group_family_list.length - 1){
-          _results.push(dropdown.append(this_opt_group))
-        }
-      } else if (current_family != "" && this_opt_group != null && item[2] == "None"){
-        _results.push(dropdown.append(this_opt_group))
-        current_family = ""
-        _results.push(dropdown.append($("<option />").val(item[0]).text(item[1])));
-      } else {
-        _results.push(dropdown.append($("<option />").val(item[0]).text(item[1])));
-      }
-    }
-  } else if (dropdown.attr('id') == "type"){
-    type_family_list = [];
-    for (_i = 0, _len = items.length; _i < _len; _i++) {
-      item = items[_i];
-      type_family_list.push([item[0], item[1], item[2]])
-    }
-
-    current_family = ""
-    this_opt_group = null
-    for (_i = 0, _len = type_family_list.length; _i < _len; _i++) {
-      item = type_family_list[_i];
-      if (item[2] != "None" && current_family == ""){
-        current_family = item[2]
-        this_opt_group = $("<optgroup label=\"" + item[2] + "\">")
-        this_opt_group.append($("<option />").val(item[0]).text(item[1]));
-        if (_i == type_family_list.length - 1){
-          _results.push(dropdown.append(this_opt_group))
-        }
-      } else if (current_family != "" && item[2] == current_family){
-        this_opt_group.append($("<option />").val(item[0]).text(item[1]));
-        if (_i == type_family_list.length - 1){
-          _results.push(dropdown.append(this_opt_group))
-        }
-      } else if (current_family != "" && item[2] != current_family && item[2] != "None"){
-        current_family = item[2]
-        _results.push(dropdown.append(this_opt_group))
-        this_opt_group = $("<optgroup label=\"" + current_family + "\">")
-        this_opt_group.append($("<option />").val(item[0]).text(item[1]));
-        if (_i == type_family_list.length - 1){
-          _results.push(dropdown.append(this_opt_group))
-        }
-      } else {
-        _results.push(dropdown.append(this_opt_group))
-        current_family = ""
-        _results.push(dropdown.append($("<option />").val(item[0]).text(item[1])));
-      } 
-    }
-  } else {
-    for (_i = 0, _len = items.length; _i < _len; _i++) {
-      item = items[_i];
-      if (item.length > 2){
-        _results.push(dropdown.append($("<option data-id=\""+item[0]+"\" />").val(item[1]).text(item[2])));
-      } else {
-        _results.push(dropdown.append($("<option />").val(item[0]).text(item[1])));
-      }
-    }
-  }
-
-  return _results;
-};
-$('#species').change((function(_this) {
-  return function() {
-    return populate_group();
-  };
-})(this));
-$('#group').change((function(_this) {
-  return function() {
-    if ($('#type').length > 0) { //This is to determine if it's the index page or the submit_trait page (which only has species and group selection and no make default option)
-      return populate_type();
-    }
-    else {
-      return false
-    }
-  };
-})(this));
-$('#type').change((function(_this) {
-  return function() {
-    return populate_dataset();
-  };
-})(this));
-open_window = function(url, name) {
-  var options;
-  options = "menubar=yes,toolbar=yes,titlebar=yes,location=yes,resizable=yes,status=yes,scrollbars=yes,directories=yes,width=900";
-  return open(url, name, options).focus();
-};
-group_info = function() {
-  var group, species, url;
-  species = $('#species').val();
-  group = $('#group').val();
-  url = "http://gn1.genenetwork.org/" + species + "Cross.html#" + group;
-  return open_window(url, "Group Info");
-};
-$('#group_info').click(group_info);
-dataset_info = function() {
-  var dataset, url;
-  accession_id = $('#dataset option:selected').data("id");
-  name = $('#dataset option:selected').val();
-  if (accession_id != "None") {
-    url = "http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&GN_AccessionId=" + accession_id + "&InfoPageName=" + name;
-  } else {
-    url = "http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&InfoPageName=" + name;
-  }
-  return open_window(url, "Dataset Info");
-};
-$('#dataset_info').click(dataset_info);
-make_default = function() {
-  var holder, item, jholder, _i, _len, _ref;
-  alert("The current settings are now your default.")
-  holder = {};
-  _ref = ['species', 'group', 'type', 'dataset'];
-  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-    item = _ref[_i];
-    holder[item] = $("#" + item).val();
-  }
-  jholder = JSON.stringify(holder);
-  return $.cookie('search_defaults', jholder, {
-    expires: 365
-  });
-};
-apply_default = function() {
-  var defaults, item, populate_function, _i, _len, _ref, _results;
-  defaults = $.cookie('search_defaults');
-  if (defaults) {
-    defaults = $.parseJSON(defaults);
-  } else {
-    defaults = {
-      species: "mouse",
-      group: "BXD",
-      type: "Hippocampus mRNA",
-      dataset: "HC_M2_0606_P"
-    };
-  }
-
-  _ref = [['species', 'group'], ['group', 'type'], ['type', 'dataset'], ['dataset', null]];
-  _results = [];
-  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-    item = _ref[_i];
-    $("#" + item[0]).val(defaults[item[0]]);
-    if (item[1]) {
-      populate_function = "populate_" + item[1];
-      console.log("Calling:", populate_function);
-      _results.push(window[populate_function]());
-    } else {
-      _results.push(void 0);
-    }
-  }
-  return _results;
-};
-check_search_term = function() {
-  var or_search_term, and_search_term;
-  or_search_term = $('#or_search').val();
-  and_search_term = $('#and_search').val();
-  console.log("or_search_term:", or_search_term);
-  console.log("and_search_term:", and_search_term);
-  if (or_search_term === "" && and_search_term === "") {
-    alert("Please enter one or more search terms or search equations.");
-    return false;
-  }
-};
-$("#make_default").click(make_default);
-$("#btsearch").click(check_search_term);
diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html
index 8d83d1a6..29fdc5f1 100644
--- a/wqflask/wqflask/templates/correlation_page.html
+++ b/wqflask/wqflask/templates/correlation_page.html
@@ -17,8 +17,8 @@
             <hr style="height: 1px; background-color: #A9A9A9;">
         </div>
         <div style="max-width: 100%;">
-          <p>Values of record {{ this_trait.name }} in the <a href="http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&{% if this_dataset.accession_id != 'None' %}GN_AccessionId={{ this_dataset.accession_id }}{% else %}InfoPageName={{ this_dataset.name }}{% endif %}">{{ this_dataset.fullname }}</a>
-          dataset were compared to all records in the <a href="http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&{% if target_dataset.accession_id != 'None' %}GN_AccessionId={{ target_dataset.accession_id }}{% else %}InfoPageName={{ target_dataset.name }}{% endif %}">{{ target_dataset.fullname }}</a>
+          <p>Values of record {{ this_trait.name }} in the <a href="http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&{% if this_dataset.accession_id %}GN_AccessionId={{ this_dataset.accession_id }}{% else %}InfoPageName={{ this_dataset.name }}{% endif %}">{{ this_dataset.fullname }}</a>
+          dataset were compared to all records in the <a href="http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&{% if target_dataset.accession_id %}GN_AccessionId={{ target_dataset.accession_id }}{% else %}InfoPageName={{ target_dataset.name }}{% endif %}">{{ target_dataset.fullname }}</a>
           dataset. The top {{ return_results }} correlations ranked by the {{ formatted_corr_type }} are displayed.
           You can resort this list by clicking the headers. Select the Record ID to open the trait data
           and analysis page.
diff --git a/wqflask/wqflask/templates/edit_probeset.html b/wqflask/wqflask/templates/edit_probeset.html
index 6c068e63..c5ef992e 100644
--- a/wqflask/wqflask/templates/edit_probeset.html
+++ b/wqflask/wqflask/templates/edit_probeset.html
@@ -3,6 +3,31 @@
 {% block content %}
 <!-- Start of body -->
 <div class="container">
+    {% with messages = get_flashed_messages(category_filter=["warning"]) %}
+    {% if messages %}
+    {% for message in messages %}
+    <div class="alert alert-warning alert-dismissible" role="alert">
+	<button class="close" type="button" data-dismiss="alert" aria-label="Close">
+	    <span aria-hidden="true">&times;</span>
+	</button>
+	{{ message }}
+    </div>
+    {% endfor %}
+    {% endif %}
+    {% endwith %}
+
+    {% with messages = get_flashed_messages(category_filter=["success"]) %}
+    {% if messages %}
+    {% for message in messages %}
+    <div class="alert alert-success alert-dismissible" role="alert">
+	<button class="close" type="button" data-dismiss="alert" aria-label="Close">
+	    <span aria-hidden="true">&times;</span>
+	</button>
+	{{ message|safe }}
+    </div>
+    {% endfor %}
+    {% endif %}
+    {% endwith %}
     <div class="page-header text-left">
 	<h1>Probeset Editing Form: {{ probeset.name }}</h1>
 	<small><a href="{{url_for('metadata_edit.show_history', name=name)}}" target="_blank">[View History]</a></small>
@@ -71,7 +96,7 @@
 	</div>
 	<div class="form-group">
             <label for="homologeneid" class="col-sm-3 col-lg-2 control-label text-left">
-		Homolegene Id:
+		Homologene Id:
             </label>
             <div class="col-sm-4">
 		<textarea name="homologeneid" class="form-control" rows="1">{{ probeset.homologeneid |default('', true) }}</textarea>
@@ -188,6 +213,12 @@
 {% block js %}
 <script>
  gn_server_url = "{{ gn_server_url }}";
+ spans = document.querySelectorAll("[data-message-id]")
+ spans.forEach((span) => {
+     span.innerHTML = $("[for='" + span.getAttribute("data-message-id") + "']").text();
+ });
+ $("[data-message-id]").lead
+ 
  function MarkAsChanged(){
      $(this).addClass("changed");
  }
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 5bcd17b8..3a6f6e91 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -17,7 +17,7 @@
         <div style="padding-top: 10px; padding-bottom: 10px; font-size: 16px;">
         <!-- Need to customize text more for other types of searches -->
 
-        <p>We searched <a href="http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&{% if dataset.accession_id != 'None' %}GN_AccessionId={{ dataset.accession_id }}{% else %}InfoPageName={{ dataset.name }}{% endif %}">{{ dataset.fullname }}</a>
+            <p>We searched <a href="http://genenetwork.org/webqtl/main.py?FormID=sharinginfo&{% if metadata.accession_id %}GN_AccessionId={{ metadata.accession_id }}{% else %}InfoPageName={{ dataset.name }}{% endif %}">{{ dataset.fullname }}</a>
           <br>
           to find all records
                 {% if go_term is not none %}
@@ -97,8 +97,8 @@
               <input type="hidden" name="database_name" id="database_name" value="{{ dataset.fullname }}">
               <input type="hidden" name="file_name" id="file_name" value="search_results">
               <input type="hidden" name="filter_term" id="filter_term" value="None">
-              {% if dataset.accession_id is defined %}
-              <input type="hidden" name="accession_id" id="accession_id" value="{{ dataset.accession_id }}">
+              {% if metadata.accession_id %}
+              <input type="hidden" name="accession_id" id="accession_id" value="{{ metadata.accession_id }}">
               {% endif %}
               <input type="hidden" name="export_data" id="export_data" value="">
               <input type="text" id="searchbox" class="form-control" style="width: 200px; display: inline;" placeholder="Search For...">
diff --git a/wqflask/wqflask/templates/show_metadata_details.html b/wqflask/wqflask/templates/show_metadata_details.html
new file mode 100644
index 00000000..ffb197e2
--- /dev/null
+++ b/wqflask/wqflask/templates/show_metadata_details.html
@@ -0,0 +1,186 @@
+<table class="table metadata">
+    {% if metadata.accession_id %}
+    <tr>
+        <td><b>Title:</b></td>
+        <td><div>{{ metadata.accession_id }} {% if metadata.title %}: {{ metadata.title }} {% endif %}</div></td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.geo_series %}
+    <tr>
+        <td><b>Geo Series:</b></td>
+        <td><div>{{ metadata.geo_series|safe }}</div></td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.dataset_group %}
+    <tr>
+        <td><b>Dataset Group:</b></td>
+        <td><div>{{ metadata.dataset_group }}</div></td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.species_name %}
+    <tr>
+        <td><b>Species:</b></td>
+        <td><div>{{ metadata.species_name }}</div></td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.inbred_set_name %}
+    <tr>
+        <td><b>Group:</b></td>
+        <td><div>{{ metadata.inbred_set_name }}</div></td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.investigators %}
+    <tr>
+        <td><b>Investigator(s):</b></td>
+        <td><div>{{ metadata.investigators.name }}, {{ metadata.investigators.city }}, {{ metadata.investigators.country }} </div></td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.tissue_name %}
+    <tr>
+	<td><b>Tissue:</b></td>
+	<td>
+	    {% if metadata.about_tissue %}
+	    <div></div>
+	    <details>
+		<summary><b title="Click to view tissue information">{{ metadata.tissue_name }}</b></summary>
+		<b>About the tissue used to generate this set of data:</b>
+		<div>{{ metadata.about_tissue|safe }}</div>
+	    </details>
+	    {% else %}
+	    {{ metadata.tissue_name }}
+	    {% endif %}
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.platform_name %}
+    <tr>
+	<td><b>Platforms:</b></td>
+	<td>
+	    {% if metadata.about_platform %}
+	    <details>
+		<summary><b title="Click to view platform information">{{ metadata.platform_name }}</b></summary>
+		<b>About the array platform:</b>
+		{{ metadata.about_platform|safe }}
+	    </details>
+	    {% else %}
+	    {{ metadata.platform_name }}
+	    {% endif %}
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.normalization_name %}
+    <tr>
+	<td><b>Normalization:</b></td>
+	<td>
+	    {{ metadata.normalization_name }}
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.summary %}
+    <tr>
+        <td></td>
+        <td>
+            <details>
+                <summary><b title="Click to view summary">Summary</b></summary>
+                {{ metadata.summary|safe  }}
+            </details>
+        </td>
+    </tr>
+    {% endif %}
+
+
+    {% if metadata.about_cases %}
+    <tr>
+	<td></td>
+	<td>
+	    <details>
+		<summary><b title="Click to view case information">About the cases used to generate this set of data</b></summary>
+		{{ metadata.about_cases|safe }}
+	    </details>
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.about_data_processing %}
+    <tr>
+        <td></td>
+	<td>
+	    <details>
+		<summary><b title="Click to view data values and processing">About Data Values and Data Processing</b></summary>
+		{{ metadata.about_data_processing|safe }}
+	    </details>
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.notes %}
+    <tr>
+        <td></td>
+	<td>
+	    <details>
+		<summary><b>Notes</b></summary>
+		{{ metadata.notes|safe }}
+	    </details>
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.experiment_design %}
+    <tr>
+        <td></td>
+	<td>
+	    <details>
+		<summary><b>Experiment Type</b></summary>
+		{{ metadata.experiment_design|safe }}
+	    </details>
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.contributors %}
+    <tr>
+        <td></td>
+	<td>
+	    <details>
+		<summary><b>Contributor(s)</b></summary>
+		{{ metadata.contributors|safe }}
+	    </details>
+	</td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.citation  %}
+    <tr>
+        <td>
+            <td>
+		<details>
+		    <summary><b>Citation</b></summary>
+		    {{ metadata.citation|safe }}
+		</details>
+	    </td>
+    </tr>
+    {% endif %}
+
+    {% if metadata.acknowledgment  %}
+    <tr>
+        <td></td>
+        <td>
+	    <details>
+	    <summary><b>Data source acknowledgment</b></summary>
+	    {{ metadata.acknowledgment|safe }}
+	    </details>
+	</td>
+    </tr>
+    {% endif %}
+
+
+</table>
diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html
index 0f93188b..4b92545c 100644
--- a/wqflask/wqflask/templates/show_trait.html
+++ b/wqflask/wqflask/templates/show_trait.html
@@ -51,8 +51,20 @@
                         <div class="panel-body">
                             {% include 'show_trait_details.html' %}
                         </div>
+		    </div>
+		    {% if metadata.accession_id %}
+		    <div class="panel-heading" data-toggle="collapse" data-parent="#accordion" data-target="#collapseMeta">
+                        <h3 class="panel-title">
+                            <span class="glyphicon glyphicon-chevron-down"></span> Data Set Group: {{  dataset.fullname }}
+                        </h3>
                     </div>
-                </div>    
+                    <div id="collapseMeta" class="panel-collapse collapse in">
+                        <div class="panel-body">
+			    {% include 'show_metadata_details.html' %}
+                        </div>
+		    </div>
+		    {% endif %}
+                </div>
                 <div class="panel panel-default">
                     <div class="panel-heading stats_panel" data-toggle="collapse" data-parent="#accordion" data-target="#collapseTwo">
                         <h3 class="panel-title">
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 211a8f13..1b34e2f8 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -83,12 +83,14 @@ from utility.helper_functions import get_species_groups
 from utility.redis_tools import get_redis_conn
 
 import utility.hmac as hmac
+from gn3.db.rdf import get_dataset_metadata
 
 
 from base.webqtlConfig import TMPDIR
 from base.webqtlConfig import GENERATED_IMAGE_DIR
 
 from wqflask.database import database_connection
+from wqflask.database import sparql_connection
 
 import jobs.jobs as jobs
 
@@ -487,7 +489,18 @@ def show_trait_page():
         template_vars.js_data = json.dumps(template_vars.js_data,
                                            default=json_default_handler,
                                            indent="   ")
-        return render_template("show_trait.html", **template_vars.__dict__)
+        metadata = (
+            template_vars.dataset.accession_id
+            .bind(
+                lambda idx: get_dataset_metadata(
+                    sparql_connection(),
+                    f"GN{idx}"
+                )
+            )
+        ).data
+
+        return render_template("show_trait.html",
+                               metadata=metadata, **template_vars.__dict__)
 
 
 @app.route("/heatmap", methods=('POST',))