source: trunk/www/views/experiments/explorer/view/plotter.jsp @ 5114

Last change on this file since 5114 was 5114, checked in by Nicklas Nordborg, 13 years ago

References #1386: Plot function in the bioassay table in experiment explorer

First version is checked in since it is friday. Most major functions should be in place. Some minor options may need tweaking as well as some visual aspects. As usual, error handling must be tested.

The code for generating an image with a stack trace has been moved to ThrowableUtil?.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 13.4 KB
Line 
1<%-- $Id: plotter.jsp 5114 2009-10-02 12:29:28Z nicklas $
2  ------------------------------------------------------------------
3  BioArray Software Environment (BASE) - http:// base.thep.lu.se/
4
5  This file is part of BASE - BioArray Software Environment.
6  Available at http://base.thep.lu.se/
7
8  BASE is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License
10  as published by the Free Software Foundation; either version 3
11  of the License, or (at your option) any later version.
12
13  BASE is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with BASE. If not, see <http://www.gnu.org/licenses/>.
20  ------------------------------------------------------------------
21
22  @author Nicklas
23  @version 2.0
24--%>
25<%@ page session="false"
26  import="net.sf.basedb.core.SessionControl"
27  import="net.sf.basedb.core.DbControl"
28  import="net.sf.basedb.core.Experiment"
29  import="net.sf.basedb.core.BioAssaySet"
30  import="net.sf.basedb.core.BioAssay"
31  import="net.sf.basedb.core.RawDataType"
32  import="net.sf.basedb.core.RawDataProperty"
33  import="net.sf.basedb.core.Formula"
34  import="net.sf.basedb.core.IntensityTransform"
35  import="net.sf.basedb.core.AnnotationType"
36  import="net.sf.basedb.core.ItemQuery"
37  import="net.sf.basedb.core.ItemResultList"
38  import="net.sf.basedb.core.Include"
39  import="net.sf.basedb.core.Permission"
40  import="net.sf.basedb.core.Item"
41  import="net.sf.basedb.core.query.Orders"
42  import="net.sf.basedb.core.query.Hql"
43  import="net.sf.basedb.core.query.Restrictions"
44  import="net.sf.basedb.core.query.Restriction"
45  import="net.sf.basedb.core.query.Expressions"
46  import="net.sf.basedb.clients.web.ExperimentExplorer"
47  import="net.sf.basedb.clients.web.Base"
48  import="net.sf.basedb.clients.web.DynamicUtil"
49  import="net.sf.basedb.clients.web.util.HTML"
50  import="net.sf.basedb.util.Values"
51  import="net.sf.basedb.clients.web.WebException"
52  import="net.sf.basedb.clients.web.taglib.table.TableColumn"
53  import="java.util.List"
54  import="java.util.LinkedList"
55%>
56<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
57<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
58<%!
59private static void addFormulaOption(StringBuilder options, String formula, String title, String description)
60{
61  options.append("<option value=\"").append(HTML.encodeTags(formula)).append("\"");
62  options.append(" title=\"").append(HTML.encodeTags(description)).append("\"");
63  options.append(">").append(HTML.encodeTags(title)).append("\n");
64}
65%>
66<%
67final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
68final float scale = Base.getScale(sc);
69final String ID = sc.getId();
70final DbControl dc = sc.newDbControl();
71try
72{
73  final int bioAssaySetId = Values.getInt(request.getParameter("bioAssaySetId"));
74  final int reporterIndex = Values.getInt(request.getParameter("reporterIndex"));
75  final int positionIndex = Values.getInt(request.getParameter("positionIndex"));
76  final boolean needAverageMethod = positionIndex == ExperimentExplorer.SPOT_AVG;
77 
78  BioAssaySet bas = BioAssaySet.getById(dc, bioAssaySetId);
79  RawDataType rdt = bas.getRawDataType();
80  Experiment experiment = bas.getExperiment();
81  int maxRawMappings = bas.getMaxRawMappingsForSpot();
82  IntensityTransform transform = bas.getIntensityTransform();
83 
84  List<TableColumn> formulas = new LinkedList<TableColumn>();
85  DynamicUtil.addSpotColumns(formulas, dc, rdt.getChannels(), transform);
86  DynamicUtil.addFormulaColumns(formulas, dc, rdt, Formula.Type.COLUMN_EXPRESSION, 
87      transform, "", "", maxRawMappings == 1);
88  DynamicUtil.addExtraColumns(formulas, dc, bas, "ev", "#", "[Xtra] ");
89  if (maxRawMappings == 1)
90  {
91    DynamicUtil.addRawDataColumns(formulas, dc, rdt, "", "", "[Raw] ");
92  }
93 
94  StringBuilder formulaOptions = new StringBuilder();
95  for (TableColumn tc : formulas)
96  {
97    if (tc.getJepExpression() != null && tc.getDatatype().isNumerical())
98    {
99      if (!needAverageMethod || tc.getAverageMethod() != Formula.AverageMethod.NONE)
100      {
101        String jepExpression = tc.getJepExpression();
102        addFormulaOption(formulaOptions, jepExpression, tc.getTitle(), tc.getDescription());
103      }
104    }
105  }
106 
107  String title = HTML.encodeTags("Plot " + bas.getName());
108  final boolean hasCreateFilePermission = sc.hasPermission(Permission.CREATE, Item.FILE);
109  %>
110  <base:page type="popup" title="<%=title%>">
111  <base:head styles="tabcontrol.css" scripts="tabcontrol.js">
112  <script language="JavaScript">
113
114  var averageMethods = new Array();
115  <%
116  for (TableColumn tc : formulas)
117  {
118    if (tc.getJepExpression() != null && tc.getDatatype().isNumerical())
119    {
120      if (!needAverageMethod || tc.getAverageMethod() != Formula.AverageMethod.NONE)
121      {
122        %>
123        averageMethods[averageMethods.length] = '<%=tc.getAverageMethod().name()%>';
124        <%
125      }
126    }
127  }
128  %>
129 
130  function validate()
131  {
132    var plotType = getPlotType();
133    if (plotType == 'scatter')
134    {
135      return validateScatterPlot();
136    }
137    return false;
138  }
139  function validateScatterPlot()
140  {
141    var frm = document.forms['scatter'];
142    if (Main.trimString(frm.yFormula.value) == '')
143    {
144      alert("You must enter an expression for the Y axis");
145      frm.yFormula.focus();
146      return false;
147    }
148    return true;
149  }
150 
151  var plotType = 'scatter';
152  function getPlotType()
153  {
154    return plotType;
155  }
156
157  function switchTab(tabControlId, tabId)
158  {
159    if (tabId == 'scatter' || tabId == 'histogram')
160    {
161      plotType = tabId;
162    }
163    TabControl.setActiveTab(tabControlId, tabId);
164  }
165
166  function presetOnChange(list, formula, label)
167  {
168    var index = list.selectedIndex;
169    var frm = document.forms['scatter'];
170    if (frm.averageMethod)
171    {
172      var avgMethod = averageMethods[index-1];
173      Forms.selectListOption(frm.averageMethod, avgMethod);
174    }
175    formula.value = list[index].value;
176    if (label && list[index].value != '') label.value = list[index].text;
177    list.selectedIndex = 0;
178  }
179   
180  function generatePlotUrl(fullSize)
181  {
182    if (validate())
183    {
184      var plotFrm = document.forms['plot'];
185      var url = getRoot() + 'views/experiments/explorer/plot';
186      url += '?ID=<%=ID%>&bioAssaySetId=<%=bioAssaySetId%>';
187      url += '&reporterIndex=<%=reporterIndex%>&positionIndex=<%=positionIndex%>';
188      url += '&title='+Main.encodeURI(plotFrm.title.value);
189      url += '&subTitle='+Main.encodeURI(plotFrm.subTitle.value);
190      if (fullSize)
191      {
192        url += '&width='+plotFrm.width.value;
193        url += '&height='+plotFrm.height.value;
194      }
195 
196      var plotType = getPlotType();
197      if (plotType == 'scatter')
198      {
199        var frm = document.forms['scatter'];
200        url += '&type=scatter';
201        url += '&y='+Main.encodeURI(frm.yFormula.value);
202        url += '&yLog='+(frm.yLog.checked ? 1 : 0);
203        url += '&yLabel='+Main.encodeURI(frm.yLabel.value);
204        url += '&showXLabels='+(frm.hideXLabels.checked ? 0 : 1);
205        if (frm.averageMethod)
206        {
207          url += '&averageMethod=' + frm.averageMethod[frm.averageMethod.selectedIndex].value;
208        }
209      }
210      url += '&' + new Date().getTime();
211      return url;
212    }
213  }
214 
215  function openExpressionBuilder(title, frmName, inputName, formulaType)
216  {
217    if (!document.forms[frmName][inputName].disabled)
218    {
219      var restrictions = formulaType == '<%=Formula.Type.COLUMN_RESTRICTION.name()%>';
220      Main.expressionBuilder('<%=ID%>', title, frmName, inputName, formulaType, '<%=rdt.getId()%>', <%=rdt.getChannels()%>, restrictions, <%=bas.getId()%>);
221    }
222  }
223 
224  function previewPlot()
225  {
226    var url = generatePlotUrl(false);
227    if (url)
228    {
229      url += '&width=600&height=400';
230      var image = document.getElementById('preview');
231      if (image.src.indexOf('plot_select') == -1)
232      {
233        var background = document.getElementById('background');
234        background.src = image.src;
235      }
236      image.src = getRoot()+'images/plot_generating.gif';
237      // Otherwise, the browser refuses to display the 'plot_generating.gif' while we are waiting.
238      //setTimeout('changePreviewImage()', 100);
239      image.realImg = new Image();
240      image.realImg.onload = changePreviewImage;
241      image.realImg.src = url;
242    }
243  }
244 
245  function changePreviewImage()
246  {
247    var image = document.getElementById('preview');
248    image.src = image.realImg.src;
249    image.realImg = null;
250  }
251 
252  function viewPlot()
253  {
254    var url = generatePlotUrl(true);
255    if (url)
256    {
257      var frm = document.forms['plot'];
258      var width = parseInt(frm.width.value);
259      var height = parseInt(frm.height.value);
260      if (!width || width < 600) width = 600;
261      if (!height || height < 400) height = 400;
262      Main.openPopup('../../plotter/view.jsp?ID=<%=ID%>&title='+Main.encodeURI(frm.title.value), 'ViewPlot', width+50, height+100);
263    }
264  }
265 
266  function downloadPlot()
267  {
268    var url = generatePlotUrl(true);
269    if (url)
270    {
271      Main.openPopup('../../plotter/download.jsp?ID=<%=ID%>', 'DownloadPlot', 500, 260);
272    }
273  }
274 
275  function savePlotAs()
276  {
277    var url = generatePlotUrl(true);
278    if (url)
279    {
280      Main.openPopup('../../plotter/save_as.jsp?ID=<%=ID%>', 'SavePlotAs', 500, 260);
281    }
282  }
283 
284  function init()
285  {
286   
287  }
288  </script>
289  </base:head>
290  <base:body onload="init()">
291 
292  <h3 class="docked"><%=title%> <base:help tabcontrol="plotType" /></h3>
293  <div class="boxed">
294 
295  <table border="0" cellspacing="0" cellpadding="2" width="100%">
296  <tr valign="bottom">
297    <td>
298    <form name="plot">
299    <table class="form">
300    <tr>
301      <td class="prompt">Plot title</td>
302      <td colspan="2"><input type="text" class="text" size="30" maxlength="255" name="title" 
303        value="<%=HTML.encodeTags(bas.getName())%>"></td>
304    </tr>
305    <tr>
306      <td class="prompt">Subtitle</td>
307      <td colspan="2"><input type="text" class="text" size="30" maxlength="255" name="subTitle" 
308        value=""></td>
309    </tr>
310    <tr>
311      <td class="prompt">Width</td>
312      <td><input type="text" class="text" size="12" maxlength="10" name="width" 
313        value="800" onkeypress="return Numbers.integerOnly(event)"></td>
314      <td rowspan="2" valign="center">(not used by preview)</td>
315    </tr>
316    <tr>
317      <td class="prompt">Height</td>
318      <td><input type="text" class="text" size="12" maxlength="10" name="height" 
319        value="600" onkeypress="return Numbers.integerOnly(event)"></td>
320    </tr>
321    </table>
322    </form>
323    <p>
324
325    <t:tabcontrol id="plotType" 
326      style="<%="width: "+(int)(scale*340)+"px;"%>" 
327      contentstyle="<%="height: "+(int)(scale*340)+"px;"%>"
328      switch="switchTab">
329    <t:tab id="scatter" title="Scatter plot" helpid="plotter.scatterplot"
330      tooltip="Create a scatter plot">
331      <form name="scatter">
332      <table border="0" cellspacing="0" cellpadding="2" class="form">
333      <tr>
334        <td class="prompt" colspan="3">Y-axis</td>
335      </tr>
336      <tr>
337        <td>&nbsp;Presets</td>
338        <td colspan="2">
339        <select name="yPresets" style="width: 20em;"
340          onchange="presetOnChange(this, this.form.yFormula, this.form.yLabel)" 
341          >
342          <option value="">- select from list or enter formula below -
343          <%=formulaOptions.toString()%>
344        </select>
345        </td>
346      </tr>
347      <tr>
348        <td>&nbsp;Expression</td>
349        <td><input type="text" class="text required" size="30" maxlength="255" name="yFormula"></td>
350        <td>
351          <base:button
352            title=""
353            image="expression_builder.gif"
354            tooltip="Use the Expression builder"
355            onclick="openExpressionBuilder('Y-axis expression', 'scatter', 'yFormula', 'COLUMN_EXPRESSION')"
356          />
357        </td>
358      </tr>
359      <tr>
360        <td>&nbsp;Label</td>
361        <td colspan="2"><input type="text" class="text" size="30" maxlength="255" name="yLabel"></td>
362      </tr>
363      <tr>
364        <td>&nbsp;Log scale</td>
365        <td colspan="2"><input type="checkbox" name="yLog" value="1"></td>
366      </tr>
367      <%
368      if (positionIndex == ExperimentExplorer.SPOT_AVG)
369      {
370        %>
371        <tr>
372          <td>&nbsp;Average</td>
373          <td>
374            <select name="averageMethod">
375            <%
376            for (Formula.AverageMethod method : Formula.AverageMethod.values())
377            {
378              if (method != Formula.AverageMethod.NONE)
379              {
380                %>
381                <option value="<%=method.name()%>"><%=method.toString()%></option>
382                <%
383              }
384            }
385            %>
386            </select>
387          </td>
388        <% 
389      }
390      %>
391      <tr>
392        <td class="prompt" colspan="3">X-axis</td>
393      </tr>
394      <tr>
395        <td>&nbsp;No labels</td>
396        <td><input type="checkbox" name="hideXLabels" value="1"></td>
397      </tr>
398      </table>
399      </form>
400    </t:tab>   
401    </t:tabcontrol>
402    </td>
403    <td xstyle="width: 600px;">
404      <div style="position: relative; top: 0px; left: 0px; width: 600px; height: 400px; padding-bottom: 2px;">
405      <img src="../../../../images/plot_empty.png" id="background" 
406        style="position: absolute; top: 0px; left: 0px; z-index: 1; border: 1px solid #999999;">
407      <img src="../../../../images/plot_select.gif" id="preview" 
408        style="position: relative; top: 0px; left: 0px; z-index: 2; border: 1px solid #999999;">
409      </div>
410    </td>
411  </tr>
412  </table>
413  </div>
414    <p>
415    <div align="center">
416    <base:buttongroup>
417      <base:button title="Preview" onclick="previewPlot()" 
418        image="plotter_preview.gif" tooltip="Generate a preview of the plot" 
419      />
420      <base:button title="View&hellip;" onclick="viewPlot()" 
421        image="plotter.gif" tooltip="View a fullsized version of the plot (in a popup)" 
422      />
423      <base:button title="Download&hellip;" onclick="downloadPlot()" 
424        image="download.gif"
425        tooltip="Downlad a fullsized version of the plot to you computer" 
426      />
427      <base:button title="Save as&hellip;" onclick="savePlotAs()" 
428        image="<%=hasCreateFilePermission ? "saveas.gif" : "saveas_disabled.gif"%>"
429        disabled="<%=!hasCreateFilePermission%>"
430        tooltip="<%=hasCreateFilePermission ? 
431          "Save a fullsized version of the plot on the BASE server" :
432          "You don't have permission to create files" %>" 
433      />
434      <base:button onclick="window.close()" title="Close" />
435    </base:buttongroup>
436    </div>
437 
438  </base:body>
439  </base:page>
440  <%
441}
442finally
443{
444  if (dc != null) dc.close();
445}
446%>
Note: See TracBrowser for help on using the repository browser.