source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/sequencing_started.jsp @ 2237

Last change on this file since 2237 was 2237, checked in by Nicklas Nordborg, 9 years ago

References #562: Re-design clustering and sequencing startup wizards

Load and display information about pools and library plate in the sequencing startup wizard to make it easier to verify that the correct runparameters.xml file has been selected.

File size: 18.8 KB
Line 
1<%@ page
2  pageEncoding="UTF-8"
3  session="false"
4  import="net.sf.basedb.core.User"
5  import="net.sf.basedb.core.DbControl"
6  import="net.sf.basedb.core.SessionControl"
7  import="net.sf.basedb.core.Application"
8  import="net.sf.basedb.clients.web.Base" 
9  import="net.sf.basedb.clients.web.util.HTML" 
10  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
11%>
12<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
13<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
14<%
15final SessionControl sc = Base.getExistingSessionControl(request, true);
16final String ID = sc.getId();
17final float scale = Base.getScale(sc);
18final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
19DbControl dc = null;
20try
21{
22  dc = sc.newDbControl();
23  final User user = User.getById(dc, sc.getLoggedInUserId());
24%>
25<base:page type="default" >
26<base:head scripts="ajax.js" styles="path.css">
27  <link rel="stylesheet" type="text/css" href="../css/reggie.css">
28  <script language="JavaScript" src="../reggie.js" type="text/javascript" charset="UTF-8"></script>
29
30<script language="JavaScript">
31
32var debug = 1;
33var currentStep = 1;
34var runParametersIsValid = false;
35
36var runParameters;
37var flowCell;
38
39function goNextAuto()
40{
41  goNext(false);
42}
43
44function goNext(manual)
45{
46  setInnerHTML('gonext.message', '');
47  if (currentStep == 1)
48  {
49    if (step1IsValid()) gotoStep2();
50  }
51}
52
53
54function step1IsValid()
55{
56  return runParametersIsValid;
57}
58
59
60function init()
61{
62  var frm = document.forms['reggie'];
63 
64  // Load sequencing protocols
65  var sequencingProtocols = getProtocols('SEQUENCING_PROTOCOL');
66  for (var i = 0; i < sequencingProtocols.length; i++)
67  {
68    var protocol = sequencingProtocols[i];
69    frm.sequencingProtocol[frm.sequencingProtocol.length] = new Option(protocol.name, protocol.id, protocol.isDefault);
70    setInputStatus('sequencingProtocol', '', 'valid');
71  }
72  if (frm.sequencingProtocol.length == 0)
73  {
74    frm.sequencingProtocol[0] = new Option('- none -', '');
75  }
76 
77  // Load sequencing machines
78  var sequencers = getHardware('SEQUENCER');
79  for (var i = 0; i < sequencers.length; i++)
80  {
81    var sequencer = sequencers[i];
82    frm.sequencer[frm.sequencer.length] = new Option(sequencer.name, sequencer.id, sequencer.isDefault);
83    setInputStatus('sequencer', '', 'valid');
84  }
85  if (frm.sequencer.length == 0)
86  {
87    frm.sequencer[0] = new Option('- none -', '');
88  }
89}
90
91function getProtocols(subtype)
92{
93  var request = Ajax.getXmlHttpRequest();
94  try
95  {
96    showLoadingAnimation('Loading ' + subtype + ' protocols...');
97    var url = '../Protocol.servlet?ID=<%=ID%>&cmd=GetProtocols&subtype='+subtype;   
98    request.open("GET", url, false); 
99    request.send(null);
100  }
101  finally
102  {
103    hideLoadingAnimation();
104  }
105
106  if (debug) Main.debug(request.responseText);
107  var response = JSON.parse(request.responseText); 
108  if (response.status != 'ok')
109  {
110    setFatalError(response.message);
111    return false;
112  }
113  return response.protocols;
114}
115
116function getHardware(subtype)
117{
118  var request = Ajax.getXmlHttpRequest();
119  try
120  {
121    showLoadingAnimation('Loading ' + subtype + ' hardware...');
122    var url = '../Hardware.servlet?ID=<%=ID%>&cmd=GetHardware&subtype='+subtype;   
123    request.open("GET", url, false); 
124    request.send(null);
125  }
126  finally
127  {
128    hideLoadingAnimation();
129  }
130
131  if (debug) Main.debug(request.responseText);
132  var response = JSON.parse(request.responseText); 
133  if (response.status != 'ok')
134  {
135    setFatalError(response.message);
136    return false;
137  }
138  return response.hardware;
139}
140
141
142function runParametersXmlFileOnChange(event)
143{
144  var frm = document.forms['reggie'];
145  var file = event.target.files[0];
146 
147  // Clear information
148  setInnerHTML('experimentName', '');
149  setInnerHTML('externalId', '');
150  setInnerHTML('runId', '');
151  setInnerHTML('position', '');
152  setInnerHTML('runNumber', '');
153  setInnerHTML('startDate', '');
154  setInnerHTML('sequencingCycles', '');
155  setInnerHTML('flowCellName', 'Flow cell information');
156  setInnerHTML('pools', '');
157  setInnerHTML('libPlate', '');
158  Main.hide('existing-sequencing-runs');
159  setInnerHTML('existing-sequencing-runs', '');
160 
161  var reader = new FileReader();
162  reader.onload = runParametersXmlFileLoaded;
163  reader.readAsText(file);
164}
165
166function runParametersXmlFileLoaded(event)
167{
168  parseRunParametersXmlFile(event.target.result);
169  var frm = document.forms['reggie'];
170  frm.comments.focus();
171}
172
173
174function parseRunParametersXmlFile(data)
175{
176  var frm = document.forms['reggie'];
177  runParametersIsValid = false;
178  setInputStatus('runParametersXml', '', '');
179 
180  var doc;
181  try
182  {
183    var parser = new DOMParser();
184    doc = parser.parseFromString(data, "application/xml");
185 
186    if (doc.documentElement.tagName == 'parsererror')
187    {
188      setInputStatus('runParametersXml', doc.documentElement.firstChild.textContent.split(/\n/)[0], 'invalid');
189      return;
190    }
191  }
192  catch (err)
193  {
194    setInputStatus('runParametersXml', err, 'invalid');
195    return;
196  }
197 
198  var info = {};
199  try
200  {
201    info.ExperimentName = getTextValue(doc, 'ExperimentName');
202    info.RunID = getTextValue(doc, 'RunID');
203    info.HiSeqPosition = getTextValue(doc, 'FCPosition');
204    info.ScannerID = getTextValue(doc, 'ScannerID');
205    info.ScanNumber = parseInt(getTextValue(doc, 'ScanNumber'));
206    info.FlowCellID = getTextValue(doc, 'Barcode');
207    info.SequencingCycles = getTextValue(doc, 'Read1') + '-' + getTextValue(doc, 'IndexRead1') + '-' + getTextValue(doc, 'Read2');
208    info.SequencingStart = '20'+getTextValue(doc, 'RunStartDate');
209
210    validateAndCopyRunParameters(info);
211  }
212  catch (msg)
213  {
214    setInputStatus('runParametersXml', msg, 'invalid');
215    if (debug) Main.debug(JSON.stringify(info));
216    return;
217  }
218 
219  runParametersIsValid = true;
220  runParameters = info;
221  setInputStatus('runParametersXml', '', 'valid');
222
223  if (debug) Main.debug(JSON.stringify(info));
224}
225
226
227function getTextValue(doc, selector)
228{
229  var el = doc.querySelector(selector);
230  if (el == null)
231  {
232    throw "Can't find tag &lt;"+selector+"&gt;";
233  }
234  return el.textContent;
235}
236
237function validateAndCopyRunParameters(info)
238{
239  var frm = document.forms['reggie'];
240
241  setInnerHTML('experimentName', info.ExperimentName);
242  setInnerHTML('externalId', info.FlowCellID);
243  setInnerHTML('runId', info.RunID);
244  setInnerHTML('position', info.HiSeqPosition);
245  setInnerHTML('runNumber', info.ScanNumber);
246  setInnerHTML('startDate', formatDate(info.SequencingStart));
247  setInnerHTML('sequencingCycles', info.SequencingCycles);
248
249  flowCell = getFlowCellInfoByBarcode(info.FlowCellID);
250  if (flowCell == null)
251  {
252    setInnerHTML('flowCellName', 'Can\'t find flow cell ' + info.FlowCellID);
253    throw 'Flow cell with ID='+info.FlowCellID+' not found.';
254  }
255 
256  setInnerHTML('flowCellName', Main.encodeTags(flowCell.name));
257
258  var pools = flowCell.pools;
259  var html = '';
260  var libPlateHtml = '';
261  for (var poolNo = 0; poolNo < pools.length; poolNo++)
262  {
263    var pool = pools[poolNo];
264    if (poolNo > 0) html += ', ';
265    html += Main.encodeTags(pool.name);
266    if (pool.LibPlate && libPlateHtml.indexOf(pool.LibPlate.name) == -1)
267    {
268      if (libPlateHtml.length > 0) libPlateHtml += ', ';
269      libPlateHtml += Main.encodeTags(pool.LibPlate.name);
270    }
271  }
272  setInnerHTML('pools', html);
273  setInnerHTML('libPlate', libPlateHtml || 'n/a');
274
275  var html = '';
276  html += '<tr valign="top" class="fc-info">';
277  html += '<td class="prompt" colspan="2">Existing sequencing runs</td>';
278  html += '';
279  html += '<td class="status"></td>';
280  html += '<td class="help">Start and end date is shown for other registered sequencing runs.</td>';
281  html += '</tr>';
282
283  var seqRuns = getSequencingRunsForFlowCell(flowCell);
284  var runExists = null;
285  if (seqRuns.length > 0)
286  {
287    for (var seqNo = 0; seqNo < seqRuns.length; seqNo++)
288    {
289      var seqRun = seqRuns[seqNo];
290      html += '<tr valign="top" class="fc-info">';
291      html += '<td class="subprompt">'+seqRun.name+'</td>';
292      html += '<td class="input" colspan="2">';
293      html += formatDate(seqRun.SequencingStart, '(no start date)') + ' -- ' + formatDate(seqRun.SequencingEnd, '(no end date)');
294      if (seqRun.SequencingResult)
295      {
296        html += ': ' + seqRun.SequencingResult;
297      }
298      html += '</td>';
299      html += '<td class="help"></td>';
300      html += '</tr>';
301      if (seqRun.DataFilesFolder == info.RunID)
302      {
303        runExists = seqRun;
304      }
305    }
306  }
307  else
308  {
309    html += '<tr valign="top" class="fc-info">';
310    html += '<td class="subprompt"></td>';
311    html += '<td class="input" colspan="2">';
312    html += 'none';
313    html += '</td>';
314    html += '<td class="help"></td>';
315    html += '</tr>';
316   
317  }
318  Main.show('existing-sequencing-runs');
319  setInnerHTML('existing-sequencing-runs', html);
320  if (runExists != null)
321  {
322    throw 'This sequencing run has already been registered: ' + runExists.name;
323  }
324 
325}
326
327function getFlowCellInfoByBarcode(barcode)
328{
329  var url = '../FlowCell.servlet?ID=<%=ID%>&cmd=GetFlowCellByBarcode';
330  url += '&barcode='+encodeURIComponent(barcode);
331 
332  var request = Ajax.getXmlHttpRequest();
333  try
334  {
335    showLoadingAnimation('Checking flow cell id...');
336    request.open("GET", url, false);
337    request.send(null);
338  }
339  finally
340  {
341    hideLoadingAnimation();
342  }
343 
344  if (debug) Main.debug(request.responseText);
345  var response = JSON.parse(request.responseText);
346
347  if (response.status != 'ok')
348  {
349    throw response.message;
350  }
351
352  return response.flowCell;
353}
354
355function getSequencingRunsForFlowCell(flowCell)
356{
357  var url = '../SequencingRun.servlet?ID=<%=ID%>&cmd=GetSequencingRunsForFlowCell';
358  url += '&flowCell='+flowCell.id;
359 
360  var request = Ajax.getXmlHttpRequest();
361  try
362  {
363    showLoadingAnimation('Loading sequencing runs...');
364    request.open("GET", url, false);
365    request.send(null);
366  }
367  finally
368  {
369    hideLoadingAnimation();
370  }
371 
372  if (debug) Main.debug(request.responseText);
373  var response = JSON.parse(request.responseText);
374
375  if (response.status != 'ok')
376  {
377    throw response.message;
378  }
379
380  return response.sequencingRuns;
381}
382
383function formatDate(value, defaultValue)
384{
385  if (!value) return defaultValue || '';
386  if (value.length == 8)
387  {
388    // YYYYMMDD
389    value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2);
390  }
391  else if (value.length == 13)
392  {
393    // YYYYMMDD HHMM
394    value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2) + ' ' + value.substr(9, 2) + ':' + value.substr(11, 2);
395  }
396  return value;
397}
398
399
400function goRegister()
401{
402  if (!step1IsValid()) return;
403  var frm = document.forms['reggie'];
404
405  frm.sequencingOperator.disabled = true;
406  frm.sequencer.disabled = true;
407  frm.sequencingProtocol.disabled = true;
408  frm.comments.disabled = true;
409 
410  Main.hide('goregister');
411  Main.hide('gocancel');
412  Main.hide('gonext.message');
413 
414  var submitInfo = {};
415  submitInfo.flowCell = flowCell;
416  submitInfo.runParameters = runParameters;
417 
418  var sequencingRun = {};
419  sequencingRun.operator = frm.sequencingOperator.value;
420  sequencingRun.sequencer = parseInt(frm.sequencer.value);
421  sequencingRun.protocol = parseInt(frm.sequencingProtocol.value);
422  sequencingRun.comments = frm.comments.value;
423  submitInfo.sequencingRun = sequencingRun;
424 
425  if (debug) Main.debug(JSON.stringify(submitInfo));
426  var url = '../SequencingRun.servlet?ID=<%=ID%>&cmd=RegisterSequencingStarted';
427  var request = Ajax.getXmlHttpRequest();
428 
429  try
430  {
431    showLoadingAnimation('Performing registration...');
432    request.open("POST", url, false);
433    request.send(JSON.stringify(submitInfo));
434  }
435  finally
436  {
437    hideLoadingAnimation();
438  }
439 
440  if (debug) Main.debug(request.responseText);
441  var response = JSON.parse(request.responseText);
442 
443  if (response.messages && response.messages.length > 0)
444  {
445    var msg = '<ul>';
446    for (var i = 0; i < response.messages.length; i++)
447    {
448      var msgLine = response.messages[i];
449      if (msgLine.indexOf('[Warning]') >= 0)
450      {
451        msg += '<li class="warning">' + msgLine.replace('[Warning]', '');
452      }
453      else
454      {
455        msg += '<li>' + msgLine;
456      }
457    }
458    msg += '</ul>';
459    setInnerHTML('messages', msg);
460    Main.show('messages');
461  }
462 
463  if (response.status != 'ok')
464  {
465    Main.addClass(document.getElementById('messages'), 'failure');
466    setFatalError(response.message);
467    return false;
468  }
469
470  Main.show('gorestart');
471}
472
473</script>
474<style>
475
476.fc-info
477{
478  background-color: #F4F4F4;
479}
480
481.fc-info .subprompt
482{
483  font-weight: normal;
484  padding-left: 2em;
485  text-align: left;
486}
487
488.fc-info .input
489{
490  font-style: italic;
491}
492
493</style>
494</base:head>
495<base:body onload="init()">
496
497  <p:path><p:pathelement 
498    title="Reggie" href="<%="../index.jsp?ID="+ID%>" 
499    /><p:pathelement title="Register sequencing started" 
500    /></p:path>
501
502  <div class="content">
503  <%
504  if (sc.getActiveProjectId() == 0)
505  {
506    %>
507    <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
508      No project has been selected. You may proceed with the registration but
509      created items will not be shared.
510    </div>
511    <%
512  }
513  %>
514
515  <form name="reggie" onsubmit="return false;">
516  <div id="step.1.section">
517  <table class="stepform">
518  <tr>
519    <td rowspan="3" class="stepno">1</td>
520    <td class="steptitle">Sequencing startup information</td>
521  </tr>
522  <tr>
523    <td class="stepfields">
524      <table style="border-collapse: collapse;">
525      <tr valign="top">
526        <td class="prompt">Operator</td>
527        <td class="input">
528          <input type="text" name="sequencingOperator" value="<%=HTML.encodeTags(user.getName()) %>" 
529            style="width: 90%;" maxlength="255" onkeypress="focusOnEnter(event, 'sequencer')">
530        </td>
531        <td class="status" id="sequencingOperator.status"></td>
532        <td class="help">
533          <span id="sequencingOperator.message" class="message" style="display: none;"></span>
534        </td>
535      </tr>
536      <tr valign="top">
537        <td class="prompt">Sequencing machine</td>
538        <td class="input"><select style="width:90%" name="sequencer" id="sequencer" 
539          onkeypress="focusOnEnter(event, 'sequencingProtocol')"></select></td>
540        <td class="status" id="sequencer.status"></td>
541        <td class="help"><span id="sequencer.message" class="message" style="display: none;"></span>
542          Select the HiSeq machine which is used for sequencing.
543        </td>
544      </tr>
545      <tr valign="top">
546        <td class="prompt">Protocol</td>
547        <td class="input"><select style="width:90%" name="sequencingProtocol" id="sequencingProtocol" 
548          onkeypress="focusOnEnter(event, 'fc-0.externalId')"></select></td>
549        <td class="status" id="sequencingProtocol.status"></td>
550        <td class="help"><span id="sequencingProtocol.message" class="message" style="display: none;"></span>
551          Select the protocol which was used in the clustering.
552        </td>
553      </tr>
554      <tr valign="baseline">
555        <td class="prompt">runParameters.xml</td>
556        <td class="input">
557          <input type="file" multiple class="required" name="runParametersXml" onchange="runParametersXmlFileOnChange(event)" style="width: 90%;">
558        </td>
559        <td class="status" id="runParametersXml.status"></td>
560        <td class="help" rowspan="12"><span id="runParametersXml.message" class="message" style="display:none;"></span>
561          Select the <b>runParameters.xml</b> file that was created by the HiSeq. Typically found in
562          <b>D:\Illumina\HiSeqTemp\&lt;run-folder&gt;</b> subfolder.
563        </td>
564      </tr>
565      <tr valign="top" class="fc-info" style="border-top: 1em solid transparent;">
566        <td class="prompt" colspan="2">Sequencing information</td>
567        <td class="status"></td>
568      </tr>
569      <tr valign="top" class="fc-info">
570        <td class="subprompt">Experiment</td>
571        <td class="input" id="experimentName"></td>
572        <td class="status"></td>
573      </tr>
574      <tr valign="top" class="fc-info">
575        <td class="subprompt">RunID</td>
576        <td class="input" id="runId"></td>
577        <td class="status"></td>
578      </tr>
579      <tr valign="top" class="fc-info">
580        <td class="subprompt">Barcode</td>
581        <td class="input" id="externalId"></td>
582        <td class="status"></td>
583      </tr>
584      <tr valign="top" class="fc-info">
585        <td class="subprompt">HiSeq position</td>
586        <td class="input" id="position"></td>
587        <td class="status"></td>
588      </tr>
589      <tr valign="top" class="fc-info">
590        <td class="subprompt">Run number</td>
591        <td class="input" id="runNumber"></td>
592        <td class="status"></td>
593      </tr>
594      <tr valign="top" class="fc-info">
595        <td class="subprompt">Start date</td>
596        <td class="input" id="startDate"></td>
597        <td class="status"></td>
598      </tr>
599      <tr valign="top" class="fc-info">
600        <td class="subprompt">Sequencing cycles</td>
601        <td class="input" id="sequencingCycles"></td>
602        <td class="status"></td>
603      </tr>
604      <tr valign="top" class="fc-info">
605        <td class="prompt" colspan="2" id="flowCellName">Flow cell information</td>
606        <td class="status"></td>
607      </tr>
608      <tr valign="top" class="fc-info">
609        <td class="subprompt">Pools</td>
610        <td class="input" id="pools"></td>
611        <td class="status"></td>
612      </tr>
613      <tr valign="top" class="fc-info">
614        <td class="subprompt">LibPlate</td>
615        <td class="input" id="libPlate"></td>
616        <td class="status"></td>
617      </tr>
618      <tbody id="existing-sequencing-runs" style="border-bottom: 1em solid transparent;">
619      <tr valign="top" class="fc-info">
620        <td class="subprompt"></td>
621        <td class="input"></td>
622        <td class="status"></td>
623        <td class="help"></td>
624      </tr>
625      </tbody>
626      <tr valign="top">
627        <td class="prompt">Comments</td>
628        <td class="input"><textarea rows="6" cols="50" style="width: 95%;" name="comments"></textarea></td>
629        <td class="status" id="comments.status"></td>
630        <td class="help"><span id="comments.message" class="message" style="display: none;"></span>
631          Comments about the sequencing startup.
632        </td>
633      </tr>
634      </table>
635    </td>
636  </tr>
637  </table>
638  </div>
639 
640 
641  <div class="loading" id="loading" style="display: none;"><table><tr><td><img src="../images/loading.gif"></td><td id="loading.msg">Please wait...</td></tr></table></div>
642 
643  <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>
644 
645  <div id="messages" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div>
646 
647  <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
648    <tr>
649      <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
650      <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)" style="display: none;"/></td>
651      <td><base:button id="goregister" title="Register" image="<%=home+"/images/import.png"%>" onclick="goRegister()" /></td>
652      <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
653      <td id="gonext.message" class="message"></td>
654    </tr>
655  </table>
656 
657  </form>
658  </div>
659 
660</base:body>
661</base:page>
662<%
663}
664finally
665{
666  if (dc != null) dc.close();
667}
668%>
Note: See TracBrowser for help on using the repository browser.