4925 |
08 May 09 |
nicklas |
1 |
/** |
4925 |
08 May 09 |
nicklas |
$Id$ |
4925 |
08 May 09 |
nicklas |
3 |
|
4925 |
08 May 09 |
nicklas |
Copyright (C) 2009 Nicklas Nordborg |
4925 |
08 May 09 |
nicklas |
5 |
|
4925 |
08 May 09 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
4925 |
08 May 09 |
nicklas |
Available at http://base.thep.lu.se/ |
4925 |
08 May 09 |
nicklas |
8 |
|
4925 |
08 May 09 |
nicklas |
BASE is free software; you can redistribute it and/or |
4925 |
08 May 09 |
nicklas |
modify it under the terms of the GNU General Public License |
4925 |
08 May 09 |
nicklas |
as published by the Free Software Foundation; either version 3 |
4925 |
08 May 09 |
nicklas |
of the License, or (at your option) any later version. |
4925 |
08 May 09 |
nicklas |
13 |
|
4925 |
08 May 09 |
nicklas |
BASE is distributed in the hope that it will be useful, |
4925 |
08 May 09 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
4925 |
08 May 09 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4925 |
08 May 09 |
nicklas |
GNU General Public License for more details. |
4925 |
08 May 09 |
nicklas |
18 |
|
4925 |
08 May 09 |
nicklas |
You should have received a copy of the GNU General Public License |
4925 |
08 May 09 |
nicklas |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
4925 |
08 May 09 |
nicklas |
21 |
*/ |
4925 |
08 May 09 |
nicklas |
22 |
package net.sf.basedb.util.export.spotdata; |
4925 |
08 May 09 |
nicklas |
23 |
|
4925 |
08 May 09 |
nicklas |
24 |
|
4925 |
08 May 09 |
nicklas |
25 |
import java.sql.SQLException; |
4925 |
08 May 09 |
nicklas |
26 |
import java.util.ArrayList; |
4925 |
08 May 09 |
nicklas |
27 |
import java.util.Arrays; |
4925 |
08 May 09 |
nicklas |
28 |
import java.util.Collection; |
4925 |
08 May 09 |
nicklas |
29 |
import java.util.LinkedHashMap; |
4925 |
08 May 09 |
nicklas |
30 |
import java.util.List; |
4925 |
08 May 09 |
nicklas |
31 |
import java.util.Map; |
4925 |
08 May 09 |
nicklas |
32 |
|
4925 |
08 May 09 |
nicklas |
33 |
import net.sf.basedb.core.BioAssay; |
4925 |
08 May 09 |
nicklas |
34 |
import net.sf.basedb.core.BioAssaySet; |
4925 |
08 May 09 |
nicklas |
35 |
import net.sf.basedb.core.DatabaseException; |
4925 |
08 May 09 |
nicklas |
36 |
import net.sf.basedb.core.DbControl; |
4925 |
08 May 09 |
nicklas |
37 |
import net.sf.basedb.core.DynamicResultIterator; |
4925 |
08 May 09 |
nicklas |
38 |
import net.sf.basedb.core.DynamicSpotQuery; |
4925 |
08 May 09 |
nicklas |
39 |
import net.sf.basedb.core.ProgressReporter; |
5373 |
03 Aug 10 |
nicklas |
40 |
import net.sf.basedb.core.Type; |
4925 |
08 May 09 |
nicklas |
41 |
import net.sf.basedb.core.VirtualColumn; |
4925 |
08 May 09 |
nicklas |
42 |
import net.sf.basedb.core.VirtualTable; |
4925 |
08 May 09 |
nicklas |
43 |
import net.sf.basedb.core.query.Dynamic; |
4925 |
08 May 09 |
nicklas |
44 |
import net.sf.basedb.core.query.Expressions; |
4925 |
08 May 09 |
nicklas |
45 |
import net.sf.basedb.core.query.JoinType; |
4925 |
08 May 09 |
nicklas |
46 |
import net.sf.basedb.core.query.Restrictions; |
4925 |
08 May 09 |
nicklas |
47 |
import net.sf.basedb.core.query.Selects; |
4925 |
08 May 09 |
nicklas |
48 |
import net.sf.basedb.core.query.SqlResult; |
5405 |
10 Sep 10 |
nicklas |
49 |
import net.sf.basedb.core.signal.ThreadSignalHandler; |
4925 |
08 May 09 |
nicklas |
50 |
import net.sf.basedb.util.Values; |
4925 |
08 May 09 |
nicklas |
51 |
import net.sf.basedb.util.basefile.BaseFileWriter; |
4925 |
08 May 09 |
nicklas |
52 |
import net.sf.basedb.util.formatter.Formatter; |
4925 |
08 May 09 |
nicklas |
53 |
import net.sf.basedb.util.formatter.IdentifiableFormatter; |
4925 |
08 May 09 |
nicklas |
54 |
import net.sf.basedb.util.formatter.ToStringFormatter; |
4925 |
08 May 09 |
nicklas |
55 |
|
4925 |
08 May 09 |
nicklas |
56 |
/** |
4925 |
08 May 09 |
nicklas |
A superclass for exporters that exports spot data to BASEfile format. |
4925 |
08 May 09 |
nicklas |
This class exposes several other configuration parameters that are |
4925 |
08 May 09 |
nicklas |
specific for BASEfile:s. |
4925 |
08 May 09 |
nicklas |
60 |
|
4925 |
08 May 09 |
nicklas |
@author Nicklas |
4925 |
08 May 09 |
nicklas |
@version 2.12 |
4925 |
08 May 09 |
nicklas |
@base.modified $Date$ |
4925 |
08 May 09 |
nicklas |
64 |
*/ |
4925 |
08 May 09 |
nicklas |
65 |
public abstract class BaseFileExporter |
4925 |
08 May 09 |
nicklas |
66 |
extends AbstractBioAssaySetExporter |
4925 |
08 May 09 |
nicklas |
67 |
{ |
4925 |
08 May 09 |
nicklas |
68 |
|
4925 |
08 May 09 |
nicklas |
69 |
private Map<String, String> parameters; |
4925 |
08 May 09 |
nicklas |
70 |
private BaseFileWriter out; |
6077 |
03 Aug 12 |
nicklas |
71 |
private boolean autoCloseWriters; |
4925 |
08 May 09 |
nicklas |
72 |
|
4925 |
08 May 09 |
nicklas |
73 |
protected BaseFileExporter() |
4925 |
08 May 09 |
nicklas |
74 |
{ |
4925 |
08 May 09 |
nicklas |
75 |
this.parameters = new LinkedHashMap<String, String>(); |
6077 |
03 Aug 12 |
nicklas |
76 |
this.autoCloseWriters = true; |
4925 |
08 May 09 |
nicklas |
77 |
} |
4925 |
08 May 09 |
nicklas |
78 |
|
4925 |
08 May 09 |
nicklas |
79 |
/* |
4925 |
08 May 09 |
nicklas |
Configuration properties |
4925 |
08 May 09 |
nicklas |
81 |
------------------------ |
4925 |
08 May 09 |
nicklas |
82 |
*/ |
4925 |
08 May 09 |
nicklas |
83 |
/** |
4925 |
08 May 09 |
nicklas |
Set the stream were the exported data should be written. |
4925 |
08 May 09 |
nicklas |
It is expected that the given writer is a fresh writer and |
4925 |
08 May 09 |
nicklas |
that no data has been written to it yet. |
4925 |
08 May 09 |
nicklas |
87 |
*/ |
4925 |
08 May 09 |
nicklas |
88 |
public void setWriter(BaseFileWriter out) |
4925 |
08 May 09 |
nicklas |
89 |
{ |
4925 |
08 May 09 |
nicklas |
90 |
this.out = out; |
4925 |
08 May 09 |
nicklas |
91 |
} |
4925 |
08 May 09 |
nicklas |
92 |
|
4925 |
08 May 09 |
nicklas |
93 |
/** |
6077 |
03 Aug 12 |
nicklas |
If this option is set then all writers are automatically closed |
6077 |
03 Aug 12 |
nicklas |
when all data has been writted to them. This setting is enabled by default. |
6077 |
03 Aug 12 |
nicklas |
@since 3.2 |
6077 |
03 Aug 12 |
nicklas |
97 |
*/ |
6077 |
03 Aug 12 |
nicklas |
98 |
public void setAutoCloseWriters(boolean autoClose) |
6077 |
03 Aug 12 |
nicklas |
99 |
{ |
6077 |
03 Aug 12 |
nicklas |
100 |
this.autoCloseWriters = autoClose; |
6077 |
03 Aug 12 |
nicklas |
101 |
} |
6077 |
03 Aug 12 |
nicklas |
102 |
|
6077 |
03 Aug 12 |
nicklas |
103 |
/** |
4925 |
08 May 09 |
nicklas |
Add a parameter that is exported in the 'settings' section, which |
4925 |
08 May 09 |
nicklas |
is the first section in the BASEfile. There can only be one value |
4925 |
08 May 09 |
nicklas |
for a given key. The parameters are written to the file in the |
4925 |
08 May 09 |
nicklas |
order they are registered by this method. |
4925 |
08 May 09 |
nicklas |
108 |
|
4925 |
08 May 09 |
nicklas |
@param key The parameter key (if null this method call is ignored) |
4925 |
08 May 09 |
nicklas |
@param value The parameter value (may be null) |
4925 |
08 May 09 |
nicklas |
111 |
*/ |
4925 |
08 May 09 |
nicklas |
112 |
public void setParameter(String key, String value) |
4925 |
08 May 09 |
nicklas |
113 |
{ |
4925 |
08 May 09 |
nicklas |
114 |
if (key == null) return; |
4925 |
08 May 09 |
nicklas |
115 |
parameters.put(key, value); |
4925 |
08 May 09 |
nicklas |
116 |
} |
4925 |
08 May 09 |
nicklas |
117 |
|
4925 |
08 May 09 |
nicklas |
118 |
/** |
4925 |
08 May 09 |
nicklas |
Get the current value of a 'settings' parameter. |
4925 |
08 May 09 |
nicklas |
@param key The parameter key |
4925 |
08 May 09 |
nicklas |
@return The value, or null if no values has been registered for |
4925 |
08 May 09 |
nicklas |
the key (or if the registered value is null) |
4925 |
08 May 09 |
nicklas |
123 |
*/ |
4925 |
08 May 09 |
nicklas |
124 |
public String getParameter(String key) |
4925 |
08 May 09 |
nicklas |
125 |
{ |
4925 |
08 May 09 |
nicklas |
126 |
return parameters.get(key); |
4925 |
08 May 09 |
nicklas |
127 |
} |
4925 |
08 May 09 |
nicklas |
128 |
|
4925 |
08 May 09 |
nicklas |
129 |
@Override |
4925 |
08 May 09 |
nicklas |
130 |
public void addSpotField(DynamicField field) |
4925 |
08 May 09 |
nicklas |
131 |
{ |
4925 |
08 May 09 |
nicklas |
132 |
super.addSpotField(field); |
4925 |
08 May 09 |
nicklas |
133 |
} |
4925 |
08 May 09 |
nicklas |
134 |
|
4925 |
08 May 09 |
nicklas |
135 |
/** |
4925 |
08 May 09 |
nicklas |
Add multiple spot fields in one go. A null collection is ignored and |
4925 |
08 May 09 |
nicklas |
so are null values in the collection. |
4925 |
08 May 09 |
nicklas |
@param fields A collection with the fields that should be added |
4925 |
08 May 09 |
nicklas |
139 |
*/ |
4925 |
08 May 09 |
nicklas |
140 |
public void addSpotFields(Collection<? extends DynamicField> fields) |
4925 |
08 May 09 |
nicklas |
141 |
{ |
4925 |
08 May 09 |
nicklas |
142 |
if (fields == null) return; |
4925 |
08 May 09 |
nicklas |
143 |
for (DynamicField f : fields) |
4925 |
08 May 09 |
nicklas |
144 |
{ |
4925 |
08 May 09 |
nicklas |
145 |
addSpotField(f); |
4925 |
08 May 09 |
nicklas |
146 |
} |
4925 |
08 May 09 |
nicklas |
147 |
} |
4925 |
08 May 09 |
nicklas |
148 |
|
4925 |
08 May 09 |
nicklas |
149 |
@Override |
4925 |
08 May 09 |
nicklas |
150 |
public List<DynamicField> getSpotFields() |
4925 |
08 May 09 |
nicklas |
151 |
{ |
4925 |
08 May 09 |
nicklas |
152 |
return super.getSpotFields(); |
4925 |
08 May 09 |
nicklas |
153 |
} |
4925 |
08 May 09 |
nicklas |
154 |
|
4925 |
08 May 09 |
nicklas |
155 |
@Override |
4925 |
08 May 09 |
nicklas |
156 |
public void addReporterField(DynamicField field) |
4925 |
08 May 09 |
nicklas |
157 |
{ |
4925 |
08 May 09 |
nicklas |
158 |
super.addReporterField(field); |
4925 |
08 May 09 |
nicklas |
159 |
} |
4925 |
08 May 09 |
nicklas |
160 |
|
4925 |
08 May 09 |
nicklas |
161 |
/** |
5373 |
03 Aug 10 |
nicklas |
Add multiple reporter fields in one go. A null collection is ignored and |
4925 |
08 May 09 |
nicklas |
so are null values in the collection. |
4925 |
08 May 09 |
nicklas |
@param fields A collection with the fields that should be added |
4925 |
08 May 09 |
nicklas |
165 |
*/ |
4925 |
08 May 09 |
nicklas |
166 |
public void addReporterFields(Collection<? extends DynamicField> fields) |
4925 |
08 May 09 |
nicklas |
167 |
{ |
4925 |
08 May 09 |
nicklas |
168 |
if (fields == null) return; |
4925 |
08 May 09 |
nicklas |
169 |
for (DynamicField f : fields) |
4925 |
08 May 09 |
nicklas |
170 |
{ |
4925 |
08 May 09 |
nicklas |
171 |
addReporterField(f); |
4925 |
08 May 09 |
nicklas |
172 |
} |
4925 |
08 May 09 |
nicklas |
173 |
} |
4925 |
08 May 09 |
nicklas |
174 |
|
4925 |
08 May 09 |
nicklas |
175 |
@Override |
4925 |
08 May 09 |
nicklas |
176 |
public List<DynamicField> getReporterFields() |
4925 |
08 May 09 |
nicklas |
177 |
{ |
4925 |
08 May 09 |
nicklas |
178 |
return super.getReporterFields(); |
4925 |
08 May 09 |
nicklas |
179 |
} |
4925 |
08 May 09 |
nicklas |
180 |
|
5373 |
03 Aug 10 |
nicklas |
181 |
/** |
5373 |
03 Aug 10 |
nicklas |
Adds an assay field to the exported file. If no fields has been added |
5373 |
03 Aug 10 |
nicklas |
the exporter will automaticall export the assay id and name and all |
5373 |
03 Aug 10 |
nicklas |
experimental factor values. |
5373 |
03 Aug 10 |
nicklas |
@since 2.16 |
5373 |
03 Aug 10 |
nicklas |
186 |
*/ |
4925 |
08 May 09 |
nicklas |
187 |
@Override |
5373 |
03 Aug 10 |
nicklas |
188 |
public void addAssayField(AssayField field) |
5373 |
03 Aug 10 |
nicklas |
189 |
{ |
5373 |
03 Aug 10 |
nicklas |
190 |
super.addAssayField(field); |
5373 |
03 Aug 10 |
nicklas |
191 |
} |
5373 |
03 Aug 10 |
nicklas |
192 |
|
5373 |
03 Aug 10 |
nicklas |
193 |
/** |
5373 |
03 Aug 10 |
nicklas |
Add multiple assay fields in one go. A null collection is ignored and |
5373 |
03 Aug 10 |
nicklas |
so are null values in the collection. If no fields has been added |
5373 |
03 Aug 10 |
nicklas |
the exporter will automaticall export the assay id and name and all |
5373 |
03 Aug 10 |
nicklas |
experimental factor values. |
5373 |
03 Aug 10 |
nicklas |
@param fields A collection with the fields that should be added |
5373 |
03 Aug 10 |
nicklas |
@since 2.16 |
5373 |
03 Aug 10 |
nicklas |
200 |
*/ |
5373 |
03 Aug 10 |
nicklas |
201 |
public void addAssayFields(Collection<? extends AssayField> fields) |
5373 |
03 Aug 10 |
nicklas |
202 |
{ |
5373 |
03 Aug 10 |
nicklas |
203 |
if (fields == null) return; |
5373 |
03 Aug 10 |
nicklas |
204 |
for (AssayField f : fields) |
5373 |
03 Aug 10 |
nicklas |
205 |
{ |
5373 |
03 Aug 10 |
nicklas |
206 |
addAssayField(f); |
5373 |
03 Aug 10 |
nicklas |
207 |
} |
5373 |
03 Aug 10 |
nicklas |
208 |
} |
5373 |
03 Aug 10 |
nicklas |
209 |
|
5373 |
03 Aug 10 |
nicklas |
210 |
/** |
5373 |
03 Aug 10 |
nicklas |
@since 2.16 |
5373 |
03 Aug 10 |
nicklas |
212 |
*/ |
5373 |
03 Aug 10 |
nicklas |
213 |
@Override |
5373 |
03 Aug 10 |
nicklas |
214 |
public List<AssayField> getAssayFields() |
5373 |
03 Aug 10 |
nicklas |
215 |
{ |
5373 |
03 Aug 10 |
nicklas |
216 |
return super.getAssayFields(); |
5373 |
03 Aug 10 |
nicklas |
217 |
} |
5373 |
03 Aug 10 |
nicklas |
218 |
|
5373 |
03 Aug 10 |
nicklas |
219 |
|
5373 |
03 Aug 10 |
nicklas |
220 |
@Override |
4925 |
08 May 09 |
nicklas |
221 |
public void setAverageOnReporter(boolean averageOnReporter) |
4925 |
08 May 09 |
nicklas |
222 |
{ |
4925 |
08 May 09 |
nicklas |
223 |
super.setAverageOnReporter(averageOnReporter); |
4925 |
08 May 09 |
nicklas |
224 |
} |
4925 |
08 May 09 |
nicklas |
225 |
@Override |
4925 |
08 May 09 |
nicklas |
226 |
public boolean getAverageOnReporter() |
4925 |
08 May 09 |
nicklas |
227 |
{ |
4925 |
08 May 09 |
nicklas |
228 |
return super.getAverageOnReporter(); |
4925 |
08 May 09 |
nicklas |
229 |
} |
4925 |
08 May 09 |
nicklas |
230 |
// -------------------------------------- |
4925 |
08 May 09 |
nicklas |
231 |
|
4925 |
08 May 09 |
nicklas |
232 |
/* |
4925 |
08 May 09 |
nicklas |
From the AbstractBioAssaySetExporter class |
4925 |
08 May 09 |
nicklas |
234 |
------------------------------------------ |
4925 |
08 May 09 |
nicklas |
235 |
*/ |
4925 |
08 May 09 |
nicklas |
236 |
/** |
4925 |
08 May 09 |
nicklas |
Prepare the export by adding all experimental |
5373 |
03 Aug 10 |
nicklas |
factors as assay fields if no fields have been specified. |
4925 |
08 May 09 |
nicklas |
239 |
*/ |
4925 |
08 May 09 |
nicklas |
240 |
@Override |
4925 |
08 May 09 |
nicklas |
241 |
protected void beginExport() |
4925 |
08 May 09 |
nicklas |
242 |
{ |
5373 |
03 Aug 10 |
nicklas |
243 |
if (getAssayFields() == null || getAssayFields().size() == 0) |
5373 |
03 Aug 10 |
nicklas |
244 |
{ |
5373 |
03 Aug 10 |
nicklas |
245 |
addAssayField(ExportableFieldFactory.assayProperty("id", "id", Type.INT, null)); |
5373 |
03 Aug 10 |
nicklas |
246 |
addAssayField(ExportableFieldFactory.assayProperty("name", "name", Type.STRING, null)); |
5373 |
03 Aug 10 |
nicklas |
247 |
addExperimentalFactorsAsAssayFields(); |
5373 |
03 Aug 10 |
nicklas |
248 |
} |
4925 |
08 May 09 |
nicklas |
249 |
} |
4925 |
08 May 09 |
nicklas |
250 |
/** |
4925 |
08 May 09 |
nicklas |
Export 'settings' and 'assays' sections. |
4925 |
08 May 09 |
nicklas |
252 |
*/ |
4925 |
08 May 09 |
nicklas |
253 |
@Override |
4925 |
08 May 09 |
nicklas |
254 |
protected boolean exportGlobalHeader() |
4925 |
08 May 09 |
nicklas |
255 |
{ |
4925 |
08 May 09 |
nicklas |
256 |
exportSettingsSection(); |
4925 |
08 May 09 |
nicklas |
257 |
exportAssaysSectionHeaders(); |
4925 |
08 May 09 |
nicklas |
258 |
exportAssaysSectionData(); |
4925 |
08 May 09 |
nicklas |
259 |
return true; |
4925 |
08 May 09 |
nicklas |
260 |
} |
6077 |
03 Aug 12 |
nicklas |
261 |
|
6077 |
03 Aug 12 |
nicklas |
262 |
@Override |
6077 |
03 Aug 12 |
nicklas |
263 |
protected void endExport(RuntimeException e) |
6077 |
03 Aug 12 |
nicklas |
264 |
{ |
6077 |
03 Aug 12 |
nicklas |
265 |
if (out != null && autoCloseWriters) out.close(); |
6077 |
03 Aug 12 |
nicklas |
266 |
super.endExport(e); |
6077 |
03 Aug 12 |
nicklas |
267 |
} |
4925 |
08 May 09 |
nicklas |
268 |
// ------------------------------------------- |
4925 |
08 May 09 |
nicklas |
269 |
|
4925 |
08 May 09 |
nicklas |
270 |
/** |
4925 |
08 May 09 |
nicklas |
Get the writer that writes the data to the file. |
4925 |
08 May 09 |
nicklas |
272 |
*/ |
4925 |
08 May 09 |
nicklas |
273 |
protected BaseFileWriter getBaseFileWriter() |
4925 |
08 May 09 |
nicklas |
274 |
{ |
4925 |
08 May 09 |
nicklas |
275 |
return out; |
4925 |
08 May 09 |
nicklas |
276 |
} |
4925 |
08 May 09 |
nicklas |
277 |
|
4925 |
08 May 09 |
nicklas |
278 |
/** |
4925 |
08 May 09 |
nicklas |
Export the settings section which contains all parameter values |
4925 |
08 May 09 |
nicklas |
registered with {@link #setParameter(String, String)}. If a parameter |
4925 |
08 May 09 |
nicklas |
with key=section exists the value of that parameter is used as the |
4925 |
08 May 09 |
nicklas |
name of this section, otherwise 'settings' is used as name. |
4925 |
08 May 09 |
nicklas |
If the 'section' parameter exists, it must be the first |
4925 |
08 May 09 |
nicklas |
parameter. It is not allowed in other places and will generate an |
4925 |
08 May 09 |
nicklas |
exception. |
4925 |
08 May 09 |
nicklas |
<p> |
4925 |
08 May 09 |
nicklas |
This method leaves the BASEfile writer in the header part in case the caller |
4925 |
08 May 09 |
nicklas |
wants to add more headers. |
4925 |
08 May 09 |
nicklas |
<p> |
4925 |
08 May 09 |
nicklas |
If no parameters has been registered this section is skipped. |
4925 |
08 May 09 |
nicklas |
291 |
|
4925 |
08 May 09 |
nicklas |
@return The number of parameters written, not including the 'section' |
4925 |
08 May 09 |
nicklas |
parameter |
4925 |
08 May 09 |
nicklas |
294 |
*/ |
4925 |
08 May 09 |
nicklas |
295 |
protected int exportSettingsSection() |
4925 |
08 May 09 |
nicklas |
296 |
{ |
4925 |
08 May 09 |
nicklas |
297 |
BaseFileWriter out = getBaseFileWriter(); |
4925 |
08 May 09 |
nicklas |
298 |
out.baseWriteBom(); |
4925 |
08 May 09 |
nicklas |
299 |
if (parameters.isEmpty()) return 0; |
4925 |
08 May 09 |
nicklas |
300 |
|
4925 |
08 May 09 |
nicklas |
301 |
boolean first = true; |
4925 |
08 May 09 |
nicklas |
302 |
int numParameters = 0; |
4925 |
08 May 09 |
nicklas |
303 |
for (Map.Entry<String, String> entry : parameters.entrySet()) |
4925 |
08 May 09 |
nicklas |
304 |
{ |
4925 |
08 May 09 |
nicklas |
305 |
String key = entry.getKey(); |
4925 |
08 May 09 |
nicklas |
306 |
String value = entry.getValue(); |
4974 |
15 Jun 09 |
nicklas |
307 |
String section = null; |
4925 |
08 May 09 |
nicklas |
308 |
if (first) |
4925 |
08 May 09 |
nicklas |
309 |
{ |
4974 |
15 Jun 09 |
nicklas |
310 |
first = false; |
4925 |
08 May 09 |
nicklas |
311 |
if ("section".equals(key)) |
4925 |
08 May 09 |
nicklas |
312 |
{ |
4974 |
15 Jun 09 |
nicklas |
313 |
section = value; |
4974 |
15 Jun 09 |
nicklas |
314 |
key = null; |
4925 |
08 May 09 |
nicklas |
315 |
} |
4925 |
08 May 09 |
nicklas |
316 |
else |
4925 |
08 May 09 |
nicklas |
317 |
{ |
4974 |
15 Jun 09 |
nicklas |
318 |
section = "settings"; |
4925 |
08 May 09 |
nicklas |
319 |
} |
4925 |
08 May 09 |
nicklas |
320 |
} |
4974 |
15 Jun 09 |
nicklas |
321 |
if (section != null) out.baseBeginSection(section); |
4974 |
15 Jun 09 |
nicklas |
322 |
if (key != null) |
4974 |
15 Jun 09 |
nicklas |
323 |
{ |
4974 |
15 Jun 09 |
nicklas |
324 |
++numParameters; |
4974 |
15 Jun 09 |
nicklas |
325 |
out.basePrintHeader(key, value); |
4974 |
15 Jun 09 |
nicklas |
326 |
} |
4925 |
08 May 09 |
nicklas |
327 |
} |
4925 |
08 May 09 |
nicklas |
328 |
out.flush(); |
4925 |
08 May 09 |
nicklas |
329 |
return numParameters; |
4925 |
08 May 09 |
nicklas |
330 |
} |
4925 |
08 May 09 |
nicklas |
331 |
|
4974 |
15 Jun 09 |
nicklas |
332 |
|
4925 |
08 May 09 |
nicklas |
333 |
/** |
4925 |
08 May 09 |
nicklas |
Exports headers for the 'assays' section which contains metadata |
4925 |
08 May 09 |
nicklas |
information about the assays in the bioassay set. |
4925 |
08 May 09 |
nicklas |
This method leaves the BASEfile writer in the header part in |
4925 |
08 May 09 |
nicklas |
case the caller wants to add more headers. |
4925 |
08 May 09 |
nicklas |
338 |
*/ |
4925 |
08 May 09 |
nicklas |
339 |
protected void exportAssaysSectionHeaders() |
4925 |
08 May 09 |
nicklas |
340 |
{ |
4925 |
08 May 09 |
nicklas |
// Get configuration settings |
4925 |
08 May 09 |
nicklas |
342 |
BaseFileWriter out = getBaseFileWriter(); |
4925 |
08 May 09 |
nicklas |
343 |
List<BioAssay> assays = getBioAssays(); |
4925 |
08 May 09 |
nicklas |
344 |
List<AssayField> assayFields = getAssayFields(); |
4925 |
08 May 09 |
nicklas |
345 |
|
4925 |
08 May 09 |
nicklas |
// Put together a list with the assay fields that are exported |
5373 |
03 Aug 10 |
nicklas |
347 |
int dataColumns = assayFields.size(); |
4925 |
08 May 09 |
nicklas |
348 |
List<String> columns = new ArrayList<String>(dataColumns); |
5373 |
03 Aug 10 |
nicklas |
349 |
List<String> annotationColumns = new ArrayList<String>(dataColumns); |
4925 |
08 May 09 |
nicklas |
350 |
for (AssayField af : assayFields) |
4925 |
08 May 09 |
nicklas |
351 |
{ |
4925 |
08 May 09 |
nicklas |
352 |
columns.add(af.getTitle()); |
5373 |
03 Aug 10 |
nicklas |
353 |
if (af.isAnnotation()) annotationColumns.add(af.getTitle()); |
4925 |
08 May 09 |
nicklas |
354 |
} |
4925 |
08 May 09 |
nicklas |
355 |
|
4925 |
08 May 09 |
nicklas |
// Write the headers |
4925 |
08 May 09 |
nicklas |
357 |
out.baseBeginSection("assays"); |
4925 |
08 May 09 |
nicklas |
358 |
out.basePrintHeader("columns", Values.getString(columns, "\t", false)); |
5373 |
03 Aug 10 |
nicklas |
359 |
out.basePrintHeader("annotationColumns", Values.getString(annotationColumns, "\t", false)); |
4925 |
08 May 09 |
nicklas |
360 |
out.basePrintHeader("count", assays.size()); |
4925 |
08 May 09 |
nicklas |
361 |
out.flush(); |
4925 |
08 May 09 |
nicklas |
362 |
} |
4925 |
08 May 09 |
nicklas |
363 |
|
4925 |
08 May 09 |
nicklas |
364 |
/** |
4925 |
08 May 09 |
nicklas |
Export data for the 'assays' section that contains information |
4925 |
08 May 09 |
nicklas |
about the bioassays in the source bioassay set. Each data line |
4925 |
08 May 09 |
nicklas |
consists of the 'id', 'name' and annotations for a bioassay. |
4925 |
08 May 09 |
nicklas |
368 |
*/ |
6875 |
20 Apr 15 |
nicklas |
369 |
@SuppressWarnings({ "unchecked", "rawtypes" }) |
4925 |
08 May 09 |
nicklas |
370 |
protected void exportAssaysSectionData() |
4925 |
08 May 09 |
nicklas |
371 |
{ |
4925 |
08 May 09 |
nicklas |
// Get configuration settings |
4925 |
08 May 09 |
nicklas |
373 |
DbControl dc = getDbControl(); |
4925 |
08 May 09 |
nicklas |
374 |
BaseFileWriter out = getBaseFileWriter(); |
4925 |
08 May 09 |
nicklas |
375 |
List<BioAssay> assays = getBioAssays(); |
4925 |
08 May 09 |
nicklas |
376 |
List<AssayField> assayFields = getAssayFields(); |
5373 |
03 Aug 10 |
nicklas |
377 |
int dataColumns = assayFields.size(); |
4925 |
08 May 09 |
nicklas |
378 |
|
4925 |
08 May 09 |
nicklas |
379 |
if (!out.isWritingData()) out.baseBeginDataPart(); |
4925 |
08 May 09 |
nicklas |
380 |
for (BioAssay ba : assays) |
4925 |
08 May 09 |
nicklas |
381 |
{ |
4925 |
08 May 09 |
nicklas |
382 |
Object[] data = new Object[dataColumns]; |
5373 |
03 Aug 10 |
nicklas |
383 |
int index = 0; |
4925 |
08 May 09 |
nicklas |
384 |
for (AssayField at : assayFields) |
4925 |
08 May 09 |
nicklas |
385 |
{ |
6875 |
20 Apr 15 |
nicklas |
386 |
Collection<?> values = at.getAssayValue(dc, ba); |
4925 |
08 May 09 |
nicklas |
387 |
Formatter f = at.getFormatter(); |
4925 |
08 May 09 |
nicklas |
388 |
data[index++] = Values.getString(values, ",", true, f); |
4925 |
08 May 09 |
nicklas |
389 |
} |
4925 |
08 May 09 |
nicklas |
390 |
out.basePrintData(data); |
4925 |
08 May 09 |
nicklas |
391 |
} |
4925 |
08 May 09 |
nicklas |
392 |
out.flush(); |
4925 |
08 May 09 |
nicklas |
393 |
} |
4925 |
08 May 09 |
nicklas |
394 |
|
4925 |
08 May 09 |
nicklas |
395 |
/** |
4925 |
08 May 09 |
nicklas |
Start a new 'spot' section and export the standard headers: |
4925 |
08 May 09 |
nicklas |
'channels, 'assays', 'columns', 'assayFields' and 'count'. |
4925 |
08 May 09 |
nicklas |
This method leaves the BASEfile writer in the header part in |
4925 |
08 May 09 |
nicklas |
case the caller wants to add more headers. |
4925 |
08 May 09 |
nicklas |
400 |
|
4925 |
08 May 09 |
nicklas |
@param assays The bioassays that this section contains data for |
4925 |
08 May 09 |
nicklas |
@param spotCount The number of data lines that is going to be |
4925 |
08 May 09 |
nicklas |
written in the data part |
4925 |
08 May 09 |
nicklas |
404 |
*/ |
4925 |
08 May 09 |
nicklas |
405 |
protected void exportSpotSectionHeaders(List<BioAssay> assays, long spotCount) |
4925 |
08 May 09 |
nicklas |
406 |
{ |
4925 |
08 May 09 |
nicklas |
// Get configuration settings |
4925 |
08 May 09 |
nicklas |
408 |
BioAssaySet source = getSource(); |
4925 |
08 May 09 |
nicklas |
409 |
List<DynamicField> reporterFields = getReporterFields(); |
4925 |
08 May 09 |
nicklas |
410 |
List<DynamicField> spotFields = getSpotFields(); |
4925 |
08 May 09 |
nicklas |
411 |
BaseFileWriter out = getBaseFileWriter(); |
4925 |
08 May 09 |
nicklas |
412 |
|
4925 |
08 May 09 |
nicklas |
// Write section 'spots' and headers |
4925 |
08 May 09 |
nicklas |
414 |
out.baseBeginSection("spots"); |
4925 |
08 May 09 |
nicklas |
415 |
out.basePrintHeader("channels", source.getRawDataType().getChannels()); |
4925 |
08 May 09 |
nicklas |
416 |
out.basePrintHeader("assays", Values.getString(assays, "\t", false, new IdentifiableFormatter(""))); |
4925 |
08 May 09 |
nicklas |
417 |
ExportableFieldFormatter f = new ExportableFieldFormatter(); |
4925 |
08 May 09 |
nicklas |
418 |
out.basePrintHeader("columns", Values.getString(reporterFields, "\t", false, f) + "\tassayData"); |
4925 |
08 May 09 |
nicklas |
419 |
out.basePrintHeader("assayFields", Values.getString(spotFields, "\t", false, f)); |
4925 |
08 May 09 |
nicklas |
420 |
out.basePrintHeader("count", spotCount); |
4925 |
08 May 09 |
nicklas |
421 |
} |
4925 |
08 May 09 |
nicklas |
422 |
|
4925 |
08 May 09 |
nicklas |
423 |
/** |
4925 |
08 May 09 |
nicklas |
Export the spot data of a 'spot' section. The given query should |
4925 |
08 May 09 |
nicklas |
return the given number of spot fields PLUS the spot position and |
4925 |
08 May 09 |
nicklas |
column (in that order). Reporter data is expected to have been cached |
4925 |
08 May 09 |
nicklas |
by {@link #cacheReporterData()} and is copied to the output by |
4925 |
08 May 09 |
nicklas |
{@link #copyReporterFields(int, Object[], int)}. |
4925 |
08 May 09 |
nicklas |
<p> |
4925 |
08 May 09 |
nicklas |
A new data row is generated each time the position number changes. If each |
4925 |
08 May 09 |
nicklas |
row should contain data from more than one assay an index map must be given. |
4925 |
08 May 09 |
nicklas |
The index map should map the bioassay column to the ordinal number of the |
4925 |
08 May 09 |
nicklas |
assay in the list of assays. |
4925 |
08 May 09 |
nicklas |
434 |
|
4925 |
08 May 09 |
nicklas |
@param assays A list of with the bioassays that the current spot |
4925 |
08 May 09 |
nicklas |
data section contains data for |
4925 |
08 May 09 |
nicklas |
@param spotQuery The query used to retreive the data |
4925 |
08 May 09 |
nicklas |
@param progress An optional progress reporter, if given progress |
4925 |
08 May 09 |
nicklas |
is reported from 0 to 100% |
4925 |
08 May 09 |
nicklas |
@param count The total number of spots must be given for the progress |
4925 |
08 May 09 |
nicklas |
reporting to work |
4925 |
08 May 09 |
nicklas |
442 |
*/ |
6875 |
20 Apr 15 |
nicklas |
443 |
@SuppressWarnings({ "unchecked", "rawtypes" }) |
4925 |
08 May 09 |
nicklas |
444 |
protected void exportSpotSectionData(List<BioAssay> assays, DynamicSpotQuery spotQuery, |
4925 |
08 May 09 |
nicklas |
445 |
ProgressReporter progress, long count) |
4925 |
08 May 09 |
nicklas |
446 |
{ |
4925 |
08 May 09 |
nicklas |
// Get configuration options |
4925 |
08 May 09 |
nicklas |
448 |
DbControl dc = getDbControl(); |
4925 |
08 May 09 |
nicklas |
449 |
BaseFileWriter out = getBaseFileWriter(); |
4925 |
08 May 09 |
nicklas |
450 |
List<DynamicField> spotFields = getSpotFields(); |
4925 |
08 May 09 |
nicklas |
451 |
int numSpotFields = spotFields.size(); |
4925 |
08 May 09 |
nicklas |
452 |
int numReporterFields = getReporterFields().size(); |
4925 |
08 May 09 |
nicklas |
453 |
|
4925 |
08 May 09 |
nicklas |
// Prepare temporary storage |
4925 |
08 May 09 |
nicklas |
455 |
int numAssaysPerRow = assays.size(); |
4925 |
08 May 09 |
nicklas |
456 |
int numColumnsPerRow = numReporterFields + numAssaysPerRow * numSpotFields; |
4925 |
08 May 09 |
nicklas |
457 |
Object[] data = new Object[numColumnsPerRow]; |
4926 |
11 May 09 |
nicklas |
// Map assay column number to index in the 'data' array |
4925 |
08 May 09 |
nicklas |
459 |
if (numAssaysPerRow > 1) |
4925 |
08 May 09 |
nicklas |
460 |
{ |
4926 |
11 May 09 |
nicklas |
461 |
prepareAssayIndexMap(assays, numReporterFields, numSpotFields); |
4925 |
08 May 09 |
nicklas |
462 |
} |
4925 |
08 May 09 |
nicklas |
463 |
Formatter[] formatters = new Formatter[numSpotFields+1]; |
4925 |
08 May 09 |
nicklas |
464 |
for (int i = 0; i < numSpotFields; ++i) |
4925 |
08 May 09 |
nicklas |
465 |
{ |
4925 |
08 May 09 |
nicklas |
466 |
Formatter f = spotFields.get(i).getFormatter(); |
4925 |
08 May 09 |
nicklas |
467 |
if (f == null) f = new ToStringFormatter(); |
4925 |
08 May 09 |
nicklas |
468 |
formatters[i+1] = f; // Note +1 to avoid re-calc of index later |
4925 |
08 May 09 |
nicklas |
469 |
} |
4925 |
08 May 09 |
nicklas |
470 |
|
4925 |
08 May 09 |
nicklas |
471 |
if (!out.isWritingData()) out.baseBeginDataPart(); |
4925 |
08 May 09 |
nicklas |
472 |
int posIndex = numSpotFields + 1; |
4925 |
08 May 09 |
nicklas |
473 |
int colIndex = numSpotFields + 2; |
4925 |
08 May 09 |
nicklas |
474 |
int currentPosition = -1; |
4925 |
08 May 09 |
nicklas |
475 |
|
4925 |
08 May 09 |
nicklas |
// Execute the query |
5229 |
04 Feb 10 |
nicklas |
477 |
if (progress != null) progress.display(0, "Loading spot data..."); |
4925 |
08 May 09 |
nicklas |
478 |
DynamicResultIterator it = spotQuery.iterate(dc); |
4925 |
08 May 09 |
nicklas |
479 |
try |
4925 |
08 May 09 |
nicklas |
480 |
{ |
4925 |
08 May 09 |
nicklas |
481 |
long numDone = 0; |
5229 |
04 Feb 10 |
nicklas |
482 |
long progressInterval = Math.max(1 + count / 100, 50); |
4925 |
08 May 09 |
nicklas |
483 |
while (it.hasNext()) |
4925 |
08 May 09 |
nicklas |
484 |
{ |
5405 |
10 Sep 10 |
nicklas |
485 |
ThreadSignalHandler.checkInterrupted(); |
4925 |
08 May 09 |
nicklas |
486 |
SqlResult result = it.next(); |
4925 |
08 May 09 |
nicklas |
487 |
|
4925 |
08 May 09 |
nicklas |
488 |
int position = result.getInt(posIndex); |
4925 |
08 May 09 |
nicklas |
489 |
if (position != currentPosition) |
4925 |
08 May 09 |
nicklas |
490 |
{ |
4925 |
08 May 09 |
nicklas |
491 |
if (currentPosition != -1) |
4925 |
08 May 09 |
nicklas |
492 |
{ |
4925 |
08 May 09 |
nicklas |
493 |
out.basePrintData(data); |
4925 |
08 May 09 |
nicklas |
494 |
Arrays.fill(data, null); |
4925 |
08 May 09 |
nicklas |
495 |
++numDone; |
5229 |
04 Feb 10 |
nicklas |
496 |
if (progress != null && numDone % progressInterval == 0) |
4925 |
08 May 09 |
nicklas |
497 |
{ |
4925 |
08 May 09 |
nicklas |
498 |
int percent = count == 0 ? 0 : 10+(int)((90L * numDone) / count); |
4925 |
08 May 09 |
nicklas |
499 |
progress.display(percent, "Exporting spot data: " + |
4925 |
08 May 09 |
nicklas |
500 |
numDone + " of " + (count == 0 ? "unknown" : count) + " done"); |
4925 |
08 May 09 |
nicklas |
501 |
} |
4925 |
08 May 09 |
nicklas |
502 |
} |
4925 |
08 May 09 |
nicklas |
503 |
copyReporterFields(position, data, 0); |
4925 |
08 May 09 |
nicklas |
504 |
currentPosition = position; |
4925 |
08 May 09 |
nicklas |
505 |
} |
4925 |
08 May 09 |
nicklas |
506 |
int index = numReporterFields; |
4925 |
08 May 09 |
nicklas |
507 |
if (numAssaysPerRow > 1) |
4925 |
08 May 09 |
nicklas |
508 |
{ |
4925 |
08 May 09 |
nicklas |
509 |
short column = result.getShort(colIndex); |
4926 |
11 May 09 |
nicklas |
510 |
index = getAssayIndex(column); |
4925 |
08 May 09 |
nicklas |
511 |
} |
4925 |
08 May 09 |
nicklas |
512 |
for (int i = 1; i <= numSpotFields; ++i) |
4925 |
08 May 09 |
nicklas |
513 |
{ |
4925 |
08 May 09 |
nicklas |
514 |
data[index] = formatters[i].format(result.getObject(i)); |
4925 |
08 May 09 |
nicklas |
515 |
++index; |
4925 |
08 May 09 |
nicklas |
516 |
} |
4925 |
08 May 09 |
nicklas |
517 |
} |
4925 |
08 May 09 |
nicklas |
// Print the final line |
4925 |
08 May 09 |
nicklas |
519 |
out.basePrintData(data); |
4925 |
08 May 09 |
nicklas |
520 |
out.flush(); |
4925 |
08 May 09 |
nicklas |
521 |
} |
4925 |
08 May 09 |
nicklas |
522 |
catch (SQLException ex) |
4925 |
08 May 09 |
nicklas |
523 |
{ |
4925 |
08 May 09 |
nicklas |
524 |
throw new DatabaseException(ex); |
4925 |
08 May 09 |
nicklas |
525 |
} |
4925 |
08 May 09 |
nicklas |
526 |
finally |
4925 |
08 May 09 |
nicklas |
527 |
{ |
4925 |
08 May 09 |
nicklas |
528 |
if (it != null) it.close(); |
4925 |
08 May 09 |
nicklas |
529 |
} |
4925 |
08 May 09 |
nicklas |
530 |
} |
4925 |
08 May 09 |
nicklas |
531 |
|
4925 |
08 May 09 |
nicklas |
532 |
/** |
4925 |
08 May 09 |
nicklas |
Get a configured query that counts the number of data lines that is about to |
4925 |
08 May 09 |
nicklas |
be written in a data section. The returned query finds this value by calculating |
4925 |
08 May 09 |
nicklas |
the number of unique positions or, if average on reporters is enabled, the number |
4925 |
08 May 09 |
nicklas |
of unique reporters. |
4925 |
08 May 09 |
nicklas |
537 |
|
4925 |
08 May 09 |
nicklas |
@param bioAssayRestriction If TRUE a restriction is added to the |
4925 |
08 May 09 |
nicklas |
query to make it return data for a single bioassay only. |
4925 |
08 May 09 |
nicklas |
Use <code>query.setParameter("bioAssayColumn", (int)bioAssay.getDataCubeColumnNo(), Type.INT)</code> |
4925 |
08 May 09 |
nicklas |
to set the value for the restriction |
4925 |
08 May 09 |
nicklas |
@return A configured query. Use {@link DynamicSpotQuery#count(DbControl)} to |
4925 |
08 May 09 |
nicklas |
get the count |
4925 |
08 May 09 |
nicklas |
544 |
*/ |
4925 |
08 May 09 |
nicklas |
545 |
protected DynamicSpotQuery getCountQuery(boolean bioAssayRestriction) |
4925 |
08 May 09 |
nicklas |
546 |
{ |
4925 |
08 May 09 |
nicklas |
// Get configuration options |
4925 |
08 May 09 |
nicklas |
548 |
BioAssaySet source = getSource(); |
4925 |
08 May 09 |
nicklas |
549 |
boolean forAverage = getAverageOnReporter(); |
4925 |
08 May 09 |
nicklas |
550 |
|
4925 |
08 May 09 |
nicklas |
551 |
DynamicSpotQuery query = source.getSpotData(); |
4925 |
08 May 09 |
nicklas |
552 |
query.setDistinct(true); |
4925 |
08 May 09 |
nicklas |
553 |
if (forAverage) |
4925 |
08 May 09 |
nicklas |
554 |
{ |
4925 |
08 May 09 |
nicklas |
555 |
query.joinReporters(JoinType.INNER); |
4925 |
08 May 09 |
nicklas |
556 |
query.select(Selects.expression(Dynamic.column(VirtualTable.POSITION, VirtualColumn.REPORTER_ID), "rep", true)); |
4925 |
08 May 09 |
nicklas |
557 |
} |
4925 |
08 May 09 |
nicklas |
558 |
else |
4925 |
08 May 09 |
nicklas |
559 |
{ |
4925 |
08 May 09 |
nicklas |
560 |
query.select(Selects.expression(Dynamic.column(VirtualColumn.POSITION), "pos", true)); |
4925 |
08 May 09 |
nicklas |
561 |
} |
4925 |
08 May 09 |
nicklas |
562 |
|
4925 |
08 May 09 |
nicklas |
// Optional restriction |
4925 |
08 May 09 |
nicklas |
564 |
if (bioAssayRestriction) |
4925 |
08 May 09 |
nicklas |
565 |
{ |
4925 |
08 May 09 |
nicklas |
566 |
query.restrict( |
4925 |
08 May 09 |
nicklas |
567 |
Restrictions.eq( |
4925 |
08 May 09 |
nicklas |
568 |
Dynamic.column(VirtualColumn.COLUMN), |
4925 |
08 May 09 |
nicklas |
569 |
Expressions.parameter("bioAssayColumn") |
4925 |
08 May 09 |
nicklas |
570 |
)); |
4925 |
08 May 09 |
nicklas |
571 |
} |
4925 |
08 May 09 |
nicklas |
572 |
return query; |
4925 |
08 May 09 |
nicklas |
573 |
} |
4925 |
08 May 09 |
nicklas |
574 |
|
4925 |
08 May 09 |
nicklas |
575 |
} |