source: trunk/www/common/expression_builder.jsp @ 4912

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

References #1120: The dynamic part of BASE should keep track whether intensity data is in log space or not

Deprecated VirtualColumn?.channel(). Added functionality in the core to make it possible to convert transformed intensities back to regular intensities. Added RawChannelFunction? for cases where the stored intensity values are needed without conversion. What remains now is to check plug-ins and tools to make sure that the work correctly with both transformed and non-transformed data.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 16.3 KB
Line 
1<%-- $Id: expression_builder.jsp 4912 2009-04-29 11:49:20Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2006, 2007 Nicklas Nordborg
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 modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12
13  BASE is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  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.DbControl"
27  import="net.sf.basedb.core.SessionControl"
28  import="net.sf.basedb.core.Item"
29  import="net.sf.basedb.core.BioAssaySet"
30  import="net.sf.basedb.core.RawDataType"
31  import="net.sf.basedb.core.RawDataTypes"
32  import="net.sf.basedb.core.RawDataProperty"
33  import="net.sf.basedb.core.ExtendedProperty"
34  import="net.sf.basedb.core.ExtendedProperties"
35  import="net.sf.basedb.core.Formula"
36  import="net.sf.basedb.core.ReporterList"
37  import="net.sf.basedb.core.ItemQuery"
38  import="net.sf.basedb.core.Include"
39  import="net.sf.basedb.core.query.Orders"
40  import="net.sf.basedb.core.query.Hql"
41  import="net.sf.basedb.util.Enumeration"
42  import="net.sf.basedb.util.jep.Jep"
43  import="net.sf.basedb.clients.web.Base"
44  import="net.sf.basedb.util.Values"
45  import="net.sf.basedb.clients.web.util.HTML"
46  import="net.sf.basedb.clients.web.DynamicUtil"
47  import="net.sf.basedb.clients.web.taglib.table.TableColumn"
48  import="java.util.List"
49  import="java.util.LinkedList"
50%>
51<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
52<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
53<%
54  String title = request.getParameter("title");
55  String form = request.getParameter("form");
56  String textarea = request.getParameter("textarea");
57  String callback = request.getParameter("callback");
58  Formula.Type formulaType = Formula.Type.valueOf(request.getParameter("formulatype"));
59  RawDataType rawDataType = RawDataTypes.getRawDataType(request.getParameter("rawdatatype"));
60  int bioAssaySetId = Values.getInt(request.getParameter("bioassayset_id"), -1);
61  boolean restrictions = Values.getBoolean(request.getParameter("restrictions"));
62  int channels = Values.getInt(request.getParameter("channels"));
63  final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
64 
65  DbControl dc = sc.newDbControl();
66  try
67  {
68    BioAssaySet bas = bioAssaySetId == -1 ? null : BioAssaySet.getById(dc, bioAssaySetId);
69    int maxRawMappings = bas == null ? 1 : bas.getMaxRawMappingsForSpot();
70
71    List<TableColumn> spotProperties = new LinkedList<TableColumn>();
72    DynamicUtil.addSpotColumns(spotProperties, dc, channels);
73    List<TableColumn> rawProperties = new LinkedList<TableColumn>();
74    if (rawDataType != null)
75    {
76      DynamicUtil.addFormulaColumns(spotProperties, dc, rawDataType, Formula.Type.COLUMN_EXPRESSION, "", "", maxRawMappings == 1);
77      if (bas != null) DynamicUtil.addExtraColumns(spotProperties, dc, bas, "", "", "[Xtra] ");
78      if (maxRawMappings == 1) DynamicUtil.addRawDataColumns(rawProperties, dc, rawDataType, "", "", "");
79    }
80    List<TableColumn> reporterProperties = new LinkedList<TableColumn>();
81    DynamicUtil.addReporterColumns(reporterProperties, dc, "", "", "");
82   
83    ItemQuery<ReporterList> reporterListQuery = ReporterList.getQuery();
84    reporterListQuery.include(Include.MINE, Include.SHARED, Include.IN_PROJECT, Include.OTHERS);
85    reporterListQuery.order(Orders.asc(Hql.property("name")));
86    List<ReporterList> reporterLists = reporterListQuery.list(dc);
87   
88  %>
89  <base:page type="popup" title="<%=title%>">
90  <base:head scripts="table.js" styles="toolbar.css">
91    <script language="JavaScript">
92    function getText()
93    {
94      document.forms['expression'].expression.value = window.opener.document.forms['<%=form%>'].elements['<%=textarea%>'].value;
95    }
96    function setExpressionAndClose()
97    {
98      var value = document.forms['expression'].expression.value;
99      <%
100      if (callback != null)
101      {
102        StringBuilder sb = new StringBuilder();
103        sb.append("window.opener.");
104        sb.append(callback).append("(");
105        if (form != null) sb.append("'").append(form).append("',");
106        if (textarea != null) sb.append("'").append(textarea).append("',");
107        sb.append("value)");
108        %>
109        <%=sb.toString()%>
110        <%
111      }
112      else
113      {
114        %>
115        var textElement = window.opener.document.forms['<%=form%>'].elements['<%=textarea%>'];
116        if (textElement.type == 'text') value = value.replace(/\n/g, '');
117        textElement.value = value;
118        <%
119      }
120      %>
121      window.close();
122    }
123    function insertSelected(list, prefix, suffix)
124    {
125      var value = list[list.selectedIndex].value;
126      if (value != '')
127      {
128        if (prefix) value = prefix + value;
129        if (!suffix) suffix = '';
130        encloseSelection(value, suffix);
131      }
132      list.selectedIndex = 0;
133    }
134    function insertReporterListFunction()
135    {
136      var frm = document.forms['expression'];
137      var listFunction = frm.listFunction[frm.listFunction.selectedIndex].value;
138      var listId = frm.reporterList[frm.reporterList.selectedIndex].value;
139      encloseSelection(listFunction+'(' + listId + ')', '');
140      frm.reporterList.selectedIndex = 0;
141    }
142 
143    /*
144      Enclose the selected text with prefix and suffix. Code taken
145      from Trac: http://projects.edgewall.com/trac/
146    */
147    function encloseSelection(prefix, suffix)
148    {
149      var frm = document.forms['expression'];
150      var textarea = frm.expression;
151      textarea.focus();
152        var start, end, sel, scrollPos, subst;
153        if (typeof(document["selection"]) != "undefined")
154        {
155          sel = document.selection.createRange().text;
156        }
157        else if (typeof(textarea["setSelectionRange"]) != "undefined")
158        {
159          start = textarea.selectionStart;
160          end = textarea.selectionEnd;
161          scrollPos = textarea.scrollTop;
162          sel = textarea.value.substring(start, end);
163        }
164        if (sel.match(/ $/))
165        {
166          // exclude ending space char, if any
167            sel = sel.substring(0, sel.length - 1);
168            suffix = suffix + " ";
169        }
170        subst = prefix + sel + suffix;
171        if (typeof(document["selection"]) != "undefined")
172        {
173          var range = document.selection.createRange().text = subst;
174          textarea.caretPos -= suffix.length;
175        }
176        else if (typeof(textarea["setSelectionRange"]) != "undefined")
177        {
178          textarea.value = textarea.value.substring(0, start) + subst +
179                           textarea.value.substring(end);
180          if (sel)
181          {
182            textarea.setSelectionRange(start + subst.length, start + subst.length);
183          }
184          else
185          {
186            textarea.setSelectionRange(start + prefix.length, start + prefix.length);
187          }
188          textarea.scrollTop = scrollPos;
189        }
190      }
191   
192    var properties = new Array();
193    <%
194    for (TableColumn tc : rawProperties)
195    {
196      %>
197      properties['raw.<%=tc.getProperty()%>'] = 1;
198      <%
199    }
200    for (TableColumn tc : reporterProperties)
201    {
202      %>
203      properties['reporter.<%=tc.getProperty()%>'] = 1;
204      <%
205    }
206    %>
207     
208    function validateOnClick()
209    {
210      var frm = document.forms['expression'];
211      if (frm.expression.value != '')
212      {
213        var expression = frm.expression.value.replace('if(', 'jepIf(');
214        try
215        {
216          var result = eval(expression);
217          alert('The expressions seems to be ok.\nNote! This feature is experimental and may not be 100% correct.');
218        }
219        catch (er)
220        {
221          alert(er + '\nNote! This feature is experimental and may not be 100% correct.');
222        }
223      }
224    }
225   
226    function raw(property)
227    {
228      <%
229      if (maxRawMappings != 1)
230      {
231        %>
232        throw 'Cannot use function raw() for bioassayset that has multiple mappings to raw data';
233        <%
234      }
235      %>
236      var rdt = '<%=rawDataType == null ? "" : rawDataType.getId()%>';
237      if (!property) throw 'Property must be specified for function raw()';
238      if (rdt == '') throw 'Cannot use function raw(). No raw data type selected';
239      if (!properties['raw.'+property]) throw 'Property '+property+' not found for raw data type ' + rdt;
240      return Math.random() * 100;
241    }
242   
243    function mean(property)
244    {
245      var rdt = '<%=rawDataType == null ? "" : rawDataType.getId()%>';
246      if (!property) throw 'Property must be specified for function mean()';
247      if (rdt == '') throw 'Cannot use function mean(). No raw data type selected';
248      if (!properties['property.'+property]) throw 'Property '+property+' not found for raw data type ' + rdt;
249      return Math.random() * 100;
250    }
251 
252    function ch(channel)
253    {
254      checkChannel('ch()', channel);
255      return channel;
256    }
257    function rawCh(channel)
258    {
259      checkChannel('rawCh()', channel);
260      return channel;
261    }
262    function checkChannel(name, channel)
263    {
264      var type = '<%=formulaType.name()%>';
265      if (type == '<%=Formula.Type.INTENSITY_EXPRESSION.name()%>')
266      {
267        // Channel function not available
268        throw 'Function ' + name + ' is not available for ' + type;
269      }
270      var channels = <%=channels%>;
271      if (!channel || channel <= 0 || channel > channels)
272      {
273        throw 'Invalid channel: ' + channel + '; must be between 1 and '+ channels;
274      }
275    }
276
277
278   
279    function pos()
280    {
281      return Math.random() * 100;
282    }
283    function rep(property)
284    {
285      if (!property) throw 'Property must be specified for function rep()';
286      if (!properties['reporter.'+property]) throw 'Property '+property+' not found for reporter';
287      return Math.random() * 100;
288    }
289   
290    function xtra(arg)
291    {
292      if (!arg) throw 'One argument is required for function xtra()';
293      return Math.random() * 100;
294    }
295   
296    function log(value)
297    {
298      return Math.log(value);
299    }
300    function log2(value)
301    {
302      return Math.log(value);
303    }
304    function ln(value)
305    {
306      return Math.log(value);
307    }
308    function sqrt(value)
309    {
310      return Math.sqrt(value);
311    }
312    function abs(value)
313    {
314      return Math.abs(value);
315    }
316    function exp(value)
317    {
318      return Math.exp(value);
319    }
320    function score(reporterListId)
321    {
322      return Math.random() * 100;
323    }
324    function jepIf(condition, ifTrue, ifFalse)
325    {
326      if (condition == undefined || ifTrue == undefined || ifFalse == undefined)
327      {
328        throw 'if() needs 3 arguments';
329      }
330      return condition ? ifTrue : ifFalse;
331    }
332    </script>
333  </base:head>
334  <base:body onload="getText()">
335 
336    <form name="expression" onsubmit="return false;">
337 
338        <h3 class="docked">Expression builder <base:help helpid="expressionbuilder" /></h3>
339       
340        <tbl:toolbar>
341          <tbl:label
342            style="width: 100px;"
343            title="Operators:"
344          />
345          <tbl:button 
346            title="AND"
347            tooltip="BOOLEAN AND: expr1 &amp;&amp; expr2"
348            onclick="encloseSelection(' &amp;&amp; ', '')"
349          />
350          <tbl:button 
351            title="OR"
352            tooltip="BOOLEAN OR: expr1 || expr2"
353            onclick="encloseSelection(' || ', '')"
354          />
355          <tbl:button 
356            title="NOT"
357            tooltip="BOOLEAN NOT: !expr1"
358            onclick="encloseSelection('!', '')"
359          />
360          <tbl:button 
361            title="=="
362            tooltip="EQUAL: expr1 == expr2"
363            onclick="encloseSelection(' == ', '')"
364          />
365          <tbl:button 
366            title="!="
367            tooltip="INEQUAL: expr1 != expr2"
368            onclick="encloseSelection(' != ', '')"
369          />
370          <tbl:button 
371            title="&lt;"
372            tooltip="LESS: expr1 &lt; expr2"
373            onclick="encloseSelection(' &lt; ', '')"
374          />
375          <tbl:button 
376            title="&lt;="
377            tooltip="LESS OR EQUAL: expr1 &lt;= expr2"
378            onclick="encloseSelection(' &lt;= ', '')"
379          />
380          <tbl:button 
381            title="&gt;="
382            tooltip="MORE OR EQUAL: expr1 &gt;= expr2"
383            onclick="encloseSelection(' &gt;= ', '')"
384            visible="<%=restrictions%>"
385          />
386          <tbl:button 
387            title="&gt;"
388            tooltip="MORE: expr1 &gt; expr2"
389            onclick="encloseSelection(' &gt; ', '')"
390          />
391          <tbl:button 
392            title="+"
393            tooltip="ADD: expr1 + expr2"
394            onclick="encloseSelection(' + ', '')"
395          />
396          <tbl:button 
397            title="-"
398            tooltip="SUBTRACT: expr1 - expr2"
399            onclick="encloseSelection(' - ', '')"
400          />
401          <tbl:button 
402            title="*"
403            tooltip="MULTIPLY: expr1 * expr2"
404            onclick="encloseSelection(' * ', '')"
405          />
406          <tbl:button 
407            title="/"
408            tooltip="DIVIDE: expr1 / expr2"
409            onclick="encloseSelection(' / ', '')"
410          />
411          <tbl:button 
412            title="( )"
413            tooltip="PARENTHESIS: (expr1)"
414            onclick="encloseSelection('(', ')')"
415          />
416        </tbl:toolbar>
417        <tbl:toolbar
418          style="border-top: 0px;"
419          >
420          <tbl:label
421            title="Functions:"
422            style="width: 100px;"
423          />
424          <%
425          Enumeration<String, String> functions = Jep.getFunctions();
426          for (int i = 0; i < functions.size(); ++i)
427          {
428            String function = functions.getKey(i);
429            %>
430            <tbl:button 
431              title="<%=function%>"
432              tooltip="<%=functions.getValue(i)%>"
433              onclick="<%="encloseSelection('" + function +"(', ')')"%>"
434            />
435            <%
436          }
437          %>
438          <tbl:label
439            title="Constants:"
440            style="width: 100px;"
441          />
442          <tbl:button 
443            title="null"
444            tooltip="The null (unknown) value"
445            onclick="<%="encloseSelection('', 'null')"%>"
446          />
447          <tbl:button 
448            title="pi"
449            tooltip="<%="The pi value: " + Math.PI %>"
450            onclick="<%="encloseSelection('', '"+Math.PI+"')"%>"
451          />
452          <tbl:button 
453            title="e"
454            tooltip="<%="The base of the natural logarithm: " + Math.E%>"
455            onclick="<%="encloseSelection('', '"+Math.E+"')"%>"
456          />
457        </tbl:toolbar>
458        <tbl:toolbar
459          style="border-top: 0px;">
460          <td class="label">Spot:
461            <select name="spot" onchange="insertSelected(this)" >
462            <option value="">- select -
463            <%
464            for (TableColumn tc : spotProperties)
465            {
466              if (tc.getJepExpression() != null)
467              {
468                %>
469                <option value="<%=tc.getJepExpression()%>" 
470                  title="<%=HTML.encodeTags(tc.getDescription())%>"><%=HTML.encodeTags(tc.getTitle())%>
471                <%
472              }
473            }
474            %>
475            </select>   
476          </td>
477          <%
478          if (rawDataType != null && rawDataType.isStoredInDb() && rawProperties.size() > 0)
479          {
480            %>
481            <td class="label">Raw data:
482              <select name="rawdata" onchange="insertSelected(this)" >
483              <option value="">- select -
484              <%
485              for (TableColumn tc : rawProperties)
486              {
487                %>
488                <option value="<%=tc.getJepExpression()%>" 
489                  title="<%=HTML.encodeTags(tc.getDescription())%>"><%=HTML.encodeTags(tc.getTitle())%>
490                <%
491              }
492              %>
493              </select>
494            </td>
495            <%
496          }
497          %>
498         
499          <td class="label">Reporter:
500            <select name="reporter" onchange="insertSelected(this)">
501            <option value="">- select -
502              <%
503              for (TableColumn tc : reporterProperties)
504              {
505                %>
506                <option value="<%=tc.getJepExpression()%>" 
507                  title="<%=HTML.encodeTags(tc.getDescription())%>"><%=HTML.encodeTags(tc.getTitle())%>
508                <%
509              }
510              %>
511            </select>
512        </tbl:toolbar>
513        <tbl:toolbar
514          style="border-top: 0px;"
515          visible="<%=reporterLists.size() > 0%>">
516          <td class="label">
517            Reporter lists:
518           
519            <select name="listFunction" >
520            <option value="score">score
521            <%
522            if (restrictions)
523            {
524              %>
525              <option value="inList">in
526              <option value="notInList">not in
527              <%
528            }
529            %>
530            </select>
531           
532            <select name="reporterList" onchange="insertReporterListFunction()">
533            <option value="">- select -
534              <%
535              for (ReporterList list : reporterLists)
536              {
537                %>
538                <option value="<%=list.getId()%>" 
539                  title="<%=HTML.encodeTags(list.getDescription())%>"><%=HTML.encodeTags(list.getName())%>
540                <%
541              }
542              %>
543            </select>
544          </td>
545        </tbl:toolbar>
546        <br>
547        <b>Expression</b><br>
548        <textarea name="expression" rows="16" cols="80" wrap="soft" style="width: 100%;"></textarea>
549
550        <br><br>
551        <table align="center">
552        <tr>
553          <td width="33%"><base:button 
554            onclick="validateOnClick()" title="Validate&hellip;" 
555            image="validate_formula.gif"
556            tooltip="Validate the expression. EXPERIMENTAL!!" /></td>
557          <td width="33%"><base:button onclick="setExpressionAndClose()" title="Ok" /></td>
558          <td width="33%"><base:button onclick="window.close()" title="Cancel" /></td>
559         
560        </tr>
561        </table>
562 
563    </form>
564  </base:body>
565  </base:page>
566  <%
567  }
568finally
569{
570  if (dc != null) dc.close();
571}
572%> 
Note: See TracBrowser for help on using the repository browser.