source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/mrna_protocol2.jsp @ 2509

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

Merge Reggie 2.15.3 to the trunk.

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