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

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

References #424, #425, #457, #479. Re-designed protocols to make the header section a bit more compact when the comment text is large. Display a warning when the remaining RNA quanitity is below 1.5 times the required amount (eg. 1.1µg or 1.22µg).

File size: 14.5 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.util.Values"
19  import="net.sf.basedb.util.formatter.WellCoordinateFormatter"
20  import="net.sf.basedb.util.extensions.Extension"
21  import="net.sf.basedb.clients.web.Base" 
22  import="net.sf.basedb.clients.web.util.HTML"
23  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
24  import="java.util.List"
25  import="java.util.ArrayList"
26%>
27<%
28final SessionControl sc = Base.getExistingSessionControl(request, true);
29final String ID = sc.getId();
30final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
31final String root = request.getContextPath();
32DbControl dc = null;
33try
34{
35  dc = sc.newDbControl();
36  final Extension reggie = ExtensionsControl.get(dc).getExtension("net.sf.basedb.reggie");
37  final User user = User.getById(dc, sc.getLoggedInUserId());
38  int libPlateId = Values.getInt(request.getParameter("bioplate"));
39  String poolSchema = request.getParameter("poolSchema");
40  String barcodeVariant = request.getParameter("barcodeVariant");
41 
42  BioPlate plate = BioPlate.getById(dc, libPlateId);
43  int columns = plate.getColumns();
44  int rows = plate.getRows();
45  String view = Values.getString(request.getParameter("view"), "list");
46%>
47<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
48<html>
49<head>
50  <title>Lab tracking protocol for library pooling</title>
51  <link rel="SHORTCUT ICON" href="<%=home%>/images/flowcell.png">
52  <link rel="stylesheet" type="text/css" href="<%=home %>/css/printable.css">
53  <link rel="stylesheet" type="text/css" href="<%=home %>/css/plate.css">
54  <script language="JavaScript" src="<%=root%>/include/scripts/main.js" type="text/javascript" charset="UTF-8"></script>
55  <script language="JavaScript" src="<%=root%>/include/scripts/ajax.js" type="text/javascript" charset="UTF-8"></script>
56  <script language="JavaScript" src="<%=home %>/reggie.js" type="text/javascript" charset="UTF-8"></script>
57  <script language="JavaScript" src="pools.js" type="text/javascript" charset="UTF-8"></script>
58  <script language="JavaScript" src="plate.js" type="text/javascript" charset="UTF-8"></script>
59 
60  <script language="JavaScript">
61  var debug = false;
62  var currentStep = 1;
63 
64  function init()
65  {
66    var schema = PoolSchema.getById('<%=poolSchema%>');
67    var barcodeVariant = PoolSchema.getBarcodeVariantByName(schema, '<%=barcodeVariant%>');
68
69    // Load Libraries and related info from the selected bioplate
70    var request = Ajax.getXmlHttpRequest();
71    try
72    {
73      showLoadingAnimation('Loading Library bioplate information...');
74      var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibraryInfoForPlate&bioplate=<%=libPlateId%>';   
75      request.open("GET", url, false);
76      request.send(null);
77    }
78    finally
79    {
80      hideLoadingAnimation();
81    }
82   
83    if (debug) Main.debug(request.responseText);
84    var response = JSON.parse(request.responseText);
85    if (response.status != 'ok')
86    {
87      setFatalError(response.message);
88      return false;
89    }
90   
91    var list = response.libraries;
92
93    // Pre-process the Library items
94    for (var i = 0; i < list.length; i++)
95    {
96      checkAndPreProcessLibrary(list[i], schema, barcodeVariant);
97    }
98   
99    <%
100    if (view.equals("list"))
101    {
102      %>
103      viewAsList(list, schema, barcodeVariant);
104      <%
105    }
106    else
107    {
108      %>
109      viewAsPlate(list, schema, barcodeVariant)
110      <%
111    }
112    %>
113  }
114 
115  function checkAndPreProcessLibrary(lib, schema, barcodeVariant)
116  {
117    var well = lib.bioWell;
118    var remarks = [];
119
120    // Check if default barcode has been modified
121    var indexSet = barcodeVariant.indexSets[well.column];
122    if (indexSet)
123    {
124      var defaultBarcode = indexSet.barcodes[well.row];
125      if (defaultBarcode && lib.barcode.name != defaultBarcode)
126      {
127        remarks[remarks.length] = 'Modified barcode';
128        lib.barcode.modified = true;
129      }
130    }
131   
132    // Calculate volume to use and water to add based on concentration
133    if (lib.molarity)
134    {
135      lib.volume = 10 / lib.molarity;
136      lib.eb = 5-lib.volume;
137      if (lib.speedVacConc != null)
138      {
139        remarks[remarks.length] = 'SpeedVac';
140        if (lib.molarity < 2) remarks[remarks.length] = 'Use 5 µl';
141      }
142    }
143
144    lib.remarks = remarks;
145  }
146 
147  /**
148    Get the plate coordinate string for a well, optionally including the plate
149    name or not.
150  */
151  function getPlateCoordinate(well, includePlateName)
152  {
153    var c = '';
154    if (well)
155    {
156      if (includePlateName) c += well.bioPlate.name;
157      c += ' ' + WELL_ALPHA[well.row] + (well.column+1);
158    }
159    return c;
160  }
161 
162 
163  function viewAsList(list, schema, barcodeVariant)
164  {
165    var lastPoolNum = -1;
166    for (var i = 0; i < list.length; i++)
167    {
168      var lib = list[i];
169      var well = lib.bioWell;
170 
171      var idSuffix = well.column + '.' + well.row;
172      if (lib.remainingQuantity)
173      {
174        Main.removeClass(document.getElementById('row.'+idSuffix), 'empty');
175        setInnerHTML('lib.'+idSuffix, lib.name);
176        setInnerHTML('pool.'+idSuffix, '????');
177        setInnerHTML('remain.'+idSuffix, Numbers.formatNumber(lib.remainingQuantity*1000, 2));
178        setInnerHTML('molarity.'+idSuffix, Numbers.formatNumber(lib.molarity, 2));
179       
180        setInnerHTML('volume.mol5.'+idSuffix, Numbers.formatNumber(lib.volume, 2));
181        setInnerHTML('eb.mol5.'+idSuffix, Numbers.formatNumber(lib.eb, 2));
182        setInnerHTML('volume.mol10.'+idSuffix, Numbers.formatNumber(lib.volume*2, 2));
183        setInnerHTML('eb.mol10.'+idSuffix, Numbers.formatNumber(lib.eb*2, 2));
184       
185        var indexSet = barcodeVariant.indexSets[well.column];
186        if (indexSet)
187        {
188          var color = lib.barcode.modified ? 'bg-modified' : indexSet.color;
189          Main.addClass(document.getElementById('pool.'+idSuffix), color);
190        }
191       
192        setInnerHTML('remarks.'+idSuffix, lib.remarks.join('; '));
193      }
194    }
195  }
196 
197 
198  function viewAsPlate(list, schema, barcodeVariant)
199  {
200    Plate.init(<%=rows%>, <%=columns%>, schema, WellPainter);
201   
202    for (var i = 0; i < list.length; i++)
203    {
204      var lib = list[i];
205      var well = lib.bioWell;
206      Plate.getWell(well.row, well.column).setExtract(lib);
207    }
208
209    WellPainter.barcodeVariant = barcodeVariant;
210    Plate.paint(Plate.getWells());
211    PoolSchema.buildPoolTableRow(schema, <%=columns%>);
212    Main.show('plateview');
213  }
214
215  var WellPainter = function()
216  {
217    var painter = {};
218   
219    painter.getClassNameForWell = function(well, schema)
220    {
221      var cls = '';
222      var indexSet = painter.barcodeVariant.indexSets[well.column];
223      if (indexSet)
224      {
225        var lib = well.extract;
226        cls += lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
227      }
228      return cls;
229    }
230   
231    painter.getWellText = function(well, schema)
232    {
233      var text = '';
234      var lib = well.extract;
235      if (lib && lib.remainingQuantity)
236      {
237        var name = lib.name;
238        var i = name.indexOf('.m');
239        text += '<div class="lib">'+name.substring(0, i)+'.<br>&nbsp;'+name.substring(i)+'</div>';
240       
241        text += '<div><span class="volume">'+Numbers.formatNumber(lib.volume, 1)+'µl</span>';
242        text += '<span class="eb">'+Numbers.formatNumber(lib.eb, 1)+'µl</span></div>';
243        text += '<div><span class="volume">'+Numbers.formatNumber(lib.volume*2, 1)+'µl</span>';
244        text += '<span class="eb">'+Numbers.formatNumber(lib.eb*2, 1)+'µl</span></div>';
245        text += '<div class="remarks">'+ lib.remarks.join('; ') + '</div>';
246      }
247      return text;
248    }
249
250    return painter;
251  }();
252  </script>
253  <style>
254  table.protocolheader
255  {
256    width: 100%;
257  }
258
259  table.protocolheader > tbody > tr
260  {
261    height: 1.25em;
262  }
263
264  table.protocolheader > tbody > tr > th
265  {
266    width: 50%;
267    text-align: left;
268    font-size: 1em;
269  }
270 
271  #listview
272  {
273    width: 100%;
274    font-size: 85%;
275    border-collapse: collapse;
276    border: 1px solid #000000;
277  }
278 
279  #listview tr.evencol
280  {
281    background-color: #F0F0F0;
282  }
283 
284  #listview thead
285  {
286    border: 1px solid #000000;
287    background-color: #F0F0F0;
288  }
289 
290  #listview tbody
291  {
292    page-break-inside: avoid;
293    border-top: 1px solid #000000;
294    border-bottom: 1px solid #000000;
295  }
296 
297  #listview th
298  {
299    border-left: 1px solid #000000;
300  }
301 
302  #listview td
303  {
304    border-left: 1px solid #000000;
305    border-top: 1px dotted #666666;
306    vertical-align: middle;
307  }
308 
309  #listview .col-num
310  {
311    width: 1.75em;
312    text-align: center;
313    font-size: 125%;
314    font-weight: bold;
315    vertical-align: top;
316  }
317 
318  #listview .lib
319  {
320    width: 15em;
321    text-align: center;
322  }
323 
324  #listview .empty .lib
325  {
326    font-style: italic;
327    color: #666666;
328    text-align: center;
329  }
330 
331  #listview .workplate
332  {
333    width: 7em;
334    text-align: center;
335  }
336 
337  #listview .pool
338  {
339    width: 7em;
340    text-align: center;
341  }
342 
343  #listview .remain, #listview .molarity
344  {
345    width: 4.5em;
346    padding-right: 0.5em;
347    text-align: right;
348  }
349
350  #listview .mol5, #listview .mol10
351  {
352    width: 8em;
353    padding-right: 0.5em;
354    text-align: right;
355  }
356 
357  #listview .empty .mol5, #listview .empty .mol10
358  {
359    visibility: hidden;
360  }
361 
362  #listview .volume
363  {
364    color: #C80000;
365    padding-right: 3px;
366  }
367 
368  #listview .eb
369  {
370    color: #0000C8;
371    padding-left: 3px;
372  }
373 
374  #listview .remarks
375  {
376    vertical-align: top;
377    padding-left: 0.25em;
378  }
379 
380  /* Divide the 12 wells across the full page */
381  #plateview .well
382  {
383    width: 8.2%;
384    max-width: 8.2%;
385    min-width: 8.2%;
386    padding: 4px;
387  }
388 
389  #plateview .well:hover
390  {
391    padding: 3px;
392  }
393 
394  #plateview .rowheader
395  {
396    width: 2em;
397  }
398 
399  #plateview .lib
400  {
401    font-weight: bold;
402    margin-bottom: 0.25em;
403  }
404  #plateview .volume
405  {
406    color: #C80000;
407  }
408  #plateview .eb
409  {
410    color: #0000C8;
411    float: right;
412  }
413 
414  #plateview .remarks
415  {
416    color: #C80000;
417    font-style: italic;
418  }
419  </style>
420</head>
421<body onload="init()">
422  <div class="paper <%=view.equals("list") ? "" : "landscape"%>">
423  <div class="noprint fullwidth" style="border-bottom: 1px dashed #A0A0A0; padding-left: 1em; padding-bottom: 1em;">
424    <span class="button" onclick="window.print()" style="float: left; margin-right: 1em;">
425      <img src="../images/print.png">Print&hellip;
426    </span>
427    <b>Note!</b> 
428    <%
429    if (view.equals("list"))
430    {
431      %>
432      For better printing reduce margins to about <i>5mm</i> and set page orientation
433      to <i>portrait</i>. To fit everything on a single page, scale down to <i>60-70%</i>.
434      <%
435    }
436    else
437    {
438      %>
439      For better printing reduce margins to about <i>5mm</i> and set page orientation
440      to <i>landscape</i>. The recommended scale is <i>100%</i>.
441      <%
442    }
443    %>
444    <br clear="all">
445  </div>
446 
447  <h1>Lab protocol for library pooling <span class="reggie">Reggie <%=reggie.getAbout().getVersion() %></span></h1>
448
449  <table style="width: 100%; border: 0px;" class="protocolheader">
450  <tr valign="top">
451    <th style="width: 40%;">Work plate: <%=HTML.encodeTags(plate.getName())%></th>
452    <th style="width: 60%">Comments:</th>
453  </tr>
454  <tr valign="top">
455    <th style="width: 40%; padding-bottom: 1.5em;">Date+operator:</th>
456    <td><%=HTML.niceFormat(plate.getDescription()) %></td>
457  </tr>
458  </table>
459
460  <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>
461  <div class="messagecontainer error" id="errorMessage" style="display: none;"></div>
462  <%
463  if (view.equals("list"))
464  {
465    %>
466    <table style="width: 100%;" id="listview">
467    <thead>
468      <tr class="toprow">
469        <th></th>
470        <th></th>
471        <th class="lib"></th>
472        <th class="workplate">Work</th>
473        <th>Remain</th>
474        <th>DNA</th>
475        <th>2nM, 5µl</th>
476        <th>2nM, 10µl</th>
477        <th></th>
478      </tr>
479      <tr>
480        <th></th>
481        <th>Pool</th>
482        <th class="lib">Library</th>
483        <th class="workplate">plate</th>
484        <th>(ng)</th>
485        <th>(nM)</th>
486        <th>(µl)</th>
487        <th>(µl)</th>
488        <th>Remarks</th>
489      </tr>
490    </thead>
491    <%
492    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
493    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
494    for (int c = 0; c < columns; ++c)
495    {
496      String rowClass = c % 2 == 0 ? "evencol" : "oddcol";
497      %>
498      <tbody>
499      <%
500      for (int r = 0; r < rows; ++r)
501      {
502        String idSuffix = c + "." + r;
503        %>
504        <tr class="<%=rowClass%> empty" id="row.<%=idSuffix%>">
505          <%
506          if (r == 0)
507          {
508            %>
509            <td class="col-num" rowspan="<%=rows%>"><%=c+1%></td>
510            <%
511          }
512          %>
513          <td class="pool" id="pool.<%=idSuffix%>"></td>
514          <td class="lib" id="lib.<%=idSuffix%>">empty</td>
515          <td class="workplate"><%=rowF.format(r)+colF.format(c)%></td>
516          <td class="remain" id="remain.<%=idSuffix%>"></td>
517          <td class="molarity" id="molarity.<%=idSuffix%>"></td>
518          <td class="mol5"><span class="volume" id="volume.mol5.<%=idSuffix%>"></span>+<span class="eb" id="eb.mol5.<%=idSuffix%>"></span></td>
519          <td class="mol10"><span class="volume" id="volume.mol10.<%=idSuffix%>"></span>+<span class="eb" id="eb.mol10.<%=idSuffix%>"></span></td>
520          <td class="remarks" id="remarks.<%=idSuffix%>"></td>
521        </tr>
522        <%
523      }
524      %>
525      </tbody>
526      <%
527    }
528    %>
529    </table>
530    <%
531  }
532  else
533  {
534    %>
535    <table class="plate" style="margin: 0em 0 0 0; width: 100%; display: none;" id="plateview">
536    <%
537    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
538    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
539    %>
540    <tr class="header">
541      <th></th>
542      <%
543      for (int c = 0; c < columns; ++c)
544      {
545        %>
546        <th id="col.<%=c%>"><%=colF.format(c)%></th>
547        <%
548      }
549      %>
550    </tr>
551    <tbody>
552    <%
553    for (int r = 0; r < rows; ++r)
554    {
555      String row = rowF.format(r);
556      %>
557      <tr class="row-<%=r%>">
558        <th id="row.<%=r%>" class="rowheader"><%=row%></th>
559        <%
560        for (int c = 0; c < columns; ++c)
561        {
562          %>
563          <td class="well col-<%=c%>" id="well.<%=r%>.<%=c%>"></td>
564          <%
565        }
566        %>
567      </tr>
568      <%
569    }
570    %>
571    </tbody>
572    <tr id="pool-row">
573      <th colspan="13">&nbsp;</th>
574    </tr>
575    </table>
576    <%
577  }
578  %>
579  </div>
580</body>
581</html>
582<%
583}
584finally
585{
586  if (dc != null) dc.close();
587}
588%>
Note: See TracBrowser for help on using the repository browser.