extensions/net.sf.basedb.reggie/trunk/resources/analysis/check_data_files.js

Code
Comments
Other
Rev Date Author Line
2641 09 Sep 14 nicklas 1 var Check = function()
2641 09 Sep 14 nicklas 2 {
2641 09 Sep 14 nicklas 3   var check = {};
2656 11 Sep 14 nicklas 4   var debug = 0;
2641 09 Sep 14 nicklas 5   
2641 09 Sep 14 nicklas 6   var currentLaneNo = 1;
2642 09 Sep 14 nicklas 7   var expectedCycles = 0;
5862 11 Mar 20 nicklas 8   var expectedTiles = -1;
5862 11 Mar 20 nicklas 9   var expectedTilesAlt = -1;
2645 10 Sep 14 nicklas 10   var readString
2642 09 Sep 14 nicklas 11   var seqRun;
2641 09 Sep 14 nicklas 12   
2641 09 Sep 14 nicklas 13   check.initPage = function()
2641 09 Sep 14 nicklas 14   {
2641 09 Sep 14 nicklas 15     var frm = document.forms['reggie'];
7031 09 Feb 23 nicklas 16     Events.addEventHandler('timeout', 'keypress', Events.integerOnly);
2641 09 Sep 14 nicklas 17     Buttons.addClickHandler('close', App.closeWindow);
2641 09 Sep 14 nicklas 18     
2641 09 Sep 14 nicklas 19     var url = '../SequencingRun.servlet?ID='+App.getSessionId();
2641 09 Sep 14 nicklas 20     url += '&cmd=GetSeqRunInfoForDataCheck';
2641 09 Sep 14 nicklas 21     url += '&seqrun='+Data.get('page-data', 'seqrun-id');
2641 09 Sep 14 nicklas 22     Wizard.asyncJsonRequest(url, check.seqRunLoaded);
2641 09 Sep 14 nicklas 23     
6735 09 May 22 nicklas 24     // Load clusters
6661 01 Apr 22 nicklas 25     var url = '../OpenGrid.servlet?ID='+App.getSessionId() + '&cmd=GetHostInfo&config=check-illumina-directory';
2641 09 Sep 14 nicklas 26     Doc.addClass('clusters', 'list-loading');
2641 09 Sep 14 nicklas 27     frm.clusters[0] = new Option('loading...');
2641 09 Sep 14 nicklas 28     Wizard.asyncJsonRequest(url, check.clustersLoaded);
2641 09 Sep 14 nicklas 29   }
2641 09 Sep 14 nicklas 30   
2641 09 Sep 14 nicklas 31   
2641 09 Sep 14 nicklas 32   check.seqRunLoaded = function(response)
2641 09 Sep 14 nicklas 33   {
2641 09 Sep 14 nicklas 34     var frm = document.forms['reggie'];
2642 09 Sep 14 nicklas 35     seqRun = response.seqRun;
2641 09 Sep 14 nicklas 36     
2641 09 Sep 14 nicklas 37     Doc.element('sequencingrun').innerHTML = Strings.encodeTags(seqRun.name);
2641 09 Sep 14 nicklas 38     Doc.element('flowCellId').innerHTML = Strings.encodeTags(seqRun.flowCell.FlowCellID);
2641 09 Sep 14 nicklas 39     Doc.element('dataFilesFolder').innerHTML = Strings.encodeTags(seqRun.DataFilesFolder);
2641 09 Sep 14 nicklas 40     Doc.element('sequencingCycles').innerHTML = Strings.encodeTags(seqRun.SequencingCycles);
5478 10 Jun 19 nicklas 41     Doc.element('flowCellType').innerHTML = Strings.encodeTags(seqRun.flowCell.FlowCellType) +'; ' + Strings.encodeTags(seqRun.pipeline);
2642 09 Sep 14 nicklas 42     if (!frm.readString.value)
2642 09 Sep 14 nicklas 43     {
2642 09 Sep 14 nicklas 44       frm.readString.value = seqRun.ReadString;
2642 09 Sep 14 nicklas 45     }
2641 09 Sep 14 nicklas 46     
5862 11 Mar 20 nicklas 47     if (seqRun.flowCell.FlowCellType == 'NovaSeq')
5862 11 Mar 20 nicklas 48     {
5862 11 Mar 20 nicklas 49       Doc.element('genseq').disabled = true;
5862 11 Mar 20 nicklas 50     }
5862 11 Mar 20 nicklas 51     
2910 10 Nov 14 nicklas 52     var omitLanes = Data.json('page-data', 'omit-lanes');
2910 10 Nov 14 nicklas 53     
2641 09 Sep 14 nicklas 54     var html = '';
2642 09 Sep 14 nicklas 55     var numLanes = seqRun.flowCell.numLanes;
2641 09 Sep 14 nicklas 56     for (var laneNo = 1; laneNo <= numLanes; laneNo++)
2641 09 Sep 14 nicklas 57     {
2910 10 Nov 14 nicklas 58       var checked = omitLanes.indexOf(laneNo) == -1 ? 'checked' : '';
2910 10 Nov 14 nicklas 59       html += '<tr><th class="subprompt">Lane ' + laneNo + '<input type="checkbox" name="lane.'+laneNo+'" '+checked+'></td>';
2641 09 Sep 14 nicklas 60       html += '<td id="lane.'+laneNo+'.status" class="status"></td>';
2641 09 Sep 14 nicklas 61       html += '<td><span id="lane.'+laneNo+'.message" class="message" data-display="block"></span></td>';
2641 09 Sep 14 nicklas 62       html += '</tr>';
2641 09 Sep 14 nicklas 63     }
2641 09 Sep 14 nicklas 64     
2641 09 Sep 14 nicklas 65     Doc.element('lanes-section').innerHTML = html;
2641 09 Sep 14 nicklas 66   }
2641 09 Sep 14 nicklas 67
2641 09 Sep 14 nicklas 68   check.clustersLoaded = function(response)
2641 09 Sep 14 nicklas 69   {
2641 09 Sep 14 nicklas 70     Doc.removeClass('clusters', 'list-loading');
2641 09 Sep 14 nicklas 71     var frm = document.forms['reggie'];
4306 17 Jan 17 nicklas 72     var clusters = response.hosts;
2641 09 Sep 14 nicklas 73     frm.clusters.length = 0;
2641 09 Sep 14 nicklas 74     for (var i = 0; i < clusters.length; i++)
2641 09 Sep 14 nicklas 75     {
2641 09 Sep 14 nicklas 76       var cl = clusters[i];
4306 17 Jan 17 nicklas 77       cl.nodes = [];
4306 17 Jan 17 nicklas 78       for (var n = 0; n < cl.config.nodes.length; n++)
2890 03 Nov 14 nicklas 79       {
4306 17 Jan 17 nicklas 80         var node = cl.config.nodes[n];
4306 17 Jan 17 nicklas 81         var option = new Option(node.name+'@'+cl.connection.name, node.name+'@'+cl.id);
2890 03 Nov 14 nicklas 82         option.cluster = cl;
2890 03 Nov 14 nicklas 83         option.node = node;
2890 03 Nov 14 nicklas 84         frm.clusters[frm.clusters.length] = option;
2890 03 Nov 14 nicklas 85       }
4306 17 Jan 17 nicklas 86       var option = new Option(cl.connection.name, cl.id);
2641 09 Sep 14 nicklas 87       option.cluster = cl;
2641 09 Sep 14 nicklas 88       frm.clusters[frm.clusters.length] = option;
2641 09 Sep 14 nicklas 89     }
2641 09 Sep 14 nicklas 90     if (frm.clusters.length == 0)
2641 09 Sep 14 nicklas 91     {
6735 09 May 22 nicklas 92       Wizard.setFatalError('No available clusters');
2641 09 Sep 14 nicklas 93     }
2641 09 Sep 14 nicklas 94     else
2641 09 Sep 14 nicklas 95     {
2641 09 Sep 14 nicklas 96       Doc.show('check');
2641 09 Sep 14 nicklas 97       Buttons.addClickHandler('check', check.performCheck);
2641 09 Sep 14 nicklas 98     }
2641 09 Sep 14 nicklas 99   }
2641 09 Sep 14 nicklas 100
2641 09 Sep 14 nicklas 101   
2641 09 Sep 14 nicklas 102   check.performCheck = function()
2641 09 Sep 14 nicklas 103   {
2641 09 Sep 14 nicklas 104     var frm = document.forms['reggie'];
2641 09 Sep 14 nicklas 105
2645 10 Sep 14 nicklas 106     readString = frm.readString.value;
5530 27 Jun 19 nicklas 107     if (!readString.match(/^(\d+[TBMS])+$/))
2641 09 Sep 14 nicklas 108     {
2641 09 Sep 14 nicklas 109       Forms.showNotification(frm.readString, 'Not a valid read string', null, 'pointer-below');
2641 09 Sep 14 nicklas 110       return;
2641 09 Sep 14 nicklas 111     }
2641 09 Sep 14 nicklas 112     
2645 10 Sep 14 nicklas 113     // Reset data
2641 09 Sep 14 nicklas 114     Doc.addClass('check', 'disabled');
2645 10 Sep 14 nicklas 115     currentLaneNo = 1;
5862 11 Mar 20 nicklas 116     if (seqRun.flowCell.FlowCellType == 'NextSeq')
5862 11 Mar 20 nicklas 117     {
5862 11 Mar 20 nicklas 118       expectedTiles = 216;
5862 11 Mar 20 nicklas 119     }
5862 11 Mar 20 nicklas 120     else if (seqRun.flowCell.FlowCellType == 'HiSeq')
5862 11 Mar 20 nicklas 121     {
5862 11 Mar 20 nicklas 122       expectedTiles = 96;  // 8-lane HiSeq has 96
5862 11 Mar 20 nicklas 123       expectedTilesAlt = 64; // 2-lane HiSeq has 64
5862 11 Mar 20 nicklas 124     }
2645 10 Sep 14 nicklas 125     expectedCycles = 0;
5530 27 Jun 19 nicklas 126     var reads = readString.match(/\d+(?=T|B|M)/g);
2645 10 Sep 14 nicklas 127     for (var i = 0; i < reads.length; i++)
2642 09 Sep 14 nicklas 128     {
2645 10 Sep 14 nicklas 129       expectedCycles += parseInt(reads[i]);
2642 09 Sep 14 nicklas 130     }
2641 09 Sep 14 nicklas 131     
2645 10 Sep 14 nicklas 132     check.runNextCheck();
2645 10 Sep 14 nicklas 133   }
2645 10 Sep 14 nicklas 134
2645 10 Sep 14 nicklas 135   
2645 10 Sep 14 nicklas 136   check.runNextCheck = function()
2645 10 Sep 14 nicklas 137   {
2645 10 Sep 14 nicklas 138     var frm = document.forms['reggie'];
2645 10 Sep 14 nicklas 139
2910 10 Nov 14 nicklas 140     if (!frm['lane.'+currentLaneNo].checked)
2910 10 Nov 14 nicklas 141     {
2910 10 Nov 14 nicklas 142       setTimeout(check.checkPerformed, 100);
2910 10 Nov 14 nicklas 143       return;
2910 10 Nov 14 nicklas 144     }
2910 10 Nov 14 nicklas 145     
2890 03 Nov 14 nicklas 146     var selected = frm.clusters[frm.clusters.selectedIndex];
2890 03 Nov 14 nicklas 147     var cluster = selected.cluster;
2890 03 Nov 14 nicklas 148     var node = selected.node;
2890 03 Nov 14 nicklas 149     
2641 09 Sep 14 nicklas 150     var url = '../SequencingRun.servlet?ID='+App.getSessionId();
2641 09 Sep 14 nicklas 151     url += '&cmd=CheckIlluminaDataFiles';
2641 09 Sep 14 nicklas 152     url += '&seqrun='+Data.get('page-data', 'seqrun-id');
2645 10 Sep 14 nicklas 153     url += '&readString='+encodeURIComponent(readString);
2890 03 Nov 14 nicklas 154     url += '&cluster='+encodeURIComponent(cluster.id);
2890 03 Nov 14 nicklas 155     if (node)
2890 03 Nov 14 nicklas 156     {
4306 17 Jan 17 nicklas 157       url += '&node='+encodeURIComponent(node.name);
2890 03 Nov 14 nicklas 158     }
2641 09 Sep 14 nicklas 159     url += '&lane='+currentLaneNo;
7031 09 Feb 23 nicklas 160     url += '&timeout='+encodeURIComponent(frm.timeout.value);
2641 09 Sep 14 nicklas 161     
2641 09 Sep 14 nicklas 162     Wizard.setInputStatus('lane.'+currentLaneNo, 'checking', 'Checking...');
2641 09 Sep 14 nicklas 163     Wizard.asyncJsonRequest(url, check.checkPerformed);
2641 09 Sep 14 nicklas 164   }
2641 09 Sep 14 nicklas 165   
2641 09 Sep 14 nicklas 166   check.checkPerformed = function(response)
2641 09 Sep 14 nicklas 167   {
2642 09 Sep 14 nicklas 168     var frm = document.forms['reggie'];
2910 10 Nov 14 nicklas 169     if (!response)
2910 10 Nov 14 nicklas 170     {
2910 10 Nov 14 nicklas 171       Wizard.setInputStatus('lane.'+currentLaneNo, '', 'Skipped');
2910 10 Nov 14 nicklas 172     }
2910 10 Nov 14 nicklas 173     else
2910 10 Nov 14 nicklas 174     {
2910 10 Nov 14 nicklas 175       var exitStatus = response.exitStatus;
6678 19 Apr 22 nicklas 176       check.setPicardStatus(currentLaneNo, exitStatus, response.stdout || response.stderr, response.stderr);
2910 10 Nov 14 nicklas 177     }
2910 10 Nov 14 nicklas 178
2910 10 Nov 14 nicklas 179     if (currentLaneNo < seqRun.flowCell.numLanes) 
2910 10 Nov 14 nicklas 180     {
2910 10 Nov 14 nicklas 181       currentLaneNo++;
2910 10 Nov 14 nicklas 182       check.runNextCheck();
2910 10 Nov 14 nicklas 183     }
2910 10 Nov 14 nicklas 184     else
2910 10 Nov 14 nicklas 185     {
2910 10 Nov 14 nicklas 186       Doc.removeClass('check', 'disabled');
2910 10 Nov 14 nicklas 187     }
2910 10 Nov 14 nicklas 188   }
2910 10 Nov 14 nicklas 189   
2910 10 Nov 14 nicklas 190   check.setPicardStatus = function(laneNo, exitStatus, stdout, stderr)
2910 10 Nov 14 nicklas 191   {
2910 10 Nov 14 nicklas 192     var status = exitStatus == 0 ? 'valid' : 'invalid';
2910 10 Nov 14 nicklas 193     var msg = '';
2910 10 Nov 14 nicklas 194
2641 09 Sep 14 nicklas 195     if (exitStatus == 0)
2641 09 Sep 14 nicklas 196     {
2642 09 Sep 14 nicklas 197       var cycles;
2642 09 Sep 14 nicklas 198       var tiles;
2910 10 Nov 14 nicklas 199       var lines = stdout.split(/\n/);
2910 10 Nov 14 nicklas 200       for (var lineNo = 0; lineNo < lines.length; lineNo++)
2642 09 Sep 14 nicklas 201       {
2910 10 Nov 14 nicklas 202         var line = lines[lineNo];
2642 09 Sep 14 nicklas 203         var c = line.indexOf('Expected cycles');
2642 09 Sep 14 nicklas 204         if (c > 0)
2642 09 Sep 14 nicklas 205         {
2642 09 Sep 14 nicklas 206           cycles = line.substring(c).match(/\d+/g);
2642 09 Sep 14 nicklas 207         }
2642 09 Sep 14 nicklas 208         var t = line.indexOf('Expected tiles');
2642 09 Sep 14 nicklas 209         if (t > 0)
2642 09 Sep 14 nicklas 210         {
2642 09 Sep 14 nicklas 211           tiles = line.substring(t).match(/\d+/g);
2642 09 Sep 14 nicklas 212         }
2642 09 Sep 14 nicklas 213       }
2642 09 Sep 14 nicklas 214       
2910 10 Nov 14 nicklas 215       msg = (cycles == null ? 'unknown' : cycles.length) + ' cycles';
2642 09 Sep 14 nicklas 216       if (cycles == null || cycles.length != expectedCycles)
2642 09 Sep 14 nicklas 217       {
2642 09 Sep 14 nicklas 218         msg += ' (expected ' + expectedCycles + ')';
2642 09 Sep 14 nicklas 219         status = 'warning';
2642 09 Sep 14 nicklas 220       }
2642 09 Sep 14 nicklas 221       
5862 11 Mar 20 nicklas 222       if (expectedTiles > 0)
2642 09 Sep 14 nicklas 223       {
5862 11 Mar 20 nicklas 224         msg += '; ' + (tiles == null ? 'unknown' : tiles.length) + ' tiles';
5862 11 Mar 20 nicklas 225         if (tiles == null || (tiles.length != expectedTiles && tiles.length != expectedTilesAlt))
5862 11 Mar 20 nicklas 226         {
5862 11 Mar 20 nicklas 227           msg += ' (expected ' + expectedTiles;
5862 11 Mar 20 nicklas 228           if (expectedTiles != expectedTilesAlt) msg += ' or ' + expectedTilesAlt;
5862 11 Mar 20 nicklas 229           msg += ')';
5862 11 Mar 20 nicklas 230           status = 'warning';
5862 11 Mar 20 nicklas 231         }
2642 09 Sep 14 nicklas 232       }
2641 09 Sep 14 nicklas 233     }
2641 09 Sep 14 nicklas 234     else
2641 09 Sep 14 nicklas 235     {
5531 27 Jun 19 nicklas 236       msg = check.extractPicardErrorMessage(stderr || stdout);
2641 09 Sep 14 nicklas 237     }
2920 11 Nov 14 nicklas 238     
2910 10 Nov 14 nicklas 239     Wizard.setInputStatus('lane.'+laneNo, status, msg);
2910 10 Nov 14 nicklas 240   }
2910 10 Nov 14 nicklas 241
5531 27 Jun 19 nicklas 242   // Strings that appear in picard output that is not related to any error
5531 27 Jun 19 nicklas 243   var PICARD_OK_STRINGS = ['Checking lane', 'Expected cycles', 'Expected tiles', 'Loading lib'];
2641 09 Sep 14 nicklas 244   
5531 27 Jun 19 nicklas 245   /**
5531 27 Jun 19 nicklas 246     Try to extract a "good" error message from the output from picard.
5531 27 Jun 19 nicklas 247     We loop over the output backwards since error messages are most likely
5531 27 Jun 19 nicklas 248     to be at the end. Each line is also checked if it contains text indicating
5531 27 Jun 19 nicklas 249     that it comes from an informational message (PICARD_OK_STRINGS). Finally,
5531 27 Jun 19 nicklas 250     we split the line by \t and if there is at least 4 columns we skip the
5531 27 Jun 19 nicklas 251     first two (since they contain 'INFO' and a timestamp).
5531 27 Jun 19 nicklas 252   */
5531 27 Jun 19 nicklas 253   check.extractPicardErrorMessage = function(stdout)
5531 27 Jun 19 nicklas 254   {
5862 11 Mar 20 nicklas 255     App.debug(stdout);
5531 27 Jun 19 nicklas 256     var lines = stdout.split(/\n/);
5531 27 Jun 19 nicklas 257     var errorLines = [];
5862 11 Mar 20 nicklas 258     var stackTraceLines = [];
5531 27 Jun 19 nicklas 259     for (var lineNo = lines.length - 1; lineNo >= 0; lineNo--)
5531 27 Jun 19 nicklas 260     {
5531 27 Jun 19 nicklas 261       var line = lines[lineNo];
5531 27 Jun 19 nicklas 262       if (!line) continue;
5531 27 Jun 19 nicklas 263       
5531 27 Jun 19 nicklas 264       var lineIsOk = false;
5531 27 Jun 19 nicklas 265       for (var i = 0; i < PICARD_OK_STRINGS.length; i++)
5531 27 Jun 19 nicklas 266       {
5531 27 Jun 19 nicklas 267         if (line.indexOf(PICARD_OK_STRINGS[i]) > 0) 
5531 27 Jun 19 nicklas 268         {
5531 27 Jun 19 nicklas 269           lineIsOk = true;
5531 27 Jun 19 nicklas 270           break;
5531 27 Jun 19 nicklas 271         }
5531 27 Jun 19 nicklas 272       }
5531 27 Jun 19 nicklas 273       
5531 27 Jun 19 nicklas 274       if (!lineIsOk) 
5531 27 Jun 19 nicklas 275       {
5862 11 Mar 20 nicklas 276         if (line.indexOf('at picard.') > 0)
5531 27 Jun 19 nicklas 277         {
5862 11 Mar 20 nicklas 278           // Line from a stacktrace -- we need to revert the order
5862 11 Mar 20 nicklas 279           stackTraceLines[stackTraceLines.length] = line;
5531 27 Jun 19 nicklas 280         }
5862 11 Mar 20 nicklas 281         else
5862 11 Mar 20 nicklas 282         {
5862 11 Mar 20 nicklas 283           var cols = line.split('\t');
5862 11 Mar 20 nicklas 284           if (cols.length > 3 && cols[0]=='INFO') 
5862 11 Mar 20 nicklas 285           {
5862 11 Mar 20 nicklas 286             line = cols.slice(2).join('\t');
5862 11 Mar 20 nicklas 287           }
5862 11 Mar 20 nicklas 288           errorLines[errorLines.length] = line;
5862 11 Mar 20 nicklas 289         }
5531 27 Jun 19 nicklas 290       }
5531 27 Jun 19 nicklas 291     }
5862 11 Mar 20 nicklas 292     
5862 11 Mar 20 nicklas 293     if (stackTraceLines.length > 0)
5862 11 Mar 20 nicklas 294     {
5862 11 Mar 20 nicklas 295       errorLines = errorLines.concat(stackTraceLines.reverse());
5862 11 Mar 20 nicklas 296     }
5862 11 Mar 20 nicklas 297     
5531 27 Jun 19 nicklas 298     return errorLines.join('\n');
5531 27 Jun 19 nicklas 299   }
5531 27 Jun 19 nicklas 300   
2641 09 Sep 14 nicklas 301   return check;
2641 09 Sep 14 nicklas 302 }();
2641 09 Sep 14 nicklas 303
2641 09 Sep 14 nicklas 304 Doc.onLoad(Check.initPage);