source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/pool_protocol2.jsp @ 2186

Last change on this file since 2186 was 2186, checked in by Nicklas Nordborg, 8 years ago

References #555: Specify amount to use from *.dil items in pool

The volume to use in the pool can now be set by selecting the wells and clicking the 'Separate mix volume' button.

As a side-effect the mix factor is now calculated dynamically so that around 2µl is used from the original lib. The previous implementation with a fixed mix factor could still yield lower than 1µl for libraries with very high contentration (>20nM).

File size: 21.6 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.core.Extract"
9  import="net.sf.basedb.core.BioMaterial"
10  import="net.sf.basedb.core.MeasuredBioMaterial"
11  import="net.sf.basedb.core.BioMaterialEventSource"
12  import="net.sf.basedb.core.BioPlate"
13  import="net.sf.basedb.core.BioWell"
14  import="net.sf.basedb.core.PermissionDeniedException"
15  import="net.sf.basedb.core.ItemQuery"
16  import="net.sf.basedb.core.query.Restrictions"
17  import="net.sf.basedb.core.query.Hql"
18  import="net.sf.basedb.core.query.Orders"
19  import="net.sf.basedb.util.Values"
20  import="net.sf.basedb.util.formatter.WellCoordinateFormatter"
21  import="net.sf.basedb.util.extensions.Extension"
22  import="net.sf.basedb.clients.web.Base" 
23  import="net.sf.basedb.clients.web.util.HTML"
24  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
25  import="java.util.List"
26  import="java.util.ArrayList"
27%>
28<%
29final SessionControl sc = Base.getExistingSessionControl(request, true);
30final String ID = sc.getId();
31final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
32final String root = request.getContextPath();
33DbControl dc = null;
34try
35{
36  dc = sc.newDbControl();
37  final Extension reggie = ExtensionsControl.get(dc).getExtension("net.sf.basedb.reggie");
38  final User user = User.getById(dc, sc.getLoggedInUserId());
39 
40  Integer[] pools = Values.getInt(request.getParameterValues("pools"));
41 
42  int libPlateId = Values.getInt(request.getParameter("bioplate"));
43  BioPlate libPlate = libPlateId == 0 ? null : BioPlate.getById(dc, libPlateId);
44  String view = Values.getString(request.getParameter("view"), "list");
45%>
46<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
47<html>
48<head>
49  <%
50  if (libPlate != null)
51  {
52    %>
53    <title>Lab protocol for pooling <%=HTML.encodeTags(libPlate.getName())%> - <%=view.equals("list") ? "list" : "table"%></title>
54    <%
55  }
56  else
57  {
58    %>
59    <title>Lab protocol for library pooling - <%=view.equals("list") ? "list" : "table"%></title>
60    <%
61  }
62  %>
63  <link rel="SHORTCUT ICON" href="<%=home%>/images/flowcell.png">
64  <link rel="stylesheet" type="text/css" href="<%=home %>/css/printable.css">
65  <link rel="stylesheet" type="text/css" href="<%=home %>/css/plate.css">
66  <link rel="stylesheet" type="text/css" href="<%=home %>/css/reggie.css">
67  <script language="JavaScript" src="<%=root%>/include/scripts/main.js" type="text/javascript" charset="UTF-8"></script>
68  <script language="JavaScript" src="<%=root%>/include/scripts/ajax.js" type="text/javascript" charset="UTF-8"></script>
69  <script language="JavaScript" src="<%=home %>/reggie.js" type="text/javascript" charset="UTF-8"></script>
70  <script language="JavaScript" src="pools.js" type="text/javascript" charset="UTF-8"></script>
71  <script language="JavaScript" src="plate.js" type="text/javascript" charset="UTF-8"></script>
72 
73  <script language="JavaScript">
74  var debug = 0;
75  var currentStep = 1;
76 
77  // Loaded from servlet when getting Library information
78  var POOL_CURRENT_SCHEMA;
79  var POOL_CURRENT_BARCODE_VARIANT;
80 
81  function init()
82  {
83    // Load information about Library bioplate
84    var libPlate;
85    <%
86    if (libPlateId != 0)
87    {
88      %>
89      // Load Libraries and related info from the selected pools
90      var request = Ajax.getXmlHttpRequest();
91      try
92      {
93        showLoadingAnimation('Loading library bioplate information...');
94        var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibPlateInfo&bioplate=<%=libPlateId%>';   
95        request.open("GET", url, false);
96        request.send(null);
97      }
98      finally
99      {
100        hideLoadingAnimation();
101      }
102     
103      if (debug) Main.debug(request.responseText);
104      var response = JSON.parse(request.responseText);
105      if (response.status != 'ok')
106      {
107        setFatalError(response.message);
108        return false;
109      }
110     
111      libPlate = response.libPlate;
112      POOL_CURRENT_SCHEMA = PoolSchema.getById(libPlate.poolSchema);
113      POOL_CURRENT_BARCODE_VARIANT = PoolSchema.getBarcodeVariantByName(POOL_CURRENT_SCHEMA, libPlate.barcodeVariant);
114      Plate.init(8, 12, POOL_CURRENT_SCHEMA, WellPainter);
115      <%
116    }
117    %>
118   
119    var pools = [<%=Values.getString(java.util.Arrays.asList(pools), ",", true)%>];
120
121    // Load Libraries and related info from the selected pools
122    var request = Ajax.getXmlHttpRequest();
123    try
124    {
125      showLoadingAnimation('Loading pooled library information...');
126      var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibraryInfoForPools&pools='+pools.join(',')+'&bioplate=<%=libPlateId%>';   
127      request.open("GET", url, false);
128      request.send(null);
129    }
130    finally
131    {
132      hideLoadingAnimation();
133    }
134   
135    if (debug) Main.debug(request.responseText);
136    var response = JSON.parse(request.responseText);
137    if (response.status != 'ok')
138    {
139      setFatalError(response.message);
140      return false;
141    }
142   
143    var pools = response.pools;
144    var poolInfo = response.poolInfo;
145
146    var pageTitle = 'Lab protocol for pooling ';
147    // Pre-process the Library items
148    for (var i = 0; i < pools.length; i++)
149    {
150      var pool = pools[i];
151      if (i > 0) pageTitle += ','
152      pageTitle += ' ' + pool.name;
153     
154      // Calculate some pool quantities
155      pool.volume = 1000 * pool.originalQuantity / pool.conc;
156
157      for (var libNo = 0; libNo < pool.libraries.length; libNo++)
158      {
159        var lib = pool.libraries[libNo];
160        PoolMix.calculateLibVolumeForProtocol(lib, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy, true);
161        PoolMix.calculateEbVolume(lib, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy);
162        checkAndPreProcessLibrary(lib, pool, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT, '<%=view%>');       
163      }
164
165      pool.extra = PoolMix.calculateFinalPoolInfo(pool.libraries, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy);
166    }
167   
168    if (!libPlate)
169    {
170      document.title = pageTitle + ' - <%=view%>';
171    }
172   
173    <%
174    if (view.equals("list"))
175    {
176      %>
177      viewAsList(pools, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT);
178      <%
179    }
180    else
181    {
182      %>
183      viewAsPlate(pools, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT);
184      <%
185    }
186    %>
187  }
188 
189  function checkAndPreProcessLibrary(lib, pool, schema, barcodeVariant, view)
190  {
191    var well = lib.bioWell;
192    var remarks = [];
193
194    // Check if default barcode has been modified
195    if (barcodeVariant)
196    {
197      var indexSet = barcodeVariant.indexSets[well.column];
198      if (indexSet)
199      {
200        var defaultBarcode = indexSet.barcodes[well.row];
201        if (defaultBarcode && lib.barcode.name != defaultBarcode)
202        {
203          remarks[remarks.length] = 'Modified barcode';
204          lib.barcode.modified = true;
205        }
206      }
207    }
208   
209    if (lib.molarity)
210    {
211      if (lib.speedVacConc != null)
212      {
213        remarks[remarks.length] = 'SpeedVac';
214      }
215 
216      if (lib.mixFactor > 1)
217      {
218        // Larger mix than default
219        if (view != 'plate')
220        {
221          remarks[remarks.length] = '<span class="mix-remark">Mix <span class="volume">'+Numbers.formatNumber(lib.actualVolume*lib.mixFactor, 1) + '</span>+<span class="eb">' + Numbers.formatNumber(lib.actualEb*lib.mixFactor, 1)+'µl</span></span>';
222        }
223        remarks[remarks.length] = 'Use <b>' + Numbers.formatNumber(lib.actualVolume+lib.actualEb, 1) + 'µl</b> in pool';
224      }
225
226      lib.remarks = remarks;
227    }
228   
229    if (lib.comment) remarks[remarks.length] = lib.comment;
230  }
231 
232  /**
233    Get the plate coordinate string for a well, optionally including the plate
234    name or not.
235  */
236  function getPlateCoordinate(well, includePlateName)
237  {
238    var c = '';
239    if (well)
240    {
241      if (includePlateName) c += well.bioPlate.name;
242      c += ' ' + WELL_ALPHA[well.row] + (well.column+1);
243    }
244    return c;
245  }
246 
247 
248  function viewAsList(pools, schema, barcodeVariant)
249  {
250    for (var poolNo = 0; poolNo < pools.length; poolNo++)
251    {
252      var pool = pools[poolNo];
253      var realPoolNo = schema.getPoolNumForColumn(pool.libraries[0].bioWell.column);
254
255      var wellsInPool = POOL_CURRENT_SCHEMA ? Plate.getPool(realPoolNo) : null;
256     
257      var html = '';
258      var tbody = document.getElementById('listview.'+pool.id+'.body');
259     
260      var wellIndex = 0;
261      for (var j = 0; j < pool.libraries.length; j++)
262      {
263        var lib = pool.libraries[j];
264        var well = lib.bioWell;
265       
266        var tr = document.createElement('tr');
267        if (POOL_CURRENT_SCHEMA)
268        {
269          wellIndex = createMissingRows(tbody, wellsInPool, wellIndex, well, barcodeVariant);
270          tr.className = well.column % 2 == 0 ? "evencol" : "oddcol";
271        }
272        else
273        {
274          tr.className = 'evencol';
275        }
276   
277        if (barcodeVariant)
278        {
279          var indexSet = barcodeVariant.indexSets[well.column];
280          if (indexSet)
281          {
282            tr.className = lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
283          }
284        }
285
286        addColumn(tr, 'lib', lib.name);
287        addColumn(tr, 'remain', Numbers.formatNumber((lib.remainingVolume), 1));
288        addColumn(tr, 'molarity', Numbers.formatNumber(lib.molarity, 2));
289        <%
290        if (libPlate==null)
291        {
292          %>
293          addColumn(tr, 'workplate', well.bioPlate.name + ' ' + well.location);
294          <%
295        }
296        else
297        {
298          %>
299          addColumn(tr, 'workplate', well.location);
300          <%
301        }
302        %>
303        var mixFactor = lib.mixFactor || 1.0;
304        addColumn(tr, 'volume', mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualVolume, 1));
305        addColumn(tr, 'eb', pool.mixingStrategy == 'dynamic' || mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualEb, 1));
306        addColumn(tr, "remarks", lib.remarks.join('; '));
307        tbody.appendChild(tr);
308      }
309      if (POOL_CURRENT_SCHEMA)
310      {
311        createMissingRows(tbody, wellsInPool, wellIndex, null, barcodeVariant);
312      }
313     
314      var poolData = '<div class="pool-data">';
315      poolData += pool.libraries.length + ' libs; ';
316      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM; ';
317      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
318      poolData += '<br>Mixing strategy: ' + pool.mixingStrategy;
319      poolData += '</div>';
320      setInnerHTML('molarity.'+pool.id, poolData);
321      setInnerHTML('eb-volume.'+pool.id, Numbers.formatNumber(Math.max(0, pool.extra.ebVolumeExtra), 1));
322      Main.show('pool.'+pool.id);
323    }
324  }
325 
326  function createMissingRows(table, wellsInPool, wellIndex, well, barcodeVariant)
327  {
328    var wellAtIndex = wellsInPool[wellIndex]; // Empty??
329    if (!well) well = {'row': -1, 'column': -1};
330    while (wellAtIndex.row != well.row || wellAtIndex.column != well.column)
331    {
332      var tr = document.createElement('tr');
333      tr.className = 'empty';
334      if (barcodeVariant)
335      {
336        var indexSet = barcodeVariant.indexSets[wellAtIndex.column];
337        if (indexSet) tr.className += ' ' + indexSet.color;
338      }
339     
340      addColumn(tr, 'lib', 'not pooled');
341      addColumn(tr, 'remain', '');
342      addColumn(tr, 'molarity', '');
343      addColumn(tr, 'workplate', WELL_ALPHA[wellAtIndex.row] + (wellAtIndex.column+1));
344      addColumn(tr, 'volume', '');
345      addColumn(tr, 'eb', '');
346      addColumn(tr, 'remarks', '');
347      table.appendChild(tr);
348      wellIndex++;
349      if (wellIndex >= wellsInPool.length) break;
350      wellAtIndex = wellsInPool[wellIndex];
351    }
352    return wellIndex+1;
353  }
354 
355  function addColumn(tr, className, html)
356  {
357    var td = document.createElement('td');
358    td.className = className;
359    td.innerHTML = html;
360    tr.appendChild(td);
361  }
362 
363  function viewAsPlate(pools, schema, barcodeVariant)
364  {
365    for (var poolNo = 0; poolNo < pools.length; poolNo++)
366    {
367      var pool = pools[poolNo];
368      for (var libNo = 0; libNo < pool.libraries.length; libNo++)
369      {
370        var lib = pool.libraries[libNo];
371        var well = lib.bioWell;
372        Plate.getWell(well.row, well.column).setExtract(lib);
373      }
374    }
375
376    WellPainter.barcodeVariant = barcodeVariant;
377    PoolSchema.buildPoolTableRow(schema, 12);
378    Main.show('plateview');
379   
380    for (var poolNo = 0; poolNo < pools.length; poolNo++)
381    {
382      var pool = pools[poolNo];
383      var realPoolNo = schema.getPoolNumForColumn(pool.libraries[0].bioWell.column);
384      Plate.paint(Plate.getPool(realPoolNo));
385     
386      var poolData = '<div class="pool-data">';
387      poolData += pool.libraries.length + ' libs  ';
388      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM  ';
389      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
390      if (pool.mixingStrategy == 'dynamic')
391      {
392        poolData += '  <span class="pool-eb">'+Numbers.formatNumber(pool.extra.ebVolumeExtra, 1, 'µl')+'</span>';
393      }
394      poolData += '<br>Mixing strategy: ' + pool.mixingStrategy;
395      poolData += '<div class="comments">'+pool.comments+'</div>';
396      poolData += '</div>';
397     
398      document.getElementById('pool.'+realPoolNo).innerHTML = pool.name + poolData;
399    }
400  }
401
402  var WellPainter = function()
403  {
404    var painter = {};
405   
406    painter.getClassNameForWell = function(well, schema)
407    {
408      var cls = '';
409      var indexSet = painter.barcodeVariant.indexSets[well.column];
410      if (indexSet)
411      {
412        var lib = well.extract;
413        cls += lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
414      }
415      return cls;
416    }
417   
418    painter.getWellText = function(well, schema)
419    {
420      var text = '';
421      var lib = well.extract;
422      if (lib)
423      {
424        var name = lib.name;
425        var mixFactor = lib.mixFactor || 1.0;
426        var i = name.indexOf('.m');
427        text += '<div class="lib">'+name.substring(0, i)+'.<br>&nbsp;'+name.substring(i)+'</div>';
428        text += '<div><span class="volume">'+Numbers.formatNumber(lib.actualVolume*mixFactor, 1)+'µl</span>';
429        if (lib.mixingStrategy == 'fixed' || lib.mixFactor > 1)
430        {
431          text += '<span class="eb">'+Numbers.formatNumber(lib.actualEb*mixFactor, 1)+'µl</span>';
432        }
433        else
434        {
435          text += '<span class="eb"></span>';
436        }
437        //text+=lib.eb+':'+lib.mixFactor;
438        text += '</div>';
439        text += '<div class="remarks">'+ lib.remarks.join('; ') + '</div>';
440      }
441      return text;
442    }
443
444    return painter;
445  }();
446  </script>
447  <style>
448  table.protocolheader
449  {
450    width: 100%;
451    border: 1px solid #000000;
452    margin-bottom: 1em;
453    border-collapse: collapse;
454  }
455
456  table.protocolheader > tbody > tr
457  {
458    vertical-align: top;
459    height: 1.25em;
460  }
461
462  table.protocolheader > tbody > tr > th
463  {
464    text-align: left;
465    font-size: 1em;
466    background-color: #F0F0F0;
467    padding: 2px;
468  }
469 
470  table.protocolheader > tbody > tr > td
471  {
472    text-align: left;
473    font-size: 1em;
474    padding: 2px;
475  }
476
477  .pool-section
478  {
479    page-break-inside: avoid;
480  }
481
482  table.poolheader
483  {
484    margin-top: 1em;
485    width: 100%;
486    border: 1px solid #000000;
487    border-bottom: 0px;
488    border-collapse: collapse;
489  }
490
491  table.poolheader > tbody > tr
492  {
493    height: 1.25em;
494  }
495
496  table.poolheader > tbody > tr > th
497  {
498    text-align: left;
499    font-size: 1.25em;
500    padding: 1px;
501  }
502 
503  .listview
504  {
505    width: 100%;
506    font-size: 85%;
507    border-collapse: collapse;
508    border: 1px solid #000000;
509  }
510 
511  .listview tr.oddcol
512  {
513    background-color: #F0F0F0;
514  }
515 
516  .listview thead
517  {
518    border: 1px solid #000000;
519    background-color: #F0F0F0;
520  }
521 
522  .listview th
523  {
524    border-left: 1px solid #000000;
525  }
526 
527  .listview td
528  {
529    border-left: 1px solid #000000;
530    border-top: 1px dotted #666666;
531    vertical-align: middle;
532    padding: 2px;
533  }
534 
535  .listview .summary
536  {
537    border-top: 1px solid #000000;
538  }
539 
540  .listview .col-num
541  {
542    width: 1.75em;
543    text-align: center;
544    font-size: 125%;
545    font-weight: bold;
546    vertical-align: top;
547  }
548 
549  .listview .lib
550  {
551    width: 15em;
552    text-align: center;
553  }
554 
555  .listview .empty .lib
556  {
557    font-style: italic;
558    color: #666666;
559    text-align: center;
560  }
561 
562  .listview .workplate
563  {
564 
565    width: <%=libPlate==null ? "14em" : "7em"%>;
566    text-align: center;
567  }
568 
569  .listview .pool
570  {
571    width: 7em;
572    text-align: center;
573  }
574 
575  .listview .remain, .listview .molarity
576  {
577    width: 4.5em;
578    padding-right: 0.5em;
579    text-align: right;
580  }
581
582  .listview .volume
583  {
584    width: 3.5em;
585    padding-right: 0.5em;
586    text-align: right;
587    color: #C80000;
588  }
589 
590  .listview .eb
591  {
592    width: 3.5em;
593    padding-right: 0.5em;
594    text-align: right;
595    color: #0000C8;
596  }
597 
598  .listview .remarks
599  {
600    vertical-align: top;
601    padding-left: 0.25em;
602  }
603 
604  .mix-remark .volume, .mix-remark .eb
605  {
606    padding: 0;
607    text-align: inherit;
608    width: inherit;
609    font-weight: bold;
610  }
611
612 
613 
614  /* Divide the 12 wells across the full page */
615  #plateview .well
616  {
617    width: 8.2%;
618    max-width: 8.2%;
619    min-width: 8.2%;
620    padding: 4px;
621  }
622 
623  #plateview .well:hover
624  {
625    padding: 3px;
626  }
627 
628  #plateview .rowheader
629  {
630    width: 2em;
631  }
632 
633  #plateview .lib
634  {
635    font-weight: bold;
636    margin-bottom: 0.25em;
637  }
638  #plateview .volume
639  {
640    color: #C80000;
641  }
642  #plateview .eb
643  {
644    color: #0000C8;
645    float: right;
646  }
647 
648  #plateview .remarks
649  {
650    color: #C80000;
651    font-style: italic;
652  }
653 
654  #plateview .mix-remark
655  {
656    display: none;
657  }
658 
659  .pool-eb
660  {
661    color: #0000C8;
662  }
663 
664  #pool-row th
665  {
666    border-top: 0;
667    border-bottom: 1px solid #808080;
668    vertical-align: top;
669    padding: 0;
670  }
671 
672  #plateview .pool-data
673  {
674    font-weight: normal;
675  }
676  #plateview .comments
677  {
678    font-style: italic;
679  }
680 
681 
682  </style>
683</head>
684<body onload="init()">
685  <div class="paper <%=view.equals("list") ? "" : "landscape"%>">
686  <div class="noprint fullwidth" style="border-bottom: 1px dashed #A0A0A0; padding-left: 1em; padding-bottom: 1em;">
687    <span class="button" onclick="window.print()" style="float: left; margin-right: 1em;">
688      <img src="../images/print.png">Print&hellip;
689    </span>
690    <b>Note!</b> 
691    <%
692    if (view.equals("list"))
693    {
694      %>
695      For better printing reduce margins to about <i>5mm</i> and set page orientation
696      to <i>portrait</i>. To fit everything on a single page, scale down to <i>60-70%</i>.
697      <%
698    }
699    else
700    {
701      %>
702      For better printing reduce margins to about <i>5mm</i> and set page orientation
703      to <i>landscape</i>. The recommended scale is <i>100%</i>.
704      <%
705    }
706    %>
707    <br clear="all">
708  </div>
709 
710  <h1>Lab protocol for library pooling <span class="reggie">Reggie <%=reggie.getAbout().getVersion() %></span></h1>
711
712  <table style="width: 100%;" class="protocolheader">
713  <tr style="border-bottom: 1px solid #000000;">
714    <th style="width: 15%;">Library plate</th>
715    <td style="width: 30%; border-right: 1px solid #000000;"><%=libPlate == null ? "Multiple" : HTML.encodeTags(libPlate.getName())%></td>
716    <th style="width: 15%;"></th>
717    <th style="width: 20%;">Date</th>
718    <th style="width: 20%;">Operator</th>
719  </tr>
720  <tr>
721    <td rowspan="1" colspan="2" style="width: 50%; border-right: 1px solid #000000;"><%=libPlate != null ? HTML.niceFormat(libPlate.getDescription()) : ""%></td>
722    <td style="border-right: 1px solid #000000;">Pooling</td>
723    <td style="border-right: 1px solid #000000;"></td>
724    <td></td>
725  </tr>
726  </table>
727
728  <%
729  if (view.equals("list"))
730  {
731    for (Integer poolId :pools)
732    {
733      Extract pool = Extract.getById(dc, poolId);
734      %>
735      <div id="pool.<%=poolId%>" style="display: none;" class="pool-section">
736      <table style="width: 100%;" class="poolheader">
737      <tr valign="top">
738        <th style="width: 25%;"><%=HTML.encodeTags(pool.getName())%></th>
739        <th style="width: 75%; border-left: 1px solid #000000;">Comments:</th>
740      </tr>
741      <tr valign="top">
742        <td style="width: 25%;"><span id="molarity.<%=poolId%>"></span></td>
743        <td style="border-left: 1px solid #000000;"><%=HTML.niceFormat(pool.getDescription()) %></td>
744      </tr>
745      </table>
746      <table style="width: 100%;" class="listview" id="listview.<%=poolId%>">
747      <thead>
748        <tr class="toprow">
749          <th class="lib"></th>
750          <th>Remain</th>
751          <th>DNA</th>
752          <th class="workplate">Work</th>
753          <th>Lib</th>
754          <th>EB</th>
755          <th></th>
756        </tr>
757        <tr>
758          <th class="lib">Library</th>
759          <th>(µl)</th>
760          <th>(nM)</th>
761          <th class="workplate">plate</th>
762          <th>(µl)</th>
763          <th>(µl)</th>
764          <th>Remarks</th>
765        </tr>
766      </thead>
767      <tbody id="listview.<%=poolId%>.body">
768      </tbody>
769      <tbody>
770        <tr class="summary">
771          <td colspan="5" style="text-align: right; font-weight: bold; padding-right: 0.5em; font-size: 120%;">EB volume to add</td>
772          <td id="eb-volume.<%=poolId%>" class="eb">eb</td>
773          <td></td>
774        </tr>
775      </tbody>
776      </table>
777      </div>
778      <%
779    }
780  }
781  %>
782
783  <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>
784  <div class="messagecontainer error" id="errorMessage" style="display: none;"></div>
785  <%
786
787  if (view.equals("plate"))
788  {
789    %>
790    <table class="plate" style="margin: 0em 0 0 0; width: 100%; display: none;" id="plateview">
791    <tr id="pool-row">
792      <th colspan="13">&nbsp;</th>
793    </tr>
794    <%
795    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
796    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
797    %>
798    <tr class="header">
799      <th></th>
800      <%
801      for (int c = 0; c < libPlate.getColumns(); ++c)
802      {
803        %>
804        <th id="col.<%=c%>"><%=colF.format(c)%></th>
805        <%
806      }
807      %>
808    </tr>
809    <tbody>
810    <%
811    for (int r = 0; r < libPlate.getRows(); ++r)
812    {
813      String row = rowF.format(r);
814      %>
815      <tr class="row-<%=r%>">
816        <th id="row.<%=r%>" class="rowheader"><%=row%></th>
817        <%
818        for (int c = 0; c < libPlate.getColumns(); ++c)
819        {
820          %>
821          <td class="well col-<%=c%>" id="well.<%=r%>.<%=c%>"></td>
822          <%
823        }
824        %>
825      </tr>
826      <%
827    }
828    %>
829    </tbody>
830    </table>
831    <div style="margin: 1em;">
832      For each pool: <i>Number of libraries</i> • <i>Final molarity</i> • <i>Total volume</i> • <i>EB volume (dynamic mixing only)</i>
833    </div>
834    <%
835  }
836  %>
837  </div>
838</body>
839</html>
840<%
841}
842finally
843{
844  if (dc != null) dc.close();
845}
846%>
Note: See TracBrowser for help on using the repository browser.