source: extensions/net.sf.basedb.reggie/branches/ticket-422/resources/libprep/mrna_protocol2.jsp @ 1814

Last change on this file since 1814 was 1814, checked in by Nicklas Nordborg, 7 years ago

References #456 and #457. Added support for manually setting barcodes. Check for duplicate barcodes in the same pool. Added list- and plate-view protocols for library preparation.

File size: 14.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.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 mRnaPlateId = Values.getInt(request.getParameter("bioplate"));
39  final Float stratageneConc = Values.getFloat(request.getParameter("stratageneConc"), null);
40  String poolSchema = request.getParameter("poolSchema");
41 
42  BioPlate plate = BioPlate.getById(dc, mRnaPlateId);
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 mRNA and cDNA preparation</title>
51  <link rel="SHORTCUT ICON" href="<%=home%>/images/pipette.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 = true;
62  var currentStep = 1;
63 
64  function init()
65  {
66    // Load mRNA and related info from the selected bioplate
67    var request = Ajax.getXmlHttpRequest();
68    try
69    {
70      showLoadingAnimation('Loading mRNA bioplate information...');
71      var url = '../MRna.servlet?ID=<%=ID%>&cmd=GetMRnaInfoForPlate&bioplate=<%=mRnaPlateId%>';   
72      request.open("GET", url, false); 
73      request.send(null);
74    }
75    finally
76    {
77      hideLoadingAnimation();
78    }
79   
80    if (debug) Main.debug(request.responseText);
81    var response = JSON.parse(request.responseText);
82    if (response.status != 'ok')
83    {
84      setFatalError(response.message);
85      return false;
86    }
87   
88    var list = response.mrna;
89    // Pre-process the return mRNA items
90    for (var i = 0; i < list.length; i++)
91    {
92      checkAndPreProcessMRna(list[i]);
93    }
94   
95    <%
96    if (view.equals("list"))
97    {
98      %>
99      viewAsList(list);
100      <%
101    }
102    else
103    {
104      %>
105      viewAsPlate(list)
106      <%
107    }
108    %>
109  }
110 
111  /**
112    Get the plate coordinate string for a well, optionally including the plate
113    name or not.
114  */
115  function getPlateCoordinate(well, includePlateName)
116  {
117    var c = '';
118    if (well)
119    {
120      if (includePlateName) c += well.bioPlate.name;
121      c += ' ' + WELL_ALPHA[well.row] + (well.column+1);
122    }
123    return c;
124  }
125 
126  /**
127    Check the mRNA and RNA items for problems and calculate derived
128    information such as volume and water, qc/stratagene flags.
129  */
130  function checkAndPreProcessMRna(mrna)
131  {
132    var rna = mrna.rna;
133    // Set the 'stratagene' flag
134    rna.stratagene = rna.name == STRATAGENE_NAME;
135    rna.external = rna.name == EXTERNAL_RNA_NAME;
136   
137    // Set the 'QC' flag if more than 1.2µg is used
138    rna.qc = rna.usedQuantity > 1.2;
139   
140    <%
141    if (stratageneConc != null && stratageneConc > 0)
142    {
143      %>
144      if (rna.stratagene) rna.NDConc = <%=stratageneConc%>;
145      <%
146    }
147    %>
148   
149    // Calculate volume to use and water to add based on concentration
150    if (rna.NDConc && rna.usedQuantity)
151    {
152      rna.volume = Math.ceil(10000*rna.usedQuantity/rna.NDConc) / 10;
153      rna.water = 50-rna.volume;
154    }
155   
156    // check for some issues that may indicate problems
157    var remarks = [];
158    if (rna.qc) remarks[remarks.length] = 'QC';
159    if (!rna.stratagene && !rna.external)
160    {
161      if (!rna.bioWell)
162      {
163        remarks[remarks.length] = 'No location';
164      }
165      if (!rna.remainingQuantity)
166      {
167        remarks[remarks.length] = 'No quantity';
168      }
169      else if (rna.remainingQuantity < (rna.qc ? 1.22 : 1.1))
170      {
171        remarks[remarks.length] = 'Low quantity';
172      }
173      if (!rna.NDConc)
174      {
175        remarks[remarks.length] = 'No NDConc value';
176      }
177    }
178    else if (rna.stratagene)
179    {
180      if (!rna.NDConc && rna.usedQuantity)
181      {
182        remarks[remarks.length] = 'Use ' + Numbers.formatNumber(rna.usedQuantity, 2) + ' µg RNA';
183      }
184    }
185    else if (rna.external)
186    {
187      remarks[remarks.length] = 'Use ' + Numbers.formatNumber(rna.usedQuantity, 2) + ' µg RNA';
188    }
189    rna.remarks = remarks;
190  }
191 
192  function viewAsList(list)
193  {
194    for (var i = 0; i < list.length; i++)
195    {
196      var mrna = list[i];
197      var rna = mrna.rna;
198     
199      var idSuffix = mrna.bioWell.column + '.' + mrna.bioWell.row;
200      Main.removeClass(document.getElementById('row.'+idSuffix), 'empty');
201      setInnerHTML('rna.'+idSuffix, rna.name);
202      setInnerHTML('box.'+idSuffix, getPlateCoordinate(rna.bioWell, true));
203      setInnerHTML('ndconc.'+idSuffix, Numbers.formatNumber(rna.NDConc, 2));
204      setInnerHTML('remain.'+idSuffix, Numbers.formatNumber(rna.remainingQuantity, 2));
205      setInnerHTML('volume.'+idSuffix, Numbers.formatNumber(rna.volume, 1));
206      setInnerHTML('water.'+idSuffix, Numbers.formatNumber(rna.water, 1));
207      setInnerHTML('remarks.'+idSuffix, rna.remarks.join('; '));
208    }
209  }
210 
211 
212  function viewAsPlate(list)
213  {
214    var schema = PoolSchema.getById('<%=poolSchema%>');
215    Plate.init(<%=rows%>, <%=columns%>, schema, WellPainter);
216   
217    for (var i = 0; i < list.length; i++)
218    {
219      var mrna = list[i];
220      var well = mrna.bioWell;
221      Plate.getWell(well.row, well.column).setExtract(mrna);
222    }
223
224    Plate.paint(Plate.getWells());
225    PoolSchema.buildPoolTableRow(schema, <%=columns%>);
226    Main.show('plateview');
227  }
228
229  var WellPainter = function()
230  {
231    var painter = {};
232   
233    painter.getClassNameForWell = function(well)
234    {
235      var cls = '';
236      var mrna = well.extract;
237      if (mrna)
238      {
239        if (mrna.rna.qc) cls += ' qc';
240      }
241      return cls;
242    }
243   
244    painter.getWellText = function(well)
245    {
246      var text = '';
247      var mrna = well.extract;
248      if (mrna)
249      {
250        var rna = mrna.rna;
251        text += '<div class="rna">'+rna.name+'</div>';
252        text += '<div class="box">'+getPlateCoordinate(rna.bioWell, true)+'</div>';
253        text += '<div class="remain">'+Numbers.formatNumber(rna.remainingQuantity, 2, 'µg')+'</div>';
254        text += '<div class="ndconc">'+Numbers.formatNumber(rna.NDConc, 2, 'ng/µl') + '</div>';
255
256        if (rna.volume && rna.water)
257        {
258          text += '<div><span class="volume">'+Numbers.formatNumber(rna.volume, 1)+'</span>';
259          text += ' + <span class="water">'+Numbers.formatNumber(rna.water, 1)+'</span>µl</div>';
260        }
261        text += '<div class="remarks">'+ rna.remarks.join('; ') + '</div>';
262      }
263      return text;
264    }
265
266    return painter;
267  }();
268  </script>
269  <style>
270  table.protocolheader
271  {
272    width: 100%;
273  }
274
275  table.protocolheader > tbody > tr
276  {
277    height: 1.25em;
278  }
279
280  table.protocolheader > tbody > tr > th
281  {
282    width: 50%;
283    text-align: left;
284    font-size: 1em;
285  }
286 
287  #listview
288  {
289    width: 100%;
290    font-size: 85%;
291    border-collapse: collapse;
292    border: 1px solid #000000;
293  }
294 
295  #listview tr.evencol
296  {
297    background-color: #E8E8E8;
298  }
299 
300  #listview thead
301  {
302    border: 1px solid #000000;
303    background-color: #E8E8E8;
304  }
305 
306  #listview tbody
307  {
308    page-break-inside: avoid;
309    border-top: 1px solid #000000;
310    border-bottom: 1px solid #000000;
311  }
312 
313  #listview th
314  {
315    border-left: 1px solid #000000;
316  }
317 
318  #listview td
319  {
320    border-left: 1px solid #000000;
321    border-top: 1px dotted #666666;
322    vertical-align: middle;
323  }
324 
325  #listview .col-num
326  {
327    width: 1.75em;
328    text-align: center;
329    font-size: 125%;
330    font-weight: bold;
331    vertical-align: top;
332  }
333 
334  #listview .rna
335  {
336    width: 9em;
337    text-align: center;
338  }
339 
340  #listview .empty .rna
341  {
342    font-style: italic;
343    color: #666666;
344    text-align: center;
345  }
346 
347  #listview .box
348  {
349    width: 8em;
350    text-align: center;
351  }
352  #listview .workplate
353  {
354    width: 5em;
355    text-align: center;
356  }
357  #listview .ndconc
358  {
359    width: 4.5em;
360    padding-right: 0.5em;
361    text-align: right;
362  }
363  #listview .remain
364  {
365    width: 4.5em;
366    padding-right: 0.5em;
367    text-align: right;
368  }
369  #listview .volume
370  {
371    width: 3.5em;
372    padding-right: 0.5em;
373    text-align: right;
374    color: #C80000;
375  }
376  #listview .water
377  {
378    width: 3.5em;
379    padding-right: 0.5em;
380    text-align: right;
381    color: #0000C8;
382  }
383  #listview .remarks
384  {
385    vertical-align: top;
386    padding-left: 0.25em;
387  }
388 
389  /* Divide the 12 wells across the full page */
390  #plateview .well
391  {
392    width: 8.2%;
393    max-width: 8.2%;
394    min-width: 8.2%;
395  }
396   
397  #plateview .rowheader
398  {
399    width: 2em;
400  }
401 
402  #plateview .rna
403  {
404    font-weight: bold;
405  }
406  #plateview .ndconc
407  {
408    display: none;
409  }
410  #plateview .remain
411  {
412    display: none;
413  }
414  #plateview .volume
415  {
416    color: #C80000;
417  }
418  #plateview .water
419  {
420    color: #0000C8;
421  }
422  #plateview .remarks
423  {
424    color: #C80000;
425    font-style: italic;
426  }
427  #plateview .qc
428  {
429    background-image: url('../images/mrnaqc.png');
430    background-position: 95% 5%;
431    background-repeat: no-repeat;
432  }
433  </style>
434</head>
435<body onload="init()">
436  <div class="paper <%=view.equals("list") ? "" : "landscape"%>">
437  <div class="noprint fullwidth" style="border-bottom: 1px dashed #A0A0A0; padding-left: 1em; padding-bottom: 1em;">
438    <span class="button" onclick="window.print()" style="float: left; margin-right: 1em;">
439      <img src="../images/print.png">Print&hellip;
440    </span>
441    <b>Note!</b> 
442    <%
443    if (view.equals("list"))
444    {
445      %>
446      For better printing reduce margins to about <i>5mm</i> and set page orientation
447      to <i>portrait</i>. To fit everything on a single page, scale down to <i>60-70%</i>.
448      <%
449    }
450    else
451    {
452      %>
453      For better printing reduce margins to about <i>5mm</i> and set page orientation
454      to <i>landscape</i>. The recommended scale is <i>100%</i>.
455      <%
456    }
457    %>
458    <br clear="all">
459  </div>
460 
461  <h1>Lab tracking protocol for mRNA and cDNA preparation <span class="reggie">Reggie <%=reggie.getAbout().getVersion() %></span></h1>
462
463  <table style="width: 100%; border: 0px;" class="protocolheader">
464  <tr valign="top">
465    <th style="width: 30%;">Work plate: <%=HTML.encodeTags(plate.getName())%></th>
466    <th style="width: 20%; text-align: right;">Comments:&nbsp;</th>
467    <td rowspan="3"><%=HTML.encodeTags(plate.getDescription()) %></td>
468  </tr>
469  <tr>
470    <th style="width: 50%;" colspan="2">Date+operator for mRNA:</th>
471  </tr>
472  <tr>
473    <th style="width: 50%;" colspan="2">Date+operator for cDNA:</th>
474  </tr>
475  </table>
476
477  <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>
478  <div class="messagecontainer error" id="errorMessage" style="display: none;"></div>
479  <%
480  if (view.equals("list"))
481  {
482    %>
483    <table style="width: 100%;" id="listview">
484    <thead>
485      <tr class="toprow">
486        <th></th>
487        <th class="rna"></th>
488        <th class="box">Storage</th>
489        <th class="workplate">Work</th>
490        <th>NDConc</th>
491        <th>Remain</th>
492        <th colspan="2">Volume</th>
493        <th></th>
494      </tr>
495      <tr>
496        <th></th>
497        <th class="rna">RNA</th>
498        <th class="box">box</th>
499        <th class="workplate">plate</th>
500        <th>(ng/µl)</th>
501        <th>(µg)</th>
502        <th>(µl)</th>
503        <th>H<sub>2</sub>O</th>
504        <th>Remarks</th>
505      </tr>
506    </thead>
507    <%
508    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
509    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
510    for (int c = 0; c < columns; ++c)
511    {
512      String rowClass = c % 2 == 0 ? "evencol" : "oddcol";
513      %>
514      <tbody>
515      <%
516      for (int r = 0; r < rows; ++r)
517      {
518        String idSuffix = c + "." + r;
519        %>
520        <tr class="<%=rowClass%> empty" id="row.<%=idSuffix%>">
521          <%
522          if (r == 0)
523          {
524            %>
525            <td class="col-num" rowspan="<%=rows%>"><%=c+1%></td>
526            <%
527          }
528          %>
529          <td class="rna" id="rna.<%=idSuffix%>">empty</td>
530          <td class="box" id="box.<%=idSuffix%>"></td>
531          <td class="workplate"><%=rowF.format(r)+colF.format(c)%></td>
532          <td class="ndconc" id="ndconc.<%=idSuffix%>"></td>
533          <td class="remain" id="remain.<%=idSuffix%>"></td>
534          <td class="volume" id="volume.<%=idSuffix%>"></td>
535          <td class="water" id="water.<%=idSuffix%>"></td>
536          <td class="remarks" id="remarks.<%=idSuffix%>"></td>
537        </tr>
538        <%
539      }
540      %>
541      </tbody>
542      <%
543    }
544    %>
545    </table>
546    <%
547  }
548  else
549  {
550    %>
551    <table class="plate" style="margin: 0em 0 0 0; width: 100%; display: none;" id="plateview">
552    <%
553    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
554    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
555    %>
556    <tr class="header">
557      <th></th>
558      <%
559      for (int c = 0; c < columns; ++c)
560      {
561        %>
562        <th id="col.<%=c%>"><%=colF.format(c)%></th>
563        <%
564      }
565      %>
566    </tr>
567    <tbody>
568    <%
569    for (int r = 0; r < rows; ++r)
570    {
571      String row = rowF.format(r);
572      %>
573      <tr class="row-<%=r%>">
574        <th id="row.<%=r%>" class="rowheader"><%=row%></th>
575        <%
576        for (int c = 0; c < columns; ++c)
577        {
578          %>
579          <td class="well col-<%=c%>" id="well.<%=r%>.<%=c%>"></td>
580          <%
581        }
582        %>
583      </tr>
584      <%
585    }
586    %>
587    </tbody>
588    <tr id="pool-row">
589      <th colspan="13">&nbsp;</th>
590    </tr>
591    </table>
592    <%
593  }
594  %>
595  </div>
596</body>
597</html>
598<%
599}
600finally
601{
602  if (dc != null) dc.close();
603}
604%>
Note: See TracBrowser for help on using the repository browser.