{"id":"3f9c13f7a85d00b5","slug":"natural-selection-analysis-of-sars-cov-2-covid-19","first_public_version":null,"paused_version":null,"likes":11,"publish_level":"public","forks":4,"fork_of":{"id":"aa32bfb855aabd38","slug":"current-state-of-sars-cov-2-evolution","title":"Genomic diversity and divergence of  SARS-CoV-2/COVID-19","owner":{"id":"9bf992815a7b66f2","avatar_url":"https://avatars.observableusercontent.com/avatar/23c8c466a3ef27f1444c95a9ed8e52bcf08888403b6d4efbd039319b0761c13d","login":"spond","name":"Sergei Pond","bio":"","home_url":"http://lab.hyphy.org","type":"team","tier":"starter_2024"},"version":212},"has_importers":true,"thumbnail":"67d228e2a1d15121721acddbe7f930055f8f3058ce025a9a1584cd923fbac8fc","default_thumbnail":"67d228e2a1d15121721acddbe7f930055f8f3058ce025a9a1584cd923fbac8fc","update_time":"2020-05-07T04:02:56.599Z","publish_time":"2020-03-24T04:41:24.413Z","publish_version":3046,"latest_version":3046,"roles":[],"sharing":null,"owner":{"id":"9bf992815a7b66f2","avatar_url":"https://avatars.observableusercontent.com/avatar/23c8c466a3ef27f1444c95a9ed8e52bcf08888403b6d4efbd039319b0761c13d","login":"spond","name":"Sergei Pond","bio":"","home_url":"http://lab.hyphy.org","type":"team","tier":"starter_2024"},"creator":{"id":"f439ea11e6786e12","avatar_url":"https://avatars.observableusercontent.com/avatar/23c8c466a3ef27f1444c95a9ed8e52bcf08888403b6d4efbd039319b0761c13d","login":"spond","name":"Sergei Pond","bio":"","home_url":"http://lab.hyphy.org","tier":"pro"},"authors":[{"id":"f439ea11e6786e12","avatar_url":"https://avatars.observableusercontent.com/avatar/23c8c466a3ef27f1444c95a9ed8e52bcf08888403b6d4efbd039319b0761c13d","name":"Sergei Pond","login":"spond","bio":"","home_url":"http://lab.hyphy.org","tier":"pro","approved":true,"description":""}],"files":[],"comments":[],"commenting_lock":null,"suggestions_to":[],"suggestion_from":null,"collections":[],"version":2150,"title":"Natural selection analysis of SARS-CoV-2/COVID-19","license":null,"copyright":"","nodes":[{"id":0,"value":"md`# Natural selection analysis of SARS-CoV-2/COVID-19`","pinned":false,"mode":"js","data":null,"name":null},{"id":55,"value":"intro = md`\n\n<small>_These analyses are based on sequences deposited in <img src=\"https://www.gisaid.org/fileadmin/gisaid/img/schild.png\" alt=\"gisaid-logo\" width=\"40\"> database by numerous contributing labs and agencies._  **Last update: May 4th, 2020**. </small>\n<br>\n\n\nWhich positions in the [SARS-CoV-2 genome](https://www.ncbi.nlm.nih.gov/nuccore/?term=COVID) **may be** subject to **positive** selection, i.e., involved in adaptation, or **negative** selection, i.e. conserved during evolution? We used several statistical techniques and other sources of information to identify potential candidates using unique genomic sequences ([details](ttps://github.com/veg/SARS-CoV-2)), with permissive thresholds to identify sets of sites that might merit a deeper look. The sites which **we think are the most interesting** are shown at the top. Each site receives _points_ for **eight** different categories, coded by icons and explained below, and sites with the most points are ranked higher.\n\nDetails of what's in the table are below all the images on the page. The table below may take a little while to load, since it combines several \"live\" sources of data. The image below summarizes all the genomic sites which appear in any of the \"interesting\" categories detailed below (total # of categories = site score, click and drag in the gene bar below the plot to zoom in).\n\n\n` ","pinned":false,"mode":"js","data":null,"name":null},{"id":1684,"value":"genome_view = vegalite({\n\t\"$schema\": \"https://vega.github.io/schema/vega-lite/v5.json\",\n\t\"config\": {\n\t\t\"view\": {\n\t\t\t\"stroke\": null\n\t\t},\n\t},\n  \"data\": {\n\t\t\t\t   \"values\": summary.plot\n        },\n\t    \"vconcat\": [{\n\t\t\t\"height\": 90,\n\t\t\t\"width\": 750,\n\n        \"mark\": {\n\t\t\t\t\ttype: \"circle\", tooltip : true,\n\t\t\t\t},\n        \"encoding\": {\n          \"y\": {\n            \"field\": \"kind\",\n            \"type\": \"nominal\",\n            \"sort\": null,\n            \"axis\": {\n              \"domain\": false,\n              \"offset\": 10,\n              \"labelFontWeight\": \"bold\",\n              \"ticks\": false,\n              \"grid\": true,\n              \"title\": null\n            }\n          },\n\t\t\t\t\t\"x\": {\n\t\t\t\t\t\t\"field\": \"position\",\n\t\t\t\t\t\t\"type\": \"quantitative\",\n\t\t\t\t\t\t\"scale\": {\n\t\t\t\t\t\t\t\"domain\": {\n\t\t\t\t\t\t\t\t\"selection\": \"brush\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"axis\": {\n\t\t\t\t\t\t\t\"title\": \"Genomic Coordinate\",\n\t\t\t\t\t\t\t\"grid\": false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t/*\"color\": {\n\t\t\t\t\t\t\"field\": \"type\",\n\t\t\t\t\t\t\"legend\": {\n\t\t\t\t\t\t\t\"title\": \"Type of selection\",\n\t\t\t\t\t\t\t\"orient\": \"bottom\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"scale\": {\n\t\t\t\t\t\t\t\"scheme\": \"tableau10\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}*/\n\t\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"height\": 50,\n\t\t\t\"width\": 750,\n\t\t\t\"layer\": [{\n\t\t\t\t\t\"transform\": [{\n\t\t\t\t\t\t\"calculate\": \"0\",\n\t\t\t\t\t\t\"as\": \"y\"\n\t\t\t\t\t},\n          {\n\t\t\t\t\t\t\"calculate\": \"10\",\n\t\t\t\t\t\t\"as\": \"y2\"\n\t\t\t\t\t}],\n\t\t\t\t\t\"mark\": {\n\t\t\t\t\t\ttype: \"rule\", tooltip : false,\n\t\t\t\t\t},\n\t\t\t\t\t\"encoding\": {\n\t\t\t\t\t\t\"x\": {\n\t\t\t\t\t\t\t\"field\": \"position\",\n\t\t\t\t\t\t\t\"type\": \"quantitative\",\n\t\t\t\t\t\t\t\"axis\": null,\n\t\t\t\t\t\t},\n            \"y\":  {\n\t\t\t\t\t\t\t\"field\": \"y\",\n\t\t\t\t\t\t\t\"type\": \"quantitative\",\n\t\t\t\t\t\t\t\"axis\": null,\n\t\t\t\t\t\t},\n            \"y2\":  {\n\t\t\t\t\t\t\t\"field\": \"y2\",\n\t\t\t\t\t\t\t\"type\": \"quantitative\",\n\t\t\t\t\t\t\t\"axis\": null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"color\": {\n\t\t\t\t\t\t\t\"field\": \"score\",\n              \"type\": \"nominal\",\n\t\t\t\t\t\t\t\"legend\": {\n\t\t\t\t\t\t\t\t\"title\": \"Site score\",\n\t\t\t\t\t\t\t\t\"orient\": \"bottom\"\n\t\t\t\t\t\t\t},\n              \"scale\": {\n\t\t\t\t\t\t\t    \"scheme\": \"lightgreyred\"\n\t\t\t\t\t\t  }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"values\": gene_coordinates\n\t\t\t\t\t},\n\t\t\t\t\t\"transform\": [{\n\t\t\t\t\t\t\t\"calculate\": \"(datum['3'] % 2) ? -1 : 1\",\n\t\t\t\t\t\t\t\"as\": \"coloring\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"calculate\": \"0\",\n\t\t\t\t\t\t\t\"as\": \"y\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"calculate\": \"10\",\n\t\t\t\t\t\t\t\"as\": \"y2\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"calculate\": \"10 + ((datum['3'] % 2) ? 0 : -13)\",\n\t\t\t\t\t\t\t\"as\": \"y3\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"calculate\": \"(datum['0']+datum['2'])*0.5\",\n\t\t\t\t\t\t\t\"as\": \"xm\"\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t],\n\t\t\t\t\t\"layer\": [{\n\t\t\t\t\t\t\t\"selection\": {\n\t\t\t\t\t\t\t\t\"brush\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"interval\",\n\t\t\t\t\t\t\t\t\t\"encodings\": [\"x\"],\n\t\t\t\t\t\t\t\t\t\"mark\": {\n\t\t\t\t\t\t\t\t\t\t\"fill\": \"#fdbb84\",\n\t\t\t\t\t\t\t\t\t\t\"fillOpacity\": 0.5,\n\t\t\t\t\t\t\t\t\t\t\"stroke\": \"#e34a33\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"mark\": {\n\t\t\t\t\t\t\t\t\"type\": \"bar\",\n\t\t\t\t\t\t\t\t\"stroke\": \"#000\",\n                 tooltip : false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"encoding\": {\n\t\t\t\t\t\t\t\t\"x\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"0\",\n\t\t\t\t\t\t\t\t\t\"type\": \"quantitative\",\n\t\t\t\t\t\t\t\t\t\"axis\": null\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"x2\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"2\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"y\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"y\",\n\t\t\t\t\t\t\t\t\t\"type\": \"quantitative\",\n\t\t\t\t\t\t\t\t\t\"axis\": null\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"y2\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"y2\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fill\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"coloring\",\n\t\t\t\t\t\t\t\t\t\"scale\": {\n\t\t\t\t\t\t\t\t\t\t\"range\": [\"lightgrey\", \"white\"]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"legend\": null,\n\t\t\t\t\t\t\t\t\t\"type\": \"nominal\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"opacity\": {\n\t\t\t\t\t\t\t\t\t\"value\": \"0.5\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"mark\": {\n\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\"fontSize\": 9,\n\t\t\t\t\t\t\t\t\"baseline\": \"bottom\",\n                \"tooltip\" : false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"encoding\": {\n\t\t\t\t\t\t\t\t\"x\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"xm\",\n\t\t\t\t\t\t\t\t\t\"type\": \"quantitative\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"y\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"y3\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"1\",\n                  \"legend\" : null,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\n\t]\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":910,"value":"viewof use_date = {\n  const dd3 = select({\n    title: \"View using data from\",\n    options:\n      analysis_dates\n  });\n  dd3.input.style.fontSize = \"30px\";\n  dd3.input.style.marginTop = \"8px\";\n  return dd3;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":276,"value":"summary_table = table(\n  summary.table,\n  {\n    limit: 5000,\n    enableCSVDownload: true,\n    sort: true,\n    enableFilter: false,\n    columns: [\n      { \n      key: 'prior',\n      name: 'First Detected',\n      render: val => {\n          if (val && val[1]) {\n            if (val[0].length == 0) {\n                return `<b>New</b>`; \n            } else {\n                return date_format_short (date_reader(val[0][0]));\n            } \n          }\n          return '<b>New</b>';\n      }\n      },\n      { \n        key: 'site',\n        name: 'Site'\n      },\n      { \n      key: 'classification',\n      name: 'Categories',\n      render: val => {\n          let tags = [];\n          if (val.fel) {\n            if (val.kind == \"negative\") tags.push ('<span style=\"color:darkgreen;\"><i class=\"fas fa-minus-circle\" title = \"Pervasive Negative\"></i></span>'); \n            else\n              tags.push ('<span style=\"color:red;\"><i class=\"fas fa-plus-circle\" title = \"Pervasive Positive\"></i></span>'); \n          } else {\n            if (val.meme) {\n               tags.push ('<span style=\"color:darkred;\"><i class=\"fas fa-plus-circle\" title= \"Episodic @ ' + d3.format (\".2p\")(val.fraction) + '\"></i></span>');\n            }\n          }\n          if (val.MAF) {\n            tags.push ('<span><i class=\"fas fa-fire\" title = \"Common variants @' + d3.format (\".2p\")(val.MAF) + '\"></i></span>');\n          }\n          if (val.trend) {\n            tags.push ('<span><i class=\"fas fa-chart-line\" title = \"Increasing trend\"></i></span>');\n          }\n          if (val.branches > 1) {\n            tags.push ('<span><i class=\"fas fa-redo\" title = \"Multiple (' + val.branches +') branches under selection\"></i></span>'); \n          }\n          if (val.variants > 0) {\n              tags.push ('<span><i class=\"fas fa-check-double\" title = \"Intrahost variants in ' + (val.variants) + ' samples \"></i></span>');          \n          }\n        \n          if (val.betas && val.betas.length > 0) {\n              tags.push ('<span><i class=\"fas fa-paw\" title = \"' + val.betas + '\"></i></span>');          \n          }\n        \n          if (val.hla) {\n              tags.push ('<span><i class=\"fas fa-syringe\" title = \"In ' + _.size (val.hla) + ' predicted HLA epitopes\"></i></span>');          \n          }\n        \n          if (('evo_support' in val) && (val.evo_support == false)) {\n             tags.push ('<span><i class=\"fas fa-exclamation-triangle\" title = \"Unexpected amino-acid variants\"></i></span>');   \n          }\n          return `${tags.join (' ')}`;}\n    },\n    { \n      key: 'composition',\n      name: 'Site composition/Evolutionary Credibility',\n      render: val => {return `${val.composition} ${val.variants.length > 0 ? '<i class=\"fas fa-info-circle\" title =\"' + _.map (val.variants, (r)=>r[6] + \" \" + r[4] + \"(\" + r[2] + \")\").join (\"\\n\") + '\"></i>' : ''} `}\n    },\n    { \n      key: 'substitutions',\n      name: 'Substitutions at <br> Internal Branches <br> [Syn:Non-syn]',\n      render:val => `${d3.format (\".2g\")(val[0])} : ${d3.format (\".2g\")(val[1])}`\n    },\n    /*{ \n      key: 'prime',\n      name: 'Biochemical Property Importance',\n      render: val => `${_.map (val, (d)=> render_property (d))}`\n    }*/\n   ]\n  }\n)","pinned":false,"mode":"js","data":null,"name":null},{"id":1384,"value":"md`----\n### Temporal and geographic site trends\n`","pinned":false,"mode":"js","data":null,"name":null},{"id":348,"value":"viewof render_site = {\n  const dd3 = select({\n    title: \"View annotated tree and time-series for a site\",\n    options:\n      _.map (summary.selectors, (d)=>{return {'label' : d[0] + \"/\" + d[1], \"value\" : d}})\n  });\n  dd3.input.style.fontSize = \"30px\";\n  dd3.input.style.marginTop = \"8px\";\n  return dd3;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":692,"value":"temporal_evolution_plot = vegalite({\n  \"title\" : \"Temporal evolution of \" + render_site.split (',').slice (0,2).join (\"/\") + \" composition\",\n  width : 600,\n  height: 300,\n  data: {values: timing},\n  transform: [{\n    \"window\": [{\n      \"op\": \"sum\",\n      \"field\": \"count\",\n      \"as\": \"total_count\"\n    }],\n    \"groupby\": [\"sample\"],\n    \"frame\" : [null, null]\n  },\n  {\n    \"calculate\": \"datum.count/datum.total_count * 100\",\n    \"as\": \"PercentOfTotal\"\n  }],\n  \n  mark: {type:\"line\", tooltip: true},\n  encoding: {\n    x: {field: \"sample\", type: \"temporal\", axis: {\"title\": \"Collection Date\", titleFontSize : 14}},\n    \"tooltip\": [\n      {\"field\": \"sample\", \"type\": \"temporal\"},\n      {\"field\": \"count\", \"type\": \"quantitative\"},\n      {\"field\": \"residue\", \"type\": \"nominal\"}\n    ]\n  },\n  \"layer\": [{\n    \"mark\": {\"type\": \"bar\", \"opacity\" : 0.5},\n    \"encoding\": {\n      \"y\": {\"field\": \"count\", \"type\": \"quantitative\", axis: {\n          \"title\": \"#Sequences with residue\",\n          \"titleFontSize\" : 14\n            \n       },\n       \"scale\": {              \n        \"type\": \"linear\"\n      }},\n      \"color\" : {\n      \"sort\": {\"field\": \"residue\"},\n      \"field\" : \"residue\" ,\n      \"scale\": {\"scheme\": \"set1\"}\n    }\n    },\n  },\n  {\n    \"mark\": {\"type\": \"line\", \"interpolate\" : \"monotone\", \"strokeWidth\" : 3},\n    \"encoding\": {\n      \"y\": {\"field\": \"PercentOfTotal\", \"type\": \"quantitative\", axis: {\n          \"title\": \"% of total\",\n          \"titleFontSize\" : 14\n       },\n      \"scale\": {              \n        \"type\": \"linear\"\n      }},\n      \n      \"color\" : {\n              \"sort\": {\"field\": \"residue\"},\n\n\n      \"field\" : \"residue\" ,\n      \"scale\": {\"scheme\": \"set1\"},\n        //\"legend\" : null\n    }\n    },\n  }\n  ],\n  \"config\": {\"axisY\": {\"minExtent\": 30}},\n  \"resolve\": {\"scale\": {\"y\": \"independent\"}}\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":1368,"value":"viewof use_residue = {\n  const dd3 = select({\n    title: \"Residue to view on map\",\n    options:\n      available_residues\n  });\n  dd3.input.style.fontSize = \"30px\";\n  dd3.input.style.marginTop = \"8px\";\n  return dd3;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":1391,"value":"md`Select a date range on the sample count histogram below to restrict the data that the map is built on`","pinned":false,"mode":"js","data":null,"name":null},{"id":1378,"value":"viewof date_range = rangeSlider(sample_count,  d=>d.date)","pinned":false,"mode":"js","data":null,"name":null},{"id":1388,"value":"distribution_map = vegalite (\n  {\n  \"width\": 800,\n  \"height\": 400,\n  \"title\" : \"Distribution of \" + use_residue + \" at \" + render_site.split (',').slice (0,2).join ('/'),\n  \"data\": {\n    \"values\" : world,\n    \"format\": {\n      \"type\": \"topojson\",\n      \"feature\": \"countries\"\n    }\n  },\n  \"transform\": [{\n    \"lookup\": \"id\",\n     \"default\" : \"-0.0001\",\n     \"from\": {\n      \"data\": {\n        \"values\": subs_count\n      },\n      \"key\": \"id\",\n      \"fields\": [\"rate\",\"name\",\"total\",\"variant\"]\n    }\n  }],\n  \"projection\": {\n    \"type\": \"mercator\",\n    \"center\" : [5,20],\n    \"scale\": 110,\n  },\n  \"mark\": {\n      type : \"geoshape\",\n  },\n  \"encoding\": {\n      \"tooltip\": [\n        {\"field\": \"name\", \"type\": \"nominal\"},\n        {\"field\": \"variant\", \"type\": \"quantitative\"},\n        {\"field\": \"total\", \"type\": \"quantitative\"},\n        {\"field\": \"rate\", \"type\": \"quantitative\"}\n      ],\n    \"color\": {\n      \"condition\": {\n        \"test\": \"datum.rate < 0\",\n        \"value\": \"#aaa\"\n      },\n      \"scale\" : {\n          //domain : [0,1]\n      },\n      \"legend\" : {\n        \n          \"title\" : \"Residue frequency\"\n      },\n      \"field\": \"rate\",\n      \"type\": \"quantitative\"\n    }\n  }\n}\n\n)","pinned":false,"mode":"js","data":null,"name":null},{"id":1828,"value":"md`---- \n### CTL epitopes\n> CTL epitopes (if any) that cover this site, based on the predictions of [Campbell et al](https://www.biorxiv.org/content/10.1101/2020.03.30.016931v1.abstract)\n`","pinned":false,"mode":"js","data":null,"name":null},{"id":1858,"value":"epitope_table = table(\n  detailed_epitopes,\n  {\n    limit: 5000,\n    enableCSVDownload: true,\n    sort: true,\n    enableFilter: false,\n    columns: [\n      { \n      key: 'epitope',\n      name: 'Epitope / sequences presenting',\n      render: val => {\n          if (!_.isArray (val)) {\n              return val;\n          }\n          let p = +val[1];\n          return val[0].substr (0,p) + \"<span style = 'color:red; font-weight: bold;'>\" + val[0][p] + \"</span>\" + val[0].substr (p+1) + \" / \" + val[2];\n      }\n      },\n      {key: 'alleles',\n       name: 'Alleles',\n       render: val => {\n          return _.map (val, (v, k)=>{\n            let short_name = k.split ('-')[1].split(':')[0];\n            return \"<a href = 'http://www.allelefrequencies.net/hla6002a.asp?all_name=\" + short_name + \"' target = '_blank'>\" + k + \"</a>\";}).join ('<br>');\n       }\n      }]})","pinned":false,"mode":"js","data":null,"name":null},{"id":1381,"value":"md`---- \n### Tree view`","pinned":false,"mode":"js","data":null,"name":null},{"id":397,"value":"viewof width = slider({\n  min: 100, \n  max: 4000,\n  value: 800,\n  step: 10, \n  format: \"d\",\n  description: \"Tree image width\"\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":401,"value":"viewof height = slider({\n  min: 100, \n  max: 10000,\n  value: 2500,\n  step: 10, \n  format: \"d\",\n  description: \"Tree image height\"\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":612,"value":"viewof tip_names = checkbox({\n  options: [{ value: \"off\", label: \"Show sequence names\" }],\n  value: \"toggle\",\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":540,"value":"tree_howto = md`\n* Area of the bubble: how many isolates have this gene sequence (only unique sequences were used for this analysis)\n* Branches with _codon_ changes (synonymous or non-synonymous) are drawn with thicker lines; hover over the branch to see the substitution. \n* Branches are colored by the amino-acid at the end of the branch\n* Hover over the leaf to see representative sequence ID and codon.\n`","pinned":false,"mode":"js","data":null,"name":null},{"id":378,"value":"rendered_tree = {\n   \n  var t = tree.render({\n  height:height, \n  width:width,\n  'left-right-spacing': 'fit-to-size', \n  'top-bottom-spacing': 'fit-to-size',\n  'is-radial' : false,\n  'node_circle_size' : (n)=>0\n});\n  const bs = (n) => {\n      if (tree.is_leafnode (n)) {\n          let bits = n.data.name.split ('_');\n          return Math.sqrt(parseFloat (bits[bits.length-1]));\n      }\n      return 0;\n  };\n  \n  if ('usebl' in tree) {\n    t.phylotree.branch_length_accessor = \n    n=>tree.usebl[n.data.name];\n  }\n  \n  var c10 = d3.scaleOrdinal(d3.schemeSet1);\n  t.node_bubble_size = bs;\n  t.phylotree.node_bubble_size = bs;\n  t.options[\"draw-size-bubbles\"] = true;\n  t.font_size = 10;\n  let node_label_set = {};\n  t.node_label ((n)=> {\n      try {\n       if (node_labels[n.data.name][0] != '-') {\n        node_label_set [node_labels[n.data.name][0]] = 1;\n       }\n \n       if (tip_names) {\n          return n.data.name + \"[\" + node_labels[n.data.name][0] + \"]\";\n         \n       }\n       return node_labels[n.data.name][0];\n      } catch {}\n      return \"\";\n  });\n  \n  c10.domain (_.sortBy(_.keys(node_label_set)));\n  \n  function sort_nodes (asc) {\n    tree.traverse_and_compute (function (n) {\n            var d = 1;\n            if (n.children && n.children.length) {\n                d += d3.max (n.children, function (d) { return d[\"count_depth\"];});\n            } \n            n[\"count_depth\"] = d;\n        });\n    tree.resort_children (function (a,b) {\n        return (a[\"count_depth\"] - b[\"count_depth\"]) * (asc ? 1 : -1);\n    });\n  }\n  \n  sort_nodes (true);\n\n    \n  t.style_edges ((e,d) => {\n    \n      try {\n        \n        if (node_labels[d.target.data.name][0] != '-') {\n          let node_label = node_labels[d.target.data.name][0];\n          if (node_label) {\n            e.style ('stroke', c10 (node_label));\n          }\n        }\n\n        let to_aa   = node_labels[d.target.data.name][0];\n        let from_aa = node_labels[d.source.data.name][0];\n        let from_codon   = node_labels[d.source.data.name][1];\n        let to_codon = node_labels[d.target.data.name][1];\n\n        \n        if (from_codon != to_codon && to_aa != \"-\") {\n          e.style ('stroke-width' , '5px');\n          //console.log ([from_aa + \"->\" + to_aa]);\n          let title = e.selectAll(\"title\").data ([from_codon + \"(\" + from_aa + \")->\" + to_codon + \"(\" + to_aa + \")\"]);\n          title.enter().append(\"title\");\n          title.text (d=>d);\n        }\n      } catch {}\n      \n  });\n               \n  t.style_nodes ((n,d) => {\n     try {\n     n.selectAll(\"title\").data ([d.data.name + \"(\" + node_labels[d.data.name][1] + \")\"]).enter().append(\"title\").text (d=>d);\n     } catch {}\n    /*if (tree.is_leafnode (d)) {\n        let ebf = Math.max (1e-3,Math.min (meme_results_json[\"branch attributes\"][indices[0]][d.data.name][site],1000));\n        n.style (\"fill\", color_scale(ebf));\n    }*/\n  });\n               \n                \n  t.update();\n  return t.show();\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":1503,"value":"documentation = md`### What's in the selection table?\nEach row is a position in the SARV-CoV-2 genome, annotated by the gene, its position within that gene, and (if appropriate) peptide product, that was _inferred_ to be evolving **not-neutrally** using [MEME](http://hyphy.org/methods/selection-methods/#meme) and/or [FEL](http://hyphy.org/methods/selection-methods/#fel) methods, restricted only to internal tree branches, **or** carried a high minor allele frequency (MAF > 0.2) among uniue haplotypes.\n\n#### First detected \nThe date this site first appeared on the list, or **New**. Note that sites that were detected in the past but are not detected at present are not shown in the table and you can choose to view the table as it appeared on a prior date by selecting it from the pull-down list.\n\n#### Categories\n\nEach site can _check_ one of the following five categories (the more it checks, the more interesting it is). Note that each site must on the list must be **either** under selection (as determined by MEME/FEL) **or** have an minor allele at frequency of 20% or greater.\n\n##### Selection kind\n* <span style='color:red;'><i class=\"fas fa-plus-circle\"></i></span> (<tt>Positive Pervasive</tt>): on average along interior tree branches, this site has a [dN/dS>1](https://en.wikipedia.org/wiki/Ka%2FKs_ratio) is accumulating non-synonyomous changes (some of which might have a functional impact, but most probably don't) faster relative to synonymous changes than would be expected under [neutral evolution](https://en.wikipedia.org/wiki/Neutral_mutation). \n* <span style='color:darkred;'><i class=\"fas fa-plus-circle\"></i></span> (<tt>Positive Episodic</tt>): only a fraction of interior tree branches has dN/dS > 1. This pattern is consistent with periods of evolutionary change followed by conservation or neutral evolution. Mouse over to the see the fraction of branches.\n* <span style='color:darkgreen;'><i class=\"fas fa-minus-circle\"></i></span> (<tt>Negative</tt>): on average along interior tree branches, this site has a dN/dS<1, meaning that it **conserved**, i.e. non-synonymous changes might be selected against. Note that sites with no changes (i.e. perfectly conserved sites) cannot be detected by dN/dS based methods\n\n##### Multiple selective events <span><i class=\"fas fa-redo\"></i></span>\nIf a site belongs to this category, then at least **two** internal branches in the tree are inferred to be subject to positive selection, implying several selective events (not just a single introduction)\n\n##### Increasing allele frequency <span><i class=\"fas fa-chart-line\"></i></span>\nWhen a site belongs to this category, alternative amino-acids at this site has an increasing frequency trend (based on applying the [Jonckheere–Terpstra test](https://en.wikipedia.org/wiki/Jonckheere%27s_trend_test) to 10-day intervals) \n\n##### High frequency variants <span><i class=\"fas fa-fire\"></i></span>\nWhen a site belongs to this category, the fraction of **unique viral hapoltypes in this gene** that carry a minor allele is ≥20%.\n\n##### High frequency variants <span><i class=\"fas fa-check-double\"></i></span>\nWhen a site belongs to this category, there is at least one [deep sequencing dataset](https://covid19.galaxyproject.org/genomics/4-Variation/) that shows the presence of intra-host variation at the same site.\n\n##### Evolutionarily unexpected variants <span><i class=\"fas fa-exclamation-triangle\"></i></i></span>\nWhen a site belongs to this category, there is at least one amino-acid present in more than one sequence that was not predicted to occur at this site based on the evolution of **other** betacoronaviruses. It might indicate evolutionary events that we have not observed in similar viruses before.\n\n##### Non-neutral evolution in closely related beta-coronaviruses <span><i class=\"fas fa-paw\"></i></i></span> \nThere is evidence of positive selection or differential selection acting on the bat/pangolin isolates closely related to the SARS-CoV-2 genome based on data from [Boni et al](https://www.biorxiv.org/content/10.1101/2020.03.30.015008v1)\n\n##### Site belongs to one or more predicted CTL-epitopes <span><i class=\"fas fa-syringe\"></i></i></span> \nThis site belongs to one or more CTL linear epitopes that are predicted to be recognized by one or more HLA alleles reported in [Campbell et al](https://www.biorxiv.org/content/10.1101/2020.03.30.016931v1.abstract)\n\n\n#### Composition/Evolutionary Credibility \n\nHow often does an amino-acid occur in the unique haplotypes and their inferred ancestral sequences (prior to 2020/04/12 updates), or all includes sequences (2020/04/12 and thereafter) ? \\`[-]\\` is used to denote a deletion (or missing sequence data). If the composition column is labeled with <i class=\"fas fa-info-circle\"></i>, then there are some deep sequencing samples where **intra-host ** (minor or major) allele variants are present at this position ([details](https://covid19.galaxyproject.org/genomics/4-Variation/)). Hover over this icon to see the <tt>SRR</tt> numbers and additional information. If there were **mixed bases** in the genome (e.g. <tt>AKT</tt> which maps to either <tt>AGT</tt>, coding for <tt>S</tt> or <tt>ATT</tt>, coding for <tt>I</tt>), you may see ambiguous amini-acids recorded in the table and the charts (e.g. SI<sub>1</sub>)\n\nEvolutionary credibility is computed by determining whether the presence of a given residue is **expected** or **unexpected** based on the imputations under an evolutionary model fitted to an alignment of homologous sequences from betacoronaviruses. The color of the residue (green, yellow, orange, red) indicates what category the residue belongs to. Currently, these calculations are only done for <tt>S</tt> and some of the <tt>ORF1a</tt>, but we are working to extend them to the entire genome.\n\n\nAs with any statistical inference, sites may be incorrectly classified, i.e. truly selected sites may be missed, and detected sites may in fact be neutral.\n\n\n`","pinned":false,"mode":"js","data":null,"name":null},{"id":1137,"value":"md`--- \n### How does the number of variable positions in individual genes/ORFs change as we collect more data?`","pinned":false,"mode":"js","data":null,"name":null},{"id":1071,"value":"variation_plot = vegalite({\n   \"title\": null,\n  //\"title\" : {text : \"Temporal evolution of genomic variation\", fontSize : 20, anchor : \"middle\"},\n  //transform: [{\"filter\" : \"datum.gene=='S'\"}],\n  width : 200,\n  height: 200,\n  data: {values: variation_data},\n  \"mark\": {\"type\": \"line\", \"interpolate\" : \"monotone\", \"strokeWidth\" : 3},\n\n  encoding: {\n     \"facet\" : {\n          \"field\" : \"gene\" ,\n          \"type\": \"ordinal\",\n          \"columns\": 3,\n          \"title\" : \"Gene\",\n          \"sort\": {\"field\": \"gene\"}\n          //\"scale\": {\"scheme\": \"set1\"},\n      },\n      \"x\": {field: \"date\", type: \"temporal\", axis: {\"title\": \"Analysis date\", titleFontSize : 14, grid : false}},\n      \n      \"y\": {\"field\": \"fraction\", \"type\": \"quantitative\", axis: {\n          \"title\": \"Fraction of total sites\",\n          \"titleFontSize\" : 14,\n          \"grid\" : false\n       },\n      \"scale\": {              \n        \"type\": \"sqrt\"\n      }},\n      \n      \"color\" : {\n          \"sort\": {\"field\": \"kind\"},\n          \"field\" : \"kind\" ,\n          \"type\": \"nominal\",\n          \"scale\": {\"scheme\": \"set1\"},\n          \"legend\" : {\"title\" : \"Variable site kind\", titleFontSize : 14, labelFontSize: 12, orient : \"right\"}\n       },\n      \n     \n  }\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":1511,"value":"dnds_plot = vegalite({\n   \"title\": null,\n  //\"title\" : {text : \"Temporal evolution of genomic variation\", fontSize : 20, anchor : \"middle\"},\n  //transform: [{\"filter\" : \"datum.gene=='S'\"}],\n  width : 200,\n  height: 200,\n  data: {values: _.flatten(_.map (all_selection_data, (d,k) => {\n    let gene_selection = [];\n    _.each (d, (r,g)=> {\n        if ((\"dN/dS\" in r) && (g == \"S\" || g == \"ORF1a\" || g == \"ORF1b\")) {\n          gene_selection.push ({\n              'date' : d3.timeParse (\"%Y%m%d\")(k),\n              'gene' : g,\n              'omega' : r[\"dN/dS\"][\"internal\"][0][0] \n          }); } \n    });\n    return gene_selection;\n  }), true)},\n  \"mark\": {\"type\": \"line\", \"interpolate\" : \"monotone\", \"strokeWidth\" : 3},\n\n  encoding: {\n     \"facet\" : {\n          \"field\" : \"gene\" ,\n          \"type\": \"ordinal\",\n          \"columns\": 3,\n          \"title\" : \"Gene\",\n          \"sort\": {\"field\": \"gene\"}\n          //\"scale\": {\"scheme\": \"set1\"},\n      },\n      \"x\": {field: \"date\", type: \"temporal\", axis: {\"title\": \"Analysis date\", titleFontSize : 14, grid : false}},\n      \n      \"y\": {\"field\": \"omega\", \"type\": \"quantitative\", axis: {\n          \"title\": \"dN/dS on internal branches\",\n          \"titleFontSize\" : 14,\n          \"grid\" : false\n       },\n      \"scale\": {              \n        \"type\": \"linear\"\n      }},     \n\n  }\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":5,"value":"md`----\n### Data`","pinned":false,"mode":"js","data":null,"name":null},{"id":198,"value":"date_format = d3.timeFormat (\"%Y-%m-%d\") ","pinned":false,"mode":"js","data":null,"name":null},{"id":1039,"value":"date_format_short = d3.timeFormat (\"%d %b\") ","pinned":false,"mode":"js","data":null,"name":null},{"id":1031,"value":"date_reader = d3.timeParse (\"%Y%m%d\")","pinned":false,"mode":"js","data":null,"name":null},{"id":26,"value":"all_selection_data = {\n  \n    let retrieve = async function asyncCall (use_this_date) {\n      let analysis_results = {};\n      let genes = ['S','N','M','ORF3a','ORF6','ORF7a','ORF8','ORF1a','ORF1b'];\n      for (var k in genes) {\n          try {\n            analysis_results[genes[k]] = await d3.json (\"https://raw.githubusercontent.com/veg/SARS-CoV-2/master/data/fasta/\"+use_this_date+\"/sequences.\" + genes[k] + \".json\");\n            if (! ('map' in analysis_results[genes[k]])) {\n                analysis_results[genes[k]]['map'] = _.range (analysis_results[genes[k]].sites); \n            }\n            /*_.each (analysis_results[genes[k]]['selection'], (site)=> {\n                _.each (site[\"labels\"], (info, branch) => {\n                    if (info[0].length > 1){ // mixed base\n                        //console.log (info[0]);\n                        site[\"labels\"][branch][0] = \"amb\";\n                    }\n                });\n            });*/\n            \n          } catch (e) {console.log (e);}\n      }\n      return analysis_results;\n    };\n  \n    let retrieve_all = async function (dates) {\n      let all_results = {};\n      for (var k in dates) {\n        all_results[dates[k]] = await retrieve (dates[k]);\n      }\n      return all_results;\n    }\n  \n    let raw_data =  retrieve_all(analysis_dates);\n    \n    \n    return raw_data;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":978,"value":"selection_data = [all_selection_data[use_date]]","pinned":false,"mode":"js","data":null,"name":null},{"id":960,"value":"analysis_dates = [\"20200503\", \"20200427\", \"20200418\",\"20200415\", \"20200410\",\"20200403\", \"20200330\",\"20200325\"];","pinned":false,"mode":"js","data":null,"name":null},{"id":241,"value":"summary = {\n  let prior_dates = [];\n  let support_format = d3.format (\".2g\");\n  \n  let tabulate_for_date = (selection_info) => {\n        let T = [];\n        let for_plotting = [];\n        let selectors = [];\n        let epitopes = {};\n\n        _.each (selection_info, (record, gene)=> {\n            _.each (record['selection'], (info, site) => {\n                let site_score = 0;\n                let genomic_site = record.map[+site]+1;\n                let ref_coord_start = _.find (gene_coordinates, (d)=> d[1] == gene)[0] + (genomic_site-1)*3;\n                let prc = for_plotting.length;\n                let plot_record = {'position' : ref_coord_start,\n                                   'gene' : gene,\n                                   'site_in_gene' : genomic_site};\n              \n                \n\n                let ref_coord = \"<a target = '_blank_' href = 'https://www.ncbi.nlm.nih.gov/nuccore/NC_045512.2?report=graph&tracks=[key:sequence_track,name:Sequence,display_name:Sequence,id:STD1,category:Sequence,annots:Sequence,ShowLabel:false,shown:true,order:1][key:gene_model_track,name:Genes,display_name:Genes,id:STD3,category:Genes,annots:Unnamed,Options:ShowAll,SNPs:true,CDSProductFeats:true,NtRuler:true,AaRuler:true,HighlightMode:2,shown:true,order:3]&mk=\"+ref_coord_start+\":\"+(ref_coord_start+2)+\"|\" + gene + genomic_site +\"&from=\"+ref_coord_start+\"&to=\"+(ref_coord_start+2)+\"'>\" + ref_coord_start + \"-\" + (ref_coord_start+2) + \"</a>\";\n                \n                let peptide_site = _.find (peptide_coordinates, (d)=> (genomic_site >= d[1] && genomic_site <= d[2] && d[3] == gene));\n                let site_record = {\n                    'site'  : gene + \" \" + genomic_site + (peptide_site ? \"<br>\" + peptide_site[0] + \" \" + (genomic_site - peptide_site[1] + 1) : \"\") + \"<br/>Genomic \" + ref_coord,\n                    'classification' : {'fel' : info['fel'] <= record.p , 'meme' : info['meme'] <= record.p, 'fraction' : info['meme-fraction'], 'kind' : info['kind'], 'branches' : info['meme-branches'] },\n                    'substitutions' : info['substitutions']\n                };\n               \n                if (peptide_site) {\n                  plot_record['peptide'] = peptide_site[0] + \" \" + (genomic_site - peptide_site[1] + 1);\n                }\n                if ((site_record['classification']['fel']||site_record['classification']['meme'])) {\n                    site_score += 1;\n                    if (info['kind'] == \"negative\") {\n                        plot_record.kind = \"Selection\";\n                        plot_record.type = \"Negative\";\n                        for_plotting.push (_.clone(plot_record));\n                    } else {\n                        plot_record.kind = \"Selection\";\n                        plot_record.type = \"Positive\";\n                        for_plotting.push (_.clone(plot_record));\n                    }\n                } else {\n                  plot_record.type = \"Neutral\"; \n                }\n                \n                  \n              \n                if (site_record['classification']['branches'] > 1) {\n                  site_score++; \n                  plot_record.kind = \"Multiple Clades\";\n                  for_plotting.push (_.clone(plot_record));\n\n                }\n              \n                if ('MAF' in record) {\n                  if (info.MAF >= record.MAF) {\n                       site_record['classification']['MAF'] = info.MAF;\n                       site_score++;\n                       plot_record.kind = \"Common Variant\";\n                       for_plotting.push (_.clone(plot_record));\n                  }\n                }\n              \n                if ('trend' in info) {\n                    if (info['trend'] >= 3) {\n                      site_record['classification']['trend'] = true;\n                      site_score++;\n                      plot_record.kind = \"Increasing frequency\";\n                      for_plotting.push (_.clone(plot_record));\n                    } \n                }\n              \n                if (gene == 'ORF1b') {\n                    ref_coord_start++;\n                }\n                if ((ref_coord_start-1) in comparative_annotation) {\n                    site_record['comp'] = comparative_annotation[ref_coord_start-1];\n                  \n                    if ('hla' in site_record['comp']) {\n                      let ec = _.size (site_record['comp']['hla']);\n                      if (ec) {\n                        site_record['classification']['hla'] = site_record['comp']['hla'];\n                        site_score++;\n                        plot_record.kind = \"Predicted CTL epitope\";\n                        for_plotting.push (_.clone(plot_record));\n                      }\n                    }\n                    if ('bFEL' in site_record['comp']) {\n                      \n                      if ( site_record['comp']['bFEL']['p'] <= record.p || site_record['comp']['bMEME']['p'] <= record.p || site_record['comp']['bCFEL']['p'] <= record.p) {\n                        if (site_record['comp']['bFEL']['p'] <= record.p) {\n                         site_record['classification']['betas'] = ((site_record['comp']['bFEL']['a'] < site_record['comp']['bFEL']['b']) ? \"Positively\" : \"Negatively\") + \" selected in the closely related bat/pangolin clade\";} else {site_record['classification']['betas'] = \"\";}\n                        if (site_record['comp']['bMEME']['p'] <= record.p) {\n                          if (site_record['classification']['betas'].length) {\n                              site_record['classification']['betas'] += \"\\n\"; \n                          }\n                          site_record['classification']['betas'] += \"Episodic positive selection in the closely related bat/pangolin clade\";\n                        }\n                        if (site_record['comp']['bCFEL']['p'] <= record.p) {\n                            if (site_record['classification']['betas'].length) {\n                              site_record['classification']['betas'] += \"\\n\"; \n                            }\n                            site_record['classification']['betas'] = site_record['comp']['bCFEL']['b-nCOV'] > site_record['comp']['bCFEL']['b'] ? \"Higher dN/dS in the closely related bat/pangolin clade\" : \"Lower dN/dS in the closely related bat/pangolin clade\";\n                        }\n                        \n                        site_score++;\n                        plot_record.kind = \"Selected in animals\";\n                        for_plotting.push (_.clone(plot_record));\n                      }\n                    }\n                }\n                             \n                let composition = _.sortBy(_.map (info['composition'], (v,k) => [k,v]), (d)=>-d[1]);\n                 if ('evolutionary_support' in info) {\n                    let support_by_residue = {};\n                    _.each (info['evolutionary_support'], (e)=>{\n                        if (! (e.aa in support_by_residue)) {\n                          support_by_residue[e.aa] = 0;\n                        }\n                        support_by_residue[e.aa] += e.support;\n                    });\n                    _.each (composition, (d, i) => {\n                        if (d[0] in support_by_residue) {\n                           d[2] = support_by_residue[d[0]];\n                        } else {\n                           d[2] = 0; \n                        }\n                    });\n                    if (_.every (composition, (d,i)=> (i == 0 || d[2] > 0 || d[1] == 1 || d[0].length > 1))) {\n                        site_record['classification']['evo_support'] = true;\n                        //site_score++;\n                    } else {\n                        site_record['classification']['evo_support'] = false;\n                        site_score++;\n                        plot_record.kind = \"Unexpected residues\";\n                        for_plotting.push (_.clone(plot_record));\n                    }\n                }\n\n\n              \n                let cov_url = \"http://cov-glue.cvr.gla.ac.uk/#/project/replacement/\";\n                if (peptide_site) {\n                    cov_url += peptide_site[0] + \":\" + composition[0][0] + \":\" + (genomic_site - peptide_site[1] + 1);\n                } else {\n                    cov_url += gene + \":\" + composition[0][0] + \":\" + genomic_site;\n                }\n                \n              \n                site_record ['composition'] = {\n                  'composition' : _.map (composition, (d,i)=>{\n                     let style_string = '';\n                     let support_text = '';\n                     if (d.length>2 && d[0].length == 1 && d[0] != '-') {\n                        if (d[2] > 0.1) {\n                            style_string = 'style=\"color:darkgreen\"';\n                            support_text = \"Very high evolutionary credibility\";\n                        } else {\n                            if (d[2] > 0.001) {\n                                style_string = 'style=\"color:#c2a90f\"';\n                                support_text = \"High evolutionary credibility\";\n                            } else {\n                              if (d[2] > 0.0) {\n                                style_string = 'style=\"color:#ff8c00\"';\n                                support_text = \"Medium evolutionary credibility\";\n                              } else {\n                                style_string = 'style=\"color:darkred\"';\n                                support_text = \"Low evolutionary credibility\";\n                              }\n                            }\n                        }\n                     }  \n                    \n                     return \"<span \" + style_string + \"title = '\" + support_text +\"'>\" + (d[0] == '-' ? '[-]' : d[0]) + \"<sub>\" + d[1] + \"</sub></span>\";\n                } ).join (\"\"), \n                  'variants' : site_record['variants'] = _.filter (intra_host, (d)=>d[0] == gene && d[1] == genomic_site && d[2]<1.0)}; \n              \n                if ('prime' in info) {\n                    site_record ['composition']['prime'] = info['prime'];\n                  \n                } \n                \n                if (site_record ['composition'].variants.length > 0) {\n                    site_record['classification']['variants'] = site_record ['composition'].variants.length;\n                    site_score++;\n                    plot_record.kind = \"Intra-host variants\";\n                    for_plotting.push (_.clone(plot_record));\n                }\n              \n                site_record['score'] = site_score;\n                for (let i = prc; i < for_plotting.length; i++) {\n                    for_plotting[i]['score'] = site_score;\n                }\n                \n                site_record['for_plot'] = _.clone(plot_record);\n                site_record['for_plot'].score = site_score;\n                T.push (site_record);\n                selectors.push ([gene, genomic_site, +site+1,site_score]);\n                epitopes [gene+\"/\"+genomic_site] = site_record['classification']['hla'];\n                \n            });\n         });\n        return {'table' : _.sortBy (T,(d)=>-d.score), 'selectors' : _.sortBy (selectors,(d)=>-d[3]), 'plot' : for_plotting, 'epitopes' : epitopes};\n    };\n  \n   let current_data = tabulate_for_date (selection_data[0]); \n   let all_dates_before_this = _.sortBy (_.filter (analysis_dates, (d)=> d < use_date));\n   if (all_dates_before_this.length > 0) {\n       let prior_summaries = {};\n       _.each (all_dates_before_this, (d)=>{\n          prior_summaries[d] = tabulate_for_date (all_selection_data[d]);\n       });\n       \n       _.each (current_data.table, (row)=>{\n            let previously_found = [];\n            _.each (prior_summaries, (d,v) => {\n                if (_.find (d.table, (r)=>r.gene == row.gene && r.site == row.site)) {\n                  previously_found.push(v);\n                }\n            });\n            row.prior = [previously_found , all_dates_before_this.length];\n            if (previously_found.length==0) {\n                let new_flag = row.for_plot;\n                new_flag.kind = \"New\";\n                current_data.plot.push (new_flag);\n            }\n       });\n   }\n    \n  return    current_data;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":1842,"value":"detailed_epitopes = {\n  let site_info = render_site.split (',')[0] + \"/\" + render_site.split (',')[1];\n  let epitope_list = summary.epitopes[ site_info];\n  if (epitope_list) {\n    return _.map (epitope_list, (p,k)=> {\n        return {\n            'epitope'  : [k, _.keys (p) [0], _.values(p)[0]],\n            'alleles' : campbell_epitopes [k]\n        }})\n  } \n  return [{'epitope' : \"No overlapping epitopes found\"}]\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":122,"value":"N_cutoff = 10","pinned":false,"mode":"js","data":null,"name":null},{"id":367,"value":"tree = {\n  var t = new phylotree.phylotree(selection_data[0][render_site.split (',')[0]]['tree']);\n  if ('bl' in selection_data[0][render_site.split (',')[0]]) {\n    t.usebl =  selection_data[0][render_site.split (',')[0]]['bl'];\n  }\n  return t;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":458,"value":"node_labels = selection_data[0][render_site.split (',')[0]\n                              ]['selection'][render_site.split (',')[2]-1]['labels'];","pinned":false,"mode":"js","data":null,"name":null},{"id":676,"value":"timing = {\n    var raw_timing = selection_data[0][render_site.split (',')[0]\n                              ]['selection'][render_site.split (',')[2]-1]['timing'];\n  \n    \n    let time_parser = d3.timeParse (\"%Y%m%d\");\n    let rows = [];\n    let do_aggregate = false;\n  \n    _.each (raw_timing, (dates, residue) => {\n        _.each (dates, (count, date_value) => {\n            if (residue != '-') {\n\n              if (_.isArray (count)) {\n                  do_aggregate = true;\n                  let row = {'residue' : residue, \n                             'count' : count[3],\n                             'sample' : time_parser (count[0])\n                            };\n                  rows.push (row);\n              } else {\n                   let row = {'residue' : residue, \n                             'count' : count,\n                             'sample' : time_parser (date_value)\n                            };\n                  rows.push (row);\n                }\n            }\n        })\n    });\n  \n    if (do_aggregate) {\n      let by_date = _.groupBy (rows, (d)=>d.sample);\n      let aggregated = [];\n      _.each (by_date, (v,d)=> {\n           _.each (_.groupBy (v, (v)=>v.residue), (counts, r)=> {\n              aggregated.push ({'residue' : r, 'sample' : d, 'count' : d3.sum (counts, (d)=>d.count)});\n                           \n          });\n      });\n      return aggregated;\n     }\n    \n    return rows;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":727,"value":"intra_host = {\n    let raw_variants = await d3.tsv (\"https://raw.githubusercontent.com/galaxyproject/SARS-CoV-2/master/genomics/4-Variation/variant_list.05.tsv\", d3.autoType);\n /*\n  Sample\tCHROM\tPOS\tREF\tALT\tDP\tAF\tSB\tDP4\tIMPACT\tFUNCLASS\tEFFECT\tGENE\tCODON\ttype\n \"*/\n    return _.map (_.filter (raw_variants, (v)=>v.POS >= gene_coordinates[0][0] && v.Sample != 'SRR11494664'), (v)=> {\n        let gene = _.find (gene_coordinates, (d,i)=> i == gene_coordinates.length -1 || gene_coordinates[i][0] <= v.POS && gene_coordinates[i+1][0] > v.POS);\n        \n        let offset = 0;\n        if (gene[1] == \"ORF1b\") {\n          offset = 3; \n        }\n        return [gene[1], Math.floor((v.POS-gene[0]+offset+1)/3),v.AF,v.POS,v[\"REF\"] + \":\" + v[\"ALT\"], v['EFFECT'], v['Sample']];\n    });\n    \n}","pinned":false,"mode":"js","data":null,"name":null},{"id":730,"value":"gene_coordinates = _.map ([\n  [266,'ORF1a',13483],\n  [13471, 'ORF1b',21555],\n  [21563,'S',25385],\n  [25393,'ORF3a',26220],\n  [26523,'M',27191],\n  [27202,'ORF6',27387],\n  [27394,'ORF7a',27759],\n  [27894,'ORF8',28259],\n  [28274,'N',29533],\n  //[29558,'ORF10',29674]\n], (d,i)=>{\n  d.push (i);\n  return d;\n});\n/*[[265,13482, 'ORF1a', 0],\n#  [13467,21554, 'ORF1b',-1],\n#  [21562,25383,'S',0],\n#  [25392,26219,'ORF3a',0],\n#  [26244,26471,'E',0],\n#  [26522,27190,'M',0],\n#  [27201,27386,'ORF6',0],\n#  [27393,27758,'ORF7a',0],\n#  [27893,28258,'ORF8',0],\n#  [28273,29532,'N',0],\n#  [29557,29673,'ORF10',0]\n#*/","pinned":false,"mode":"js","data":null,"name":null},{"id":1148,"value":"variation_data = {\n    let variation_records = [];\n    _.each (all_selection_data, (gene_info, date) => {\n        let parsed_date = date_reader (date);\n        _.each (gene_info, (fields, gene) => {\n            variation_records.push ({'date' : parsed_date, 'gene' : gene, 'kind' : 'any', 'fraction' : fields['any variation'] / fields['sites'], 'seqs' : fields['total sequences']});\n            variation_records.push ({'date' : parsed_date, 'gene' : gene, 'kind' : '≥2x', 'fraction' : fields['all variant sites'].length / fields['sites']});\n            variation_records.push ({'date' : parsed_date, 'gene' : gene, 'kind' : '≥2x amino-acid', 'fraction' : fields['aminoacid variant sites'].length / fields['sites']});\n          variation_records.push ({'date' : parsed_date, 'gene' : gene, 'kind' : 'Putatively Selected', 'fraction' : _.size(fields['selection']) / fields['sites']});\n        });\n      \n    });\n    return variation_records;\n}\n\n","pinned":false,"mode":"js","data":null,"name":null},{"id":1168,"value":"peptide_coordinates = {\n  let absolute_coordinates = [\n        // 1 based; name; from; to; parent ORF\n        ['leader protein', 266, 805, 'ORF1a'],\n        ['nsp2',  806, 2719, 'ORF1a'],\n        ['nsp3',  2720, 8554, 'ORF1a'],\n        ['nsp4', 8555, 10054, 'ORF1a'],\n        ['3C-like proteinase', 10055, 10972,'ORF1a'],\n        ['nsp6', 10973, 11842, 'ORF1a'],\n        ['nsp7', 11843, 12091, 'ORF1a'],\n        ['nsp8', 12092, 12685, 'ORF1a'],\n        ['nsp9', 12686, 13024, 'ORF1a'],\n        ['nsp10', 13025, 13441, 'ORF1a'],\n        ['RdRp', 13441, 16236, 'ORF1b'],\n        ['helicase', 16237, 18039, 'ORF1b'],\n        [\"3'-to-5' exonuclease\",18040, 19620, 'ORF1b'],\n        ['endoRNAse', 19621, 20658, 'ORF1b'],\n        [\"2'-O-ribose methyltransferase\", 20659, 21552, 'ORF1b'],\n    \n  ];\n  return _.map (absolute_coordinates, (d)=> d[3] == 'ORF1a' ? [d[0], (d[1]-266)/3 + 1, (d[2]-265)/3, d[3]] : [d[0], (d[1]-13468)/3, (d[2]-13467)/3-1, d[3]])\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":1341,"value":"world = d3.json(\"https://unpkg.com/world-atlas@1/world/110m.json\")","pinned":false,"mode":"js","data":null,"name":null},{"id":1345,"value":"country_codes = d3.json(\"https://raw.githubusercontent.com/lukes/ISO-3166-Countries-with-Regional-Codes/master/slim-3/slim-3.json\")","pinned":false,"mode":"js","data":null,"name":null},{"id":1348,"value":"country_equiv = d3.json (\"https://raw.githubusercontent.com/mledoze/countries/master/dist/countries.json\")","pinned":false,"mode":"js","data":null,"name":null},{"id":1355,"value":"current_site_info = selection_data[0][render_site.split (',')[0]\n                              ]['selection'][render_site.split (',')[2]-1]","pinned":false,"mode":"js","data":null,"name":null},{"id":1373,"value":"subs_count = {\n  let residue = use_residue;\n  let raw_counts = current_site_info[\"timing\"];\n  const parser =  d3.timeParse (\"%Y%m%d\");\n  let counts_by_country = {};\n  const resolved_name = (name)=> {\n    if (name == \"England\") {\n      name = \"United Kingdom\"; \n    }\n    let c = _.find (country_equiv, (c)=>(c.name.common == name || c.name.official == name || c.cca3 == name || c.altSpellings.find ((e)=>e==name)!=undefined));\n    if (c) {\n      return c.name.common; \n    }\n    return \"N/A\";\n  };\n  _.each (_.flatten(_.map (raw_counts, (residue)=>residue)), (d) => {\n    let td = parser (d[0]);\n    if (td >= date_range.range[0] && td <= date_range.range[1]) {\n      const cn = resolved_name (d[1]);\n      if (cn in counts_by_country) {\n        counts_by_country [cn] += d[3]; \n      } else {\n        counts_by_country [cn] = d[3];       \n      }\n    }\n  });\n  let residue_by_country = {};\n  _.each (raw_counts[residue],(d) => {\n    let td = parser (d[0]);\n    if (td >= date_range.range[0] && td <= date_range.range[1]) {\n      const cn = resolved_name (d[1]);\n      if (cn in residue_by_country) {\n        residue_by_country [cn] += d[3]; \n      } else {\n        residue_by_country [cn] = d[3];       \n      }\n    }\n  });\n  let fractions = _.map (counts_by_country, (d,c)=> {\n      let cc = 0;\n      if (c in residue_by_country) {\n        cc = residue_by_country[c];\n      };\n      return [c,cc/d,cc,d]\n        \n  });\n  \n  return _.map (fractions, (d) => {\n    let name = d[0];\n    let country = _.find (country_equiv, (c)=>(c.name.common == name || c.name.official == name || c.cca3 == name || c.altSpellings.find ((e)=>e==name)!=undefined));\n    if (country) {\n      return {'id' : country.ccn3, 'name' : name, 'rate' : d[1], 'total' : d[3], 'variant' : d[2]};\n    }\n    return d;\n  });\n  \n}","pinned":false,"mode":"js","data":null,"name":null},{"id":1351,"value":"available_residues = _.map (_.sortBy (_.map (current_site_info[\"timing\"], (d,v)=>[v,current_site_info.composition[v]]), d=>-d[1]), d=>d[0])","pinned":false,"mode":"js","data":null,"name":null},{"id":1366,"value":"sample_count = {\n  let raw_counts = current_site_info[\"timing\"];\n  let residue_by_date = [];\n  const parser =  d3.timeParse (\"%Y%m%d\");\n  _.each (raw_counts[use_residue],(d) => {\n    let td = parser(d[0]);\n    residue_by_date.push ({'date' : td});\n  });\n  return residue_by_date;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":1791,"value":"comparative_annotation = await d3.json (\"https://raw.githubusercontent.com/veg/SARS-CoV-2/master/data/comparative-annotation.json\")","pinned":false,"mode":"js","data":null,"name":null},{"id":1836,"value":"campbell_epitopes = await d3.json (\"https://raw.githubusercontent.com/veg/SARS-CoV-2/master/data/ctl/epitopes.json\")","pinned":false,"mode":"js","data":null,"name":null},{"id":10,"value":"md`### Dependencies`","pinned":false,"mode":"js","data":null,"name":null},{"id":17,"value":"d3=require(\"d3\")","pinned":false,"mode":"js","data":null,"name":null},{"id":20,"value":"_ = require('lodash')","pinned":false,"mode":"js","data":null,"name":null},{"id":22,"value":"vegalite = require(\"vega-embed@6\")","pinned":false,"mode":"js","data":null,"name":null},{"id":227,"value":"import { table } from \"@gampleman/table\"","pinned":false,"mode":"js","data":null,"name":null},{"id":314,"value":"render_property =  (value) => {\n    let tag = value[0].split (' ');\n    if (tag.length > 2) {\n      tag = tag.slice (2).join (' ');\n    } else {\n      tag = value[0]; \n    }\n    if (value[2] > 0) {\n      return '<span><i class=\"fas fa-hand-paper\"></i>' + tag + '</span>';\n    }   \n    if (value[2] < 0) {\n      return '<span><i class=\"fas fa-exchange-alt\"></i>' + tag + '</span>';\n    }     \n    return tag;\n  }","pinned":false,"mode":"js","data":null,"name":null},{"id":334,"value":"import {select, slider, checkbox} from \"@jashkenas/inputs\"","pinned":false,"mode":"js","data":null,"name":null},{"id":360,"value":"resolve(\"phylotree@0.1/phylotree.css\")","pinned":false,"mode":"js","data":null,"name":null},{"id":364,"value":"phylotree=require (\"phylotree@1.0.0-alpha.26\")","pinned":false,"mode":"js","data":null,"name":null},{"id":1375,"value":"import {rangeSlider} from \"@bumbeishvili/utils\"","pinned":false,"mode":"js","data":null,"name":null},{"id":1593,"value":"md`#### CSS`","pinned":false,"mode":"js","data":null,"name":null},{"id":310,"value":"html`<link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.5.0/css/all.css\" integrity=\"sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU\" crossorigin=\"anonymous\">`","pinned":false,"mode":"js","data":null,"name":null},{"id":1591,"value":"stylesheet = html`<link rel='stylesheet'\n  href='https://unpkg.com/phylotree@alpha/dist/phylotree.css' />`","pinned":false,"mode":"js","data":null,"name":null}],"resolutions":[],"schedule":null,"last_view_time":null}